Nimber arithmetic

(or at least, heavily inspired by FreeBasic)

Not limited by integer size. Doesn't rely on twos complement bitwise and.

sub infix:<⊕> (Int $x, Int $y) { $x +^ $y }

sub infix:<⊗> (Int $x, Int $y) {
    return $x × $y if so $x|$y < 2;
    my $h = exp $x.lsb, 2;
    return ($h ⊗ $y) ⊕ (($x ⊕ $h) ⊗ $y) if $x > $h;
    return ($y ⊗ $x) if $y.lsb < $y.msb;
    return $x × $y unless my $comp = $x.lsb +& $y.lsb;
    $h = exp $comp.lsb, 2;
    (($x +> $h) ⊗ ($y +> $h)) ⊗ (3 +< ($h - 1))
}

# TESTING

my $upto = 26;

for <⊕>, &infix:<⊕>,
    <⊗>, &infix:<⊗>
  -> $op, &f {

    put " $op │", ^$upto .fmt('%3s'), "\n───┼", '────' x $upto;
    -> $r { put $r.fmt('%2s'), ' │', ^$upto .map: { &f($r, $_).fmt('%3s')} } for ^$upto;
    put "\n";
}

put "21508 ⊕ 42689 = ", 21508 ⊕ 42689;
put "21508 ⊗ 42689 = ", 21508 ⊗ 42689;

put "2150821508215082150821508 ⊕ 4268942689426894268942689 = ", 2150821508215082150821508 ⊕ 4268942689426894268942689;
put "2150821508215082150821508 ⊗ 4268942689426894268942689 = ", 2150821508215082150821508 ⊗ 4268942689426894268942689;

Output:

Last updated

Was this helpful?