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