diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2011-12-21 14:28:56 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2011-12-21 14:28:56 -0800 |
commit | 28a3dc321c180dd708867406d3c2c5cc45b586e4 (patch) | |
tree | 3f9a6c082ac837595a797f6c5bdd12cae366119b | |
parent | 371d2635382eb0be35426983e7be5fed703024a6 (diff) | |
download | txr-28a3dc321c180dd708867406d3c2c5cc45b586e4.tar.gz txr-28a3dc321c180dd708867406d3c2c5cc45b586e4.tar.bz2 txr-28a3dc321c180dd708867406d3c2c5cc45b586e4.zip |
* rand.c (random): Bugfix: not building up sufficiently large bignums.
Work properly when mp_digit is smaller than 32 bits.
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | rand.c | 15 |
2 files changed, 17 insertions, 3 deletions
@@ -1,5 +1,10 @@ 2011-12-21 Kaz Kylheku <kaz@kylheku.com> + * rand.c (random): Bugfix: not building up sufficiently large bignums. + Work properly when mp_digit is smaller than 32 bits. + +2011-12-21 Kaz Kylheku <kaz@kylheku.com> + * Makefile (OBJS): new object file, rand.o. * eval.c: Includes rand.h header. @@ -166,15 +166,24 @@ val random(val state, val modulus) int digits = USED(m); int bits = digits * MP_DIGIT_BIT; int bits_needed = bits + 32; - int digits_needed = (bits_needed + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT; + int rands_needed = (bits_needed + 32 - 1) / 32; val out = make_bignum(); mp_int *om = mp(out); int i, err; - for (i = 0; i < digits_needed; i++) { + for (i = 0; i < rands_needed; i++) { + rand32_t rnd = rand32(r); +#if MP_DIGIT_SIZE >= 4 if (i > 0) mp_mul_2d(om, 32, om); - mp_add_d(om, rand32(r), om); + mp_add_d(om, rnd, om); +#else + if (i > 0) + mp_mul_2d(om, 16, om); + mp_add_d(om, rnd & 0xFFFF, om); + mp_mul_2d(om, 16, om); + mp_add_d(om, rnd >> 16, om); +#endif } err = mp_mod(om, m, om); if (err != MP_OKAY) |