xfstests updates - rework build to be like other xfs packages, revive some old fs...
[xfstests-dev.git] / lib / random_range.c
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., 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
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
101 int
102 parse_ranges(str, defmin, defmax, defmult, parse_func, rangeptr, errptr)
103 char    *str;
104 int     defmin;
105 int     defmax;
106 int     defmult;
107 int     (*parse_func)();
108 char    **rangeptr;
109 char    **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
222 static int
223 str_to_int(str, ip)
224 char    *str;
225 int     *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
242 int
243 range_min(rbuf, r)
244 char    *rbuf;
245 int     r;
246 {
247         return ((struct range *)rbuf)[r].min;
248 }
249
250 int
251 range_max(rbuf, r)
252 char    *rbuf;
253 int     r;
254 {
255         return ((struct range *)rbuf)[r].max;
256 }
257
258 int
259 range_mult(rbuf, r)
260 char    *rbuf;
261 int     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
291 long
292 random_range(min, max, mult, errp)
293 int     min;
294 int     max;
295 int     mult;
296 char    **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  */
381 long
382 random_rangel(min, max, mult, errp)
383 long    min;
384 long    max;
385 long    mult;
386 char    **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  */
472 long long
473 random_rangell(min, max, mult, errp)
474 long long       min;
475 long long       max;
476 long long       mult;
477 char            **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  */
570 static long long
571 divider(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
599 printf("divider: min=%lld, max=%lld, cnt=%lld, rand=%lld\n", min, max, cnt, rand);
600 printf("   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
636 void
637 random_range_seed(s)
638 long    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  ****************************************************************************/
652 long
653 random_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;
668         for ( nshift=0; nshift<sizeof(long)*8; nshift++) {
669                 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  */
707 main(argc, argv)
708 int argc;
709 char **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
749 int
750 main(argc, argv)
751 int argc;
752 char **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