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