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