Sweeping change in the stats package....again...
[gem5.git] / base / statistics.cc
1 /*
2 * Copyright (c) 2003 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <iomanip>
30 #include <iostream>
31 #include <list>
32 #include <map>
33 #include <string>
34 #include <sstream>
35
36 #include "base/callback.hh"
37 #include "base/cprintf.hh"
38 #include "base/misc.hh"
39 #include "base/statistics.hh"
40 #include "base/str.hh"
41 #include "sim/universe.hh"
42
43 #ifdef __M5_NAN
44 float
45 __nan()
46 {
47 union {
48 uint32_t ui;
49 float f;
50 } nan;
51
52 nan.ui = 0x7fc00000;
53 return nan.f;
54 }
55 #endif
56
57 #ifdef STAT_DEBUG
58 static int total_stats = 0;
59 #endif
60
61 using namespace std;
62
63 // This is a hack to get this parameter from the old stats package.
64 namespace Statistics {
65 bool PrintDescriptions = true;
66 DisplayMode default_mode = mode_simplescalar;
67
68 namespace Database
69 {
70 class Data
71 {
72 private:
73 typedef list<StatData *> list_t;
74 typedef map<void *, StatData *> map_t;
75
76 list<MainBin *> bins;
77 map<const MainBin *, string > bin_names;
78 list_t binnedStats;
79
80 list_t allStats;
81 list_t printStats;
82 map_t statMap;
83
84 public:
85 void dump(ostream &stream);
86
87 StatData *find(void *stat);
88 void mapStat(void *stat, StatData *data);
89
90 void check();
91 void reset();
92 void regBin(MainBin *bin, string name);
93 void regPrint(void *stat);
94 };
95
96
97 void
98 Data::dump(ostream &stream)
99 {
100 #ifndef FS_MEASURE
101 list_t::iterator i = printStats.begin();
102 list_t::iterator end = printStats.end();
103 while (i != end) {
104 StatData *stat = *i;
105 if (stat->binned())
106 binnedStats.push_back(stat);
107 ++i;
108 }
109 #endif //FS_MEASURE
110
111 list<MainBin *>::iterator j = bins.begin();
112 list<MainBin *>::iterator bins_end=bins.end();
113
114 if (!bins.empty()) {
115 ccprintf(stream, "PRINTING BINNED STATS\n");
116 while (j != bins_end) {
117 (*j)->activate();
118 map<const MainBin *, string>::const_iterator iter;
119 iter = bin_names.find(*j);
120 if (iter == bin_names.end())
121 panic("a binned stat not found in names map!");
122 ccprintf(stream,"---%s Bin------------\n", (*iter).second);
123
124 #ifdef FS_MEASURE
125 list_t::iterator i = printStats.begin();
126 list_t::iterator end = printStats.end();
127 #else
128 list_t::iterator i = binnedStats.begin();
129 list_t::iterator end = binnedStats.end();
130 #endif
131 while (i != end) {
132 StatData *stat = *i;
133 if (stat->dodisplay())
134 stat->display(stream);
135 ++i;
136 }
137 ++j;
138 ccprintf(stream, "---------------------------------\n");
139 }
140 #ifndef FS_MEASURE
141 ccprintf(stream, "**************ALL STATS************\n");
142 #endif
143 }
144
145 /**
146 * get bin totals working, then print the stat here (as total), even if
147 * its' binned. (this is only for the case you selectively bin a few stats
148 */
149 #ifndef FS_MEASURE
150 list_t::iterator k = printStats.begin();
151 list_t::iterator endprint = printStats.end();
152 while (k != endprint) {
153 StatData *stat = *k;
154 if (stat->dodisplay() /*&& !stat->binned()*/)
155 stat->display(stream);
156 ++k;
157 }
158 #endif
159 }
160
161 StatData *
162 Data::find(void *stat)
163 {
164 map_t::const_iterator i = statMap.find(stat);
165
166 if (i == statMap.end())
167 return NULL;
168
169 return (*i).second;
170 }
171
172 void
173 Data::check()
174 {
175 list_t::iterator i = allStats.begin();
176 list_t::iterator end = allStats.end();
177
178 while (i != end) {
179 StatData *stat = *i;
180 assert(stat);
181 stat->check();
182 ++i;
183 }
184 }
185
186 void
187 Data::reset()
188 {
189 list_t::iterator i = allStats.begin();
190 list_t::iterator end = allStats.end();
191 while (i != end) {
192 StatData *stat = *i;
193 stat->reset();
194 ++i;
195 }
196
197 MainBin *orig = MainBin::curBin();
198
199 list<MainBin *>::iterator bi = bins.begin();
200 list<MainBin *>::iterator be = bins.end();
201 while (bi != be) {
202 MainBin *bin = *bi;
203 bin->activate();
204
205 i = allStats.begin();
206 while (i != end) {
207 StatData *stat = *i;
208 stat->reset();
209 ++i;
210 }
211 ++bi;
212 }
213
214 if (orig)
215 orig->activate();
216 }
217
218 void
219 Data::mapStat(void *stat, StatData *data)
220 {
221 if (statMap.find(stat) != statMap.end())
222 panic("shouldn't register stat twice!");
223
224 allStats.push_back(data);
225
226 bool success = (statMap.insert(make_pair(stat, data))).second;
227 assert(statMap.find(stat) != statMap.end());
228 assert(success && "this should never fail");
229 }
230
231 void
232 Data::regBin(MainBin *bin, string name)
233 {
234 if (bin_names.find(bin) != bin_names.end())
235 panic("shouldn't register bin twice");
236
237 bins.push_back(bin);
238
239 bool success = (bin_names.insert(make_pair(bin,name))).second;
240 assert(bin_names.find(bin) != bin_names.end());
241 assert(success && "this should not fail");
242
243 cprintf("registering %s\n", name);
244 }
245
246 void
247 Data::regPrint(void *stat)
248 {
249 StatData *data = find(stat);
250
251 if (!data->print) {
252 data->print = true;
253
254 list_t::iterator j = printStats.insert(printStats.end(), data);
255 inplace_merge(printStats.begin(), j,
256 printStats.end(), StatData::less);
257 }
258
259 }
260
261 Data &
262 StatDB()
263 {
264 static Data db;
265 return db;
266 }
267
268 }
269
270 StatData *
271 DataAccess::find() const
272 {
273 return Database::StatDB().find(const_cast<void *>((const void *)this));
274 }
275
276 void
277 DataAccess::map(StatData *data)
278 {
279 Database::StatDB().mapStat(this, data);
280 }
281
282 StatData *
283 DataAccess::statData()
284 {
285 StatData *ptr = find();
286 assert(ptr);
287 return ptr;
288 }
289
290 const StatData *
291 DataAccess::statData() const
292 {
293 const StatData *ptr = find();
294 assert(ptr);
295 return ptr;
296 }
297
298 void
299 DataAccess::setInit()
300 {
301 statData()->init = true;
302 }
303
304 void
305 DataAccess::setPrint()
306 {
307 Database::StatDB().regPrint(this);
308 }
309
310 StatData::~StatData()
311 {
312 }
313
314 bool
315 StatData::less(StatData *stat1, StatData *stat2)
316 {
317 const string &name1 = stat1->name;
318 const string &name2 = stat2->name;
319
320 vector<string> v1;
321 vector<string> v2;
322
323 tokenize(v1, name1, '.');
324 tokenize(v2, name2, '.');
325
326 int last = min(v1.size(), v2.size()) - 1;
327 for (int i = 0; i < last; ++i)
328 if (v1[i] != v2[i])
329 return v1[i] < v2[i];
330
331 // Special compare for last element.
332 if (v1[last] == v2[last])
333 return v1.size() < v2.size();
334 else
335 return v1[last] < v2[last];
336
337 return false;
338 }
339
340 bool
341 StatData::check() const
342 {
343 if (!init) {
344 #ifdef STAT_DEBUG
345 cprintf("this is stat number %d\n",(*i)->number);
346 #endif
347 panic("Not all stats have been initialized");
348 return false;
349 }
350
351 if (print && name.empty()) {
352 panic("all printable stats must be named");
353 return false;
354 }
355
356 return true;
357 }
358
359 string
360 ValueToString(result_t value, DisplayMode mode, int precision)
361 {
362 stringstream val;
363
364 if (!isnan(value)) {
365 if (precision != -1)
366 val.precision(precision);
367 else if (value == rint(value))
368 val.precision(0);
369
370 val.unsetf(ios::showpoint);
371 val.setf(ios::fixed);
372 val << value;
373 } else {
374 val << (mode == mode_m5 ? "no value" : "<err: div-0>");
375 }
376
377 return val.str();
378 }
379
380 struct ScalarPrint
381 {
382 result_t value;
383 string name;
384 string desc;
385 int precision;
386 DisplayMode mode;
387 FormatFlags flags;
388 result_t pdf;
389 result_t cdf;
390
391 ScalarPrint()
392 : value(0.0), precision(0), mode(default_mode), flags(0),
393 pdf(NAN), cdf(NAN)
394 {}
395
396 void operator()(ostream &stream) const;
397 };
398
399 void
400 ScalarPrint::operator()(ostream &stream) const
401 {
402 if (flags & nozero && value == 0.0 ||
403 flags & nonan && isnan(value))
404 return;
405
406 stringstream pdfstr, cdfstr;
407
408 if (!isnan(pdf))
409 ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
410
411 if (!isnan(cdf))
412 ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
413
414 if (mode == mode_simplescalar && flags & __substat) {
415 ccprintf(stream, "%32s %12s %10s %10s", name,
416 ValueToString(value, mode, precision),
417 pdfstr, cdfstr);
418 } else {
419 ccprintf(stream, "%-40s %12s %10s %10s", name,
420 ValueToString(value, mode, precision), pdfstr, cdfstr);
421 }
422
423 if (PrintDescriptions) {
424 if (!desc.empty())
425 ccprintf(stream, " # %s", desc);
426 }
427 stream << endl;
428 }
429
430 struct VectorPrint
431 {
432 string name;
433 string desc;
434 vector<string> subnames;
435 vector<string> subdescs;
436 int precision;
437 DisplayMode mode;
438 FormatFlags flags;
439 rvec_t vec;
440 result_t total;
441
442 VectorPrint()
443 : subnames(0), subdescs(0), precision(-1), mode(default_mode),
444 flags(0), total(NAN)
445 {}
446
447 void operator()(ostream &stream) const;
448 };
449
450 void
451 VectorPrint::operator()(std::ostream &stream) const
452 {
453 int _size = vec.size();
454 result_t _total = 0.0;
455
456 if (flags & (pdf | cdf)) {
457 for (int i = 0; i < _size; ++i) {
458 _total += vec[i];
459 }
460 }
461
462 string base = name + ((mode == mode_simplescalar) ? "_" : "::");
463
464 ScalarPrint print;
465 print.name = name;
466 print.desc = desc;
467 print.precision = precision;
468 print.flags = flags;
469
470 bool havesub = !subnames.empty();
471
472 if (_size == 1) {
473 print.value = vec[0];
474 print(stream);
475 } else if (mode == mode_m5) {
476 for (int i = 0; i < _size; ++i) {
477 if (havesub && (i >= subnames.size() || subnames[i].empty()))
478 continue;
479
480 print.name = base + (havesub ? subnames[i] : to_string(i));
481 print.desc = subdescs.empty() ? desc : subdescs[i];
482 print.value = vec[i];
483
484 if (_total && (flags & pdf)) {
485 print.pdf = vec[i] / _total;
486 print.cdf += print.pdf;
487 }
488
489 print(stream);
490 }
491
492 if (flags & ::Statistics::total) {
493 print.name = base + "total";
494 print.desc = desc;
495 print.value = total;
496 print(stream);
497 }
498 } else {
499 if (flags & ::Statistics::total) {
500 print.value = total;
501 print(stream);
502 }
503
504 result_t _pdf = 0.0;
505 result_t _cdf = 0.0;
506 if (flags & dist) {
507 ccprintf(stream, "%s.start_dist\n", name);
508 for (int i = 0; i < _size; ++i) {
509 print.name = havesub ? subnames[i] : to_string(i);
510 print.desc = subdescs.empty() ? desc : subdescs[i];
511 print.flags |= __substat;
512 print.value = vec[i];
513
514 if (_total) {
515 _pdf = vec[i] / _total;
516 _cdf += _pdf;
517 }
518
519 if (flags & pdf)
520 print.pdf = _pdf;
521 if (flags & cdf)
522 print.cdf = _cdf;
523
524 print(stream);
525 }
526 ccprintf(stream, "%s.end_dist\n", name);
527 } else {
528 for (int i = 0; i < _size; ++i) {
529 if (havesub && subnames[i].empty())
530 continue;
531
532 print.name = base;
533 print.name += havesub ? subnames[i] : to_string(i);
534 print.desc = subdescs.empty() ? desc : subdescs[i];
535 print.value = vec[i];
536
537 if (_total) {
538 _pdf = vec[i] / _total;
539 _cdf += _pdf;
540 } else {
541 _pdf = _cdf = NAN;
542 }
543
544 if (flags & pdf) {
545 print.pdf = _pdf;
546 print.cdf = _cdf;
547 }
548
549 print(stream);
550 }
551 }
552 }
553 }
554
555 struct DistPrint
556 {
557 string name;
558 string desc;
559 int precision;
560 DisplayMode mode;
561 FormatFlags flags;
562
563 result_t min_val;
564 result_t max_val;
565 result_t underflow;
566 result_t overflow;
567 rvec_t vec;
568 result_t sum;
569 result_t squares;
570 result_t samples;
571
572 int min;
573 int max;
574 int bucket_size;
575 int size;
576 bool fancy;
577
578 void operator()(ostream &stream) const;
579 };
580
581 void
582 DistPrint::operator()(ostream &stream) const
583 {
584 if (fancy) {
585 ScalarPrint print;
586 string base = name + ((mode == mode_m5) ? "::" : "_");
587
588 print.precision = precision;
589 print.flags = flags;
590 print.desc = desc;
591
592 print.name = base + "mean";
593 print.value = samples ? sum / samples : NAN;
594 print(stream);
595
596 print.name = base + "stdev";
597 print.value = samples ? sqrt((samples * squares - sum * sum) /
598 (samples * (samples - 1.0))) : NAN;
599 print(stream);
600
601 print.name = "**Ignore: " + base + "TOT";
602 print.value = samples;
603 print(stream);
604 return;
605 }
606
607 assert(size == vec.size());
608
609 result_t total = 0.0;
610
611 total += underflow;
612 for (int i = 0; i < size; ++i)
613 total += vec[i];
614 total += overflow;
615
616 string base = name + (mode == mode_m5 ? "::" : ".");
617
618 ScalarPrint print;
619 print.desc = (mode == mode_m5) ? desc : "";
620 print.precision = precision;
621 print.mode = mode;
622 print.flags = flags;
623
624 if (mode == mode_simplescalar) {
625 ccprintf(stream, "%-42s", base + "start_dist");
626 if (PrintDescriptions && !desc.empty())
627 ccprintf(stream, " # %s", desc);
628 stream << endl;
629 }
630
631 print.name = base + "samples";
632 print.value = samples;
633 print(stream);
634
635 print.name = base + "min_value";
636 print.value = min_val;
637 print(stream);
638
639 if (mode == mode_m5 || underflow > 0.0) {
640 print.name = base + "underflows";
641 print.value = underflow;
642 if (mode == mode_m5 && total) {
643 print.pdf = underflow / total;
644 print.cdf += print.pdf;
645 }
646 print(stream);
647 }
648
649
650 if (mode == mode_m5) {
651 for (int i = 0; i < size; ++i) {
652 stringstream namestr;
653 namestr << name;
654
655 int low = i * bucket_size + min;
656 int high = ::min((i + 1) * bucket_size + min - 1, max);
657 namestr << low;
658 if (low < high)
659 namestr << "-" << high;
660
661 print.name = namestr.str();
662 print.value = vec[i];
663 if (total) {
664 print.pdf = vec[i] / total;
665 print.cdf += print.pdf;
666 }
667 print(stream);
668 }
669
670 } else {
671 int _min;
672 result_t _pdf;
673 result_t _cdf = 0.0;
674
675 print.flags = flags | __substat;
676
677 for (int i = 0; i < size; ++i) {
678 if (flags & nozero && vec[i] == 0.0 ||
679 flags & nonan && isnan(vec[i]))
680 continue;
681
682 _min = i * bucket_size + min;
683 _pdf = vec[i] / total * 100.0;
684 _cdf += _pdf;
685
686
687 print.name = ValueToString(_min, mode, 0);
688 print.value = vec[i];
689 print.pdf = (flags & pdf) ? _pdf : NAN;
690 print.cdf = (flags & cdf) ? _cdf : NAN;
691 print(stream);
692 }
693
694 print.flags = flags;
695 if (flags & (pdf || cdf)) {
696 print.pdf = NAN;
697 print.cdf = NAN;
698 }
699 }
700
701 if (mode == mode_m5 || overflow > 0.0) {
702 print.name = base + "overflows";
703 print.value = overflow;
704 if (mode == mode_m5 && total) {
705 print.pdf = overflow / total;
706 print.cdf += print.pdf;
707 }
708 print(stream);
709 }
710
711 print.pdf = NAN;
712 print.cdf = NAN;
713
714 if (mode != mode_simplescalar) {
715 print.name = base + "total";
716 print.value = total;
717 print(stream);
718 }
719
720 print.name = base + "max_value";
721 print.value = max_val;
722 print(stream);
723
724 if (mode != mode_simplescalar && samples != 0) {
725 print.name = base + "mean";
726 print.value = sum / samples;
727 print(stream);
728
729 print.name = base + "stdev";
730 print.value = sqrt((samples * squares - sum * sum) /
731 (samples * (samples - 1.0)));
732 print(stream);
733 }
734
735 if (mode == mode_simplescalar)
736 ccprintf(stream, "%send_dist\n\n", base);
737 }
738
739 void
740 ScalarDataBase::display(ostream &stream) const
741 {
742 ScalarPrint print;
743 print.value = val();
744 print.name = name;
745 print.desc = desc;
746 print.precision = precision;
747 print.flags = flags;
748
749 print(stream);
750 }
751
752 void
753 VectorDataBase::display(ostream &stream) const
754 {
755 int size = this->size();
756 const_cast<VectorDataBase *>(this)->update();
757
758 VectorPrint print;
759
760 print.name = name;
761 print.desc = desc;
762 print.mode = mode;
763 print.flags = flags;
764 print.precision = precision;
765 print.vec = val();
766 print.total = total();
767
768 for (int i = 0; i < size; ++i) {
769 if (!subnames[i].empty()) {
770 print.subnames = subnames;
771 print.subnames.resize(size);
772 for (int i = 0; i < size; ++i) {
773 if (!subnames[i].empty() && !subdescs[i].empty()) {
774 print.subdescs = subdescs;
775 print.subdescs.resize(size);
776 break;
777 }
778 }
779 break;
780 }
781 }
782
783
784 print(stream);
785 }
786
787 void
788 Vector2dDataBase::display(ostream &stream) const
789 {
790 const_cast<Vector2dDataBase *>(this)->update();
791
792 bool havesub = false;
793 VectorPrint print;
794
795 print.subnames = y_subnames;
796 print.mode = mode;
797 print.flags = flags;
798 print.precision = precision;
799
800 if (!subnames.empty()) {
801 for (int i = 0; i < x; ++i)
802 if (!subnames[i].empty())
803 havesub = true;
804 }
805
806 rvec_t tot_vec(y);
807 result_t super_total = 0.0;
808 for (int i = 0; i < x; ++i) {
809 if (havesub && (i >= subnames.size() || subnames[i].empty()))
810 continue;
811
812 int iy = i * y;
813 rvec_t yvec(y);
814
815 result_t total = 0.0;
816 for (int j = 0; j < y; ++j) {
817 yvec[j] = vec[iy + j];
818 tot_vec[j] += yvec[j];
819 total += yvec[j];
820 super_total += yvec[j];
821 }
822
823 print.name = name + "_" + (havesub ? subnames[i] : to_string(i));
824 print.desc = desc;
825 print.vec = yvec;
826 print.total = total;
827 print(stream);
828 }
829
830 if ((flags & ::Statistics::total) && (x > 1)) {
831 print.name = name;
832 print.desc = desc;
833 print.vec = tot_vec;
834 print.total = super_total;
835 print(stream);
836 }
837 }
838
839 void
840 DistDataBase::display(ostream &stream) const
841 {
842 const_cast<DistDataBase *>(this)->update();
843
844 DistPrint print;
845
846 print.name = name;
847 print.desc = desc;
848 print.precision = precision;
849 print.mode = mode;
850 print.flags = flags;
851
852 print.min_val = data.min_val;
853 print.max_val = data.max_val;
854 print.underflow = data.underflow;
855 print.overflow = data.overflow;
856 print.vec = data.vec;
857 print.sum = data.sum;
858 print.squares = data.squares;
859 print.samples = data.samples;
860
861 print.min = data.min;
862 print.max = data.max;
863 print.bucket_size = data.bucket_size;
864 print.size = data.size;
865 print.fancy = data.fancy;
866
867 print(stream);
868 }
869
870 void
871 VectorDistDataBase::display(ostream &stream) const
872 {
873 const_cast<VectorDistDataBase *>(this)->update();
874
875 for (int i = 0; i < size(); ++i) {
876 DistPrint print;
877
878 print.name = name +
879 (subnames[i].empty() ? ("_" + to_string(i)) : subnames[i]);
880 print.desc = subdescs[i].empty() ? desc : subdescs[i];
881 print.precision = precision;
882 print.mode = mode;
883 print.flags = flags;
884
885 print.min_val = data[i].min_val;
886 print.max_val = data[i].max_val;
887 print.underflow = data[i].underflow;
888 print.overflow = data[i].overflow;
889 print.vec = data[i].vec;
890 print.sum = data[i].sum;
891 print.squares = data[i].squares;
892 print.samples = data[i].samples;
893
894 print.min = data[i].min;
895 print.max = data[i].max;
896 print.bucket_size = data[i].bucket_size;
897 print.size = data[i].size;
898 print.fancy = data[i].fancy;
899
900 print(stream);
901 }
902 }
903
904 void
905 FormulaBase::val(rvec_t &vec) const
906 {
907 vec = root->val();
908 }
909
910 result_t
911 FormulaBase::total() const
912 {
913 return root->total();
914 }
915
916 size_t
917 FormulaBase::size() const
918 {
919 if (!root)
920 return 0;
921 else
922 return root->size();
923 }
924
925 bool
926 FormulaBase::binned() const
927 {
928 return root->binned();
929 }
930
931 void
932 FormulaBase::reset()
933 {
934 }
935
936 bool
937 FormulaBase::zero() const
938 {
939 rvec_t vec;
940 val(vec);
941 for (int i = 0; i < vec.size(); ++i)
942 if (vec[i] != 0.0)
943 return false;
944 return true;
945 }
946
947 void
948 FormulaBase::update(StatData *)
949 {
950 }
951
952 Formula::Formula()
953 {
954 setInit();
955 }
956
957 Formula::Formula(Temp r)
958 {
959 root = r;
960 assert(size());
961 }
962
963 const Formula &
964 Formula::operator=(Temp r)
965 {
966 assert(!root && "Can't change formulas");
967 root = r;
968 assert(size());
969 return *this;
970 }
971
972 const Formula &
973 Formula::operator+=(Temp r)
974 {
975 if (root)
976 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
977 else
978 root = r;
979 assert(size());
980 return *this;
981 }
982
983 MainBin::MainBin(const string &name)
984 : _name(name), mem(NULL), memsize(-1)
985 {
986 Database::StatDB().regBin(this, name);
987 }
988
989 MainBin::~MainBin()
990 {
991 if (mem)
992 delete [] mem;
993 }
994
995 char *
996 MainBin::memory(off_t off)
997 {
998 if (memsize == -1)
999 memsize = CeilPow2((size_t) offset());
1000
1001 if (!mem) {
1002 mem = new char[memsize];
1003 memset(mem, 0, memsize);
1004 }
1005
1006 assert(offset() <= size());
1007 return mem + off;
1008 }
1009
1010 void
1011 check()
1012 {
1013 Database::StatDB().check();
1014 }
1015
1016 void
1017 dump(ostream &stream)
1018 {
1019 Database::StatDB().dump(stream);
1020 }
1021
1022 CallbackQueue resetQueue;
1023
1024 void
1025 RegResetCallback(Callback *cb)
1026 {
1027 resetQueue.add(cb);
1028 }
1029
1030 void
1031 reset()
1032 {
1033 Database::StatDB().reset();
1034 resetQueue.process();
1035 }
1036
1037 } // namespace Statistics