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