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