librarylibs/Polynomials/src/Polynomials.xtl
Polynomials: polynomials -- evaluation, sums, products, derivatives, integrals, real roots, text. Import it with an alias of your choice: "py:" u_se< "Polynomials". Put libs/Polynomials/src on XETAL_PATH ("just path"); the reference is libs/Polynomials/docs. Names with l: are exported; those under h: are private to this file.
A polynomial is its coefficients, highest power first, as APL's decode reads digits: 3 -2 1 is 3x^2 - 2x + 1. Results are Floats.
Evaluation
ˡa̲t : (Num a, Num b) => a -> b -> Float
p a_t x: p's value at each x: the coefficients decoded in radix x (APL's decode is Horner's rule, on any numbers).
ˡa̲t ← { p x → c ← f̲loat p◆ '{ v → v d̲ecode c } e̲ach f̲loat x }
Arithmetic
ʰt̲rim : Num a => a -> a
p without its leading zeros (at least one coefficient kept).
ʰt̲rim ← { p → n ← t̲ally w̲here '∧ s̲\ p = 0◆ (n m̲in (t̲ally p) − 1) d̲rop p }
ˡp̲lus : (Num a, Num b) => a -> b -> Float
a p_lus b: the sum.
ˡp̲lus ← { a b → n ← (t̲ally a) m̲ax t̲ally b ʰt̲rim ((n̲eg n) t̲ake f̲loat a) + (n̲eg n) t̲ake f̲loat b }
ˡt̲imes : (Num a, Num b) => a -> b -> Float
a t_imes b: the product: every product of a coefficient of a with one of b, summed by the power it belongs to.
ˡt̲imes ← { a b → m ← (f̲loat a) '× t̲able f̲loat b k ← r̲avel (o̲ffsets t̲ally a) '+ t̲able o̲ffsets t̲ally b v ← r̲avel m ʰt̲rim '{ i → '+ r̲/ (k = i) r̲eplicate v } e̲ach o̲ffsets (t̲ally a) + (t̲ally b) − 1 }
ˡd̲erivative : Num a => a -> Float
d_erivative p: the derivative (0 for a constant).
ˡd̲erivative ← { p → 1 = t̲ally p ? 1 r̲eshape 0.0 -1 d̲rop (f̲loat p) × f̲loat r̲ev o̲ffsets t̲ally p }
ˡi̲ntegral : Num a => a -> Float
i_ntegral p: the integral that is 0 at 0.
ˡi̲ntegral ← { p → ((f̲loat p) ÷ f̲loat 1 + r̲ev o̲ffsets t̲ally p) c̲at 0.0 }
Roots
ʰs̲tep : Num a => a -> Float -> Float
One Newton step for every x at once (a flat spot is nudged, not divided by).
ʰs̲tep ← { p x → d ← (ˡd̲erivative p) ˡa̲t x x − (p ˡa̲t x) ÷ d + 0.000000000001 × f̲loat d = 0.0 }
ˡr̲oots : Num a => a -> Float
r_oots p: the real roots, found by Newton's method from 64 starting points spread over the interval holding them all (Cauchy's bound), kept where the value is 0 to within 1e-9, rounded to 9 decimals.
ˡr̲oots ← { p → q ← ʰt̲rim f̲loat p 1 = t̲ally q ? 0 r̲eshape 0.0 b ← 1.0 + 'm̲ax r̲/ a̲bs (1 d̲rop q) ÷ f̲irst q x ← 60 '{ y → q ʰs̲tep y } p̲ower b × ((f̲loat o̲ffsets 64) ÷ 31.5) − 1.0 x ← (0.000000001 > a̲bs q ˡa̲t x) r̲eplicate x s̲ort u̲nique (f̲loat f̲loor 0.5 + x × 1000000000.0) ÷ 1000000000.0 }
Text
ʰs̲ize : Float -> Char
A coefficient's size as text: whole numbers without a point.
ʰs̲ize ← { c → a ← a̲bs c◆ a = f̲loat f̲loor a ? f̲ormat f̲loor a◆ f̲ormat a }
ʰp̲ow : Num a => a -> Char
x to the power k, as text.
ʰp̲ow ← { k → k = 0 ? ""◆ k = 1 ? "x"◆ "x^" c̲at f̲ormat k }
ʰt̲erm : Num a => Float -> a -> Char
One term, without its sign: the size (left out when it is 1 and a power of x follows) and the power.
ʰt̲erm ← { c k → (k > 0) ∧ 1.0 = a̲bs c ? ʰp̲ow k◆ (ʰs̲ize c) c̲at ʰp̲ow k }
ʰs̲ep : Float -> Char
The sign between terms.
ʰs̲ep ← { c → c < 0.0 ? " - "◆ " + " }
ˡt̲ext : Num a => a -> Char
t_ext p: the polynomial as text, 3x^2 - 2x + 1.
ˡt̲ext ← { p → c0 ← f̲loat ʰt̲rim p keep ← (c0 ≠ 0.0) ∨ 1 = t̲ally c0 c ← keep r̲eplicate c0 k ← keep r̲eplicate r̲ev o̲ffsets t̲ally c0 first ← (((f̲irst c) < 0.0) r̲eplicate "-") c̲at (f̲irst c) ʰt̲erm f̲irst k rest ← '{ i → (ʰs̲ep f̲irst i s̲elect c) c̲at (f̲irst i s̲elect c) ʰt̲erm f̲irst i s̲elect k } m̲ap 1 d̲rop r̲ange t̲ally c first c̲at "" ᵗj̲oin rest }