mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
918 lines
23 KiB
C
918 lines
23 KiB
C
/*
|
|
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it would be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* Further, this software is distributed without any warranty that it is
|
|
* free of the rightful claim of any third person regarding infringement
|
|
* or the like. Any license provided herein, whether implied or
|
|
* otherwise, applies only to this software file. Patent licenses, if
|
|
* any, provided herein do not apply to combinations of this program with
|
|
* other software, or any other product whatsoever.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write the Free Software Foundation, Inc., 59
|
|
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
|
*
|
|
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
|
* Mountain View, CA 94043, or:
|
|
*
|
|
* http://www.sgi.com
|
|
*
|
|
* For further information regarding this notice, see:
|
|
*
|
|
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <malloc.h>
|
|
#include "random_range.h"
|
|
|
|
/*
|
|
* Internal format of the range array set up by parse_range()
|
|
*/
|
|
|
|
struct range {
|
|
int min;
|
|
int max;
|
|
int mult;
|
|
};
|
|
|
|
/*
|
|
* parse_ranges() is a function to parse a comma-separated list of range
|
|
* tokens each having the following form:
|
|
*
|
|
* num
|
|
* or
|
|
* min:max[:mult]
|
|
*
|
|
* any of the values may be blank (ie. min::mult, :max, etc.) and default
|
|
* values for missing arguments may be supplied by the caller.
|
|
*
|
|
* The special first form is short hand for 'num:num'.
|
|
*
|
|
* After parsing the string, the ranges are put into an array of integers,
|
|
* which is malloc'd by the routine. The min, max, and mult entries of each
|
|
* range can be extracted from the array using the range_min(), range_max(),
|
|
* and range_mult() functions.
|
|
*
|
|
* It is the responsibility of the caller to free the space allocated by
|
|
* parse_ranges() - a single call to free() will free the space.
|
|
*
|
|
* str The string to parse - assumed to be a comma-separated
|
|
* list of tokens having the above format.
|
|
* defmin default value to plug in for min, if it is missing
|
|
* defmax default value to plug in for max, if it is missing
|
|
* defmult default value to plug in for mult, if missing
|
|
* parse_func A user-supplied function pointer, which parse_ranges()
|
|
* can call to parse the min, max, and mult strings. This
|
|
* allows for customized number formats. The function
|
|
* MUST have the following prototype:
|
|
* parse_func(char *str, int *val)
|
|
* The function should return -1 if str cannot be parsed
|
|
* into an integer, or >= 0 if it was successfully
|
|
* parsed. The resulting integer will be stored in
|
|
* *val. If parse_func is NULL, parse_ranges will parse
|
|
* the tokens in a manner consistent with the the sscanf
|
|
* %i format.
|
|
* range_ptr A user-supplied char **, which will be set to point
|
|
* at malloc'd space which holds the parsed range
|
|
* values. If range_ptr is NULL, parse_ranges() just
|
|
* parses the string. The data returned in range_ptr
|
|
* should not be processed directly - use the functions
|
|
* range_min(), range_max(), and range_mult() to access
|
|
* data for a given range.
|
|
* errptr user-supplied char ** which can be set to point to a
|
|
* static error string. If errptr is NULL, it is ignored.
|
|
*
|
|
* parse_range() returns -1 on error, or the number of ranges parsed.
|
|
*/
|
|
|
|
static int str_to_int();
|
|
static long long divider(long long, long long, long long, long long);
|
|
|
|
int
|
|
parse_ranges(str, defmin, defmax, defmult, parse_func, rangeptr, errptr)
|
|
char *str;
|
|
int defmin;
|
|
int defmax;
|
|
int defmult;
|
|
int (*parse_func)();
|
|
char **rangeptr;
|
|
char **errptr;
|
|
{
|
|
int ncommas;
|
|
char *tmpstr, *cp, *tok, *n1str, *n2str, *multstr;
|
|
struct range *rp, *ranges;
|
|
static char errmsg[256];
|
|
|
|
if (errptr != NULL) {
|
|
*errptr = errmsg;
|
|
}
|
|
|
|
for (ncommas = 0, cp = str; *cp != '\0'; cp++) {
|
|
if (*cp == ',') {
|
|
ncommas++;
|
|
}
|
|
}
|
|
|
|
if (parse_func == NULL) {
|
|
parse_func = str_to_int;
|
|
}
|
|
|
|
tmpstr = strdup(str);
|
|
ranges = (struct range *)malloc((ncommas+1) * sizeof(struct range));
|
|
rp = ranges;
|
|
|
|
tok = strtok(tmpstr, ",");
|
|
while (tok != NULL) {
|
|
n1str = tok;
|
|
n2str = NULL;
|
|
multstr = NULL;
|
|
|
|
rp->min = defmin;
|
|
rp->max = defmax;
|
|
rp->mult = defmult;
|
|
|
|
if ((cp = strchr(n1str, ':')) != NULL) {
|
|
*cp = '\0';
|
|
n2str = cp+1;
|
|
|
|
if ((cp = strchr(n2str, ':')) != NULL) {
|
|
*cp = '\0';
|
|
multstr = cp+1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Parse the 'min' field - if it is zero length (:n2[:mult]
|
|
* format), retain the default value, otherwise, pass the
|
|
* string to the parse function.
|
|
*/
|
|
|
|
if ((int)strlen(n1str) > 0) {
|
|
if ((*parse_func)(n1str, &rp->min) < 0) {
|
|
sprintf(errmsg, "error parsing string %s into an integer", n1str);
|
|
free(tmpstr);
|
|
free(ranges);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Process the 'max' field - if one was not present (n1 format)
|
|
* set max equal to min. If the field was present, but
|
|
* zero length (n1: format), retain the default. Otherwise
|
|
* pass the string to the parse function.
|
|
*/
|
|
|
|
if (n2str == NULL) {
|
|
rp->max = rp->min;
|
|
} else if ((int)strlen(n2str) > 0) {
|
|
if ((*parse_func)(n2str, &rp->max) < 0) {
|
|
sprintf(errmsg, "error parsing string %s into an integer", n2str);
|
|
free(tmpstr);
|
|
free(ranges);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Process the 'mult' field - if one was not present
|
|
* (n1:n2 format), or the field was zero length (n1:n2: format)
|
|
* then set the mult field to defmult - otherwise pass then
|
|
* mult field to the parse function.
|
|
*/
|
|
|
|
if (multstr != NULL && (int)strlen(multstr) > 0) {
|
|
if ((*parse_func)(multstr, &rp->mult) < 0) {
|
|
sprintf(errmsg, "error parsing string %s into an integer", multstr);
|
|
free(tmpstr);
|
|
free(ranges);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
rp++;
|
|
tok = strtok(NULL, ",");
|
|
}
|
|
|
|
free(tmpstr);
|
|
|
|
if (rangeptr != NULL) {
|
|
*rangeptr = (char *)ranges;
|
|
} else {
|
|
free(ranges); /* just running in parse mode */
|
|
}
|
|
|
|
return (rp - ranges);
|
|
}
|
|
|
|
/*
|
|
* The default integer-parsing function
|
|
*/
|
|
|
|
static int
|
|
str_to_int(str, ip)
|
|
char *str;
|
|
int *ip;
|
|
{
|
|
char c;
|
|
|
|
if (sscanf(str, "%i%c", ip, &c) != 1) {
|
|
return -1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Three simple functions to return the min, max, and mult values for a given
|
|
* range. It is assumed that rbuf is a range buffer set up by parse_ranges(),
|
|
* and that r is a valid range within that buffer.
|
|
*/
|
|
|
|
int
|
|
range_min(rbuf, r)
|
|
char *rbuf;
|
|
int r;
|
|
{
|
|
return ((struct range *)rbuf)[r].min;
|
|
}
|
|
|
|
int
|
|
range_max(rbuf, r)
|
|
char *rbuf;
|
|
int r;
|
|
{
|
|
return ((struct range *)rbuf)[r].max;
|
|
}
|
|
|
|
int
|
|
range_mult(rbuf, r)
|
|
char *rbuf;
|
|
int r;
|
|
{
|
|
return ((struct range *)rbuf)[r].mult;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* random_range(int start, int end, int mult, char **errp)
|
|
*
|
|
* Returns a psuedo-random number which is >= 'start', <= 'end', and a multiple
|
|
* of 'mult'. Start and end may be any valid integer, but mult must be an
|
|
* integer > 0. errp is a char ** which will be set to point to a static
|
|
* error message buffer if it is not NULL, and an error occurs.
|
|
*
|
|
* The errp is the only way to check if the routine fails - currently the only
|
|
* failure conditions are:
|
|
*
|
|
* mult < 1
|
|
* no numbers in the start-end range that are a multiple of 'mult'
|
|
*
|
|
* If random_range_fails, and errp is a valid pointer, it will point to an
|
|
* internal error buffer. If errp is a vaild pointer, and random_range
|
|
* is successful, errp will be set to NULL.
|
|
*
|
|
* Note - if mult is 1 (the most common case), there are error conditions
|
|
* possible, and errp need not be used.
|
|
*
|
|
* Note: Uses lrand48(), assuming that set_random_seed() uses srand48() when
|
|
* setting the seed.
|
|
*****************************************************************************/
|
|
|
|
long
|
|
random_range(min, max, mult, errp)
|
|
int min;
|
|
int max;
|
|
int mult;
|
|
char **errp;
|
|
{
|
|
int r, nmults, orig_min, orig_max, orig_mult, tmp;
|
|
extern long lrand48();
|
|
static char errbuf[128];
|
|
|
|
/*
|
|
* Sanity check
|
|
*/
|
|
|
|
if (mult < 1) {
|
|
if (errp != NULL) {
|
|
sprintf(errbuf, "mult arg must be greater than 0");
|
|
*errp = errbuf;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Save original parameter values for use in error message
|
|
*/
|
|
|
|
orig_min = min;
|
|
orig_max = max;
|
|
orig_mult = mult;
|
|
|
|
/*
|
|
* switch min/max if max < min
|
|
*/
|
|
|
|
if (max < min) {
|
|
tmp = max;
|
|
max = min;
|
|
min = tmp;
|
|
}
|
|
|
|
/*
|
|
* select the random number
|
|
*/
|
|
|
|
if ((r = min % mult)) /* bump to the next higher 'mult' multiple */
|
|
min += mult - r;
|
|
|
|
if ((r = max % mult)) /* reduce to the next lower 'mult' multiple */
|
|
max -= r;
|
|
|
|
if (min > max) { /* no 'mult' multiples between min & max */
|
|
if (errp != NULL) {
|
|
sprintf(errbuf, "no numbers in the range %d:%d that are a multiple of %d", orig_min, orig_max, orig_mult);
|
|
*errp = errbuf;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
if (errp != NULL) {
|
|
*errp = NULL;
|
|
}
|
|
|
|
nmults = ((max - min) / mult) + 1;
|
|
#if CRAY
|
|
/*
|
|
* If max is less than 2gb, then the value can fit in 32 bits
|
|
* and the standard lrand48() routine can be used.
|
|
*/
|
|
if ( max <= (long)2147483647 ) {
|
|
return (long) (min + (((long)lrand48() % nmults) * mult));
|
|
} else {
|
|
/*
|
|
* max is greater than 2gb - meeds more than 32 bits.
|
|
* Since lrand48 only will get a number up to 32bits.
|
|
*/
|
|
long randnum;
|
|
randnum=divider(min, max, 0, -1);
|
|
return (long) (min + ((randnum % nmults) * mult));
|
|
}
|
|
|
|
#else
|
|
return (min + ((lrand48() % nmults) * mult));
|
|
#endif
|
|
|
|
}
|
|
|
|
/*
|
|
* Just like random_range, but all values are longs.
|
|
*/
|
|
long
|
|
random_rangel(min, max, mult, errp)
|
|
long min;
|
|
long max;
|
|
long mult;
|
|
char **errp;
|
|
{
|
|
long r, nmults, orig_min, orig_max, orig_mult, tmp;
|
|
extern long lrand48();
|
|
static char errbuf[128];
|
|
|
|
/*
|
|
* Sanity check
|
|
*/
|
|
|
|
if (mult < 1) {
|
|
if (errp != NULL) {
|
|
sprintf(errbuf, "mult arg must be greater than 0");
|
|
*errp = errbuf;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Save original parameter values for use in error message
|
|
*/
|
|
|
|
orig_min = min;
|
|
orig_max = max;
|
|
orig_mult = mult;
|
|
|
|
/*
|
|
* switch min/max if max < min
|
|
*/
|
|
|
|
if (max < min) {
|
|
tmp = max;
|
|
max = min;
|
|
min = tmp;
|
|
}
|
|
|
|
/*
|
|
* select the random number
|
|
*/
|
|
|
|
if ((r = min % mult)) /* bump to the next higher 'mult' multiple */
|
|
min += mult - r;
|
|
|
|
if ((r = max % mult)) /* reduce to the next lower 'mult' multiple */
|
|
max -= r;
|
|
|
|
if (min > max) { /* no 'mult' multiples between min & max */
|
|
if (errp != NULL) {
|
|
sprintf(errbuf,
|
|
"no numbers in the range %ld:%ld that are a multiple of %ld",
|
|
orig_min, orig_max, orig_mult);
|
|
*errp = errbuf;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
if (errp != NULL) {
|
|
*errp = NULL;
|
|
}
|
|
|
|
nmults = ((max - min) / mult) + 1;
|
|
#if CRAY || (_MIPS_SZLONG == 64)
|
|
/*
|
|
* If max is less than 2gb, then the value can fit in 32 bits
|
|
* and the standard lrand48() routine can be used.
|
|
*/
|
|
if ( max <= (long)2147483647 ) {
|
|
return (long) (min + (((long)lrand48() % nmults) * mult));
|
|
} else {
|
|
/*
|
|
* max is greater than 2gb - meeds more than 32 bits.
|
|
* Since lrand48 only will get a number up to 32bits.
|
|
*/
|
|
long randnum;
|
|
randnum=divider(min, max, 0, -1);
|
|
return (long) (min + ((randnum % nmults) * mult));
|
|
}
|
|
|
|
#else
|
|
return (min + ((lrand48() % nmults) * mult));
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Attempts to be just like random_range, but everything is long long (64 bit)
|
|
*/
|
|
long long
|
|
random_rangell(min, max, mult, errp)
|
|
long long min;
|
|
long long max;
|
|
long long mult;
|
|
char **errp;
|
|
{
|
|
long long r, nmults, orig_min, orig_max, orig_mult, tmp;
|
|
long long randnum;
|
|
extern long lrand48();
|
|
static char errbuf[128];
|
|
|
|
/*
|
|
* Sanity check
|
|
*/
|
|
|
|
if (mult < 1) {
|
|
if (errp != NULL) {
|
|
sprintf(errbuf, "mult arg must be greater than 0");
|
|
*errp = errbuf;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Save original parameter values for use in error message
|
|
*/
|
|
|
|
orig_min = min;
|
|
orig_max = max;
|
|
orig_mult = mult;
|
|
|
|
/*
|
|
* switch min/max if max < min
|
|
*/
|
|
|
|
if (max < min) {
|
|
tmp = max;
|
|
max = min;
|
|
min = tmp;
|
|
}
|
|
|
|
/*
|
|
* select the random number
|
|
*/
|
|
|
|
if ((r = min % mult)) /* bump to the next higher 'mult' multiple */
|
|
min += mult - r;
|
|
|
|
if ((r = max % mult)) /* reduce to the next lower 'mult' multiple */
|
|
max -= r;
|
|
|
|
if (min > max) { /* no 'mult' multiples between min & max */
|
|
if (errp != NULL) {
|
|
sprintf(errbuf,
|
|
"no numbers in the range %lld:%lld that are a multiple of %lld",
|
|
orig_min, orig_max, orig_mult);
|
|
*errp = errbuf;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
if (errp != NULL) {
|
|
*errp = NULL;
|
|
}
|
|
|
|
nmults = ((max - min) / mult) + 1;
|
|
/*
|
|
* If max is less than 2gb, then the value can fit in 32 bits
|
|
* and the standard lrand48() routine can be used.
|
|
*/
|
|
if ( max <= (long)2147483647 ) {
|
|
return (long long) (min + (((long long)lrand48() % nmults) * mult));
|
|
} else {
|
|
/*
|
|
* max is greater than 2gb - meeds more than 32 bits.
|
|
* Since lrand48 only will get a number up to 32bits.
|
|
*/
|
|
randnum=divider(min, max, 0, -1);
|
|
return (long long) (min + ((randnum % nmults) * mult));
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* This functional will recusively call itself to return a random
|
|
* number min and max. It was designed to work the 64bit numbers
|
|
* even when compiled as 32 bit process.
|
|
* algorithm: to use the official lrand48() routine - limited to 32 bits.
|
|
* find the difference between min and max (max-min).
|
|
* if the difference is 2g or less, use the random number gotton from lrand48().
|
|
* Determine the midway point between min and max.
|
|
* if the midway point is less than 2g from min or max,
|
|
* randomly add the random number gotton from lrand48() to
|
|
* either min or the midpoint.
|
|
* Otherwise, call outself with min and max being min and midway value or
|
|
* midway value and max. This will reduce the range in half.
|
|
*/
|
|
static long long
|
|
divider(long long min, long long max, long long cnt, long long rand)
|
|
{
|
|
long long med, half, diff;
|
|
|
|
/*
|
|
* prevent run away code. We are dividing by two each count.
|
|
* if we get to a count of more than 32, we should have gotten
|
|
* to 2gb.
|
|
*/
|
|
if ( cnt > 32 )
|
|
return -1;
|
|
|
|
/*
|
|
* Only get a random number the first time.
|
|
*/
|
|
if ( cnt == 0 || rand < -1 ) {
|
|
rand = (long long)lrand48(); /* 32 bit random number */
|
|
}
|
|
|
|
diff = max - min;
|
|
|
|
if ( diff <= 2147483647 )
|
|
return min + rand;
|
|
|
|
half = diff/(long long)2; /* half the distance between min and max */
|
|
med = min + half; /* med way point between min and max */
|
|
|
|
#if DEBUG
|
|
printf("divider: min=%lld, max=%lld, cnt=%lld, rand=%lld\n", min, max, cnt, rand);
|
|
printf(" diff = %lld, half = %lld, med = %lld\n", diff, half, med);
|
|
#endif
|
|
|
|
if ( half <= 2147483647 ) {
|
|
/*
|
|
* If half is smaller than 2gb, we can use the random number
|
|
* to pick the number within the min to med or med to max
|
|
* if the cnt bit of rand is zero or one, respectively.
|
|
*/
|
|
if ( rand & (1<<cnt) )
|
|
return med + rand;
|
|
else
|
|
return min + rand;
|
|
} else {
|
|
/*
|
|
* recursively call ourself to reduce the value to the bottom half
|
|
* or top half (bit cnt is set).
|
|
*/
|
|
if ( rand & (1<<cnt) ) {
|
|
return divider(med, max, cnt+1, rand);
|
|
} else {
|
|
return divider(min, med, cnt+1, rand);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* random_range_seed(s)
|
|
*
|
|
* Sets the random seed to s. Uses srand48(), assuming that lrand48() will
|
|
* be used in random_range().
|
|
*****************************************************************************/
|
|
|
|
void
|
|
random_range_seed(s)
|
|
long s;
|
|
{
|
|
extern void srand48();
|
|
|
|
srand48(s);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* random_bit(mask)
|
|
*
|
|
* This function randomly returns a single bit from the bits
|
|
* set in mask. If mask is zero, zero is returned.
|
|
*
|
|
****************************************************************************/
|
|
long
|
|
random_bit(long mask)
|
|
{
|
|
int nbits = 0; /* number of set bits in mask */
|
|
long bit; /* used to count bits and num of set bits choosen */
|
|
int nshift; /* used to count bit shifts */
|
|
|
|
if ( mask == 0 )
|
|
return 0;
|
|
|
|
/*
|
|
* get the number of bits set in mask
|
|
*/
|
|
#ifndef CRAY
|
|
|
|
bit=1L;
|
|
for ( nshift=0; nshift<sizeof(long)*8; nshift++) {
|
|
if ( mask & bit )
|
|
nbits++;
|
|
bit=bit<<1;
|
|
}
|
|
|
|
#else
|
|
nbits=_popcnt(mask);
|
|
#endif /* if CRAY */
|
|
|
|
/*
|
|
* randomly choose a bit.
|
|
*/
|
|
bit=random_range(1, nbits, 1, NULL);
|
|
|
|
/*
|
|
* shift bits until you determine which bit was randomly choosen.
|
|
* nshift will hold the number of shifts to make.
|
|
*/
|
|
|
|
nshift=0;
|
|
while (bit) {
|
|
/* check if the current one's bit is set */
|
|
if ( mask & 1L ) {
|
|
bit--;
|
|
}
|
|
mask = mask >> 1;
|
|
nshift++;
|
|
}
|
|
|
|
return 01L << (nshift-1);
|
|
|
|
}
|
|
|
|
|
|
#if RANDOM_BIT_UNITTEST
|
|
/*
|
|
* The following is a unit test main function for random_bit().
|
|
*/
|
|
main(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
int ind;
|
|
int cnt, iter;
|
|
long mask, ret;
|
|
|
|
printf("test for first and last bit set\n");
|
|
mask=1L;
|
|
ret=random_bit(mask);
|
|
printf("random_bit(%#o) returned %#o\n", mask, ret);
|
|
|
|
mask=1L<<(sizeof(long)*8-1);
|
|
ret=random_bit(mask);
|
|
printf("random_bit(%#o) returned %#o\n", mask, ret);
|
|
|
|
if ( argc >= 3 ) {
|
|
iter=atoi(argv[1]);
|
|
for (ind=2; ind<argc; ind++) {
|
|
printf("Calling random_bit %d times for mask %#o\n", iter, mask);
|
|
sscanf(argv[ind], "%i", &mask);
|
|
for (cnt=0; cnt<iter; cnt++) {
|
|
ret=random_bit(mask);
|
|
printf("random_bit(%#o) returned %#o\n", mask, ret);
|
|
}
|
|
}
|
|
}
|
|
exit(0);
|
|
}
|
|
|
|
#endif /* end if RANDOM_BIT_UNITTEST */
|
|
|
|
|
|
#if UNIT_TEST
|
|
/*
|
|
* The following is a unit test main function for random_range*().
|
|
*/
|
|
|
|
#define PARTNUM 10 /* used to determine even distribution of random numbers */
|
|
#define MEG 1024*1024*1024
|
|
#define GIG 1073741824
|
|
int
|
|
main(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
int ind;
|
|
int cnt, iter=10;
|
|
int imin=0, imult=1, itmin, itmax=0;
|
|
#if CRAY
|
|
int imax=6*GIG; /* higher than 32 bits */
|
|
#else
|
|
int imax=1048576;
|
|
#endif
|
|
|
|
long lret, lmin=0, lmult=1, ltmin, ltmax=0;
|
|
#if CRAY || (_MIPS_SZLONG == 64)
|
|
long lmax=6*(long)GIG; /* higher than 32 bits */
|
|
#else
|
|
long lmax=1048576;
|
|
#endif
|
|
long long llret, llmin=0, llmult=1, lltmin, lltmax=0;
|
|
long long llmax=(long long)80*(long long)GIG;
|
|
|
|
long part;
|
|
long long lpart;
|
|
long cntarr[PARTNUM];
|
|
long valbound[PARTNUM];
|
|
long long lvalbound[PARTNUM];
|
|
|
|
for (ind=0; ind<PARTNUM; ind++ )
|
|
cntarr[ind]=0;
|
|
|
|
if ( argc < 2 ) {
|
|
printf("Usage: %s func [iterations] \n", argv[0]);
|
|
printf("func can be random_range, random_rangel, random_rangell\n");
|
|
exit(1);
|
|
}
|
|
|
|
if ( argc >= 3 ) {
|
|
if ( sscanf(argv[2], "%i", &iter) != 1 ) {
|
|
printf("Usage: %s [func iterations] \n", argv[0]);
|
|
printf("argv[2] is not a number\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* random_rangel ()
|
|
*/
|
|
if ( strcmp(argv[1], "random_rangel") == 0 ) {
|
|
ltmin=lmax;
|
|
part = lmax/PARTNUM;
|
|
for(ind=0; ind<PARTNUM; ind++) {
|
|
valbound[ind]=part*ind;
|
|
}
|
|
|
|
for(cnt=0; cnt<iter; cnt++) {
|
|
lret=random_rangel(lmin, lmax, lmult, NULL);
|
|
if ( iter < 100 )
|
|
printf("%ld\n", lret);
|
|
if ( lret < ltmin )
|
|
ltmin = lret;
|
|
if ( lret > ltmax )
|
|
ltmax = lret;
|
|
for(ind=0; ind<PARTNUM-1; ind++) {
|
|
if ( valbound[ind] < lret && lret <= valbound[ind+1] ) {
|
|
cntarr[ind]++;
|
|
break;
|
|
}
|
|
}
|
|
if ( lret > valbound[PARTNUM-1] ) {
|
|
cntarr[PARTNUM-1]++;
|
|
}
|
|
}
|
|
for(ind=0; ind<PARTNUM-1; ind++) {
|
|
printf("%2d %-13ld to %-13ld %5ld %4.4f\n", ind+1,
|
|
valbound[ind], valbound[ind+1], cntarr[ind],
|
|
(float)(cntarr[ind]/(float)iter));
|
|
}
|
|
printf("%2d %-13ld to %-13ld %5ld %4.4f\n", PARTNUM,
|
|
valbound[PARTNUM-1], lmax, cntarr[PARTNUM-1],
|
|
(float)(cntarr[PARTNUM-1]/(float)iter));
|
|
printf(" min=%ld, max=%ld\n", ltmin, ltmax);
|
|
|
|
} else if ( strcmp(argv[1], "random_rangell") == 0 ) {
|
|
/*
|
|
* random_rangell() unit test
|
|
*/
|
|
lltmin=llmax;
|
|
lpart = llmax/PARTNUM;
|
|
for(ind=0; ind<PARTNUM; ind++) {
|
|
lvalbound[ind]=(long long)(lpart*ind);
|
|
}
|
|
|
|
for(cnt=0; cnt<iter; cnt++) {
|
|
llret=random_rangell(llmin, llmax, llmult, NULL);
|
|
if ( iter < 100 )
|
|
printf("random_rangell returned %lld\n", llret);
|
|
if ( llret < lltmin )
|
|
lltmin = llret;
|
|
if ( llret > lltmax )
|
|
lltmax = llret;
|
|
|
|
for(ind=0; ind<PARTNUM-1; ind++) {
|
|
if ( lvalbound[ind] < llret && llret <= lvalbound[ind+1] ) {
|
|
cntarr[ind]++;
|
|
break;
|
|
}
|
|
}
|
|
if ( llret > lvalbound[PARTNUM-1] ) {
|
|
cntarr[PARTNUM-1]++;
|
|
}
|
|
}
|
|
for(ind=0; ind<PARTNUM-1; ind++) {
|
|
printf("%2d %-13lld to %-13lld %5ld %4.4f\n", ind+1,
|
|
lvalbound[ind], lvalbound[ind+1], cntarr[ind],
|
|
(float)(cntarr[ind]/(float)iter));
|
|
}
|
|
printf("%2d %-13lld to %-13lld %5ld %4.4f\n", PARTNUM,
|
|
lvalbound[PARTNUM-1], llmax, cntarr[PARTNUM-1],
|
|
(float)(cntarr[PARTNUM-1]/(float)iter));
|
|
printf(" min=%lld, max=%lld\n", lltmin, lltmax);
|
|
|
|
} else {
|
|
/*
|
|
* random_range() unit test
|
|
*/
|
|
itmin=imax;
|
|
part = imax/PARTNUM;
|
|
for(ind=0; ind<PARTNUM; ind++) {
|
|
valbound[ind]=part*ind;
|
|
}
|
|
|
|
for(cnt=0; cnt<iter; cnt++) {
|
|
lret=random_range(imin, imax, imult, NULL);
|
|
if ( iter < 100 )
|
|
printf("%ld\n", lret);
|
|
if ( lret < itmin )
|
|
itmin = lret;
|
|
if ( lret > itmax )
|
|
itmax = lret;
|
|
|
|
for(ind=0; ind<PARTNUM-1; ind++) {
|
|
if ( valbound[ind] < lret && lret <= valbound[ind+1] ) {
|
|
cntarr[ind]++;
|
|
break;
|
|
}
|
|
}
|
|
if ( lret > valbound[PARTNUM-1] ) {
|
|
cntarr[PARTNUM-1]++;
|
|
}
|
|
}
|
|
for(ind=0; ind<PARTNUM-1; ind++) {
|
|
printf("%2d %-13ld to %-13ld %5ld %4.4f\n", ind+1,
|
|
valbound[ind], valbound[ind+1], cntarr[ind],
|
|
(float)(cntarr[ind]/(float)iter));
|
|
}
|
|
printf("%2d %-13ld to %-13ld %5ld %4.4f\n", PARTNUM,
|
|
valbound[PARTNUM-1], (long)imax, cntarr[PARTNUM-1],
|
|
(float)(cntarr[PARTNUM-1]/(float)iter));
|
|
printf(" min=%d, max=%d\n", itmin, itmax);
|
|
|
|
}
|
|
|
|
exit(0);
|
|
}
|
|
|
|
#endif
|