[7297] Fixed profession spells sorting in trainer spell list at client.
[getmangos.git] / dep / ACE_wrappers / ace / Stats.cpp
blobbb6dcf0a6a818b5523c6ed96e2d1e66b87f0657c
1 // $Id: Stats.cpp 80826 2008-03-04 14:51:23Z wotte $
3 #include "ace/Stats.h"
5 #if !defined (__ACE_INLINE__)
6 # include "ace/Stats.inl"
7 #endif /* __ACE_INLINE__ */
9 #include "ace/OS_NS_stdio.h"
10 #include "ace/OS_NS_string.h"
12 ACE_RCSID(ace, Stats, "$Id: Stats.cpp 80826 2008-03-04 14:51:23Z wotte $")
14 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
16 ACE_UINT32
17 ACE_Stats_Value::fractional_field (void) const
19 if (precision () == 0)
21 return 1;
23 else
25 ACE_UINT32 field = 10;
26 for (u_int i = 0; i < precision () - 1; ++i)
28 field *= 10;
31 return field;
35 int
36 ACE_Stats::sample (const ACE_INT32 value)
38 if (samples_.enqueue_tail (value) == 0)
40 ++number_of_samples_;
41 if (number_of_samples_ == 0)
43 // That's a lot of samples :-)
44 overflow_ = EFAULT;
45 return -1;
48 if (value < min_)
49 min_ = value;
51 if (value > max_)
52 max_ = value;
54 return 0;
56 else
58 // Probably failed due to running out of memory when trying to
59 // enqueue the new value.
60 overflow_ = errno;
61 return -1;
65 void
66 ACE_Stats::mean (ACE_Stats_Value &m,
67 const ACE_UINT32 scale_factor)
69 if (number_of_samples_ > 0)
71 #if defined ACE_LACKS_LONGLONG_T
72 // If ACE_LACKS_LONGLONG_T, then ACE_UINT64 is a user-defined class.
73 // To prevent having to construct a static of that class, declare it
74 // on the stack, and construct it, in each function that needs it.
75 const ACE_U_LongLong ACE_STATS_INTERNAL_OFFSET (0, 8);
76 #else /* ! ACE_LACKS_LONGLONG_T */
77 const ACE_UINT64 ACE_STATS_INTERNAL_OFFSET =
78 ACE_UINT64_LITERAL (0x100000000);
79 #endif /* ! ACE_LACKS_LONGLONG_T */
81 ACE_UINT64 sum = ACE_STATS_INTERNAL_OFFSET;
82 ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_);
83 while (! i.done ())
85 ACE_INT32 *sample;
86 if (i.next (sample))
88 sum += *sample;
89 i.advance ();
93 // sum_ was initialized with ACE_STATS_INTERNAL_OFFSET, so
94 // subtract that off here.
95 quotient (sum - ACE_STATS_INTERNAL_OFFSET,
96 number_of_samples_ * scale_factor,
97 m);
99 else
101 m.whole (0);
102 m.fractional (0);
107 ACE_Stats::std_dev (ACE_Stats_Value &std_dev,
108 const ACE_UINT32 scale_factor)
110 if (number_of_samples_ <= 1)
112 std_dev.whole (0);
113 std_dev.fractional (0);
115 else
117 const ACE_UINT32 field = std_dev.fractional_field ();
119 // The sample standard deviation is:
121 // sqrt (sum (sample_i - mean)^2 / (number_of_samples_ - 1))
123 ACE_UINT64 mean_scaled;
124 // Calculate the mean, scaled, so that we don't lose its
125 // precision.
126 ACE_Stats_Value avg (std_dev.precision ());
127 mean (avg, 1u);
128 avg.scaled_value (mean_scaled);
130 // Calculate the summation term, of squared differences from the
131 // mean.
132 ACE_UINT64 sum_of_squares = 0;
133 ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_);
134 while (! i.done ())
136 ACE_INT32 *sample;
137 if (i.next (sample))
139 const ACE_UINT64 original_sum_of_squares = sum_of_squares;
141 // Scale up by field width so that we don't lose the
142 // precision of the mean. Carefully . . .
143 const ACE_UINT64 product (*sample * field);
145 ACE_UINT64 difference;
146 // NOTE: please do not reformat this code! It //
147 // works with the Diab compiler the way it is! //
148 if (product >= mean_scaled) //
149 { //
150 difference = product - mean_scaled; //
151 } //
152 else //
153 { //
154 difference = mean_scaled - product; //
155 } //
156 // NOTE: please do not reformat this code! It //
157 // works with the Diab compiler the way it is! //
159 // Square using 64-bit arithmetic.
160 sum_of_squares += difference * ACE_U64_TO_U32 (difference);
161 i.advance ();
163 if (sum_of_squares < original_sum_of_squares)
165 overflow_ = ENOSPC;
166 return -1;
171 // Divide the summation by (number_of_samples_ - 1), to get the
172 // variance. In addition, scale the variance down to undo the
173 // mean scaling above. Otherwise, it can get too big.
174 ACE_Stats_Value variance (std_dev.precision ());
175 quotient (sum_of_squares,
176 (number_of_samples_ - 1) * field * field,
177 variance);
179 // Take the square root of the variance to get the standard
180 // deviation. First, scale up . . .
181 ACE_UINT64 scaled_variance;
182 variance.scaled_value (scaled_variance);
184 // And scale up, once more, because we'll be taking the square
185 // root.
186 scaled_variance *= field;
187 ACE_Stats_Value unscaled_standard_deviation (std_dev.precision ());
188 square_root (scaled_variance,
189 unscaled_standard_deviation);
191 // Unscale.
192 quotient (unscaled_standard_deviation,
193 scale_factor * field,
194 std_dev);
197 return 0;
201 void
202 ACE_Stats::reset (void)
204 overflow_ = 0u;
205 number_of_samples_ = 0u;
206 min_ = 0x7FFFFFFF;
207 max_ = -0x8000 * 0x10000;
208 samples_.reset ();
212 ACE_Stats::print_summary (const u_int precision,
213 const ACE_UINT32 scale_factor,
214 FILE *file) const
216 ACE_TCHAR mean_string [128];
217 ACE_TCHAR std_dev_string [128];
218 ACE_TCHAR min_string [128];
219 ACE_TCHAR max_string [128];
220 int success = 0;
222 for (int tmp_precision = precision;
223 ! overflow_ && ! success && tmp_precision >= 0;
224 --tmp_precision)
226 // Build a format string, in case the C library doesn't support %*u.
227 ACE_TCHAR format[32];
228 if (tmp_precision == 0)
229 ACE_OS::sprintf (format, ACE_TEXT ("%%%d"), tmp_precision);
230 else
231 ACE_OS::sprintf (format, ACE_TEXT ("%%d.%%0%du"), tmp_precision);
233 ACE_Stats_Value u (tmp_precision);
234 ((ACE_Stats *) this)->mean (u, scale_factor);
235 ACE_OS::sprintf (mean_string, format, u.whole (), u.fractional ());
237 ACE_Stats_Value sd (tmp_precision);
238 if (((ACE_Stats *) this)->std_dev (sd, scale_factor))
240 success = 0;
241 continue;
243 else
245 success = 1;
247 ACE_OS::sprintf (std_dev_string, format, sd.whole (), sd.fractional ());
249 ACE_Stats_Value minimum (tmp_precision), maximum (tmp_precision);
250 if (min_ != 0)
252 const ACE_UINT64 m (min_);
253 quotient (m, scale_factor, minimum);
255 if (max_ != 0)
257 const ACE_UINT64 m (max_);
258 quotient (m, scale_factor, maximum);
260 ACE_OS::sprintf (min_string, format,
261 minimum.whole (), minimum.fractional ());
262 ACE_OS::sprintf (max_string, format,
263 maximum.whole (), maximum.fractional ());
266 if (success == 1)
268 ACE_OS::fprintf (file, ACE_TEXT ("samples: %u (%s - %s); mean: ")
269 ACE_TEXT ("%s; std dev: %s\n"),
270 samples (), min_string, max_string,
271 mean_string, std_dev_string);
272 return 0;
274 else
276 #if !defined (ACE_HAS_WINCE)
277 ACE_OS::fprintf (file,
278 ACE_TEXT ("ACE_Stats::print_summary: OVERFLOW: %s\n"),
279 ACE_OS::strerror (overflow_));
280 #else
281 // WinCE doesn't have strerror ;(
282 ACE_OS::fprintf (file,
283 ACE_TEXT ("ACE_Stats::print_summary: OVERFLOW\n"));
284 #endif /* ACE_HAS_WINCE */
285 return -1;
289 void
290 ACE_Stats::quotient (const ACE_UINT64 dividend,
291 const ACE_UINT32 divisor,
292 ACE_Stats_Value &quotient)
294 // The whole part of the division comes from simple integer division.
295 quotient.whole (static_cast<ACE_UINT32> (divisor == 0
296 ? 0 : dividend / divisor));
298 if (quotient.precision () > 0 || divisor == 0)
300 const ACE_UINT32 field = quotient.fractional_field ();
302 // Fractional = (dividend % divisor) * 10^precision / divisor
304 // It would be nice to add round-up term:
305 // Fractional = (dividend % divisor) * 10^precision / divisor +
306 // 10^precision/2 / 10^precision
307 // = ((dividend % divisor) * 10^precision + divisor) /
308 // divisor
309 quotient.fractional (static_cast<ACE_UINT32> (
310 dividend % divisor * field / divisor));
312 else
314 // No fractional portion is requested, so don't bother
315 // calculating it.
316 quotient.fractional (0);
320 void
321 ACE_Stats::quotient (const ACE_Stats_Value &dividend,
322 const ACE_UINT32 divisor,
323 ACE_Stats_Value &quotient)
325 // The whole part of the division comes from simple integer division.
326 quotient.whole (divisor == 0 ? 0 : dividend.whole () / divisor);
328 if (quotient.precision () > 0 || divisor == 0)
330 const ACE_UINT32 field = quotient.fractional_field ();
332 // Fractional = (dividend % divisor) * 10^precision / divisor.
333 quotient.fractional (dividend.whole () % divisor * field / divisor +
334 dividend.fractional () / divisor);
336 else
338 // No fractional portion is requested, so don't bother
339 // calculating it.
340 quotient.fractional (0);
344 void
345 ACE_Stats::square_root (const ACE_UINT64 n,
346 ACE_Stats_Value &square_root)
348 ACE_UINT32 floor = 0;
349 ACE_UINT32 ceiling = 0xFFFFFFFFu;
350 ACE_UINT32 mid = 0;
351 u_int i;
353 // The maximum number of iterations is log_2 (2^64) == 64.
354 for (i = 0; i < 64; ++i)
356 mid = (ceiling - floor) / 2 + floor;
357 if (floor == mid)
358 // Can't divide the interval any further.
359 break;
360 else
362 // Multiply carefully to avoid overflow.
363 ACE_UINT64 mid_squared = mid; mid_squared *= mid;
364 if (mid_squared == n)
365 break;
366 else if (mid_squared < n)
367 floor = mid;
368 else
369 ceiling = mid;
373 square_root.whole (mid);
374 ACE_UINT64 mid_squared = mid; mid_squared *= mid;
376 if (square_root.precision () && mid_squared < n)
378 // (mid * 10^precision + fractional)^2 ==
379 // n^2 * 10^(precision * 2)
381 const ACE_UINT32 field = square_root.fractional_field ();
383 floor = 0;
384 ceiling = field;
385 mid = 0;
387 // Do the 64-bit arithmetic carefully to avoid overflow.
388 ACE_UINT64 target = n;
389 target *= field;
390 target *= field;
392 ACE_UINT64 difference = 0;
394 for (i = 0; i < square_root.precision (); ++i)
396 mid = (ceiling - floor) / 2 + floor;
398 ACE_UINT64 current = square_root.whole () * field + mid;
399 current *= square_root.whole () * field + mid;
401 if (floor == mid)
403 difference = target - current;
404 break;
406 else if (current <= target)
407 floor = mid;
408 else
409 ceiling = mid;
412 // Check to see if the fractional part should be one greater.
413 ACE_UINT64 next = square_root.whole () * field + mid + 1;
414 next *= square_root.whole () * field + mid + 1;
416 square_root.fractional (next - target < difference ? mid + 1 : mid);
418 else
420 // No fractional portion is requested, so don't bother
421 // calculating it.
422 square_root.fractional (0);
426 ACE_END_VERSIONED_NAMESPACE_DECL