This is ElkinsEngine.m in view mode; [Download] [Up]
// // ElkinsEngine // // Copyright (C) 1992 Contemporary Design Studios. All rights reserved. // #import "ElkinsEngine.h" #import <sys/time.h> #import <stdio.h> // // Constants: // // See the journal article referenced in the header file. // #define M1 32771 #define M2 32779 #define M3 32783 #define F1 179 #define F2 183 #define F3 182 #define RANGE 32768 //#define RANGE 65536 #define MAXNUM (RANGE - 1) @implementation ElkinsEngine // // unit // // The ElkinsEngine, as defined in the article only uses 15 of the 16 bits // in an unsigned short. We want full bytes of random bits, so we must // throw away the partial byte. // + (ulong)unit { return 30; } // // init // - init { [super init]; [self newSeeds]; return self; } // // initSeeds::: // - initSeeds:(ushort)s1 :(ushort)s2 :(ushort)s3 { [super init]; [self setSeeds:s1 :s2 :s3]; return self; } // // newSeeds // - newSeeds { struct timeval theTime; // gettimeofday return structure // ushort foo; gettimeofday(&theTime, 0); // Get the time of day in seconds and microseconds h1 = theTime.tv_usec % RANGE; // Set seed 1 by microseconds past second gettimeofday(&theTime, 0); // Get the time of day in seconds and microseconds h2 = theTime.tv_usec % RANGE; // Set seed 2 by microseconds past second gettimeofday(&theTime, 0); // Get the time of day in seconds and microseconds h3 = theTime.tv_usec % RANGE; // Set seed 3 by microseconds past second // printf("ElkinsEngine: Seeds set to: %d %d %d\n", (long)h1, (long)h2, (long)h3); // [self makeRandom:(char *)(&foo)]; return self; } // // setSeeds::: // - setSeeds:(ushort) s1 :(ushort) s2 :(ushort) s3 { // ushort foo; h1 = s1; // Set the seeds to the values given h2 = s2; h3 = s3; // [self makeRandom:(char *)(&foo)]; return self; } // // getSeeds::: // - getSeeds:(ushort *)s1 :(ushort *)s2 :(ushort *)s3 { if((s1 == NULL) || (s2 == NULL) || (s3 == NULL)) return nil; *s1 = h1; *s2 = h2; *s3 = h3; return self; } // // makeRandom: // // See the Source article for the explanations of these constants: // - makeRandom:(uchar *)storage { ushort temp; int i; ushort *out = (ushort *)storage; do{ h1 = (F1 * h1) % M1; // Update the sections h2 = (F2 * h2) % M2; h3 = (F2 * h3) % M3; } while ((h1 > MAXNUM) || (h2 > MAXNUM) || (h3 > MAXNUM)); // If a section is out of range, temp = ((h1 + h2 + h3) % RANGE); for(i = 0; i < 15; i++) { do{ h1 = (F1 * h1) % M1; h2 = (F2 * h2) % M2; h3 = (F2 * h3) % M3; } while ((h1 > MAXNUM) || (h2 > MAXNUM) || (h3 > MAXNUM)); // // Save the value, and grab a bit from temp; // out[i] = (ushort)((h1 + h2 + h3) % RANGE) + ((temp & 0x0001) ? 0x8000 : 0x0000); temp = temp >> 1; } return self; } // // read: // - read:(NXTypedStream *)stream { int t1; // Stuff h's into ints for temporary. int t2; int t3; [super read:stream]; NXReadTypes(stream, "iii", &t1, &t2, &t3); h1 = (ushort)t1; h2 = (ushort)t2; h3 = (ushort)t3; return self; } // // write: // - write:(NXTypedStream *)stream { int t1 = (int)h1; // Stuff h's into ints for temporary. int t2 = (int)h2; int t3 = (int)h3; [super write:stream]; NXWriteTypes(stream, "iii", &t1, &t2, &t3); 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.