| 1 |
;; Polynomials |
|---|
| 2 |
;; Liam Healy, Tue Mar 21 2006 - 18:33 |
|---|
| 3 |
;; Time-stamp: <2008-03-17 21:35:52EDT polynomial.lisp> |
|---|
| 4 |
;; $Id$ |
|---|
| 5 |
|
|---|
| 6 |
(in-package :gsl) |
|---|
| 7 |
|
|---|
| 8 |
;;; Provide autotranslation from CL pure arrays? |
|---|
| 9 |
;;; Divided differences not complete/tested. |
|---|
| 10 |
|
|---|
| 11 |
;;;;**************************************************************************** |
|---|
| 12 |
;;;; Polynomial Evaluation |
|---|
| 13 |
;;;;**************************************************************************** |
|---|
| 14 |
|
|---|
| 15 |
(defmfun polynomial-eval (coefficients x) |
|---|
| 16 |
"gsl_poly_eval" |
|---|
| 17 |
(((gsl-array coefficients) :pointer) ((dim0 coefficients) size) (x :double)) |
|---|
| 18 |
:documentation ; FDL |
|---|
| 19 |
"Evaluate the polyonomial with coefficients at the point x." |
|---|
| 20 |
:c-return :double) |
|---|
| 21 |
|
|---|
| 22 |
;;;;**************************************************************************** |
|---|
| 23 |
;;;; Divided Difference Representation of Polynomials |
|---|
| 24 |
;;;;**************************************************************************** |
|---|
| 25 |
|
|---|
| 26 |
(defmfun divided-difference (dd xa ya) |
|---|
| 27 |
"gsl_poly_dd_init" |
|---|
| 28 |
(((gsl-array dd) :pointer) |
|---|
| 29 |
((gsl-array xa) :pointer) ((gsl-array ya) :pointer) |
|---|
| 30 |
((dim0 xa) size)) |
|---|
| 31 |
:return (dd)) |
|---|
| 32 |
|
|---|
| 33 |
(defmfun polynomial-eval-divided-difference (dd xa x) |
|---|
| 34 |
"gsl_poly_dd_eval" |
|---|
| 35 |
(((gsl-array dd) :pointer) |
|---|
| 36 |
((gsl-array xa) :pointer) |
|---|
| 37 |
((dim0 xa) size) |
|---|
| 38 |
(x :double)) |
|---|
| 39 |
:c-return :double |
|---|
| 40 |
:documentation ; FDL |
|---|
| 41 |
"Evaluate the polynomial stored in divided-difference form |
|---|
| 42 |
in the arrays dd and xa at the point x.") |
|---|
| 43 |
|
|---|
| 44 |
(defmfun taylor-divided-difference (coefs xp dd xa workspace) |
|---|
| 45 |
"gsl_poly_dd_taylor" |
|---|
| 46 |
(((gsl-array coefs) :pointer) |
|---|
| 47 |
(xp :double) |
|---|
| 48 |
((gsl-array dd) :pointer) |
|---|
| 49 |
((gsl-array xa) :pointer) |
|---|
| 50 |
((dim0 xa) size) |
|---|
| 51 |
((gsl-array workspace) :pointer)) |
|---|
| 52 |
:invalidate (coefs) |
|---|
| 53 |
:documentation ; FDL |
|---|
| 54 |
"Convert the divided-difference representation of a |
|---|
| 55 |
polynomial to a Taylor expansion. The divided-difference representation |
|---|
| 56 |
is supplied in the arrays dd and xa of the same length. |
|---|
| 57 |
On output the Taylor coefficients of the polynomial expanded about the |
|---|
| 58 |
point xp are stored in the array coefs which has the same length |
|---|
| 59 |
as xa and dd. A workspace of length must be provided.") |
|---|
| 60 |
|
|---|
| 61 |
;;;;**************************************************************************** |
|---|
| 62 |
;;;; Quadratic Equations |
|---|
| 63 |
;;;;**************************************************************************** |
|---|
| 64 |
|
|---|
| 65 |
(defmfun solve-quadratic (a b c) |
|---|
| 66 |
"gsl_poly_solve_quadratic" |
|---|
| 67 |
((a :double) (b :double) (c :double) (root1 :double) (root2 :double)) |
|---|
| 68 |
:c-return :number-of-answers |
|---|
| 69 |
:documentation ; FDL |
|---|
| 70 |
"The real roots of the quadratic equation a x^2 + b x + c = 0. |
|---|
| 71 |
Two values are always returned; if the roots are not real, these |
|---|
| 72 |
values are NIL.") |
|---|
| 73 |
|
|---|
| 74 |
(defmfun solve-quadratic-complex (a b c) |
|---|
| 75 |
"gsl_poly_complex_solve_quadratic" |
|---|
| 76 |
((a :double) (b :double) (c :double) (root1 gsl-complex) (root2 gsl-complex)) |
|---|
| 77 |
:c-return :number-of-answers |
|---|
| 78 |
:documentation ; FDL |
|---|
| 79 |
"The complex roots of the quadratic equation a x^2 + b x + c = 0. |
|---|
| 80 |
Two values are always returned; if a root does not exist, the |
|---|
| 81 |
value returned will be NIL.") |
|---|
| 82 |
|
|---|
| 83 |
;;;;**************************************************************************** |
|---|
| 84 |
;;;; Cubic Equations |
|---|
| 85 |
;;;;**************************************************************************** |
|---|
| 86 |
|
|---|
| 87 |
(defmfun solve-cubic (a b c) |
|---|
| 88 |
"gsl_poly_solve_cubic" |
|---|
| 89 |
((a :double) (b :double) (c :double) |
|---|
| 90 |
(root1 :double) (root2 :double) (root3 :double)) |
|---|
| 91 |
:c-return :number-of-answers |
|---|
| 92 |
:documentation ; FDL |
|---|
| 93 |
"Find the real roots of the cubic equation, x^3 + a x^2 + b x + c = 0 |
|---|
| 94 |
with a leading coefficient of unity. The roots are given |
|---|
| 95 |
in ascending order. Three values are always returned; |
|---|
| 96 |
if a root is not real, the value returned for it will be NIL.") |
|---|
| 97 |
|
|---|
| 98 |
(defmfun solve-cubic-complex (a b c) |
|---|
| 99 |
"gsl_poly_complex_solve_cubic" |
|---|
| 100 |
((a :double) (b :double) (c :double) |
|---|
| 101 |
(root1 gsl-complex) (root2 gsl-complex) (root3 gsl-complex)) |
|---|
| 102 |
:c-return :number-of-answers |
|---|
| 103 |
:documentation ; FDL |
|---|
| 104 |
"Find the complex roots of the cubic equation, x^3 + a x^2 + b x + c = 0 |
|---|
| 105 |
with a leading coefficient of unity. Three values are always returned; |
|---|
| 106 |
if a root does not exist, the value returned for it will be NIL.") |
|---|
| 107 |
|
|---|
| 108 |
;;;;**************************************************************************** |
|---|
| 109 |
;;;; General Polynomial Equations |
|---|
| 110 |
;;;;**************************************************************************** |
|---|
| 111 |
|
|---|
| 112 |
(defgo-s (complex-workspace n) |
|---|
| 113 |
allocate-complex-workspace free-complex-workspace) |
|---|
| 114 |
|
|---|
| 115 |
(defmfun allocate-complex-workspace (n) |
|---|
| 116 |
"gsl_poly_complex_workspace_alloc" ((n size)) |
|---|
| 117 |
:c-return :pointer |
|---|
| 118 |
:export nil |
|---|
| 119 |
:index (letm complex-workspace)) |
|---|
| 120 |
|
|---|
| 121 |
(defmfun free-complex-workspace (ws) |
|---|
| 122 |
"gsl_poly_complex_workspace_free" ((ws :pointer)) |
|---|
| 123 |
:c-return :void |
|---|
| 124 |
:export nil |
|---|
| 125 |
:index (letm complex-workspace)) |
|---|
| 126 |
|
|---|
| 127 |
(defun polynomial-solve (coefficients) |
|---|
| 128 |
;; FDL |
|---|
| 129 |
"The roots of the general polynomial |
|---|
| 130 |
P(x) = a_0 + a_1 x + a_2 x^2 + ... + a_{n-1} x^{n-1} using |
|---|
| 131 |
balanced-QR reduction of the companion matrix. The parameter n |
|---|
| 132 |
specifies the length of the coefficient array. The coefficient of the |
|---|
| 133 |
highest order term must be non-zero. The function requires a workspace |
|---|
| 134 |
w of the appropriate size. The n-1 roots are returned in |
|---|
| 135 |
the packed complex array z of length 2(n-1), alternating |
|---|
| 136 |
real and imaginary parts." |
|---|
| 137 |
(let ((len (length coefficients))) |
|---|
| 138 |
(letm ((coef (vector-double-float coefficients)) |
|---|
| 139 |
(answer (vector-double-float (* 2 (1- len)))) |
|---|
| 140 |
(ws (complex-workspace len))) |
|---|
| 141 |
(values-list (polynomial-solve-ws coef ws answer))))) |
|---|
| 142 |
|
|---|
| 143 |
(defmfun polynomial-solve-ws (coefficients workspace answer-pd) |
|---|
| 144 |
"gsl_poly_complex_solve" |
|---|
| 145 |
(((gsl-array coefficients) :pointer) ((dim0 coefficients) size) |
|---|
| 146 |
(workspace :pointer) ((gsl-array answer-pd) :pointer)) |
|---|
| 147 |
:return |
|---|
| 148 |
((loop for i from 0 below (dim0 answer-pd) by 2 |
|---|
| 149 |
collect (complex (maref answer-pd i) |
|---|
| 150 |
(maref answer-pd (1+ i))))) |
|---|
| 151 |
:documentation ; FDL |
|---|
| 152 |
"Arguments are: |
|---|
| 153 |
a GSL array of coefficients, a workspace, a gsl-array of doubles." |
|---|
| 154 |
:export nil |
|---|
| 155 |
:index polynomial-solve) |
|---|
| 156 |
|
|---|
| 157 |
|
|---|
| 158 |
;;;;**************************************************************************** |
|---|
| 159 |
;;;; Examples and unit test |
|---|
| 160 |
;;;;**************************************************************************** |
|---|
| 161 |
|
|---|
| 162 |
#| |
|---|
| 163 |
(make-tests polynomial |
|---|
| 164 |
(letm ((xa (vector-double-float #(0.0d0 1.0d0 2.0d0 3.0d0))) |
|---|
| 165 |
(ya (vector-double-float #(2.5d0 7.2d0 32.7d0 91.0d0))) |
|---|
| 166 |
(dd (vector-double-float 4))) |
|---|
| 167 |
(divided-difference dd xa ya) |
|---|
| 168 |
(list |
|---|
| 169 |
(polynomial-eval-divided-difference dd xa 0.0d0) |
|---|
| 170 |
(polynomial-eval-divided-difference dd xa 1.0d0) |
|---|
| 171 |
(polynomial-eval-divided-difference dd xa 2.0d0) |
|---|
| 172 |
(polynomial-eval-divided-difference dd xa 3.0d0))) |
|---|
| 173 |
(letm ((vec (vector-double-float #(1.0d0 2.0d0 3.0d0)))) |
|---|
| 174 |
(polynomial-eval vec -1.0d0)) |
|---|
| 175 |
(solve-quadratic 1.0d0 0.0d0 1.0d0) |
|---|
| 176 |
(solve-quadratic 1.0d0 -2.0d0 1.0d0) |
|---|
| 177 |
(solve-quadratic-complex 1.0d0 -2.0d0 1.0d0) |
|---|
| 178 |
(solve-cubic -6.0d0 -13.0d0 42.0d0) |
|---|
| 179 |
(solve-cubic-complex -1.0d0 1.0d0 -1.0d0) |
|---|
| 180 |
;; Example from GSL manual |
|---|
| 181 |
(polynomial-solve #(-1.0d0 0.0d0 0.0d0 0.0d0 0.0d0 1.0d0))) |
|---|
| 182 |
|# |
|---|
| 183 |
|
|---|
| 184 |
(LISP-UNIT:DEFINE-TEST POLYNOMIAL |
|---|
| 185 |
(LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 186 |
(LIST (LIST 2.5d0 7.2d0 32.7d0 91.0d0)) |
|---|
| 187 |
(MULTIPLE-VALUE-LIST |
|---|
| 188 |
(LETM |
|---|
| 189 |
((XA (VECTOR-DOUBLE-FLOAT #(0.0d0 1.0d0 2.0d0 3.0d0))) |
|---|
| 190 |
(YA (VECTOR-DOUBLE-FLOAT #(2.5d0 7.2d0 32.7d0 91.0d0))) |
|---|
| 191 |
(DD (VECTOR-DOUBLE-FLOAT 4))) |
|---|
| 192 |
(DIVIDED-DIFFERENCE DD XA YA) |
|---|
| 193 |
(LIST |
|---|
| 194 |
(POLYNOMIAL-EVAL-DIVIDED-DIFFERENCE DD XA 0.0d0) |
|---|
| 195 |
(POLYNOMIAL-EVAL-DIVIDED-DIFFERENCE DD XA 1.0d0) |
|---|
| 196 |
(POLYNOMIAL-EVAL-DIVIDED-DIFFERENCE DD XA 2.0d0) |
|---|
| 197 |
(POLYNOMIAL-EVAL-DIVIDED-DIFFERENCE DD XA 3.0d0))))) |
|---|
| 198 |
(LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 199 |
(LIST 2.0d0) |
|---|
| 200 |
(MULTIPLE-VALUE-LIST |
|---|
| 201 |
(LETM ((VEC (VECTOR-DOUBLE-FLOAT #(1.0d0 2.0d0 3.0d0)))) |
|---|
| 202 |
(POLYNOMIAL-EVAL VEC -1.0d0)))) |
|---|
| 203 |
(LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 204 |
(LIST (LIST) (LIST)) |
|---|
| 205 |
(MULTIPLE-VALUE-LIST |
|---|
| 206 |
(SOLVE-QUADRATIC 1.0d0 0.0d0 1.0d0))) |
|---|
| 207 |
(LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 208 |
(LIST 1.0d0 1.0d0) |
|---|
| 209 |
(MULTIPLE-VALUE-LIST (SOLVE-QUADRATIC 1.0d0 -2.0d0 1.0d0))) |
|---|
| 210 |
(LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 211 |
(LIST #C(1.0d0 0.0d0) #C(1.0d0 0.0d0)) |
|---|
| 212 |
(MULTIPLE-VALUE-LIST |
|---|
| 213 |
(SOLVE-QUADRATIC-COMPLEX 1.0d0 -2.0d0 1.0d0))) |
|---|
| 214 |
(LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 215 |
(LIST -3.000000000000001d0 1.9999999999999996d0 |
|---|
| 216 |
7.000000000000001d0) |
|---|
| 217 |
(MULTIPLE-VALUE-LIST |
|---|
| 218 |
(SOLVE-CUBIC -6.0d0 -13.0d0 42.0d0))) |
|---|
| 219 |
(LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 220 |
(LIST #C(-5.551115123125783d-17 -0.9999999999999999d0) |
|---|
| 221 |
#C(-5.551115123125783d-17 0.9999999999999999d0) |
|---|
| 222 |
#C(1.0d0 0.0d0)) |
|---|
| 223 |
(MULTIPLE-VALUE-LIST |
|---|
| 224 |
(SOLVE-CUBIC-COMPLEX -1.0d0 1.0d0 -1.0d0))) |
|---|
| 225 |
(LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 226 |
(LIST #C(-0.8090169943749477d0 0.5877852522924734d0) |
|---|
| 227 |
#C(-0.8090169943749477d0 -0.5877852522924734d0) |
|---|
| 228 |
#C(0.3090169943749475d0 0.951056516295153d0) |
|---|
| 229 |
#C(0.3090169943749475d0 -0.951056516295153d0) |
|---|
| 230 |
#C(0.9999999999999999d0 0.0d0)) |
|---|
| 231 |
(MULTIPLE-VALUE-LIST |
|---|
| 232 |
(POLYNOMIAL-SOLVE |
|---|
| 233 |
#(-1.0d0 0.0d0 0.0d0 0.0d0 0.0d0 1.0d0))))) |
|---|