statistics.cc revision 394
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/misc.hh" 39#include "base/statistics.hh" 40#include "base/str.hh" 41#include "sim/universe.hh" 42 43#ifdef __M5_NAN 44float 45__nan() 46{ 47 union { 48 uint32_t ui; 49 float f; 50 } nan; 51 52 nan.ui = 0x7fc00000; 53 return nan.f; 54} 55#endif 56 57#ifdef STAT_DEBUG 58static int total_stats = 0; 59#endif 60 61using namespace std; 62 63// This is a hack to get this parameter from the old stats package. 64namespace Statistics { 65bool PrintDescriptions = true; 66DisplayMode default_mode = mode_simplescalar; 67 68namespace Database 69{ 70 class Data 71 { 72 private: 73 typedef list<StatData *> list_t; 74 typedef map<void *, StatData *> map_t; 75 76 list<MainBin *> bins; 77 map<const MainBin *, string > bin_names; 78 list_t binnedStats; 79 80 list_t allStats; 81 list_t printStats; 82 map_t statMap; 83 84 public: 85 void dump(ostream &stream); 86 87 StatData *find(void *stat); 88 void mapStat(void *stat, StatData *data); 89 90 void check(); 91 void reset(); 92 void regBin(MainBin *bin, string name); 93 void regPrint(void *stat); 94 }; 95 96 97void 98Data::dump(ostream &stream) 99{ 100#ifndef FS_MEASURE 101 list_t::iterator i = printStats.begin(); 102 list_t::iterator end = printStats.end(); 103 while (i != end) { 104 StatData *stat = *i; 105 if (stat->binned()) 106 binnedStats.push_back(stat); 107 ++i; 108 } 109#endif //FS_MEASURE 110 111 list<MainBin *>::iterator j = bins.begin(); 112 list<MainBin *>::iterator bins_end=bins.end(); 113 114 if (!bins.empty()) { 115 ccprintf(stream, "PRINTING BINNED STATS\n"); 116 while (j != bins_end) { 117 (*j)->activate(); 118 map<const MainBin *, string>::const_iterator iter; 119 iter = bin_names.find(*j); 120 if (iter == bin_names.end()) 121 panic("a binned stat not found in names map!"); 122 ccprintf(stream,"---%s Bin------------\n", (*iter).second); 123 124#ifdef FS_MEASURE 125 list_t::iterator i = printStats.begin(); 126 list_t::iterator end = printStats.end(); 127#else 128 list_t::iterator i = binnedStats.begin(); 129 list_t::iterator end = binnedStats.end(); 130#endif 131 while (i != end) { 132 StatData *stat = *i; 133 if (stat->dodisplay()) 134 stat->display(stream); 135 ++i; 136 } 137 ++j; 138 ccprintf(stream, "---------------------------------\n"); 139 } 140#ifndef FS_MEASURE 141 ccprintf(stream, "**************ALL STATS************\n"); 142#endif 143 } 144 145/** 146 * get bin totals working, then print the stat here (as total), even if 147 * its' binned. (this is only for the case you selectively bin a few stats 148 */ 149#ifndef FS_MEASURE 150 list_t::iterator k = printStats.begin(); 151 list_t::iterator endprint = printStats.end(); 152 while (k != endprint) { 153 StatData *stat = *k; 154 if (stat->dodisplay() /*&& !stat->binned()*/) 155 stat->display(stream); 156 ++k; 157 } 158#endif 159} 160 161StatData * 162Data::find(void *stat) 163{ 164 map_t::const_iterator i = statMap.find(stat); 165 166 if (i == statMap.end()) 167 return NULL; 168 169 return (*i).second; 170} 171 172void 173Data::check() 174{ 175 list_t::iterator i = allStats.begin(); 176 list_t::iterator end = allStats.end(); 177 178 while (i != end) { 179 StatData *stat = *i; 180 assert(stat); 181 stat->check(); 182 ++i; 183 } 184} 185 186void 187Data::reset() 188{ 189 list_t::iterator i = allStats.begin(); 190 list_t::iterator end = allStats.end(); 191 while (i != end) { 192 StatData *stat = *i; 193 stat->reset(); 194 ++i; 195 } 196 197 MainBin *orig = MainBin::curBin(); 198 199 list<MainBin *>::iterator bi = bins.begin(); 200 list<MainBin *>::iterator be = bins.end(); 201 while (bi != be) { 202 MainBin *bin = *bi; 203 bin->activate(); 204 205 i = allStats.begin(); 206 while (i != end) { 207 StatData *stat = *i; 208 stat->reset(); 209 ++i; 210 } 211 ++bi; 212 } 213 214 if (orig) 215 orig->activate(); 216} 217 218void 219Data::mapStat(void *stat, StatData *data) 220{ 221 if (statMap.find(stat) != statMap.end()) 222 panic("shouldn't register stat twice!"); 223 224 allStats.push_back(data); 225 226 bool success = (statMap.insert(make_pair(stat, data))).second; 227 assert(statMap.find(stat) != statMap.end()); 228 assert(success && "this should never fail"); 229} 230 231void 232Data::regBin(MainBin *bin, string name) 233{ 234 if (bin_names.find(bin) != bin_names.end()) 235 panic("shouldn't register bin twice"); 236 237 bins.push_back(bin); 238 239 bool success = (bin_names.insert(make_pair(bin,name))).second; 240 assert(bin_names.find(bin) != bin_names.end()); 241 assert(success && "this should not fail"); 242 243 cprintf("registering %s\n", name); 244} 245 246void 247Data::regPrint(void *stat) 248{ 249 StatData *data = find(stat); 250 251 if (!data->print) { 252 data->print = true; 253 254 list_t::iterator j = printStats.insert(printStats.end(), data); 255 inplace_merge(printStats.begin(), j, 256 printStats.end(), StatData::less); 257 } 258 259} 260 261Data & 262StatDB() 263{ 264 static Data db; 265 return db; 266} 267 268} 269 270StatData * 271DataAccess::find() const 272{ 273 return Database::StatDB().find(const_cast<void *>((const void *)this)); 274} 275 276void 277DataAccess::map(StatData *data) 278{ 279 Database::StatDB().mapStat(this, data); 280} 281 282StatData * 283DataAccess::statData() 284{ 285 StatData *ptr = find(); 286 assert(ptr); 287 return ptr; 288} 289 290const StatData * 291DataAccess::statData() const 292{ 293 const StatData *ptr = find(); 294 assert(ptr); 295 return ptr; 296} 297 298void 299DataAccess::setInit() 300{ 301 statData()->init = true; 302} 303 304void 305DataAccess::setPrint() 306{ 307 Database::StatDB().regPrint(this); 308} 309 310StatData::~StatData() 311{ 312} 313 314bool 315StatData::less(StatData *stat1, StatData *stat2) 316{ 317 const string &name1 = stat1->name; 318 const string &name2 = stat2->name; 319 320 vector<string> v1; 321 vector<string> v2; 322 323 tokenize(v1, name1, '.'); 324 tokenize(v2, name2, '.'); 325 326 int last = min(v1.size(), v2.size()) - 1; 327 for (int i = 0; i < last; ++i) 328 if (v1[i] != v2[i]) 329 return v1[i] < v2[i]; 330 331 // Special compare for last element. 332 if (v1[last] == v2[last]) 333 return v1.size() < v2.size(); 334 else 335 return v1[last] < v2[last]; 336 337 return false; 338} 339 340bool 341StatData::check() const 342{ 343 if (!init) { 344#ifdef STAT_DEBUG 345 cprintf("this is stat number %d\n",(*i)->number); 346#endif 347 panic("Not all stats have been initialized"); 348 return false; 349 } 350 351 if (print && name.empty()) { 352 panic("all printable stats must be named"); 353 return false; 354 } 355 356 return true; 357} 358 359string 360ValueToString(result_t value, DisplayMode mode, int precision) 361{ 362 stringstream val; 363 364 if (!isnan(value)) { 365 if (precision != -1) 366 val.precision(precision); 367 else if (value == rint(value)) 368 val.precision(0); 369 370 val.unsetf(ios::showpoint); 371 val.setf(ios::fixed); 372 val << value; 373 } else { 374 val << (mode == mode_m5 ? "no value" : "<err: div-0>"); 375 } 376 377 return val.str(); 378} 379 380struct ScalarPrint 381{ 382 result_t value; 383 string name; 384 string desc; 385 int precision; 386 DisplayMode mode; 387 FormatFlags flags; 388 result_t pdf; 389 result_t cdf; 390 391 ScalarPrint() 392 : value(0.0), precision(0), mode(default_mode), flags(0), 393 pdf(NAN), cdf(NAN) 394 {} 395 396 void operator()(ostream &stream) const; 397}; 398 399void 400ScalarPrint::operator()(ostream &stream) const 401{ 402 if (flags & nozero && value == 0.0 || 403 flags & nonan && isnan(value)) 404 return; 405 406 stringstream pdfstr, cdfstr; 407 408 if (!isnan(pdf)) 409 ccprintf(pdfstr, "%.2f%%", pdf * 100.0); 410 411 if (!isnan(cdf)) 412 ccprintf(cdfstr, "%.2f%%", cdf * 100.0); 413 414 if (mode == mode_simplescalar && flags & __substat) { 415 ccprintf(stream, "%32s %12s %10s %10s", name, 416 ValueToString(value, mode, precision), 417 pdfstr, cdfstr); 418 } else { 419 ccprintf(stream, "%-40s %12s %10s %10s", name, 420 ValueToString(value, mode, precision), pdfstr, cdfstr); 421 } 422 423 if (PrintDescriptions) { 424 if (!desc.empty()) 425 ccprintf(stream, " # %s", desc); 426 } 427 stream << endl; 428} 429 430struct VectorPrint 431{ 432 string name; 433 string desc; 434 vector<string> subnames; 435 vector<string> subdescs; 436 int precision; 437 DisplayMode mode; 438 FormatFlags flags; 439 rvec_t vec; 440 result_t total; 441 442 VectorPrint() 443 : subnames(0), subdescs(0), precision(-1), mode(default_mode), 444 flags(0), total(NAN) 445 {} 446 447 void operator()(ostream &stream) const; 448}; 449 450void 451VectorPrint::operator()(std::ostream &stream) const 452{ 453 int _size = vec.size(); 454 result_t _total = 0.0; 455 456 if (flags & (pdf | cdf)) { 457 for (int i = 0; i < _size; ++i) { 458 _total += vec[i]; 459 } 460 } 461 462 string base = name + ((mode == mode_simplescalar) ? "_" : "::"); 463 464 ScalarPrint print; 465 print.name = name; 466 print.desc = desc; 467 print.precision = precision; 468 print.flags = flags; 469 470 bool havesub = !subnames.empty(); 471 472 if (_size == 1) { 473 print.value = vec[0]; 474 print(stream); 475 } else if (mode == mode_m5) { 476 for (int i = 0; i < _size; ++i) { 477 if (havesub && (i >= subnames.size() || subnames[i].empty())) 478 continue; 479 480 print.name = base + (havesub ? subnames[i] : to_string(i)); 481 print.desc = subdescs.empty() ? desc : subdescs[i]; 482 print.value = vec[i]; 483 484 if (_total && (flags & pdf)) { 485 print.pdf = vec[i] / _total; 486 print.cdf += print.pdf; 487 } 488 489 print(stream); 490 } 491 492 if (flags & ::Statistics::total) { 493 print.name = base + "total"; 494 print.desc = desc; 495 print.value = total; 496 print(stream); 497 } 498 } else { 499 if (flags & ::Statistics::total) { 500 print.value = total; 501 print(stream); 502 } 503 504 result_t _pdf = 0.0; 505 result_t _cdf = 0.0; 506 if (flags & dist) { 507 ccprintf(stream, "%s.start_dist\n", name); 508 for (int i = 0; i < _size; ++i) { 509 print.name = havesub ? subnames[i] : to_string(i); 510 print.desc = subdescs.empty() ? desc : subdescs[i]; 511 print.flags |= __substat; 512 print.value = vec[i]; 513 514 if (_total) { 515 _pdf = vec[i] / _total; 516 _cdf += _pdf; 517 } 518 519 if (flags & pdf) 520 print.pdf = _pdf; 521 if (flags & cdf) 522 print.cdf = _cdf; 523 524 print(stream); 525 } 526 ccprintf(stream, "%s.end_dist\n", name); 527 } else { 528 for (int i = 0; i < _size; ++i) { 529 if (havesub && subnames[i].empty()) 530 continue; 531 532 print.name = base; 533 print.name += havesub ? subnames[i] : to_string(i); 534 print.desc = subdescs.empty() ? desc : subdescs[i]; 535 print.value = vec[i]; 536 537 if (_total) { 538 _pdf = vec[i] / _total; 539 _cdf += _pdf; 540 } else { 541 _pdf = _cdf = NAN; 542 } 543 544 if (flags & pdf) { 545 print.pdf = _pdf; 546 print.cdf = _cdf; 547 } 548 549 print(stream); 550 } 551 } 552 } 553} 554 555struct DistPrint 556{ 557 string name; 558 string desc; 559 int precision; 560 DisplayMode mode; 561 FormatFlags flags; 562 563 result_t min_val; 564 result_t max_val; 565 result_t underflow; 566 result_t overflow; 567 rvec_t vec; 568 result_t sum; 569 result_t squares; 570 result_t samples; 571 572 int min; 573 int max; 574 int bucket_size; 575 int size; 576 bool fancy; 577 578 void operator()(ostream &stream) const; 579}; 580 581void 582DistPrint::operator()(ostream &stream) const 583{ 584 if (fancy) { 585 ScalarPrint print; 586 string base = name + ((mode == mode_m5) ? "::" : "_"); 587 588 print.precision = precision; 589 print.flags = flags; 590 print.desc = desc; 591 592 print.name = base + "mean"; 593 print.value = samples ? sum / samples : NAN; 594 print(stream); 595 596 print.name = base + "stdev"; 597 print.value = samples ? sqrt((samples * squares - sum * sum) / 598 (samples * (samples - 1.0))) : NAN; 599 print(stream); 600 601 print.name = "**Ignore: " + base + "TOT"; 602 print.value = samples; 603 print(stream); 604 return; 605 } 606 607 assert(size == vec.size()); 608 609 result_t total = 0.0; 610 611 total += underflow; 612 for (int i = 0; i < size; ++i) 613 total += vec[i]; 614 total += overflow; 615 616 string base = name + (mode == mode_m5 ? "::" : "."); 617 618 ScalarPrint print; 619 print.desc = (mode == mode_m5) ? desc : ""; 620 print.precision = precision; 621 print.mode = mode; 622 print.flags = flags; 623 624 if (mode == mode_simplescalar) { 625 ccprintf(stream, "%-42s", base + "start_dist"); 626 if (PrintDescriptions && !desc.empty()) 627 ccprintf(stream, " # %s", desc); 628 stream << endl; 629 } 630 631 print.name = base + "samples"; 632 print.value = samples; 633 print(stream); 634 635 print.name = base + "min_value"; 636 print.value = min_val; 637 print(stream); 638 639 if (mode == mode_m5 || underflow > 0.0) { 640 print.name = base + "underflows"; 641 print.value = underflow; 642 if (mode == mode_m5 && total) { 643 print.pdf = underflow / total; 644 print.cdf += print.pdf; 645 } 646 print(stream); 647 } 648 649 650 if (mode == mode_m5) { 651 for (int i = 0; i < size; ++i) { 652 stringstream namestr; 653 namestr << name; 654 655 int low = i * bucket_size + min; 656 int high = ::min((i + 1) * bucket_size + min - 1, max); 657 namestr << low; 658 if (low < high) 659 namestr << "-" << high; 660 661 print.name = namestr.str(); 662 print.value = vec[i]; 663 if (total) { 664 print.pdf = vec[i] / total; 665 print.cdf += print.pdf; 666 } 667 print(stream); 668 } 669 670 } else { 671 int _min; 672 result_t _pdf; 673 result_t _cdf = 0.0; 674 675 print.flags = flags | __substat; 676 677 for (int i = 0; i < size; ++i) { 678 if (flags & nozero && vec[i] == 0.0 || 679 flags & nonan && isnan(vec[i])) 680 continue; 681 682 _min = i * bucket_size + min; 683 _pdf = vec[i] / total * 100.0; 684 _cdf += _pdf; 685 686 687 print.name = ValueToString(_min, mode, 0); 688 print.value = vec[i]; 689 print.pdf = (flags & pdf) ? _pdf : NAN; 690 print.cdf = (flags & cdf) ? _cdf : NAN; 691 print(stream); 692 } 693 694 print.flags = flags; 695 if (flags & (pdf || cdf)) { 696 print.pdf = NAN; 697 print.cdf = NAN; 698 } 699 } 700 701 if (mode == mode_m5 || overflow > 0.0) { 702 print.name = base + "overflows"; 703 print.value = overflow; 704 if (mode == mode_m5 && total) { 705 print.pdf = overflow / total; 706 print.cdf += print.pdf; 707 } 708 print(stream); 709 } 710 711 print.pdf = NAN; 712 print.cdf = NAN; 713 714 if (mode != mode_simplescalar) { 715 print.name = base + "total"; 716 print.value = total; 717 print(stream); 718 } 719 720 print.name = base + "max_value"; 721 print.value = max_val; 722 print(stream); 723 724 if (mode != mode_simplescalar && samples != 0) { 725 print.name = base + "mean"; 726 print.value = sum / samples; 727 print(stream); 728 729 print.name = base + "stdev"; 730 print.value = sqrt((samples * squares - sum * sum) / 731 (samples * (samples - 1.0))); 732 print(stream); 733 } 734 735 if (mode == mode_simplescalar) 736 ccprintf(stream, "%send_dist\n\n", base); 737} 738 739void 740ScalarDataBase::display(ostream &stream) const 741{ 742 ScalarPrint print; 743 print.value = val(); 744 print.name = name; 745 print.desc = desc; 746 print.precision = precision; 747 print.flags = flags; 748 749 print(stream); 750} 751 752void 753VectorDataBase::display(ostream &stream) const 754{ 755 int size = this->size(); 756 const_cast<VectorDataBase *>(this)->update(); 757 758 VectorPrint print; 759 760 print.name = name; 761 print.desc = desc; 762 print.mode = mode; 763 print.flags = flags; 764 print.precision = precision; 765 print.vec = val(); 766 print.total = total(); 767 768 for (int i = 0; i < size; ++i) { 769 if (!subnames[i].empty()) { 770 print.subnames = subnames; 771 print.subnames.resize(size); 772 for (int i = 0; i < size; ++i) { 773 if (!subnames[i].empty() && !subdescs[i].empty()) { 774 print.subdescs = subdescs; 775 print.subdescs.resize(size); 776 break; 777 } 778 } 779 break; 780 } 781 } 782 783 784 print(stream); 785} 786 787void 788Vector2dDataBase::display(ostream &stream) const 789{ 790 const_cast<Vector2dDataBase *>(this)->update(); 791 792 bool havesub = false; 793 VectorPrint print; 794 795 print.subnames = y_subnames; 796 print.mode = mode; 797 print.flags = flags; 798 print.precision = precision; 799 800 if (!subnames.empty()) { 801 for (int i = 0; i < x; ++i) 802 if (!subnames[i].empty()) 803 havesub = true; 804 } 805 806 rvec_t tot_vec(y); 807 result_t super_total = 0.0; 808 for (int i = 0; i < x; ++i) { 809 if (havesub && (i >= subnames.size() || subnames[i].empty())) 810 continue; 811 812 int iy = i * y; 813 rvec_t yvec(y); 814 815 result_t total = 0.0; 816 for (int j = 0; j < y; ++j) { 817 yvec[j] = vec[iy + j]; 818 tot_vec[j] += yvec[j]; 819 total += yvec[j]; 820 super_total += yvec[j]; 821 } 822 823 print.name = name + "_" + (havesub ? subnames[i] : to_string(i)); 824 print.desc = desc; 825 print.vec = yvec; 826 print.total = total; 827 print(stream); 828 } 829 830 if ((flags & ::Statistics::total) && (x > 1)) { 831 print.name = name; 832 print.desc = desc; 833 print.vec = tot_vec; 834 print.total = super_total; 835 print(stream); 836 } 837} 838 839void 840DistDataBase::display(ostream &stream) const 841{ 842 const_cast<DistDataBase *>(this)->update(); 843 844 DistPrint print; 845 846 print.name = name; 847 print.desc = desc; 848 print.precision = precision; 849 print.mode = mode; 850 print.flags = flags; 851 852 print.min_val = data.min_val; 853 print.max_val = data.max_val; 854 print.underflow = data.underflow; 855 print.overflow = data.overflow; 856 print.vec = data.vec; 857 print.sum = data.sum; 858 print.squares = data.squares; 859 print.samples = data.samples; 860 861 print.min = data.min; 862 print.max = data.max; 863 print.bucket_size = data.bucket_size; 864 print.size = data.size; 865 print.fancy = data.fancy; 866 867 print(stream); 868} 869 870void 871VectorDistDataBase::display(ostream &stream) const 872{ 873 const_cast<VectorDistDataBase *>(this)->update(); 874 875 for (int i = 0; i < size(); ++i) { 876 DistPrint print; 877 878 print.name = name + 879 (subnames[i].empty() ? ("_" + to_string(i)) : subnames[i]); 880 print.desc = subdescs[i].empty() ? desc : subdescs[i]; 881 print.precision = precision; 882 print.mode = mode; 883 print.flags = flags; 884 885 print.min_val = data[i].min_val; 886 print.max_val = data[i].max_val; 887 print.underflow = data[i].underflow; 888 print.overflow = data[i].overflow; 889 print.vec = data[i].vec; 890 print.sum = data[i].sum; 891 print.squares = data[i].squares; 892 print.samples = data[i].samples; 893 894 print.min = data[i].min; 895 print.max = data[i].max; 896 print.bucket_size = data[i].bucket_size; 897 print.size = data[i].size; 898 print.fancy = data[i].fancy; 899 900 print(stream); 901 } 902} 903 904void 905FormulaBase::val(rvec_t &vec) const 906{ 907 vec = root->val(); 908} 909 910result_t 911FormulaBase::total() const 912{ 913 return root->total(); 914} 915 916size_t 917FormulaBase::size() const 918{ 919 if (!root) 920 return 0; 921 else 922 return root->size(); 923} 924 925bool 926FormulaBase::binned() const 927{ 928 return root->binned(); 929} 930 931void 932FormulaBase::reset() 933{ 934} 935 936bool 937FormulaBase::zero() const 938{ 939 rvec_t vec; 940 val(vec); 941 for (int i = 0; i < vec.size(); ++i) 942 if (vec[i] != 0.0) 943 return false; 944 return true; 945} 946 947void 948FormulaBase::update(StatData *) 949{ 950} 951 952Formula::Formula() 953{ 954 setInit(); 955} 956 957Formula::Formula(Temp r) 958{ 959 root = r; 960 assert(size()); 961} 962 963const Formula & 964Formula::operator=(Temp r) 965{ 966 assert(!root && "Can't change formulas"); 967 root = r; 968 assert(size()); 969 return *this; 970} 971 972const Formula & 973Formula::operator+=(Temp r) 974{ 975 if (root) 976 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r)); 977 else 978 root = r; 979 assert(size()); 980 return *this; 981} 982 983MainBin::MainBin(const string &name) 984 : _name(name), mem(NULL), memsize(-1) 985{ 986 Database::StatDB().regBin(this, name); 987} 988 989MainBin::~MainBin() 990{ 991 if (mem) 992 delete [] mem; 993} 994 995char * 996MainBin::memory(off_t off) 997{ 998 if (memsize == -1) 999 memsize = CeilPow2((size_t) offset()); 1000 1001 if (!mem) { 1002 mem = new char[memsize]; 1003 memset(mem, 0, memsize); 1004 } 1005 1006 assert(offset() <= size()); 1007 return mem + off; 1008} 1009 1010void 1011check() 1012{ 1013 Database::StatDB().check(); 1014} 1015 1016void 1017dump(ostream &stream) 1018{ 1019 Database::StatDB().dump(stream); 1020} 1021 1022CallbackQueue resetQueue; 1023 1024void 1025registerResetCallback(Callback *cb) 1026{ 1027 resetQueue.add(cb); 1028} 1029 1030void 1031reset() 1032{ 1033 Database::StatDB().reset(); 1034 resetQueue.process(); 1035} 1036 1037} // namespace Statistics 1038