summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--rand.c15
2 files changed, 17 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 82adbaf2..2e9563e7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/rand.c b/rand.c
index 47b882a4..e8d52965 100644
--- a/rand.c
+++ b/rand.c
@@ -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)