diff --git a/src/SkewLinearAlgebra.jl b/src/SkewLinearAlgebra.jl index f5ad466..18b063d 100644 --- a/src/SkewLinearAlgebra.jl +++ b/src/SkewLinearAlgebra.jl @@ -11,18 +11,22 @@ export #Types SkewHermitian, SkewHermTridiagonal, + SkewCholesky, #functions isskewhermitian, skewhermitian, skewhermitian!, pfaffian, - pfaffian! + pfaffian!, + skewchol, + skewchol! include("skewhermitian.jl") include("tridiag.jl") include("hessenberg.jl") include("eigen.jl") include("exp.jl") +include("cholesky.jl") include("pfaffian.jl") end diff --git a/src/cholesky.jl b/src/cholesky.jl index 992b783..1823e5a 100644 --- a/src/cholesky.jl +++ b/src/cholesky.jl @@ -1,62 +1,68 @@ -#import .SkewLinearAlgebra as SLA -@views function skewchol!(A::SLA.SkewHermitian) - B = A.data - tol = 1e-15 + +struct SkewCholesky{T,R<:UpperTriangular{<:T},J<:SkewHermTridiagonal{<:T},P<:AbstractVector{<:Integer}} + Rm::R #Uppertriangular matrix + Jm::J # Block diagonal skew-symmetric matrix + Pv::P #Permutation vector + + function SkewCholesky{T,R,J,P}(Rm,Jm,Pv) where {T,R,J,P} + LA.require_one_based_indexing(Rm) + new{T,R,J,P}(Rm,Jm,Pv) + end +end +#SkewCholesky(Rm::UpperTriangular{<:T},Jm::SkewHermTridiagonal{<:T},Pv::AbstractVector{<:Integer}) where {T<:Real} = SkewCholesky(Rm,Jm,Pv) + +function SkewCholesky(Rm::UpperTriangular{<:T},Pv::AbstractVector{<:Integer}) where {T<:Real} + n=size(Rm,1) + vec = zeros(T,n-1) + for i = 1:2:n-1 + vec[i] = -1 + end + return SkewCholesky{T,UpperTriangular{<:T},SkewHermTridiagonal{<:T},AbstractVector{<:Integer}}(Rm,SkewHermTridiagonal(vec),Pv) + +end + +function _skewchol!(A::SkewHermitian) + @views B = A.data + tol = 1e-15*norm(B) m = size(B,1) - J2 = [0 1;-1 0] + J2 = similar(B,2,2) + J2[1,1] = 0; J2[2,1] = -1; J2[1,2] = 1; J2[2,2] = 0 ii = 0; jj = 0; kk = 0 P = Array(1:m) - temp = similar(B,m) tempM = similar(B,2,m-2) for j = 1:m÷2 j2 = 2*j - M = maximum(B[j2-1:m,j2-1:m]) - for i1 = j2-1:m - for i2 = j2-1:m - if B[i1,i2] == M - ii = i1 - jj = i2 - end - end - end + + M = findmax(B[j2-1:m,j2-1:m]) + ii = M[2][1] + j2 - 2 + jj = M[2][2] + j2 - 2 if abs(B[ii,jj])RQx=J^T R^(-T) Q^Tb -""" + + + diff --git a/test/runtests.jl b/test/runtests.jl index b44766b..04fd70f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -265,16 +265,6 @@ end end end - -@testset "pfaffian.jl" begin - for n in [2,3,4,5,6,8,10,20,40] - A=SLA.skewhermitian(rand(-10:10,n,n)*2) - Abig = BigInt.(A.data) - @test SLA.pfaffian(A) ≈ SLA.pfaffian(Abig) == SLA.pfaffian(SLA.SkewHermitian(Abig)) - #@test SLA.pfaffian(Abig)^2 ≈ det(Abig) #ideally compare with == if recent Julia version - end - -end @testset "pfaffian.jl" begin for n in [2,3,4,5,6,8,10,20,40] A=SLA.skewhermitian(rand(-10:10,n,n)*2) @@ -289,6 +279,22 @@ end @test SLA.pfaffian(big.([0 14 7 -10 0 10 0 -11; -14 0 -10 7 13 -9 -12 -13; -7 10 0 -4 6 -17 -1 18; 10 -7 4 0 -2 -4 0 11; 0 -13 -6 2 0 -8 -18 17; -10 9 17 4 8 0 -8 12; 0 12 1 0 18 8 0 0; 11 13 -18 -11 -17 -12 0 0])) == -119000 end +@testset "cholesky.jl" begin + for T in (Int32, Int64, Float32, Float64), n in [2,4,20,100] + if T<:Integer + A = SLA.skewhermitian(rand(convert(Array{T},-10:10),n,n)*2) + else + A = SLA.skewhermitian(randn(T,n,n)) + end + C = SLA.skewchol(A) + @test transpose(C.Rm)*Matrix(C.Jm)*C.Rm ≈A.data[C.Pv,C.Pv] + B = Matrix(A) + C = SLA.skewchol(B) + @test transpose(C.Rm)*Matrix(C.Jm)*C.Rm ≈B[C.Pv,C.Pv] + end +end + + #=