Fix stats debugging and always compile it in for the
[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 <fstream>
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/hostinfo.hh"
39 #include "base/misc.hh"
40 #include "base/python.hh"
41 #include "base/statistics.hh"
42 #include "base/str.hh"
43 #include "base/time.hh"
44 #include "base/trace.hh"
45
46 #ifdef __M5_NAN
47 float
48 __nan()
49 {
50 union {
51 uint32_t ui;
52 float f;
53 } nan;
54
55 nan.ui = 0x7fc00000;
56 return nan.f;
57 }
58 #endif
59
60 #ifdef DEBUG
61 static int total_stats = 0;
62 #endif
63
64 using namespace std;
65
66 // This is a hack to get this parameter from the old stats package.
67 namespace Statistics {
68 bool PrintDescriptions = true;
69 DisplayMode DefaultMode = mode_simplescalar;
70
71 namespace Database
72 {
73 class Data
74 {
75 private:
76 typedef list<StatData *> list_t;
77 typedef map<void *, StatData *> map_t;
78
79 list<MainBin *> bins;
80
81 list_t allStats;
82 list_t printStats;
83 map_t statMap;
84
85 ofstream *stream;
86 Python *py;
87
88 public:
89 Data();
90 ~Data();
91
92 void dump(ostream &stream, DisplayMode mode);
93 void display(ostream &stream, DisplayMode mode);
94 void python_start(const string &file);
95 void python_dump(const string &name, const string &subname);
96 void python(const string &name, const string &subname,
97 const string &bin);
98
99 StatData *find(void *stat);
100 void mapStat(void *stat, StatData *data);
101
102 void check();
103 void reset();
104 void regBin(MainBin *bin, string name);
105 void regPrint(void *stat);
106
107 static std::string name() { return "Statistics Database"; }
108 };
109
110 Data::Data()
111 : stream(0), py(0)
112 {
113 }
114
115 Data::~Data()
116 {
117 if (stream) {
118 delete py;
119 ccprintf(*stream, "\n\nif __name__ == '__main__':\n");
120 ccprintf(*stream, " program_display()\n");
121 stream->close();
122 delete stream;
123 }
124 }
125
126 void
127 Data::dump(ostream &stream, DisplayMode mode)
128 {
129 MainBin *orig = MainBin::curBin();
130
131 switch (mode) {
132 case mode_m5:
133 case mode_simplescalar:
134 display(stream, mode);
135 break;
136 default:
137 warn("invalid display mode!\n");
138 display(stream, mode_m5);
139 break;
140 }
141
142 if (orig)
143 orig->activate();
144 }
145
146 void
147 Data::display(ostream &stream, DisplayMode mode)
148 {
149 if (!bins.empty()) {
150 list<MainBin *>::iterator i = bins.begin();
151 list<MainBin *>::iterator bins_end = bins.end();
152 ccprintf(stream, "PRINTING BINNED STATS\n");
153 while (i != bins_end) {
154 (*i)->activate();
155 ccprintf(stream,"---%s Bin------------\n", (*i)->name());
156
157 list_t::iterator j = printStats.begin();
158 list_t::iterator end = printStats.end();
159 while (j != end) {
160 StatData *stat = *j;
161 if (stat->dodisplay())
162 stat->display(stream, mode);
163 ++j;
164 }
165 ++i;
166 ccprintf(stream, "---------------------------------\n");
167 }
168 } else {
169 list_t::iterator i = printStats.begin();
170 list_t::iterator end = printStats.end();
171 while (i != end) {
172 StatData *stat = *i;
173 if (stat->dodisplay() && !stat->binned())
174 stat->display(stream, mode);
175 ++i;
176 }
177 }
178 }
179
180 void
181 Data::python_start(const string &file)
182 {
183 if (stream)
184 panic("can't start python twice!");
185
186 stream = new ofstream(file.c_str(), ios::trunc);
187 py = new Python(*stream);
188
189 ccprintf(*stream, "import sys\n");
190 ccprintf(*stream, "sys.path.append('.')\n");
191 ccprintf(*stream, "from m5stats import *\n\n");
192 }
193
194 void
195 Data::python_dump(const string &name, const string &subname)
196 {
197 if (!py)
198 panic("Can't dump python without first opening the file");
199
200 if (bins.empty()) {
201 python(name, subname, "");
202 } else {
203 list<MainBin *>::iterator i = bins.begin();
204 list<MainBin *>::iterator end = bins.end();
205
206 while (i != end) {
207 (*i)->activate();
208 python(name, subname, (*i)->name());
209 ++i;
210 }
211 }
212 }
213
214 void
215 Data::python(const string &name, const string &subname, const string &bin)
216 {
217 py->name("collections.append");
218 py->newline();
219 py->name("Collection");
220 py->newline();
221 py->qarg(name);
222 py->newline();
223 py->qarg(subname);
224 py->newline();
225 py->qarg(bin);
226 py->newline();
227 py->qarg(hostname());
228 py->newline();
229 py->qarg(Time::start.date());
230 py->newline();
231 py->list();
232 list_t::iterator i = allStats.begin();
233 list_t::iterator end = allStats.end();
234 while (i != end) {
235 StatData *stat = *i;
236 py->newline();
237 stat->python(*py);
238 ++i;
239 }
240 py->newline();
241 py->listEnd();
242 py->newline();
243 py->nameEnd();
244 py->newline();
245 py->nameEnd();
246 py->newline();
247 }
248
249 StatData *
250 Data::find(void *stat)
251 {
252 map_t::const_iterator i = statMap.find(stat);
253
254 if (i == statMap.end())
255 return NULL;
256
257 return (*i).second;
258 }
259
260 void
261 Data::check()
262 {
263 list_t::iterator i = allStats.begin();
264 list_t::iterator end = allStats.end();
265
266 while (i != end) {
267 StatData *data = *i;
268 assert(data);
269 data->check();
270 ++i;
271 }
272
273 i = allStats.begin();
274 int j = 0;
275 while (i != end) {
276 StatData *data = *i;
277 if (!(data->flags & print))
278 data->name = "__Stat" + to_string(j++);
279 ++i;
280 }
281 }
282
283 void
284 Data::reset()
285 {
286 // reset non-binned stats
287 list_t::iterator i = allStats.begin();
288 list_t::iterator end = allStats.end();
289 while (i != end) {
290 StatData *data = *i;
291 if (!data->binned())
292 data->reset();
293 ++i;
294 }
295
296 // save the bin so we can go back to where we were
297 MainBin *orig = MainBin::curBin();
298
299 // reset binned stats
300 list<MainBin *>::iterator bi = bins.begin();
301 list<MainBin *>::iterator be = bins.end();
302 while (bi != be) {
303 MainBin *bin = *bi;
304 bin->activate();
305
306 i = allStats.begin();
307 while (i != end) {
308 StatData *data = *i;
309 if (data->binned())
310 data->reset();
311 ++i;
312 }
313 ++bi;
314 }
315
316 // restore bin
317 MainBin::curBin() = orig;
318 }
319
320 void
321 Data::mapStat(void *stat, StatData *data)
322 {
323 if (statMap.find(stat) != statMap.end())
324 panic("shouldn't register stat twice!");
325
326 allStats.push_back(data);
327
328 #ifndef NDEBUG
329 bool success =
330 #endif
331 (statMap.insert(make_pair(stat, data))).second;
332 assert(statMap.find(stat) != statMap.end());
333 assert(success && "this should never fail");
334 }
335
336 void
337 Data::regBin(MainBin *bin, string _name)
338 {
339 bins.push_back(bin);
340 DPRINTF(Stats, "registering %s\n", _name);
341 }
342
343 void
344 Data::regPrint(void *stat)
345 {
346 StatData *data = find(stat);
347
348 if (data->flags & print)
349 return;
350
351 data->flags |= print;
352
353 list_t::iterator j = printStats.insert(printStats.end(), data);
354 inplace_merge(printStats.begin(), j, printStats.end(), StatData::less);
355 }
356
357 Data &
358 StatDB()
359 {
360 static Data db;
361 return db;
362 }
363
364 }
365
366 StatData *
367 DataAccess::find() const
368 {
369 return Database::StatDB().find(const_cast<void *>((const void *)this));
370 }
371
372 const StatData *
373 getStatData(const void *stat)
374 {
375 return Database::StatDB().find(const_cast<void *>(stat));
376 }
377
378 void
379 DataAccess::map(StatData *data)
380 {
381 Database::StatDB().mapStat(this, data);
382 }
383
384 StatData *
385 DataAccess::statData()
386 {
387 StatData *ptr = find();
388 assert(ptr);
389 return ptr;
390 }
391
392 const StatData *
393 DataAccess::statData() const
394 {
395 const StatData *ptr = find();
396 assert(ptr);
397 return ptr;
398 }
399
400 void
401 DataAccess::setInit()
402 {
403 statData()->flags |= init;
404 }
405
406 void
407 DataAccess::setPrint()
408 {
409 Database::StatDB().regPrint(this);
410 }
411
412 StatData::StatData()
413 : flags(none), precision(-1), prereq(0)
414 {
415 #ifdef DEBUG
416 number = total_stats++;
417 #endif
418 }
419
420 StatData::~StatData()
421 {
422 }
423
424 bool
425 StatData::less(StatData *stat1, StatData *stat2)
426 {
427 const string &name1 = stat1->name;
428 const string &name2 = stat2->name;
429
430 vector<string> v1;
431 vector<string> v2;
432
433 tokenize(v1, name1, '.');
434 tokenize(v2, name2, '.');
435
436 int last = min(v1.size(), v2.size()) - 1;
437 for (int i = 0; i < last; ++i)
438 if (v1[i] != v2[i])
439 return v1[i] < v2[i];
440
441 // Special compare for last element.
442 if (v1[last] == v2[last])
443 return v1.size() < v2.size();
444 else
445 return v1[last] < v2[last];
446
447 return false;
448 }
449
450 bool
451 StatData::baseCheck() const
452 {
453 if (!(flags & init)) {
454 #ifdef DEBUG
455 cprintf("this is stat number %d\n", number);
456 #endif
457 panic("Not all stats have been initialized");
458 return false;
459 }
460
461 if ((flags & print) && name.empty()) {
462 panic("all printable stats must be named");
463 return false;
464 }
465
466 return true;
467 }
468
469 string
470 ValueToString(result_t value, DisplayMode mode, int precision)
471 {
472 stringstream val;
473
474 if (!isnan(value)) {
475 if (precision != -1)
476 val.precision(precision);
477 else if (value == rint(value))
478 val.precision(0);
479
480 val.unsetf(ios::showpoint);
481 val.setf(ios::fixed);
482 val << value;
483 } else {
484 val << (mode == mode_m5 ? "no value" : "<err: div-0>");
485 }
486
487 return val.str();
488 }
489
490 struct ScalarPrint
491 {
492 result_t value;
493 string name;
494 string desc;
495 StatFlags flags;
496 DisplayMode mode;
497 int precision;
498 result_t pdf;
499 result_t cdf;
500
501 ScalarPrint()
502 : value(0.0), flags(0), mode(DefaultMode), precision(0),
503 pdf(NAN), cdf(NAN)
504 {}
505
506 void operator()(ostream &stream) const;
507 };
508
509 void
510 ScalarPrint::operator()(ostream &stream) const
511 {
512 if (flags & nozero && value == 0.0 ||
513 flags & nonan && isnan(value))
514 return;
515
516 stringstream pdfstr, cdfstr;
517
518 if (!isnan(pdf))
519 ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
520
521 if (!isnan(cdf))
522 ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
523
524 if (mode == mode_simplescalar && flags & __substat) {
525 ccprintf(stream, "%32s %12s %10s %10s", name,
526 ValueToString(value, mode, precision), pdfstr, cdfstr);
527 } else {
528 ccprintf(stream, "%-40s %12s %10s %10s", name,
529 ValueToString(value, mode, precision), pdfstr, cdfstr);
530 }
531
532 if (PrintDescriptions) {
533 if (!desc.empty())
534 ccprintf(stream, " # %s", desc);
535 }
536 stream << endl;
537 }
538
539 struct VectorPrint
540 {
541 string name;
542 string desc;
543 vector<string> subnames;
544 vector<string> subdescs;
545 StatFlags flags;
546 DisplayMode mode;
547 int precision;
548 rvec_t vec;
549 result_t total;
550
551 VectorPrint()
552 : subnames(0), subdescs(0), flags(0), mode(DefaultMode),
553 precision(-1), total(NAN)
554 {}
555
556 void operator()(ostream &stream) const;
557 };
558
559 void
560 VectorPrint::operator()(std::ostream &stream) const
561 {
562 int _size = vec.size();
563 result_t _total = 0.0;
564
565 if (flags & (pdf | cdf)) {
566 for (int i = 0; i < _size; ++i) {
567 _total += vec[i];
568 }
569 }
570
571 string base = name + ((mode == mode_simplescalar) ? "_" : "::");
572
573 ScalarPrint print;
574 print.name = name;
575 print.desc = desc;
576 print.precision = precision;
577 print.flags = flags;
578
579 bool havesub = !subnames.empty();
580
581 if (_size == 1) {
582 print.value = vec[0];
583 print(stream);
584 } else if (mode == mode_m5) {
585 for (int i = 0; i < _size; ++i) {
586 if (havesub && (i >= subnames.size() || subnames[i].empty()))
587 continue;
588
589 print.name = base + (havesub ? subnames[i] : to_string(i));
590 print.desc = subdescs.empty() ? desc : subdescs[i];
591 print.value = vec[i];
592
593 if (_total && (flags & pdf)) {
594 print.pdf = vec[i] / _total;
595 print.cdf += print.pdf;
596 }
597
598 print(stream);
599 }
600
601 if (flags & ::Statistics::total) {
602 print.name = base + "total";
603 print.desc = desc;
604 print.value = total;
605 print(stream);
606 }
607 } else {
608 if (flags & ::Statistics::total) {
609 print.value = total;
610 print(stream);
611 }
612
613 result_t _pdf = 0.0;
614 result_t _cdf = 0.0;
615 if (flags & dist) {
616 ccprintf(stream, "%s.start_dist\n", name);
617 for (int i = 0; i < _size; ++i) {
618 print.name = havesub ? subnames[i] : to_string(i);
619 print.desc = subdescs.empty() ? desc : subdescs[i];
620 print.flags |= __substat;
621 print.value = vec[i];
622
623 if (_total) {
624 _pdf = vec[i] / _total;
625 _cdf += _pdf;
626 }
627
628 if (flags & pdf)
629 print.pdf = _pdf;
630 if (flags & cdf)
631 print.cdf = _cdf;
632
633 print(stream);
634 }
635 ccprintf(stream, "%s.end_dist\n", name);
636 } else {
637 for (int i = 0; i < _size; ++i) {
638 if (havesub && subnames[i].empty())
639 continue;
640
641 print.name = base;
642 print.name += havesub ? subnames[i] : to_string(i);
643 print.desc = subdescs.empty() ? desc : subdescs[i];
644 print.value = vec[i];
645
646 if (_total) {
647 _pdf = vec[i] / _total;
648 _cdf += _pdf;
649 } else {
650 _pdf = _cdf = NAN;
651 }
652
653 if (flags & pdf) {
654 print.pdf = _pdf;
655 print.cdf = _cdf;
656 }
657
658 print(stream);
659 }
660 }
661 }
662 }
663
664 struct DistPrint
665 {
666 string name;
667 string desc;
668 StatFlags flags;
669 DisplayMode mode;
670 int precision;
671
672 result_t min_val;
673 result_t max_val;
674 result_t underflow;
675 result_t overflow;
676 rvec_t vec;
677 result_t sum;
678 result_t squares;
679 result_t samples;
680
681 int min;
682 int max;
683 int bucket_size;
684 int size;
685 bool fancy;
686
687 void operator()(ostream &stream) const;
688 };
689
690 void
691 DistPrint::operator()(ostream &stream) const
692 {
693 if (fancy) {
694 ScalarPrint print;
695 string base = name + ((mode == mode_m5) ? "::" : "_");
696
697 print.precision = precision;
698 print.flags = flags;
699 print.mode = mode;
700 print.desc = desc;
701
702 print.name = base + "mean";
703 print.value = samples ? sum / samples : NAN;
704 print(stream);
705
706 print.name = base + "stdev";
707 print.value = samples ? sqrt((samples * squares - sum * sum) /
708 (samples * (samples - 1.0))) : NAN;
709 print(stream);
710
711 print.name = "**Ignore: " + base + "TOT";
712 print.value = samples;
713 print(stream);
714 return;
715 }
716
717 assert(size == vec.size());
718
719 result_t total = 0.0;
720
721 total += underflow;
722 for (int i = 0; i < size; ++i)
723 total += vec[i];
724 total += overflow;
725
726 string base = name + (mode == mode_m5 ? "::" : ".");
727
728 ScalarPrint print;
729 print.desc = (mode == mode_m5) ? desc : "";
730 print.flags = flags;
731 print.mode = mode;
732 print.precision = precision;
733
734 if (mode == mode_simplescalar) {
735 ccprintf(stream, "%-42s", base + "start_dist");
736 if (PrintDescriptions && !desc.empty())
737 ccprintf(stream, " # %s", desc);
738 stream << endl;
739 }
740
741 print.name = base + "samples";
742 print.value = samples;
743 print(stream);
744
745 print.name = base + "min_value";
746 print.value = min_val;
747 print(stream);
748
749 if (mode == mode_m5 || underflow > 0.0) {
750 print.name = base + "underflows";
751 print.value = underflow;
752 if (mode == mode_m5 && total) {
753 print.pdf = underflow / total;
754 print.cdf += print.pdf;
755 }
756 print(stream);
757 }
758
759
760 if (mode == mode_m5) {
761 for (int i = 0; i < size; ++i) {
762 stringstream namestr;
763 namestr << name;
764
765 int low = i * bucket_size + min;
766 int high = ::min((i + 1) * bucket_size + min - 1, max);
767 namestr << low;
768 if (low < high)
769 namestr << "-" << high;
770
771 print.name = namestr.str();
772 print.value = vec[i];
773 if (total) {
774 print.pdf = vec[i] / total;
775 print.cdf += print.pdf;
776 }
777 print(stream);
778 }
779
780 } else {
781 int _min;
782 result_t _pdf;
783 result_t _cdf = 0.0;
784
785 print.flags = flags | __substat;
786
787 for (int i = 0; i < size; ++i) {
788 if (flags & nozero && vec[i] == 0.0 ||
789 flags & nonan && isnan(vec[i]))
790 continue;
791
792 _min = i * bucket_size + min;
793 _pdf = vec[i] / total * 100.0;
794 _cdf += _pdf;
795
796
797 print.name = ValueToString(_min, mode, 0);
798 print.value = vec[i];
799 print.pdf = (flags & pdf) ? _pdf : NAN;
800 print.cdf = (flags & cdf) ? _cdf : NAN;
801 print(stream);
802 }
803
804 print.flags = flags;
805 }
806
807 if (mode == mode_m5 || overflow > 0.0) {
808 print.name = base + "overflows";
809 print.value = overflow;
810 if (mode == mode_m5 && total) {
811 print.pdf = overflow / total;
812 print.cdf += print.pdf;
813 } else {
814 print.pdf = NAN;
815 print.cdf = NAN;
816 }
817 print(stream);
818 }
819
820 print.pdf = NAN;
821 print.cdf = NAN;
822
823 if (mode != mode_simplescalar) {
824 print.name = base + "total";
825 print.value = total;
826 print(stream);
827 }
828
829 print.name = base + "max_value";
830 print.value = max_val;
831 print(stream);
832
833 if (mode != mode_simplescalar && samples != 0) {
834 print.name = base + "mean";
835 print.value = sum / samples;
836 print(stream);
837
838 print.name = base + "stdev";
839 print.value = sqrt((samples * squares - sum * sum) /
840 (samples * (samples - 1.0)));
841 print(stream);
842 }
843
844 if (mode == mode_simplescalar)
845 ccprintf(stream, "%send_dist\n\n", base);
846 }
847
848 void
849 ScalarDataBase::display(ostream &stream, DisplayMode mode) const
850 {
851 ScalarPrint print;
852 print.value = val();
853 print.name = name;
854 print.desc = desc;
855 print.flags = flags;
856 print.mode = mode;
857 print.precision = precision;
858
859 print(stream);
860 }
861
862 void
863 VectorDataBase::display(ostream &stream, DisplayMode mode) const
864 {
865 int size = this->size();
866 const_cast<VectorDataBase *>(this)->update();
867
868 VectorPrint print;
869
870 print.name = name;
871 print.desc = desc;
872 print.flags = flags;
873 print.mode = mode;
874 print.precision = precision;
875 print.vec = val();
876 print.total = total();
877
878 if (!subnames.empty()) {
879 for (int i = 0; i < size; ++i) {
880 if (!subnames[i].empty()) {
881 print.subnames = subnames;
882 print.subnames.resize(size);
883 for (int i = 0; i < size; ++i) {
884 if (!subnames[i].empty() && !subdescs[i].empty()) {
885 print.subdescs = subdescs;
886 print.subdescs.resize(size);
887 break;
888 }
889 }
890 break;
891 }
892 }
893 }
894
895 print(stream);
896 }
897
898 void
899 Vector2dDataBase::display(ostream &stream, DisplayMode mode) const
900 {
901 const_cast<Vector2dDataBase *>(this)->update();
902
903 bool havesub = false;
904 VectorPrint print;
905
906 print.subnames = y_subnames;
907 print.flags = flags;
908 print.mode = mode;
909 print.precision = precision;
910
911 if (!subnames.empty()) {
912 for (int i = 0; i < x; ++i)
913 if (!subnames[i].empty())
914 havesub = true;
915 }
916
917 rvec_t tot_vec(y);
918 result_t super_total = 0.0;
919 for (int i = 0; i < x; ++i) {
920 if (havesub && (i >= subnames.size() || subnames[i].empty()))
921 continue;
922
923 int iy = i * y;
924 rvec_t yvec(y);
925
926 result_t total = 0.0;
927 for (int j = 0; j < y; ++j) {
928 yvec[j] = vec[iy + j];
929 tot_vec[j] += yvec[j];
930 total += yvec[j];
931 super_total += yvec[j];
932 }
933
934 print.name = name + "_" + (havesub ? subnames[i] : to_string(i));
935 print.desc = desc;
936 print.vec = yvec;
937 print.total = total;
938 print(stream);
939 }
940
941 if ((flags & ::Statistics::total) && (x > 1)) {
942 print.name = name;
943 print.desc = desc;
944 print.vec = tot_vec;
945 print.total = super_total;
946 print(stream);
947 }
948 }
949
950 void
951 DistDataBase::display(ostream &stream, DisplayMode mode) const
952 {
953 const_cast<DistDataBase *>(this)->update();
954
955 DistPrint print;
956
957 print.name = name;
958 print.desc = desc;
959 print.flags = flags;
960 print.mode = mode;
961 print.precision = precision;
962
963 print.min_val = data.min_val;
964 print.max_val = data.max_val;
965 print.underflow = data.underflow;
966 print.overflow = data.overflow;
967 print.vec = data.vec;
968 print.sum = data.sum;
969 print.squares = data.squares;
970 print.samples = data.samples;
971
972 print.min = data.min;
973 print.max = data.max;
974 print.bucket_size = data.bucket_size;
975 print.size = data.size;
976 print.fancy = data.fancy;
977
978 print(stream);
979 }
980
981 void
982 VectorDistDataBase::display(ostream &stream, DisplayMode mode) const
983 {
984 const_cast<VectorDistDataBase *>(this)->update();
985
986 for (int i = 0; i < size(); ++i) {
987 DistPrint print;
988
989 print.name = name +
990 (subnames[i].empty() ? ("_" + to_string(i)) : subnames[i]);
991 print.desc = subdescs[i].empty() ? desc : subdescs[i];
992 print.flags = flags;
993 print.mode = mode;
994 print.precision = precision;
995
996 print.min_val = data[i].min_val;
997 print.max_val = data[i].max_val;
998 print.underflow = data[i].underflow;
999 print.overflow = data[i].overflow;
1000 print.vec = data[i].vec;
1001 print.sum = data[i].sum;
1002 print.squares = data[i].squares;
1003 print.samples = data[i].samples;
1004
1005 print.min = data[i].min;
1006 print.max = data[i].max;
1007 print.bucket_size = data[i].bucket_size;
1008 print.size = data[i].size;
1009 print.fancy = data[i].fancy;
1010
1011 print(stream);
1012 }
1013 }
1014
1015 void
1016 ScalarDataBase::python(Python &py) const
1017 {
1018 py.name("Scalar");
1019 py.qarg(name);
1020 py.qqqarg(desc);
1021 py.kwarg("binned", binned());
1022 py.kwarg("precision", precision);
1023 py.kwarg("flags", flags);
1024 if (prereq)
1025 py.qkwarg("prereq", prereq->name);
1026 py.kwarg("value", val());
1027 py.nameEnd();
1028 }
1029
1030 void
1031 VectorDataBase::python(Python &py) const
1032 {
1033 const_cast<VectorDataBase *>(this)->update();
1034
1035 py.name("Vector");
1036 py.qarg(name);
1037 py.qqqarg(desc);
1038 py.kwarg("binned", binned());
1039 py.kwarg("precision", precision);
1040 py.kwarg("flags", flags);
1041 if (prereq)
1042 py.qkwarg("prereq", prereq->name);
1043 py.kwarg("value", val());
1044 if (!subnames.empty())
1045 py.qkwarg("subnames", subnames);
1046 if (!subdescs.empty())
1047 py.qkwarg("subdescs", subdescs);
1048 py.nameEnd();
1049 }
1050
1051 void
1052 DistDataData::python(Python &py, const string &name) const
1053 {
1054 string s = name.empty() ? "" : name + "=";
1055
1056 if (samples == 0 || fancy)
1057 s += "SimpleDist";
1058 else
1059 s += "FullDist";
1060
1061 py.name(s);
1062 py.arg(sum);
1063 py.arg(squares);
1064 py.arg(samples);
1065 if (samples && !fancy) {
1066 py.arg(min_val);
1067 py.arg(min_val);
1068 py.arg(underflow);
1069 py.arg(vec);
1070 py.arg(overflow);
1071 py.arg(min);
1072 py.arg(max);
1073 py.arg(bucket_size);
1074 py.arg(size);
1075 }
1076 py.nameEnd();
1077 }
1078
1079 void
1080 FormulaDataBase::python(Python &py) const
1081 {
1082 const_cast<FormulaDataBase *>(this)->update();
1083
1084 py.name("Formula");
1085 py.qarg(name);
1086 py.qqqarg(desc);
1087 py.kwarg("binned", binned());
1088 py.kwarg("precision", precision);
1089 py.kwarg("flags", flags);
1090 if (prereq)
1091 py.qkwarg("prereq", prereq->name);
1092 py.qkwarg("formula", str());
1093 if (!subnames.empty())
1094 py.qkwarg("subnames", subnames);
1095 if (!subdescs.empty())
1096 py.qkwarg("subdescs", subdescs);
1097 py.nameEnd();
1098 }
1099
1100 void
1101 DistDataBase::python(Python &py) const
1102 {
1103 const_cast<DistDataBase *>(this)->update();
1104
1105 py.name("Dist");
1106 py.qarg(name);
1107 py.qqqarg(desc);
1108 py.kwarg("binned", binned());
1109 py.kwarg("precision", precision);
1110 py.kwarg("flags", flags);
1111 if (prereq)
1112 py.qkwarg("prereq", prereq->name);
1113 data.python(py, "dist");
1114 py.nameEnd();
1115 }
1116
1117 void
1118 VectorDistDataBase::python(Python &py) const
1119 {
1120 const_cast<VectorDistDataBase *>(this)->update();
1121
1122 py.name("VectorDist");
1123 py.qarg(name);
1124 py.qqqarg(desc);
1125 py.kwarg("binned", binned());
1126 py.kwarg("precision", precision);
1127 py.kwarg("flags", flags);
1128 if (prereq)
1129 py.qkwarg("prereq", prereq->name);
1130 if (!subnames.empty())
1131 py.qkwarg("subnames", subnames);
1132 if (!subdescs.empty())
1133 py.qkwarg("subdescs", subdescs);
1134
1135 py.tuple("dist");
1136 typedef std::vector<DistDataData>::const_iterator iter;
1137 iter i = data.begin();
1138 iter end = data.end();
1139 while (i != end) {
1140 i->python(py, "");
1141 ++i;
1142 }
1143 py.tupleEnd();
1144 py.nameEnd();
1145 }
1146
1147 void
1148 Vector2dDataBase::python(Python &py) const
1149 {
1150 const_cast<Vector2dDataBase *>(this)->update();
1151
1152 py.name("Vector2d");
1153 py.qarg(name);
1154 py.qqqarg(desc);
1155 py.kwarg("binned", binned());
1156 py.kwarg("precision", precision);
1157 py.kwarg("flags", flags);
1158 if (prereq)
1159 py.qkwarg("prereq", prereq->name);
1160
1161 py.kwarg("value", vec);
1162 if (!subnames.empty())
1163 py.qkwarg("subnames", subnames);
1164 if (!subdescs.empty())
1165 py.qkwarg("subdescs", subdescs);
1166 if (!y_subnames.empty())
1167 py.qkwarg("ysubnames", y_subnames);
1168
1169 py.kwarg("x", x);
1170 py.kwarg("y", y);
1171 py.nameEnd();
1172 }
1173
1174 void
1175 FormulaBase::val(rvec_t &vec) const
1176 {
1177 if (root)
1178 vec = root->val();
1179 }
1180
1181 result_t
1182 FormulaBase::total() const
1183 {
1184 return root ? root->total() : 0.0;
1185 }
1186
1187 size_t
1188 FormulaBase::size() const
1189 {
1190 if (!root)
1191 return 0;
1192 else
1193 return root->size();
1194 }
1195
1196 bool
1197 FormulaBase::binned() const
1198 {
1199 return root && root->binned();
1200 }
1201
1202 void
1203 FormulaBase::reset()
1204 {
1205 }
1206
1207 bool
1208 FormulaBase::zero() const
1209 {
1210 rvec_t vec;
1211 val(vec);
1212 for (int i = 0; i < vec.size(); ++i)
1213 if (vec[i] != 0.0)
1214 return false;
1215 return true;
1216 }
1217
1218 void
1219 FormulaBase::update(StatData *)
1220 {
1221 }
1222
1223 string
1224 FormulaBase::str() const
1225 {
1226 return root ? root->str() : "";
1227 }
1228
1229 Formula::Formula()
1230 {
1231 setInit();
1232 }
1233
1234 Formula::Formula(Temp r)
1235 {
1236 root = r;
1237 assert(size());
1238 }
1239
1240 const Formula &
1241 Formula::operator=(Temp r)
1242 {
1243 assert(!root && "Can't change formulas");
1244 root = r;
1245 assert(size());
1246 return *this;
1247 }
1248
1249 const Formula &
1250 Formula::operator+=(Temp r)
1251 {
1252 if (root)
1253 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
1254 else
1255 root = r;
1256 assert(size());
1257 return *this;
1258 }
1259
1260 MainBin::MainBin(const string &name)
1261 : _name(name), mem(NULL), memsize(-1)
1262 {
1263 Database::StatDB().regBin(this, name);
1264 }
1265
1266 MainBin::~MainBin()
1267 {
1268 if (mem)
1269 delete [] mem;
1270 }
1271
1272 char *
1273 MainBin::memory(off_t off)
1274 {
1275 if (memsize == -1)
1276 memsize = CeilPow2((size_t) offset());
1277
1278 if (!mem) {
1279 mem = new char[memsize];
1280 memset(mem, 0, memsize);
1281 }
1282
1283 assert(offset() <= size());
1284 return mem + off;
1285 }
1286
1287 void
1288 check()
1289 {
1290 Database::StatDB().check();
1291 }
1292
1293 void
1294 dump(ostream &stream, DisplayMode mode)
1295 {
1296 Database::StatDB().dump(stream, mode);
1297 }
1298
1299 void
1300 python_start(const string &file)
1301 {
1302 Database::StatDB().python_start(file);
1303 }
1304
1305 void
1306 python_dump(const string &name, const string &subname)
1307 {
1308 Database::StatDB().python_dump(name, subname);
1309 }
1310
1311
1312 CallbackQueue resetQueue;
1313
1314 void
1315 registerResetCallback(Callback *cb)
1316 {
1317 resetQueue.add(cb);
1318 }
1319
1320 void
1321 reset()
1322 {
1323 Database::StatDB().reset();
1324 resetQueue.process();
1325 }
1326
1327 } // namespace Statistics