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
42struct range {
43	int min;
44	int max;
45	int mult;
46};
47
48/*
49 * parse_ranges() is a function to parse a comma-separated list of range
50 * tokens each having the following form:
51 *
52 *		num
53 *	or
54 *		min:max[:mult]
55 *
56 * any of the values may be blank (ie. min::mult, :max, etc.) and default
57 * values for missing arguments may be supplied by the caller.
58 *
59 * The special first form is short hand for 'num:num'.
60 *
61 * After parsing the string, the ranges are put into an array of integers,
62 * which is malloc'd by the routine.  The min, max, and mult entries of each
63 * range can be extracted from the array using the range_min(), range_max(),
64 * and range_mult() functions.
65 *
66 * It is the responsibility of the caller to free the space allocated by
67 * parse_ranges() - a single call to free() will free the space.
68 *
69 *	str		The string to parse - assumed to be a comma-separated
70 *			list of tokens having the above format.
71 *	defmin		default value to plug in for min, if it is missing
72 *	defmax		default value to plug in for max, if it is missing
73 *	defmult		default value to plug in for mult, if missing
74 *	parse_func	A user-supplied function pointer, which parse_ranges()
75 *			can call to parse the min, max, and mult strings.  This
76 *			allows for customized number formats.  The function
77 *			MUST have the following prototype:
78 *				parse_func(char *str, int *val)
79 *			The function should return -1 if str cannot be parsed
80 *			into an integer, or >= 0 if it was successfully
81 *			parsed.  The resulting integer will be stored in
82 *			*val.  If parse_func is NULL, parse_ranges will parse
83 *			the tokens in a manner consistent with the the sscanf
84 *			%i format.
85 *	range_ptr	A user-supplied char **, which will be set to point
86 *			at malloc'd space which holds the parsed range
87 *			values.   If range_ptr is NULL, parse_ranges() just
88 *			parses the string.  The data returned in range_ptr
89 *			should not be processed directly - use the functions
90 *			range_min(), range_max(), and range_mult() to access
91 *			data for a given range.
92 *	errptr		user-supplied char ** which can be set to point to a
93 *			static error string.  If errptr is NULL, it is ignored.
94 *
95 * parse_range() returns -1 on error, or the number of ranges parsed.
96 */
97
98static int str_to_int();
99static long long divider(long long, long long, long long, long long);
100
101int 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
221static 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
238int range_min(char *rbuf, int r)
239{
240	return ((struct range *)rbuf)[r].min;
241}
242
243int range_max(char *rbuf, int r)
244{
245	return ((struct range *)rbuf)[r].max;
246}
247
248int 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
278long 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 */
365long 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 */
451long 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 */
546static long long
547divider(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
612void 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 ****************************************************************************/
626long 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 */
679main(argc, argv)
680int argc;
681char **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
722int main(argc, argv)
723int argc;
724char **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