home *** CD-ROM | disk | FTP | other *** search
- //
- // 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.
- //