libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
ave_deviation_meter_impl.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2002 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE {
20 
21  template<typename MeteredObjType>
22  inline tostream & __fastcall
23  operator<<(tostream &os, ave_deviation_meter<MeteredObjType> const &p) noexcept(false) {
24  os<<p.to_string();
25  return os;
26  }
27 
28  template<class MeteredObjType, class Fn>
29  inline ave_deviation_meter<MeteredObjType>
30  estimate_average_deviation(typename ave_deviation_meter<MeteredObjType>::value_type const computations, Fn fn) {
31  ave_deviation_meter<MeteredObjType> meter(fn.operator()());
32  for (auto i=typename ave_deviation_meter<MeteredObjType>::value_type();i<computations;++i) {
33  meter.update(fn.operator()());
34  }
35  return meter;
36  }
37 
38  template<class MeteredObjType, class Fn>
39  inline std::pair<ave_deviation_meter<MeteredObjType>, bool>
40  compute_average_deviation(double const target_deviation, typename ave_deviation_meter<MeteredObjType>::value_type const computations, Fn fn) {
41  std::pair<ave_deviation_meter<MeteredObjType>, bool> meter(ave_deviation_meter<MeteredObjType>(fn.operator()()), true);
42  for (auto i=typename ave_deviation_meter<MeteredObjType>::value_type();i<computations;++i) {
43  meter.first.update(fn.operator()());
44  if (meter.first.deviation_percentage()<=target_deviation) {
45  meter.second=false;
46  break;
47  }
48  }
49  return meter;
50  }
51 
52  template<typename MeteredObjType> inline void
53  ave_deviation_meter<MeteredObjType>::invariant() const noexcept(true) {
54 #ifndef _REENTRANT
55  assert(num_samples_>0 || ((minimum_>=std::numeric_limits<value_type>::max()) && (maximum_<=std::numeric_limits<value_type>::min()) && num_samples_==0));
56  assert((minimum_>=std::numeric_limits<value_type>::max()) || (minimum_<=arithmetic_mean_));
57  assert((maximum_<=std::numeric_limits<value_type>::min()) || (arithmetic_mean_<=maximum_));
58  assert(maximum_<=total_);
59 // assert(((minimum_>=std::numeric_limits<value_type>::max()) || (minimum_<=arithmetic_mean_)) || (fprintf(stdout, "minimum_=%lu, arithmetic_mean_=%g, num_samples_=%lu, cond=%i\n", minimum_, arithmetic_mean_, num_samples_, ((minimum_>=std::numeric_limits<value_type>::max()) || (minimum_<=arithmetic_mean_))) && 0));
60 // assert(((maximum_<=std::numeric_limits<value_type>::min()) || (arithmetic_mean_<=maximum_)) || (fprintf(stdout, "maximum_=%lu\n", maximum_) && 0));
61 // assert((maximum_<=total_) || (fprintf(stdout, "total_=%lu\n", total_) && 0));
62 #endif
63  }
64 
65  template<typename MeteredObjType> inline constexpr
66  ave_deviation_meter<MeteredObjType>::ave_deviation_meter() noexcept(true)
67  : num_samples_(),
70  total_(),
71  arithmetic_mean_(),
72  ave_deviation() {
73  }
74 
75  template<typename MeteredObjType> inline constexpr
76  ave_deviation_meter<MeteredObjType>::ave_deviation_meter(const value_type val) noexcept(true)
77  : num_samples_(1),
81  ave_deviation(std::abs(arithmetic_mean_)) {
82  }
83 
84  template<typename MeteredObjType> inline constexpr
85  ave_deviation_meter<MeteredObjType>::ave_deviation_meter(value_type const val, double const dev) noexcept(true)
86  : num_samples_(1),
88  total_(val),
90  ave_deviation(dev) {
91  }
92 
93  template<typename MeteredObjType> inline
94  ave_deviation_meter<MeteredObjType>::ave_deviation_meter(ave_deviation_meter const &rm) noexcept(true)
95  : num_samples_(rm.num_samples_),
97  total_(rm.total_),
98  arithmetic_mean_(rm.arithmetic_mean_),
99  ave_deviation(rm.ave_deviation) {
100  invariant();
101  }
102 
103  template<typename MeteredObjType> inline
104  ave_deviation_meter<MeteredObjType>::~ave_deviation_meter() noexcept(true) {
105  }
106 
107  template<typename MeteredObjType> inline ave_deviation_meter<MeteredObjType> &
108  ave_deviation_meter<MeteredObjType>::operator=(ave_deviation_meter const &rm) noexcept(true) {
109  num_samples_=rm.num_samples_;
110  minimum_=rm.minimum_;
111  maximum_=rm.maximum_;
112  total_=rm.total_;
113  arithmetic_mean_=rm.arithmetic_mean_;
114  ave_deviation=rm.ave_deviation;
115  invariant();
116  return *this;
117  }
118 
119  template<typename MeteredObjType> inline ave_deviation_meter<MeteredObjType> &
120  ave_deviation_meter<MeteredObjType>::operator+=(ave_deviation_meter const &rm) noexcept(true) {
121  invariant();
122  minimum_=std::min(minimum_, rm.minimum_);
123  maximum_=std::max(maximum_, rm.maximum_);
124  total_+=rm.total_;
125  if (num_samples_+rm.num_samples_) {
126  arithmetic_mean_=(arithmetic_mean_*num_samples_+rm.arithmetic_mean_*rm.num_samples_)/(num_samples_+rm.num_samples_);
127  }
128  ave_deviation=(ave_deviation+rm.ave_deviation)/2;
129  num_samples_+=rm.num_samples_;
130  minimum_=std::min(minimum_, rm.minimum_);
131  invariant();
132  return *this;
133  }
134 
135  template<typename MeteredObjType> inline ave_deviation_meter<MeteredObjType> &
136  ave_deviation_meter<MeteredObjType>::update(value_type const new_val) noexcept(true) {
137  invariant();
138  minimum_=std::min(minimum_, new_val);
139  maximum_=std::max(maximum_, new_val);
140  total_+=new_val;
141  unsigned long const old_num_samples_=num_samples_++;
142  value_type const old_arith_mean=arithmetic_mean_;
143  arithmetic_mean_=(arithmetic_mean_*old_num_samples_+new_val)/num_samples_;
144  if (old_num_samples_) {
145  ave_deviation=(std::abs(ave_deviation-(arithmetic_mean_-old_arith_mean))*old_num_samples_+std::abs(new_val-arithmetic_mean_))/num_samples_;
146  }
147  invariant();
148  return *this;
149  }
150 
151  template<typename MeteredObjType> inline constexpr typename ave_deviation_meter<MeteredObjType>::value_type
152  ave_deviation_meter<MeteredObjType>::min() const noexcept(true) {
153  return minimum_;
154  }
155 
156  template<typename MeteredObjType> inline constexpr typename ave_deviation_meter<MeteredObjType>::value_type
157  ave_deviation_meter<MeteredObjType>::arithmetic_mean() const noexcept(true) {
158  return static_cast<value_type>(arithmetic_mean_);
159  }
160 
161  template<typename MeteredObjType> inline constexpr typename ave_deviation_meter<MeteredObjType>::value_type
162  ave_deviation_meter<MeteredObjType>::max() const noexcept(true) {
163  return maximum_;
164  }
165 
166  template<typename MeteredObjType> inline constexpr typename ave_deviation_meter<MeteredObjType>::value_type
167  ave_deviation_meter<MeteredObjType>::total() const noexcept(true) {
168  return total_;
169  }
170 
171  template<typename MeteredObjType> inline constexpr double
172  ave_deviation_meter<MeteredObjType>::deviation() const noexcept(true) {
173  return ave_deviation;
174  }
175 
176  template<typename MeteredObjType> inline constexpr double
177  ave_deviation_meter<MeteredObjType>::deviation_percentage() const noexcept(true) {
178  return ave_deviation*100/arithmetic_mean_;
179  }
180 
181  template<typename MeteredObjType> inline constexpr unsigned short
182  ave_deviation_meter<MeteredObjType>::percent() const noexcept(true) {
183  return static_cast<unsigned short>(deviation_percentage());
184  }
185 
186  template<typename MeteredObjType> inline tstring
187  ave_deviation_meter<MeteredObjType>::to_string() const noexcept(false) {
188  invariant();
189  tostringstream os;
190  os
191  <<_T("[")<<minimum_<<_T(", ")<<value_type(arithmetic_mean_)<<_T(" ~(+/-")<<std::setprecision(2)<<value_type(deviation_percentage())<<_T("%), ")<<maximum_<<_T("]")
192  _T(", samples=")<<num_samples_
193  <<_T(", total=")<<total_;
194  return os.str();
195  }
196 
197  template<typename MeteredObjType> inline tstring
198  ave_deviation_meter<MeteredObjType>::to_csv() const noexcept(false) {
199  invariant();
200  tostringstream os;
201  os
202  <<_T("|")<<value_type(arithmetic_mean_)<<_T("|")<<std::setprecision(2)<<deviation_percentage()/100;
203  return os.str();
204  }
205 
206 } }