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