Skip to content

Commit 7055644

Browse files
authored
Unalias off-diagonals in Tridiagonal constructor (#51763)
1 parent c1ca0d3 commit 7055644

File tree

4 files changed

+18
-10
lines changed

4 files changed

+18
-10
lines changed

stdlib/LinearAlgebra/src/lu.jl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -520,9 +520,6 @@ end
520520

521521
# Initialize variables
522522
info = 0
523-
if dl === du
524-
throw(ArgumentError("off-diagonals must not alias"))
525-
end
526523
fill!(du2, 0)
527524

528525
@inbounds begin

stdlib/LinearAlgebra/src/tridiag.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -472,13 +472,13 @@ struct Tridiagonal{T,V<:AbstractVector{T}} <: AbstractMatrix{T}
472472
"lengths of subdiagonal, diagonal and superdiagonal: ",
473473
"($(length(dl)), $(length(d)), $(length(du)))")))
474474
end
475-
new{T,V}(dl, d, du)
475+
new{T,V}(dl, d, Base.unalias(dl, du))
476476
end
477477
# constructor used in lu!
478478
function Tridiagonal{T,V}(dl, d, du, du2) where {T,V<:AbstractVector{T}}
479479
require_one_based_indexing(dl, d, du, du2)
480480
# length checks?
481-
new{T,V}(dl, d, du, du2)
481+
new{T,V}(dl, d, Base.unalias(dl, du), du2)
482482
end
483483
end
484484

@@ -491,6 +491,10 @@ solvers, but may be converted into a regular matrix with
491491
[`convert(Array, _)`](@ref) (or `Array(_)` for short).
492492
The lengths of `dl` and `du` must be one less than the length of `d`.
493493
494+
!!! note
495+
The subdiagonal `dl` and the superdiagonal `du` must not be aliased to each other.
496+
If aliasing is detected, the constructor will use a copy of `du` as its argument.
497+
494498
# Examples
495499
```jldoctest
496500
julia> dl = [1, 2, 3];
@@ -912,9 +916,6 @@ function ldiv!(A::Tridiagonal, B::AbstractVecOrMat)
912916
dl = A.dl
913917
d = A.d
914918
du = A.du
915-
if dl === du
916-
throw(ArgumentError("off-diagonals of `A` must not alias"))
917-
end
918919

919920
@inbounds begin
920921
for i in 1:n-1

stdlib/LinearAlgebra/test/lu.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ dimg = randn(n)/2
9797
dlu = convert.(eltya, [1, 1])
9898
dia = convert.(eltya, [-2, -2, -2])
9999
tri = Tridiagonal(dlu, dia, dlu)
100-
@test_throws ArgumentError lu!(tri)
100+
L = lu(tri)
101+
@test lu!(tri) == L
102+
@test UpperTriangular(tri) == L.U
101103
end
102104
end
103105
@testset for eltyb in (Float32, Float64, ComplexF32, ComplexF64, Int)

stdlib/LinearAlgebra/test/tridiag.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ end
8282
@test TT == Matrix(TT)
8383
@test TT.dl === y
8484
@test TT.d === x
85-
@test TT.du === y
85+
@test TT.du == y
8686
@test typeof(TT)(TT) === TT
8787
end
8888
ST = SymTridiagonal{elty}([1,2,3,4], [1,2,3])
@@ -521,6 +521,14 @@ end
521521
@test Tridiagonal(4:5, 1:3, 1:2) == [1 1 0; 4 2 2; 0 5 3]
522522
end
523523

524+
@testset "Prevent off-diagonal aliasing in Tridiagonal" begin
525+
e = ones(4)
526+
f = e[1:end-1]
527+
T = Tridiagonal(f, 2e, f)
528+
T ./= 10
529+
@test all(==(0.1), f)
530+
end
531+
524532
@testset "Issue #26994 (and the empty case)" begin
525533
T = SymTridiagonal([1.0],[3.0])
526534
x = ones(1)

0 commit comments

Comments
 (0)