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