I've watched this thread (as well as read the original slashdot story). Interesting stuff. George is right, though, the GPL code can't be incorporated. Recently I redid the random number generator in my code because I wanted it to be faster (well, I also wanted to play with RNGs in general). Below is a program to compare my code and the circle code. I base my algorithm pretty much verbatim from Knuth's Art of Computer Programming volume 2 (Semi-numerical algorithms). It uses no multiplication and is quite fast, with a tradeoff of maybe 220 bytes of memory. It has a period of (at least) 2^55 - 1. It can be adapted to generate floating point random numbers as well... I've considered doing this but have refrained. In my code I needed numbers generated on a normal distribution (ie the bell curve thing) and use floats for that purpose. Anyway, here's the code. It's faster, has a longer period, and has been proven in extensive tests (by others) to be quite reliable. My own experience indicates this as well. Knuth writes that he would recommend it completely except that though it has withstood a great deal of empirical testing, little theoretical work has made headway on it. The output of the program without optimizations is: Old: 51, new: 19 With -mpentium and -O9 on egcs 1.03a, the ouput is Old: 21, new: 6 So this one is about 3 times faster with a longer period than stock's. Use it anywhere you like, I don't care, and you don't have to put me in any credits or whatnot :) One thing. The code does use circle's old random number generator when it seeds itself, so you'll need to keep it around. --cut here-- #include <time.h> #include <stdio.h> #define m (unsigned long)2147483647 #define q (unsigned long)127773 #define a (unsigned int)16807 #define r (unsigned int)2836 /* ** F(z) = (az)%m ** = az-m(az/m) ** ** F(z) = G(z)+mT(z) ** G(z) = a(z%q)- r(z/q) ** T(z) = (z/q) - (az/m) ** ** F(z) = a(z%q)- rz/q+ m((z/q) - a(z/m)) ** = a(z%q)- rz/q+ m(z/q) - az */ static unsigned long seed; void circle_srandom_old(unsigned long initial_seed) { seed = initial_seed; } unsigned long circle_random_old(void) { register int lo, hi, test; hi = seed/q; lo = seed%q; test = a*lo - r*hi; if (test > 0) seed = test; else seed = test+ m; return seed; } /* new code below */ static unsigned long rand_list[56]; static unsigned long rand_j, rand_k; void circle_srandom_new(unsigned long seed) { int i; circle_srandom_old(seed); for (i = 0; i <= 55; i++) rand_list[i] = circle_random_old(); rand_list[24] |= 1; /* make sure all aren't even */ rand_j = 24; rand_k = 55; } unsigned long circle_random_new() { unsigned long retval; retval = rand_list[rand_k] = (rand_list[rand_k] + rand_list[rand_j]); rand_k--; rand_j--; if (rand_j == 0) rand_j = 55; else if (rand_k == 0) rand_k = 55; return retval; } #define NUM_TESTS 100000000 int main() { int i, delta1, delta2; circle_srandom_old(time(NULL)); circle_srandom_new(time(NULL)); delta1 = time(NULL); for (i = 0; i < NUM_TESTS; i++) circle_random_old(); delta1 = time(NULL) - delta1; delta2 = time(NULL); for (i = 0; i < NUM_TESTS; i++) circle_random_new(); delta2 = time(NULL) - delta2; printf("Old: %d, new: %d\n", delta1, delta2); return 0; } --cut here-- -- James Turner turnerjh@pattern.net UIN: 1102038 http://www.vuse.vanderbilt.edu/~turnerjh/ +------------------------------------------------------------+ | Ensure that you have read the CircleMUD Mailing List FAQ: | | http://democracy.queensu.ca/~fletcher/Circle/list-faq.html | +------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 12/15/00 PST