statistics.hh revision 5547:747034106af4
1/* 2 * Copyright (c) 2003-2005 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 * Authors: Nathan Binkert 29 * Erik Hallnor 30 */ 31 32/** @file 33 * Declaration of Statistics objects. 34 */ 35 36/** 37* @todo 38* 39* Generalized N-dimensinal vector 40* documentation 41* key stats 42* interval stats 43* -- these both can use the same function that prints out a 44* specific set of stats 45* VectorStandardDeviation totals 46* Document Namespaces 47*/ 48#ifndef __BASE_STATISTICS_HH__ 49#define __BASE_STATISTICS_HH__ 50 51#include <algorithm> 52#include <cassert> 53#ifdef __SUNPRO_CC 54#include <math.h> 55#endif 56#include <cmath> 57#include <functional> 58#include <iosfwd> 59#include <limits> 60#include <string> 61#include <vector> 62 63#include "base/cprintf.hh" 64#include "base/intmath.hh" 65#include "base/refcnt.hh" 66#include "base/str.hh" 67#include "base/stats/flags.hh" 68#include "base/stats/visit.hh" 69#include "base/stats/types.hh" 70#include "sim/host.hh" 71 72class Callback; 73 74/** The current simulated tick. */ 75extern Tick curTick; 76 77/* A namespace for all of the Statistics */ 78namespace Stats { 79 80typedef std::numeric_limits<Counter> CounterLimits; 81 82/* Contains the statistic implementation details */ 83////////////////////////////////////////////////////////////////////// 84// 85// Statistics Framework Base classes 86// 87////////////////////////////////////////////////////////////////////// 88struct StatData 89{ 90 /** The name of the stat. */ 91 std::string name; 92 /** The description of the stat. */ 93 std::string desc; 94 /** The formatting flags. */ 95 StatFlags flags; 96 /** The display precision. */ 97 int precision; 98 /** A pointer to a prerequisite Stat. */ 99 const StatData *prereq; 100 /** 101 * A unique stat ID for each stat in the simulator. 102 * Can be used externally for lookups as well as for debugging. 103 */ 104 int id; 105 106 StatData(); 107 virtual ~StatData(); 108 109 /** 110 * Reset the corresponding stat to the default state. 111 */ 112 virtual void reset() = 0; 113 114 /** 115 * @return true if this stat has a value and satisfies its 116 * requirement as a prereq 117 */ 118 virtual bool zero() const = 0; 119 120 /** 121 * Check that this stat has been set up properly and is ready for 122 * use 123 * @return true for success 124 */ 125 virtual bool check() const = 0; 126 bool baseCheck() const; 127 128 /** 129 * Visitor entry for outputing statistics data 130 */ 131 virtual void visit(Visit &visitor) = 0; 132 133 /** 134 * Checks if the first stat's name is alphabetically less than the second. 135 * This function breaks names up at periods and considers each subname 136 * separately. 137 * @param stat1 The first stat. 138 * @param stat2 The second stat. 139 * @return stat1's name is alphabetically before stat2's 140 */ 141 static bool less(StatData *stat1, StatData *stat2); 142}; 143 144class ScalarData : public StatData 145{ 146 public: 147 virtual Counter value() const = 0; 148 virtual Result result() const = 0; 149 virtual Result total() const = 0; 150 virtual void visit(Visit &visitor) { visitor.visit(*this); } 151}; 152 153template <class Stat> 154class ScalarStatData : public ScalarData 155{ 156 protected: 157 Stat &s; 158 159 public: 160 ScalarStatData(Stat &stat) : s(stat) {} 161 162 virtual bool check() const { return s.check(); } 163 virtual Counter value() const { return s.value(); } 164 virtual Result result() const { return s.result(); } 165 virtual Result total() const { return s.total(); } 166 virtual void reset() { s.reset(); } 167 virtual bool zero() const { return s.zero(); } 168}; 169 170struct VectorData : public StatData 171{ 172 /** Names and descriptions of subfields. */ 173 mutable std::vector<std::string> subnames; 174 mutable std::vector<std::string> subdescs; 175 176 virtual size_t size() const = 0; 177 virtual const VCounter &value() const = 0; 178 virtual const VResult &result() const = 0; 179 virtual Result total() const = 0; 180 void update() 181 { 182 if (!subnames.empty()) { 183 int s = size(); 184 if (subnames.size() < s) 185 subnames.resize(s); 186 187 if (subdescs.size() < s) 188 subdescs.resize(s); 189 } 190 } 191}; 192 193template <class Stat> 194class VectorStatData : public VectorData 195{ 196 protected: 197 Stat &s; 198 mutable VCounter cvec; 199 mutable VResult rvec; 200 201 public: 202 VectorStatData(Stat &stat) : s(stat) {} 203 204 virtual bool check() const { return s.check(); } 205 virtual bool zero() const { return s.zero(); } 206 virtual void reset() { s.reset(); } 207 208 virtual size_t size() const { return s.size(); } 209 virtual VCounter &value() const 210 { 211 s.value(cvec); 212 return cvec; 213 } 214 virtual const VResult &result() const 215 { 216 s.result(rvec); 217 return rvec; 218 } 219 virtual Result total() const { return s.total(); } 220 virtual void visit(Visit &visitor) 221 { 222 update(); 223 s.update(this); 224 visitor.visit(*this); 225 } 226}; 227 228struct DistDataData 229{ 230 Counter min_val; 231 Counter max_val; 232 Counter underflow; 233 Counter overflow; 234 VCounter cvec; 235 Counter sum; 236 Counter squares; 237 Counter samples; 238 239 Counter min; 240 Counter max; 241 Counter bucket_size; 242 int size; 243 bool fancy; 244}; 245 246struct DistData : public StatData 247{ 248 /** Local storage for the entry values, used for printing. */ 249 DistDataData data; 250}; 251 252template <class Stat> 253class DistStatData : public DistData 254{ 255 protected: 256 Stat &s; 257 258 public: 259 DistStatData(Stat &stat) : s(stat) {} 260 261 virtual bool check() const { return s.check(); } 262 virtual void reset() { s.reset(); } 263 virtual bool zero() const { return s.zero(); } 264 virtual void visit(Visit &visitor) 265 { 266 s.update(this); 267 visitor.visit(*this); 268 } 269}; 270 271struct VectorDistData : public StatData 272{ 273 std::vector<DistDataData> data; 274 275 /** Names and descriptions of subfields. */ 276 mutable std::vector<std::string> subnames; 277 mutable std::vector<std::string> subdescs; 278 279 /** Local storage for the entry values, used for printing. */ 280 mutable VResult rvec; 281 282 virtual size_t size() const = 0; 283 void update() 284 { 285 int s = size(); 286 if (subnames.size() < s) 287 subnames.resize(s); 288 289 if (subdescs.size() < s) 290 subdescs.resize(s); 291 } 292}; 293 294template <class Stat> 295class VectorDistStatData : public VectorDistData 296{ 297 protected: 298 Stat &s; 299 300 public: 301 VectorDistStatData(Stat &stat) : s(stat) {} 302 303 virtual bool check() const { return s.check(); } 304 virtual void reset() { s.reset(); } 305 virtual size_t size() const { return s.size(); } 306 virtual bool zero() const { return s.zero(); } 307 virtual void visit(Visit &visitor) 308 { 309 update(); 310 s.update(this); 311 visitor.visit(*this); 312 } 313}; 314 315struct Vector2dData : public StatData 316{ 317 /** Names and descriptions of subfields. */ 318 std::vector<std::string> subnames; 319 std::vector<std::string> subdescs; 320 std::vector<std::string> y_subnames; 321 322 /** Local storage for the entry values, used for printing. */ 323 mutable VCounter cvec; 324 mutable int x; 325 mutable int y; 326 327 void update() 328 { 329 if (subnames.size() < x) 330 subnames.resize(x); 331 } 332}; 333 334template <class Stat> 335class Vector2dStatData : public Vector2dData 336{ 337 protected: 338 Stat &s; 339 340 public: 341 Vector2dStatData(Stat &stat) : s(stat) {} 342 343 virtual bool check() const { return s.check(); } 344 virtual void reset() { s.reset(); } 345 virtual bool zero() const { return s.zero(); } 346 virtual void visit(Visit &visitor) 347 { 348 update(); 349 s.update(this); 350 visitor.visit(*this); 351 } 352}; 353 354class DataAccess 355{ 356 protected: 357 StatData *find() const; 358 void map(StatData *data); 359 360 StatData *statData(); 361 const StatData *statData() const; 362 363 void setInit(); 364 void setPrint(); 365}; 366 367template <class Parent, class Child, template <class> class Data> 368class Wrap : public Child 369{ 370 protected: 371 Parent &self() { return *reinterpret_cast<Parent *>(this); } 372 373 protected: 374 Data<Child> *statData() 375 { 376 StatData *__data = DataAccess::statData(); 377 Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data); 378 assert(ptr); 379 return ptr; 380 } 381 382 public: 383 const Data<Child> *statData() const 384 { 385 const StatData *__data = DataAccess::statData(); 386 const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data); 387 assert(ptr); 388 return ptr; 389 } 390 391 protected: 392 /** 393 * Copy constructor, copies are not allowed. 394 */ 395 Wrap(const Wrap &stat); 396 /** 397 * Can't copy stats. 398 */ 399 void operator=(const Wrap &); 400 401 public: 402 Wrap() 403 { 404 this->map(new Data<Child>(*this)); 405 } 406 407 /** 408 * Set the name and marks this stat to print at the end of simulation. 409 * @param name The new name. 410 * @return A reference to this stat. 411 */ 412 Parent &name(const std::string &_name) 413 { 414 Data<Child> *data = this->statData(); 415 data->name = _name; 416 this->setPrint(); 417 return this->self(); 418 } 419 420 /** 421 * Set the description and marks this stat to print at the end of 422 * simulation. 423 * @param desc The new description. 424 * @return A reference to this stat. 425 */ 426 Parent &desc(const std::string &_desc) 427 { 428 this->statData()->desc = _desc; 429 return this->self(); 430 } 431 432 /** 433 * Set the precision and marks this stat to print at the end of simulation. 434 * @param p The new precision 435 * @return A reference to this stat. 436 */ 437 Parent &precision(int _precision) 438 { 439 this->statData()->precision = _precision; 440 return this->self(); 441 } 442 443 /** 444 * Set the flags and marks this stat to print at the end of simulation. 445 * @param f The new flags. 446 * @return A reference to this stat. 447 */ 448 Parent &flags(StatFlags _flags) 449 { 450 this->statData()->flags |= _flags; 451 return this->self(); 452 } 453 454 /** 455 * Set the prerequisite stat and marks this stat to print at the end of 456 * simulation. 457 * @param prereq The prerequisite stat. 458 * @return A reference to this stat. 459 */ 460 template <class Stat> 461 Parent &prereq(const Stat &prereq) 462 { 463 this->statData()->prereq = prereq.statData(); 464 return this->self(); 465 } 466}; 467 468template <class Parent, class Child, template <class Child> class Data> 469class WrapVec : public Wrap<Parent, Child, Data> 470{ 471 public: 472 // The following functions are specific to vectors. If you use them 473 // in a non vector context, you will get a nice compiler error! 474 475 /** 476 * Set the subfield name for the given index, and marks this stat to print 477 * at the end of simulation. 478 * @param index The subfield index. 479 * @param name The new name of the subfield. 480 * @return A reference to this stat. 481 */ 482 Parent &subname(int index, const std::string &name) 483 { 484 std::vector<std::string> &subn = this->statData()->subnames; 485 if (subn.size() <= index) 486 subn.resize(index + 1); 487 subn[index] = name; 488 return this->self(); 489 } 490 491 /** 492 * Set the subfield description for the given index and marks this stat to 493 * print at the end of simulation. 494 * @param index The subfield index. 495 * @param desc The new description of the subfield 496 * @return A reference to this stat. 497 */ 498 Parent &subdesc(int index, const std::string &desc) 499 { 500 std::vector<std::string> &subd = this->statData()->subdescs; 501 if (subd.size() <= index) 502 subd.resize(index + 1); 503 subd[index] = desc; 504 505 return this->self(); 506 } 507 508}; 509 510template <class Parent, class Child, template <class Child> class Data> 511class WrapVec2d : public WrapVec<Parent, Child, Data> 512{ 513 public: 514 /** 515 * @warning This makes the assumption that if you're gonna subnames a 2d 516 * vector, you're subnaming across all y 517 */ 518 Parent &ysubnames(const char **names) 519 { 520 Data<Child> *data = this->statData(); 521 data->y_subnames.resize(this->y); 522 for (int i = 0; i < this->y; ++i) 523 data->y_subnames[i] = names[i]; 524 return this->self(); 525 } 526 Parent &ysubname(int index, const std::string subname) 527 { 528 Data<Child> *data = this->statData(); 529 assert(index < this->y); 530 data->y_subnames.resize(this->y); 531 data->y_subnames[index] = subname.c_str(); 532 return this->self(); 533 } 534}; 535 536////////////////////////////////////////////////////////////////////// 537// 538// Simple Statistics 539// 540////////////////////////////////////////////////////////////////////// 541 542/** 543 * Templatized storage and interface for a simple scalar stat. 544 */ 545struct StatStor 546{ 547 public: 548 /** The paramaters for this storage type, none for a scalar. */ 549 struct Params { }; 550 551 private: 552 /** The statistic value. */ 553 Counter data; 554 555 public: 556 /** 557 * Builds this storage element and calls the base constructor of the 558 * datatype. 559 */ 560 StatStor(const Params &) : data(Counter()) {} 561 562 /** 563 * The the stat to the given value. 564 * @param val The new value. 565 * @param p The paramters of this storage type. 566 */ 567 void set(Counter val, const Params &p) { data = val; } 568 /** 569 * Increment the stat by the given value. 570 * @param val The new value. 571 * @param p The paramters of this storage type. 572 */ 573 void inc(Counter val, const Params &p) { data += val; } 574 /** 575 * Decrement the stat by the given value. 576 * @param val The new value. 577 * @param p The paramters of this storage type. 578 */ 579 void dec(Counter val, const Params &p) { data -= val; } 580 /** 581 * Return the value of this stat as its base type. 582 * @param p The params of this storage type. 583 * @return The value of this stat. 584 */ 585 Counter value(const Params &p) const { return data; } 586 /** 587 * Return the value of this stat as a result type. 588 * @param p The parameters of this storage type. 589 * @return The value of this stat. 590 */ 591 Result result(const Params &p) const { return (Result)data; } 592 /** 593 * Reset stat value to default 594 */ 595 void reset() { data = Counter(); } 596 597 /** 598 * @return true if zero value 599 */ 600 bool zero() const { return data == Counter(); } 601}; 602 603/** 604 * Templatized storage and interface to a per-tick average stat. This keeps 605 * a current count and updates a total (count * ticks) when this count 606 * changes. This allows the quick calculation of a per tick count of the item 607 * being watched. This is good for keeping track of residencies in structures 608 * among other things. 609 */ 610struct AvgStor 611{ 612 public: 613 /** The paramaters for this storage type */ 614 struct Params { }; 615 616 private: 617 /** The current count. */ 618 Counter current; 619 /** The total count for all tick. */ 620 mutable Result total; 621 /** The tick that current last changed. */ 622 mutable Tick last; 623 624 public: 625 /** 626 * Build and initializes this stat storage. 627 */ 628 AvgStor(Params &p) : current(0), total(0), last(0) { } 629 630 /** 631 * Set the current count to the one provided, update the total and last 632 * set values. 633 * @param val The new count. 634 * @param p The parameters for this storage. 635 */ 636 void set(Counter val, Params &p) { 637 total += current * (curTick - last); 638 last = curTick; 639 current = val; 640 } 641 642 /** 643 * Increment the current count by the provided value, calls set. 644 * @param val The amount to increment. 645 * @param p The parameters for this storage. 646 */ 647 void inc(Counter val, Params &p) { set(current + val, p); } 648 649 /** 650 * Deccrement the current count by the provided value, calls set. 651 * @param val The amount to decrement. 652 * @param p The parameters for this storage. 653 */ 654 void dec(Counter val, Params &p) { set(current - val, p); } 655 656 /** 657 * Return the current count. 658 * @param p The parameters for this storage. 659 * @return The current count. 660 */ 661 Counter value(const Params &p) const { return current; } 662 663 /** 664 * Return the current average. 665 * @param p The parameters for this storage. 666 * @return The current average. 667 */ 668 Result result(const Params &p) const 669 { 670 total += current * (curTick - last); 671 last = curTick; 672 return (Result)(total + current) / (Result)(curTick + 1); 673 } 674 675 /** 676 * Reset stat value to default 677 */ 678 void reset() 679 { 680 total = 0; 681 last = curTick; 682 } 683 684 /** 685 * @return true if zero value 686 */ 687 bool zero() const { return total == 0.0; } 688}; 689 690/** 691 * Implementation of a scalar stat. The type of stat is determined by the 692 * Storage template. 693 */ 694template <class Stor> 695class ScalarBase : public DataAccess 696{ 697 public: 698 typedef Stor Storage; 699 700 /** Define the params of the storage class. */ 701 typedef typename Storage::Params Params; 702 703 protected: 704 /** The storage of this stat. */ 705 char storage[sizeof(Storage)] __attribute__ ((aligned (8))); 706 707 /** The parameters for this stat. */ 708 Params params; 709 710 protected: 711 /** 712 * Retrieve the storage. 713 * @param index The vector index to access. 714 * @return The storage object at the given index. 715 */ 716 Storage * 717 data() 718 { 719 return reinterpret_cast<Storage *>(storage); 720 } 721 722 /** 723 * Retrieve a const pointer to the storage. 724 * for the given index. 725 * @param index The vector index to access. 726 * @return A const pointer to the storage object at the given index. 727 */ 728 const Storage * 729 data() const 730 { 731 return reinterpret_cast<const Storage *>(storage); 732 } 733 734 void 735 doInit() 736 { 737 new (storage) Storage(params); 738 setInit(); 739 } 740 741 public: 742 /** 743 * Return the current value of this stat as its base type. 744 * @return The current value. 745 */ 746 Counter value() const { return data()->value(params); } 747 748 public: 749 /** 750 * Create and initialize this stat, register it with the database. 751 */ 752 ScalarBase() 753 { } 754 755 public: 756 // Common operators for stats 757 /** 758 * Increment the stat by 1. This calls the associated storage object inc 759 * function. 760 */ 761 void operator++() { data()->inc(1, params); } 762 /** 763 * Decrement the stat by 1. This calls the associated storage object dec 764 * function. 765 */ 766 void operator--() { data()->dec(1, params); } 767 768 /** Increment the stat by 1. */ 769 void operator++(int) { ++*this; } 770 /** Decrement the stat by 1. */ 771 void operator--(int) { --*this; } 772 773 /** 774 * Set the data value to the given value. This calls the associated storage 775 * object set function. 776 * @param v The new value. 777 */ 778 template <typename U> 779 void operator=(const U &v) { data()->set(v, params); } 780 781 /** 782 * Increment the stat by the given value. This calls the associated 783 * storage object inc function. 784 * @param v The value to add. 785 */ 786 template <typename U> 787 void operator+=(const U &v) { data()->inc(v, params); } 788 789 /** 790 * Decrement the stat by the given value. This calls the associated 791 * storage object dec function. 792 * @param v The value to substract. 793 */ 794 template <typename U> 795 void operator-=(const U &v) { data()->dec(v, params); } 796 797 /** 798 * Return the number of elements, always 1 for a scalar. 799 * @return 1. 800 */ 801 size_t size() const { return 1; } 802 803 bool check() const { return true; } 804 805 /** 806 * Reset stat value to default 807 */ 808 void reset() { data()->reset(); } 809 810 Counter value() { return data()->value(params); } 811 812 Result result() { return data()->result(params); } 813 814 Result total() { return result(); } 815 816 bool zero() { return result() == 0.0; } 817 818}; 819 820class ProxyData : public ScalarData 821{ 822 public: 823 virtual void visit(Visit &visitor) { visitor.visit(*this); } 824 virtual std::string str() const { return to_string(value()); } 825 virtual size_t size() const { return 1; } 826 virtual bool zero() const { return value() == 0; } 827 virtual bool check() const { return true; } 828 virtual void reset() { } 829}; 830 831template <class T> 832class ValueProxy : public ProxyData 833{ 834 private: 835 T *scalar; 836 837 public: 838 ValueProxy(T &val) : scalar(&val) {} 839 virtual Counter value() const { return *scalar; } 840 virtual Result result() const { return *scalar; } 841 virtual Result total() const { return *scalar; } 842}; 843 844template <class T> 845class FunctorProxy : public ProxyData 846{ 847 private: 848 T *functor; 849 850 public: 851 FunctorProxy(T &func) : functor(&func) {} 852 virtual Counter value() const { return (*functor)(); } 853 virtual Result result() const { return (*functor)(); } 854 virtual Result total() const { return (*functor)(); } 855}; 856 857class ValueBase : public DataAccess 858{ 859 private: 860 ProxyData *proxy; 861 862 public: 863 ValueBase() : proxy(NULL) { } 864 ~ValueBase() { if (proxy) delete proxy; } 865 866 template <class T> 867 void scalar(T &value) 868 { 869 proxy = new ValueProxy<T>(value); 870 setInit(); 871 } 872 873 template <class T> 874 void functor(T &func) 875 { 876 proxy = new FunctorProxy<T>(func); 877 setInit(); 878 } 879 880 Counter value() { return proxy->value(); } 881 Result result() const { return proxy->result(); } 882 Result total() const { return proxy->total(); }; 883 size_t size() const { return proxy->size(); } 884 885 std::string str() const { return proxy->str(); } 886 bool zero() const { return proxy->zero(); } 887 bool check() const { return proxy != NULL; } 888 void reset() { } 889}; 890 891////////////////////////////////////////////////////////////////////// 892// 893// Vector Statistics 894// 895////////////////////////////////////////////////////////////////////// 896 897/** 898 * A proxy class to access the stat at a given index in a VectorBase stat. 899 * Behaves like a ScalarBase. 900 */ 901template <class Stat> 902class ScalarProxy 903{ 904 private: 905 /** Pointer to the parent Vector. */ 906 Stat *stat; 907 908 /** The index to access in the parent VectorBase. */ 909 int index; 910 911 public: 912 /** 913 * Return the current value of this stat as its base type. 914 * @return The current value. 915 */ 916 Counter value() const { return stat->data(index)->value(stat->params); } 917 918 /** 919 * Return the current value of this statas a result type. 920 * @return The current value. 921 */ 922 Result result() const { return stat->data(index)->result(stat->params); } 923 924 public: 925 /** 926 * Create and initialize this proxy, do not register it with the database. 927 * @param p The params to use. 928 * @param i The index to access. 929 */ 930 ScalarProxy(Stat *s, int i) 931 : stat(s), index(i) 932 { 933 assert(stat); 934 } 935 936 /** 937 * Create a copy of the provided ScalarProxy. 938 * @param sp The proxy to copy. 939 */ 940 ScalarProxy(const ScalarProxy &sp) 941 : stat(sp.stat), index(sp.index) 942 {} 943 944 /** 945 * Set this proxy equal to the provided one. 946 * @param sp The proxy to copy. 947 * @return A reference to this proxy. 948 */ 949 const ScalarProxy &operator=(const ScalarProxy &sp) { 950 stat = sp.stat; 951 index = sp.index; 952 return *this; 953 } 954 955 public: 956 // Common operators for stats 957 /** 958 * Increment the stat by 1. This calls the associated storage object inc 959 * function. 960 */ 961 void operator++() { stat->data(index)->inc(1, stat->params); } 962 /** 963 * Decrement the stat by 1. This calls the associated storage object dec 964 * function. 965 */ 966 void operator--() { stat->data(index)->dec(1, stat->params); } 967 968 /** Increment the stat by 1. */ 969 void operator++(int) { ++*this; } 970 /** Decrement the stat by 1. */ 971 void operator--(int) { --*this; } 972 973 /** 974 * Set the data value to the given value. This calls the associated storage 975 * object set function. 976 * @param v The new value. 977 */ 978 template <typename U> 979 void operator=(const U &v) { stat->data(index)->set(v, stat->params); } 980 981 /** 982 * Increment the stat by the given value. This calls the associated 983 * storage object inc function. 984 * @param v The value to add. 985 */ 986 template <typename U> 987 void operator+=(const U &v) { stat->data(index)->inc(v, stat->params); } 988 989 /** 990 * Decrement the stat by the given value. This calls the associated 991 * storage object dec function. 992 * @param v The value to substract. 993 */ 994 template <typename U> 995 void operator-=(const U &v) { stat->data(index)->dec(v, stat->params); } 996 997 /** 998 * Return the number of elements, always 1 for a scalar. 999 * @return 1. 1000 */ 1001 size_t size() const { return 1; } 1002 1003 /** 1004 * This stat has no state. Nothing to reset 1005 */ 1006 void reset() { } 1007 1008 public: 1009 std::string 1010 str() const 1011 { 1012 return csprintf("%s[%d]", stat->str(), index); 1013 1014 } 1015}; 1016 1017/** 1018 * Implementation of a vector of stats. The type of stat is determined by the 1019 * Storage class. @sa ScalarBase 1020 */ 1021template <class Stor> 1022class VectorBase : public DataAccess 1023{ 1024 public: 1025 typedef Stor Storage; 1026 1027 /** Define the params of the storage class. */ 1028 typedef typename Storage::Params Params; 1029 1030 /** Proxy type */ 1031 typedef ScalarProxy<VectorBase<Storage> > Proxy; 1032 1033 friend class ScalarProxy<VectorBase<Storage> >; 1034 1035 protected: 1036 /** The storage of this stat. */ 1037 Storage *storage; 1038 size_t _size; 1039 1040 /** The parameters for this stat. */ 1041 Params params; 1042 1043 protected: 1044 /** 1045 * Retrieve the storage. 1046 * @param index The vector index to access. 1047 * @return The storage object at the given index. 1048 */ 1049 Storage *data(int index) { return &storage[index]; } 1050 1051 /** 1052 * Retrieve a const pointer to the storage. 1053 * @param index The vector index to access. 1054 * @return A const pointer to the storage object at the given index. 1055 */ 1056 const Storage *data(int index) const { return &storage[index]; } 1057 1058 void 1059 doInit(int s) 1060 { 1061 assert(s > 0 && "size must be positive!"); 1062 assert(!storage && "already initialized"); 1063 _size = s; 1064 1065 char *ptr = new char[_size * sizeof(Storage)]; 1066 storage = reinterpret_cast<Storage *>(ptr); 1067 1068 for (int i = 0; i < _size; ++i) 1069 new (&storage[i]) Storage(params); 1070 1071 setInit(); 1072 } 1073 1074 public: 1075 void value(VCounter &vec) const 1076 { 1077 vec.resize(size()); 1078 for (int i = 0; i < size(); ++i) 1079 vec[i] = data(i)->value(params); 1080 } 1081 1082 /** 1083 * Copy the values to a local vector and return a reference to it. 1084 * @return A reference to a vector of the stat values. 1085 */ 1086 void result(VResult &vec) const 1087 { 1088 vec.resize(size()); 1089 for (int i = 0; i < size(); ++i) 1090 vec[i] = data(i)->result(params); 1091 } 1092 1093 /** 1094 * Return a total of all entries in this vector. 1095 * @return The total of all vector entries. 1096 */ 1097 Result total() const { 1098 Result total = 0.0; 1099 for (int i = 0; i < size(); ++i) 1100 total += data(i)->result(params); 1101 return total; 1102 } 1103 1104 /** 1105 * @return the number of elements in this vector. 1106 */ 1107 size_t size() const { return _size; } 1108 1109 bool 1110 zero() const 1111 { 1112 for (int i = 0; i < size(); ++i) 1113 if (data(i)->zero()) 1114 return false; 1115 return true; 1116 } 1117 1118 bool 1119 check() const 1120 { 1121 return storage != NULL; 1122 } 1123 1124 void 1125 reset() 1126 { 1127 for (int i = 0; i < size(); ++i) 1128 data(i)->reset(); 1129 } 1130 1131 public: 1132 VectorBase() 1133 : storage(NULL) 1134 {} 1135 1136 ~VectorBase() 1137 { 1138 if (!storage) 1139 return; 1140 1141 for (int i = 0; i < _size; ++i) 1142 data(i)->~Storage(); 1143 delete [] reinterpret_cast<char *>(storage); 1144 } 1145 1146 /** 1147 * Return a reference (ScalarProxy) to the stat at the given index. 1148 * @param index The vector index to access. 1149 * @return A reference of the stat. 1150 */ 1151 Proxy 1152 operator[](int index) 1153 { 1154 assert (index >= 0 && index < size()); 1155 return Proxy(this, index); 1156 } 1157 1158 void update(StatData *data) {} 1159}; 1160 1161template <class Stat> 1162class VectorProxy 1163{ 1164 private: 1165 Stat *stat; 1166 int offset; 1167 int len; 1168 1169 private: 1170 mutable VResult vec; 1171 1172 typename Stat::Storage * 1173 data(int index) 1174 { 1175 assert(index < len); 1176 return stat->data(offset + index); 1177 } 1178 1179 const typename Stat::Storage * 1180 data(int index) const 1181 { 1182 assert(index < len); 1183 return const_cast<Stat *>(stat)->data(offset + index); 1184 } 1185 1186 public: 1187 const VResult & 1188 result() const 1189 { 1190 vec.resize(size()); 1191 1192 for (int i = 0; i < size(); ++i) 1193 vec[i] = data(i)->result(stat->params); 1194 1195 return vec; 1196 } 1197 1198 Result 1199 total() const 1200 { 1201 Result total = 0; 1202 for (int i = 0; i < size(); ++i) 1203 total += data(i)->result(stat->params); 1204 return total; 1205 } 1206 1207 public: 1208 VectorProxy(Stat *s, int o, int l) 1209 : stat(s), offset(o), len(l) 1210 { 1211 } 1212 1213 VectorProxy(const VectorProxy &sp) 1214 : stat(sp.stat), offset(sp.offset), len(sp.len) 1215 { 1216 } 1217 1218 const VectorProxy & 1219 operator=(const VectorProxy &sp) 1220 { 1221 stat = sp.stat; 1222 offset = sp.offset; 1223 len = sp.len; 1224 return *this; 1225 } 1226 1227 ScalarProxy<Stat> operator[](int index) 1228 { 1229 assert (index >= 0 && index < size()); 1230 return ScalarProxy<Stat>(stat, offset + index); 1231 } 1232 1233 size_t size() const { return len; } 1234 1235 /** 1236 * This stat has no state. Nothing to reset. 1237 */ 1238 void reset() { } 1239}; 1240 1241template <class Stor> 1242class Vector2dBase : public DataAccess 1243{ 1244 public: 1245 typedef Stor Storage; 1246 typedef typename Storage::Params Params; 1247 typedef VectorProxy<Vector2dBase<Storage> > Proxy; 1248 friend class ScalarProxy<Vector2dBase<Storage> >; 1249 friend class VectorProxy<Vector2dBase<Storage> >; 1250 1251 protected: 1252 size_t x; 1253 size_t y; 1254 size_t _size; 1255 Storage *storage; 1256 Params params; 1257 1258 protected: 1259 Storage *data(int index) { return &storage[index]; } 1260 const Storage *data(int index) const { return &storage[index]; } 1261 1262 void 1263 doInit(int _x, int _y) 1264 { 1265 assert(_x > 0 && _y > 0 && "sizes must be positive!"); 1266 assert(!storage && "already initialized"); 1267 1268 Vector2dData *statdata = dynamic_cast<Vector2dData *>(find()); 1269 1270 x = _x; 1271 y = _y; 1272 statdata->x = _x; 1273 statdata->y = _y; 1274 _size = x * y; 1275 1276 char *ptr = new char[_size * sizeof(Storage)]; 1277 storage = reinterpret_cast<Storage *>(ptr); 1278 1279 for (int i = 0; i < _size; ++i) 1280 new (&storage[i]) Storage(params); 1281 1282 setInit(); 1283 } 1284 1285 public: 1286 Vector2dBase() 1287 : storage(NULL) 1288 {} 1289 1290 ~Vector2dBase() 1291 { 1292 if (!storage) 1293 return; 1294 1295 for (int i = 0; i < _size; ++i) 1296 data(i)->~Storage(); 1297 delete [] reinterpret_cast<char *>(storage); 1298 } 1299 1300 void 1301 update(Vector2dData *newdata) 1302 { 1303 int size = this->size(); 1304 newdata->cvec.resize(size); 1305 for (int i = 0; i < size; ++i) 1306 newdata->cvec[i] = data(i)->value(params); 1307 } 1308 1309 std::string ysubname(int i) const { return (*this->y_subnames)[i]; } 1310 1311 Proxy 1312 operator[](int index) 1313 { 1314 int offset = index * y; 1315 assert (index >= 0 && offset + index < size()); 1316 return Proxy(this, offset, y); 1317 } 1318 1319 1320 size_t 1321 size() const 1322 { 1323 return _size; 1324 } 1325 1326 bool 1327 zero() const 1328 { 1329 return data(0)->zero(); 1330#if 0 1331 for (int i = 0; i < size(); ++i) 1332 if (!data(i)->zero()) 1333 return false; 1334 return true; 1335#endif 1336 } 1337 1338 /** 1339 * Reset stat value to default 1340 */ 1341 void 1342 reset() 1343 { 1344 for (int i = 0; i < size(); ++i) 1345 data(i)->reset(); 1346 } 1347 1348 bool 1349 check() 1350 { 1351 return storage != NULL; 1352 } 1353}; 1354 1355////////////////////////////////////////////////////////////////////// 1356// 1357// Non formula statistics 1358// 1359////////////////////////////////////////////////////////////////////// 1360 1361/** 1362 * Templatized storage and interface for a distrbution stat. 1363 */ 1364struct DistStor 1365{ 1366 public: 1367 /** The parameters for a distribution stat. */ 1368 struct Params 1369 { 1370 /** The minimum value to track. */ 1371 Counter min; 1372 /** The maximum value to track. */ 1373 Counter max; 1374 /** The number of entries in each bucket. */ 1375 Counter bucket_size; 1376 /** The number of buckets. Equal to (max-min)/bucket_size. */ 1377 int size; 1378 }; 1379 enum { fancy = false }; 1380 1381 private: 1382 /** The smallest value sampled. */ 1383 Counter min_val; 1384 /** The largest value sampled. */ 1385 Counter max_val; 1386 /** The number of values sampled less than min. */ 1387 Counter underflow; 1388 /** The number of values sampled more than max. */ 1389 Counter overflow; 1390 /** The current sum. */ 1391 Counter sum; 1392 /** The sum of squares. */ 1393 Counter squares; 1394 /** The number of samples. */ 1395 Counter samples; 1396 /** Counter for each bucket. */ 1397 VCounter cvec; 1398 1399 public: 1400 DistStor(const Params ¶ms) 1401 : cvec(params.size) 1402 { 1403 reset(); 1404 } 1405 1406 /** 1407 * Add a value to the distribution for the given number of times. 1408 * @param val The value to add. 1409 * @param number The number of times to add the value. 1410 * @param params The paramters of the distribution. 1411 */ 1412 void sample(Counter val, int number, const Params ¶ms) 1413 { 1414 if (val < params.min) 1415 underflow += number; 1416 else if (val > params.max) 1417 overflow += number; 1418 else { 1419 int index = (int)std::floor((val - params.min) / params.bucket_size); 1420 assert(index < size(params)); 1421 cvec[index] += number; 1422 } 1423 1424 if (val < min_val) 1425 min_val = val; 1426 1427 if (val > max_val) 1428 max_val = val; 1429 1430 Counter sample = val * number; 1431 sum += sample; 1432 squares += sample * sample; 1433 samples += number; 1434 } 1435 1436 /** 1437 * Return the number of buckets in this distribution. 1438 * @return the number of buckets. 1439 * @todo Is it faster to return the size from the parameters? 1440 */ 1441 size_t size(const Params &) const { return cvec.size(); } 1442 1443 /** 1444 * Returns true if any calls to sample have been made. 1445 * @param params The paramters of the distribution. 1446 * @return True if any values have been sampled. 1447 */ 1448 bool zero(const Params ¶ms) const 1449 { 1450 return samples == Counter(); 1451 } 1452 1453 void update(DistDataData *data, const Params ¶ms) 1454 { 1455 data->min = params.min; 1456 data->max = params.max; 1457 data->bucket_size = params.bucket_size; 1458 data->size = params.size; 1459 1460 data->min_val = (min_val == CounterLimits::max()) ? 0 : min_val; 1461 data->max_val = (max_val == CounterLimits::min()) ? 0 : max_val; 1462 data->underflow = underflow; 1463 data->overflow = overflow; 1464 data->cvec.resize(params.size); 1465 for (int i = 0; i < params.size; ++i) 1466 data->cvec[i] = cvec[i]; 1467 1468 data->sum = sum; 1469 data->squares = squares; 1470 data->samples = samples; 1471 } 1472 1473 /** 1474 * Reset stat value to default 1475 */ 1476 void reset() 1477 { 1478 min_val = CounterLimits::max(); 1479 max_val = CounterLimits::min(); 1480 underflow = 0; 1481 overflow = 0; 1482 1483 int size = cvec.size(); 1484 for (int i = 0; i < size; ++i) 1485 cvec[i] = Counter(); 1486 1487 sum = Counter(); 1488 squares = Counter(); 1489 samples = Counter(); 1490 } 1491}; 1492 1493/** 1494 * Templatized storage and interface for a distribution that calculates mean 1495 * and variance. 1496 */ 1497struct FancyStor 1498{ 1499 public: 1500 /** 1501 * No paramters for this storage. 1502 */ 1503 struct Params {}; 1504 enum { fancy = true }; 1505 1506 private: 1507 /** The current sum. */ 1508 Counter sum; 1509 /** The sum of squares. */ 1510 Counter squares; 1511 /** The number of samples. */ 1512 Counter samples; 1513 1514 public: 1515 /** 1516 * Create and initialize this storage. 1517 */ 1518 FancyStor(const Params &) 1519 : sum(Counter()), squares(Counter()), samples(Counter()) 1520 { } 1521 1522 /** 1523 * Add a value the given number of times to this running average. 1524 * Update the running sum and sum of squares, increment the number of 1525 * values seen by the given number. 1526 * @param val The value to add. 1527 * @param number The number of times to add the value. 1528 * @param p The parameters of this stat. 1529 */ 1530 void sample(Counter val, int number, const Params &p) 1531 { 1532 Counter value = val * number; 1533 sum += value; 1534 squares += value * value; 1535 samples += number; 1536 } 1537 1538 void update(DistDataData *data, const Params ¶ms) 1539 { 1540 data->sum = sum; 1541 data->squares = squares; 1542 data->samples = samples; 1543 } 1544 1545 /** 1546 * Return the number of entries in this stat, 1 1547 * @return 1. 1548 */ 1549 size_t size(const Params &) const { return 1; } 1550 1551 /** 1552 * Return true if no samples have been added. 1553 * @return True if no samples have been added. 1554 */ 1555 bool zero(const Params &) const { return samples == Counter(); } 1556 1557 /** 1558 * Reset stat value to default 1559 */ 1560 void reset() 1561 { 1562 sum = Counter(); 1563 squares = Counter(); 1564 samples = Counter(); 1565 } 1566}; 1567 1568/** 1569 * Templatized storage for distribution that calculates per tick mean and 1570 * variance. 1571 */ 1572struct AvgFancy 1573{ 1574 public: 1575 /** No parameters for this storage. */ 1576 struct Params {}; 1577 enum { fancy = true }; 1578 1579 private: 1580 /** Current total. */ 1581 Counter sum; 1582 /** Current sum of squares. */ 1583 Counter squares; 1584 1585 public: 1586 /** 1587 * Create and initialize this storage. 1588 */ 1589 AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {} 1590 1591 /** 1592 * Add a value to the distribution for the given number of times. 1593 * Update the running sum and sum of squares. 1594 * @param val The value to add. 1595 * @param number The number of times to add the value. 1596 * @param p The paramters of the distribution. 1597 */ 1598 void sample(Counter val, int number, const Params &p) 1599 { 1600 Counter value = val * number; 1601 sum += value; 1602 squares += value * value; 1603 } 1604 1605 void update(DistDataData *data, const Params ¶ms) 1606 { 1607 data->sum = sum; 1608 data->squares = squares; 1609 data->samples = curTick; 1610 } 1611 1612 /** 1613 * Return the number of entries, in this case 1. 1614 * @return 1. 1615 */ 1616 size_t size(const Params ¶ms) const { return 1; } 1617 /** 1618 * Return true if no samples have been added. 1619 * @return True if the sum is zero. 1620 */ 1621 bool zero(const Params ¶ms) const { return sum == Counter(); } 1622 /** 1623 * Reset stat value to default 1624 */ 1625 void reset() 1626 { 1627 sum = Counter(); 1628 squares = Counter(); 1629 } 1630}; 1631 1632/** 1633 * Implementation of a distribution stat. The type of distribution is 1634 * determined by the Storage template. @sa ScalarBase 1635 */ 1636template <class Stor> 1637class DistBase : public DataAccess 1638{ 1639 public: 1640 typedef Stor Storage; 1641 /** Define the params of the storage class. */ 1642 typedef typename Storage::Params Params; 1643 1644 protected: 1645 /** The storage for this stat. */ 1646 char storage[sizeof(Storage)] __attribute__ ((aligned (8))); 1647 1648 /** The parameters for this stat. */ 1649 Params params; 1650 1651 protected: 1652 /** 1653 * Retrieve the storage. 1654 * @return The storage object for this stat. 1655 */ 1656 Storage *data() 1657 { 1658 return reinterpret_cast<Storage *>(storage); 1659 } 1660 1661 /** 1662 * Retrieve a const pointer to the storage. 1663 * @return A const pointer to the storage object for this stat. 1664 */ 1665 const Storage * 1666 data() const 1667 { 1668 return reinterpret_cast<const Storage *>(storage); 1669 } 1670 1671 void 1672 doInit() 1673 { 1674 new (storage) Storage(params); 1675 setInit(); 1676 } 1677 1678 public: 1679 DistBase() { } 1680 1681 /** 1682 * Add a value to the distribtion n times. Calls sample on the storage 1683 * class. 1684 * @param v The value to add. 1685 * @param n The number of times to add it, defaults to 1. 1686 */ 1687 template <typename U> 1688 void sample(const U &v, int n = 1) { data()->sample(v, n, params); } 1689 1690 /** 1691 * Return the number of entries in this stat. 1692 * @return The number of entries. 1693 */ 1694 size_t size() const { return data()->size(params); } 1695 /** 1696 * Return true if no samples have been added. 1697 * @return True if there haven't been any samples. 1698 */ 1699 bool zero() const { return data()->zero(params); } 1700 1701 void update(DistData *base) 1702 { 1703 base->data.fancy = Storage::fancy; 1704 data()->update(&(base->data), params); 1705 } 1706 1707 /** 1708 * Reset stat value to default 1709 */ 1710 void 1711 reset() 1712 { 1713 data()->reset(); 1714 } 1715 1716 bool 1717 check() 1718 { 1719 return true; 1720 } 1721}; 1722 1723template <class Stat> 1724class DistProxy; 1725 1726template <class Stor> 1727class VectorDistBase : public DataAccess 1728{ 1729 public: 1730 typedef Stor Storage; 1731 typedef typename Storage::Params Params; 1732 typedef DistProxy<VectorDistBase<Storage> > Proxy; 1733 friend class DistProxy<VectorDistBase<Storage> >; 1734 1735 protected: 1736 Storage *storage; 1737 size_t _size; 1738 Params params; 1739 1740 protected: 1741 Storage * 1742 data(int index) 1743 { 1744 return &storage[index]; 1745 } 1746 1747 const Storage * 1748 data(int index) const 1749 { 1750 return &storage[index]; 1751 } 1752 1753 void 1754 doInit(int s) 1755 { 1756 assert(s > 0 && "size must be positive!"); 1757 assert(!storage && "already initialized"); 1758 _size = s; 1759 1760 char *ptr = new char[_size * sizeof(Storage)]; 1761 storage = reinterpret_cast<Storage *>(ptr); 1762 1763 for (int i = 0; i < _size; ++i) 1764 new (&storage[i]) Storage(params); 1765 1766 setInit(); 1767 } 1768 1769 public: 1770 VectorDistBase() 1771 : storage(NULL) 1772 {} 1773 1774 ~VectorDistBase() 1775 { 1776 if (!storage) 1777 return ; 1778 1779 for (int i = 0; i < _size; ++i) 1780 data(i)->~Storage(); 1781 delete [] reinterpret_cast<char *>(storage); 1782 } 1783 1784 Proxy operator[](int index); 1785 1786 size_t 1787 size() const 1788 { 1789 return _size; 1790 } 1791 1792 bool 1793 zero() const 1794 { 1795 return false; 1796#if 0 1797 for (int i = 0; i < size(); ++i) 1798 if (!data(i)->zero(params)) 1799 return false; 1800 return true; 1801#endif 1802 } 1803 1804 /** 1805 * Reset stat value to default 1806 */ 1807 void 1808 reset() 1809 { 1810 for (int i = 0; i < size(); ++i) 1811 data(i)->reset(); 1812 } 1813 1814 bool 1815 check() 1816 { 1817 return storage != NULL; 1818 } 1819 1820 void 1821 update(VectorDistData *base) 1822 { 1823 int size = this->size(); 1824 base->data.resize(size); 1825 for (int i = 0; i < size; ++i) { 1826 base->data[i].fancy = Storage::fancy; 1827 data(i)->update(&(base->data[i]), params); 1828 } 1829 } 1830}; 1831 1832template <class Stat> 1833class DistProxy 1834{ 1835 private: 1836 Stat *stat; 1837 int index; 1838 1839 protected: 1840 typename Stat::Storage *data() { return stat->data(index); } 1841 const typename Stat::Storage *data() const { return stat->data(index); } 1842 1843 public: 1844 DistProxy(Stat *s, int i) 1845 : stat(s), index(i) 1846 {} 1847 1848 DistProxy(const DistProxy &sp) 1849 : stat(sp.stat), index(sp.index) 1850 {} 1851 1852 const DistProxy &operator=(const DistProxy &sp) 1853 { 1854 stat = sp.stat; 1855 index = sp.index; 1856 return *this; 1857 } 1858 1859 public: 1860 template <typename U> 1861 void 1862 sample(const U &v, int n = 1) 1863 { 1864 data()->sample(v, n, stat->params); 1865 } 1866 1867 size_t 1868 size() const 1869 { 1870 return 1; 1871 } 1872 1873 bool 1874 zero() const 1875 { 1876 return data()->zero(stat->params); 1877 } 1878 1879 /** 1880 * Proxy has no state. Nothing to reset. 1881 */ 1882 void reset() { } 1883}; 1884 1885template <class Storage> 1886inline typename VectorDistBase<Storage>::Proxy 1887VectorDistBase<Storage>::operator[](int index) 1888{ 1889 assert (index >= 0 && index < size()); 1890 return typename VectorDistBase<Storage>::Proxy(this, index); 1891} 1892 1893#if 0 1894template <class Storage> 1895Result 1896VectorDistBase<Storage>::total(int index) const 1897{ 1898 int total = 0; 1899 for (int i = 0; i < x_size(); ++i) { 1900 total += data(i)->result(stat->params); 1901 } 1902} 1903#endif 1904 1905////////////////////////////////////////////////////////////////////// 1906// 1907// Formula Details 1908// 1909////////////////////////////////////////////////////////////////////// 1910 1911/** 1912 * Base class for formula statistic node. These nodes are used to build a tree 1913 * that represents the formula. 1914 */ 1915class Node : public RefCounted 1916{ 1917 public: 1918 /** 1919 * Return the number of nodes in the subtree starting at this node. 1920 * @return the number of nodes in this subtree. 1921 */ 1922 virtual size_t size() const = 0; 1923 /** 1924 * Return the result vector of this subtree. 1925 * @return The result vector of this subtree. 1926 */ 1927 virtual const VResult &result() const = 0; 1928 /** 1929 * Return the total of the result vector. 1930 * @return The total of the result vector. 1931 */ 1932 virtual Result total() const = 0; 1933 1934 /** 1935 * 1936 */ 1937 virtual std::string str() const = 0; 1938}; 1939 1940/** Reference counting pointer to a function Node. */ 1941typedef RefCountingPtr<Node> NodePtr; 1942 1943class ScalarStatNode : public Node 1944{ 1945 private: 1946 const ScalarData *data; 1947 mutable VResult vresult; 1948 1949 public: 1950 ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {} 1951 virtual const VResult &result() const 1952 { 1953 vresult[0] = data->result(); 1954 return vresult; 1955 } 1956 virtual Result total() const { return data->result(); }; 1957 1958 virtual size_t size() const { return 1; } 1959 1960 /** 1961 * 1962 */ 1963 virtual std::string str() const { return data->name; } 1964}; 1965 1966template <class Stat> 1967class ScalarProxyNode : public Node 1968{ 1969 private: 1970 const ScalarProxy<Stat> proxy; 1971 mutable VResult vresult; 1972 1973 public: 1974 ScalarProxyNode(const ScalarProxy<Stat> &p) 1975 : proxy(p), vresult(1) 1976 { } 1977 1978 virtual const VResult & 1979 result() const 1980 { 1981 vresult[0] = proxy.result(); 1982 return vresult; 1983 } 1984 1985 virtual Result 1986 total() const 1987 { 1988 return proxy.result(); 1989 } 1990 1991 virtual size_t 1992 size() const 1993 { 1994 return 1; 1995 } 1996 1997 /** 1998 * 1999 */ 2000 virtual std::string 2001 str() const 2002 { 2003 return proxy.str(); 2004 } 2005}; 2006 2007class VectorStatNode : public Node 2008{ 2009 private: 2010 const VectorData *data; 2011 2012 public: 2013 VectorStatNode(const VectorData *d) : data(d) { } 2014 virtual const VResult &result() const { return data->result(); } 2015 virtual Result total() const { return data->total(); }; 2016 2017 virtual size_t size() const { return data->size(); } 2018 2019 virtual std::string str() const { return data->name; } 2020}; 2021 2022template <class T> 2023class ConstNode : public Node 2024{ 2025 private: 2026 VResult vresult; 2027 2028 public: 2029 ConstNode(T s) : vresult(1, (Result)s) {} 2030 const VResult &result() const { return vresult; } 2031 virtual Result total() const { return vresult[0]; }; 2032 virtual size_t size() const { return 1; } 2033 virtual std::string str() const { return to_string(vresult[0]); } 2034}; 2035 2036template <class T> 2037class ConstVectorNode : public Node 2038{ 2039 private: 2040 VResult vresult; 2041 2042 public: 2043 ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {} 2044 const VResult &result() const { return vresult; } 2045 virtual Result total() const 2046 { 2047 int size = this->size(); 2048 Result tmp = 0; 2049 for (int i = 0; i < size; i++) 2050 { 2051 tmp += vresult[i]; 2052 } 2053 return tmp; 2054 } 2055 virtual size_t size() const { return vresult.size(); } 2056 virtual std::string str() const 2057 { 2058 int size = this->size(); 2059 std::string tmp = "("; 2060 for (int i = 0; i < size; i++) 2061 { 2062 tmp += csprintf("%s ",to_string(vresult[i])); 2063 } 2064 tmp += ")"; 2065 return tmp; 2066 } 2067}; 2068 2069template <class Op> 2070struct OpString; 2071 2072template<> 2073struct OpString<std::plus<Result> > 2074{ 2075 static std::string str() { return "+"; } 2076}; 2077 2078template<> 2079struct OpString<std::minus<Result> > 2080{ 2081 static std::string str() { return "-"; } 2082}; 2083 2084template<> 2085struct OpString<std::multiplies<Result> > 2086{ 2087 static std::string str() { return "*"; } 2088}; 2089 2090template<> 2091struct OpString<std::divides<Result> > 2092{ 2093 static std::string str() { return "/"; } 2094}; 2095 2096template<> 2097struct OpString<std::modulus<Result> > 2098{ 2099 static std::string str() { return "%"; } 2100}; 2101 2102template<> 2103struct OpString<std::negate<Result> > 2104{ 2105 static std::string str() { return "-"; } 2106}; 2107 2108template <class Op> 2109class UnaryNode : public Node 2110{ 2111 public: 2112 NodePtr l; 2113 mutable VResult vresult; 2114 2115 public: 2116 UnaryNode(NodePtr &p) : l(p) {} 2117 2118 const VResult &result() const 2119 { 2120 const VResult &lvec = l->result(); 2121 int size = lvec.size(); 2122 2123 assert(size > 0); 2124 2125 vresult.resize(size); 2126 Op op; 2127 for (int i = 0; i < size; ++i) 2128 vresult[i] = op(lvec[i]); 2129 2130 return vresult; 2131 } 2132 2133 Result total() const 2134 { 2135 const VResult &vec = this->result(); 2136 Result total = 0; 2137 for (int i = 0; i < size(); i++) 2138 total += vec[i]; 2139 return total; 2140 } 2141 2142 virtual size_t size() const { return l->size(); } 2143 2144 virtual std::string str() const 2145 { 2146 return OpString<Op>::str() + l->str(); 2147 } 2148}; 2149 2150template <class Op> 2151class BinaryNode : public Node 2152{ 2153 public: 2154 NodePtr l; 2155 NodePtr r; 2156 mutable VResult vresult; 2157 2158 public: 2159 BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {} 2160 2161 const VResult &result() const 2162 { 2163 Op op; 2164 const VResult &lvec = l->result(); 2165 const VResult &rvec = r->result(); 2166 2167 assert(lvec.size() > 0 && rvec.size() > 0); 2168 2169 if (lvec.size() == 1 && rvec.size() == 1) { 2170 vresult.resize(1); 2171 vresult[0] = op(lvec[0], rvec[0]); 2172 } else if (lvec.size() == 1) { 2173 int size = rvec.size(); 2174 vresult.resize(size); 2175 for (int i = 0; i < size; ++i) 2176 vresult[i] = op(lvec[0], rvec[i]); 2177 } else if (rvec.size() == 1) { 2178 int size = lvec.size(); 2179 vresult.resize(size); 2180 for (int i = 0; i < size; ++i) 2181 vresult[i] = op(lvec[i], rvec[0]); 2182 } else if (rvec.size() == lvec.size()) { 2183 int size = rvec.size(); 2184 vresult.resize(size); 2185 for (int i = 0; i < size; ++i) 2186 vresult[i] = op(lvec[i], rvec[i]); 2187 } 2188 2189 return vresult; 2190 } 2191 2192 Result total() const 2193 { 2194 const VResult &vec = this->result(); 2195 Result total = 0; 2196 for (int i = 0; i < size(); i++) 2197 total += vec[i]; 2198 return total; 2199 } 2200 2201 virtual size_t size() const { 2202 int ls = l->size(); 2203 int rs = r->size(); 2204 if (ls == 1) 2205 return rs; 2206 else if (rs == 1) 2207 return ls; 2208 else { 2209 assert(ls == rs && "Node vector sizes are not equal"); 2210 return ls; 2211 } 2212 } 2213 2214 virtual std::string str() const 2215 { 2216 return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str()); 2217 } 2218}; 2219 2220template <class Op> 2221class SumNode : public Node 2222{ 2223 public: 2224 NodePtr l; 2225 mutable VResult vresult; 2226 2227 public: 2228 SumNode(NodePtr &p) : l(p), vresult(1) {} 2229 2230 const VResult &result() const 2231 { 2232 const VResult &lvec = l->result(); 2233 int size = lvec.size(); 2234 assert(size > 0); 2235 2236 vresult[0] = 0.0; 2237 2238 Op op; 2239 for (int i = 0; i < size; ++i) 2240 vresult[0] = op(vresult[0], lvec[i]); 2241 2242 return vresult; 2243 } 2244 2245 Result total() const 2246 { 2247 const VResult &lvec = l->result(); 2248 int size = lvec.size(); 2249 assert(size > 0); 2250 2251 Result vresult = 0.0; 2252 2253 Op op; 2254 for (int i = 0; i < size; ++i) 2255 vresult = op(vresult, lvec[i]); 2256 2257 return vresult; 2258 } 2259 2260 virtual size_t size() const { return 1; } 2261 2262 virtual std::string str() const 2263 { 2264 return csprintf("total(%s)", l->str()); 2265 } 2266}; 2267 2268 2269////////////////////////////////////////////////////////////////////// 2270// 2271// Visible Statistics Types 2272// 2273////////////////////////////////////////////////////////////////////// 2274/** 2275 * @defgroup VisibleStats "Statistic Types" 2276 * These are the statistics that are used in the simulator. 2277 * @{ 2278 */ 2279 2280/** 2281 * This is a simple scalar statistic, like a counter. 2282 * @sa Stat, ScalarBase, StatStor 2283 */ 2284template<int N = 0> 2285class Scalar : public Wrap<Scalar<N>, ScalarBase<StatStor>, ScalarStatData> 2286{ 2287 public: 2288 /** The base implementation. */ 2289 typedef ScalarBase<StatStor> Base; 2290 2291 Scalar() 2292 { 2293 this->doInit(); 2294 } 2295 2296 /** 2297 * Sets the stat equal to the given value. Calls the base implementation 2298 * of operator= 2299 * @param v The new value. 2300 */ 2301 template <typename U> 2302 void operator=(const U &v) { Base::operator=(v); } 2303}; 2304 2305class Value : public Wrap<Value, ValueBase, ScalarStatData> 2306{ 2307 public: 2308 /** The base implementation. */ 2309 typedef ValueBase Base; 2310 2311 template <class T> 2312 Value &scalar(T &value) 2313 { 2314 Base::scalar(value); 2315 return *this; 2316 } 2317 2318 template <class T> 2319 Value &functor(T &func) 2320 { 2321 Base::functor(func); 2322 return *this; 2323 } 2324}; 2325 2326/** 2327 * A stat that calculates the per tick average of a value. 2328 * @sa Stat, ScalarBase, AvgStor 2329 */ 2330template<int N = 0> 2331class Average : public Wrap<Average<N>, ScalarBase<AvgStor>, ScalarStatData> 2332{ 2333 public: 2334 /** The base implementation. */ 2335 typedef ScalarBase<AvgStor> Base; 2336 2337 Average() 2338 { 2339 this->doInit(); 2340 } 2341 2342 /** 2343 * Sets the stat equal to the given value. Calls the base implementation 2344 * of operator= 2345 * @param v The new value. 2346 */ 2347 template <typename U> 2348 void operator=(const U &v) { Base::operator=(v); } 2349}; 2350 2351/** 2352 * A vector of scalar stats. 2353 * @sa Stat, VectorBase, StatStor 2354 */ 2355template<int N = 0> 2356class Vector : public WrapVec<Vector<N>, VectorBase<StatStor>, VectorStatData> 2357{ 2358 public: 2359 /** The base implementation. */ 2360 typedef ScalarBase<StatStor> Base; 2361 2362 /** 2363 * Set this vector to have the given size. 2364 * @param size The new size. 2365 * @return A reference to this stat. 2366 */ 2367 Vector &init(size_t size) { 2368 this->doInit(size); 2369 return *this; 2370 } 2371}; 2372 2373/** 2374 * A vector of Average stats. 2375 * @sa Stat, VectorBase, AvgStor 2376 */ 2377template<int N = 0> 2378class AverageVector 2379 : public WrapVec<AverageVector<N>, VectorBase<AvgStor>, VectorStatData> 2380{ 2381 public: 2382 /** 2383 * Set this vector to have the given size. 2384 * @param size The new size. 2385 * @return A reference to this stat. 2386 */ 2387 AverageVector &init(size_t size) { 2388 this->doInit(size); 2389 return *this; 2390 } 2391}; 2392 2393/** 2394 * A 2-Dimensional vecto of scalar stats. 2395 * @sa Stat, Vector2dBase, StatStor 2396 */ 2397template<int N = 0> 2398class Vector2d 2399 : public WrapVec2d<Vector2d<N>, Vector2dBase<StatStor>, Vector2dStatData> 2400{ 2401 public: 2402 Vector2d &init(size_t x, size_t y) { 2403 this->doInit(x, y); 2404 return *this; 2405 } 2406}; 2407 2408/** 2409 * A simple distribution stat. 2410 * @sa Stat, DistBase, DistStor 2411 */ 2412template<int N = 0> 2413class Distribution 2414 : public Wrap<Distribution<N>, DistBase<DistStor>, DistStatData> 2415{ 2416 public: 2417 /** Base implementation. */ 2418 typedef DistBase<DistStor> Base; 2419 /** The Parameter type. */ 2420 typedef DistStor::Params Params; 2421 2422 public: 2423 /** 2424 * Set the parameters of this distribution. @sa DistStor::Params 2425 * @param min The minimum value of the distribution. 2426 * @param max The maximum value of the distribution. 2427 * @param bkt The number of values in each bucket. 2428 * @return A reference to this distribution. 2429 */ 2430 Distribution &init(Counter min, Counter max, Counter bkt) { 2431 this->params.min = min; 2432 this->params.max = max; 2433 this->params.bucket_size = bkt; 2434 this->params.size = (int)rint((max - min) / bkt + 1.0); 2435 this->doInit(); 2436 return *this; 2437 } 2438}; 2439 2440/** 2441 * Calculates the mean and variance of all the samples. 2442 * @sa Stat, DistBase, FancyStor 2443 */ 2444template<int N = 0> 2445class StandardDeviation 2446 : public Wrap<StandardDeviation<N>, DistBase<FancyStor>, DistStatData> 2447{ 2448 public: 2449 /** The base implementation */ 2450 typedef DistBase<DistStor> Base; 2451 /** The parameter type. */ 2452 typedef DistStor::Params Params; 2453 2454 public: 2455 /** 2456 * Construct and initialize this distribution. 2457 */ 2458 StandardDeviation() { 2459 this->doInit(); 2460 } 2461}; 2462 2463/** 2464 * Calculates the per tick mean and variance of the samples. 2465 * @sa Stat, DistBase, AvgFancy 2466 */ 2467template<int N = 0> 2468class AverageDeviation 2469 : public Wrap<AverageDeviation<N>, DistBase<AvgFancy>, DistStatData> 2470{ 2471 public: 2472 /** The base implementation */ 2473 typedef DistBase<DistStor> Base; 2474 /** The parameter type. */ 2475 typedef DistStor::Params Params; 2476 2477 public: 2478 /** 2479 * Construct and initialize this distribution. 2480 */ 2481 AverageDeviation() 2482 { 2483 this->doInit(); 2484 } 2485}; 2486 2487/** 2488 * A vector of distributions. 2489 * @sa Stat, VectorDistBase, DistStor 2490 */ 2491template<int N = 0> 2492class VectorDistribution 2493 : public WrapVec<VectorDistribution<N>, 2494 VectorDistBase<DistStor>, 2495 VectorDistStatData> 2496{ 2497 public: 2498 /** The base implementation */ 2499 typedef VectorDistBase<DistStor> Base; 2500 /** The parameter type. */ 2501 typedef DistStor::Params Params; 2502 2503 public: 2504 /** 2505 * Initialize storage and parameters for this distribution. 2506 * @param size The size of the vector (the number of distributions). 2507 * @param min The minimum value of the distribution. 2508 * @param max The maximum value of the distribution. 2509 * @param bkt The number of values in each bucket. 2510 * @return A reference to this distribution. 2511 */ 2512 VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) { 2513 this->params.min = min; 2514 this->params.max = max; 2515 this->params.bucket_size = bkt; 2516 this->params.size = (int)rint((max - min) / bkt + 1.0); 2517 this->doInit(size); 2518 return *this; 2519 } 2520}; 2521 2522/** 2523 * This is a vector of StandardDeviation stats. 2524 * @sa Stat, VectorDistBase, FancyStor 2525 */ 2526template<int N = 0> 2527class VectorStandardDeviation 2528 : public WrapVec<VectorStandardDeviation<N>, 2529 VectorDistBase<FancyStor>, 2530 VectorDistStatData> 2531{ 2532 public: 2533 /** The base implementation */ 2534 typedef VectorDistBase<FancyStor> Base; 2535 /** The parameter type. */ 2536 typedef DistStor::Params Params; 2537 2538 public: 2539 /** 2540 * Initialize storage for this distribution. 2541 * @param size The size of the vector. 2542 * @return A reference to this distribution. 2543 */ 2544 VectorStandardDeviation &init(int size) { 2545 this->doInit(size); 2546 return *this; 2547 } 2548}; 2549 2550/** 2551 * This is a vector of AverageDeviation stats. 2552 * @sa Stat, VectorDistBase, AvgFancy 2553 */ 2554template<int N = 0> 2555class VectorAverageDeviation 2556 : public WrapVec<VectorAverageDeviation<N>, 2557 VectorDistBase<AvgFancy>, 2558 VectorDistStatData> 2559{ 2560 public: 2561 /** The base implementation */ 2562 typedef VectorDistBase<AvgFancy> Base; 2563 /** The parameter type. */ 2564 typedef DistStor::Params Params; 2565 2566 public: 2567 /** 2568 * Initialize storage for this distribution. 2569 * @param size The size of the vector. 2570 * @return A reference to this distribution. 2571 */ 2572 VectorAverageDeviation &init(int size) { 2573 this->doInit(size); 2574 return *this; 2575 } 2576}; 2577 2578/** 2579 * A formula for statistics that is calculated when printed. A formula is 2580 * stored as a tree of Nodes that represent the equation to calculate. 2581 * @sa Stat, ScalarStat, VectorStat, Node, Temp 2582 */ 2583class FormulaBase : public DataAccess 2584{ 2585 protected: 2586 /** The root of the tree which represents the Formula */ 2587 NodePtr root; 2588 friend class Temp; 2589 2590 public: 2591 /** 2592 * Return the result of the Fomula in a vector. If there were no Vector 2593 * components to the Formula, then the vector is size 1. If there were, 2594 * like x/y with x being a vector of size 3, then the result returned will 2595 * be x[0]/y, x[1]/y, x[2]/y, respectively. 2596 * @return The result vector. 2597 */ 2598 void result(VResult &vec) const; 2599 2600 /** 2601 * Return the total Formula result. If there is a Vector 2602 * component to this Formula, then this is the result of the 2603 * Formula if the formula is applied after summing all the 2604 * components of the Vector. For example, if Formula is x/y where 2605 * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If 2606 * there is no Vector component, total() returns the same value as 2607 * the first entry in the VResult val() returns. 2608 * @return The total of the result vector. 2609 */ 2610 Result total() const; 2611 2612 /** 2613 * Return the number of elements in the tree. 2614 */ 2615 size_t size() const; 2616 2617 bool check() const { return true; } 2618 2619 /** 2620 * Formulas don't need to be reset 2621 */ 2622 void reset(); 2623 2624 /** 2625 * 2626 */ 2627 bool zero() const; 2628 2629 /** 2630 * 2631 */ 2632 void update(StatData *); 2633 2634 std::string str() const; 2635}; 2636 2637class FormulaData : public VectorData 2638{ 2639 public: 2640 virtual std::string str() const = 0; 2641 virtual bool check() const { return true; } 2642}; 2643 2644template <class Stat> 2645class FormulaStatData : public FormulaData 2646{ 2647 protected: 2648 Stat &s; 2649 mutable VResult vec; 2650 mutable VCounter cvec; 2651 2652 public: 2653 FormulaStatData(Stat &stat) : s(stat) {} 2654 2655 virtual bool zero() const { return s.zero(); } 2656 virtual void reset() { s.reset(); } 2657 2658 virtual size_t size() const { return s.size(); } 2659 virtual const VResult &result() const 2660 { 2661 s.result(vec); 2662 return vec; 2663 } 2664 virtual Result total() const { return s.total(); } 2665 virtual VCounter &value() const { return cvec; } 2666 virtual void visit(Visit &visitor) 2667 { 2668 update(); 2669 s.update(this); 2670 visitor.visit(*this); 2671 } 2672 virtual std::string str() const { return s.str(); } 2673}; 2674 2675class Temp; 2676class Formula 2677 : public WrapVec<Formula, 2678 FormulaBase, 2679 FormulaStatData> 2680{ 2681 public: 2682 /** 2683 * Create and initialize thie formula, and register it with the database. 2684 */ 2685 Formula(); 2686 2687 /** 2688 * Create a formula with the given root node, register it with the 2689 * database. 2690 * @param r The root of the expression tree. 2691 */ 2692 Formula(Temp r); 2693 2694 /** 2695 * Set an unitialized Formula to the given root. 2696 * @param r The root of the expression tree. 2697 * @return a reference to this formula. 2698 */ 2699 const Formula &operator=(Temp r); 2700 2701 /** 2702 * Add the given tree to the existing one. 2703 * @param r The root of the expression tree. 2704 * @return a reference to this formula. 2705 */ 2706 const Formula &operator+=(Temp r); 2707}; 2708 2709class FormulaNode : public Node 2710{ 2711 private: 2712 const Formula &formula; 2713 mutable VResult vec; 2714 2715 public: 2716 FormulaNode(const Formula &f) : formula(f) {} 2717 2718 virtual size_t size() const { return formula.size(); } 2719 virtual const VResult &result() const { formula.result(vec); return vec; } 2720 virtual Result total() const { return formula.total(); } 2721 2722 virtual std::string str() const { return formula.str(); } 2723}; 2724 2725/** 2726 * Helper class to construct formula node trees. 2727 */ 2728class Temp 2729{ 2730 protected: 2731 /** 2732 * Pointer to a Node object. 2733 */ 2734 NodePtr node; 2735 2736 public: 2737 /** 2738 * Copy the given pointer to this class. 2739 * @param n A pointer to a Node object to copy. 2740 */ 2741 Temp(NodePtr n) : node(n) { } 2742 2743 /** 2744 * Return the node pointer. 2745 * @return the node pointer. 2746 */ 2747 operator NodePtr&() { return node;} 2748 2749 public: 2750 /** 2751 * Create a new ScalarStatNode. 2752 * @param s The ScalarStat to place in a node. 2753 */ 2754 template <int N> 2755 Temp(const Scalar<N> &s) 2756 : node(new ScalarStatNode(s.statData())) { } 2757 2758 /** 2759 * Create a new ScalarStatNode. 2760 * @param s The ScalarStat to place in a node. 2761 */ 2762 Temp(const Value &s) 2763 : node(new ScalarStatNode(s.statData())) { } 2764 2765 /** 2766 * Create a new ScalarStatNode. 2767 * @param s The ScalarStat to place in a node. 2768 */ 2769 template <int N> 2770 Temp(const Average<N> &s) 2771 : node(new ScalarStatNode(s.statData())) { } 2772 2773 /** 2774 * Create a new VectorStatNode. 2775 * @param s The VectorStat to place in a node. 2776 */ 2777 template <int N> 2778 Temp(const Vector<N> &s) 2779 : node(new VectorStatNode(s.statData())) { } 2780 2781 /** 2782 * 2783 */ 2784 Temp(const Formula &f) 2785 : node(new FormulaNode(f)) { } 2786 2787 /** 2788 * Create a new ScalarProxyNode. 2789 * @param p The ScalarProxy to place in a node. 2790 */ 2791 template <class Stat> 2792 Temp(const ScalarProxy<Stat> &p) 2793 : node(new ScalarProxyNode<Stat>(p)) { } 2794 2795 /** 2796 * Create a ConstNode 2797 * @param value The value of the const node. 2798 */ 2799 Temp(signed char value) 2800 : node(new ConstNode<signed char>(value)) {} 2801 2802 /** 2803 * Create a ConstNode 2804 * @param value The value of the const node. 2805 */ 2806 Temp(unsigned char value) 2807 : node(new ConstNode<unsigned char>(value)) {} 2808 2809 /** 2810 * Create a ConstNode 2811 * @param value The value of the const node. 2812 */ 2813 Temp(signed short value) 2814 : node(new ConstNode<signed short>(value)) {} 2815 2816 /** 2817 * Create a ConstNode 2818 * @param value The value of the const node. 2819 */ 2820 Temp(unsigned short value) 2821 : node(new ConstNode<unsigned short>(value)) {} 2822 2823 /** 2824 * Create a ConstNode 2825 * @param value The value of the const node. 2826 */ 2827 Temp(signed int value) 2828 : node(new ConstNode<signed int>(value)) {} 2829 2830 /** 2831 * Create a ConstNode 2832 * @param value The value of the const node. 2833 */ 2834 Temp(unsigned int value) 2835 : node(new ConstNode<unsigned int>(value)) {} 2836 2837 /** 2838 * Create a ConstNode 2839 * @param value The value of the const node. 2840 */ 2841 Temp(signed long value) 2842 : node(new ConstNode<signed long>(value)) {} 2843 2844 /** 2845 * Create a ConstNode 2846 * @param value The value of the const node. 2847 */ 2848 Temp(unsigned long value) 2849 : node(new ConstNode<unsigned long>(value)) {} 2850 2851 /** 2852 * Create a ConstNode 2853 * @param value The value of the const node. 2854 */ 2855 Temp(signed long long value) 2856 : node(new ConstNode<signed long long>(value)) {} 2857 2858 /** 2859 * Create a ConstNode 2860 * @param value The value of the const node. 2861 */ 2862 Temp(unsigned long long value) 2863 : node(new ConstNode<unsigned long long>(value)) {} 2864 2865 /** 2866 * Create a ConstNode 2867 * @param value The value of the const node. 2868 */ 2869 Temp(float value) 2870 : node(new ConstNode<float>(value)) {} 2871 2872 /** 2873 * Create a ConstNode 2874 * @param value The value of the const node. 2875 */ 2876 Temp(double value) 2877 : node(new ConstNode<double>(value)) {} 2878}; 2879 2880 2881/** 2882 * @} 2883 */ 2884 2885void check(); 2886void dump(); 2887void reset(); 2888void registerResetCallback(Callback *cb); 2889 2890inline Temp 2891operator+(Temp l, Temp r) 2892{ 2893 return NodePtr(new BinaryNode<std::plus<Result> >(l, r)); 2894} 2895 2896inline Temp 2897operator-(Temp l, Temp r) 2898{ 2899 return NodePtr(new BinaryNode<std::minus<Result> >(l, r)); 2900} 2901 2902inline Temp 2903operator*(Temp l, Temp r) 2904{ 2905 return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r)); 2906} 2907 2908inline Temp 2909operator/(Temp l, Temp r) 2910{ 2911 return NodePtr(new BinaryNode<std::divides<Result> >(l, r)); 2912} 2913 2914inline Temp 2915operator-(Temp l) 2916{ 2917 return NodePtr(new UnaryNode<std::negate<Result> >(l)); 2918} 2919 2920template <typename T> 2921inline Temp 2922constant(T val) 2923{ 2924 return NodePtr(new ConstNode<T>(val)); 2925} 2926 2927template <typename T> 2928inline Temp 2929constantVector(T val) 2930{ 2931 return NodePtr(new ConstVectorNode<T>(val)); 2932} 2933 2934inline Temp 2935sum(Temp val) 2936{ 2937 return NodePtr(new SumNode<std::plus<Result> >(val)); 2938} 2939 2940/* namespace Stats */ } 2941 2942#endif // __BASE_STATISTICS_HH__ 2943