Skip to content

Commit c599817

Browse files
committed
Merge branch 'master' of https://github.com/JuliaMath/Polynomials.jl into master
2 parents 17ce08a + 6605bc5 commit c599817

File tree

8 files changed

+991
-23
lines changed

8 files changed

+991
-23
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ julia:
1111
- 1.2
1212
- 1.3
1313
- 1.4
14+
- 1.5
1415
- nightly
1516

1617
notifications:

Project.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
21
name = "Polynomials"
32
uuid = "f27b6e38-b328-58d1-80ce-0feddd5e7a45"
43
license = "MIT"
54
author = "JuliaMath"
6-
version = "1.1.3"
5+
version = "1.1.4"
76

87
[deps]
98
Intervals = "d8418881-c3e1-53bb-8760-2df7ec849ed5"
109
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
10+
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
1111
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
1212

1313
[compat]
14-
Intervals = "0.5, 1"
14+
Intervals = "0.5, 1.0, 1.3"
1515
RecipesBase = "0.7, 0.8, 1"
16+
OffsetArrays = "1"
1617
julia = "1"
1718

18-
1919
[extras]
2020
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
2121
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

src/Polynomials.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module Polynomials
22

33
using LinearAlgebra
44
using Intervals
5+
using OffsetArrays
56

67
include("abstract.jl")
78
include("show.jl")
@@ -18,6 +19,7 @@ include("polynomials/Polynomial.jl")
1819
include("polynomials/ImmutablePolynomial.jl")
1920
include("polynomials/SparsePolynomial.jl")
2021
include("polynomials/LaurentPolynomial.jl")
22+
include("polynomials/ngcd.jl")
2123

2224
include("polynomials/ChebyshevT.jl")
2325

src/common.jl

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -536,11 +536,17 @@ Polynomial(4.0 - 6.0*x + 2.0*x^2)
536536
537537
```
538538
"""
539-
function Base.gcd(p1::AbstractPolynomial{T}, p2::AbstractPolynomial{S};
540-
atol::Real=zero(real(promote_type(T,S))),
541-
rtol::Real=Base.rtoldefault(real(promote_type(T,S)))
542-
) where {T,S}
543-
r₀, r₁ = promote(p1, p2)
539+
function Base.gcd(p1::AbstractPolynomial{T}, p2::AbstractPolynomial{S}; kwargs...) where {T,S}
540+
gcd(promote(p1, p2)...; kwargs...)
541+
end
542+
543+
function Base.gcd(p1::P, p2::Q;
544+
atol::Real=zero(real(T)),
545+
rtol::Real=Base.rtoldefault(real(T))
546+
) where {T, P <: AbstractPolynomial{T}, Q <: AbstractPolynomial{T}}
547+
548+
549+
r₀, r₁ = p1, p2
544550
iter = 1
545551
itermax = length(r₁)
546552

src/polynomials/LaurentPolynomial.jl

Lines changed: 154 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export LaurentPolynomial
55
66
A [Laurent](https://en.wikipedia.org/wiki/Laurent_polynomial) polynomial is of the form `a_{m}x^m + ... + a_{n}x^n` where `m,n` are integers (not necessarily positive) with ` m <= n`.
77
8-
The `coeffs` specify `a_{m}, a_{m-1}, ..., a_{n}`. Rhe range specified is of the form `m:n`, if left empty, `0:length(coeffs)-1` is used (i.e., the coefficients refer to the standard basis).
8+
The `coeffs` specify `a_{m}, a_{m-1}, ..., a_{n}`. The range specified is of the form `m:n`, if left empty, `0:length(coeffs)-1` is used (i.e., the coefficients refer to the standard basis). Alternatively, the coefficients can be specified using an `OffsetVector` from the `OffsetArrays` package.
99
1010
Laurent polynomials and standard basis polynomials promote to Laurent polynomials. Laurent polynomials may be converted to a standard basis polynomial when `m >= 0`
1111
.
@@ -94,6 +94,17 @@ end
9494

9595
@register LaurentPolynomial
9696

97+
# Add interface for OffsetArray
98+
function LaurentPolynomial{T}(coeffs::OffsetArray{S, 1, Array{S,1}}, var::SymbolLike=:x) where {T, S}
99+
m,n = axes(coeffs, 1)
100+
LaurentPolynomial{T}(T.(coeffs.parent), m:n, Symbol(var))
101+
end
102+
function LaurentPolynomial(coeffs::OffsetArray{S, 1, Array{S,1}}, var::SymbolLike=:x) where {S}
103+
LaurentPolynomial{S}(coeffs, var)
104+
end
105+
106+
107+
97108
function LaurentPolynomial{T}(coeffs::AbstractVector{S},
98109
rng::UnitRange{Int64}=0:length(coeffs)-1,
99110
var::Symbol=:x) where {T <: Number, S <: Number}
@@ -109,11 +120,11 @@ function LaurentPolynomial(coeffs::AbstractVector{T}, var::SymbolLike=:x) where
109120
end
110121

111122
## Alternate interface
112-
Polynomial(coeffs::AbstractVector{T}, rng::UnitRange, var::SymbolLike=:x) where {T <: Number} =
113-
LaurentPolynomial{T}(coeffs, rng, Symbol(var))
123+
Polynomial(coeffs::OffsetArray{T,1,Array{T,1}}, var::SymbolLike=:x) where {T <: Number} =
124+
LaurentPolynomial{T}(coeffs, var)
114125

115-
Polynomial{T}(coeffs::AbstractVector{S}, rng::UnitRange, var::SymbolLike=:x) where {T <: Number, S <: Number} =
116-
LaurentPolynomial{T}(T.(coeffs), rng, Symbol(var))
126+
Polynomial{T}(coeffs::OffsetArray{S,1,Array{S,1}}, var::SymbolLike=:x) where {T <: Number, S <: Number} =
127+
LaurentPolynomial{T}(coeffs, var)
117128

118129
##
119130
## conversion
@@ -267,6 +278,122 @@ function showterm(io::IO, ::Type{<:LaurentPolynomial}, pj::T, var, j, first::Boo
267278
end
268279

269280

281+
##
282+
## ---- Conjugation has different defintions
283+
##
284+
285+
"""
286+
conj(p)
287+
288+
This satisfies `conj(p(x)) = conj(p)(conj(x)) = p̄(conj(x))` or `p̄(x) = (conj ∘ p ∘ conj)(x)`
289+
290+
Examples
291+
```jldoctest
292+
julia> z = variable(LaurentPolynomial, :z)
293+
LaurentPolynomial(z)
294+
295+
julia> p = LaurentPolynomial([im, 1+im, 2 + im], -1:1, :z)
296+
LaurentPolynomial(im*z⁻¹ + (1 + 1im) + (2 + 1im)*z)
297+
298+
julia> conj(p)(conj(z)) ≈ conj(p(z))
299+
true
300+
301+
julia> conj(p)(z) ≈ (conj ∘ p ∘ conj)(z)
302+
true
303+
```
304+
"""
305+
function LinearAlgebra.conj(p::P) where {P <: LaurentPolynomial}
306+
ps = coeffs(p)
307+
m,n = extrema(p)
308+
(P)(conj(ps),m:n, p.var)
309+
end
310+
311+
312+
"""
313+
paraconj(p)
314+
315+
[cf.](https://ccrma.stanford.edu/~jos/filters/Paraunitary_FiltersC_3.html)
316+
317+
Call `p̂ = paraconj(p)` and `p̄` = conj(p)`, then this satisfies
318+
`conj(p(z)) = p̂(1/conj(z))` or `p̂(z) = p̄(1/z) = (conj ∘ p ∘ conj ∘ inf)(z)`.
319+
320+
Examples:
321+
322+
```jldoctest
323+
julia> z = variable(LaurentPolynomial, :z)
324+
LaurentPolynomial(z)
325+
326+
julia> h = LaurentPolynomial([1,1], -1:0, :z)
327+
LaurentPolynomial(z⁻¹ + 1)
328+
329+
julia> Polynomials.paraconj(h)(z) ≈ 1 + z ≈ LaurentPolynomial([1,1], 0:1, :z)
330+
true
331+
332+
julia> h = LaurentPolynomial([3,2im,1], -2:0, :z)
333+
LaurentPolynomial(3*z⁻² + 2im*z⁻¹ + 1)
334+
335+
julia> Polynomials.paraconj(h)(z) ≈ 1 - 2im*z + 3z^2 ≈ LaurentPolynomial([1, -2im, 3], 0:2, :z)
336+
true
337+
338+
julia> Polynomials.paraconj(h)(z) ≈ (conj ∘ h ∘ conj ∘ inv)(z)
339+
true
340+
"""
341+
function paraconj(p::LaurentPolynomial)
342+
cs = p.coeffs
343+
ds = adjoint.(cs)
344+
m,n = extrema(p)
345+
LaurentPolynomial(reverse(ds), -n:-m, p.var)
346+
end
347+
348+
"""
349+
cconj(p)
350+
351+
Conjugation of a polynomial with respect to the imaginary axis.
352+
353+
The `cconj` of a polynomial, `p̃`, conjugates the coefficients and applies `s -> -s`. That is `cconj(p)(s) = conj(p)(-s)`.
354+
355+
This satisfies for *imaginary* `s`: `conj(p(s)) = p̃(s) = (conj ∘ p)(s) = cconj(p)(s) `
356+
357+
[ref](https://github.com/hurak/PolynomialEquations.jl#symmetrix-conjugate-equation-continuous-time-case)
358+
359+
Examples:
360+
```jldoctest
361+
julia> s = 2im
362+
0 + 2im
363+
364+
julia> p = LaurentPolynomial([im,-1, -im, 1], 1:2, :s)
365+
LaurentPolynomial(im*s - s² - im*s³ + s⁴)
366+
367+
julia> Polynomials.cconj(p)(s) ≈ conj(p(s))
368+
true
369+
370+
julia> a = LaurentPolynomial([-0.12, -0.29, 1],:s)
371+
LaurentPolynomial(-0.12 - 0.29*s + 1.0*s²)
372+
373+
julia> b = LaurentPolynomial([1.86, -0.34, -1.14, -0.21, 1.19, -1.12],:s)
374+
LaurentPolynomial(1.86 - 0.34*s - 1.14*s² - 0.21*s³ + 1.19*s⁴ - 1.12*s⁵)
375+
376+
julia> x = LaurentPolynomial([-15.5, 50.0096551724139, 1.19], :s)
377+
LaurentPolynomial(-15.5 + 50.0096551724139*s + 1.19*s²)
378+
379+
julia> Polynomials.cconj(a) * x + a * Polynomials.cconj(x) ≈ b + Polynomials.cconj(b)
380+
true
381+
```
382+
383+
"""
384+
function cconj(p::LaurentPolynomial)
385+
ps = conj.(coeffs(p))
386+
m,n = extrema(p)
387+
for i in m:n
388+
if isodd(i)
389+
ps[i+1-m] *= -1
390+
end
391+
end
392+
LaurentPolynomial(ps, m:n, p.var)
393+
end
394+
395+
396+
270397
##
271398
## ----
272399
##
@@ -279,10 +406,13 @@ function (p::LaurentPolynomial{T})(x::S) where {T,S}
279406
if m >= 0
280407
evalpoly(x, NTuple{n+1,T}(p[i] for i in 0:n))
281408
elseif n <= 0
282-
evalpoly(inv(x), NTuple{m+1,T}(p[i] for i in 0:-1:m))
409+
evalpoly(inv(x), NTuple{-m+1,T}(p[i] for i in 0:-1:m))
283410
else
284411
# eval pl(x) = a_mx^m + ...+ a_0 at 1/x; pr(x) = a_0 + a_1x + ... + a_nx^n at x; subtract a_0
285-
evalpoly(inv(x), NTuple{-m+1,T}(p[i] for i in 0:-1:m)) + evalpoly(x, NTuple{n+1,T}(p[i] for i in 0:n)) - p[0]
412+
l = evalpoly(inv(x), NTuple{-m+1,T}(p[i] for i in 0:-1:m))
413+
r = evalpoly(x, NTuple{n+1,T}(p[i] for i in 0:n))
414+
mid = p[0]
415+
l + r - mid
286416
end
287417
end
288418

@@ -426,3 +556,20 @@ function integrate(p::P, k::S) where {T, P<: LaurentPolynomial{T}, S<:Number}
426556
return (P)(as, m:n, p.var)
427557

428558
end
559+
560+
561+
function Base.gcd(p::LaurentPolynomial{T}, q::LaurentPolynomial{T}, args...; kwargs...) where {T}
562+
mp, Mp = extrema(p)
563+
mq, Mq = extrema(q)
564+
if mp < 0 || mq < 0
565+
throw(ArgumentError("GCD is not defined when there are `x⁻¹` terms"))
566+
end
567+
568+
degree(p) == 0 && return iszero(p) ? q : one(q)
569+
degree(q) == 0 && return iszero(q) ? p : one(p)
570+
check_same_variable(p,q) || throw(ArgumentError("p and q have different symbols"))
571+
572+
pp, qq = convert(Polynomial, p), convert(Polynomial, q)
573+
u = gcd(pp, qq, args..., kwargs...)
574+
return LaurentPolynomial(coeffs(u), p.var)
575+
end

0 commit comments

Comments
 (0)