@@ -13,14 +13,10 @@ export polyval, polyint, polyder, roots, polyfit
13
13
export Pade, padeval
14
14
15
15
import 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
17
17
import Base: promote_rule, truncate, chop, call, conj, transpose, dot, hash
18
18
import Base: isequal
19
19
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
-
24
20
typealias SymbolLike Union{AbstractString,Char,Symbol}
25
21
26
22
"""
@@ -152,34 +148,29 @@ variable{T}(p::Poly{T}) = variable(T, p.var)
152
148
variable (var:: SymbolLike = :x ) = variable (Float64, var)
153
149
154
150
"""
151
+ truncate{T}(p::Poly{T}; reltol::Real = Base.rtoldefault(real(T)), abstol::Real = 0)
155
152
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`.
158
154
"""
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 )
160
157
a = coeffs (p)
161
158
amax = maximum (abs,a)
162
159
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)
173
161
return Poly (anew, p. var)
174
162
end
175
163
176
164
"""
177
165
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.
180
169
170
+ The tolerances `reltol` and `abstol` are passed to `isapprox`.
181
171
"""
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 )
183
174
c = copy (p. a)
184
175
for k= length (c): - 1 : 1
185
176
if ! isapprox (c[k], zero (T); rtol= reltol, atol= abstol)
@@ -345,14 +336,35 @@ end
345
336
div (num:: Poly , den:: Poly ) = divrem (num, den)[1 ]
346
337
rem (num:: Poly , den:: Poly ) = divrem (num, den)[2 ]
347
338
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)
354
357
end
355
358
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
+
356
368
hash (f:: Poly , h:: UInt ) = hash (f. var, hash (f. a, h))
357
369
isequal (p1:: Poly , p2:: Poly ) = hash (p1) == hash (p2)
358
370
@@ -505,15 +517,16 @@ roots(poly([1,2,3,4])) # [1.0,2.0,3.0,4.0]
505
517
function roots {T} (p:: Poly{T} )
506
518
R = promote_type (T, Float64)
507
519
length (p) == 0 && return zeros (R, 0 )
520
+ p = truncate (p)
508
521
num_leading_zeros = 0
509
- while abs ( p[num_leading_zeros]) <= 2 * eps (T)
522
+ while p[num_leading_zeros] ≈ zero (T)
510
523
if num_leading_zeros == length (p)- 1
511
524
return zeros (R, 0 )
512
525
end
513
526
num_leading_zeros += 1
514
527
end
515
528
num_trailing_zeros = 0
516
- while abs ( p[end - num_trailing_zeros]) <= 2 * eps (T)
529
+ while p[end - num_trailing_zeros] ≈ zero (T)
517
530
num_trailing_zeros += 1
518
531
end
519
532
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)
543
556
```
544
557
"""
545
558
function 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)
552
564
end
553
565
554
566
0 commit comments