Skip to content

Commit 5c7c982

Browse files
committed
implemented ChebyshevT divrem
1 parent 0ebf9ff commit 5c7c982

File tree

2 files changed

+87
-25
lines changed

2 files changed

+87
-25
lines changed

src/polynomials/ChebyshevT.jl

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ function fromroots(P::Type{<:ChebyshevT}, roots::AbstractVector{T}; var::SymbolL
7171
p = tmp
7272
n = m
7373
end
74-
# return truncate!(reduce(*, p))
7574
return truncate!(p[1])
7675
end
7776

@@ -149,29 +148,28 @@ function Base.:*(p1::ChebyshevT{T}, p2::ChebyshevT{S}) where {T,S}
149148
end
150149

151150
##
152-
# function Base.divrem(num::ChebyshevT{T}, den::ChebyshevT{S}) where {T,S}
153-
# num.var != den.var && error("Polynomials must have same variable")
154-
# n = length(num) - 1
155-
# m = length(den) - 1
156-
# if m == 0 && den[0] ≈ 0 throw(DivideError()) end
157-
# R = typeof(one(T) / one(S))
158-
# P = ChebyshevT{R}
159-
# deg = n - m + 1
160-
# if deg ≤ 0
161-
# return zero(P), convert(P, num)
162-
# end
163-
# q_coeff = zeros(R, deg)
164-
# r_coeff = R.(num[0:n])
165-
# @inbounds for i in n:-1:m
166-
# q = r_coeff[i + 1] / den[m]
167-
# q_coeff[i - m + 1] = q
168-
# @inbounds for j in 0:m
169-
# elem = den[j] * q
170-
# r_coeff[i - m + j + 1] -= elem
171-
# end
172-
# end
173-
# return P(q_coeff, num.var), P(r_coeff, num.var)
174-
# end
151+
function Base.divrem(num::ChebyshevT{T}, den::ChebyshevT{S}) where {T,S}
152+
num.var != den.var && error("Polynomials must have same variable")
153+
n = length(num) - 1
154+
m = length(den) - 1
155+
156+
R = typeof(one(T) / one(S))
157+
P = ChebyshevT{R}
158+
159+
if n < m
160+
return zero(P), convert(P, num)
161+
elseif m == 0
162+
den[0] 0 && throw(DivideError())
163+
return num ./ den[end], zero(P)
164+
end
165+
166+
znum = _c_to_z(num.coeffs)
167+
zden = _c_to_z(den.coeffs)
168+
quo, rem = _z_division(znum, zden)
169+
q_coeff = _z_to_c(quo)
170+
r_coeff = _z_to_c(rem)
171+
return P(q_coeff, num.var), P(r_coeff, num.var)
172+
end
175173
# ##
176174
# function Base.gcd(a::ChebyshevT{T}, b::ChebyshevT{S}) where {T,S}
177175
# U = typeof(one(T) / one(S))
@@ -213,3 +211,39 @@ function _z_to_c(z::AbstractVector{T}) where {T}
213211
cs[2:n] *= 2
214212
return cs
215213
end
214+
215+
function _z_division(z1::AbstractVector{T}, z2::AbstractVector{S}) where {T,S}
216+
R = eltype(one(T) / one(S))
217+
length(z1)
218+
length(z2)
219+
if length(z2) == 1
220+
z1 ./= z2
221+
return z1, zero(R)
222+
elseif length(z1) < length(z2)
223+
return zero(R), R.(z1)
224+
end
225+
dlen = length(z1) - length(z2)
226+
scl = z2[1]
227+
z2 ./= scl
228+
quo = Vector{R}(undef, dlen + 1)
229+
i = 1
230+
j = dlen + 1
231+
while i < j
232+
r = z1[i]
233+
quo[i] = z1[i]
234+
quo[end - i + 1] = r
235+
tmp = r .* z2
236+
z1[i:i + length(z2) - 1] .-= tmp
237+
z1[j:j + length(z2) - 1] .-= tmp
238+
i += 1
239+
j -= 1
240+
end
241+
242+
r = z1[i]
243+
quo[i] = r
244+
tmp = r * z2
245+
z1[i:i + length(z2) - 1] .-= tmp
246+
quo ./= scl
247+
rem = z1[i + 1:i - 2 + length(z2)]
248+
return quo, rem
249+
end

test/ChebyshevT.jl

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ end
5050
for i in 1:5
5151
roots = cos.(range(-π, 0, length = 2i + 1)[2:2:end])
5252
target = ChebyshevT(append!(zeros(i), [1]))
53-
res = fromroots(ChebyshevT, roots) .* 2^(i-1)
53+
res = fromroots(ChebyshevT, roots) .* 2^(i - 1)
5454
@test res == target
5555
end
5656
@test fromroots(ChebyshevT, [-1, 0, 1]) == ChebyshevT([0, -0.25, 0, 0.25])
@@ -86,6 +86,27 @@ end
8686
c2 = ChebyshevT([3, 2, 1])
8787
@test c1 * c2 == ChebyshevT([6.5, 12, 12, 4, 1.5])
8888

89+
# division remainder
90+
for i in 1:5, j in 1:5
91+
c1 = ChebyshevT(append!(zeros(i), [1]))
92+
c2 = ChebyshevT(append!(zeros(j), [1]))
93+
target = c1 + c2
94+
quo, rem = divrem(target, c1)
95+
res = quo * c1 + rem
96+
@test res target
97+
end
98+
99+
c1 = ChebyshevT([1, 2, 3])
100+
c2 = ChebyshevT([3, 2, 1])
101+
d, r = divrem(c1, c2)
102+
@test coeffs(d) [3]
103+
@test coeffs(r) [-8, -4]
104+
105+
c2 = ChebyshevT([0, 1, 2, 3])
106+
d, r = divrem(c2, c1)
107+
@test coeffs(d) [0, 2]
108+
@test coeffs(r) [-2, -4]
109+
89110
end
90111

91112
@testset "z-series" for i in 1:5
@@ -96,4 +117,11 @@ end
96117
@test zs == target
97118
c = Polynomials._z_to_c(zs)
98119
@test c == input
120+
121+
# div
122+
z1 = [0.5, 0.0, 0.5]
123+
z2 = [0.5, 0.0, 0.5]
124+
q, r = Polynomials._z_division(z1, z2)
125+
@test q == [1]
126+
@test r == [0]
99127
end

0 commit comments

Comments
 (0)