word.bend source
word.bend on the hub · documented module
# word.bend: the vocabulary wordlib's laws are stated in.import Base# a bit as a Natdef b2n(b: Bool) -> Nat: match b: case False{}: 0n case True{}: 1n# p if k, else 0ndef scale(k: Bool, p: Nat) -> Nat: match k: case False{}: 0n case True{}: pdef pow2(n: Nat) -> Nat: match n: case 0n: 1n case 1n+p: Nat.double(pow2(p))# majority of three bits: a full adder's carry outdef maj(a: Bool, b: Bool, c: Bool) -> Bool: match a b c: case False{} False{} _: False{} case True{} True{} _: True{} case False{} True{} _: c case True{} False{} _: c# the carry out of Word.adc's add: the bit an n-bit sum overflows intodef carry(n: Nat, a: Word(n), b: Word(n), c: Bool) -> Bool: match n: case 0n: c case 1n+p: match a b: case WCon{ab, at} WCon{bb, bt}: carry(p, at, bt, maj(ab, bb, c))# the bit Word.shl.put(n, c, w) shifts out: w's top bit, or c when n is 0def top(n: Nat, c: Bool, w: Word(n)) -> Bool: match n: case 0n: c case 1n+p: match w: case WCon{b, t}: top(p, b, t)# the lowest bit (False for the empty word)def lsb(n: Nat, w: Word(n)) -> Bool: match n: case 0n: False{} case 1n+p: match w: case WCon{b, t}: b# how many times Word.mul.go's result wrapped past 2^n: each step adds the# carry of acc + b (on a 1 bit) and, for every later bit of a, the top bit# that shl pushed out of bdef mulq(+n: Nat, m: Nat, a: Word(m), +b: Word(n), +acc: Word(n)) -> Nat: match m: case 0n: 0n case 1n++mp: match a: case WCon{False{}, +at}: Nat.add(mulq(n, mp, at, Word.shl(n, b), acc), Nat.mul(Word.to_nat(mp, at), b2n(top(n, False{}, b)))) case WCon{True{}, +at}: Nat.add(mulq(n, mp, at, Word.shl(n, b), Word.add(n, acc, b)), Nat.add(Nat.mul(Word.to_nat(mp, at), b2n(top(n, False{}, b))), b2n(carry(n, acc, b, False{}))))