summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2025-03-23 13:25:57 -0700
committerKaz Kylheku <kaz@kylheku.com>2025-03-23 13:25:57 -0700
commit4b7a74d693fff116b5a8cc0820788004453278f2 (patch)
tree68fce90b4250a1a22fca9be0b39460170ab792e5
parent8999e74125d1ca2f526d25f437848861cdc19024 (diff)
downloadtxr-4b7a74d693fff116b5a8cc0820788004453278f2.tar.gz
txr-4b7a74d693fff116b5a8cc0820788004453278f2.tar.bz2
txr-4b7a74d693fff116b5a8cc0820788004453278f2.zip
rand: rearrange code to test fixnump first.
* rand.c (random): The fixnump is going to come up more often than bignum, and is also fast to test for since fixnums are identified by just the tag in value word.
-rw-r--r--rand.c92
1 files changed, 46 insertions, 46 deletions
diff --git a/rand.c b/rand.c
index 4610d8f7..ad79c523 100644
--- a/rand.c
+++ b/rand.c
@@ -367,52 +367,7 @@ val random(val state, val modulus)
cobj_handle(self, state, random_state_cls));
mp_int *m;
- if (bignump(modulus) && !mp_isneg(m = mp(modulus))) {
- ucnum bits = mp_count_bits(m) - mp_is_pow_two(m);
- ucnum rands_needed = (bits + 32 - 1) / 32;
- ucnum msb_rand_bits = bits % 32;
- rand32_t msb_rand_mask = convert(rand32_t, -1) >> (msb_rand_bits
- ? 32 - msb_rand_bits
- : 0);
- val out = make_bignum();
- mp_int *om = mp(out);
-
- for (;;) {
- ucnum i;
- for (i = 0; i < rands_needed; i++) {
- rand32_t rnd = rand32(r);
- mp_err mpe = MP_OKAY;
-#if MP_DIGIT_SIZE >= 4
- if (i > 0)
- mpe = mp_mul_2d(om, 32, om);
- else
- rnd &= msb_rand_mask;
- if (mpe == MP_OKAY)
- mpe = mp_add_d(om, rnd, om);
-#else
- if (i > 0)
- mpe = mp_mul_2d(om, 16, om);
- else
- rnd &= msb_rand_mask;
- if (mpe == MP_OKAY)
- mpe = mp_add_d(om, rnd & 0xFFFF, om);
- if (mpe == MP_OKAY)
- mpe = mp_mul_2d(om, 16, om);
- if (mpe == MP_OKAY)
- mp_add_d(om, rnd >> 16, om);
-#endif
- if (mpe != MP_OKAY)
- do_mp_error(self, mpe);
- }
- if (mp_cmp(om, m) != MP_LT) {
- mp_zero(om);
- continue;
- }
- break;
- }
-
- return normalize(out);
- } else if (fixnump(modulus)) {
+ if (fixnump(modulus)) {
cnum m = c_num(modulus, self);
if (m == 1) {
return zero;
@@ -583,6 +538,51 @@ val random(val state, val modulus)
default:
break;
}
+ } else if (bignump(modulus) && !mp_isneg(m = mp(modulus))) {
+ ucnum bits = mp_count_bits(m) - mp_is_pow_two(m);
+ ucnum rands_needed = (bits + 32 - 1) / 32;
+ ucnum msb_rand_bits = bits % 32;
+ rand32_t msb_rand_mask = convert(rand32_t, -1) >> (msb_rand_bits
+ ? 32 - msb_rand_bits
+ : 0);
+ val out = make_bignum();
+ mp_int *om = mp(out);
+
+ for (;;) {
+ ucnum i;
+ for (i = 0; i < rands_needed; i++) {
+ rand32_t rnd = rand32(r);
+ mp_err mpe = MP_OKAY;
+#if MP_DIGIT_SIZE >= 4
+ if (i > 0)
+ mpe = mp_mul_2d(om, 32, om);
+ else
+ rnd &= msb_rand_mask;
+ if (mpe == MP_OKAY)
+ mpe = mp_add_d(om, rnd, om);
+#else
+ if (i > 0)
+ mpe = mp_mul_2d(om, 16, om);
+ else
+ rnd &= msb_rand_mask;
+ if (mpe == MP_OKAY)
+ mpe = mp_add_d(om, rnd & 0xFFFF, om);
+ if (mpe == MP_OKAY)
+ mpe = mp_mul_2d(om, 16, om);
+ if (mpe == MP_OKAY)
+ mp_add_d(om, rnd >> 16, om);
+#endif
+ if (mpe != MP_OKAY)
+ do_mp_error(self, mpe);
+ }
+ if (mp_cmp(om, m) != MP_LT) {
+ mp_zero(om);
+ continue;
+ }
+ break;
+ }
+
+ return normalize(out);
}
uw_throwf(numeric_error_s, lit("~a: invalid modulus ~s"),