This is Random.m in view mode; [Download] [Up]
// // Random // // <<See the file Random.h for more information>>. // // Version 1.1, 1992 Feb 27 // // Written by Gregor Purdy // gregor@umich.edu // // See the README file included for information // and distribution and usage rights. // #import <sys/time.h> #import <math.h> #import "Random.h" #define RAND_DEBUG @implementation Random + (int)version { return 2; // Was 0 last release, but should have been 1. } - init { [super init]; // Make a new instance using superclass' method [self newSeeds]; // Get a new seed for ourselves iset = 0; // No saved gaussian yet. gset = 0.0; gscale = 1.0; gorigin = 0.0; return self; } - initSeeds:(int)s1 :(int)s2 :(int)s3 { [super init]; [self setSeeds:s1 :s2 :s3]; return self; } - newSeeds { struct timeval theTime; // gettimeofday return structure gettimeofday(&theTime,0); // Get the time of day in seconds and microseconds h1 = theTime.tv_usec; // Set seed 1 by microseconds past second gettimeofday(&theTime,0); // Get the time of day in seconds and microseconds h2 = theTime.tv_usec; // Set seed 2 by microseconds past second gettimeofday(&theTime,0); // Get the time of day in seconds and microseconds h3 = theTime.tv_usec; // Set seed 3 by microseconds past second return self; } - setSeeds:(int) s1 :(int) s2 :(int) s3 { h1 = s1; // Set the seeds to the values given h2 = s2; h3 = s3; return self; } - getSeeds:(int *)s1 :(int *)s2 :(int *)s3 { if((s1 == NULL) || (s2 == NULL) || (s3 == NULL)) return nil; *s1 = h1; *s2 = h2; *s3 = h3; return self; } // // See the Source article for the explanations of these constants // #define M1 32771 #define M2 32779 #define M3 32783 #define F1 179 #define F2 183 #define F3 182 #define MAXNUM 32767 #define RANGE 32768 - (int) rand { h1 = (F1 * h1) % M1; // Update the sections h2 = (F2 * h2) % M2; h3 = (F2 * h3) % M3; if ((h1 > MAXNUM) || (h2 > MAXNUM) || (h3 > MAXNUM)) // If a section is out of range, return [self rand]; // return next result else // Otherwise, return (h1 + h2 + h3) % RANGE; // Return this result } - (int) randMax:(int)max { if(max <= 0) return 0; else return (int)((float)[self rand] / (float)RANGE * (float)(max + 1)); } - (int)randMin:(int)min max:(int)max { return min + [self randMax:(max - min)]; } - (double)percent { return ((double)[self rand] / (double)RANGE); } - (BOOL)bool { return ([self randMax:1]); } - (int)rollDie:(int) numSides { return [self randMax:(numSides - 1)] + 1; } - (int)roll:(int) numRolls die:(int) numSides { int temp = 0; int loop; for (loop = 1 ; loop <= numRolls ; loop++ ) temp += [self rollDie:numSides]; return temp; } - (int) rollBest:(int)numWanted of:(int)numRolls die:(int)numSides { int temp[numRolls]; // Array of rolls int loop1; // First loop control variable int loop2; // Second loop control variable int highest; // Index of highest found roll int accumulator = 0; // Accumulates total best roll for (loop1 = 1 ; loop1 <= numRolls ; loop1++) // Fill an array with rolls temp[loop1] = [self rollDie:numSides]; for (loop1 = 1 ; loop1 <= numWanted; loop1++) { highest = 1; // Start off as if first is highest for (loop2 = 2 ; loop2 <= numRolls ; loop2++) // Scan array for higher rolls if (temp[loop2] > temp[highest]) // If temp[loop2] is higher, then highest = loop2; // remember that fact accumulator += temp[highest]; // Add highest roll to accumulator temp[highest] = 0; // Clear highest roll so we don't find it again } return accumulator; // Return what we found } - (double)randFunc:(ddfunc)func { return (*func)([self percent]); } - (double)gScale { return gscale; } - setGScale:(double)aScale { gscale = aScale; return self; } - (double)gOrigin { return gorigin; } - setGOrigin:(double)anOrigin { gorigin = anOrigin; return self; } - (double)gaussian { double fac, r, v1, v2, temp; if(iset == 0) { // If none stored, calculate a pair. r = 0.0; while((r >= 1.0) || (r == 0.0)) { // Find a pair which are inside unit circle. v1 = 2.0 * [self percent] - 1.0; v2 = 2.0 * [self percent] - 1.0; r = (v1 * v1) + (v2 * v2); } fac = sqrt(-2.0 * log(r) / r); // Do Box-Muller transformation. gset = v1 * fac; iset = 1; temp = v2 * fac; // Return one of the pair. } else { // Otherwise return stored one. iset = 0; temp = gset; } return ((temp * gscale) + gorigin); // Modify the variable. } - read:(NXTypedStream *)stream { [super read:stream]; NXReadTypes(stream, "iiiiddd", &h1, &h2, &h3, &iset, &gset, &gscale, &gorigin); return self; } - write:(NXTypedStream *)stream { [super write:stream]; NXWriteTypes(stream, "iiiiddd", &h1, &h2, &h3, &iset, &gset, &gscale, &gorigin); return self; } @end // // End of file. //
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.