Line data Source code
1 : /* 2 : * 3 : * 4 : * Distributed under the OpenDDS License. 5 : * See: http://www.opendds.org/license.html 6 : */ 7 : 8 : #ifndef OPENDDS_DCPS_STATS_T_H 9 : #define OPENDDS_DCPS_STATS_T_H 10 : 11 : #if !defined (ACE_LACKS_PRAGMA_ONCE) 12 : #pragma once 13 : #endif /* ACE_LACKS_PRAGMA_ONCE */ 14 : 15 : #include "DataCollector_T.h" 16 : 17 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 18 : 19 : namespace OpenDDS { 20 : namespace DCPS { 21 : 22 : /** 23 : * @class Stats<DataType> 24 : * 25 : * @brief Accumulates average, n, variance, minimum, and maximum statistics 26 : */ 27 : template<typename DataType> 28 : class Stats : public DataCollector<DataType> { 29 : public: 30 : /// Default constructor. 31 : Stats(unsigned int amount = 0, 32 : typename DataCollector<DataType>::OnFull type = 33 : DataCollector<DataType>::KeepOldest); 34 : 35 : Stats(const Stats&); 36 : 37 : /// Default bitwise copy is sufficient. 38 : 39 : /// Assignment operator 40 : Stats& operator=(const Stats& rhs); 41 : 42 : /// Reset statistics to nil. 43 : void reset(); 44 : 45 : /** 46 : * Accumulate a new value. 47 : * @param value the new value to be accumulated. 48 : */ 49 : void add(DataType value); 50 : 51 : /// Calculate the average value. 52 : long double mean() const; 53 : 54 : /// Calculate the variance value. 55 : long double var() const; 56 : 57 : /// Access the minimum value. 58 : DataType minimum() const; 59 : 60 : /// Access the maximum value. 61 : DataType maximum() const; 62 : 63 : /// Access the number of values accumulated. 64 : unsigned long n() const; 65 : 66 : private: 67 : // Direct statistics. 68 : unsigned long n_; 69 : DataType minimum_; 70 : DataType maximum_; 71 : 72 : // Internal variables have the largest range and highest precision possible. 73 : long double an_ ; 74 : long double bn_ ; 75 : long double cn_ ; 76 : long double variance_ ; 77 : }; 78 : 79 : template<typename DataType> 80 : inline 81 0 : Stats<DataType>::Stats( 82 : unsigned int amount, 83 0 : typename DataCollector<DataType>::OnFull type) : DataCollector<DataType>(amount, type) 84 : { 85 0 : this->reset(); 86 0 : } 87 : 88 : template<typename DataType> 89 : inline 90 0 : Stats<DataType>::Stats(const Stats<DataType>& v) : DataCollector<DataType>(v), 91 0 : n_(v.n_), 92 0 : minimum_(v.minimum_), 93 0 : maximum_(v.maximum_), 94 0 : an_(v.an_), 95 0 : bn_(v.bn_), 96 0 : cn_(v.cn_), 97 0 : variance_(v.variance_) 98 : { 99 0 : } 100 : 101 : template<typename DataType> 102 : inline 103 : Stats<DataType>& 104 : Stats<DataType>::operator=(const Stats& rhs) 105 : { 106 : this->n_ = rhs.n_; 107 : this->minimum_ = rhs.minimum_; 108 : this->maximum_ = rhs.maximum_; 109 : this->an_ = rhs.an_ ; 110 : this->bn_ = rhs.bn_ ; 111 : this->cn_ = rhs.cn_ ; 112 : this->variance_ = rhs.variance_ ; 113 : return *this; 114 : } 115 : 116 : template<typename DataType> 117 : inline 118 : void 119 0 : Stats<DataType>::reset() 120 : { 121 0 : this->n_ = 0; 122 0 : this->minimum_ = static_cast<DataType>(0); 123 0 : this->maximum_ = static_cast<DataType>(0); 124 0 : this->an_ = 0.0; 125 0 : this->bn_ = 0.0; 126 0 : this->cn_ = 0.0; 127 0 : this->variance_ = 0.0; 128 0 : } 129 : 130 : template<typename DataType> 131 : inline 132 : void 133 0 : Stats<DataType>::add(DataType value) 134 : { 135 : // Save the raw value if configured to. 136 0 : this->collect(value); 137 : 138 : // Slide rule style calculations. 139 : long double term; 140 : 141 : // 142 : // V(N+1) = V(N) * N^2 / (N+1)^2 143 : // + A(N) 144 : // - B(N) * X(N+1) 145 : // + C(N) * X(N+1)^2 146 : // 147 0 : this->variance_ /= (this->n_ + 1); 148 0 : this->variance_ *= this->n_; 149 0 : this->variance_ /= (this->n_ + 1); 150 0 : this->variance_ *= this->n_; 151 : 152 0 : term = static_cast<long double>(value); 153 0 : this->variance_ += this->an_; 154 0 : this->variance_ -= this->bn_ * term; 155 0 : this->variance_ += this->cn_ * term * term; 156 : 157 : // The internal variable updates _must_ follow the variance update. 158 : 159 : // 160 : // A(N+1) = (A(N) * (N+1)^2 / (N+2)^2) + (X(N+1) / (N+2)^2) 161 : // 162 0 : this->an_ /= (this->n_ + 2); 163 0 : this->an_ *= (this->n_ + 1); 164 0 : this->an_ /= (this->n_ + 2); 165 0 : this->an_ *= (this->n_ + 1); 166 : 167 : // term = static_cast<long double>( value); 168 0 : term *= term; 169 0 : term /= (this->n_ + 2); 170 0 : term /= (this->n_ + 2); 171 0 : this->an_ += term; 172 : 173 : // 174 : // B(N+1) = (B(N) * (N+1)^2 / (N+2)^2) + (2 * X(N+1) / (N+2)^2) 175 : // 176 0 : this->bn_ /= (this->n_ + 2); 177 0 : this->bn_ *= (this->n_ + 1); 178 0 : this->bn_ /= (this->n_ + 2); 179 0 : this->bn_ *= (this->n_ + 1); 180 : 181 0 : term = static_cast<long double>(value * 2); 182 0 : term /= (this->n_ + 2); 183 0 : term /= (this->n_ + 2); 184 0 : this->bn_ += term; 185 : 186 : // 187 : // C(N+1) = (N+1) / (N+2)^2 188 : // 189 0 : this->cn_ = this->n_ + 1; 190 0 : this->cn_ /= (this->n_ + 2); 191 0 : this->cn_ /= (this->n_ + 2); 192 : 193 0 : if ((this->n_ == 0) || (value < this->minimum_)) { 194 0 : this->minimum_ = value; 195 : } 196 : 197 0 : if ((this->n_ == 0) || (value > this->maximum_)) { 198 0 : this->maximum_ = value; 199 : } 200 : 201 0 : this->n_ += 1; // Must follow internal variable updates. 202 0 : } 203 : 204 : template<typename DataType> 205 : inline 206 : long double 207 0 : Stats<DataType>::mean() const 208 : { 209 0 : if (this->n_ == 0) { 210 : /// @TODO: return qNaN with no data. 211 0 : return 0.0; 212 : } 213 : 214 : // Slide rule style calculations. 215 : 216 : // 217 : // MEAN = B(N) * (N+1)^2 / (2 * N) 218 : // 219 0 : long double average = this->bn_ / 2.0 ; 220 : 221 0 : average *= (this->n_ + 1) ; 222 0 : average /= this->n_ ; 223 0 : average *= (this->n_ + 1) ; 224 : 225 0 : return average ; 226 : } 227 : 228 : template<typename DataType> 229 : inline 230 : long double 231 0 : Stats<DataType>::var() const 232 : { 233 0 : return this->variance_ ; 234 : } 235 : 236 : template<typename DataType> 237 : inline 238 : DataType 239 0 : Stats<DataType>::minimum() const 240 : { 241 : /// @TODO: return qNaN with no data. 242 0 : return (this->n_ == 0)? 0: this->minimum_; 243 : } 244 : 245 : template<typename DataType> 246 : inline 247 : DataType 248 0 : Stats<DataType>::maximum() const 249 : { 250 : /// @TODO: return qNaN with no data. 251 0 : return (this->n_ == 0)? 0: this->maximum_; 252 : } 253 : 254 : template<typename DataType> 255 : inline 256 : unsigned long 257 0 : Stats<DataType>::n() const 258 : { 259 0 : return this->n_; 260 : } 261 : 262 : } // namespace DCPS 263 : } // namespace OpenDDS 264 : 265 : OPENDDS_END_VERSIONED_NAMESPACE_DECL 266 : 267 : #endif // OPENDDS_DCPS_STATS_T_H