@@ -27,7 +27,7 @@ promote_rule{T, S}(::Type{Poly{T}}, ::Type{Poly{S}}) = Poly{promote_type(T, S)}
27
27
eltype {T} (:: Poly{T} ) = T
28
28
29
29
length (p:: Poly ) = length (p. a)
30
- endof (p:: Poly ) = length (p)
30
+ endof (p:: Poly ) = length (p) - 1
31
31
32
32
getindex {T} (p:: Poly{T} , i) = (i+ 1 > length (p. a) ? zero (T) : p. a[i+ 1 ])
33
33
function setindex! (p:: Poly , v, i)
@@ -67,12 +67,13 @@ function printterm{T}(io::IO,p::Poly{T},j,first)
67
67
if pj == zero (T)
68
68
return false
69
69
end
70
- neg = abs (pj) < 0
70
+ neg = pj < 0
71
71
if first
72
72
neg && print (io, " -" ) # Prepend - if first and negative
73
73
else
74
74
neg ? print (io, " - " ) : print (io," + " )
75
75
end
76
+ pj = abs (pj)
76
77
if pj != one (T) || j == 0
77
78
show (io,pj)
78
79
end
@@ -154,10 +155,23 @@ function -{T}(c::Number, p::Poly{T})
154
155
end
155
156
end
156
157
157
- + {T,S}(p1:: Poly{T} , p2:: Poly{S} ) = Poly ([p1[i] + p2[i] for i = 0 : max (length (p1),length (p2))])
158
- - {T,S}(p1:: Poly{T} , p2:: Poly{S} ) = Poly ([p1[i] - p2[i] for i = 0 : max (length (p1),length (p2))])
158
+ function + {T,S}(p1:: Poly{T} , p2:: Poly{S} )
159
+ if p1. var != p2. var
160
+ error (" Polynomials must have same variable" )
161
+ end
162
+ Poly ([p1[i] + p2[i] for i = 0 : max (length (p1),length (p2))])
163
+ end
164
+ function - {T,S}(p1:: Poly{T} , p2:: Poly{S} )
165
+ if p1. var != p2. var
166
+ error (" Polynomials must have same variable" )
167
+ end
168
+ Poly ([p1[i] - p2[i] for i = 0 : max (length (p1),length (p2))])
169
+ end
159
170
160
171
function * {T,S}(p1:: Poly{T} , p2:: Poly{S} )
172
+ if p1. var != p2. var
173
+ error (" Polynomials must have same variable" )
174
+ end
161
175
R = promote_type (T,S)
162
176
n = length (p1)
163
177
m = length (p2)
@@ -170,39 +184,43 @@ function *{T,S}(p1::Poly{T}, p2::Poly{S})
170
184
a
171
185
end
172
186
187
+ function degree {T} (p:: Poly{T} )
188
+ for i = length (p): - 1 : 0
189
+ if p[i] > 2 * eps (T)
190
+ return i
191
+ end
192
+ end
193
+ return - 1
194
+ end
195
+
173
196
function divrem {T, S} (num:: Poly{T} , den:: Poly{S} )
174
197
if num. var != den. var
175
198
error (" Polynomials must have same variable" )
176
199
end
177
- m = length (den)
178
- if m == 0
200
+ m = degree (den)
201
+ if m < 0
179
202
throw (DivideError ())
180
203
end
181
204
R = typeof (one (T)/ one (S))
182
- n = length (num)
205
+ n = degree (num)
183
206
deg = n- m+ 1
184
207
if deg <= 0
185
- return zero (Poly{R}), convert (Poly{R}, num)
208
+ return convert (Poly{R}, zero (num) ), convert (Poly{R}, num)
186
209
end
187
- d = zeros (R, n)
188
- q = zeros (R, deg)
189
- r = zeros (R, n)
190
- r[:] = num. a
191
- for i = 1 : deg
192
- quot = r[i] / den[1 ]
193
- q[i] = quot
194
- if i > 1
195
- d[i- 1 ] = 0
196
- r[i- 1 ] = 0
197
- end
198
- for j = 1 : m
199
- k = i+ j- 1
210
+ # We will still modify q,r, but already wrap it in a
211
+ # polynomial, so the indexing below is more natural
212
+ pQ = Poly (zeros (R, deg), num. var)
213
+ pR = Poly (zeros (R, n+ 1 ), num. var)
214
+ pR. a[:] = num. a[1 : (n+ 1 )]
215
+ for i = n: - 1 : m
216
+ quot = pR[i] / den[m]
217
+ pQ[i- m] = quot
218
+ for j = 0 : m
200
219
elem = den[j]* quot
201
- d[k] = elem
202
- r[k] -= elem
220
+ pR[i- (m- j)] -= elem
203
221
end
204
222
end
205
- return Poly (q, num . var), Poly (r, num . var)
223
+ return pQ, pR
206
224
end
207
225
/ (num:: Poly , den:: Poly ) = divrem (num, den)[1 ]
208
226
rem (num:: Poly , den:: Poly ) = divrem (num, den)[2 ]
@@ -227,7 +245,7 @@ function polyval{T}(p::Poly{T}, x::Number)
227
245
return zero (R)
228
246
else
229
247
y = convert (R, p[end ])
230
- for i = (lenp - 1 ): - 1 : 0
248
+ for i = (endof (p) - 1 ): - 1 : 0
231
249
y = p[i] + x.* y
232
250
end
233
251
return y
@@ -277,34 +295,50 @@ poly(A::Matrix, var::Char) = poly(eig(A)[1], symbol(var))
277
295
278
296
roots {T} (p:: Poly{Rational{T}} ) = roots (convert (Poly{promote_type (T, Float64)}, p))
279
297
298
+
280
299
# compute the roots of a polynomial
281
300
function roots {T} (p:: Poly{T} )
282
301
R = promote_type (T, Float64)
283
- num_zeros = 0
284
- if length (p) == 0
285
- return zeros (R, 0 )
286
- end
287
- while abs (p[num_zeros]) <= 2 * eps (T)
288
- if num_zeros == length (p)- 1
302
+ length (p) == 0 && return zeros (R, 0 )
303
+
304
+ num_leading_zeros = 0
305
+ while abs (p[num_leading_zeros]) <= 2 * eps (T)
306
+ if num_leading_zeros == length (p)- 1
289
307
return zeros (R, 0 )
290
308
end
291
- num_zeros += 1
309
+ num_leading_zeros += 1
292
310
end
293
- n = length (p)- num_zeros- 1
294
- if n < 1
295
- return zeros (R, length (p)- 1 )
311
+
312
+ num_trailing_zeros = 0
313
+ while abs (p[end - num_trailing_zeros]) <= 2 * eps (T)
314
+ num_trailing_zeros += 1
296
315
end
316
+
317
+ n = endof (p)- (num_leading_zeros + num_trailing_zeros)
318
+
319
+ n < 1 && return zeros (R, length (p) - num_trailing_zeros - 1 )
320
+
297
321
companion = zeros (R, n, n)
298
- a0 = p[num_zeros ]
322
+ an = p[end - num_trailing_zeros ]
299
323
for i = 1 : n- 1
300
- companion[1 ,i ] = - p[num_zeros + i ] / a0
324
+ companion[i,n ] = - p[num_leading_zeros + i - 1 ] / an
301
325
companion[i+ 1 ,i] = 1 ;
302
326
end
303
- companion[1 ,end ] = - p[end ] / a0
304
- D,V = eig (companion)
305
- r = zeros (eltype (D),length (p)- 1 )
306
- r[1 : n] = 1. / D
327
+ companion[end ,end ] = - p[end - num_trailing_zeros - 1 ] / an
328
+ D = eigvals (companion)
329
+ r = zeros (eltype (D),length (p)- num_trailing_zeros - 1 )
330
+ r[1 : n] = D
307
331
return r
308
332
end
309
333
334
+ function gcd {T<:FloatingPoint, S<:FloatingPoint} (a:: Poly{T} , b:: Poly{S} )
335
+ # Finds the Greatest Common Denominator of two polynomials recursively using
336
+ # Euclid's algorithm: http://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#Euclid.27s_algorithm
337
+ if all (abs (b. a).<= 2 * eps (S))
338
+ return a
339
+ else
340
+ s, r = divrem (a, b)
341
+ return gcd (b, r)
342
+ end
343
+ end
310
344
end # module Poly
0 commit comments