Merge ehallnor@zizzer:/bk/m5 into zazzer.eecs.umich.edu:/z/ehallnor/m5
[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 #ifndef NDEBUG
227 bool success =
228 #endif
229 (statMap.insert(make_pair(stat, data))).second;
230 assert(statMap.find(stat) != statMap.end());
231 assert(success && "this should never fail");
232 }
233
234 void
235 Data::regBin(MainBin *bin, string name)
236 {
237 if (bin_names.find(bin) != bin_names.end())
238 panic("shouldn't register bin twice");
239
240 bins.push_back(bin);
241
242 #ifndef NDEBUG
243 bool success =
244 #endif
245 (bin_names.insert(make_pair(bin,name))).second;
246 assert(bin_names.find(bin) != bin_names.end());
247 assert(success && "this should not fail");
248
249 cprintf("registering %s\n", name);
250 }
251
252 void
253 Data::regPrint(void *stat)
254 {
255 StatData *data = find(stat);
256
257 if (!data->print) {
258 data->print = true;
259
260 list_t::iterator j = printStats.insert(printStats.end(), data);
261 inplace_merge(printStats.begin(), j,
262 printStats.end(), StatData::less);
263 }
264
265 }
266
267 Data &
268 StatDB()
269 {
270 static Data db;
271 return db;
272 }
273
274 }
275
276 StatData *
277 DataAccess::find() const
278 {
279 return Database::StatDB().find(const_cast<void *>((const void *)this));
280 }
281
282 void
283 DataAccess::map(StatData *data)
284 {
285 Database::StatDB().mapStat(this, data);
286 }
287
288 StatData *
289 DataAccess::statData()
290 {
291 StatData *ptr = find();
292 assert(ptr);
293 return ptr;
294 }
295
296 const StatData *
297 DataAccess::statData() const
298 {
299 const StatData *ptr = find();
300 assert(ptr);
301 return ptr;
302 }
303
304 void
305 DataAccess::setInit()
306 {
307 statData()->init = true;
308 }
309
310 void
311 DataAccess::setPrint()
312 {
313 Database::StatDB().regPrint(this);
314 }
315
316 StatData::~StatData()
317 {
318 }
319
320 bool
321 StatData::less(StatData *stat1, StatData *stat2)
322 {
323 const string &name1 = stat1->name;
324 const string &name2 = stat2->name;
325
326 vector<string> v1;
327 vector<string> v2;
328
329 tokenize(v1, name1, '.');
330 tokenize(v2, name2, '.');
331
332 int last = min(v1.size(), v2.size()) - 1;
333 for (int i = 0; i < last; ++i)
334 if (v1[i] != v2[i])
335 return v1[i] < v2[i];
336
337 // Special compare for last element.
338 if (v1[last] == v2[last])
339 return v1.size() < v2.size();
340 else
341 return v1[last] < v2[last];
342
343 return false;
344 }
345
346 bool
347 StatData::baseCheck() const
348 {
349 if (!init) {
350 #ifdef STAT_DEBUG
351 cprintf("this is stat number %d\n",(*i)->number);
352 #endif
353 panic("Not all stats have been initialized");
354 return false;
355 }
356
357 if (print && name.empty()) {
358 panic("all printable stats must be named");
359 return false;
360 }
361
362 return true;
363 }
364
365 string
366 ValueToString(result_t value, DisplayMode mode, int precision)
367 {
368 stringstream val;
369
370 if (!isnan(value)) {
371 if (precision != -1)
372 val.precision(precision);
373 else if (value == rint(value))
374 val.precision(0);
375
376 val.unsetf(ios::showpoint);
377 val.setf(ios::fixed);
378 val << value;
379 } else {
380 val << (mode == mode_m5 ? "no value" : "<err: div-0>");
381 }
382
383 return val.str();
384 }
385
386 struct ScalarPrint
387 {
388 result_t value;
389 string name;
390 string desc;
391 int precision;
392 DisplayMode mode;
393 FormatFlags flags;
394 result_t pdf;
395 result_t cdf;
396
397 ScalarPrint()
398 : value(0.0), precision(0), mode(default_mode), flags(0),
399 pdf(NAN), cdf(NAN)
400 {}
401
402 void operator()(ostream &stream) const;
403 };
404
405 void
406 ScalarPrint::operator()(ostream &stream) const
407 {
408 if (flags & nozero && value == 0.0 ||
409 flags & nonan && isnan(value))
410 return;
411
412 stringstream pdfstr, cdfstr;
413
414 if (!isnan(pdf))
415 ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
416
417 if (!isnan(cdf))
418 ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
419
420 if (mode == mode_simplescalar && flags & __substat) {
421 ccprintf(stream, "%32s %12s %10s %10s", name,
422 ValueToString(value, mode, precision),
423 pdfstr, cdfstr);
424 } else {
425 ccprintf(stream, "%-40s %12s %10s %10s", name,
426 ValueToString(value, mode, precision), pdfstr, cdfstr);
427 }
428
429 if (PrintDescriptions) {
430 if (!desc.empty())
431 ccprintf(stream, " # %s", desc);
432 }
433 stream << endl;
434 }
435
436 struct VectorPrint
437 {
438 string name;
439 string desc;
440 vector<string> subnames;
441 vector<string> subdescs;
442 int precision;
443 DisplayMode mode;
444 FormatFlags flags;
445 rvec_t vec;
446 result_t total;
447
448 VectorPrint()
449 : subnames(0), subdescs(0), precision(-1), mode(default_mode),
450 flags(0), total(NAN)
451 {}
452
453 void operator()(ostream &stream) const;
454 };
455
456 void
457 VectorPrint::operator()(std::ostream &stream) const
458 {
459 int _size = vec.size();
460 result_t _total = 0.0;
461
462 if (flags & (pdf | cdf)) {
463 for (int i = 0; i < _size; ++i) {
464 _total += vec[i];
465 }
466 }
467
468 string base = name + ((mode == mode_simplescalar) ? "_" : "::");
469
470 ScalarPrint print;
471 print.name = name;
472 print.desc = desc;
473 print.precision = precision;
474 print.flags = flags;
475
476 bool havesub = !subnames.empty();
477
478 if (_size == 1) {
479 print.value = vec[0];
480 print(stream);
481 } else if (mode == mode_m5) {
482 for (int i = 0; i < _size; ++i) {
483 if (havesub && (i >= subnames.size() || subnames[i].empty()))
484 continue;
485
486 print.name = base + (havesub ? subnames[i] : to_string(i));
487 print.desc = subdescs.empty() ? desc : subdescs[i];
488 print.value = vec[i];
489
490 if (_total && (flags & pdf)) {
491 print.pdf = vec[i] / _total;
492 print.cdf += print.pdf;
493 }
494
495 print(stream);
496 }
497
498 if (flags & ::Statistics::total) {
499 print.name = base + "total";
500 print.desc = desc;
501 print.value = total;
502 print(stream);
503 }
504 } else {
505 if (flags & ::Statistics::total) {
506 print.value = total;
507 print(stream);
508 }
509
510 result_t _pdf = 0.0;
511 result_t _cdf = 0.0;
512 if (flags & dist) {
513 ccprintf(stream, "%s.start_dist\n", name);
514 for (int i = 0; i < _size; ++i) {
515 print.name = havesub ? subnames[i] : to_string(i);
516 print.desc = subdescs.empty() ? desc : subdescs[i];
517 print.flags |= __substat;
518 print.value = vec[i];
519
520 if (_total) {
521 _pdf = vec[i] / _total;
522 _cdf += _pdf;
523 }
524
525 if (flags & pdf)
526 print.pdf = _pdf;
527 if (flags & cdf)
528 print.cdf = _cdf;
529
530 print(stream);
531 }
532 ccprintf(stream, "%s.end_dist\n", name);
533 } else {
534 for (int i = 0; i < _size; ++i) {
535 if (havesub && subnames[i].empty())
536 continue;
537
538 print.name = base;
539 print.name += havesub ? subnames[i] : to_string(i);
540 print.desc = subdescs.empty() ? desc : subdescs[i];
541 print.value = vec[i];
542
543 if (_total) {
544 _pdf = vec[i] / _total;
545 _cdf += _pdf;
546 } else {
547 _pdf = _cdf = NAN;
548 }
549
550 if (flags & pdf) {
551 print.pdf = _pdf;
552 print.cdf = _cdf;
553 }
554
555 print(stream);
556 }
557 }
558 }
559 }
560
561 struct DistPrint
562 {
563 string name;
564 string desc;
565 int precision;
566 DisplayMode mode;
567 FormatFlags flags;
568
569 result_t min_val;
570 result_t max_val;
571 result_t underflow;
572 result_t overflow;
573 rvec_t vec;
574 result_t sum;
575 result_t squares;
576 result_t samples;
577
578 int min;
579 int max;
580 int bucket_size;
581 int size;
582 bool fancy;
583
584 void operator()(ostream &stream) const;
585 };
586
587 void
588 DistPrint::operator()(ostream &stream) const
589 {
590 if (fancy) {
591 ScalarPrint print;
592 string base = name + ((mode == mode_m5) ? "::" : "_");
593
594 print.precision = precision;
595 print.flags = flags;
596 print.desc = desc;
597
598 print.name = base + "mean";
599 print.value = samples ? sum / samples : NAN;
600 print(stream);
601
602 print.name = base + "stdev";
603 print.value = samples ? sqrt((samples * squares - sum * sum) /
604 (samples * (samples - 1.0))) : NAN;
605 print(stream);
606
607 print.name = "**Ignore: " + base + "TOT";
608 print.value = samples;
609 print(stream);
610 return;
611 }
612
613 assert(size == vec.size());
614
615 result_t total = 0.0;
616
617 total += underflow;
618 for (int i = 0; i < size; ++i)
619 total += vec[i];
620 total += overflow;
621
622 string base = name + (mode == mode_m5 ? "::" : ".");
623
624 ScalarPrint print;
625 print.desc = (mode == mode_m5) ? desc : "";
626 print.precision = precision;
627 print.mode = mode;
628 print.flags = flags;
629
630 if (mode == mode_simplescalar) {
631 ccprintf(stream, "%-42s", base + "start_dist");
632 if (PrintDescriptions && !desc.empty())
633 ccprintf(stream, " # %s", desc);
634 stream << endl;
635 }
636
637 print.name = base + "samples";
638 print.value = samples;
639 print(stream);
640
641 print.name = base + "min_value";
642 print.value = min_val;
643 print(stream);
644
645 if (mode == mode_m5 || underflow > 0.0) {
646 print.name = base + "underflows";
647 print.value = underflow;
648 if (mode == mode_m5 && total) {
649 print.pdf = underflow / total;
650 print.cdf += print.pdf;
651 }
652 print(stream);
653 }
654
655
656 if (mode == mode_m5) {
657 for (int i = 0; i < size; ++i) {
658 stringstream namestr;
659 namestr << name;
660
661 int low = i * bucket_size + min;
662 int high = ::min((i + 1) * bucket_size + min - 1, max);
663 namestr << low;
664 if (low < high)
665 namestr << "-" << high;
666
667 print.name = namestr.str();
668 print.value = vec[i];
669 if (total) {
670 print.pdf = vec[i] / total;
671 print.cdf += print.pdf;
672 }
673 print(stream);
674 }
675
676 } else {
677 int _min;
678 result_t _pdf;
679 result_t _cdf = 0.0;
680
681 print.flags = flags | __substat;
682
683 for (int i = 0; i < size; ++i) {
684 if (flags & nozero && vec[i] == 0.0 ||
685 flags & nonan && isnan(vec[i]))
686 continue;
687
688 _min = i * bucket_size + min;
689 _pdf = vec[i] / total * 100.0;
690 _cdf += _pdf;
691
692
693 print.name = ValueToString(_min, mode, 0);
694 print.value = vec[i];
695 print.pdf = (flags & pdf) ? _pdf : NAN;
696 print.cdf = (flags & cdf) ? _cdf : NAN;
697 print(stream);
698 }
699
700 print.flags = flags;
701 if (flags & (pdf || cdf)) {
702 print.pdf = NAN;
703 print.cdf = NAN;
704 }
705 }
706
707 if (mode == mode_m5 || overflow > 0.0) {
708 print.name = base + "overflows";
709 print.value = overflow;
710 if (mode == mode_m5 && total) {
711 print.pdf = overflow / total;
712 print.cdf += print.pdf;
713 }
714 print(stream);
715 }
716
717 print.pdf = NAN;
718 print.cdf = NAN;
719
720 if (mode != mode_simplescalar) {
721 print.name = base + "total";
722 print.value = total;
723 print(stream);
724 }
725
726 print.name = base + "max_value";
727 print.value = max_val;
728 print(stream);
729
730 if (mode != mode_simplescalar && samples != 0) {
731 print.name = base + "mean";
732 print.value = sum / samples;
733 print(stream);
734
735 print.name = base + "stdev";
736 print.value = sqrt((samples * squares - sum * sum) /
737 (samples * (samples - 1.0)));
738 print(stream);
739 }
740
741 if (mode == mode_simplescalar)
742 ccprintf(stream, "%send_dist\n\n", base);
743 }
744
745 void
746 ScalarDataBase::display(ostream &stream) const
747 {
748 ScalarPrint print;
749 print.value = val();
750 print.name = name;
751 print.desc = desc;
752 print.precision = precision;
753 print.flags = flags;
754
755 print(stream);
756 }
757
758 void
759 VectorDataBase::display(ostream &stream) const
760 {
761 int size = this->size();
762 const_cast<VectorDataBase *>(this)->update();
763
764 VectorPrint print;
765
766 print.name = name;
767 print.desc = desc;
768 print.mode = mode;
769 print.flags = flags;
770 print.precision = precision;
771 print.vec = val();
772 print.total = total();
773
774 for (int i = 0; i < size; ++i) {
775 if (!subnames[i].empty()) {
776 print.subnames = subnames;
777 print.subnames.resize(size);
778 for (int i = 0; i < size; ++i) {
779 if (!subnames[i].empty() && !subdescs[i].empty()) {
780 print.subdescs = subdescs;
781 print.subdescs.resize(size);
782 break;
783 }
784 }
785 break;
786 }
787 }
788
789
790 print(stream);
791 }
792
793 void
794 Vector2dDataBase::display(ostream &stream) const
795 {
796 const_cast<Vector2dDataBase *>(this)->update();
797
798 bool havesub = false;
799 VectorPrint print;
800
801 print.subnames = y_subnames;
802 print.mode = mode;
803 print.flags = flags;
804 print.precision = precision;
805
806 if (!subnames.empty()) {
807 for (int i = 0; i < x; ++i)
808 if (!subnames[i].empty())
809 havesub = true;
810 }
811
812 rvec_t tot_vec(y);
813 result_t super_total = 0.0;
814 for (int i = 0; i < x; ++i) {
815 if (havesub && (i >= subnames.size() || subnames[i].empty()))
816 continue;
817
818 int iy = i * y;
819 rvec_t yvec(y);
820
821 result_t total = 0.0;
822 for (int j = 0; j < y; ++j) {
823 yvec[j] = vec[iy + j];
824 tot_vec[j] += yvec[j];
825 total += yvec[j];
826 super_total += yvec[j];
827 }
828
829 print.name = name + "_" + (havesub ? subnames[i] : to_string(i));
830 print.desc = desc;
831 print.vec = yvec;
832 print.total = total;
833 print(stream);
834 }
835
836 if ((flags & ::Statistics::total) && (x > 1)) {
837 print.name = name;
838 print.desc = desc;
839 print.vec = tot_vec;
840 print.total = super_total;
841 print(stream);
842 }
843 }
844
845 void
846 DistDataBase::display(ostream &stream) const
847 {
848 const_cast<DistDataBase *>(this)->update();
849
850 DistPrint print;
851
852 print.name = name;
853 print.desc = desc;
854 print.precision = precision;
855 print.mode = mode;
856 print.flags = flags;
857
858 print.min_val = data.min_val;
859 print.max_val = data.max_val;
860 print.underflow = data.underflow;
861 print.overflow = data.overflow;
862 print.vec = data.vec;
863 print.sum = data.sum;
864 print.squares = data.squares;
865 print.samples = data.samples;
866
867 print.min = data.min;
868 print.max = data.max;
869 print.bucket_size = data.bucket_size;
870 print.size = data.size;
871 print.fancy = data.fancy;
872
873 print(stream);
874 }
875
876 void
877 VectorDistDataBase::display(ostream &stream) const
878 {
879 const_cast<VectorDistDataBase *>(this)->update();
880
881 for (int i = 0; i < size(); ++i) {
882 DistPrint print;
883
884 print.name = name +
885 (subnames[i].empty() ? ("_" + to_string(i)) : subnames[i]);
886 print.desc = subdescs[i].empty() ? desc : subdescs[i];
887 print.precision = precision;
888 print.mode = mode;
889 print.flags = flags;
890
891 print.min_val = data[i].min_val;
892 print.max_val = data[i].max_val;
893 print.underflow = data[i].underflow;
894 print.overflow = data[i].overflow;
895 print.vec = data[i].vec;
896 print.sum = data[i].sum;
897 print.squares = data[i].squares;
898 print.samples = data[i].samples;
899
900 print.min = data[i].min;
901 print.max = data[i].max;
902 print.bucket_size = data[i].bucket_size;
903 print.size = data[i].size;
904 print.fancy = data[i].fancy;
905
906 print(stream);
907 }
908 }
909
910 void
911 FormulaBase::val(rvec_t &vec) const
912 {
913 vec = root->val();
914 }
915
916 result_t
917 FormulaBase::total() const
918 {
919 return root->total();
920 }
921
922 size_t
923 FormulaBase::size() const
924 {
925 if (!root)
926 return 0;
927 else
928 return root->size();
929 }
930
931 bool
932 FormulaBase::binned() const
933 {
934 return root->binned();
935 }
936
937 void
938 FormulaBase::reset()
939 {
940 }
941
942 bool
943 FormulaBase::zero() const
944 {
945 rvec_t vec;
946 val(vec);
947 for (int i = 0; i < vec.size(); ++i)
948 if (vec[i] != 0.0)
949 return false;
950 return true;
951 }
952
953 void
954 FormulaBase::update(StatData *)
955 {
956 }
957
958 Formula::Formula()
959 {
960 setInit();
961 }
962
963 Formula::Formula(Temp r)
964 {
965 root = r;
966 assert(size());
967 }
968
969 const Formula &
970 Formula::operator=(Temp r)
971 {
972 assert(!root && "Can't change formulas");
973 root = r;
974 assert(size());
975 return *this;
976 }
977
978 const Formula &
979 Formula::operator+=(Temp r)
980 {
981 if (root)
982 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
983 else
984 root = r;
985 assert(size());
986 return *this;
987 }
988
989 MainBin::MainBin(const string &name)
990 : _name(name), mem(NULL), memsize(-1)
991 {
992 Database::StatDB().regBin(this, name);
993 }
994
995 MainBin::~MainBin()
996 {
997 if (mem)
998 delete [] mem;
999 }
1000
1001 char *
1002 MainBin::memory(off_t off)
1003 {
1004 if (memsize == -1)
1005 memsize = CeilPow2((size_t) offset());
1006
1007 if (!mem) {
1008 mem = new char[memsize];
1009 memset(mem, 0, memsize);
1010 }
1011
1012 assert(offset() <= size());
1013 return mem + off;
1014 }
1015
1016 void
1017 check()
1018 {
1019 Database::StatDB().check();
1020 }
1021
1022 void
1023 dump(ostream &stream)
1024 {
1025 Database::StatDB().dump(stream);
1026 }
1027
1028 CallbackQueue resetQueue;
1029
1030 void
1031 registerResetCallback(Callback *cb)
1032 {
1033 resetQueue.add(cb);
1034 }
1035
1036 void
1037 reset()
1038 {
1039 Database::StatDB().reset();
1040 resetQueue.process();
1041 }
1042
1043 } // namespace Statistics