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