Skip to content

Commit f796a8c

Browse files
committed
reorganize; add polyfit and polyinterpolate
1 parent 929c5b0 commit f796a8c

File tree

2 files changed

+120
-32
lines changed

2 files changed

+120
-32
lines changed

src/Polynomials.jl

Lines changed: 107 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ module Polynomials
55

66
using Compat
77

8-
export Poly, polyval, polyint, polyder, poly, roots
9-
export Pade, padeval, degree
8+
export Poly, poly
9+
export degree, coeffs
10+
export polyval, polyint, polyder, roots, polyfit, polyinterpolate
11+
export Pade, padeval
1012

1113
import Base: length, endof, getindex, setindex!, copy, zero, one, convert, norm, gcd
1214
import Base: show, print, *, /, //, -, +, ==, divrem, div, rem, eltype
@@ -73,7 +75,36 @@ end
7375

7476
@compat Poly{T<:Number}(a::Vector{T}, var::Union{AbstractString,Symbol,Char}=:x) = Poly{T}(a, var)
7577

76-
include("show.jl")
78+
# create a Poly object from its roots
79+
"""
80+
81+
* `poly(r::AbstractVector)`: Construct a polynomial from its
82+
roots. This is in contrast to the `Poly` constructor, which
83+
constructs a polynomial from its coefficients.
84+
85+
Example:
86+
```
87+
## Represents (x-1)*(x-2)*(x-3)
88+
poly([1,2,3]) # Poly(-6 + 11x - 6x^2 + x^3)
89+
```
90+
"""
91+
function poly{T}(r::AbstractVector{T}, var=:x)
92+
n = length(r)
93+
c = zeros(T, n+1)
94+
c[1] = 1
95+
for j = 1:n
96+
for i = j:-1:1
97+
c[i+1] = c[i+1]-r[j]*c[i]
98+
end
99+
end
100+
return Poly(reverse(c), var)
101+
end
102+
poly(A::Matrix, var=:x) = poly(eig(A)[1], var)
103+
poly(A::Matrix, var::AbstractString) = poly(eig(A)[1], symbol(var))
104+
poly(A::Matrix, var::Char) = poly(eig(A)[1], symbol(var))
105+
106+
107+
include("show.jl") # display polynomials.
77108

78109
convert{T}(::Type{Poly{T}}, p::Poly) = Poly(convert(Vector{T}, p.a), p.var)
79110
convert{T, S<:Number}(::Type{Poly{T}}, x::S) = Poly(promote_type(T, S)[x])
@@ -328,39 +359,14 @@ polyder{T}(a::Array{Poly{T},1}, order::Int = 1) = [ polyder(p,order) for p in a
328359
polyint{n,T}(a::Array{Poly{T},n}, k::Number = 0) = map(p->polyint(p,k),a)
329360
polyder{n,T}(a::Array{Poly{T},n}, order::Int = 1) = map(p->polyder(p,order),a)
330361

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.
337362

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-
"""
344-
function poly{T}(r::AbstractVector{T}, var=:x)
345-
n = length(r)
346-
c = zeros(T, n+1)
347-
c[1] = 1
348-
for j = 1:n
349-
for i = j:-1:1
350-
c[i+1] = c[i+1]-r[j]*c[i]
351-
end
352-
end
353-
return Poly(reverse(c), var)
354-
end
355-
poly(A::Matrix, var=:x) = poly(eig(A)[1], var)
356-
poly(A::Matrix, var::AbstractString) = poly(eig(A)[1], symbol(var))
357-
poly(A::Matrix, var::Char) = poly(eig(A)[1], symbol(var))
358363

359-
360-
roots{T}(p::Poly{Rational{T}}) = roots(convert(Poly{promote_type(T, Float64)}, p))
364+
##################################################
365+
##
366+
## Some functions on polynomials...
361367

362368

363-
# compute the roots of a polynomial
369+
# compute the roots of a polynomial
364370
"""
365371
366372
* `roots(p::Poly)`: Return the roots (zeros) of `p`, with
@@ -372,6 +378,7 @@ Examples:
372378
roots(Poly([1, 0, -1])) # [-1.0, 1.0]
373379
roots(Poly([1, 0, 1])) # [0.0+1.0im, 0.0-1.0im]
374380
roots(Poly([0, 0, 1])) # [0.0, 0.0]
381+
roots(poly([1,2,3,4])) # [1.0,2.0,3.0,4.0]
375382
```
376383
"""
377384
function roots{T}(p::Poly{T})
@@ -407,7 +414,9 @@ function roots{T}(p::Poly{T})
407414
r[1:n] = D
408415
return r
409416
end
417+
roots{T}(p::Poly{Rational{T}}) = roots(convert(Poly{promote_type(T, Float64)}, p))
410418

419+
## compute gcd of two polynomials
411420
"""
412421
413422
* `gcd(a::Poly, b::Poly)`: Finds the Greatest Common Denominator of
@@ -428,6 +437,72 @@ function gcd{T, S}(a::Poly{T}, b::Poly{S})
428437
end
429438
end
430439

440+
441+
## Fit degree n polynomial to points
442+
"""
443+
444+
`polyfit(x::AbstractVector, y::AbstractVector)`: Fit a polynomial of degree `n` through the points specified by `x` and `y` where `n <= length(x) - 1` using least squares fit.
445+
446+
Example:
447+
448+
```
449+
xs = linspace(0, pi, 5)
450+
ys = map(sin, xs)
451+
polyfit(xs, ys, 2)
452+
```
453+
454+
Original by [ggggggggg](https://github.com/Keno/Polynomials.jl/issues/19)
455+
"""
456+
function polyfit(x, y, n)
457+
length(x) == length(y) || throw(DomainError)
458+
n <= length(x) - 1 || throw(DomainError)
459+
460+
A = [ float(x[i])^p for i = 1:length(x), p = 0:n ]
461+
Poly(A \ y)
462+
end
463+
464+
## Find interpolating polynomial through the points
465+
"""
466+
467+
* `polyinterpolate(x, y)`: Return interpolating polynomial of degree `n-1` or less.
468+
469+
Example
470+
471+
```
472+
xs = linspace(0, pi, 3)
473+
ys = map(sin, xs)
474+
polyinterpolate(xs, ys)
475+
```
476+
477+
This uses [Algorithm 1](http://www.ams.org/journals/mcom/1970-24-109/S0025-5718-1970-0258240-X/S0025-5718-1970-0258240-X.pdf) of Krogh, *Efficient Algorithms for Polynomial Interpolation and Numerical Differentiation*.
478+
"""
479+
function polyinterpolate(xs, ys; xvar=:x)
480+
length(unique(xs)) == length(xs) || throw(DomainError)
481+
n = length(xs) - 1
482+
etype = eltype(float(ys))
483+
x = Poly([0, one(etype,)])
484+
485+
omega = 1
486+
π = 1
487+
p = Poly(ys[1:1], xvar)
488+
489+
Vii = zeros(etype, n + 1)
490+
Vii[1] = ys[1]
491+
492+
for k = 1:n
493+
V_ik = ys[k+1]
494+
for i=0:(k-1)
495+
V_ik = (Vii[i+1] - V_ik) / (xs[i+1] - xs[k+1])
496+
end
497+
Vii[k+1] = V_ik
498+
omega = x - xs[k-1 + 1]
499+
π = omega * π
500+
p = p + π * Vii[k+1]
501+
end
502+
503+
p
504+
end
505+
431506
### Pull in others
432507
include("pade.jl")
433508

test/runtests.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,16 @@ PQexpint = Pade(d,30,30)
128128
println("The approximate sum of the convergent series is: ",exp(1)*(-γ-sum([(-1).^k/k./gamma(k+1) for k=1:20])))
129129
@test isapprox(convert(Float64, padeval(PQexpint,1.0)),
130130
exp(1)*(-γ-sum([(-1).^k/k./gamma(k+1) for k=1:20])))
131+
132+
133+
## polyfit
134+
xs = linspace(0, pi, 10)
135+
ys = sin(xs)
136+
p = polyfit(xs, ys, 2)
137+
@test maximum(abs(map(x->polyval(p, x), xs) - ys)) <= 0.03
138+
139+
## polyinterpolate
140+
xs = linspace(0, pi, 3)
141+
ys = sin(xs)
142+
p = polyinterpolate(xs, ys)
143+
@test maximum(abs(map(x->polyval(p, x), xs) - ys)) <= 10*eps()

0 commit comments

Comments
 (0)