chiark / gitweb /
wip new bigfloats, debugged quite a lot
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 4 Oct 2020 14:22:52 +0000 (15:22 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 4 Oct 2020 14:22:52 +0000 (15:22 +0100)
   x= '!0000 ffff_ffff_fff0'; y= '+0000 0000_0000_0001'; i=Bigfloats.iter_upto(x, y, 4); i()
=> "!0000 ffff_0000_fff3"

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
templates/bigfloat.ts

index 22aa98f0089ea149458a7178a2c80dce15a5e36c..89c3cd1efcb2592e49f59df7bf50caebb819f005 100644 (file)
@@ -60,7 +60,7 @@ namespace Bigfloats {
     limbs: Limb[], // BE
   };
 
-  function unpack(p: Packed): Unpacked {
+  export function unpack(p: Packed): Unpacked {
     let head = p.match(UNPACK_HEAD_RE);
     UNPACK_LIMB_RE.lastIndex = 0;
     let limbs = [];
@@ -76,12 +76,12 @@ namespace Bigfloats {
     };
   }
 
-  function pack(v: Unpacked): Packed {
-    function hex16(v: number) { return '000' + v.toString(16).slice(-4); }
-    function hex48(v: Limb) {
-      return (hex16(v / 0x100000000) + '_' +
-             hex16(v &  0xffff0000) + '_' +
-             hex16(v /  0x0000ffff));
+  export function pack(v: Unpacked): Packed {
+    function hex16(x: number) { return ('000' + x.toString(16)).slice(-4); }
+    function hex48(x: Limb) {
+      return (hex16(Math.floor(x / 0x100000000)) + '_' +
+             hex16(           x &  0xffff0000)  + '_' +
+             hex16(           x &  0x0000ffff)        );
     }
     return (
       (v.sign < 0 ? '!' : '+') +
@@ -112,13 +112,33 @@ namespace Bigfloats {
   }
 
   function extend_left_so_index_valid(v: Unpacked, i: number): number {
+    // returns adjustment to apply to index
     let newlimb = ms_limb_from_sign(v);
+    let adj = 0;
     while (i < 0) {
       this.limbs.unshift(newlimb);
       this.exponent++;
       i++;
+      adj++;
+    }
+    return adj;
+  }
+
+  function add_to_limb(v: Unpacked, i: number, step: number): number {
+    // returns adjustment to apply to index
+    let totadj = 0;
+    for (;;) {
+      v.limbs[i] = Math.floor(v.limbs[i] + step);
+      if (v.limbs[i] < LIMB_MODULUS) return totadj;
+      i--;
+      if (i < 0) {
+       if (v.sign < 0) { v.sign = +1; return totadj; }
+       let adj = extend_left_so_index_valid(v, i);
+       i += adj;
+       totadj += adj;
+      }
+      step=1;
     }
-    return i;
   }
 
   export function iter_upto(ap: Packed, bp: Packed, count: number):
@@ -142,20 +162,19 @@ namespace Bigfloats {
       let avail = limb_mask(lb - la);
 
       let current = clone(av);
-      let i = extend_left_so_index_valid(current, ia);
+      let i = ia + extend_left_so_index_valid(current, ia);
       let step; // floating!
       if (avail > count+1) {
        step = avail / (count+1);
       } else {
-       current.limbs[i] += Math.floor(avail / 2);
+       i += add_to_limb(current, i, avail / 2);
        step = LIMB_MODULUS / (count+1);
        i++;
        current.limbs.length = i;
        current.limbs[i] = 0;
       }
       return function() {
-       current.limbs[i] += step;
-       current.limbs[i] = limb_mask(Math.floor(current.limbs[i]));
+       i += add_to_limb(current, i, step);
        return pack(current);
       }
     }