chiark / gitweb /
wip bigfloat
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 3 Oct 2020 23:24:26 +0000 (00:24 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 3 Oct 2020 23:24:26 +0000 (00:24 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
templates/bigfloat.ts [new file with mode: 0644]

diff --git a/templates/bigfloat.ts b/templates/bigfloat.ts
new file mode 100644 (file)
index 0000000..a9ee238
--- /dev/null
@@ -0,0 +1,99 @@
+// -*- JavaScript -*-
+
+// Copyright 2020 Ian Jackson
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// There is NO WARRANTY.
+
+// This is a really really shonky BigFloat with only a handful of
+// operations available!
+
+class Bigfloat {
+  exponent: number,
+  limbs: number[], // BE, limbs are each in [ 0, 2^48 )
+  // binary point is just before limbs[0]
+  // exponent is in limbs
+  // sign bit is top bit of limbs[0]
+  // always at least one limb
+
+  static type Iterator = function() => BigFlot;
+
+  static const LIMB_BIT      : number = 48;
+  private const LIMB_NEGATIVE : number = 1<<47;
+  private const LIMB_MODULUS  : number = 1<<48;
+
+  function constructor(j: { e: number, l: number[] }) {
+    this.exponent = e;
+    this.limbs = l;
+  }
+
+  private static l0_value(l0: number) -> number {
+    return l0 > Bigfloat.LIMB_NEGATIVE ? l0 - Bigfloat.LIMB_MODULUS : l0;
+  }
+
+  private limb_lookup(i) -> number {
+    if (i >= this.limbs.length) return 0;
+    if (i >= 0) return this.limbs[i];
+    let l0 = this.limbs[0];
+    return (l0 < Bigfloat.LIMB_NEGATIVE ? 0 : Bigfloat.LIMB_MODULUS-1);
+  }
+
+  function cmp(other: Bigfloat): boolean {
+    let de = other.exponent - this.exponent;
+    if (de) {
+      if ((de > 0 ? this : other).limbs[0] > Bigfloat.LIMB_NEGATIVE)
+       de *= -1;
+      return de;
+    }
+    let lt0v = BigFloat.l0_value(this.limbs[0]);
+    let lo0v = BigFloat.l0_value(other.limbs[0]);
+    return lo0 - lt0;
+  }
+
+  function extend_left() {
+    this.limbs.unshift(l0_value(this.limbs[0]));
+    this.exponent++;
+  }
+  
+  function iter_upto(endv: BigFloat, count: number):
+  {
+    // next() can be called count times
+    // to produce values > this, < endv
+    let e_out = Number.max(this.exponent, max.exponent);
+    for (e = e_out;
+        e;
+        e--) {
+      let it = e - this.exponent;
+      let ie = e - endv exponent;
+      if (it > this.limbs.length && ie > endv.limbs.length) {
+       // Oh actually these numbers are equal!
+       return function(){ this; }
+      }
+      let lt = this.limb_lookup(it)
+      let le = endv.limb_lookup(ie)
+      if (lt == le) continue;
+
+      let avail = (le - lt) & (BIGFLOAT_LIMB_MODULUS-1);
+      let start = this.copy();
+      while (it < 0) {
+       start.extend_left();
+       it++;
+      }
+      let step; // floating!
+      if (avail > count+1) {
+       step = avail / (count+1);
+      } else {
+       start[it] += (avail>>1);
+       step = Bigfloat.LIMB_MODULUS / (count+1);
+       it++;
+       start.length = it;
+       start[it] = 0;
+      }
+      return function() {
+       start[it] += step;
+       start[it] = Math.floor(start[it]);
+       start[it] &= (Bigfloat.LIMB_MODULUS-1);
+       return start.copy();
+      }
+    }
+  }
+}