1 // $Id: Stats.cpp 80826 2008-03-04 14:51:23Z wotte $
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
17 ACE_Stats_Value::fractional_field (void) const
19 if (precision () == 0)
25 ACE_UINT32 field
= 10;
26 for (u_int i
= 0; i
< precision () - 1; ++i
)
36 ACE_Stats::sample (const ACE_INT32 value
)
38 if (samples_
.enqueue_tail (value
) == 0)
41 if (number_of_samples_
== 0)
43 // That's a lot of samples :-)
58 // Probably failed due to running out of memory when trying to
59 // enqueue the new value.
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_
);
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
,
107 ACE_Stats::std_dev (ACE_Stats_Value
&std_dev
,
108 const ACE_UINT32 scale_factor
)
110 if (number_of_samples_
<= 1)
113 std_dev
.fractional (0);
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
126 ACE_Stats_Value
avg (std_dev
.precision ());
128 avg
.scaled_value (mean_scaled
);
130 // Calculate the summation term, of squared differences from the
132 ACE_UINT64 sum_of_squares
= 0;
133 ACE_Unbounded_Queue_Iterator
<ACE_INT32
> i (samples_
);
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
) //
150 difference
= product
- mean_scaled
; //
154 difference
= mean_scaled
- product
; //
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
);
163 if (sum_of_squares
< original_sum_of_squares
)
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
,
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
186 scaled_variance
*= field
;
187 ACE_Stats_Value
unscaled_standard_deviation (std_dev
.precision ());
188 square_root (scaled_variance
,
189 unscaled_standard_deviation
);
192 quotient (unscaled_standard_deviation
,
193 scale_factor
* field
,
202 ACE_Stats::reset (void)
205 number_of_samples_
= 0u;
207 max_
= -0x8000 * 0x10000;
212 ACE_Stats::print_summary (const u_int precision
,
213 const ACE_UINT32 scale_factor
,
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];
222 for (int tmp_precision
= precision
;
223 ! overflow_
&& ! success
&& tmp_precision
>= 0;
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
);
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
))
247 ACE_OS::sprintf (std_dev_string
, format
, sd
.whole (), sd
.fractional ());
249 ACE_Stats_Value
minimum (tmp_precision
), maximum (tmp_precision
);
252 const ACE_UINT64
m (min_
);
253 quotient (m
, scale_factor
, minimum
);
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 ());
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
);
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_
));
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 */
290 ACE_Stats::quotient (const ACE_UINT64 dividend
,
291 const ACE_UINT32 divisor
,
292 ACE_Stats_Value
"ient
)
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) /
309 quotient
.fractional (static_cast<ACE_UINT32
> (
310 dividend
% divisor
* field
/ divisor
));
314 // No fractional portion is requested, so don't bother
316 quotient
.fractional (0);
321 ACE_Stats::quotient (const ACE_Stats_Value
÷nd
,
322 const ACE_UINT32 divisor
,
323 ACE_Stats_Value
"ient
)
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
);
338 // No fractional portion is requested, so don't bother
340 quotient
.fractional (0);
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
;
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
;
358 // Can't divide the interval any further.
362 // Multiply carefully to avoid overflow.
363 ACE_UINT64 mid_squared
= mid
; mid_squared
*= mid
;
364 if (mid_squared
== n
)
366 else if (mid_squared
< n
)
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 ();
387 // Do the 64-bit arithmetic carefully to avoid overflow.
388 ACE_UINT64 target
= n
;
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
;
403 difference
= target
- current
;
406 else if (current
<= target
)
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
);
420 // No fractional portion is requested, so don't bother
422 square_root
.fractional (0);
426 ACE_END_VERSIONED_NAMESPACE_DECL