1 /* Most of it stolen from Pierre Beyssac's bing */
2 
3 /* $Id$ */
4 
5 #include "echoping.h"
6 
7 #define STATES 32
8 
9 #include <time.h>
10 #include <ctype.h>
11 
12 char           *
random_string(unsigned length)13 random_string(unsigned length)
14 {
15 
16     char           *state = (char *) malloc(sizeof(char) * STATES);
17     char           *result = (char *) malloc(length + 1);
18     int             i, number;
19     unsigned        seed = (unsigned) time((time_t *) NULL);
20 
21     /* printf ("Seed is %u\n", seed); */
22 
23     /* Initialize random generator */
24     (void) initstate(seed, state, STATES);
25 
26     for (i = 0; i < length; i++) {
27         number = (random() % 94) + 33;
28         /* printf ("Number for %d is %d\n", i, number); */
29         result[i] = (char) number;
30     }
31     result[length] = '\0';
32 
33     /* printf ("Result is %s\n", result); */
34 
35     return result;
36 
37 }
38 
39 char           *
to_upper(char * input)40 to_upper(char *input)
41 {
42     int             c;
43     char           *result;
44     result = (char *) malloc(strlen(input));
45     for (c = 0; c < strlen(input); c++)
46         result[c] = toupper((int) input[c]);
47     result[strlen(input)] = '\0';
48     return result;
49 }
50 
51 /*
52  * tvsub -- Subtract 2 timeval structs:  out = out - in. Out is assumed to be
53  * >= in. Comes from the bing program.
54  */
55 void
tvsub(out,in)56 tvsub(out, in)
57     struct timeval *out, *in;
58 {
59     if ((out->tv_usec -= in->tv_usec) < 0) {
60         --out->tv_sec;
61         out->tv_usec += 1000000;
62     }
63     out->tv_sec -= in->tv_sec;
64 }
65 
66 /* tvadd -- Adds 2 timeval structs:  out = out + in. */
67 void
tvadd(out,in)68 tvadd(out, in)
69     struct timeval *out, *in;
70 {
71     if ((out->tv_usec += in->tv_usec) >= 1000000) {
72         ++out->tv_sec;
73         out->tv_usec -= 1000000;
74     }
75     out->tv_sec += in->tv_sec;
76 }
77 
78 /* tvavg -- Averages a timeval struct */
79 void
tvavg(out,number)80 tvavg(out, number)
81     struct timeval *out;
82     int             number;
83 {
84     double          result;
85     /*
86      * out->tv_sec = out->tv_sec/number; out->tv_usec =
87      * out->tv_usec/number;
88      */
89     result = (1000000 * out->tv_sec + out->tv_usec) / number;
90     /* printf ("Result of average is %f\n", result) */ ;
91     out->tv_sec = (long) (result / 1000000);
92     out->tv_usec = (long) (result - (out->tv_sec * 1000000));
93 }
94 
95 /* tvstddev -- Computes the standard deviation of a set of results */
96 void
tvstddev(out,number,average,results)97 tvstddev(out, number, average, results)
98     struct timeval *out;
99     int             number;
100     struct timeval  average;
101     struct result  *results;
102 {
103     int             i;
104     struct timeval  result = null_timeval;
105     struct timeval  avg = null_timeval;
106 #ifdef DEBUG
107     struct timeval  var = null_timeval;
108 #endif
109     struct timeval  large, small;
110     double          d_offset, d_square, d_variance = 0;
111     *out = null_timeval;
112     for (i = 0; i < number; i++) {
113         if (results[i].valid == 1) {
114             result = results[i].timevalue;
115 #ifdef DEBUG
116             printf("DEBUG: Value is %f (average is %f)\n", tv2double
117                    (result), tv2double(average));
118 #endif
119             avg = average;
120             if (tvcmp(&result, &avg) == -1) {
121                 small = result;
122                 large = avg;
123             } else {
124                 large = result;
125                 small = avg;
126             }
127             tvsub(&large, &small);
128 #ifdef DEBUG
129             printf("abs offset is %f\n", tv2double(large));
130 #endif
131             d_offset = tv2double(large);
132             d_square = d_offset * d_offset;
133             d_variance += d_square;
134 #ifdef DEBUG
135             printf("variance is now %f\n", tv2double(var));
136 #endif
137         }
138     }
139     result = double2tv(sqrt(d_variance / (double) number));
140     out->tv_sec = result.tv_sec;
141     out->tv_usec = result.tv_usec;
142 }
143 
144 
145  /* tvstddevavg -- Computes the average of values within a set of results where the
146   * sample is within the given number of standard deviations from the average */
147 /* TODO: IWBN to return the number of excluded outliers */
148 void
tvstddevavg(out,number,average,results,n_stddev)149 tvstddevavg(out, number, average, results, n_stddev)
150     struct timeval *out;        /* contains std dev on entry */
151     int             number;
152     struct timeval  average;
153     struct result  *results;
154     double          n_stddev;
155 {
156     int             i, valid = 0;
157     struct timeval  result;     /* working value */
158     struct timeval  var = null_timeval; /* result accumulator */
159     double          x;
160     double          maxdev = tv2double(*out) * n_stddev;
161 
162     if (tvcmp(out, &null_timeval) == 0) {
163         /* if the SD is 0 then we just return the average */
164         *out = average;
165         return;
166     }
167 
168     for (i = 0; i < number; i++) {
169         if (results[i].valid == 1) {
170             result = results[i].timevalue;
171             tvsub(&result, &average);
172             /* printf ("value is %f (stddev is %f)\n", tv2double (result), tv2double
173              * (stddev)); */
174             /* ensure that result (difference to average) is absolute value */
175             if (tvcmp(&result, &null_timeval) == -1) {
176                 result = average;
177                 tvsub(&result, &results[i].timevalue);
178             }
179             x = tv2double(result);
180             /* printf("value is %g maxdev %g\n",x,maxdev); */
181             if (x <= maxdev) {
182                 /* deviation is less than stddev */
183                 tvadd(&var, &results[i].timevalue);
184                 valid++;
185             } else {
186                 /* printf("dropped\n"); */
187             }
188         }
189     }
190     /* printf ("total is %f in %d samples\n", tv2double (var), valid); */
191     if (valid > 0) {
192         *out = double2tv(tv2double(var) / valid);
193     } else {
194         *out = null_timeval;
195     }
196 
197 }
198 
199 /* tvcmp -- Compares two timeval structs */
200 int
tvcmp(left,right)201 tvcmp(left, right)
202     struct timeval *left, *right;
203 {
204     if (left->tv_sec < right->tv_sec) {
205         return -1;
206     }
207     if (left->tv_sec > right->tv_sec) {
208         return 1;
209     }
210     if (left->tv_usec < right->tv_usec) {
211         return -1;
212     }
213     if (left->tv_usec > right->tv_usec) {
214         return 1;
215     }
216     return 0;
217 
218 }
219 
220 /* tvmin */
221 void
tvmin(champion,challenger)222 tvmin(champion, challenger)
223     struct timeval *champion, *challenger;
224 {
225     if (tvcmp(champion, challenger) == 1) {
226         champion->tv_sec = challenger->tv_sec;
227         champion->tv_usec = challenger->tv_usec;
228     }
229 }
230 
231 /* tvmax */
232 void
tvmax(champion,challenger)233 tvmax(champion, challenger)
234     struct timeval *champion, *challenger;
235 {
236     if (tvcmp(champion, challenger) == -1) {
237         champion->tv_sec = challenger->tv_sec;
238         champion->tv_usec = challenger->tv_usec;
239     }
240 }
241 
242 double
tv2double(tv)243 tv2double(tv)
244     struct timeval  tv;
245 {
246     double          result;
247     result =
248         (((((double) tv.tv_sec) * 1000000.0) + (double) tv.tv_usec) / 1000000.0);
249     /* printf ("Double is %9.3f\n", result); */
250     return result;
251 }
252 
253 struct timeval
double2tv(x)254 double2tv(x)
255     double          x;
256 {
257     struct timeval  result;
258     result.tv_sec = (int) (x);
259     result.tv_usec = (int) ((x - result.tv_sec) * 1000000);
260     return result;
261 }
262