@@ -13,14 +13,10 @@ export polyval, polyint, polyder, roots, polyfit
1313export Pade, padeval
1414
1515import Base: length, endof, getindex, setindex!, copy, zero, one, convert, norm, gcd
16- import Base: show, print, * , / , // , - , + , == , divrem, div, rem, eltype
16+ import Base: show, print, * , / , // , - , + , == , isapprox, divrem, div, rem, eltype
1717import Base: promote_rule, truncate, chop, call, conj, transpose, dot, hash
1818import Base: isequal
1919
20- eps {T} (:: Type{T} ) = zero (T)
21- eps {F<:AbstractFloat} (x:: Type{F} ) = Base. eps (F)
22- eps {T} (x:: Type{Complex{T}} ) = eps (T)
23-
2420typealias SymbolLike Union{AbstractString,Char,Symbol}
2521
2622"""
@@ -152,34 +148,29 @@ variable{T}(p::Poly{T}) = variable(T, p.var)
152148variable (var:: SymbolLike = :x ) = variable (Float64, var)
153149
154150"""
151+ truncate{T}(p::Poly{T}; reltol::Real = Base.rtoldefault(real(T)), abstol::Real = 0)
155152
156- `truncate{T}(p::Poly{T}; reltol = eps(T), abstol = eps(T))`: returns a polynomial with coefficients a_i truncated to zero if |a_i| <= reltol*maxabs(a)+abstol
157-
153+ Return a polynomial with coefficients `a_i` truncated to zero if `|a_i| <= reltol*maxabs(a)+abstol`.
158154"""
159- function truncate {T} (p:: Poly{Complex{T}} ; reltol = eps (T), abstol = eps (T))
155+ function truncate {T} (p:: Poly{T} ; reltol:: Real = Base. rtoldefault (real (T)),
156+ abstol:: Real = 0 )
160157 a = coeffs (p)
161158 amax = maximum (abs,a)
162159 thresh = amax * reltol + abstol
163- anew = map (ai -> complex (abs (real (ai)) <= thresh ? zero (T) : real (ai),
164- abs (imag (ai)) <= thresh ? zero (T) : imag (ai)),
165- a)
166- return Poly (anew, p. var)
167- end
168-
169- function truncate {T} (p:: Poly{T} ; reltol = eps (T), abstol = eps (T))
170- a = coeffs (p)
171- amax = maximum (abs,a)
172- anew = map (ai -> abs (ai) <= amax* reltol+ abstol ? zero (T) : ai, a)
160+ anew = map (ai -> abs (ai) <= thresh ? zero (T) : ai, a)
173161 return Poly (anew, p. var)
174162end
175163
176164"""
177165
178- `chop(p::Poly{T}; kwargs...)` chop off leading values which are
179- approximately zero. The tolerances are passed to `isapprox`.
166+ chop(p::Poly{T}; reltol::Real = Base.rtoldefault(real(T)), abstol::Real = 0)
167+
168+ Chop off leading values which are approximately zero.
180169
170+ The tolerances `reltol` and `abstol` are passed to `isapprox`.
181171"""
182- function chop {T} (p:: Poly{T} ; reltol= zero (T), abstol= 2 * eps (T))
172+ function chop {T} (p:: Poly{T} ; reltol:: Real = Base. rtoldefault (real (T)),
173+ abstol:: Real = 0 )
183174 c = copy (p. a)
184175 for k= length (c): - 1 : 1
185176 if ! isapprox (c[k], zero (T); rtol= reltol, atol= abstol)
@@ -345,14 +336,35 @@ end
345336div (num:: Poly , den:: Poly ) = divrem (num, den)[1 ]
346337rem (num:: Poly , den:: Poly ) = divrem (num, den)[2 ]
347338
348- function == (p1:: Poly , p2:: Poly )
349- if p1. var != p2. var
350- return false
351- else
352- return p1. a == p2. a
353- end
339+ == (p1:: Poly , p2:: Poly ) = (p1. var == p2. var && p1. a == p2. a)
340+ == (p1:: Poly , n:: Number ) = (coeffs (p1) == [n])
341+ == (n:: Number , p1:: Poly ) = (p1 == n)
342+
343+ """
344+ isapprox{T,S}(p1::Poly{T}, p2::Poly{S}; reltol::Real = Base.rtoldefault(T,S), abstol::Real = 0, norm::Function = vecnorm)
345+
346+ Truncate `p1` and `p2`, and compare the coefficients with `isapprox`.
347+
348+ The tolerances `reltol` and `abstol` are passed to both `truncate` and `isapprox`.
349+ """
350+ function isapprox {T,S} (p1:: Poly{T} , p2:: Poly{S} ;
351+ reltol:: Real = Base. rtoldefault (T,S), abstol:: Real = 0 , norm:: Function = vecnorm)
352+ p1. var == p2. var || error (" Polynomials must have same variable" )
353+ p1t = truncate (p1; reltol = reltol, abstol = abstol)
354+ p2t = truncate (p2; reltol = reltol, abstol = abstol)
355+ length (p1t) == length (p2t) && isapprox (coeffs (p1t), coeffs (p2t); rtol = reltol,
356+ atol = abstol, norm = norm)
354357end
355358
359+ function isapprox {T,S<:Number} (p1:: Poly{T} , n:: S ; reltol:: Real = Base. rtoldefault (T,S),
360+ abstol:: Real = 0 )
361+ p1t = truncate (p1; reltol = reltol, abstol = abstol)
362+ degree (p1t) == 0 && isapprox (coeffs (p1), [n]; rtol = reltol, atol = abstol)
363+ end
364+
365+ isapprox {T,S<:Number} (n:: S , p1:: Poly{T} ; reltol:: Real = Base. rtoldefault (T,S),
366+ abstol:: Real = 0 ) = isapprox (p1, n; reltol = reltol, abstol = abstol)
367+
356368hash (f:: Poly , h:: UInt ) = hash (f. var, hash (f. a, h))
357369isequal (p1:: Poly , p2:: Poly ) = hash (p1) == hash (p2)
358370
@@ -505,15 +517,16 @@ roots(poly([1,2,3,4])) # [1.0,2.0,3.0,4.0]
505517function roots {T} (p:: Poly{T} )
506518 R = promote_type (T, Float64)
507519 length (p) == 0 && return zeros (R, 0 )
520+ p = truncate (p)
508521 num_leading_zeros = 0
509- while abs ( p[num_leading_zeros]) <= 2 * eps (T)
522+ while p[num_leading_zeros] ≈ zero (T)
510523 if num_leading_zeros == length (p)- 1
511524 return zeros (R, 0 )
512525 end
513526 num_leading_zeros += 1
514527 end
515528 num_trailing_zeros = 0
516- while abs ( p[end - num_trailing_zeros]) <= 2 * eps (T)
529+ while p[end - num_trailing_zeros] ≈ zero (T)
517530 num_trailing_zeros += 1
518531 end
519532 n = endof (p)- (num_leading_zeros + num_trailing_zeros)
@@ -543,12 +556,11 @@ gcd(poly([1,1,2]), poly([1,2,3])) # returns (x-1)*(x-2)
543556```
544557"""
545558function gcd {T, S} (a:: Poly{T} , b:: Poly{S} )
546- if reduce (& , (@compat abs .(b. a)) .<= 2 * eps (S))
547- return a
548- else
549- s, r = divrem (a, b)
550- return gcd (b, r)
551- end
559+ R = typeof (one (T)/ one (S))
560+ degree (b) == 0 && b ≈ zero (b) && return convert (Poly{R}, a)
561+
562+ s, r = divrem (a, b)
563+ return gcd (b, r)
552564end
553565
554566
0 commit comments