Attachment "None" to
ticket [402781ffff]
added by
dgp
2000-12-11 23:26:32.
Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.17
diff -c -r1.17 tclExecute.c
*** generic/tclExecute.c 2000/12/10 03:26:04 1.17
--- generic/tclExecute.c 2000/12/11 16:23:24
***************
*** 4050,4060 ****
register int stackTop; /* Cached top index of evaluation stack. */
Interp *iPtr = (Interp *) interp;
double dResult;
! int tmp;
if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
iPtr->flags |= RAND_SEED_INITIALIZED;
iPtr->randSeed = TclpGetClicks();
}
/*
--- 4050,4070 ----
register int stackTop; /* Cached top index of evaluation stack. */
Interp *iPtr = (Interp *) interp;
double dResult;
! long tmp; /* Algorithm assumes at least 32 bits.
! * Only long guarantees that. See below. */
if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
iPtr->flags |= RAND_SEED_INITIALIZED;
iPtr->randSeed = TclpGetClicks();
+
+ /*
+ * Make sure 1 <= randSeed <= (2^31) - 2. See below.
+ */
+
+ iPtr->randSeed &= (unsigned long) 0x7fffffff;
+ if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
+ iPtr->randSeed ^= 123459876;
+ }
}
/*
***************
*** 4067,4077 ****
* Generate the random number using the linear congruential
* generator defined by the following recurrence:
* seed = ( IA * seed ) mod IM
! * where IA is 16807 and IM is (2^31) - 1. In order to avoid
! * potential problems with integer overflow, the code uses
! * additional constants IQ and IR such that
* IM = IA*IQ + IR
! * For details on how this algorithm works, refer to the following
* papers:
*
* S.K. Park & K.W. Miller, "Random number generators: good ones
--- 4077,4096 ----
* Generate the random number using the linear congruential
* generator defined by the following recurrence:
* seed = ( IA * seed ) mod IM
! * where IA is 16807 and IM is (2^31) - 1. The recurrence maps
! * a seed in the range [1, IM - 1] to a new seed in that same range.
! * The recurrence maps IM to 0, and maps 0 back to 0, so those two
! * values must not be allowed as initial values of seed.
! *
! * In order to avoid potential problems with integer overflow, the
! * recurrence is implemented in terms of additional constants
! * IQ and IR such that
* IM = IA*IQ + IR
! * None of the operations in the implementation overflows a 32-bit
! * signed integer, and the C type long is guaranteed to be at least
! * 32 bits wide.
! *
! * For more details on how this algorithm works, refer to the following
* papers:
*
* S.K. Park & K.W. Miller, "Random number generators: good ones
***************
*** 4087,4100 ****
#define RAND_IR 2836
#define RAND_MASK 123459876
- if (iPtr->randSeed == 0) {
- /*
- * Don't allow a 0 seed, since it breaks the generator. Shift
- * it to some other value.
- */
-
- iPtr->randSeed = 123459876;
- }
tmp = iPtr->randSeed/RAND_IQ;
iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp;
if (iPtr->randSeed < 0) {
--- 4106,4111 ----
***************
*** 4102,4115 ****
}
/*
! * On 64-bit architectures we need to mask off the upper bits to
! * ensure we only have a 32-bit range. The constant has the
! * bizarre form below in order to make sure that it doesn't
! * get sign-extended (the rules for sign extension are very
! * concat, particularly on 64-bit machines).
*/
- iPtr->randSeed &= ((((unsigned long) 0xfffffff) << 4) | 0xf);
dResult = iPtr->randSeed * (1.0/RAND_IM);
/*
--- 4113,4122 ----
}
/*
! * Since the recurrence keeps seed values in the range [1, RAND_IM - 1],
! * dividing by RAND_IM yields a double in the range (0, 1).
*/
dResult = iPtr->randSeed * (1.0/RAND_IM);
/*
***************
*** 4256,4266 ****
}
/*
! * Reset the seed.
*/
iPtr->flags |= RAND_SEED_INITIALIZED;
iPtr->randSeed = i;
/*
* To avoid duplicating the random number generation code we simply
--- 4263,4278 ----
}
/*
! * Reset the seed. Make sure 1 <= randSeed <= 2^31 - 2.
! * See comments in ExprRandFunc() for more details.
*/
iPtr->flags |= RAND_SEED_INITIALIZED;
iPtr->randSeed = i;
+ iPtr->randSeed &= (unsigned long) 0x7fffffff;
+ if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
+ iPtr->randSeed ^= 123459876;
+ }
/*
* To avoid duplicating the random number generation code we simply
Index: tests/expr-old.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/expr-old.test,v
retrieving revision 1.9
diff -c -r1.9 expr-old.test
*** tests/expr-old.test 2000/05/09 00:00:36 1.9
--- tests/expr-old.test 2000/12/11 16:23:25
***************
*** 825,830 ****
--- 825,836 ----
test expr-old-32.51 {math functions in expressions} {
list [catch {expr {srand([lindex "6ty" 0])}} msg] $msg
} {1 {argument to math function didn't have numeric value}}
+ test expr-old-32.52 {math functions in expressions} {
+ expr {srand(1<<37) < 1}
+ } {1}
+ test expr-old-32.53 {math functions in expressions} {
+ expr {srand((1<<31) - 1) > 0}
+ } {1}
test expr-old-33.1 {conversions and fancy args to math functions} {
expr hypot ( 3 , 4 )