root/trunk/polynomial.lisp

Revision 39 (checked in by lhealy, 5 months ago)

Changed #'divided-difference in ~liam/mathematics/gsl/polynomial.lisp
to be more like a standard GSLL interface, with a single function
definition in terms of the GSL function. Example/test for it added.

  • Property svn:keywords set to Id
Line 
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)))))
Note: See TracBrowser for help on using the browser.