ath@helios.prosys.se (Anders Thulin) (03/28/89)
The random number generator in GhostScript 1.2 occasionally returns negative numbers. The reason appear to be that the routine zrand() in zmath.c calls rand(), and does some juggling to avoid propagating the non-randomness in rand(). A possible patch would be to do something like: value &= 0x7FFFFFFF; but I wouldn't swear on the resulting generator being sufficiently random. Another approach would be to change to nrand48(). This would have the added benefit of avoiding possibly long loops in zsrand(). Suggested patches: *** zmath.old.c Fri Feb 24 09:11:39 1989 --- zmath.c Tue Mar 28 10:17:40 1989 *************** *** 32,45 **** double degrees_to_radians = M_PI / 180.0; double radians_to_degrees = 180.0 / M_PI; ! /* Iteration count for random number generator */ ! static long rand_count; /* Initialize the random number generator. */ void zmath_init() ! { rand_count = 0; ! srand(1); } /****** NOTE: none of these operators currently ******/ --- 32,44 ---- double degrees_to_radians = M_PI / 180.0; double radians_to_degrees = 180.0 / M_PI; ! /* Current seed for random number generator */ ! static unsigned short rand_seed[3] = {0,}; /* Initialize the random number generator. */ void zmath_init() ! { rand_seed[0] = rand_seed[1] = rand_seed[2] = 0; } /****** NOTE: none of these operators currently ******/ *************** *** 166,176 **** int zrand(register ref *op) { long value; ! /* The Unix man page for rand suggests dropping the lowest bits, */ ! /* so that's effectively what we do here. */ ! value = (long)rand() << 21; ! value += (long)rand() << 10; ! value += rand() >> 3; push(1); make_int(op, value); return 0; --- 165,171 ---- int zrand(register ref *op) { long value; ! value = nrand48(rand_seed); push(1); make_int(op, value); return 0; *************** *** 179,190 **** /* srand */ int zsrand(register ref *op) ! { long niter; check_type(*op, t_integer); ! niter = op->value.intval; ! rand_count = niter; ! srand(1); ! while ( niter-- ) rand(), rand(), rand(); pop(1); return 0; } --- 174,185 ---- /* srand */ int zsrand(register ref *op) ! { long seed; check_type(*op, t_integer); ! seed = op->value.intval; ! rand_seed[0] = seed >> 16; ! rand_seed[1] = seed & 0xFFFF; ! rand_seed[2] = 0x330E; pop(1); return 0; } *************** *** 193,199 **** int zrrand(register ref *op) { push(1); ! make_int(op, rand_count); return 0; } --- 188,194 ---- int zrrand(register ref *op) { push(1); ! make_int(op, (rand_seed[0]<<16) + rand_seed[1]); return 0; } *************** *** 218,220 **** --- 213,216 ---- }; z_op_init(my_defs); } + - - - - - - - end of patches - - - - - -- Anders Thulin INET : ath@prosys.se ProgramSystem AB UUCP : ...!{uunet,mcvax}!enea!prosys!ath Teknikringen 2A PHONE: +46 (0)13 21 40 40 S-583 30 Linkoping, Sweden FAX : +46 (0)13 21 36 35