I did a bunch of work months ago on the polynomial and rational function namespaces; now they can both participate in all of the generic functions, including derivatives and all arithmetic.
I realized today that I could use an ACTUAL polynomial instance in that wacky "find-path" example from pages 22-23 of SICM. Everything is way faster and makes more sense, since find-path returns an actual polynomial.
This function generates a polynomial by passing the (identity) polynomial into the Lagrange interpolation code: https://github.com/sicmutils/sicmutils/blob/main/src/sicmutils/polynomial/interpolate.cljc#L28
Because that code is written with generics, passing
(sicmutils.polynomial/identity)
forces the whole return value into a
Polynomial:
(defn from-points [xs]
(pi/lagrange xs (identity)))
Then Lagrange-interpolation-function
from the book is just a call to from-points
:
(defn Lagrange-interpolation-function [ys xs]
(p/from-points
(map vector xs ys)))
And now the book example runs 5-6x faster, and produces an ACTUAL polynomial, instead of an opaque function.
(e/find-path
(L/L-harmonic 1.0 1.0) 0. 1. (/ Math/PI 2) 0. 3)
;; "Elapsed time: 95.581625 msecs"
;; #object[sicmutils.polynomial.Polynomial 0x4d2ea0e6 "1: (0.9999999999999999*{} + 0.002014527898073215*{0 1} + -0.5127747212600422*{0 2} + 0.022442469684206934*{0 3} + 0.02875695785610377*{0 4})"]
Then of course that renders nicely as infix:
(sicmutils.env/->infix (sicmutils.polynomial/->expression *1 ['x]))
"0.02875695785610377 x⁴ + 0.022442469684206934 x³ -0.5127747212600422 x² + 0.002014527898073215 x + 0.9999999999999999"
And WolframAlpha is happy to graph that strange string with superscripts etc: https://www.wolframalpha.com/input/?i=0.02875695785610377+x%E2%81%B4+%2B+0.022442469684206934+x%C2%B3+-0.5127747212600422+x%C2%B2+%2B+0.002014527898073215+x+%2B+0.9999999999999999