@@ -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)
@@ -347,14 +338,35 @@ end
347338div (num:: Poly , den:: Poly ) = divrem (num, den)[1 ]
348339rem (num:: Poly , den:: Poly ) = divrem (num, den)[2 ]
349340
350- function == (p1:: Poly , p2:: Poly )
351- if p1. var != p2. var
352- return false
353- else
354- return p1. a == p2. a
355- end
341+ == (p1:: Poly , p2:: Poly ) = (p1. var == p2. var && p1. a == p2. a)
342+ == (p1:: Poly , n:: Number ) = (coeffs (p1) == [n])
343+ == (n:: Number , p1:: Poly ) = (p1 == n)
344+
345+ """
346+ isapprox{T,S}(p1::Poly{T}, p2::Poly{S}; reltol::Real = Base.rtoldefault(T,S), abstol::Real = 0, norm::Function = vecnorm)
347+
348+ Truncate `p1` and `p2`, and compare the coefficients with `isapprox`.
349+
350+ The tolerances `reltol` and `abstol` are passed to both `truncate` and `isapprox`.
351+ """
352+ function isapprox {T,S} (p1:: Poly{T} , p2:: Poly{S} ;
353+ reltol:: Real = Base. rtoldefault (T,S), abstol:: Real = 0 , norm:: Function = vecnorm)
354+ p1. var == p2. var || error (" Polynomials must have same variable" )
355+ p1t = truncate (p1; reltol = reltol, abstol = abstol)
356+ p2t = truncate (p2; reltol = reltol, abstol = abstol)
357+ length (p1t) == length (p2t) && isapprox (coeffs (p1t), coeffs (p2t); rtol = reltol,
358+ atol = abstol, norm = norm)
356359end
357360
361+ function isapprox {T,S<:Number} (p1:: Poly{T} , n:: S ; reltol:: Real = Base. rtoldefault (T,S),
362+ abstol:: Real = 0 )
363+ p1t = truncate (p1; reltol = reltol, abstol = abstol)
364+ degree (p1t) == 0 && isapprox (coeffs (p1), [n]; rtol = reltol, atol = abstol)
365+ end
366+
367+ isapprox {T,S<:Number} (n:: S , p1:: Poly{T} ; reltol:: Real = Base. rtoldefault (T,S),
368+ abstol:: Real = 0 ) = isapprox (p1, n; reltol = reltol, abstol = abstol)
369+
358370hash (f:: Poly , h:: UInt ) = hash (f. var, hash (f. a, h))
359371isequal (p1:: Poly , p2:: Poly ) = hash (p1) == hash (p2)
360372
@@ -507,15 +519,16 @@ roots(poly([1,2,3,4])) # [1.0,2.0,3.0,4.0]
507519function roots {T} (p:: Poly{T} )
508520 R = promote_type (T, Float64)
509521 length (p) == 0 && return zeros (R, 0 )
522+ p = truncate (p)
510523 num_leading_zeros = 0
511- while abs ( p[num_leading_zeros]) <= 2 * eps (T)
524+ while p[num_leading_zeros] ≈ zero (T)
512525 if num_leading_zeros == length (p)- 1
513526 return zeros (R, 0 )
514527 end
515528 num_leading_zeros += 1
516529 end
517530 num_trailing_zeros = 0
518- while abs ( p[end - num_trailing_zeros]) <= 2 * eps (T)
531+ while p[end - num_trailing_zeros] ≈ zero (T)
519532 num_trailing_zeros += 1
520533 end
521534 n = endof (p)- (num_leading_zeros + num_trailing_zeros)
@@ -545,12 +558,11 @@ gcd(poly([1,1,2]), poly([1,2,3])) # returns (x-1)*(x-2)
545558```
546559"""
547560function gcd {T, S} (a:: Poly{T} , b:: Poly{S} )
548- if reduce (& , (@compat abs .(b. a)) .<= 2 * eps (S))
549- return a
550- else
551- s, r = divrem (a, b)
552- return gcd (b, r)
553- end
561+ R = typeof (one (T)/ one (S))
562+ degree (b) == 0 && b ≈ zero (b) && return convert (Poly{R}, a)
563+
564+ s, r = divrem (a, b)
565+ return gcd (b, r)
554566end
555567
556568
0 commit comments