Copyright (C) IBM Corp. 2007
Author(s): Charles P. Wright <cpwright@us.ibm.com>

/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  Authors : Benjamin GAUTHIER - 24 Mar 2004
 *            Joseph BANINO
 *            Olivier JACQUES
 *            Richard GAYRAUD
 *            From Hewlett Packard Company.
 *            Wolfgang Beck
 *
 */
Index: sipp.2007-02-28/stat.cpp
===================================================================
--- sipp.2007-02-28.orig/stat.cpp
+++ sipp.2007-02-28/stat.cpp
@@ -51,11 +51,11 @@
 #define DISPLAY_VAL_RATEF_COL(T1, V1, V2)\
   fprintf(f,"  %-22.22s | %8.3f cps              | %8.3f cps             \r\n", T1, V1, V2)
 #define DISPLAY_2VAL(T1, V1, V2)\
-  fprintf(f,"  %-22.22s | %8d                  | %8d                 \r\n", T1, V1, V2)
+  fprintf(f,"  %-22.22s | %8llu                  | %8llu                 \r\n", T1, V1, V2)
 #define DISPLAY_CUMUL(T1, V1)\
-  fprintf(f,"  %-22.22s |                           | %8d                 \r\n", T1, V1)
+  fprintf(f,"  %-22.22s |                           | %8llu                 \r\n", T1, V1)
 #define DISPLAY_PERIO(T1, V1)\
-  fprintf(f,"  %-22.22s | %8d                  |                          \r\n", T1, V1)
+  fprintf(f,"  %-22.22s | %8llu                  |                          \r\n", T1, V1)
 #define DISPLAY_VALF(T1, V1)\
   fprintf(f,"  %-22.22s | %8.3f ms                                          \r\n", T1, V1)
 #define DISPLAY_VAL_RATEF(T1, V1)\
@@ -675,38 +675,37 @@ unsigned long CStat::GetStat (E_CounterN
   return M_counters [P_counter];
 }
 
-/* Use the short form standard deviation formula given our average square and
- * the average.  */
-unsigned long CStat::computeStdev(E_CounterName P_AverageCounter,
+/* Use the short form standard deviation formula given the sum of the squares
+ * and the sum. */
+double CStat::computeStdev(E_CounterName P_SumCounter,
 			 E_CounterName P_NbOfCallUsed,
 			 E_CounterName P_Squares) {
-	return (unsigned long)sqrt((double)(M_counters[P_Squares] - (M_counters[P_AverageCounter] * M_counters[P_AverageCounter])));
+  double numerator = ((double)(M_counters[P_NbOfCallUsed]) * (double)(M_counters[P_Squares])) - ((double)(M_counters[P_SumCounter] * M_counters[P_SumCounter]));
+  double denominator = (double)(M_counters[P_NbOfCallUsed]) * (((double)(M_counters[P_NbOfCallUsed])) - 1.0);
+
+  return sqrt(numerator/denominator);
+}
+
+double CStat::computeMean(E_CounterName P_SumCounter,
+			 E_CounterName P_NbOfCallUsed) {
+  return ((double)(M_counters[P_SumCounter]) / (double)(M_counters[P_NbOfCallUsed]));
 }
 
-void CStat::updateAverageCounter(E_CounterName P_AverageCounter, 
+void CStat::updateAverageCounter(E_CounterName P_SumCounter,
                                  E_CounterName P_NbOfCallUsed,
                                  E_CounterName P_Squares,
-                                 unsigned long long* P_sum, 
-                                 unsigned long long* P_sq,
                                  unsigned long P_value)
 {
   if (M_counters [P_NbOfCallUsed] <= 0)
     {
       M_counters [P_NbOfCallUsed] ++;
-      *(P_sum) = M_counters [P_AverageCounter] = P_value;
-      *(P_sq) = M_counters [P_Squares] = (P_value * P_value);
+      M_counters [P_SumCounter] = P_value;
+      M_counters [P_Squares] = (P_value * P_value);
     }
   else
     {
-      (*P_sum) = P_value + (*P_sum);
-      (*P_sq) = (P_value * P_value)  + (*P_sq);
-
-      M_counters [P_AverageCounter] = (*P_sum) /
-        (M_counters [P_NbOfCallUsed] + 1);
-
-      M_counters [P_Squares] = (*P_sq) /
-        (M_counters [P_NbOfCallUsed] + 1);
-
+      M_counters [P_SumCounter] += P_value;
+      M_counters [P_Squares] += (P_value * P_value);
       M_counters [P_NbOfCallUsed] ++;
     }
 }
@@ -724,25 +723,19 @@ int CStat::computeStat (E_Action P_actio
     {
     case E_ADD_CALL_DURATION :
       // Updating Cumulative Counter
-      updateAverageCounter(CPT_C_AverageCallLength, 
+      updateAverageCounter(CPT_C_AverageCallLength_Sum,
                            CPT_C_NbOfCallUsedForAverageCallLength,
-			   CPT_C_AverageCallLength_Squares,
-                           &M_C_sumCallLength,
-			   &M_C_sumCallLength_Square, P_value);
+			   CPT_C_AverageCallLength_Squares, P_value);
       updateRepartition(M_CallLengthRepartition, 
                         M_SizeOfCallLengthRepartition, P_value);
       // Updating Periodical Diplayed counter
-      updateAverageCounter(CPT_PD_AverageCallLength, 
+      updateAverageCounter(CPT_PD_AverageCallLength_Sum,
                            CPT_PD_NbOfCallUsedForAverageCallLength,
-			   CPT_PD_AverageCallLength_Squares,
-                           &M_PD_sumCallLength,
-                           &M_PD_sumCallLength_Square, P_value);
+			   CPT_PD_AverageCallLength_Squares, P_value);
       // Updating Periodical Logging counter
-      updateAverageCounter(CPT_PL_AverageCallLength, 
+      updateAverageCounter(CPT_PL_AverageCallLength_Sum,
                            CPT_PL_NbOfCallUsedForAverageCallLength,
-			   CPT_PL_AverageCallLength_Squares,
-                           &M_PL_sumCallLength,
-			   &M_PL_sumCallLength_Square, P_value);
+			   CPT_PL_AverageCallLength_Squares, P_value);
       break;
 
 
@@ -754,22 +747,19 @@ int CStat::computeStat (E_Action P_actio
 
     case E_ADD_RESPONSE_TIME_DURATION :
       // Updating Cumulative Counter
-      updateAverageCounter((E_CounterName)(CPT_C_AverageResponseTime + which), 
+      updateAverageCounter((E_CounterName)(CPT_C_AverageResponseTime_Sum + which),
                            (E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + which),
-                           (E_CounterName)(CPT_C_AverageResponseTime_Squares + which),
-                           &M_C_sumResponseTime[which], &M_C_sumResponseTime_Square[which], P_value);
+                           (E_CounterName)(CPT_C_AverageResponseTime_Squares + which), P_value);
       updateRepartition(M_ResponseTimeRepartition[which], 
                         M_SizeOfResponseTimeRepartition, P_value);
       // Updating Periodical Diplayed counter
-      updateAverageCounter((E_CounterName)(CPT_PD_AverageResponseTime + which), 
+      updateAverageCounter((E_CounterName)(CPT_PD_AverageResponseTime_Sum + which),
                            (E_CounterName)(CPT_PD_NbOfCallUsedForAverageResponseTime + which),
-                           (E_CounterName)(CPT_PD_AverageResponseTime_Squares + which),
-                           &M_PD_sumResponseTime[which], &M_PD_sumResponseTime_Square[which], P_value);
+                           (E_CounterName)(CPT_PD_AverageResponseTime_Squares + which), P_value);
       // Updating Periodical Logging counter
-      updateAverageCounter((E_CounterName)(CPT_PL_AverageResponseTime + which), 
+      updateAverageCounter((E_CounterName)(CPT_PL_AverageResponseTime_Sum + which),
                            (E_CounterName)(CPT_PL_NbOfCallUsedForAverageResponseTime + which),
-                           (E_CounterName)(CPT_PL_AverageResponseTime_Squares + which),
-                           &M_PL_sumResponseTime[which], &M_PL_sumResponseTime_Square[which], P_value);
+                           (E_CounterName)(CPT_PL_AverageResponseTime_Squares + which), P_value);
       break;
 
     default :
@@ -1026,18 +1016,18 @@ void CStat::displayData (FILE *f)
 
     sprintf(s, "Response Time %d", i + 1);
     DISPLAY_TXT_COL (s,
-	msToHHMMSSmmm( M_counters [CPT_PD_AverageResponseTime + i] ),
-	msToHHMMSSmmm( M_counters [CPT_C_AverageResponseTime + i] ));
+	msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_PD_AverageResponseTime_Sum + i), (E_CounterName)(CPT_PD_NbOfCallUsedForAverageResponseTime + i)) ),
+	msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_C_AverageResponseTime_Sum + i), (E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + i)) ) );
   }
   DISPLAY_TXT_COL ("Call Length", 
-                   msToHHMMSSmmm( M_counters [CPT_PD_AverageCallLength] ), 
-                   msToHHMMSSmmm( M_counters [CPT_C_AverageCallLength] ));
+                   msToHHMMSSmmm( (unsigned long)computeMean(CPT_PD_AverageCallLength_Sum, CPT_PD_NbOfCallUsedForAverageCallLength)),
+                   msToHHMMSSmmm( (unsigned long)computeMean(CPT_C_AverageCallLength_Sum, CPT_C_NbOfCallUsedForAverageCallLength) ));
   DISPLAY_CROSS_LINE ();
 
   for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) {
     char s[50];
 
-    if (M_counters[CPT_C_AverageResponseTime + i] == 0) {
+    if (M_counters[CPT_C_NbOfCallUsedForAverageResponseTime + i] == 0) {
       continue;
     }
 
@@ -1152,12 +1142,12 @@ void CStat::displayStat (FILE *f)
 
     sprintf(s, "Response Time %d", i + 1);
     DISPLAY_TXT_COL (s,
-	msToHHMMSSmmm( M_counters [CPT_PD_AverageResponseTime + i] ),
-	msToHHMMSSmmm( M_counters [CPT_C_AverageResponseTime + i] ));
+	msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_PD_AverageResponseTime_Sum + i), (E_CounterName)(CPT_PD_NbOfCallUsedForAverageResponseTime + i)) ),
+	msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_C_AverageResponseTime_Sum + i), (E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + i))));
   }
   DISPLAY_TXT_COL ("Call Length", 
-                   msToHHMMSSmmm( M_counters [CPT_PD_AverageCallLength] ), 
-                   msToHHMMSSmmm( M_counters [CPT_C_AverageCallLength] ));
+                   msToHHMMSSmmm( (unsigned long)computeMean(CPT_PD_AverageCallLength_Sum, CPT_PD_NbOfCallUsedForAverageCallLength ) ),
+                   msToHHMMSSmmm( (unsigned long)computeMean(CPT_C_AverageCallLength_Sum, CPT_C_NbOfCallUsedForAverageCallLength) ));
 }
 
 void CStat::displayRepartition (FILE *f)
@@ -1354,29 +1344,40 @@ void CStat::dumpData ()
   // SF917289 << M_counters[CPT_C_UnexpectedMessage]    << stat_delimiter;
   for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) {
     (*M_outputStream) 
-      << msToHHMMSSmmm( M_counters [CPT_PL_AverageResponseTime + i] ) << stat_delimiter;
+      << msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_PL_AverageResponseTime_Sum + i),
+				    (E_CounterName)(CPT_PL_NbOfCallUsedForAverageResponseTime + i))) << stat_delimiter;
     (*M_outputStream) 
-      << msToHHMMSSmmm( M_counters [CPT_C_AverageResponseTime  + i] ) << stat_delimiter;
+      << msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_C_AverageResponseTime_Sum + i),
+				    (E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + i))) << stat_delimiter;
+
+    (*M_outputStream) << M_counters[(E_CounterName)(CPT_PL_AverageResponseTime_Sum + i)] << stat_delimiter;
+    (*M_outputStream) << M_counters[(E_CounterName)(CPT_C_AverageResponseTime_Sum + i)] << stat_delimiter;
+
+    (*M_outputStream) << M_counters[(E_CounterName)(CPT_PL_NbOfCallUsedForAverageResponseTime + i)] << stat_delimiter;
+    (*M_outputStream) << M_counters[(E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + i)] << stat_delimiter;
+
+    (*M_outputStream) << M_counters[(E_CounterName)(CPT_PL_AverageResponseTime_Squares + i)] << stat_delimiter;
+    (*M_outputStream) << M_counters[(E_CounterName)(CPT_C_AverageResponseTime_Squares + i)] << stat_delimiter;
 
     (*M_outputStream)
-      << msToHHMMSSmmm( computeStdev((E_CounterName)(CPT_PL_AverageResponseTime + i),
+      << msToHHMMSSmmm( (unsigned long)computeStdev((E_CounterName)(CPT_PL_AverageResponseTime_Sum + i),
 				     (E_CounterName)(CPT_PL_NbOfCallUsedForAverageResponseTime + i),
 				     (E_CounterName)(CPT_PL_AverageResponseTime_Squares + i)) ) << stat_delimiter;
     (*M_outputStream)
-      << msToHHMMSSmmm( computeStdev((E_CounterName)(CPT_C_AverageResponseTime + i),
+      << msToHHMMSSmmm( (unsigned long)computeStdev((E_CounterName)(CPT_C_AverageResponseTime_Sum + i),
 				     (E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + i),
 				     (E_CounterName)(CPT_C_AverageResponseTime_Squares + i)) ) << stat_delimiter;
   }
   (*M_outputStream) 
-    << msToHHMMSSmmm( M_counters [CPT_PL_AverageCallLength  ] ) << stat_delimiter;
+    << msToHHMMSSmmm( (unsigned long)computeMean(CPT_PL_AverageCallLength_Sum, CPT_PL_NbOfCallUsedForAverageCallLength) ) << stat_delimiter;
   (*M_outputStream) 
-    << msToHHMMSSmmm( M_counters [CPT_C_AverageCallLength   ] ) << stat_delimiter;
+    << msToHHMMSSmmm( (unsigned long)computeMean(CPT_C_AverageCallLength_Sum, CPT_C_NbOfCallUsedForAverageCallLength) ) << stat_delimiter;
   (*M_outputStream)
-    << msToHHMMSSmmm( computeStdev(CPT_PL_AverageCallLength,
+    << msToHHMMSSmmm( (unsigned long)computeStdev(CPT_PL_AverageCallLength_Sum,
 				   CPT_PL_NbOfCallUsedForAverageCallLength,
 				   CPT_PL_AverageCallLength_Squares )) << stat_delimiter;
   (*M_outputStream)
-    << msToHHMMSSmmm( computeStdev(CPT_C_AverageCallLength,
+    << msToHHMMSSmmm( (unsigned long)computeStdev(CPT_C_AverageCallLength_Sum,
 				   CPT_C_NbOfCallUsedForAverageCallLength,
 				   CPT_C_AverageCallLength_Squares )) << stat_delimiter;
 
@@ -1475,8 +1476,6 @@ char* CStat::msToHHMMSSmmm (unsigned lon
   return (L_time);
 } /* end of msToHHMMSS */
 
-
-
 char* CStat::formatTime (struct timeval* P_tv)
 {
   static char L_time [TIME_LENGTH];
Index: sipp.2007-02-28/stat.hpp
===================================================================
--- sipp.2007-02-28.orig/stat.hpp
+++ sipp.2007-02-28/stat.hpp
@@ -118,18 +118,18 @@ public:
   CPT_C_FailedCall,
   CPT_C_CurrentCall,
   CPT_C_NbOfCallUsedForAverageCallLength,
-  CPT_C_AverageCallLength,
+  CPT_C_AverageCallLength_Sum,
   CPT_C_AverageCallLength_Squares,
   CPT_C_NbOfCallUsedForAverageResponseTime,
   CPT_C_NbOfCallUsedForAverageResponseTime_2,
   CPT_C_NbOfCallUsedForAverageResponseTime_3,
   CPT_C_NbOfCallUsedForAverageResponseTime_4,
   CPT_C_NbOfCallUsedForAverageResponseTime_5, // This must match or exceed MAX_RTD_INFO
-  CPT_C_AverageResponseTime,
-  CPT_C_AverageResponseTime_2,
-  CPT_C_AverageResponseTime_3,
-  CPT_C_AverageResponseTime_4,
-  CPT_C_AverageResponseTime_5, // This must match or exceed MAX_RTD_INFO
+  CPT_C_AverageResponseTime_Sum,
+  CPT_C_AverageResponseTime_Sum_2,
+  CPT_C_AverageResponseTime_Sum_3,
+  CPT_C_AverageResponseTime_Sum_4,
+  CPT_C_AverageResponseTime_Sum_5, // This must match or exceed MAX_RTD_INFO
   CPT_C_AverageResponseTime_Squares,
   CPT_C_AverageResponseTime_Squares_2,
   CPT_C_AverageResponseTime_Squares_3,
@@ -159,18 +159,18 @@ public:
   CPT_PD_SuccessfulCall,
   CPT_PD_FailedCall,
   CPT_PD_NbOfCallUsedForAverageCallLength,
-  CPT_PD_AverageCallLength,
+  CPT_PD_AverageCallLength_Sum,
   CPT_PD_AverageCallLength_Squares,
   CPT_PD_NbOfCallUsedForAverageResponseTime,
   CPT_PD_NbOfCallUsedForAverageResponseTime_2, // This must match or exceed MAX_RTD_INFO
   CPT_PD_NbOfCallUsedForAverageResponseTime_3, // This must match or exceed MAX_RTD_INFO
   CPT_PD_NbOfCallUsedForAverageResponseTime_4, // This must match or exceed MAX_RTD_INFO
   CPT_PD_NbOfCallUsedForAverageResponseTime_5, // This must match or exceed MAX_RTD_INFO
-  CPT_PD_AverageResponseTime,
-  CPT_PD_AverageResponseTime_2,
-  CPT_PD_AverageResponseTime_3,
-  CPT_PD_AverageResponseTime_4,
-  CPT_PD_AverageResponseTime_5,
+  CPT_PD_AverageResponseTime_Sum,
+  CPT_PD_AverageResponseTime_Sum_2,
+  CPT_PD_AverageResponseTime_Sum_3,
+  CPT_PD_AverageResponseTime_Sum_4,
+  CPT_PD_AverageResponseTime_Sum_5,
   CPT_PD_AverageResponseTime_Squares,
   CPT_PD_AverageResponseTime_Squares_2,
   CPT_PD_AverageResponseTime_Squares_3,
@@ -200,7 +200,7 @@ public:
   CPT_PL_SuccessfulCall,
   CPT_PL_FailedCall,
   CPT_PL_NbOfCallUsedForAverageCallLength,
-  CPT_PL_AverageCallLength,
+  CPT_PL_AverageCallLength_Sum,
   /* The squares let us compute the standard deviation. */
   CPT_PL_AverageCallLength_Squares,
   CPT_PL_NbOfCallUsedForAverageResponseTime,
@@ -208,11 +208,11 @@ public:
   CPT_PL_NbOfCallUsedForAverageResponseTime_3,
   CPT_PL_NbOfCallUsedForAverageResponseTime_4,
   CPT_PL_NbOfCallUsedForAverageResponseTime_5,
-  CPT_PL_AverageResponseTime,
-  CPT_PL_AverageResponseTime_2,
-  CPT_PL_AverageResponseTime_3,
-  CPT_PL_AverageResponseTime_4,
-  CPT_PL_AverageResponseTime_5,
+  CPT_PL_AverageResponseTime_Sum,
+  CPT_PL_AverageResponseTime_Sum_2,
+  CPT_PL_AverageResponseTime_Sum_3,
+  CPT_PL_AverageResponseTime_Sum_4,
+  CPT_PL_AverageResponseTime_Sum_5,
   CPT_PL_AverageResponseTime_Squares,
   CPT_PL_AverageResponseTime_Squares_2,
   CPT_PL_AverageResponseTime_Squares_3,
@@ -371,7 +371,7 @@ private:
   ~CStat ();
 
   static CStat*            M_instance;
-  unsigned long            M_counters[E_NB_COUNTER];
+  unsigned long long       M_counters[E_NB_COUNTER];
   T_dynamicalRepartition*  M_ResponseTimeRepartition[MAX_RTD_INFO_LENGTH];
   T_dynamicalRepartition*  M_CallLengthRepartition;
   int                      M_SizeOfResponseTimeRepartition;
@@ -393,19 +393,6 @@ private:
   int                      M_counterDumpRespTime       ;
   unsigned long            M_report_freq_dumpRtt       ;
 
-  unsigned long long       M_C_sumCallLength;
-  unsigned long long       M_C_sumCallLength_Square;
-  unsigned long long       M_C_sumResponseTime[MAX_RTD_INFO_LENGTH];
-  unsigned long long       M_C_sumResponseTime_Square[MAX_RTD_INFO_LENGTH];
-  unsigned long long       M_PD_sumCallLength;
-  unsigned long long       M_PD_sumCallLength_Square;
-  unsigned long long       M_PD_sumResponseTime[MAX_RTD_INFO_LENGTH];
-  unsigned long long       M_PD_sumResponseTime_Square[MAX_RTD_INFO_LENGTH];
-  unsigned long long       M_PL_sumCallLength;
-  unsigned long long       M_PL_sumCallLength_Square;
-  unsigned long long       M_PL_sumResponseTime[MAX_RTD_INFO_LENGTH];
-  unsigned long long       M_PL_sumResponseTime_Square[MAX_RTD_INFO_LENGTH];
-
   /**
    * initRepartition
    * This methode is used to create the repartition table with a table of 
@@ -479,11 +466,9 @@ private:
    * This methode compute the real moyenne with the passed value on the given 
    * counter
    */
-  void updateAverageCounter(E_CounterName P_AverageCounter, 
+  void updateAverageCounter(E_CounterName P_SumCounter,
                             E_CounterName P_NbOfCallUsed,
                             E_CounterName P_Squares,
-                            unsigned long long* P_sum, 
-                            unsigned long long* P_sq,
                             unsigned long P_value);
 
   /**
@@ -491,11 +476,17 @@ private:
    * This method computes the standard deviation using our recorded mean
    * and recorded mean square.
    */
-  unsigned long computeStdev(E_CounterName P_AverageCounter,
+  double computeStdev(E_CounterName P_SumCounter,
                              E_CounterName P_NbOfCallUsed,
                              E_CounterName P_Squares);
 
   /**
+   * computeMean
+   * This method computes the recorded sum and count.
+   */
+  double computeMean(E_CounterName P_SumCounter,
+                             E_CounterName P_NbOfCallUsed);
+  /**
    * computeDiffTimeInMs.
    *
    * This method calculates elaped time in ms
