00001 #ifndef AVERAGER_IMPLEMENTATION
00002 #define AVERAGER_IMPLEMENTATION
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "averager.h"
00019
00020 #include <basis/array.cpp>
00021 #include <basis/function.h>
00022
00023
00024
00025
00026
00027 #ifdef EMBEDDED_BUILD
00028 #define AVERAGER_SIZE_LIMIT 4192
00029 #elif defined(__WIN32__)
00030 #define AVERAGER_SIZE_LIMIT 180000
00031 #elif defined(__UNIX__)
00032 #define AVERAGER_SIZE_LIMIT 180000
00033 #else
00034 #define AVERAGER_SIZE_LIMIT 10000
00035 #endif
00036
00037 template <class contents>
00038 averager<contents>::averager(int entries, bool compacting)
00039 : _do_compaction(compacting), _averages(), _entries(entries)
00040 {
00041 int unit_size = sizeof(weighted_entry);
00042 if (negative(_entries) || !_entries)
00043 _entries = int(AVERAGER_SIZE_LIMIT / unit_size);
00044 }
00045
00046 template <class contents>
00047 void averager<contents>::compact()
00048 {
00049 if (length() < 8) return;
00050 int end_whacking = _averages.length() / 4;
00051 if (_do_compaction) {
00052 contents whacked_average = average(0, end_whacking);
00053 _averages.zap(1, end_whacking);
00054 _averages[0].value = whacked_average;
00055 _averages[0].count = end_whacking + 1;
00056 } else _averages.zap(0, end_whacking);
00057 }
00058
00059 template <class contents>
00060 void averager<contents>::check_for_compaction()
00061 {
00062
00063 int unit_size = sizeof(weighted_entry);
00064 int limit = minimum(AVERAGER_SIZE_LIMIT, int(_entries) * unit_size);
00065 if (int(_averages.length() + 2) * unit_size >= limit) compact();
00066 }
00067
00068 template <class contents>
00069 void averager<contents>::add(contents value, int count)
00070 {
00071 weighted_entry to_add;
00072 to_add.value = value;
00073 to_add.count = count;
00074 check_for_compaction();
00075 _averages += to_add;
00076 }
00077
00078 template <class contents>
00079 contents averager<contents>::average(int start, int end) const
00080 {
00081 bounds_return(start, 0, length() - 1, 0);
00082 bounds_return(end, start, length() - 1, 0);
00083 bounds_return(end - start + 1, 1, length(), 0);
00084
00085 contents accum = 0;
00086 contents count = 0;
00087 for (int i = start; i <= end; i++) {
00088 accum += get(i).value * get(i).count;
00089 count += get(i).count;
00090 }
00091 if (!count) count = 1;
00092 return accum / count;
00093 }
00094
00095 template <class contents>
00096 int averager<contents>::samples() const
00097 {
00098 int to_return = 0;
00099 for (int i = 0; i < length(); i++) to_return += get(i).count;
00100 return to_return;
00101 }
00102
00103 #endif
00104