Skip to content

Commit b719954

Browse files
authored
fix: Taylor exponentiate shouldn't assume typeof(A*A) === typeof(A) (#255)
1 parent dad6197 commit b719954

2 files changed

Lines changed: 28 additions & 4 deletions

File tree

src/implementations/exponential.jl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,16 @@ function exponential!(A::AbstractMatrix, expA, alg::MatrixFunctionViaTaylor)
130130
# Form a minimal set of powers of A up front and use them to sharpen the norm estimate
131131
# through the Al-Mohy–Higham quantities dₚ = ‖Aᵖ‖^(1/p).
132132
p₀ = min(convert(Int, get(alg.kwargs, :estimate_order, 4)), m)
133-
powers = Vector{typeof(A)}(undef, p₀)
134-
powers[1] = A
135133
d = Vector{R}(undef, p₀)
136134
d[1] = LinearAlgebra.opnorm(A, 1)
137135
iszero(d[1]) && return one!(expA)
136+
137+
powers = Vector{Base.promote_op(similar, typeof(A))}(undef, p₀)
138+
powers[1] = eltype(powers) === typeof(A) ? A : copyto!(similar(A), A)
139+
138140
for p in 2:p₀
139-
powers[p] = powers[p - 1] * A
141+
powers[p] = similar(powers[1])
142+
mul!(powers[p], powers[p - 1], powers[1])
140143
d[p] = LinearAlgebra.opnorm(powers[p], 1)^(1 / p)
141144
end
142145

@@ -152,8 +155,11 @@ function exponential!(A::AbstractMatrix, expA, alg::MatrixFunctionViaTaylor)
152155
end
153156
end
154157
# Extend from p₀ to `blocksize` powers (blocksize ≥ p₀ always, see taylor_order_and_squarings)
158+
sizehint!(powers, blocksize)
155159
for p in (p₀ + 1):blocksize
156-
push!(powers, powers[p - 1] * powers[1])
160+
Pp = similar(powers[1])
161+
mul!(Pp, powers[p - 1], powers[1])
162+
push!(powers, Pp)
157163
end
158164

159165

test/exponential.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,24 @@ end
5757
@test_throws DomainError exponential((τ, A); alg = MatrixFunctionViaEigh(LAPACK_QRIteration()))
5858
end
5959

60+
@testset "exponential! for non-Matrix input $T" for T in BLASFloats
61+
rng = StableRNG(123)
62+
m = 12
63+
A = LinearAlgebra.normalize!(randn(rng, T, m, m))
64+
expA = LinearAlgebra.exp(A)
65+
66+
wrappers = (
67+
("view", B -> view(B, :, :)),
68+
("PermutedDimsArray", B -> PermutedDimsArray(permutedims(B), (2, 1))),
69+
("ReshapedArray", B -> reshape(view(vec(B), 1:(m * m)), m, m)),
70+
)
71+
@testset "$name" for (name, wrap) in wrappers
72+
W = wrap(copy(A))
73+
@test !(W isa Matrix)
74+
@test exponential!(W) expA
75+
end
76+
end
77+
6078
@testset "exponential! for Diagonal{$T}" for T in (BLASFloats..., GenericFloats...)
6179
rng = StableRNG(123)
6280
m = 54

0 commit comments

Comments
 (0)