summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-12-21 14:28:56 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-12-21 14:28:56 -0800
commit28a3dc321c180dd708867406d3c2c5cc45b586e4 (patch)
tree3f9a6c082ac837595a797f6c5bdd12cae366119b
parent371d2635382eb0be35426983e7be5fed703024a6 (diff)
downloadtxr-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--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)