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