@@ -8,7 +8,7 @@ using Compat
8
8
export Poly, polyval, polyint, polyder, poly, roots
9
9
export Pade, padeval, degree
10
10
11
- import Base: length, endof, getindex, setindex!, copy, zero, one, convert
11
+ import Base: length, endof, getindex, setindex!, copy, zero, one, convert, norm, gcd
12
12
import Base: show, print, * , / , // , - , + , == , divrem, div, rem, eltype
13
13
import Base: promote_rule
14
14
if VERSION >= v " 0.4"
@@ -19,6 +19,43 @@ eps{T}(::Type{T}) = zero(T)
19
19
eps {F<:AbstractFloat} (x:: Type{F} ) = Base. eps (F)
20
20
eps {T} (x:: Type{Complex{T}} ) = eps (T)
21
21
22
+
23
+ """
24
+
25
+ * `Poly{T<:Number}(a::Vector)`: Construct a polynomial from its coefficients, lowest order first. That is if `p=a_n x^n + ... + a_2 x^2 + a_1 x^1 + a_0`, we construct this through `Poly([a_0, a_1, ..., a_n])`.
26
+
27
+ Example:
28
+ ```
29
+ Poly([1,0,3,4]) # Poly(1 + 3x^2 + 4x^3)
30
+ ```
31
+
32
+ An optional variable parameter can be added:
33
+
34
+ ```
35
+ Poly([1,2,3], :s) # Poly(1 + 2s + 3s^2)
36
+ ```
37
+
38
+ The usual arithmetic operators are overloaded to work on polynomials, and combinations of polynomials and scalars.
39
+
40
+ ```
41
+ p = Poly([1,2]) # Poly(1 + 2x)
42
+ q = Poly([1, 0, -1]) # Poly(1 - x^2)
43
+ 2p # Poly(2 + 4x)
44
+ 2+p # Poly(3 + 2x)
45
+ p - q # Poly(2x + x^2)
46
+ p*q # Poly(1 + 2x - x^2 - 2x^3)
47
+ q/2 # Poly(0.5 - 0.5x^2)
48
+ ```
49
+
50
+ Note that operations involving polynomials with different variables will error:
51
+
52
+ ```j
53
+ p = Poly([1, 2, 3], :x)
54
+ q = Poly([1, 2, 3], :s)
55
+ p + q # ERROR: Polynomials must have same variable.
56
+ ```
57
+
58
+ """
22
59
immutable Poly{T<: Number }
23
60
a:: Vector{T}
24
61
var:: Symbol
36
73
37
74
@compat Poly {T<:Number} (a:: Vector{T} , var:: Union{AbstractString,Symbol,Char} = :x ) = Poly {T} (a, var)
38
75
76
+ include (" show.jl" )
77
+
39
78
convert {T} (:: Type{Poly{T}} , p:: Poly ) = Poly (convert (Vector{T}, p. a), p. var)
40
79
convert {T, S<:Number} (:: Type{Poly{T}} , x:: S ) = Poly (promote_type (T, S)[x])
41
80
convert {T, S<:Number,n} (:: Type{Poly{T}} , x:: Array{S,n} ) = map (el-> convert (Poly{promote_type (T,S)},el),x)
42
81
promote_rule {T, S} (:: Type{Poly{T}} , :: Type{Poly{S}} ) = Poly{promote_type (T, S)}
43
82
eltype {T} (:: Poly{T} ) = T
44
83
84
+ """
85
+
86
+ `legnth(p::Poly)`: return length of coefficient vector
87
+
88
+ """
45
89
length (p:: Poly ) = length (p. a)
46
- degree (p:: Poly ) = length (p)- 1
90
+
91
+ """
92
+
93
+ `degree(p::Poly)`: return degree of polynomial `p`
94
+
95
+ """
96
+ degree (p:: Poly ) = length (p) - 1
47
97
endof (p:: Poly ) = length (p) - 1
48
98
99
+ """
100
+
101
+ `coeffs(p::Poly)`: return coefficient vector [a_0, a_1, ..., a_n]
102
+
103
+ """
104
+ coeffs (p:: Poly ) = p. a
105
+
106
+ """
107
+
108
+ * `norm(q::Poly, [p])`: return `p` norm of polynomial `q`
109
+
110
+ """
111
+ norm (q:: Poly , args... ) = norm (coeffs (q), args... )
112
+
113
+ """
114
+
115
+ * `getindex(p::Poly, i)`: If `p=a_n x^n + a_{n-1}x^{n-1} + ... + a_1 x^1 + a_0`, then `p[i]` returns `a_i`.
116
+
117
+ """
49
118
getindex {T} (p:: Poly{T} , i) = (i+ 1 > length (p. a) ? zero (T) : p. a[i+ 1 ])
50
119
function setindex! (p:: Poly , v, i)
51
120
n = length (p. a)
@@ -64,93 +133,11 @@ zero{T}(::Type{Poly{T}}) = Poly(T[])
64
133
one {T} (p:: Poly{T} ) = Poly ([one (T)], p. var)
65
134
one {T} (:: Type{Poly{T}} ) = Poly ([one (T)])
66
135
67
- function show (io:: IO , p:: Poly )
68
- print (io," Poly(" )
69
- print (io,p)
70
- print (io," )" )
71
- end
72
-
73
- function printexponent (io,var,i)
74
- if i == 0
75
- elseif i == 1
76
- print (io,var)
77
- else
78
- print (io,var," ^" ,i)
79
- end
80
- end
81
-
82
- function printterm {T} (io:: IO ,p:: Poly{T} ,j,first)
83
- pj = p[j]
84
- if pj == zero (T)
85
- return false
86
- end
87
- neg = pj < 0
88
- if first
89
- neg && print (io, " -" ) # Prepend - if first and negative
90
- else
91
- neg ? print (io, " - " ) : print (io," + " )
92
- end
93
- pj = abs (pj)
94
- if pj != one (T) || j == 0
95
- show (io,pj)
96
- end
97
- printexponent (io,p. var,j)
98
- true
99
- end
100
-
101
- function printterm {T<:Complex} (io:: IO ,p:: Poly{T} ,j,first)
102
- pj = p[j]
103
- abs_repj = abs (real (pj))
104
- abs_impj = abs (imag (pj))
105
- if abs_repj < 2 * eps (T) && abs_impj < 2 * eps (T)
106
- return false
107
- end
108
-
109
- # We show a negative sign either for any complex number with negative
110
- # real part (and then negate the immaginary part) of for complex
111
- # numbers that are pure imaginary with negative imaginary part
112
-
113
- neg = ((abs_repj > 2 * eps (T)) && real (pj) < 0 ) ||
114
- ((abs_impj > 2 * eps (T)) && imag (pj) < 0 )
115
-
116
- if first
117
- neg && print (io, " -" ) # Prepend - if first and negative
118
- else
119
- neg ? print (io," - " ) : print (io," + " )
120
- end
121
-
122
- if abs_repj > 2 * eps (T) # Real part is not 0
123
- if abs_impj > 2 * eps (T) # Imag part is not 0
124
- print (io,' (' ,neg ? - pj : pj,' )' )
125
- else
126
- print (io, neg ? - real (pj) : real (pj))
127
- end
128
- else
129
- if abs_impj > 2 * eps (T)
130
- print (io,' (' , imag (pj)," im)" )
131
- end
132
- end
133
- printexponent (io,p. var,j)
134
- true
135
- end
136
-
137
- function print {T} (io:: IO , p:: Poly{T} )
138
- first = true
139
- printed_anything = false
140
- n = length (p)- 1
141
- for i = 0 : n
142
- printed = printterm (io,p,i,first)
143
- first &= ! printed
144
- printed_anything |= printed
145
- end
146
- printed_anything || print (io,zero (T))
147
- end
148
-
136
+ # # Overload arithmetic operators for polynomial operations between polynomials and scalars
149
137
* {T<: Number ,S}(c:: T , p:: Poly{S} ) = Poly (c * p. a, p. var)
150
138
* {T<: Number ,S}(p:: Poly{S} , c:: T ) = Poly (p. a * c, p. var)
151
139
/ (p:: Poly , c:: Number ) = Poly (p. a / c, p. var)
152
140
- (p:: Poly ) = Poly (- p. a, p. var)
153
-
154
141
- (p:: Poly , c:: Number ) = + (p, - c)
155
142
+ (c:: Number , p:: Poly ) = + (p, c)
156
143
function + (p:: Poly , c:: Number )
@@ -220,7 +207,7 @@ function divrem{T, S}(num::Poly{T}, den::Poly{S})
220
207
221
208
aQ = zeros (R, deg)
222
209
# aR = deepcopy(num.a)
223
- @show num. a
210
+ # @show num.a
224
211
aR = R[ num. a[i] for i = 1 : n+ 1 ]
225
212
for i = n: - 1 : m
226
213
quot = aR[i+ 1 ] / den[m]
@@ -248,6 +235,22 @@ function ==(p1::Poly, p2::Poly)
248
235
end
249
236
end
250
237
238
+ """
239
+ * `polyval(p::Poly, x::Number)`: Evaluate the polynomial `p` at `x` using Horner's method.
240
+
241
+ Example:
242
+ ```
243
+ polyval(Poly([1, 0, -1]), 0.1) # 0.99
244
+ ```
245
+
246
+ For `julia` version `0.4` or greater, the `call` method can be used:
247
+
248
+ ```
249
+ p = Poly([1,2,3])
250
+ p(4) # 57 = 1 + 2*4 + 3*4^2
251
+ ```
252
+
253
+ """
251
254
function polyval {T,S} (p:: Poly{T} , x:: S )
252
255
R = promote_type (T,S)
253
256
lenp = length (p)
@@ -268,6 +271,19 @@ if VERSION >= v"0.4"
268
271
call (p:: Poly , x) = polyval (p, x)
269
272
end
270
273
274
+ """
275
+
276
+ * `polyint(p::Poly, k::Number=0)`: Integrate the polynomial `p` term
277
+ by term, optionally adding constant term `k`. The order of the
278
+ resulting polynomial is one higher than the order of `p`.
279
+
280
+ Examples:
281
+ ```
282
+ polyint(Poly([1, 0, -1])) # Poly(x - 0.3333333333333333x^3)
283
+ polyint(Poly([1, 0, -1]), 2) # Poly(2.0 + x - 0.3333333333333333x^3)
284
+ ```
285
+
286
+ """
271
287
function polyint {T} (p:: Poly{T} , k:: Number = 0 )
272
288
n = length (p)
273
289
R = typeof (one (T)/ 1 )
@@ -279,6 +295,17 @@ function polyint{T}(p::Poly{T}, k::Number=0)
279
295
return Poly (a2, p. var)
280
296
end
281
297
298
+ """
299
+
300
+ * `polyder(p::Poly)`: Differentiate the polynomial `p` term by
301
+ term. The order of the resulting polynomial is one lower than the
302
+ order of `p`.
303
+
304
+ Example:
305
+ ```
306
+ polyder(Poly([1, 3, -1])) # Poly(3 - 2x)
307
+ ```
308
+ """
282
309
function polyder {T} (p:: Poly{T} , order:: Int = 1 )
283
310
n = length (p)
284
311
if order < 0
@@ -301,7 +328,19 @@ polyder{T}(a::Array{Poly{T},1}, order::Int = 1) = [ polyder(p,order) for p in a
301
328
polyint {n,T} (a:: Array{Poly{T},n} , k:: Number = 0 ) = map (p-> polyint (p,k),a)
302
329
polyder {n,T} (a:: Array{Poly{T},n} , order:: Int = 1 ) = map (p-> polyder (p,order),a)
303
330
304
- # create a Poly object from its roots
331
+ # create a Poly object from its roots
332
+ """
333
+
334
+ * `poly(r::AbstractVector)`: Construct a polynomial from its
335
+ roots. This is in contrast to the `Poly` constructor, which
336
+ constructs a polynomial from its coefficients.
337
+
338
+ Example:
339
+ ```
340
+ ## Represents (x-1)*(x-2)*(x-3)
341
+ poly([1,2,3]) # Poly(-6 + 11x - 6x^2 + x^3)
342
+ ```
343
+ """
305
344
function poly {T} (r:: AbstractVector{T} , var= :x )
306
345
n = length (r)
307
346
c = zeros (T, n+ 1 )
@@ -317,10 +356,24 @@ poly(A::Matrix, var=:x) = poly(eig(A)[1], var)
317
356
poly (A:: Matrix , var:: AbstractString ) = poly (eig (A)[1 ], symbol (var))
318
357
poly (A:: Matrix , var:: Char ) = poly (eig (A)[1 ], symbol (var))
319
358
359
+
320
360
roots {T} (p:: Poly{Rational{T}} ) = roots (convert (Poly{promote_type (T, Float64)}, p))
321
361
322
362
323
- # compute the roots of a polynomial
363
+ # compute the roots of a polynomial
364
+ """
365
+
366
+ * `roots(p::Poly)`: Return the roots (zeros) of `p`, with
367
+ multiplicity. The number of roots returned is equal to the order of
368
+ `p`. The returned roots may be real or complex.
369
+
370
+ Examples:
371
+ ```
372
+ roots(Poly([1, 0, -1])) # [-1.0, 1.0]
373
+ roots(Poly([1, 0, 1])) # [0.0+1.0im, 0.0-1.0im]
374
+ roots(Poly([0, 0, 1])) # [0.0, 0.0]
375
+ ```
376
+ """
324
377
function roots {T} (p:: Poly{T} )
325
378
R = promote_type (T, Float64)
326
379
length (p) == 0 && return zeros (R, 0 )
@@ -355,9 +408,18 @@ function roots{T}(p::Poly{T})
355
408
return r
356
409
end
357
410
411
+ """
412
+
413
+ * `gcd(a::Poly, b::Poly)`: Finds the Greatest Common Denominator of
414
+ two polynomials recursively using [Euclid's
415
+ algorithm](http://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#Euclid.27s_algorithm).
416
+
417
+ Example:
418
+ ```
419
+ gcd(poly([1,1,2]), poly([1,2,3])) # returns (x-1)*(x-2)
420
+ ```
421
+ """
358
422
function gcd {T, S} (a:: Poly{T} , b:: Poly{S} )
359
- # Finds the Greatest Common Denominator of two polynomials recursively using
360
- # Euclid's algorithm: http://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#Euclid.27s_algorithm
361
423
if all (abs (b. a).<= 2 * eps (S))
362
424
return a
363
425
else
@@ -366,6 +428,7 @@ function gcd{T, S}(a::Poly{T}, b::Poly{S})
366
428
end
367
429
end
368
430
431
+ # ## Pull in others
369
432
include (" pade.jl" )
370
433
371
434
end # module Poly
0 commit comments