```nats←{⎕IO ⎕ML←0 1                           ⍝ Natural number arithmetic.

arith←{                                 ⍝ ⍺ ⍺⍺ ⍵, where ⍺⍺ ∊ +-×÷...
fn←⍺⍺{aa←⍺⍺ ⋄ ⊃⎕CR'aa'}⍵            ⍝ char rep of operand function.
'+'≡fn:ndn 0,+⌿⍺ mix ⍵              ⍝ sum.
'-'≡fn:nup-⌿dck ⍺ mix ⍵             ⍝ difference.
'×'≡fn:⍺ mul ⍵                      ⍝ product.
'*'≡fn:⍺ exp ⍵                      ⍝ exponent.
'÷'≡fn:⊃⍺ div ⍵                     ⍝ quotient.
'<≤=≥>≠'∊⍨fn:⍺⍺ cmp ⍺ mix ⍵         ⍝ relational.
'⌊'≡fn:(>cmp ⍺ mix ⍵)⊃⍺ ⍵           ⍝ min.
'⌈'≡fn:(<cmp ⍺ mix ⍵)⊃⍺ ⍵           ⍝ max.
'|'≡fn:⍺ res ⍵                      ⍝ residue.
'∨'≡fn:⍺ gcd ⍵                      ⍝ greatest common divisor.
'∧'≡fn:⍺ lcm ⍵                      ⍝ least common multiple.
err'Can''t do: ',fn                 ⍝ :-(
}

mul←{                                   ⍝ product.
dlz ndn 0,↑⍵{                       ⍝ normalised vector.
digit take←⍺                    ⍝ next digit and shift.
+⌿⍵ mix digit×take↑⍺⍺           ⍝ accumulated product.
}/(⍺,¨(⍴⍵)+⌽⍳⍴⍺),⊂,0                ⍝ digit-shift pairs.
}{                                      ⍝ guard against overflow:
m n←,↑⍴¨⍺ ⍵                         ⍝ numbers of rx-digits in each arg.
m>n:⍺ ∇⍨⍵                           ⍝ quicker if larger number on right.
n<(2*53)÷rx*2:⍺ ⍺⍺ ⍵                ⍝ ⍵ won't overflow: proceed.
s←⌊n÷2                              ⍝ digit-split for large ⍵.
p q←⍺∘∇¨(s↑⍵)(s↓⍵)                  ⍝ sub-products (see notes).
dlz ndn 0,+⌿(p,s↓n⍴0)mix q          ⍝ sum of sub-products.
}

exp←{                                   ⍝ exponent.
=cmp ⍵ mix,0:1                      ⍝ ⍺*0 → 1
=cmp ⍵ mix,1:⍺                      ⍝ ⍺*1 → ⍺
hlf←{dlz ndn(⌊⍵÷2)+0,¯1↓(rx÷2)×2|⍵} ⍝ quick ⌊⍵÷2.
evn←dlz ndn{⍵ mul ⍵}ndn ⍺ ∇ hlf ⍵   ⍝ even power
0=2|¯1↑⍵:evn ⋄ ⍺ mul evn            ⍝ even or odd power.
}

div←{                                   ⍝ quotient.
⍵∧.=0:⍺{⍺∧.=0:1 ⋄ err'Div by 0'}⍵   ⍝ ⍺÷0
svec←(⍴⍵)+⍳0⌈1+(⍴⍺)-⍴⍵              ⍝ shift vector.
↑⍵{                                 ⍝ fold along dividend.
r p←⍵                           ⍝ result & dividend.
q←⍺↑⍺⍺                          ⍝ shifted divisor.
ppqq←rx⊥⍉2 2↑p mix q            ⍝ 2 most sig digits of p & q.
r∆←p q{                         ⍝ next rx-digit of result.
(p q)(lo hi)←⍺ ⍵            ⍝ div and high-low test.
lo=hi-1:p{                  ⍝ convergence:
(≥cmp ⍺ mix ⍵)⊃lo hi    ⍝ low or high.
}dlz ndn 0,hi×q             ⍝ multiple.
mid←⌊0.5×lo+hi              ⍝ mid-point.
nxt←dlz ndn 0,q×mid         ⍝ next multiplier.
gt←>cmp p mix nxt           ⍝ greater than:
⍺ ∇ gt⊃2,/lo mid hi         ⍝ choose upper or lower interval.
}⌊0 1+↑÷/ppqq+(0 1)(1 0)        ⍝ lower and upper bounds of ratio.
mpl←dlz ndn 0,q×r∆              ⍝ multiple.
p∆←dlz nup-⌿p mix mpl           ⍝ remainder.
(r,r∆)p∆                        ⍝ result & remainder.
}/svec,⊂⍬ ⍺                         ⍝ fold-accumulated reslt.
}

gcd←{0∧.=⍵:⍺ ⋄ ⍵ ∇⊃⌽⍺ div ⍵}            ⍝ greatest common divisor.
lcm←{⍺ mul⊃⍵ div ⍺ gcd ⍵}               ⍝ least common multiple.
res←{⍺∧.=0:⍵ ⋄ ⊃⌽⍵ div ⍺}               ⍝ residue (0|⍵ → ⍵).

zro←{(1⌈⍴⍵)↑⍵}                          ⍝ 0 for ⍬.
ndn←{+⌿1 0⌽0 rx⊤⍵}⍣≡                    ⍝ normalise down: 3 21 → 5 1 (RH)
nup←{⍵++⌿0 1⌽rx ¯1∘.×⍵<0}⍣≡             ⍝ normalise up:   3 ¯1 → 2 9
mix←{↑(-(⍴⍺)⌈⍴⍵)↑¨⍺ ⍵}                  ⍝ right-aligned mix.
num←{dlzs rep ⎕D⍳chk⍕⍵}                 ⍝ vector of rx-digits.

chk←{∧/⍵∊⎕D:⍵ ⋄ err'Bad number: ',⍵}    ⍝ check raw no. not too big.
dck←{(2 1+(≥cmp ⍵)⌽0 ¯1)⌿⍵}             ⍝ difference check.
rep←{10⊥⍵{⍉⍵⍴(-×/⍵)↑⍺}(⌈(⍴⍵)÷px),px}    ⍝ radix rx rep of number.
fmt←{⎕D[zro dlzs,⍉(px⍴10)⊤⍵]}           ⍝ vector of chars.
cmp←{⍺⍺/,(<\≠⌿⍵)/⍵}                     ⍝ compare first different digit.
err←⎕SIGNAL∘11                          ⍝ stop with error msg ⍵.

fmt(num ⍺)⍺⍺ arith num ⍵                ⍝ char vector result.
}
code_colours

test script

Back to: notes

Back to: Workspaces
```