File: poly.texi

package info (click to toggle)
gsl-doc 2.3-1
  • links: PTS
  • area: non-free
  • in suites: buster
  • size: 27,748 kB
  • ctags: 15,177
  • sloc: ansic: 235,014; sh: 11,585; makefile: 925
file content (386 lines) | stat: -rw-r--r-- 14,602 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
@cindex polynomials, roots of 

This chapter describes functions for evaluating and solving polynomials.
There are routines for finding real and complex roots of quadratic and
cubic equations using analytic methods.  An iterative polynomial solver
is also available for finding the roots of general polynomials with real
coefficients (of any order).  The functions are declared in the header
file @file{gsl_poly.h}.

@menu
* Polynomial Evaluation::       
* Divided Difference Representation of Polynomials::  
* Quadratic Equations::         
* Cubic Equations::             
* General Polynomial Equations::  
* Roots of Polynomials Examples::  
* Roots of Polynomials References and Further Reading::  
@end menu

@node Polynomial Evaluation
@section Polynomial Evaluation
@cindex polynomial evaluation
@cindex evaluation of polynomials

The functions described here evaluate the polynomial 
@c{$P(x) = c[0] + c[1] x + c[2] x^2 + \dots + c[len-1] x^{len-1}$}
@math{P(x) = c[0] + c[1] x + c[2] x^2 + \dots + c[len-1] x^@{len-1@}} using
Horner's method for stability. @inlinefns{}

@deftypefun double gsl_poly_eval (const double @var{c}[], const int @var{len}, const double @var{x})
This function evaluates a polynomial with real coefficients for the real variable @var{x}.
@end deftypefun

@deftypefun gsl_complex gsl_poly_complex_eval (const double @var{c}[], const int @var{len}, const gsl_complex @var{z})
This function evaluates a polynomial with real coefficients for the complex variable @var{z}.
@end deftypefun

@deftypefun gsl_complex gsl_complex_poly_complex_eval (const gsl_complex @var{c}[], const int @var{len}, const gsl_complex @var{z})
This function evaluates a polynomial with complex coefficients for the complex variable @var{z}.
@end deftypefun

@deftypefun int gsl_poly_eval_derivs (const double @var{c}[], const size_t @var{lenc}, const double @var{x}, double @var{res}[], const size_t @var{lenres})
This function evaluates a polynomial and its derivatives storing the
results in the array @var{res} of size @var{lenres}.  The output array
contains the values of @math{d^k P/d x^k} for the specified value of
@var{x} starting with @math{k = 0}.
@end deftypefun

@node Divided Difference Representation of Polynomials
@section Divided Difference Representation of Polynomials
@cindex divided differences, polynomials
@cindex evaluation of polynomials, in divided difference form

The functions described here manipulate polynomials stored in Newton's
divided-difference representation.  The use of divided-differences is
described in Abramowitz & Stegun sections 25.1.4 and 25.2.26, and
Burden and Faires, chapter 3, and discussed briefly below.

@noindent
Given a function @math{f(x)}, an @math{n}th degree interpolating polynomial @math{P_{n}(x)}
can be constructed which agrees with @math{f} at @math{n+1} distinct points
@math{x_0,x_1,...,x_{n}}. This polynomial can be written in a
form known as Newton's divided-difference representation:
@tex
\beforedisplay
$$
P_{n}(x) = f(x_0) + \sum_{k=1}^n [x_0,x_1,...,x_k] (x-x_0)(x-x_1) \cdots (x-x_{k-1})
$$
\afterdisplay
@end tex
@ifinfo

@example
P_n(x) = f(x_0) + \sum_(k=1)^n [x_0,x_1,...,x_k] (x-x_0)(x-x_1)...(x-x_(k-1))
@end example

@end ifinfo
where the divided differences @math{[x_0,x_1,...,x_k]} are defined in section 25.1.4 of
Abramowitz and Stegun. Additionally, it is possible to construct an interpolating
polynomial of degree @math{2n+1} which also matches the first derivatives of @math{f}
at the points @math{x_0,x_1,...,x_n}. This is called the Hermite interpolating
polynomial and is defined as
@tex
\beforedisplay
$$
H_{2n+1}(x) = f(z_0) + \sum_{k=1}^{2n+1} [z_0,z_1,...,z_k] (x-z_0)(x-z_1) \cdots (x-z_{k-1})
$$
\afterdisplay
@end tex
@ifinfo

@example
H_(2n+1)(x) = f(z_0) + \sum_(k=1)^(2n+1) [z_0,z_1,...,z_k] (x-z_0)(x-z_1)...(x-z_(k-1))
@end example

@end ifinfo
where the elements of @math{z = \{x_0,x_0,x_1,x_1,...,x_n,x_n\}} are defined by
@math{z_{2k} = z_{2k+1} = x_k}. The divided-differences @math{[z_0,z_1,...,z_k]}
are discussed in Burden and Faires, section 3.4.

@deftypefun int gsl_poly_dd_init (double @var{dd}[], const double @var{xa}[], const double @var{ya}[], size_t @var{size})
This function computes a divided-difference representation of the
interpolating polynomial for the points (@var{x}, @var{y}) stored in
the arrays @var{xa} and @var{ya} of length @var{size}.  On output the
divided-differences of (@var{xa},@var{ya}) are stored in the array
@var{dd}, also of length @var{size}. Using the notation above,
@math{dd[k] = [x_0,x_1,...,x_k]}.
@end deftypefun

@deftypefun double gsl_poly_dd_eval (const double @var{dd}[], const double @var{xa}[], const size_t @var{size}, const double @var{x})
This function evaluates the polynomial stored in divided-difference form
in the arrays @var{dd} and @var{xa} of length @var{size} at the point
@var{x}.  @inlinefn{}
@end deftypefun

@deftypefun int gsl_poly_dd_taylor (double @var{c}[], double @var{xp}, const double @var{dd}[], const double @var{xa}[], size_t @var{size}, double @var{w}[])
This function converts the divided-difference representation of a
polynomial to a Taylor expansion.  The divided-difference representation
is supplied in the arrays @var{dd} and @var{xa} of length @var{size}.
On output the Taylor coefficients of the polynomial expanded about the
point @var{xp} are stored in the array @var{c} also of length
@var{size}.  A workspace of length @var{size} must be provided in the
array @var{w}.
@end deftypefun

@deftypefun int gsl_poly_dd_hermite_init (double @var{dd}[], double @var{za}[], const double @var{xa}[], const double @var{ya}[], const double @var{dya}[], const size_t @var{size})
This function computes a divided-difference representation of the
interpolating Hermite polynomial for the points (@var{x}, @var{y}) stored in
the arrays @var{xa} and @var{ya} of length @var{size}. Hermite interpolation
constructs polynomials which also match first derivatives @math{dy/dx} which are
provided in the array @var{dya} also of length @var{size}. The first derivatives can be
incorported into the usual divided-difference algorithm by forming a new
dataset @math{z = \{x_0,x_0,x_1,x_1,...\}}, which is stored in the array
@var{za} of length 2*@var{size} on output. On output the
divided-differences of the Hermite representation are stored in the array
@var{dd}, also of length 2*@var{size}. Using the notation above,
@math{dd[k] = [z_0,z_1,...,z_k]}. The resulting Hermite polynomial
can be evaluated by calling @code{gsl_poly_dd_eval} and using
@var{za} for the input argument @var{xa}.
@end deftypefun

@node  Quadratic Equations
@section Quadratic Equations
@cindex quadratic equation, solving

@deftypefun int gsl_poly_solve_quadratic (double @var{a}, double @var{b}, double @var{c}, double * @var{x0}, double * @var{x1})
This function finds the real roots of the quadratic equation,
@tex
\beforedisplay
$$
a x^2 + b x + c = 0
$$
\afterdisplay
@end tex
@ifinfo

@example
a x^2 + b x + c = 0
@end example

@end ifinfo
@noindent
The number of real roots (either zero, one or two) is returned, and
their locations are stored in @var{x0} and @var{x1}.  If no real roots
are found then @var{x0} and @var{x1} are not modified.  If one real root
is found (i.e. if @math{a=0}) then it is stored in @var{x0}.  When two
real roots are found they are stored in @var{x0} and @var{x1} in
ascending order.  The case of coincident roots is not considered
special.  For example @math{(x-1)^2=0} will have two roots, which happen
to have exactly equal values.

The number of roots found depends on the sign of the discriminant
@math{b^2 - 4 a c}.  This will be subject to rounding and cancellation
errors when computed in double precision, and will also be subject to
errors if the coefficients of the polynomial are inexact.  These errors
may cause a discrete change in the number of roots.  However, for
polynomials with small integer coefficients the discriminant can always
be computed exactly.

@end deftypefun

@deftypefun int gsl_poly_complex_solve_quadratic (double @var{a}, double @var{b}, double @var{c}, gsl_complex * @var{z0}, gsl_complex * @var{z1})

This function finds the complex roots of the quadratic equation,
@tex
\beforedisplay
$$
a z^2 + b z + c = 0
$$
\afterdisplay
@end tex
@ifinfo

@example
a z^2 + b z + c = 0
@end example

@end ifinfo
@noindent
The number of complex roots is returned (either one or two) and the
locations of the roots are stored in @var{z0} and @var{z1}.  The roots
are returned in ascending order, sorted first by their real components
and then by their imaginary components.  If only one real root is found
(i.e. if @math{a=0}) then it is stored in @var{z0}.

@end deftypefun


@node Cubic Equations
@section Cubic Equations
@cindex cubic equation, solving

@deftypefun int gsl_poly_solve_cubic (double @var{a}, double @var{b}, double @var{c}, double * @var{x0}, double * @var{x1}, double * @var{x2})

This function finds the real roots of the cubic equation,
@tex
\beforedisplay
$$
x^3 + a x^2 + b x + c = 0
$$
\afterdisplay
@end tex
@ifinfo

@example
x^3 + a x^2 + b x + c = 0
@end example

@end ifinfo
@noindent
with a leading coefficient of unity.  The number of real roots (either
one or three) is returned, and their locations are stored in @var{x0},
@var{x1} and @var{x2}.  If one real root is found then only @var{x0}
is modified.  When three real roots are found they are stored in
@var{x0}, @var{x1} and @var{x2} in ascending order.  The case of
coincident roots is not considered special.  For example, the equation
@math{(x-1)^3=0} will have three roots with exactly equal values.  As
in the quadratic case, finite precision may cause equal or
closely-spaced real roots to move off the real axis into the complex
plane, leading to a discrete change in the number of real roots.
@end deftypefun

@deftypefun int gsl_poly_complex_solve_cubic (double @var{a}, double @var{b}, double @var{c}, gsl_complex * @var{z0}, gsl_complex * @var{z1}, gsl_complex * @var{z2})

This function finds the complex roots of the cubic equation,
@tex
\beforedisplay
$$
z^3 + a z^2 + b z + c = 0
$$
\afterdisplay
@end tex
@ifinfo

@example
z^3 + a z^2 + b z + c = 0
@end example

@end ifinfo
@noindent
The number of complex roots is returned (always three) and the locations
of the roots are stored in @var{z0}, @var{z1} and @var{z2}.  The roots
are returned in ascending order, sorted first by their real components
and then by their imaginary components.

@end deftypefun


@node General Polynomial Equations
@section General Polynomial Equations
@cindex general polynomial equations, solving

The roots of polynomial equations cannot be found analytically beyond
the special cases of the quadratic, cubic and quartic equation.  The
algorithm described in this section uses an iterative method to find the
approximate locations of roots of higher order polynomials.

@deftypefun {gsl_poly_complex_workspace *} gsl_poly_complex_workspace_alloc (size_t @var{n})
@tindex gsl_poly_complex_workspace
This function allocates space for a @code{gsl_poly_complex_workspace}
struct and a workspace suitable for solving a polynomial with @var{n}
coefficients using the routine @code{gsl_poly_complex_solve}.

The function returns a pointer to the newly allocated
@code{gsl_poly_complex_workspace} if no errors were detected, and a null
pointer in the case of error.
@end deftypefun

@deftypefun void gsl_poly_complex_workspace_free (gsl_poly_complex_workspace * @var{w})
This function frees all the memory associated with the workspace
@var{w}.
@end deftypefun

@deftypefun int gsl_poly_complex_solve (const double * @var{a}, size_t @var{n}, gsl_poly_complex_workspace * @var{w}, gsl_complex_packed_ptr @var{z})
This function computes the roots of the general polynomial 
@c{$P(x) = a_0 + a_1 x + a_2 x^2 + ... + a_{n-1} x^{n-1}$} 
@math{P(x) = a_0 + a_1 x + a_2 x^2 + ... + a_@{n-1@} x^@{n-1@}} using 
balanced-QR reduction of the companion matrix.  The parameter @var{n}
specifies the length of the coefficient array.  The coefficient of the
highest order term must be non-zero.  The function requires a workspace
@var{w} of the appropriate size.  The @math{n-1} roots are returned in
the packed complex array @var{z} of length @math{2(n-1)}, alternating
real and imaginary parts.

The function returns @code{GSL_SUCCESS} if all the roots are found. If
the QR reduction does not converge, the error handler is invoked with
an error code of @code{GSL_EFAILED}.  Note that due to finite precision,
roots of higher multiplicity are returned as a cluster of simple roots
with reduced accuracy.  The solution of polynomials with higher-order
roots requires specialized algorithms that take the multiplicity
structure into account (see e.g. Z. Zeng, Algorithm 835, ACM
Transactions on Mathematical Software, Volume 30, Issue 2 (2004), pp
218--236).
@end deftypefun

@node Roots of Polynomials Examples
@section Examples

To demonstrate the use of the general polynomial solver we will take the
polynomial @math{P(x) = x^5 - 1} which has the following roots,
@tex
\beforedisplay
$$
1, e^{2\pi i /5}, e^{4\pi i /5}, e^{6\pi i /5}, e^{8\pi i /5}
$$
\afterdisplay
@end tex
@ifinfo

@example
1, e^@{2\pi i /5@}, e^@{4\pi i /5@}, e^@{6\pi i /5@}, e^@{8\pi i /5@}
@end example

@end ifinfo
@noindent
The following program will find these roots.

@example
@verbatiminclude examples/polyroots.c
@end example

@noindent
The output of the program is,

@example
$ ./a.out 
@verbatiminclude examples/polyroots.txt
@end example

@noindent
which agrees with the analytic result, @math{z_n = \exp(2 \pi n i/5)}.

@node Roots of Polynomials References and Further Reading
@section References and Further Reading

The balanced-QR method and its error analysis are described in the
following papers,

@itemize @w{}
@item
R.S. Martin, G. Peters and J.H. Wilkinson, ``The QR Algorithm for Real
Hessenberg Matrices'', @cite{Numerische Mathematik}, 14 (1970), 219--231.

@item
B.N. Parlett and C. Reinsch, ``Balancing a Matrix for Calculation of
Eigenvalues and Eigenvectors'', @cite{Numerische Mathematik}, 13 (1969),
293--304.

@item
A. Edelman and H. Murakami, ``Polynomial roots from companion matrix
eigenvalues'', @cite{Mathematics of Computation}, Vol.@: 64, No.@: 210
(1995), 763--776.
@end itemize

@noindent
The formulas for divided differences are given in the following texts,

@itemize @w{}
@item
Abramowitz and Stegun, @cite{Handbook of Mathematical Functions},
Sections 25.1.4 and 25.2.26.

@item
R. L. Burden and J. D. Faires, @cite{Numerical Analysis}, 9th edition,
ISBN 0-538-73351-9, 2011.
@end itemize