Skip to content

Commit d5a472a

Browse files
Use Leja ordering for fromroots (#586)
1 parent b00ea5e commit d5a472a

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

src/common.jl

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,41 @@ export fromroots,
1717
isintegral,
1818
ismonic
1919

20+
function lejaorder!(roots) # see https://doi.org/10.1023/A:1025555803588
21+
if length(roots) <= 2
22+
return roots
23+
end
24+
#ii = argmax(j -> abs(roots[j]), eachindex(roots))
25+
ii = firstindex(roots)
26+
rmax = abs(roots[ii])
27+
for j in eachindex(roots)
28+
rabs = abs(roots[j])
29+
if rabs > rmax
30+
ii = j
31+
rmax = rabs
32+
end
33+
end
34+
roots[1], roots[ii] = roots[ii], roots[1]
35+
products = abs.(roots .- roots[1])
36+
for k in eachindex(roots)[begin+1:end-1]
37+
ii = findnext(iszero, products, k) # product[ii] == 0 means that roots[ii] == roots[k-1]
38+
if isnothing(ii)
39+
#ii = argmax(i -> products[i], k:lastindex(roots))
40+
ii = k
41+
for j in k+1:lastindex(products)
42+
if products[j] > products[ii]
43+
ii = j
44+
end
45+
end
46+
end
47+
roots[k], roots[ii] = roots[ii], roots[k]
48+
products[k], products[ii] = products[ii], products[k]
49+
products .*= abs.(roots .- roots[k])
50+
end
51+
return roots
52+
end
53+
lejaorder(roots) = lejaorder!(copy(roots))
54+
2055
"""
2156
fromroots(::AbstractVector{<:Number}; var=:x)
2257
fromroots(::Type{<:AbstractPolynomial}, ::AbstractVector{<:Number}; var=:x)
@@ -33,7 +68,7 @@ Polynomial(6 - 5*x + x^2)
3368
"""
3469
function fromroots(P::Type{<:AbstractPolynomial}, rs; var::SymbolLike = :x)
3570
x = variable(P, var)
36-
p = prod(x-r for r rs; init=one(x))
71+
p = prod(x-r for r lejaorder(rs); init=one(x))
3772
p = truncate!!(p)
3873
p
3974
end

src/polynomials/standard-basis/standard-basis.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ end
403403
## polynomial-roots
404404
function fromroots(P::Type{<:AbstractDenseUnivariatePolynomial{StandardBasis}}, r::AbstractVector{T}; var::SymbolLike = Var(:x)) where {T <: Number}
405405
n = length(r)
406+
r = lejaorder(r)
406407
c = zeros(T, n + 1)
407408
c[1] = one(T)
408409
for j in 1:n, i in j:-1:1

test/StandardBasis.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,10 @@ end
984984
b = fromroots(r)
985985
(b a) & isreal(coeffs(b)) # the coeff should be real
986986
end
987+
p = Polynomial([1; zeros(99); -1])
988+
if P !== FactoredPolynomial
989+
@test fromroots(P, roots(p)) * p[end] p
990+
end
987991
end
988992
end
989993

0 commit comments

Comments
 (0)