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 83735 2008-11-14 09:41:52Z johnnyw $")
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 ACE_OS::fprintf (file,
00277 ACE_TEXT ("ACE_Stats::print_summary: OVERFLOW: %s\n"),
00278 ACE_OS::strerror (overflow_));
00279
00280 return -1;
00281 }
00282 }
00283
00284 void
00285 ACE_Stats::quotient (const ACE_UINT64 dividend,
00286 const ACE_UINT32 divisor,
00287 ACE_Stats_Value "ient)
00288 {
00289
00290 quotient.whole (static_cast<ACE_UINT32> (divisor == 0
00291 ? 0 : dividend / divisor));
00292
00293 if (quotient.precision () > 0 || divisor == 0)
00294 {
00295 const ACE_UINT32 field = quotient.fractional_field ();
00296
00297
00298
00299
00300
00301
00302
00303
00304 quotient.fractional (static_cast<ACE_UINT32> (
00305 dividend % divisor * field / divisor));
00306 }
00307 else
00308 {
00309
00310
00311 quotient.fractional (0);
00312 }
00313 }
00314
00315 void
00316 ACE_Stats::quotient (const ACE_Stats_Value ÷nd,
00317 const ACE_UINT32 divisor,
00318 ACE_Stats_Value "ient)
00319 {
00320
00321 quotient.whole (divisor == 0 ? 0 : dividend.whole () / divisor);
00322
00323 if (quotient.precision () > 0 || divisor == 0)
00324 {
00325 const ACE_UINT32 field = quotient.fractional_field ();
00326
00327
00328 quotient.fractional (dividend.whole () % divisor * field / divisor +
00329 dividend.fractional () / divisor);
00330 }
00331 else
00332 {
00333
00334
00335 quotient.fractional (0);
00336 }
00337 }
00338
00339 void
00340 ACE_Stats::square_root (const ACE_UINT64 n,
00341 ACE_Stats_Value &square_root)
00342 {
00343 ACE_UINT32 floor = 0;
00344 ACE_UINT32 ceiling = 0xFFFFFFFFu;
00345 ACE_UINT32 mid = 0;
00346 u_int i;
00347
00348
00349 for (i = 0; i < 64; ++i)
00350 {
00351 mid = (ceiling - floor) / 2 + floor;
00352 if (floor == mid)
00353
00354 break;
00355 else
00356 {
00357
00358 ACE_UINT64 mid_squared = mid; mid_squared *= mid;
00359 if (mid_squared == n)
00360 break;
00361 else if (mid_squared < n)
00362 floor = mid;
00363 else
00364 ceiling = mid;
00365 }
00366 }
00367
00368 square_root.whole (mid);
00369 ACE_UINT64 mid_squared = mid; mid_squared *= mid;
00370
00371 if (square_root.precision () && mid_squared < n)
00372 {
00373
00374
00375
00376 const ACE_UINT32 field = square_root.fractional_field ();
00377
00378 floor = 0;
00379 ceiling = field;
00380 mid = 0;
00381
00382
00383 ACE_UINT64 target = n;
00384 target *= field;
00385 target *= field;
00386
00387 ACE_UINT64 difference = 0;
00388
00389 for (i = 0; i < square_root.precision (); ++i)
00390 {
00391 mid = (ceiling - floor) / 2 + floor;
00392
00393 ACE_UINT64 current = square_root.whole () * field + mid;
00394 current *= square_root.whole () * field + mid;
00395
00396 if (floor == mid)
00397 {
00398 difference = target - current;
00399 break;
00400 }
00401 else if (current <= target)
00402 floor = mid;
00403 else
00404 ceiling = mid;
00405 }
00406
00407
00408 ACE_UINT64 next = square_root.whole () * field + mid + 1;
00409 next *= square_root.whole () * field + mid + 1;
00410
00411 square_root.fractional (next - target < difference ? mid + 1 : mid);
00412 }
00413 else
00414 {
00415
00416
00417 square_root.fractional (0);
00418 }
00419 }
00420
00421 ACE_END_VERSIONED_NAMESPACE_DECL