00001
00002
00003 #include "ace/Stats.h"
00004
00005 #if !defined (__ACE_INLINE__)
00006 # include "ace/Stats.inl"
00007 #endif
00008
00009 #include "ace/OS_NS_stdio.h"
00010 #include "ace/OS_NS_string.h"
00011
00012 ACE_RCSID(ace, Stats, "$Id: Stats.cpp 80826 2008-03-04 14:51:23Z wotte $")
00013
00014 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00015
00016 ACE_UINT32
00017 ACE_Stats_Value::fractional_field (void) const
00018 {
00019 if (precision () == 0)
00020 {
00021 return 1;
00022 }
00023 else
00024 {
00025 ACE_UINT32 field = 10;
00026 for (u_int i = 0; i < precision () - 1; ++i)
00027 {
00028 field *= 10;
00029 }
00030
00031 return field;
00032 }
00033 }
00034
00035 int
00036 ACE_Stats::sample (const ACE_INT32 value)
00037 {
00038 if (samples_.enqueue_tail (value) == 0)
00039 {
00040 ++number_of_samples_;
00041 if (number_of_samples_ == 0)
00042 {
00043
00044 overflow_ = EFAULT;
00045 return -1;
00046 }
00047
00048 if (value < min_)
00049 min_ = value;
00050
00051 if (value > max_)
00052 max_ = value;
00053
00054 return 0;
00055 }
00056 else
00057 {
00058
00059
00060 overflow_ = errno;
00061 return -1;
00062 }
00063 }
00064
00065 void
00066 ACE_Stats::mean (ACE_Stats_Value &m,
00067 const ACE_UINT32 scale_factor)
00068 {
00069 if (number_of_samples_ > 0)
00070 {
00071 #if defined ACE_LACKS_LONGLONG_T
00072
00073
00074
00075 const ACE_U_LongLong ACE_STATS_INTERNAL_OFFSET (0, 8);
00076 #else
00077 const ACE_UINT64 ACE_STATS_INTERNAL_OFFSET =
00078 ACE_UINT64_LITERAL (0x100000000);
00079 #endif
00080
00081 ACE_UINT64 sum = ACE_STATS_INTERNAL_OFFSET;
00082 ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_);
00083 while (! i.done ())
00084 {
00085 ACE_INT32 *sample;
00086 if (i.next (sample))
00087 {
00088 sum += *sample;
00089 i.advance ();
00090 }
00091 }
00092
00093
00094
00095 quotient (sum - ACE_STATS_INTERNAL_OFFSET,
00096 number_of_samples_ * scale_factor,
00097 m);
00098 }
00099 else
00100 {
00101 m.whole (0);
00102 m.fractional (0);
00103 }
00104 }
00105
00106 int
00107 ACE_Stats::std_dev (ACE_Stats_Value &std_dev,
00108 const ACE_UINT32 scale_factor)
00109 {
00110 if (number_of_samples_ <= 1)
00111 {
00112 std_dev.whole (0);
00113 std_dev.fractional (0);
00114 }
00115 else
00116 {
00117 const ACE_UINT32 field = std_dev.fractional_field ();
00118
00119
00120
00121
00122
00123 ACE_UINT64 mean_scaled;
00124
00125
00126 ACE_Stats_Value avg (std_dev.precision ());
00127 mean (avg, 1u);
00128 avg.scaled_value (mean_scaled);
00129
00130
00131
00132 ACE_UINT64 sum_of_squares = 0;
00133 ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_);
00134 while (! i.done ())
00135 {
00136 ACE_INT32 *sample;
00137 if (i.next (sample))
00138 {
00139 const ACE_UINT64 original_sum_of_squares = sum_of_squares;
00140
00141
00142
00143 const ACE_UINT64 product (*sample * field);
00144
00145 ACE_UINT64 difference;
00146
00147
00148 if (product >= mean_scaled)
00149 {
00150 difference = product - mean_scaled;
00151 }
00152 else
00153 {
00154 difference = mean_scaled - product;
00155 }
00156
00157
00158
00159
00160 sum_of_squares += difference * ACE_U64_TO_U32 (difference);
00161 i.advance ();
00162
00163 if (sum_of_squares < original_sum_of_squares)
00164 {
00165 overflow_ = ENOSPC;
00166 return -1;
00167 }
00168 }
00169 }
00170
00171
00172
00173
00174 ACE_Stats_Value variance (std_dev.precision ());
00175 quotient (sum_of_squares,
00176 (number_of_samples_ - 1) * field * field,
00177 variance);
00178
00179
00180
00181 ACE_UINT64 scaled_variance;
00182 variance.scaled_value (scaled_variance);
00183
00184
00185
00186 scaled_variance *= field;
00187 ACE_Stats_Value unscaled_standard_deviation (std_dev.precision ());
00188 square_root (scaled_variance,
00189 unscaled_standard_deviation);
00190
00191
00192 quotient (unscaled_standard_deviation,
00193 scale_factor * field,
00194 std_dev);
00195 }
00196
00197 return 0;
00198 }
00199
00200
00201 void
00202 ACE_Stats::reset (void)
00203 {
00204 overflow_ = 0u;
00205 number_of_samples_ = 0u;
00206 min_ = 0x7FFFFFFF;
00207 max_ = -0x8000 * 0x10000;
00208 samples_.reset ();
00209 }
00210
00211 int
00212 ACE_Stats::print_summary (const u_int precision,
00213 const ACE_UINT32 scale_factor,
00214 FILE *file) const
00215 {
00216 ACE_TCHAR mean_string [128];
00217 ACE_TCHAR std_dev_string [128];
00218 ACE_TCHAR min_string [128];
00219 ACE_TCHAR max_string [128];
00220 int success = 0;
00221
00222 for (int tmp_precision = precision;
00223 ! overflow_ && ! success && tmp_precision >= 0;
00224 --tmp_precision)
00225 {
00226
00227 ACE_TCHAR format[32];
00228 if (tmp_precision == 0)
00229 ACE_OS::sprintf (format, ACE_TEXT ("%%%d"), tmp_precision);
00230 else
00231 ACE_OS::sprintf (format, ACE_TEXT ("%%d.%%0%du"), tmp_precision);
00232
00233 ACE_Stats_Value u (tmp_precision);
00234 ((ACE_Stats *) this)->mean (u, scale_factor);
00235 ACE_OS::sprintf (mean_string, format, u.whole (), u.fractional ());
00236
00237 ACE_Stats_Value sd (tmp_precision);
00238 if (((ACE_Stats *) this)->std_dev (sd, scale_factor))
00239 {
00240 success = 0;
00241 continue;
00242 }
00243 else
00244 {
00245 success = 1;
00246 }
00247 ACE_OS::sprintf (std_dev_string, format, sd.whole (), sd.fractional ());
00248
00249 ACE_Stats_Value minimum (tmp_precision), maximum (tmp_precision);
00250 if (min_ != 0)
00251 {
00252 const ACE_UINT64 m (min_);
00253 quotient (m, scale_factor, minimum);
00254 }
00255 if (max_ != 0)
00256 {
00257 const ACE_UINT64 m (max_);
00258 quotient (m, scale_factor, maximum);
00259 }
00260 ACE_OS::sprintf (min_string, format,
00261 minimum.whole (), minimum.fractional ());
00262 ACE_OS::sprintf (max_string, format,
00263 maximum.whole (), maximum.fractional ());
00264 }
00265
00266 if (success == 1)
00267 {
00268 ACE_OS::fprintf (file, ACE_TEXT ("samples: %u (%s - %s); mean: ")
00269 ACE_TEXT ("%s; std dev: %s\n"),
00270 samples (), min_string, max_string,
00271 mean_string, std_dev_string);
00272 return 0;
00273 }
00274 else
00275 {
00276 #if !defined (ACE_HAS_WINCE)
00277 ACE_OS::fprintf (file,
00278 ACE_TEXT ("ACE_Stats::print_summary: OVERFLOW: %s\n"),
00279 ACE_OS::strerror (overflow_));
00280 #else
00281
00282 ACE_OS::fprintf (file,
00283 ACE_TEXT ("ACE_Stats::print_summary: OVERFLOW\n"));
00284 #endif
00285 return -1;
00286 }
00287 }
00288
00289 void
00290 ACE_Stats::quotient (const ACE_UINT64 dividend,
00291 const ACE_UINT32 divisor,
00292 ACE_Stats_Value "ient)
00293 {
00294
00295 quotient.whole (static_cast<ACE_UINT32> (divisor == 0
00296 ? 0 : dividend / divisor));
00297
00298 if (quotient.precision () > 0 || divisor == 0)
00299 {
00300 const ACE_UINT32 field = quotient.fractional_field ();
00301
00302
00303
00304
00305
00306
00307
00308
00309 quotient.fractional (static_cast<ACE_UINT32> (
00310 dividend % divisor * field / divisor));
00311 }
00312 else
00313 {
00314
00315
00316 quotient.fractional (0);
00317 }
00318 }
00319
00320 void
00321 ACE_Stats::quotient (const ACE_Stats_Value ÷nd,
00322 const ACE_UINT32 divisor,
00323 ACE_Stats_Value "ient)
00324 {
00325
00326 quotient.whole (divisor == 0 ? 0 : dividend.whole () / divisor);
00327
00328 if (quotient.precision () > 0 || divisor == 0)
00329 {
00330 const ACE_UINT32 field = quotient.fractional_field ();
00331
00332
00333 quotient.fractional (dividend.whole () % divisor * field / divisor +
00334 dividend.fractional () / divisor);
00335 }
00336 else
00337 {
00338
00339
00340 quotient.fractional (0);
00341 }
00342 }
00343
00344 void
00345 ACE_Stats::square_root (const ACE_UINT64 n,
00346 ACE_Stats_Value &square_root)
00347 {
00348 ACE_UINT32 floor = 0;
00349 ACE_UINT32 ceiling = 0xFFFFFFFFu;
00350 ACE_UINT32 mid = 0;
00351 u_int i;
00352
00353
00354 for (i = 0; i < 64; ++i)
00355 {
00356 mid = (ceiling - floor) / 2 + floor;
00357 if (floor == mid)
00358
00359 break;
00360 else
00361 {
00362
00363 ACE_UINT64 mid_squared = mid; mid_squared *= mid;
00364 if (mid_squared == n)
00365 break;
00366 else if (mid_squared < n)
00367 floor = mid;
00368 else
00369 ceiling = mid;
00370 }
00371 }
00372
00373 square_root.whole (mid);
00374 ACE_UINT64 mid_squared = mid; mid_squared *= mid;
00375
00376 if (square_root.precision () && mid_squared < n)
00377 {
00378
00379
00380
00381 const ACE_UINT32 field = square_root.fractional_field ();
00382
00383 floor = 0;
00384 ceiling = field;
00385 mid = 0;
00386
00387
00388 ACE_UINT64 target = n;
00389 target *= field;
00390 target *= field;
00391
00392 ACE_UINT64 difference = 0;
00393
00394 for (i = 0; i < square_root.precision (); ++i)
00395 {
00396 mid = (ceiling - floor) / 2 + floor;
00397
00398 ACE_UINT64 current = square_root.whole () * field + mid;
00399 current *= square_root.whole () * field + mid;
00400
00401 if (floor == mid)
00402 {
00403 difference = target - current;
00404 break;
00405 }
00406 else if (current <= target)
00407 floor = mid;
00408 else
00409 ceiling = mid;
00410 }
00411
00412
00413 ACE_UINT64 next = square_root.whole () * field + mid + 1;
00414 next *= square_root.whole () * field + mid + 1;
00415
00416 square_root.fractional (next - target < difference ? mid + 1 : mid);
00417 }
00418 else
00419 {
00420
00421
00422 square_root.fractional (0);
00423 }
00424 }
00425
00426 ACE_END_VERSIONED_NAMESPACE_DECL