xfstests: some refinements on "make depend"
[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 #if CRAY 
342         /*
343          * If max is less than 2gb, then the value can fit in 32 bits
344          * and the standard lrand48() routine can be used.
345          */
346         if ( max <= (long)2147483647 ) {
347             return (long) (min + (((long)lrand48() % nmults) * mult));
348         } else {
349             /*
350              * max is greater than 2gb - meeds more than 32 bits.
351              * Since lrand48 only will get a number up to 32bits.
352              */
353             long randnum;
354             randnum=divider(min, max, 0, -1);
355             return (long) (min + ((randnum % nmults) * mult));
356         }
357
358 #else
359         return (min + ((lrand48() % nmults) * mult));
360 #endif
361
362 }
363
364 /*
365  * Just like random_range, but all values are longs.
366  */
367 long
368 random_rangel(min, max, mult, errp)
369 long    min;
370 long    max;
371 long    mult;
372 char    **errp;
373 {
374         long            r, nmults, orig_min, orig_max, orig_mult, tmp;
375         extern long     lrand48();
376         static char     errbuf[128];
377
378         /*
379          * Sanity check
380          */
381
382         if (mult < 1) {
383                 if (errp != NULL) {
384                         sprintf(errbuf, "mult arg must be greater than 0");
385                         *errp = errbuf;
386                 }
387                 return -1;
388         }
389
390         /*
391          * Save original parameter values for use in error message
392          */
393
394         orig_min = min;
395         orig_max = max;
396         orig_mult = mult;
397
398         /*
399          * switch min/max if max < min
400          */
401
402         if (max < min) {
403                 tmp = max;
404                 max = min;
405                 min = tmp;
406         }
407
408         /*
409          * select the random number
410          */
411
412         if ((r = min % mult))     /* bump to the next higher 'mult' multiple */
413                 min += mult - r;
414
415         if ((r = max % mult))     /* reduce to the next lower 'mult' multiple */
416                 max -= r;
417
418         if (min > max) {         /* no 'mult' multiples between min & max */
419                 if (errp != NULL) {
420                     sprintf(errbuf,
421                         "no numbers in the range %ld:%ld that are a multiple of %ld",
422                         orig_min, orig_max, orig_mult);
423                     *errp = errbuf;
424                 }
425                 return -1;
426         }
427
428         if (errp != NULL) {
429                 *errp = NULL;
430         }
431
432         nmults = ((max - min) / mult) + 1;
433 #if CRAY || (_MIPS_SZLONG == 64)
434         /*
435          * If max is less than 2gb, then the value can fit in 32 bits
436          * and the standard lrand48() routine can be used.
437          */
438         if ( max <= (long)2147483647 ) {
439             return (long) (min + (((long)lrand48() % nmults) * mult));
440         } else {
441             /*
442              * max is greater than 2gb - meeds more than 32 bits.
443              * Since lrand48 only will get a number up to 32bits.
444              */
445             long randnum;
446             randnum=divider(min, max, 0, -1);
447             return (long) (min + ((randnum % nmults) * mult));
448         }
449
450 #else
451         return (min + ((lrand48() % nmults) * mult));
452 #endif
453 }
454
455 /*
456  *  Attempts to be just like random_range, but everything is long long (64 bit)
457  */
458 long long
459 random_rangell(min, max, mult, errp)
460 long long       min;
461 long long       max;
462 long long       mult;
463 char            **errp;
464 {
465         long long       r, nmults, orig_min, orig_max, orig_mult, tmp;
466         long long       randnum;
467         extern long     lrand48();
468         static char     errbuf[128];
469
470         /*
471          * Sanity check
472          */
473
474         if (mult < 1) {
475                 if (errp != NULL) {
476                         sprintf(errbuf, "mult arg must be greater than 0");
477                         *errp = errbuf;
478                 }
479                 return -1;
480         }
481
482         /*
483          * Save original parameter values for use in error message
484          */
485
486         orig_min = min;
487         orig_max = max;
488         orig_mult = mult;
489
490         /*
491          * switch min/max if max < min
492          */
493
494         if (max < min) {
495                 tmp = max;
496                 max = min;
497                 min = tmp;
498         }
499
500         /*
501          * select the random number
502          */
503
504         if ((r = min % mult))     /* bump to the next higher 'mult' multiple */
505                 min += mult - r;
506
507         if ((r = max % mult))     /* reduce to the next lower 'mult' multiple */
508                 max -= r;
509
510         if (min > max) {         /* no 'mult' multiples between min & max */
511                 if (errp != NULL) {
512                     sprintf(errbuf,
513                         "no numbers in the range %lld:%lld that are a multiple of %lld",
514                         orig_min, orig_max, orig_mult);
515                     *errp = errbuf;
516                 }
517                 return -1;
518         }
519
520         if (errp != NULL) {
521                 *errp = NULL;
522         }
523
524         nmults = ((max - min) / mult) + 1;
525         /*
526          * If max is less than 2gb, then the value can fit in 32 bits
527          * and the standard lrand48() routine can be used.
528          */
529         if ( max <= (long)2147483647 ) {  
530             return (long long) (min + (((long long)lrand48() % nmults) * mult));
531         } else {
532             /*
533              * max is greater than 2gb - meeds more than 32 bits.
534              * Since lrand48 only will get a number up to 32bits.
535              */
536             randnum=divider(min, max, 0, -1);
537             return (long long) (min + ((randnum % nmults) * mult));
538         }
539
540 }
541
542 /*
543  * This functional will recusively call itself to return a random
544  * number min and max.   It was designed to work the 64bit numbers
545  * even when compiled as 32 bit process.
546  * algorithm:  to use the official lrand48() routine - limited to 32 bits.
547  *   find the difference between min and max (max-min).
548  *   if the difference is 2g or less, use the random number gotton from lrand48().
549  *   Determine the midway point between min and max.
550  *   if the midway point is less than 2g from min or max,
551  *      randomly add the random number gotton from lrand48() to
552  *      either min or the midpoint.
553  *   Otherwise, call outself with min and max being min and midway value or
554  *   midway value and max.  This will reduce the range in half.
555  */
556 static long long
557 divider(long long min, long long max, long long cnt, long long rand)
558 {
559     long long med, half, diff;
560
561     /*
562      * prevent run away code.  We are dividing by two each count.
563      * if we get to a count of more than 32, we should have gotten
564      * to 2gb.
565      */
566     if ( cnt > 32 )
567        return -1;
568
569     /*
570      * Only get a random number the first time.
571      */
572     if ( cnt == 0 || rand < -1 ) { 
573         rand = (long long)lrand48();  /* 32 bit random number */
574     }
575
576     diff = max - min;
577
578     if ( diff <= 2147483647 )
579         return min + rand;
580
581     half = diff/(long long)2;   /* half the distance between min and max */
582     med = min + half;           /* med way point between min and max */
583
584 #if DEBUG
585 printf("divider: min=%lld, max=%lld, cnt=%lld, rand=%lld\n", min, max, cnt, rand);
586 printf("   diff = %lld, half = %lld,   med = %lld\n", diff, half, med);
587 #endif
588
589     if ( half <= 2147483647 ) {
590         /*
591          * If half is smaller than 2gb, we can use the random number
592          * to pick the number within the min to med or med to max
593          * if the cnt bit of rand is zero or one, respectively.
594          */
595         if ( rand & (1<<cnt) )
596             return med + rand;
597         else
598             return min + rand;
599     } else {
600         /*
601          * recursively call ourself to reduce the value to the bottom half
602          * or top half (bit cnt is set).
603          */
604         if ( rand & (1<<cnt) ) {
605             return divider(med, max, cnt+1, rand);
606         } else {
607             return divider(min, med, cnt+1, rand);
608         }
609         
610     }
611
612 }
613
614
615 /*****************************************************************************
616  * random_range_seed(s)
617  *
618  * Sets the random seed to s.  Uses srand48(), assuming that lrand48() will
619  * be used in random_range().
620  *****************************************************************************/
621
622 void
623 random_range_seed(s)
624 long    s;
625 {
626     extern void srand48();
627
628     srand48(s);
629 }
630
631 /****************************************************************************
632  * random_bit(mask)
633  *
634  * This function randomly returns a single bit from the bits
635  * set in mask.  If mask is zero, zero is returned.
636  *
637  ****************************************************************************/
638 long
639 random_bit(long mask)
640 {
641     int nbits = 0;      /* number of set bits in mask */
642     long bit;           /* used to count bits and num of set bits choosen */
643     int nshift;         /* used to count bit shifts */
644
645     if ( mask == 0 )
646         return 0;
647
648     /*
649      * get the number of bits set in mask
650      */
651 #ifndef CRAY
652
653         bit=1L;
654         for ( nshift=0; nshift<sizeof(long)*8; nshift++) {
655                 if ( mask & bit )
656                         nbits++;
657                 bit=bit<<1;
658         }
659
660 #else
661         nbits=_popcnt(mask);
662 #endif  /* if CRAY */
663
664     /*
665      * randomly choose a bit.
666      */
667     bit=random_range(1, nbits, 1, NULL);
668
669     /*
670      * shift bits until you determine which bit was randomly choosen.
671      * nshift will hold the number of shifts to make.
672      */
673
674     nshift=0;
675     while (bit) {
676         /* check if the current one's bit is set */
677         if ( mask & 1L ) {
678             bit--;
679         }
680         mask = mask >> 1;
681         nshift++;
682     }
683
684     return 01L << (nshift-1);
685
686 }
687
688
689 #if RANDOM_BIT_UNITTEST
690 /*
691  *  The following is a unit test main function for random_bit().
692  */
693 main(argc, argv)
694 int argc;
695 char **argv;
696 {
697     int ind;
698     int cnt, iter;
699     long mask, ret;
700
701     printf("test for first and last bit set\n");
702     mask=1L;
703     ret=random_bit(mask);
704     printf("random_bit(%#o) returned %#o\n", mask, ret);
705
706     mask=1L<<(sizeof(long)*8-1);
707     ret=random_bit(mask);
708     printf("random_bit(%#o) returned %#o\n", mask, ret);
709
710     if ( argc >= 3 ) {
711         iter=atoi(argv[1]);
712         for (ind=2; ind<argc; ind++) {
713             printf("Calling random_bit %d times for mask %#o\n", iter, mask);
714             sscanf(argv[ind], "%i", &mask);
715             for (cnt=0; cnt<iter; cnt++) {
716                 ret=random_bit(mask);
717                 printf("random_bit(%#o) returned %#o\n", mask, ret);
718             }
719         }
720     }
721     exit(0);
722 }
723
724 #endif /* end if RANDOM_BIT_UNITTEST */
725
726
727 #if UNIT_TEST
728 /*
729  *  The following is a unit test main function for random_range*().
730  */
731
732 #define PARTNUM 10      /* used to determine even distribution of random numbers */
733 #define MEG  1024*1024*1024
734 #define GIG 1073741824
735 int
736 main(argc, argv)
737 int argc;
738 char **argv;
739 {
740     int ind;
741     int cnt, iter=10;
742     int imin=0, imult=1, itmin, itmax=0;
743 #if CRAY
744     int imax=6*GIG;     /* higher than 32 bits */
745 #else
746     int imax=1048576;
747 #endif
748
749     long lret, lmin=0, lmult=1, ltmin, ltmax=0; 
750 #if CRAY || (_MIPS_SZLONG == 64)
751     long lmax=6*(long)GIG;      /* higher than 32 bits */
752 #else
753     long lmax=1048576;
754 #endif
755     long long llret, llmin=0, llmult=1, lltmin, lltmax=0;
756     long long llmax=(long long)80*(long long)GIG;
757
758     long part;
759     long long lpart;
760     long cntarr[PARTNUM];
761     long valbound[PARTNUM];
762     long long lvalbound[PARTNUM];
763
764     for (ind=0; ind<PARTNUM; ind++ )
765         cntarr[ind]=0;
766     
767     if ( argc < 2 ) {
768         printf("Usage: %s func [iterations] \n", argv[0]);
769         printf("func can be random_range, random_rangel, random_rangell\n");
770         exit(1);
771     }
772
773     if ( argc >= 3 ) {
774         if ( sscanf(argv[2], "%i", &iter) != 1 ) {
775             printf("Usage: %s [func iterations] \n", argv[0]);
776             printf("argv[2] is not a number\n");
777             exit(1);
778         }
779     }
780
781
782     /*
783      * random_rangel ()
784      */
785     if ( strcmp(argv[1], "random_rangel") == 0 ) {
786         ltmin=lmax;
787         part = lmax/PARTNUM;
788         for(ind=0; ind<PARTNUM; ind++) {
789             valbound[ind]=part*ind;
790         }
791
792         for(cnt=0; cnt<iter; cnt++) {
793             lret=random_rangel(lmin, lmax, lmult, NULL);
794             if ( iter < 100 )
795                 printf("%ld\n", lret);
796             if ( lret < ltmin )
797                 ltmin = lret;
798             if ( lret > ltmax )
799                 ltmax = lret;
800             for(ind=0; ind<PARTNUM-1; ind++) {
801                 if ( valbound[ind]  < lret && lret <= valbound[ind+1] ) {
802                     cntarr[ind]++;
803                     break;
804                 }
805             }
806             if ( lret > valbound[PARTNUM-1] ) {
807                 cntarr[PARTNUM-1]++;
808             }
809         }
810         for(ind=0; ind<PARTNUM-1; ind++) {
811             printf("%2d %-13ld to  %-13ld   %5ld %4.4f\n", ind+1,
812                 valbound[ind], valbound[ind+1], cntarr[ind],
813                 (float)(cntarr[ind]/(float)iter));
814         }
815         printf("%2d %-13ld to  %-13ld   %5ld %4.4f\n", PARTNUM, 
816             valbound[PARTNUM-1], lmax, cntarr[PARTNUM-1],
817             (float)(cntarr[PARTNUM-1]/(float)iter));
818         printf("  min=%ld,  max=%ld\n", ltmin, ltmax);
819
820     } else if ( strcmp(argv[1], "random_rangell") == 0 ) {
821        /*
822         * random_rangell() unit test
823         */
824          lltmin=llmax;
825         lpart = llmax/PARTNUM;
826         for(ind=0; ind<PARTNUM; ind++) {
827             lvalbound[ind]=(long long)(lpart*ind);
828         }
829
830         for(cnt=0; cnt<iter; cnt++) {
831             llret=random_rangell(llmin, llmax, llmult, NULL);
832             if ( iter < 100 )
833                 printf("random_rangell returned %lld\n", llret);
834             if ( llret < lltmin )
835                 lltmin = llret;
836             if ( llret > lltmax )
837                 lltmax = llret;
838
839             for(ind=0; ind<PARTNUM-1; ind++) {
840                 if ( lvalbound[ind]  < llret && llret <= lvalbound[ind+1] ) {
841                     cntarr[ind]++;
842                     break;
843                 }
844             }
845             if ( llret > lvalbound[PARTNUM-1] ) {
846                 cntarr[PARTNUM-1]++;
847             }
848         }
849         for(ind=0; ind<PARTNUM-1; ind++) {
850             printf("%2d %-13lld to  %-13lld   %5ld %4.4f\n", ind+1,
851                 lvalbound[ind], lvalbound[ind+1], cntarr[ind],
852                 (float)(cntarr[ind]/(float)iter));
853         }
854         printf("%2d %-13lld to  %-13lld   %5ld %4.4f\n", PARTNUM,
855             lvalbound[PARTNUM-1], llmax, cntarr[PARTNUM-1],
856             (float)(cntarr[PARTNUM-1]/(float)iter));
857         printf("  min=%lld,  max=%lld\n", lltmin, lltmax);
858
859     } else {
860         /*
861          * random_range() unit test
862          */
863         itmin=imax;
864         part = imax/PARTNUM;
865         for(ind=0; ind<PARTNUM; ind++) {
866             valbound[ind]=part*ind;
867         }
868
869         for(cnt=0; cnt<iter; cnt++) {
870             lret=random_range(imin, imax, imult, NULL);
871             if ( iter < 100 )
872                 printf("%ld\n", lret);
873             if ( lret < itmin )
874                 itmin = lret;
875             if ( lret > itmax )
876                 itmax = lret;
877
878             for(ind=0; ind<PARTNUM-1; ind++) {
879                 if ( valbound[ind]  < lret && lret <= valbound[ind+1] ) {
880                     cntarr[ind]++;
881                     break;
882                 }
883             }
884             if ( lret > valbound[PARTNUM-1] ) {
885                 cntarr[PARTNUM-1]++;
886             }
887         }
888         for(ind=0; ind<PARTNUM-1; ind++) {
889             printf("%2d %-13ld to  %-13ld   %5ld %4.4f\n", ind+1,
890                 valbound[ind], valbound[ind+1], cntarr[ind],
891                 (float)(cntarr[ind]/(float)iter));
892         }
893         printf("%2d %-13ld to  %-13ld   %5ld %4.4f\n", PARTNUM, 
894             valbound[PARTNUM-1], (long)imax, cntarr[PARTNUM-1],
895             (float)(cntarr[PARTNUM-1]/(float)iter));
896         printf("  min=%d,  max=%d\n", itmin, itmax);
897
898     }
899
900     exit(0);
901 }
902
903 #endif