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