Home | History | Annotate | Download | only in lib
      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 
    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 
    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 
    238 int range_min(char *rbuf, int r)
    239 {
    240 	return ((struct range *)rbuf)[r].min;
    241 }
    242 
    243 int range_max(char *rbuf, int r)
    244 {
    245 	return ((struct range *)rbuf)[r].max;
    246 }
    247 
    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 
    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  */
    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  */
    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
    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 
    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  ****************************************************************************/
    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  */
    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
    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