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