sourcelibs/Polynomials/src/Polynomials.xtlm

1⍝# Polynomials: its macro library -- p_oly<, maths notation compiled. 2⍝# Imported with the functions, under one alias: "py:" u_se< "Polynomials". 3⍝# A macro is a function from the source text written left and right of 4⍝# its call to the source that replaces the call, run before the program 5⍝# is compiled (X_eTaL MC10). Names with m: are macros; those under h: are 6⍝# private to this file. 7 8allowed ← ⎕D c̲at ".x^+-" 9 10⍝## Parsing 11 12⍝# The text without spaces. 13ʰs̲queezed ← { t → (t ≠ f̲irst " ") r̲eplicate t } 14 15⍝# The terms of a sum: a new term at each + or - after the first 16⍝# character; each keeps its sign. 17ʰt̲erms ← { t → 18 s ← (t m̲ember? "+-") ∧ (r̲ange t̲ally t) > 1 19 (1 + '+ s̲\ s) p̲artition t 20} 21 22⍝# A term's sign and the rest. 23ʰs̲ign ← { t → (f̲irst t) = f̲irst "-" ? -1.0◆ 1.0 } 24ʰb̲ody ← { t → (f̲irst t) m̲ember? "+-" ? 1 d̲rop t◆ t } 25 26⍝# Whether a term is well formed: digits and at most one point before 27⍝# x, then nothing, x, or x^ and digits. 28ʰw̲ell? ← { t → 29 b ← ʰb̲ody t 30 0 = t̲ally b ? 0 = 1 31 k ← t̲ally w̲here b = f̲irst "x" 32 k > 1 ? 0 = 1 33 k = 0 ? ʰn̲umeral? b 34 p ← f̲irst w̲here b = f̲irst "x" 35 c ← (p − 1) t̲ake b 36 e ← p d̲rop b 37 n̲ot (0 = t̲ally c) ∨ ʰn̲umeral? c ? 0 = 1 38 0 = t̲ally e ? 1 = 1 ⍝ x alone 39 n̲ot "^" m̲atch 1 t̲ake e ? 0 = 1 40 (1 < t̲ally e) ∧ '∧ r̲/ (1 d̲rop e) m̲ember? ⎕D 41} 42 43⍝# Whether a text is a number: digits with at most one point. 44ʰn̲umeral? ← { c → (0 < t̲ally c) ∧ ('∧ r̲/ c m̲ember? ⎕D c̲at ".") ∧ 1 ≥ t̲ally w̲here c = f̲irst "." } 45 46⍝# A well-formed term's power of x. 47ʰp̲ower ← { t → 48 b ← ʰb̲ody t 49 0 = t̲ally w̲here b = f̲irst "x" ? 0 50 e ← (f̲irst w̲here b = f̲irst "x") d̲rop b 51 0 = t̲ally e ? 1 52 f̲loor f̲irst n̲umbers 1 d̲rop e 53} 54 55⍝# A well-formed term's coefficient, with its sign. 56ʰc̲oefficient ← { t → 57 b ← ʰb̲ody t 58 p ← w̲here b = f̲irst "x" 59 c ← (f̲irst p c̲at 1 + t̲ally b) − 1 60 c ← c t̲ake b 61 0 = t̲ally c ? ʰs̲ign t 62 (ʰs̲ign t) × f̲irst n̲umbers c 63} 64 65⍝## The macro 66 67⍝# @ py:p_oly< "3x^2 - 2x + 1": the polynomial written in maths 68⍝# notation, compiled into its coefficients, highest power first 69⍝# (3.0 -2.0 1.0), when the program is compiled. Notation that is not a 70⍝# polynomial in x stops the compiler at it: error[bad-polynomial]. 71⍝# Nothing goes on the left (@). 72ᵐp̲oly< ← { none t → 73 ({ @ → 0 })_ none ⍝ the left side takes only @ (MC22) 74 s ← ʰs̲queezed t 75 (0 = t̲ally s) ∨ n̲ot '∧ r̲/ s m̲ember? allowed ? "bad-polynomial right" ⎕R̲EJECT t c̲at " is not a polynomial in x: use digits, x, ^, + and -" 76 ts ← ʰt̲erms s 77 n̲ot '∧ r̲/ '{ ʰw̲ell? d̲isclose ⍵ } e̲ach ts ? "bad-polynomial right" ⎕R̲EJECT t c̲at " is not a polynomial in x: each term is a number, x, or x^k" 78 k ← '{ ʰp̲ower d̲isclose ⍵ } e̲ach ts 79 c ← '{ ʰc̲oefficient d̲isclose ⍵ } e̲ach ts 80 d ← 'm̲ax r̲/ k 81 f̲ormat '{ i → '+ r̲/ (k = i) r̲eplicate c } e̲ach r̲ev o̲ffsets d + 1 82}