makefile:
[gem5.git] / base / statistics.hh
1 /*
2 * Copyright (c) 2003 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
29 /*
30 * @todo
31 *
32 * Generalized N-dimensinal vector
33 * documentation
34 * fix AvgStor
35 * key stats
36 * interval stats
37 * -- these both can use the same function that prints out a
38 * specific set of stats
39 * VectorStandardDeviation totals
40 *
41 */
42 #ifndef __STATISTICS_HH__
43 #define __STATISTICS_HH__
44
45 #include <algorithm>
46 #include <functional>
47 #include <iosfwd>
48 #include <sstream>
49 #include <string>
50 #include <vector>
51
52 #include <assert.h>
53
54 #include "host.hh"
55 #include "refcnt.hh"
56 #include "str.hh"
57
58 #ifndef NAN
59 float __nan();
60 #define NAN (__nan())
61 #define __M5_NAN
62 #endif
63
64 #define STAT_DISPLAY_COMPAT
65
66 extern Tick curTick;
67
68 namespace Statistics {
69 typedef double result_t;
70 typedef std::vector<result_t> rvec_t;
71
72 typedef u_int32_t FormatFlags;
73 const FormatFlags none = 0x0000;
74 const FormatFlags total = 0x0001;
75 const FormatFlags pdf = 0x0002;
76 const FormatFlags nozero = 0x0004;
77 const FormatFlags nonan = 0x0008;
78 const FormatFlags cdf = 0x0010;
79 const FormatFlags dist = 0x0020;
80 const FormatFlags __substat = 0x8000;
81 const FormatFlags __reserved = __substat;
82
83 namespace Detail {
84 //////////////////////////////////////////////////////////////////////
85 //
86 // Statistics Framework Base classes
87 //
88 //////////////////////////////////////////////////////////////////////
89 struct StatData;
90 struct SubData;
91
92 class Stat
93 {
94 protected:
95 void setInit();
96 StatData *mydata();
97 const StatData *mydata() const;
98 StatData *print();
99 const SubData *mysubdata(int index) const;
100 SubData *mysubdata_create(int index);
101
102 public:
103 virtual std::string myname() const;
104 virtual std::string mysubname(int index) const;
105 virtual std::string mydesc() const;
106 virtual std::string mysubdesc(int index) const;
107 virtual FormatFlags myflags() const;
108 virtual bool dodisplay() const;
109 virtual int myprecision() const;
110
111 public:
112 Stat(bool reg);
113 virtual ~Stat() {}
114
115 virtual void display(std::ostream &stream) const = 0;
116 virtual size_t size() const = 0;
117 virtual bool zero() const = 0;
118
119 Stat &name(const std::string &name);
120 Stat &desc(const std::string &desc);
121 Stat &precision(int p);
122 Stat &flags(FormatFlags f);
123 Stat &prereq(const Stat &prereq);
124 Stat &subname(int index, const std::string &name);
125 Stat &subdesc(int index, const std::string &name);
126
127 public:
128 static bool less(Stat *stat1, Stat *stat2);
129
130 #ifdef STAT_DEBUG
131 int number;
132 #endif
133 };
134
135 // Scalar stats involved in formulas
136 class ScalarStat : public Stat
137 {
138 public:
139 ScalarStat(bool reg) : Stat(reg) {}
140 virtual result_t val() const = 0;
141 virtual bool zero() const;
142 virtual void display(std::ostream &stream) const;
143 };
144
145 void
146 VectorDisplay(std::ostream &stream, const std::string &myname,
147 const std::vector<std::string> *mysubnames,
148 const std::string &mydesc,
149 const std::vector<std::string> *mysubdescs,
150 int myprecision, FormatFlags myflags, const rvec_t &vec,
151 result_t mytotal);
152
153 // Vector stats involved in formulas
154 class VectorStat : public Stat
155 {
156 public:
157 VectorStat(bool reg) : Stat(reg) {}
158 virtual const rvec_t &val() const = 0;
159 virtual result_t total() const = 0;
160 virtual bool zero() const;
161 virtual void display(std::ostream &stream) const;
162 };
163
164 //////////////////////////////////////////////////////////////////////
165 //
166 // Simple Statistics
167 //
168 //////////////////////////////////////////////////////////////////////
169 template <typename T>
170 struct StatStor
171 {
172 public:
173 struct Params { };
174
175 private:
176 T data;
177
178 public:
179 StatStor(const Params &) : data(T()) {}
180
181 void set(T val, const Params &p) { data = val; }
182 void inc(T val, const Params &p) { data += val; }
183 void dec(T val, const Params &p) { data -= val; }
184 result_t val(const Params &p) const { return (result_t)data; }
185 T value(const Params &p) const { return data; }
186 };
187
188 template <typename T>
189 struct AvgStor
190 {
191 public:
192 struct Params { };
193
194 private:
195 T current;
196 mutable result_t total;
197 mutable Tick last;
198
199 public:
200 AvgStor(const Params &) : current(T()), total(0), last(0) { }
201
202 void set(T val, const Params &p) {
203 total += current * (curTick - last);
204 last = curTick;
205 current = val;
206 }
207 void inc(T val, const Params &p) { set(current + val, p); }
208 void dec(T val, const Params &p) { set(current - val, p); }
209 result_t val(const Params &p) const {
210 total += current * (curTick - last);
211 last = curTick;
212 return (result_t)(total + current) / (result_t)(curTick + 1);
213 }
214 T value(const Params &p) const { return current; }
215 };
216
217 template <typename T, template <typename T> class Storage, class Bin>
218 class ScalarBase : public ScalarStat
219 {
220 protected:
221 typedef Storage<T> storage_t;
222 typedef typename storage_t::Params params_t;
223 typedef typename Bin::Bin<storage_t> bin_t;
224
225 protected:
226 bin_t bin;
227 params_t params;
228
229 protected:
230 storage_t *data() { return bin.data(params); }
231 const storage_t *data() const {
232 return (const_cast<bin_t *>(&bin))->data(params);
233 }
234
235 protected:
236 // Copying stats is not allowed
237 ScalarBase(const ScalarBase &stat);
238 const ScalarBase &operator=(const ScalarBase &);
239
240 public:
241 result_t val() const { return data()->val(params); }
242 T value() const { return data()->value(params); }
243
244 public:
245 ScalarBase() : ScalarStat(true) {
246 bin.init(params);
247 setInit();
248 }
249
250 public:
251 // Common operators for stats
252 void operator++() { data()->inc(1, params); }
253 void operator--() { data()->dec(1, params); }
254
255 void operator++(int) { ++*this; }
256 void operator--(int) { --*this; }
257
258 template <typename U>
259 void operator=(const U& v) { data()->set(v, params); }
260
261 template <typename U>
262 void operator+=(const U& v) { data()->inc(v, params); }
263
264 template <typename U>
265 void operator-=(const U& v) { data()->dec(v, params); }
266
267 virtual size_t size() const { return 1; }
268 };
269
270 //////////////////////////////////////////////////////////////////////
271 //
272 // Vector Statistics
273 //
274 //////////////////////////////////////////////////////////////////////
275 template <typename T, template <typename T> class Storage, class Bin>
276 class ScalarProxy;
277
278 template <typename T, template <typename T> class Storage, class Bin>
279 class VectorBase : public VectorStat
280 {
281 protected:
282 typedef Storage<T> storage_t;
283 typedef typename storage_t::Params params_t;
284 typedef typename Bin::VectorBin<storage_t> bin_t;
285
286 private:
287 mutable rvec_t *vec;
288
289 protected:
290 bin_t bin;
291 params_t params;
292
293 protected:
294 storage_t *data(int index) { return bin.data(index, params); }
295 const storage_t *data(int index) const {
296 return (const_cast<bin_t *>(&bin))->data(index, params);
297 }
298
299 protected:
300 // Copying stats is not allowed
301 VectorBase(const VectorBase &stat);
302 const VectorBase &operator=(const VectorBase &);
303
304 public:
305 const rvec_t &val() const {
306 if (vec)
307 vec->resize(size());
308 else
309 vec = new rvec_t(size());
310
311 for (int i = 0; i < size(); ++i)
312 (*vec)[i] = data(i)->val(params);
313
314 return *vec;
315 }
316
317 result_t total() const {
318 result_t total = 0.0;
319 for (int i = 0; i < size(); ++i)
320 total += data(i)->val(params);
321 return total;
322 }
323
324 public:
325 VectorBase() : VectorStat(true), vec(NULL) {}
326 ~VectorBase() { if (vec) delete vec; }
327
328 VectorBase &init(size_t size) {
329 bin.init(size, params);
330 setInit();
331
332 return *this;
333 }
334
335 friend class ScalarProxy<T, Storage, Bin>;
336 ScalarProxy<T, Storage, Bin> operator[](int index);
337
338 virtual size_t size() const { return bin.size(); }
339 };
340
341 template <typename T, template <typename T> class Storage, class Bin>
342 class ScalarProxy : public ScalarStat
343 {
344 protected:
345 typedef Storage<T> storage_t;
346 typedef typename storage_t::Params params_t;
347 typedef typename Bin::VectorBin<storage_t> bin_t;
348
349 private:
350 bin_t *bin;
351 params_t *params;
352 int index;
353
354 protected:
355 storage_t *data() { return bin->data(index, *params); }
356 const storage_t *data() const { return bin->data(index, *params); }
357
358 public:
359 result_t val() const { return data()->val(*params); }
360 T value() const { return data()->value(*params); }
361
362 public:
363 ScalarProxy(bin_t &b, params_t &p, int i)
364 : ScalarStat(false), bin(&b), params(&p), index(i) {}
365 ScalarProxy(const ScalarProxy &sp)
366 : ScalarStat(false), bin(sp.bin), params(sp.params), index(sp.index) {}
367 const ScalarProxy &operator=(const ScalarProxy &sp) {
368 bin = sp.bin;
369 params = sp.params;
370 index = sp.index;
371 return *this;
372 }
373
374 public:
375 // Common operators for stats
376 void operator++() { data()->inc(1, *params); }
377 void operator--() { data()->dec(1, *params); }
378
379 void operator++(int) { ++*this; }
380 void operator--(int) { --*this; }
381
382 template <typename U>
383 void operator=(const U& v) { data()->set(v, *params); }
384
385 template <typename U>
386 void operator+=(const U& v) { data()->inc(v, *params); }
387
388 template <typename U>
389 void operator-=(const U& v) { data()->dec(v, *params); }
390
391 virtual size_t size() const { return 1; }
392 };
393
394 template <typename T, template <typename T> class Storage, class Bin>
395 inline ScalarProxy<T, Storage, Bin>
396 VectorBase<T, Storage, Bin>::operator[](int index)
397 {
398 assert (index >= 0 && index < size());
399 return ScalarProxy<T, Storage, Bin>(bin, params, index);
400 }
401
402 template <typename T, template <typename T> class Storage, class Bin>
403 class VectorProxy;
404
405 template <typename T, template <typename T> class Storage, class Bin>
406 class Vector2dBase : public Stat
407 {
408 protected:
409 typedef Storage<T> storage_t;
410 typedef typename storage_t::Params params_t;
411 typedef typename Bin::VectorBin<storage_t> bin_t;
412
413 protected:
414 size_t x;
415 size_t y;
416 bin_t bin;
417 params_t params;
418 std::vector<std::string> *y_subnames;
419
420 protected:
421 storage_t *data(int index) { return bin.data(index, params); }
422 const storage_t *data(int index) const {
423 return (const_cast<bin_t *>(&bin))->data(index, params);
424 }
425
426 protected:
427 // Copying stats is not allowed
428 Vector2dBase(const Vector2dBase &stat);
429 const Vector2dBase &operator=(const Vector2dBase &);
430
431 public:
432 Vector2dBase() : Stat(true) {}
433 ~Vector2dBase() { }
434
435 Vector2dBase &init(size_t _x, size_t _y) {
436 x = _x;
437 y = _y;
438 bin.init(x * y, params);
439 setInit();
440 y_subnames = new std::vector<std::string>(y);
441
442 return *this;
443 }
444
445 /**
446 * This makes the assumption that if you're gonna subnames a 2d vector,
447 * you're subnaming across all y
448 */
449 Vector2dBase &ysubnames(const char **names)
450 {
451 for (int i=0; i < y; ++i) {
452 (*y_subnames)[i] = names[i];
453 }
454 return *this;
455 }
456 Vector2dBase &ysubname(int index, const std::string subname)
457 {
458 (*y_subnames)[i] = subname.c_str();
459 return *this;
460 }
461 std::string ysubname(int i) const { return (*y_subnames)[i]; }
462
463 friend class VectorProxy<T, Storage, Bin>;
464 VectorProxy<T, Storage, Bin> operator[](int index);
465
466 virtual size_t size() const { return bin.size(); }
467 virtual bool zero() const { return data(0)->value(params) == 0.0; }
468
469 virtual void
470 display(std::ostream &out) const
471 {
472 bool have_subname = false;
473 for (int i = 0; i < x; ++i) {
474 if (!mysubname(i).empty())
475 have_subname = true;
476 }
477
478 rvec_t tot_vec(y);
479 result_t super_total = 0.0;
480 for (int i = 0; i < x; ++i) {
481 std::string subname;
482 if (have_subname) {
483 subname = mysubname(i);
484 if (subname.empty())
485 continue;
486 } else
487 subname = to_string(i);
488
489 int iy = i * y;
490 rvec_t vec(y);
491
492 result_t total = 0.0;
493 for (int j = 0; j < y; ++j) {
494 vec[j] = data(iy + j)->val(params);
495 tot_vec[j] += vec[j];
496 total += vec[j];
497 super_total += vec[j];
498 }
499
500 std::string desc;
501 if (mysubdesc(i).empty()) {
502 desc = mydesc();
503 } else {
504 desc = mysubdesc(i);
505 }
506
507 VectorDisplay(out, myname() + "_" + subname, y_subnames, desc, 0,
508 myprecision(), myflags(), vec, total);
509
510 }
511 if ((myflags() & ::Statistics::total) && (x > 1)) {
512 VectorDisplay(out, myname(), y_subnames, mydesc(), 0,
513 myprecision(), myflags(), tot_vec, super_total);
514
515 }
516 }
517 };
518
519 template <typename T, template <typename T> class Storage, class Bin>
520 class VectorProxy : public VectorStat
521 {
522 protected:
523 typedef Storage<T> storage_t;
524 typedef typename storage_t::Params params_t;
525 typedef typename Bin::VectorBin<storage_t> bin_t;
526
527 private:
528 bin_t *bin;
529 params_t *params;
530 int offset;
531 int len;
532
533 private:
534 mutable rvec_t *vec;
535
536 storage_t *data(int index) {
537 assert(index < len);
538 return bin->data(offset + index, *params);
539 }
540
541 const storage_t *data(int index) const {
542 return (const_cast<bin_t *>(bin))->data(offset + index, *params);
543 }
544
545 public:
546 const rvec_t &val() const {
547 if (vec)
548 vec->resize(size());
549 else
550 vec = new rvec_t(size());
551
552 for (int i = 0; i < size(); ++i)
553 (*vec)[i] = data(i)->val(*params);
554
555 return *vec;
556 }
557
558 result_t total() const {
559 result_t total = 0.0;
560 for (int i = 0; i < size(); ++i)
561 total += data(i)->val(*params);
562 return total;
563 }
564
565 public:
566 VectorProxy(bin_t &b, params_t &p, int o, int l)
567 : VectorStat(false), bin(&b), params(&p), offset(o), len(l), vec(NULL)
568 { }
569 VectorProxy(const VectorProxy &sp)
570 : VectorStat(false), bin(sp.bin), params(sp.params), offset(sp.offset),
571 len(sp.len), vec(NULL)
572 { }
573 ~VectorProxy() {
574 if (vec)
575 delete vec;
576 }
577
578 const VectorProxy &operator=(const VectorProxy &sp) {
579 bin = sp.bin;
580 params = sp.params;
581 offset = sp.offset;
582 len = sp.len;
583 if (vec)
584 delete vec;
585 vec = NULL;
586 return *this;
587 }
588
589 virtual size_t size() const { return len; }
590
591 ScalarProxy<T, Storage, Bin> operator[](int index) {
592 assert (index >= 0 && index < size());
593 return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index);
594 }
595 };
596
597 template <typename T, template <typename T> class Storage, class Bin>
598 inline VectorProxy<T, Storage, Bin>
599 Vector2dBase<T, Storage, Bin>::operator[](int index)
600 {
601 int offset = index * y;
602 assert (index >= 0 && offset < size());
603 return VectorProxy<T, Storage, Bin>(bin, params, offset, y);
604 }
605
606 //////////////////////////////////////////////////////////////////////
607 //
608 // Non formula statistics
609 //
610 //////////////////////////////////////////////////////////////////////
611
612 void DistDisplay(std::ostream &stream, const std::string &name,
613 const std::string &desc, int precision, FormatFlags flags,
614 result_t min_val, result_t max_val,
615 result_t underflow, result_t overflow,
616 const rvec_t &vec, int min, int max, int bucket_size,
617 int size);
618
619 template <typename T>
620 struct DistStor
621 {
622 public:
623 struct Params
624 {
625 int min;
626 int max;
627 int bucket_size;
628 int size;
629 };
630
631 private:
632 T min_val;
633 T max_val;
634 T underflow;
635 T overflow;
636 std::vector<T> vec;
637
638 public:
639 DistStor(const Params &params)
640 : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0),
641 vec(params.size) {
642 }
643 void sample(T val, int number, const Params &params) {
644 if (val < params.min)
645 underflow += number;
646 else if (val > params.max)
647 overflow += number;
648 else {
649 int index = (val - params.min) / params.bucket_size;
650 assert(index < size(params));
651 vec[index] += number;
652 }
653
654 if (val < min_val)
655 min_val = val;
656
657 if (val > max_val)
658 max_val = val;
659 }
660
661 size_t size(const Params &) const { return vec.size(); }
662
663 bool zero(const Params &params) const {
664 if (underflow != 0 || overflow != 0)
665 return true;
666
667 int s = size(params);
668 for (int i = 0; i < s; i++)
669 if (vec[i] != 0)
670 return true;
671
672 return false;
673 }
674
675 void display(std::ostream &stream, const std::string &name,
676 const std::string &desc, int precision, FormatFlags flags,
677 const Params &params) const {
678
679 #ifdef STAT_DISPLAY_COMPAT
680 result_t min = params.min;
681 #else
682 result_t min = (min_val == INT_MAX) ? params.min : min_val;
683 #endif
684 result_t max = (max_val == INT_MIN) ? 0 : max_val;
685
686 rvec_t rvec(params.size);
687 for (int i = 0; i < params.size; ++i)
688 rvec[i] = vec[i];
689
690 DistDisplay(stream, name, desc, precision, flags,
691 (result_t)min, (result_t)max,
692 (result_t)underflow, (result_t)overflow,
693 rvec, params.min, params.max, params.bucket_size,
694 params.size);
695 }
696 };
697
698 void FancyDisplay(std::ostream &stream, const std::string &name,
699 const std::string &desc, int precision, FormatFlags flags,
700 result_t mean, result_t variance);
701 template <typename T>
702 struct FancyStor
703 {
704 public:
705 struct Params {};
706
707 private:
708 T sum;
709 T squares;
710 int total;
711
712 public:
713 FancyStor(const Params &) : sum(0), squares(0), total(0) {}
714
715 void sample(T val, int number, const Params &) {
716 T value = val * number;
717 sum += value;
718 squares += value * value;
719 total += number;
720 }
721 void display(std::ostream &stream, const std::string &name,
722 const std::string &desc, int precision, FormatFlags flags,
723 const Params &) const {
724
725 result_t mean = NAN;
726 result_t variance = NAN;
727
728 if (total != 0) {
729 result_t fsum = sum;
730 result_t fsq = squares;
731 result_t ftot = total;
732
733 mean = fsum / ftot;
734 variance = (ftot * fsq - (fsum * fsum)) / (ftot * (ftot - 1.0));
735 }
736
737 FancyDisplay(stream, name, desc, precision, flags, mean, variance);
738 }
739
740 size_t size(const Params &) const { return 1; }
741 bool zero(const Params &) const { return total == 0; }
742 };
743
744 template <typename T>
745 struct AvgFancy
746 {
747 public:
748 struct Params {};
749
750 private:
751 T sum;
752 T squares;
753
754 public:
755 AvgFancy(const Params &) : sum(0), squares(0) {}
756
757 void sample(T val, int number, const Params& p) {
758 T value = val * number;
759 sum += value;
760 squares += value * value;
761 }
762 void display(std::ostream &stream, const std::string &name,
763 const std::string &desc, int precision, FormatFlags flags,
764 const Params &params) const {
765 result_t mean = sum / curTick;
766 result_t variance = (squares - sum * sum) / curTick;
767
768 FancyDisplay(stream, name, desc, precision, flags, mean, variance);
769 }
770
771 size_t size(const Params &params) const { return 1; }
772 bool zero(const Params &params) const { return sum == 0; }
773 };
774
775 template <typename T, template <typename T> class Storage, class Bin>
776 class DistBase : public Stat
777 {
778 protected:
779 typedef Storage<T> storage_t;
780 typedef typename storage_t::Params params_t;
781 typedef typename Bin::Bin<storage_t> bin_t;
782
783 protected:
784 bin_t bin;
785 params_t params;
786
787 protected:
788 storage_t *data() { return bin.data(params); }
789 const storage_t *data() const {
790 return (const_cast<bin_t *>(&bin))->data(params);
791 }
792
793 protected:
794 // Copying stats is not allowed
795 DistBase(const DistBase &stat);
796 const DistBase &operator=(const DistBase &);
797
798 public:
799 DistBase() : Stat(true) { }
800 ~DistBase() { }
801
802 template <typename U>
803 void sample(const U& v, int n = 1) { data()->sample(v, n, params); }
804
805 virtual size_t size() const { return data()->size(params); }
806 virtual bool zero() const { return data()->zero(params); }
807 virtual void display(std::ostream &stream) const {
808 data()->display(stream, myname(), mydesc(), myprecision(), myflags(),
809 params);
810 }
811 };
812
813 template <typename T, template <typename T> class Storage, class Bin>
814 class VectorDistProxy;
815
816 template <typename T, template <typename T> class Storage, class Bin>
817 class VectorDistBase : public Stat
818 {
819 protected:
820 typedef Storage<T> storage_t;
821 typedef typename storage_t::Params params_t;
822 typedef typename Bin::VectorBin<storage_t> bin_t;
823
824 protected:
825 bin_t bin;
826 params_t params;
827
828 protected:
829 storage_t *data(int index) { return bin.data(index, params); }
830 const storage_t *data(int index) const {
831 return (const_cast<bin_t *>(&bin))->data(index, params);
832 }
833
834 protected:
835 // Copying stats is not allowed
836 VectorDistBase(const VectorDistBase &stat);
837 const VectorDistBase &operator=(const VectorDistBase &);
838
839 public:
840 VectorDistBase() : Stat(true) { }
841 ~VectorDistBase() { }
842
843 friend class VectorDistProxy<T, Storage, Bin>;
844 VectorDistProxy<T, Storage, Bin> operator[](int index);
845 const VectorDistProxy<T, Storage, Bin> operator[](int index) const;
846
847 virtual size_t size() const { return bin.size(); }
848 virtual bool zero() const { return false; }
849 virtual void display(std::ostream &stream) const;
850 };
851
852 template <typename T, template <typename T> class Storage, class Bin>
853 class VectorDistProxy : public Stat
854 {
855 protected:
856 typedef Storage<T> storage_t;
857 typedef typename storage_t::Params params_t;
858 typedef typename Bin::Bin<storage_t> bin_t;
859 typedef VectorDistBase<T, Storage, Bin> base_t;
860
861 private:
862 union {
863 base_t *stat;
864 const base_t *cstat;
865 };
866 int index;
867
868 protected:
869 storage_t *data() { return stat->data(index); }
870 const storage_t *data() const { return cstat->data(index); }
871
872 public:
873 VectorDistProxy(const VectorDistBase<T, Storage, Bin> &s, int i)
874 : Stat(false), cstat(&s), index(i) {}
875 VectorDistProxy(const VectorDistProxy &sp)
876 : Stat(false), cstat(sp.cstat), index(sp.index) {}
877 const VectorDistProxy &operator=(const VectorDistProxy &sp) {
878 cstat = sp.cstat; index = sp.index; return *this;
879 }
880
881 public:
882 template <typename U>
883 void sample(const U& v, int n = 1) { data()->sample(v, n, cstat->params); }
884
885 virtual size_t size() const { return 1; }
886 virtual bool zero() const {
887 return data()->zero(cstat->params);
888 }
889 virtual void display(std::ostream &stream) const {
890 std::stringstream name, desc;
891
892 if (!(cstat->mysubname(index).empty())) {
893 name << cstat->myname() << cstat->mysubname(index);
894 } else {
895 name << cstat->myname() << "_" << index;
896 }
897 if (!(cstat->mysubdesc(index).empty())) {
898 desc << cstat->mysubdesc(index);
899 } else {
900 desc << cstat->mydesc();
901 }
902
903 data()->display(stream, name.str(), desc.str(),
904 cstat->myprecision(), cstat->myflags(), cstat->params);
905 }
906 };
907
908 template <typename T, template <typename T> class Storage, class Bin>
909 inline VectorDistProxy<T, Storage, Bin>
910 VectorDistBase<T, Storage, Bin>::operator[](int index)
911 {
912 assert (index >= 0 && index < size());
913 return VectorDistProxy<T, Storage, Bin>(*this, index);
914 }
915
916 template <typename T, template <typename T> class Storage, class Bin>
917 inline const VectorDistProxy<T, Storage, Bin>
918 VectorDistBase<T, Storage, Bin>::operator[](int index) const
919 {
920 assert (index >= 0 && index < size());
921 return VectorDistProxy<T, Storage, Bin>(*this, index);
922 }
923
924 /**
925 * @todo Need a way to print Distribution totals across the Vector
926 */
927 template <typename T, template <typename T> class Storage, class Bin>
928 void
929 VectorDistBase<T, Storage, Bin>::display(std::ostream &stream) const
930 {
931 for (int i = 0; i < size(); ++i) {
932 VectorDistProxy<T, Storage, Bin> proxy(*this, i);
933 proxy.display(stream);
934 }
935 }
936
937 #if 0
938 result_t
939 VectorDistBase<T, Storage, Bin>::total(int index) const
940 {
941 int total = 0;
942 for (int i=0; i < x_size(); ++i) {
943 total += data(i)->val(*params);
944 }
945 }
946 #endif
947
948 //////////////////////////////////////////////////////////////////////
949 //
950 // Formula Details
951 //
952 //////////////////////////////////////////////////////////////////////
953 class Node : public RefCounted
954 {
955 public:
956 virtual size_t size() const = 0;
957 virtual const rvec_t &val() const = 0;
958 virtual result_t total() const = 0;
959 };
960
961 typedef RefCountingPtr<Node> NodePtr;
962
963 class ScalarStatNode : public Node
964 {
965 private:
966 const ScalarStat &stat;
967 mutable rvec_t result;
968
969 public:
970 ScalarStatNode(const ScalarStat &s) : stat(s), result(1) {}
971 const rvec_t &val() const { result[0] = stat.val(); return result; }
972 virtual result_t total() const { return stat.val(); };
973
974 virtual size_t size() const { return 1; }
975 };
976
977 template <typename T, template <typename T> class Storage, class Bin>
978 class ScalarProxyNode : public Node
979 {
980 private:
981 const ScalarProxy<T, Storage, Bin> proxy;
982 mutable rvec_t result;
983
984 public:
985 ScalarProxyNode(const ScalarProxy<T, Storage, Bin> &p)
986 : proxy(p), result(1) { }
987 const rvec_t &val() const { result[0] = proxy.val(); return result; }
988 virtual result_t total() const { return proxy.val(); };
989
990 virtual size_t size() const { return 1; }
991 };
992
993 class VectorStatNode : public Node
994 {
995 private:
996 const VectorStat &stat;
997
998 public:
999 VectorStatNode(const VectorStat &s) : stat(s) {}
1000 const rvec_t &val() const { return stat.val(); }
1001 virtual result_t total() const { return stat.total(); };
1002
1003 virtual size_t size() const { return stat.size(); }
1004 };
1005
1006 template <typename T>
1007 class ConstNode : public Node
1008 {
1009 private:
1010 rvec_t data;
1011
1012 public:
1013 ConstNode(T s) : data(1, (result_t)s) {}
1014 const rvec_t &val() const { return data; }
1015 virtual result_t total() const { return data[0]; };
1016
1017 virtual size_t size() const { return 1; }
1018 };
1019
1020 template <typename T>
1021 class FunctorNode : public Node
1022 {
1023 private:
1024 T &functor;
1025 mutable rvec_t result;
1026
1027 public:
1028 FunctorNode(T &f) : functor(f) { result.resize(1); }
1029 const rvec_t &val() const {
1030 result[0] = (result_t)functor();
1031 return result;
1032 }
1033 virtual result_t total() const { return (result_t)functor(); };
1034
1035 virtual size_t size() const { return 1; }
1036 };
1037
1038 template <typename T>
1039 class ScalarNode : public Node
1040 {
1041 private:
1042 T &scalar;
1043 mutable rvec_t result;
1044
1045 public:
1046 ScalarNode(T &s) : scalar(s) { result.resize(1); }
1047 const rvec_t &val() const {
1048 result[0] = (result_t)scalar;
1049 return result;
1050 }
1051 virtual result_t total() const { return (result_t)scalar; };
1052
1053 virtual size_t size() const { return 1; }
1054 };
1055
1056 template <class Op>
1057 class UnaryNode : public Node
1058 {
1059 public:
1060 NodePtr l;
1061 mutable rvec_t result;
1062
1063 public:
1064 UnaryNode(NodePtr p) : l(p) {}
1065
1066 const rvec_t &val() const {
1067 const rvec_t &lvec = l->val();
1068 int size = lvec.size();
1069
1070 assert(size > 0);
1071
1072 result.resize(size);
1073 Op op;
1074 for (int i = 0; i < size; ++i)
1075 result[i] = op(lvec[i]);
1076
1077 return result;
1078 }
1079
1080 result_t total() const {
1081 Op op;
1082 return op(l->total());
1083 }
1084
1085 virtual size_t size() const { return l->size(); }
1086 };
1087
1088 template <class Op>
1089 class BinaryNode : public Node
1090 {
1091 public:
1092 NodePtr l;
1093 NodePtr r;
1094 mutable rvec_t result;
1095
1096 public:
1097 BinaryNode(NodePtr a, NodePtr b) : l(a), r(b) {}
1098
1099 const rvec_t &val() const {
1100 Op op;
1101 const rvec_t &lvec = l->val();
1102 const rvec_t &rvec = r->val();
1103
1104 assert(lvec.size() > 0 && rvec.size() > 0);
1105
1106 if (lvec.size() == 1 && rvec.size() == 1) {
1107 result.resize(1);
1108 result[0] = op(lvec[0], rvec[0]);
1109 } else if (lvec.size() == 1) {
1110 int size = rvec.size();
1111 result.resize(size);
1112 for (int i = 0; i < size; ++i)
1113 result[i] = op(lvec[0], rvec[i]);
1114 } else if (rvec.size() == 1) {
1115 int size = lvec.size();
1116 result.resize(size);
1117 for (int i = 0; i < size; ++i)
1118 result[i] = op(lvec[i], rvec[0]);
1119 } else if (rvec.size() == lvec.size()) {
1120 int size = rvec.size();
1121 result.resize(size);
1122 for (int i = 0; i < size; ++i)
1123 result[i] = op(lvec[i], rvec[i]);
1124 }
1125
1126 return result;
1127 }
1128
1129 result_t total() const {
1130 Op op;
1131 return op(l->total(), r->total());
1132 }
1133
1134 virtual size_t size() const {
1135 int ls = l->size();
1136 int rs = r->size();
1137 if (ls == 1)
1138 return rs;
1139 else if (rs == 1)
1140 return ls;
1141 else {
1142 assert(ls == rs && "Node vector sizes are not equal");
1143 return ls;
1144 }
1145 }
1146 };
1147
1148 template <class Op>
1149 class SumNode : public Node
1150 {
1151 public:
1152 NodePtr l;
1153 mutable rvec_t result;
1154
1155 public:
1156 SumNode(NodePtr p) : l(p), result(1) {}
1157
1158 const rvec_t &val() const {
1159 const rvec_t &lvec = l->val();
1160 int size = lvec.size();
1161 assert(size > 0);
1162
1163 result[0] = 0.0;
1164
1165 Op op;
1166 for (int i = 0; i < size; ++i)
1167 result[0] = op(result[0], lvec[i]);
1168
1169 return result;
1170 }
1171
1172 result_t total() const {
1173 const rvec_t &lvec = l->val();
1174 int size = lvec.size();
1175 assert(size > 0);
1176
1177 result_t result = 0.0;
1178
1179 Op op;
1180 for (int i = 0; i < size; ++i)
1181 result = op(result, lvec[i]);
1182
1183 return result;
1184 }
1185
1186 virtual size_t size() const { return 1; }
1187 };
1188
1189 class Temp
1190 {
1191 private:
1192 NodePtr node;
1193
1194 public:
1195 Temp(NodePtr n) : node(n) {}
1196 Temp(const ScalarStat &s) : node(new ScalarStatNode(s)) {}
1197 template <typename T, template <typename T> class Storage, class Bin>
1198 Temp(const ScalarProxy<T, Storage, Bin> &p)
1199 : node(new ScalarProxyNode<T, Storage, Bin>(p)) {}
1200 Temp(const VectorStat &s) : node(new VectorStatNode(s)) {}
1201
1202 #define TempSCALAR(T) \
1203 Temp(T value) : node(new ConstNode<T>(value)) {}
1204
1205 TempSCALAR( signed char);
1206 TempSCALAR(unsigned char);
1207 TempSCALAR( signed short);
1208 TempSCALAR(unsigned short);
1209 TempSCALAR( signed int);
1210 TempSCALAR(unsigned int);
1211 TempSCALAR( signed long);
1212 TempSCALAR(unsigned long);
1213 TempSCALAR( signed long long);
1214 TempSCALAR(unsigned long long);
1215 TempSCALAR(float);
1216 TempSCALAR(double);
1217 #undef TempSCALAR
1218
1219 operator NodePtr() { return node;}
1220 };
1221
1222
1223 //////////////////////////////////////////////////////////////////////
1224 //
1225 // Binning Interface
1226 //
1227 //////////////////////////////////////////////////////////////////////
1228
1229 class BinBase
1230 {
1231 private:
1232 off_t memsize;
1233 char *mem;
1234
1235 protected:
1236 off_t size() const { return memsize; }
1237 char *memory();
1238
1239 public:
1240 BinBase(size_t size);
1241 ~BinBase();
1242 };
1243
1244 } // namespace Detail
1245
1246 template <class BinType>
1247 struct StatBin : public Detail::BinBase
1248 {
1249 static StatBin *&curBin() {
1250 static StatBin *current = NULL;
1251 return current;
1252 }
1253
1254 static void setCurBin(StatBin *bin) { curBin() = bin; }
1255 static StatBin *current() { assert(curBin()); return curBin(); }
1256
1257 static off_t &offset() {
1258 static off_t offset = 0;
1259 return offset;
1260 }
1261
1262 static off_t new_offset(size_t size) {
1263 size_t mask = sizeof(u_int64_t) - 1;
1264 off_t off = offset();
1265
1266 // That one is for the last trailing flags byte.
1267 offset() += (size + 1 + mask) & ~mask;
1268
1269 return off;
1270 }
1271
1272 explicit StatBin(size_t size = 1024) : Detail::BinBase(size) {}
1273
1274 char *memory(off_t off) {
1275 assert(offset() <= size());
1276 return Detail::BinBase::memory() + off;
1277 }
1278
1279 static void activate(StatBin &bin) { setCurBin(&bin); }
1280
1281 class BinBase
1282 {
1283 private:
1284 int offset;
1285
1286 public:
1287 BinBase() : offset(-1) {}
1288 void allocate(size_t size) {
1289 offset = new_offset(size);
1290 }
1291 char *access() {
1292 assert(offset != -1);
1293 return current()->memory(offset);
1294 }
1295 };
1296
1297 template <class Storage>
1298 class Bin : public BinBase
1299 {
1300 public:
1301 typedef typename Storage::Params Params;
1302
1303 public:
1304 Bin() { allocate(sizeof(Storage)); }
1305 bool initialized() const { return true; }
1306 void init(const Params &params) { }
1307
1308 int size() const { return 1; }
1309
1310 Storage *data(const Params &params) {
1311 assert(initialized());
1312 char *ptr = access();
1313 char *flags = ptr + sizeof(Storage);
1314 if (!(*flags & 0x1)) {
1315 *flags |= 0x1;
1316 new (ptr) Storage(params);
1317 }
1318 return reinterpret_cast<Storage *>(ptr);
1319 }
1320 };
1321
1322 template <class Storage>
1323 class VectorBin : public BinBase
1324 {
1325 public:
1326 typedef typename Storage::Params Params;
1327
1328 private:
1329 int _size;
1330
1331 public:
1332 VectorBin() : _size(0) {}
1333
1334 bool initialized() const { return _size > 0; }
1335 void init(int s, const Params &params) {
1336 assert(!initialized());
1337 assert(s > 0);
1338 _size = s;
1339 allocate(_size * sizeof(Storage));
1340 }
1341
1342 int size() const { return _size; }
1343
1344 Storage *data(int index, const Params &params) {
1345 assert(initialized());
1346 assert(index >= 0 && index < size());
1347 char *ptr = access();
1348 char *flags = ptr + size() * sizeof(Storage);
1349 if (!(*flags & 0x1)) {
1350 *flags |= 0x1;
1351 for (int i = 0; i < size(); ++i)
1352 new (ptr + i * sizeof(Storage)) Storage(params);
1353 }
1354 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
1355 }
1356 };
1357 };
1358
1359 class MainBinType {};
1360 typedef StatBin<MainBinType> MainBin;
1361
1362 struct NoBin
1363 {
1364 template <class Storage>
1365 struct Bin
1366 {
1367 public:
1368 typedef typename Storage::Params Params;
1369
1370 private:
1371 char ptr[sizeof(Storage)];
1372
1373 public:
1374 bool initialized() const { return true; }
1375 void init(const Params &params) {
1376 new (ptr) Storage(params);
1377 }
1378 int size() const{ return 1; }
1379 Storage *data(const Params &params) {
1380 assert(initialized());
1381 return reinterpret_cast<Storage *>(ptr);
1382 }
1383 };
1384
1385 template <class Storage>
1386 struct VectorBin
1387 {
1388 public:
1389 typedef typename Storage::Params Params;
1390
1391 private:
1392 char *ptr;
1393 int _size;
1394
1395 public:
1396 VectorBin() : ptr(NULL) { }
1397 ~VectorBin() {
1398 if (initialized())
1399 delete [] ptr;
1400 }
1401 bool initialized() const { return ptr != NULL; }
1402 void init(int s, const Params &params) {
1403 assert(s > 0 && "size must be positive!");
1404 assert(!initialized());
1405 _size = s;
1406 ptr = new char[_size * sizeof(Storage)];
1407 for (int i = 0; i < _size; ++i)
1408 new (ptr + i * sizeof(Storage)) Storage(params);
1409 }
1410
1411 int size() const { return _size; }
1412
1413 Storage *data(int index, const Params &params) {
1414 assert(initialized());
1415 assert(index >= 0 && index < size());
1416 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
1417 }
1418 };
1419 };
1420
1421 //////////////////////////////////////////////////////////////////////
1422 //
1423 // Visible Statistics Types
1424 //
1425 //////////////////////////////////////////////////////////////////////
1426 template <typename T = Counter, class Bin = NoBin>
1427 class Scalar : public Detail::ScalarBase<T, Detail::StatStor, Bin>
1428 {
1429 public:
1430 typedef Detail::ScalarBase<T, Detail::StatStor, Bin> Base;
1431
1432 template <typename U>
1433 void operator=(const U& v) { Base::operator=(v); }
1434 };
1435
1436 template <typename T = Counter, class Bin = NoBin>
1437 class Average : public Detail::ScalarBase<T, Detail::AvgStor, Bin>
1438 {
1439 public:
1440 typedef Detail::ScalarBase<T, Detail::AvgStor, Bin> Base;
1441
1442 template <typename U>
1443 void operator=(const U& v) { Base::operator=(v); }
1444 };
1445
1446 template <typename T = Counter, class Bin = NoBin>
1447 class Vector : public Detail::VectorBase<T, Detail::StatStor, Bin>
1448 { };
1449
1450 template <typename T = Counter, class Bin = NoBin>
1451 class AverageVector : public Detail::VectorBase<T, Detail::AvgStor, Bin>
1452 { };
1453
1454 template <typename T = Counter, class Bin = NoBin>
1455 class Vector2d : public Detail::Vector2dBase<T, Detail::StatStor, Bin>
1456 { };
1457
1458 template <typename T = Counter, class Bin = NoBin>
1459 class Distribution : public Detail::DistBase<T, Detail::DistStor, Bin>
1460 {
1461 private:
1462 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1463 typedef typename Detail::DistStor<T>::Params Params;
1464
1465 public:
1466 Distribution &init(T min, T max, int bkt) {
1467 params.min = min;
1468 params.max = max;
1469 params.bucket_size = bkt;
1470 params.size = (max - min) / bkt + 1;
1471 bin.init(params);
1472 setInit();
1473
1474 return *this;
1475 }
1476 };
1477
1478 template <typename T = Counter, class Bin = NoBin>
1479 class StandardDeviation : public Detail::DistBase<T, Detail::FancyStor, Bin>
1480 {
1481 private:
1482 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1483 typedef typename Detail::DistStor<T>::Params Params;
1484
1485 public:
1486 StandardDeviation() {
1487 bin.init(params);
1488 setInit();
1489 }
1490 };
1491
1492 template <typename T = Counter, class Bin = NoBin>
1493 class AverageDeviation : public Detail::DistBase<T, Detail::AvgFancy, Bin>
1494 {
1495 private:
1496 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1497 typedef typename Detail::DistStor<T>::Params Params;
1498
1499 public:
1500 AverageDeviation() {
1501 bin.init(params);
1502 setInit();
1503 }
1504 };
1505
1506 template <typename T = Counter, class Bin = NoBin>
1507 class VectorDistribution
1508 : public Detail::VectorDistBase<T, Detail::DistStor, Bin>
1509 {
1510 private:
1511 typedef Detail::VectorDistBase<T, Detail::DistStor, Bin> Base;
1512 typedef typename Detail::DistStor<T>::Params Params;
1513
1514 public:
1515 VectorDistribution &init(int size, T min, T max, int bkt) {
1516 params.min = min;
1517 params.max = max;
1518 params.bucket_size = bkt;
1519 params.size = (max - min) / bkt + 1;
1520 bin.init(size, params);
1521 setInit();
1522
1523 return *this;
1524 }
1525 };
1526
1527 template <typename T = Counter, class Bin = NoBin>
1528 class VectorStandardDeviation
1529 : public Detail::VectorDistBase<T, Detail::FancyStor, Bin>
1530 {
1531 private:
1532 typedef Detail::VectorDistBase<T, Detail::FancyStor, Bin> Base;
1533 typedef typename Detail::DistStor<T>::Params Params;
1534
1535 public:
1536 VectorStandardDeviation &init(int size) {
1537 bin.init(size, params);
1538 setInit();
1539
1540 return *this;
1541 }
1542 };
1543
1544 template <typename T = Counter, class Bin = NoBin>
1545 class VectorAverageDeviation
1546 : public Detail::VectorDistBase<T, Detail::AvgFancy, Bin>
1547 {
1548 private:
1549 typedef Detail::VectorDistBase<T, Detail::AvgFancy, Bin> Base;
1550 typedef typename Detail::DistStor<T>::Params Params;
1551
1552 public:
1553 VectorAverageDeviation &init(int size) {
1554 bin.init(size, params);
1555 setInit();
1556
1557 return *this;
1558 }
1559 };
1560
1561 class Formula : public Detail::VectorStat
1562 {
1563 private:
1564 Detail::NodePtr root;
1565 friend class Detail::Temp;
1566
1567 public:
1568 Formula() : VectorStat(true) { setInit(); }
1569 Formula(Detail::Temp r) : VectorStat(true) {
1570 root = r;
1571 assert(size());
1572 }
1573
1574 const Formula &operator=(Detail::Temp r) {
1575 assert(!root && "Can't change formulas");
1576 root = r;
1577 assert(size());
1578 return *this;
1579 }
1580
1581 const Formula &operator+=(Detail::Temp r) {
1582 using namespace Detail;
1583 if (root)
1584 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
1585 else
1586 root = r;
1587 assert(size());
1588 return *this;
1589 }
1590
1591 const rvec_t &val() const { return root->val(); }
1592 result_t total() const { return root->total(); }
1593
1594 size_t size() const {
1595 if (!root)
1596 return 0;
1597 else
1598 return root->size();
1599 }
1600 };
1601
1602 void check();
1603 void dump(std::ostream &stream);
1604
1605 inline Detail::Temp
1606 operator+(Detail::Temp l, Detail::Temp r)
1607 {
1608 using namespace Detail;
1609 return NodePtr(new BinaryNode<std::plus<result_t> >(l, r));
1610 }
1611
1612 inline Detail::Temp
1613 operator-(Detail::Temp l, Detail::Temp r)
1614 {
1615 using namespace Detail;
1616 return NodePtr(new BinaryNode<std::minus<result_t> >(l, r));
1617 }
1618
1619 inline Detail::Temp
1620 operator*(Detail::Temp l, Detail::Temp r)
1621 {
1622 using namespace Detail;
1623 return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r));
1624 }
1625
1626 inline Detail::Temp
1627 operator/(Detail::Temp l, Detail::Temp r)
1628 {
1629 using namespace Detail;
1630 return NodePtr(new BinaryNode<std::divides<result_t> >(l, r));
1631 }
1632
1633 inline Detail::Temp
1634 operator%(Detail::Temp l, Detail::Temp r)
1635 {
1636 using namespace Detail;
1637 return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r));
1638 }
1639
1640 inline Detail::Temp
1641 operator-(Detail::Temp l)
1642 {
1643 using namespace Detail;
1644 return NodePtr(new UnaryNode<std::negate<result_t> >(l));
1645 }
1646
1647 template <typename T>
1648 inline Detail::Temp
1649 constant(T val)
1650 {
1651 using namespace Detail;
1652 return NodePtr(new ConstNode<T>(val));
1653 }
1654
1655 template <typename T>
1656 inline Detail::Temp
1657 functor(T &val)
1658 {
1659 using namespace Detail;
1660 return NodePtr(new FunctorNode<T>(val));
1661 }
1662
1663 template <typename T>
1664 inline Detail::Temp
1665 scalar(T &val)
1666 {
1667 using namespace Detail;
1668 return NodePtr(new ScalarNode<T>(val));
1669 }
1670
1671 inline Detail::Temp
1672 sum(Detail::Temp val)
1673 {
1674 using namespace Detail;
1675 return NodePtr(new SumNode<std::plus<result_t> >(val));
1676 }
1677
1678 extern bool PrintDescriptions;
1679
1680 } // namespace statistics
1681
1682 #endif // __STATISTICS_HH__