1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 */
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <malloc.h>
36 #include "random_range.h"
37
38 /*
39 * Internal format of the range array set up by parse_range()
40 */
41
42 struct range {
43 int min;
44 int max;
45 int mult;
46 };
47
48 /*
49 * parse_ranges() is a function to parse a comma-separated list of range
50 * tokens each having the following form:
51 *
52 * num
53 * or
54 * min:max[:mult]
55 *
56 * any of the values may be blank (ie. min::mult, :max, etc.) and default
57 * values for missing arguments may be supplied by the caller.
58 *
59 * The special first form is short hand for 'num:num'.
60 *
61 * After parsing the string, the ranges are put into an array of integers,
62 * which is malloc'd by the routine. The min, max, and mult entries of each
63 * range can be extracted from the array using the range_min(), range_max(),
64 * and range_mult() functions.
65 *
66 * It is the responsibility of the caller to free the space allocated by
67 * parse_ranges() - a single call to free() will free the space.
68 *
69 * str The string to parse - assumed to be a comma-separated
70 * list of tokens having the above format.
71 * defmin default value to plug in for min, if it is missing
72 * defmax default value to plug in for max, if it is missing
73 * defmult default value to plug in for mult, if missing
74 * parse_func A user-supplied function pointer, which parse_ranges()
75 * can call to parse the min, max, and mult strings. This
76 * allows for customized number formats. The function
77 * MUST have the following prototype:
78 * parse_func(char *str, int *val)
79 * The function should return -1 if str cannot be parsed
80 * into an integer, or >= 0 if it was successfully
81 * parsed. The resulting integer will be stored in
82 * *val. If parse_func is NULL, parse_ranges will parse
83 * the tokens in a manner consistent with the the sscanf
84 * %i format.
85 * range_ptr A user-supplied char **, which will be set to point
86 * at malloc'd space which holds the parsed range
87 * values. If range_ptr is NULL, parse_ranges() just
88 * parses the string. The data returned in range_ptr
89 * should not be processed directly - use the functions
90 * range_min(), range_max(), and range_mult() to access
91 * data for a given range.
92 * errptr user-supplied char ** which can be set to point to a
93 * static error string. If errptr is NULL, it is ignored.
94 *
95 * parse_range() returns -1 on error, or the number of ranges parsed.
96 */
97
98 static int str_to_int();
99 static long long divider(long long, long long, long long, long long);
100
parse_ranges(char * str,int defmin,int defmax,int defmult,int (* parse_func)(),char ** rangeptr,char ** errptr)101 int parse_ranges(char *str, int defmin, int defmax, int defmult,
102 int (*parse_func)(), char **rangeptr, char **errptr)
103 {
104 int ncommas;
105 char *tmpstr, *cp, *tok, *n1str, *n2str, *multstr;
106 struct range *rp, *ranges;
107 static char errmsg[256];
108
109 if (errptr != NULL) {
110 *errptr = errmsg;
111 }
112
113 for (ncommas = 0, cp = str; *cp != '\0'; cp++) {
114 if (*cp == ',') {
115 ncommas++;
116 }
117 }
118
119 if (parse_func == NULL) {
120 parse_func = str_to_int;
121 }
122
123 tmpstr = strdup(str);
124 ranges = malloc((ncommas + 1) * sizeof(struct range));
125 rp = ranges;
126
127 tok = strtok(tmpstr, ",");
128 while (tok != NULL) {
129 n1str = tok;
130 n2str = NULL;
131 multstr = NULL;
132
133 rp->min = defmin;
134 rp->max = defmax;
135 rp->mult = defmult;
136
137 if ((cp = strchr(n1str, ':')) != NULL) {
138 *cp = '\0';
139 n2str = cp + 1;
140
141 if ((cp = strchr(n2str, ':')) != NULL) {
142 *cp = '\0';
143 multstr = cp + 1;
144 }
145 }
146
147 /*
148 * Parse the 'min' field - if it is zero length (:n2[:mult]
149 * format), retain the default value, otherwise, pass the
150 * string to the parse function.
151 */
152
153 if ((int)strlen(n1str) > 0) {
154 if ((*parse_func) (n1str, &rp->min) < 0) {
155 sprintf(errmsg,
156 "error parsing string %s into an integer",
157 n1str);
158 free(tmpstr);
159 free(ranges);
160 return -1;
161 }
162 }
163
164 /*
165 * Process the 'max' field - if one was not present (n1 format)
166 * set max equal to min. If the field was present, but
167 * zero length (n1: format), retain the default. Otherwise
168 * pass the string to the parse function.
169 */
170
171 if (n2str == NULL) {
172 rp->max = rp->min;
173 } else if ((int)strlen(n2str) > 0) {
174 if ((*parse_func) (n2str, &rp->max) < 0) {
175 sprintf(errmsg,
176 "error parsing string %s into an integer",
177 n2str);
178 free(tmpstr);
179 free(ranges);
180 return -1;
181 }
182 }
183
184 /*
185 * Process the 'mult' field - if one was not present
186 * (n1:n2 format), or the field was zero length (n1:n2: format)
187 * then set the mult field to defmult - otherwise pass then
188 * mult field to the parse function.
189 */
190
191 if (multstr != NULL && (int)strlen(multstr) > 0) {
192 if ((*parse_func) (multstr, &rp->mult) < 0) {
193 sprintf(errmsg,
194 "error parsing string %s into an integer",
195 multstr);
196 free(tmpstr);
197 free(ranges);
198 return -1;
199 }
200 }
201
202 rp++;
203 tok = strtok(NULL, ",");
204 }
205
206 free(tmpstr);
207
208 if (rangeptr != NULL) {
209 *rangeptr = (char *)ranges;
210 } else {
211 free(ranges); /* just running in parse mode */
212 }
213
214 return (rp - ranges);
215 }
216
217 /*
218 * The default integer-parsing function
219 */
220
str_to_int(char * str,int * ip)221 static int str_to_int(char *str, int *ip)
222 {
223 char c;
224
225 if (sscanf(str, "%i%c", ip, &c) != 1) {
226 return -1;
227 } else {
228 return 0;
229 }
230 }
231
232 /*
233 * Three simple functions to return the min, max, and mult values for a given
234 * range. It is assumed that rbuf is a range buffer set up by parse_ranges(),
235 * and that r is a valid range within that buffer.
236 */
237
range_min(char * rbuf,int r)238 int range_min(char *rbuf, int r)
239 {
240 return ((struct range *)rbuf)[r].min;
241 }
242
range_max(char * rbuf,int r)243 int range_max(char *rbuf, int r)
244 {
245 return ((struct range *)rbuf)[r].max;
246 }
247
range_mult(char * rbuf,int r)248 int range_mult(char *rbuf, int r)
249 {
250 return ((struct range *)rbuf)[r].mult;
251 }
252
253 /*****************************************************************************
254 * random_range(int start, int end, int mult, char **errp)
255 *
256 * Returns a psuedo-random number which is >= 'start', <= 'end', and a multiple
257 * of 'mult'. Start and end may be any valid integer, but mult must be an
258 * integer > 0. errp is a char ** which will be set to point to a static
259 * error message buffer if it is not NULL, and an error occurs.
260 *
261 * The errp is the only way to check if the routine fails - currently the only
262 * failure conditions are:
263 *
264 * mult < 1
265 * no numbers in the start-end range that are a multiple of 'mult'
266 *
267 * If random_range_fails, and errp is a valid pointer, it will point to an
268 * internal error buffer. If errp is a vaild pointer, and random_range
269 * is successful, errp will be set to NULL.
270 *
271 * Note - if mult is 1 (the most common case), there are error conditions
272 * possible, and errp need not be used.
273 *
274 * Note: Uses lrand48(), assuming that set_random_seed() uses srand48() when
275 * setting the seed.
276 *****************************************************************************/
277
random_range(int min,int max,int mult,char ** errp)278 long random_range(int min, int max, int mult, char **errp)
279 {
280 int r, nmults, orig_min, orig_max, orig_mult, tmp;
281 extern long lrand48();
282 static char errbuf[128];
283
284 /*
285 * Sanity check
286 */
287
288 if (mult < 1) {
289 if (errp != NULL) {
290 sprintf(errbuf, "mult arg must be greater than 0");
291 *errp = errbuf;
292 }
293 return -1;
294 }
295
296 /*
297 * Save original parameter values for use in error message
298 */
299
300 orig_min = min;
301 orig_max = max;
302 orig_mult = mult;
303
304 /*
305 * switch min/max if max < min
306 */
307
308 if (max < min) {
309 tmp = max;
310 max = min;
311 min = tmp;
312 }
313
314 /*
315 * select the random number
316 */
317
318 if ((r = min % mult)) /* bump to the next higher 'mult' multiple */
319 min += mult - r;
320
321 if ((r = max % mult)) /* reduce to the next lower 'mult' multiple */
322 max -= r;
323
324 if (min > max) { /* no 'mult' multiples between min & max */
325 if (errp != NULL) {
326 sprintf(errbuf,
327 "no numbers in the range %d:%d that are a multiple of %d",
328 orig_min, orig_max, orig_mult);
329 *errp = errbuf;
330 }
331 return -1;
332 }
333
334 if (errp != NULL) {
335 *errp = NULL;
336 }
337
338 nmults = ((max - min) / mult) + 1;
339 #if CRAY
340 /*
341 * If max is less than 2gb, then the value can fit in 32 bits
342 * and the standard lrand48() routine can be used.
343 */
344 if (max <= (long)2147483647) {
345 return (long)(min + (((long)lrand48() % nmults) * mult));
346 } else {
347 /*
348 * max is greater than 2gb - meeds more than 32 bits.
349 * Since lrand48 only will get a number up to 32bits.
350 */
351 long randnum;
352 randnum = divider(min, max, 0, -1);
353 return (long)(min + ((randnum % nmults) * mult));
354 }
355
356 #else
357 return (min + ((lrand48() % nmults) * mult));
358 #endif
359
360 }
361
362 /*
363 * Just like random_range, but all values are longs.
364 */
random_rangel(long min,long max,long mult,char ** errp)365 long random_rangel(long min, long max, long mult, char **errp)
366 {
367 long r, nmults, orig_min, orig_max, orig_mult, tmp;
368 extern long lrand48();
369 static char errbuf[128];
370
371 /*
372 * Sanity check
373 */
374
375 if (mult < 1) {
376 if (errp != NULL) {
377 sprintf(errbuf, "mult arg must be greater than 0");
378 *errp = errbuf;
379 }
380 return -1;
381 }
382
383 /*
384 * Save original parameter values for use in error message
385 */
386
387 orig_min = min;
388 orig_max = max;
389 orig_mult = mult;
390
391 /*
392 * switch min/max if max < min
393 */
394
395 if (max < min) {
396 tmp = max;
397 max = min;
398 min = tmp;
399 }
400
401 /*
402 * select the random number
403 */
404
405 if ((r = min % mult)) /* bump to the next higher 'mult' multiple */
406 min += mult - r;
407
408 if ((r = max % mult)) /* reduce to the next lower 'mult' multiple */
409 max -= r;
410
411 if (min > max) { /* no 'mult' multiples between min & max */
412 if (errp != NULL) {
413 sprintf(errbuf,
414 "no numbers in the range %ld:%ld that are a multiple of %ld",
415 orig_min, orig_max, orig_mult);
416 *errp = errbuf;
417 }
418 return -1;
419 }
420
421 if (errp != NULL) {
422 *errp = NULL;
423 }
424
425 nmults = ((max - min) / mult) + 1;
426 #if CRAY || (_MIPS_SZLONG == 64)
427 /*
428 * If max is less than 2gb, then the value can fit in 32 bits
429 * and the standard lrand48() routine can be used.
430 */
431 if (max <= (long)2147483647) {
432 return (long)(min + (((long)lrand48() % nmults) * mult));
433 } else {
434 /*
435 * max is greater than 2gb - meeds more than 32 bits.
436 * Since lrand48 only will get a number up to 32bits.
437 */
438 long randnum;
439 randnum = divider(min, max, 0, -1);
440 return (long)(min + ((randnum % nmults) * mult));
441 }
442
443 #else
444 return (min + ((lrand48() % nmults) * mult));
445 #endif
446 }
447
448 /*
449 * Attempts to be just like random_range, but everything is long long (64 bit)
450 */
random_rangell(long long min,long long max,long long mult,char ** errp)451 long long random_rangell(long long min, long long max,
452 long long mult, char **errp)
453 {
454 long long r, nmults, orig_min, orig_max, orig_mult, tmp;
455 long long randnum;
456 extern long lrand48();
457 static char errbuf[128];
458
459 /*
460 * Sanity check
461 */
462
463 if (mult < 1) {
464 if (errp != NULL) {
465 sprintf(errbuf, "mult arg must be greater than 0");
466 *errp = errbuf;
467 }
468 return -1;
469 }
470
471 /*
472 * Save original parameter values for use in error message
473 */
474
475 orig_min = min;
476 orig_max = max;
477 orig_mult = mult;
478
479 /*
480 * switch min/max if max < min
481 */
482
483 if (max < min) {
484 tmp = max;
485 max = min;
486 min = tmp;
487 }
488
489 /*
490 * select the random number
491 */
492
493 if ((r = min % mult)) /* bump to the next higher 'mult' multiple */
494 min += mult - r;
495
496 if ((r = max % mult)) /* reduce to the next lower 'mult' multiple */
497 max -= r;
498
499 if (min > max) { /* no 'mult' multiples between min & max */
500 if (errp != NULL) {
501 sprintf(errbuf,
502 "no numbers in the range %lld:%lld that are a multiple of %lld",
503 orig_min, orig_max, orig_mult);
504 *errp = errbuf;
505 }
506 return -1;
507 }
508
509 if (errp != NULL) {
510 *errp = NULL;
511 }
512
513 nmults = ((max - min) / mult) + 1;
514 /*
515 * If max is less than 2gb, then the value can fit in 32 bits
516 * and the standard lrand48() routine can be used.
517 */
518 if (max <= (long)2147483647) {
519 return (long long)(min +
520 (((long long)lrand48() % nmults) * mult));
521 } else {
522 /*
523 * max is greater than 2gb - meeds more than 32 bits.
524 * Since lrand48 only will get a number up to 32bits.
525 */
526 randnum = divider(min, max, 0, -1);
527 return (long long)(min + ((randnum % nmults) * mult));
528 }
529
530 }
531
532 /*
533 * This functional will recusively call itself to return a random
534 * number min and max. It was designed to work the 64bit numbers
535 * even when compiled as 32 bit process.
536 * algorithm: to use the official lrand48() routine - limited to 32 bits.
537 * find the difference between min and max (max-min).
538 * if the difference is 2g or less, use the random number gotton from lrand48().
539 * Determine the midway point between min and max.
540 * if the midway point is less than 2g from min or max,
541 * randomly add the random number gotton from lrand48() to
542 * either min or the midpoint.
543 * Otherwise, call outself with min and max being min and midway value or
544 * midway value and max. This will reduce the range in half.
545 */
546 static long long
divider(long long min,long long max,long long cnt,long long rand)547 divider(long long min, long long max, long long cnt, long long rand)
548 {
549 long long med, half, diff;
550
551 /*
552 * prevent run away code. We are dividing by two each count.
553 * if we get to a count of more than 32, we should have gotten
554 * to 2gb.
555 */
556 if (cnt > 32)
557 return -1;
558
559 /*
560 * Only get a random number the first time.
561 */
562 if (cnt == 0 || rand < -1) {
563 rand = (long long)lrand48(); /* 32 bit random number */
564 }
565
566 diff = max - min;
567
568 if (diff <= 2147483647)
569 return min + rand;
570
571 half = diff / (long long)2; /* half the distance between min and max */
572 med = min + half; /* med way point between min and max */
573
574 #if DEBUG
575 printf("divider: min=%lld, max=%lld, cnt=%lld, rand=%lld\n", min, max,
576 cnt, rand);
577 printf(" diff = %lld, half = %lld, med = %lld\n", diff, half, med);
578 #endif
579
580 if (half <= 2147483647) {
581 /*
582 * If half is smaller than 2gb, we can use the random number
583 * to pick the number within the min to med or med to max
584 * if the cnt bit of rand is zero or one, respectively.
585 */
586 if (rand & (1 << cnt))
587 return med + rand;
588 else
589 return min + rand;
590 } else {
591 /*
592 * recursively call ourself to reduce the value to the bottom half
593 * or top half (bit cnt is set).
594 */
595 if (rand & (1 << cnt)) {
596 return divider(med, max, cnt + 1, rand);
597 } else {
598 return divider(min, med, cnt + 1, rand);
599 }
600
601 }
602
603 }
604
605 /*****************************************************************************
606 * random_range_seed(s)
607 *
608 * Sets the random seed to s. Uses srand48(), assuming that lrand48() will
609 * be used in random_range().
610 *****************************************************************************/
611
random_range_seed(long s)612 void random_range_seed(long s)
613 {
614 extern void srand48();
615
616 srand48(s);
617 }
618
619 /****************************************************************************
620 * random_bit(mask)
621 *
622 * This function randomly returns a single bit from the bits
623 * set in mask. If mask is zero, zero is returned.
624 *
625 ****************************************************************************/
random_bit(long mask)626 long random_bit(long mask)
627 {
628 int nbits = 0; /* number of set bits in mask */
629 long bit; /* used to count bits and num of set bits choosen */
630 int nshift; /* used to count bit shifts */
631
632 if (mask == 0)
633 return 0;
634
635 /*
636 * get the number of bits set in mask
637 */
638 #ifndef CRAY
639
640 bit = 1L;
641 for (nshift = 0; (unsigned int)nshift < sizeof(long) * 8; nshift++) {
642 if (mask & bit)
643 nbits++;
644 bit = bit << 1;
645 }
646
647 #else
648 nbits = _popcnt(mask);
649 #endif /* if CRAY */
650
651 /*
652 * randomly choose a bit.
653 */
654 bit = random_range(1, nbits, 1, NULL);
655
656 /*
657 * shift bits until you determine which bit was randomly choosen.
658 * nshift will hold the number of shifts to make.
659 */
660
661 nshift = 0;
662 while (bit) {
663 /* check if the current one's bit is set */
664 if (mask & 1L) {
665 bit--;
666 }
667 mask = mask >> 1;
668 nshift++;
669 }
670
671 return 01L << (nshift - 1);
672
673 }
674
675 #if RANDOM_BIT_UNITTEST
676 /*
677 * The following is a unit test main function for random_bit().
678 */
main(argc,argv)679 main(argc, argv)
680 int argc;
681 char **argv;
682 {
683 int ind;
684 int cnt, iter;
685 long mask, ret;
686
687 printf("test for first and last bit set\n");
688 mask = 1L;
689 ret = random_bit(mask);
690 printf("random_bit(%#o) returned %#o\n", mask, ret);
691
692 mask = 1L << (sizeof(long) * 8 - 1);
693 ret = random_bit(mask);
694 printf("random_bit(%#o) returned %#o\n", mask, ret);
695
696 if (argc >= 3) {
697 iter = atoi(argv[1]);
698 for (ind = 2; ind < argc; ind++) {
699 printf("Calling random_bit %d times for mask %#o\n",
700 iter, mask);
701 sscanf(argv[ind], "%i", &mask);
702 for (cnt = 0; cnt < iter; cnt++) {
703 ret = random_bit(mask);
704 printf("random_bit(%#o) returned %#o\n", mask,
705 ret);
706 }
707 }
708 }
709 exit(0);
710 }
711
712 #endif /* end if RANDOM_BIT_UNITTEST */
713
714 #if UNIT_TEST
715 /*
716 * The following is a unit test main function for random_range*().
717 */
718
719 #define PARTNUM 10 /* used to determine even distribution of random numbers */
720 #define MEG 1024*1024*1024
721 #define GIG 1073741824
main(argc,argv)722 int main(argc, argv)
723 int argc;
724 char **argv;
725 {
726 int ind;
727 int cnt, iter = 10;
728 int imin = 0, imult = 1, itmin, itmax = 0;
729 #if CRAY
730 int imax = 6 * GIG; /* higher than 32 bits */
731 #else
732 int imax = 1048576;
733 #endif
734
735 long lret, lmin = 0, lmult = 1, ltmin, ltmax = 0;
736 #if CRAY || (_MIPS_SZLONG == 64)
737 long lmax = 6 * (long)GIG; /* higher than 32 bits */
738 #else
739 long lmax = 1048576;
740 #endif
741 long long llret, llmin = 0, llmult = 1, lltmin, lltmax = 0;
742 long long llmax = (long long)80 * (long long)GIG;
743
744 long part;
745 long long lpart;
746 long cntarr[PARTNUM];
747 long valbound[PARTNUM];
748 long long lvalbound[PARTNUM];
749
750 for (ind = 0; ind < PARTNUM; ind++)
751 cntarr[ind] = 0;
752
753 if (argc < 2) {
754 printf("Usage: %s func [iterations] \n", argv[0]);
755 printf
756 ("func can be random_range, random_rangel, random_rangell\n");
757 exit(1);
758 }
759
760 if (argc >= 3) {
761 if (sscanf(argv[2], "%i", &iter) != 1) {
762 printf("Usage: %s [func iterations] \n", argv[0]);
763 printf("argv[2] is not a number\n");
764 exit(1);
765 }
766 }
767
768 /*
769 * random_rangel ()
770 */
771 if (strcmp(argv[1], "random_rangel") == 0) {
772 ltmin = lmax;
773 part = lmax / PARTNUM;
774 for (ind = 0; ind < PARTNUM; ind++) {
775 valbound[ind] = part * ind;
776 }
777
778 for (cnt = 0; cnt < iter; cnt++) {
779 lret = random_rangel(lmin, lmax, lmult, NULL);
780 if (iter < 100)
781 printf("%ld\n", lret);
782 if (lret < ltmin)
783 ltmin = lret;
784 if (lret > ltmax)
785 ltmax = lret;
786 for (ind = 0; ind < PARTNUM - 1; ind++) {
787 if (valbound[ind] < lret
788 && lret <= valbound[ind + 1]) {
789 cntarr[ind]++;
790 break;
791 }
792 }
793 if (lret > valbound[PARTNUM - 1]) {
794 cntarr[PARTNUM - 1]++;
795 }
796 }
797 for (ind = 0; ind < PARTNUM - 1; ind++) {
798 printf("%2d %-13ld to %-13ld %5ld %4.4f\n", ind + 1,
799 valbound[ind], valbound[ind + 1], cntarr[ind],
800 (float)(cntarr[ind] / (float)iter));
801 }
802 printf("%2d %-13ld to %-13ld %5ld %4.4f\n", PARTNUM,
803 valbound[PARTNUM - 1], lmax, cntarr[PARTNUM - 1],
804 (float)(cntarr[PARTNUM - 1] / (float)iter));
805 printf(" min=%ld, max=%ld\n", ltmin, ltmax);
806
807 } else if (strcmp(argv[1], "random_rangell") == 0) {
808 /*
809 * random_rangell() unit test
810 */
811 lltmin = llmax;
812 lpart = llmax / PARTNUM;
813 for (ind = 0; ind < PARTNUM; ind++) {
814 lvalbound[ind] = (long long)(lpart * ind);
815 }
816
817 for (cnt = 0; cnt < iter; cnt++) {
818 llret = random_rangell(llmin, llmax, llmult, NULL);
819 if (iter < 100)
820 printf("random_rangell returned %lld\n", llret);
821 if (llret < lltmin)
822 lltmin = llret;
823 if (llret > lltmax)
824 lltmax = llret;
825
826 for (ind = 0; ind < PARTNUM - 1; ind++) {
827 if (lvalbound[ind] < llret
828 && llret <= lvalbound[ind + 1]) {
829 cntarr[ind]++;
830 break;
831 }
832 }
833 if (llret > lvalbound[PARTNUM - 1]) {
834 cntarr[PARTNUM - 1]++;
835 }
836 }
837 for (ind = 0; ind < PARTNUM - 1; ind++) {
838 printf("%2d %-13lld to %-13lld %5ld %4.4f\n",
839 ind + 1, lvalbound[ind], lvalbound[ind + 1],
840 cntarr[ind], (float)(cntarr[ind] / (float)iter));
841 }
842 printf("%2d %-13lld to %-13lld %5ld %4.4f\n", PARTNUM,
843 lvalbound[PARTNUM - 1], llmax, cntarr[PARTNUM - 1],
844 (float)(cntarr[PARTNUM - 1] / (float)iter));
845 printf(" min=%lld, max=%lld\n", lltmin, lltmax);
846
847 } else {
848 /*
849 * random_range() unit test
850 */
851 itmin = imax;
852 part = imax / PARTNUM;
853 for (ind = 0; ind < PARTNUM; ind++) {
854 valbound[ind] = part * ind;
855 }
856
857 for (cnt = 0; cnt < iter; cnt++) {
858 lret = random_range(imin, imax, imult, NULL);
859 if (iter < 100)
860 printf("%ld\n", lret);
861 if (lret < itmin)
862 itmin = lret;
863 if (lret > itmax)
864 itmax = lret;
865
866 for (ind = 0; ind < PARTNUM - 1; ind++) {
867 if (valbound[ind] < lret
868 && lret <= valbound[ind + 1]) {
869 cntarr[ind]++;
870 break;
871 }
872 }
873 if (lret > valbound[PARTNUM - 1]) {
874 cntarr[PARTNUM - 1]++;
875 }
876 }
877 for (ind = 0; ind < PARTNUM - 1; ind++) {
878 printf("%2d %-13ld to %-13ld %5ld %4.4f\n", ind + 1,
879 valbound[ind], valbound[ind + 1], cntarr[ind],
880 (float)(cntarr[ind] / (float)iter));
881 }
882 printf("%2d %-13ld to %-13ld %5ld %4.4f\n", PARTNUM,
883 valbound[PARTNUM - 1], (long)imax, cntarr[PARTNUM - 1],
884 (float)(cntarr[PARTNUM - 1] / (float)iter));
885 printf(" min=%d, max=%d\n", itmin, itmax);
886
887 }
888
889 exit(0);
890 }
891
892 #endif
893