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