Skip to content

Commit

Permalink
Add LDLt factorization for Strang (#78)
Browse files Browse the repository at this point in the history
* Add factorize for Strang

* Show Strang LDL'

* Limit factorize to >= v1.8
  • Loading branch information
JeffFessler committed Jan 2, 2023
1 parent 6632c23 commit 18622c3
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
10 changes: 9 additions & 1 deletion docs/lit/examples/1-overview.jl
Expand Up @@ -23,6 +23,7 @@ Toeplitz, Hankel, and circulant matrices.

using SpecialMatrices
using Polynomials
using LinearAlgebra: factorize, Diagonal


# ## [`Cauchy` matrix](http://en.wikipedia.org/wiki/Cauchy_matrix)
Expand Down Expand Up @@ -111,7 +112,14 @@ Riemann(5)
A special symmetric, tridiagonal, Toeplitz matrix named after Gilbert Strang.
=#

Strang(5)
S = Strang(5)

# The Strang matrix has a special ``L D L'`` factorization:
F = factorize(S)

# Here is a verification:
F.L * Diagonal(F.D) * F.L'


# ## [`Vandermonde` matrix](http://en.wikipedia.org/wiki/Vandermonde_matrix)

Expand Down
28 changes: 28 additions & 0 deletions src/strang.jl
@@ -1,5 +1,7 @@
export Strang

using LinearAlgebra: LDLt, SymTridiagonal

"""
Strang([T=Int,] n::Int)
Expand Down Expand Up @@ -61,3 +63,29 @@ end
y[2:end] .-= @view x[1:end-1]
return y
end


# LU factors for future reference:
#=
SparseArrays: spdiagm
L = spdiagm(0 => ones(n), -1 => -(1:n-1) ./ (2:n))
U = spdiagm(0 => (2:n+1) ./ (1:n), 1 => -ones(n-1))
=#

if VERSION >= v"1.8"
#=
Strang is a special case of SymTridiagonal,
and the default factorization of that class is LDLt
https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#LinearAlgebra.factorize
so we use that here,
even though it does not fully exploit the sparse structure
of the LL' and LDL' factorizations of a Strang matrix.
=#
function LinearAlgebra.factorize(A::Strang)
n = A.n
ev = -(1:n-1) ./ (2:n) # L = spdiagm(0 => ones(n), -1 => ev)
dv = (2:n+1) ./ (1:n) # D = Diagonal(dv)
S = SymTridiagonal(dv, ev)
return LDLt(S)
end
end
20 changes: 20 additions & 0 deletions test/strang.jl
Expand Up @@ -2,6 +2,7 @@

using SpecialMatrices: Strang
using LinearAlgebra: diagm, issymmetric, ishermitian, isposdef
using LinearAlgebra: factorize, SymTridiagonal, Diagonal
using Test: @test, @testset, @test_throws, @inferred

@testset "strang" begin
Expand Down Expand Up @@ -30,3 +31,22 @@ using Test: @test, @testset, @test_throws, @inferred
@test ishermitian(A)
@test isposdef(A)
end


if VERSION >= v"1.8"

@testset "strang-factor" begin
# factorize:
n = 5
A = Strang(5)
M = Matrix(A)
T = SymTridiagonal(M)
F = factorize(T)
G = factorize(A)
H = G.L * Diagonal(G.D) * G.L'
@test H M
@test F.L G.L
@test F.D G.D
end

end

2 comments on commit 18622c3

@JeffFessler
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator() register

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/74907

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v3.0.0 -m "<description of version>" 18622c37e3ab06952edb3c76430186aa53edcb70
git push origin v3.0.0

Please sign in to comment.