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