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