Permalink
Browse files

Fix bug with large 0 initialization in BigInteger. Add bigrand C# fun…

…ction. Use it to properly implement integer Range.roll (and by extension, Range.pick).
  • Loading branch information...
1 parent 3a38229 commit e3c9e7117dc60ee52477d0501b217e89b87fd14d @colomon colomon committed Sep 24, 2012
Showing with 28 additions and 2 deletions.
  1. +1 −1 lib/BigInteger.cs
  2. +26 −0 lib/Builtins.cs
  3. +1 −1 lib/CORE.setting
View
@@ -258,7 +258,7 @@ public BigInteger (byte[] value)
sign = 1;
if (sign == 1) {
- while (value [len - 1] == 0)
+ while (len > 1 && value [len - 1] == 0)
--len;
int full_words, size;
View
@@ -1105,6 +1105,32 @@ public partial class Builtins {
PromoteToBigInt(r3, n3)));
}
+ static readonly Func<Constants,Variable,Variable> bigrand_d = bigrand;
+ [ImplicitConsts] public static Variable bigrand(Constants c, Variable a1) {
+ // Assumes a1 is positive!
+ int r1;
+ P6any o1 = a1.Fetch();
+ if (!o1.mo.is_any)
+ return HandleSpecial1(c, a1, o1, bigrand_d);
+ P6any n1 = GetNumber(a1, o1, out r1);
+
+ BigInteger top = PromoteToBigInt(r1, n1);
+ int bits = (int) Math.Ceiling(BigInteger.Log(top, 2));
+ int bytes = bits / 8 + 1;
+ byte mask = (byte) ((1 << (bits % 8)) - 1);
+
+ Random rnd = new Random();
+ byte[] b = new byte[bytes + 1];
+ while (true) {
+ rnd.NextBytes(b);
+ b[bytes] = 0;
+ b[bytes - 1] &= mask;
+ BigInteger candidate = new BigInteger (b);
+ if (candidate < top)
+ return MakeInt(candidate);
+ }
+ }
+
[TrueGlobal] static IForeignInterpreter p5_interpreter;
public static Variable eval_perl5(Variable v) {
P6any o1 = v.Fetch();
View
@@ -3021,7 +3021,7 @@ my class Range is Cool does Positional {
my $elems = 1 + ($!excludes_max ?? $!max - 1 !! $!max) - $least;
sub choose {
- $elems ?? ($least + $elems.rand.floor) !! Any;
+ $elems ?? ($least + Q:CgOp { (bigrand {$elems}) }) !! Any;
}
return choose() xx * if $count ~~ Whatever;

0 comments on commit e3c9e71

Please sign in to comment.