# LDLt factorization for full matrices

**URL:** <https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356>\
**Category:** Numerics\
**Tags:** question, linearalgebra\
**Created:** [January 28, 2022, 12:09pm UTC](https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356 "2022-01-28T12:09:26Z")\
**Posts on this page:** 8\
**Page:** 2

<div class="post-metadata">

**Author:** ![mstewart](https://avatars.discourse-cdn.com/v4/letter/m/b5a626/32.png) [@mstewart](https://discourse.julialang.org/u/mstewart)\
**Post date:** [May 23, 2022, 4:54pm UTC](https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356/22 "2022-05-23T16:54:56Z")

</div>

I’m not on a computer where I can try Matlab, although maybe I can check it out later. Looking it over, it’s not clear to me where on that doc page it says that it will produce 2\times 2 blocks if the function is applied to a sparse indefinite matrix. Does Matlab do that when you try it? I thought Matlab used CHOLMOD, which pretty clearly says in [CHOLMOD Docs](https://github.com/DrTimothyAldenDavis/SuiteSparse/blob/master/CHOLMOD/Doc/CHOLMOD_UserGuide.pdf) that A needs to have well conditioned leading principal submatrices. That is a pretty strong hint that it isn’t pivoting for stability.

Update: I did try it on Matlab. It looks like they are using the algorithm [MA57](https://dl.acm.org/doi/abs/10.1145/992200.992202) which is in [HSL](https://www.hsl.rl.ac.uk/). There appear to be an interface to HSL at [HSL.jl](https://github.com/JuliaSmoothOptimizers/HSL.jl). If it works as expected, it looks like you can do this and get back the separate factors to modify and enforce positive definiteness.

---

<div class="post-metadata">

**Author:** ![mancolric](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mancolric/32/21799_2.png) [@mancolric](https://discourse.julialang.org/u/mancolric)\
**Post date:** [May 23, 2022, 6:55pm UTC](https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356/23 "2022-05-23T18:55:16Z")

</div>

Thank you very much @mstewart and others, you have helped me a lot.

---

<div class="post-metadata">

**Author:** ![RoyiAvital](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/royiavital/32/571_2.png) [@RoyiAvital](https://discourse.julialang.org/u/RoyiAvital)\
**Post date:** [August 17, 2025, 4:47pm UTC](https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356/24 "2025-08-17T16:47:00Z")

</div>

> [@mstewart](#):
>
> If you are looking for exactly diagonal D for an indefinite matrix, it’s a bit worse than unstable. The decomposition you are looking for does not even exist in general for symmetric indefinite A, even with symmetric pivoting.

What about a symmetric matrix with non negative eigen values (Semi Definite / SPSD)?  
Will that case have a stable \boldsymbol{L} \boldsymbol{D} \boldsymbol{L}^{T} decomposition?

---

<div class="post-metadata">

**Author:** ![mstewart](https://avatars.discourse-cdn.com/v4/letter/m/b5a626/32.png) [@mstewart](https://discourse.julialang.org/u/mstewart)\
**Post date:** [August 17, 2025, 5:21pm UTC](https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356/25 "2025-08-17T17:21:28Z")

</div>

Assuming you mean an LDL^T with pivoting, it does exist for symmetric positive semidefinite matrices. Even somewhat better, there is a pivoted Cholesky that can be computed with

```julia-auto
C = cholesky(A, RowMaximum())

```

There are some keyword parameters for checking the decomposition and providing a tolerance for rank determination.

---

<div class="post-metadata">

**Author:** ![RoyiAvital](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/royiavital/32/571_2.png) [@RoyiAvital](https://discourse.julialang.org/u/RoyiAvital)\
**Post date:** [August 17, 2025, 5:26pm UTC](https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356/26 "2025-08-17T17:26:06Z")

</div>

> [@mstewart](#):
>
> There are some keyword parameters for checking the decomposition and providing a tolerance for rank determination.

Any chance you elaborate on that?  
What if the LDL Decomposition is specifically needed. How can one achieve it?

---

<div class="post-metadata">

**Author:** ![mstewart](https://avatars.discourse-cdn.com/v4/letter/m/b5a626/32.png) [@mstewart](https://discourse.julialang.org/u/mstewart)\
**Post date:** [August 17, 2025, 6:05pm UTC](https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356/27 "2025-08-17T18:05:53Z")

</div>

You just factor out the diagonal from L on both sides and L becomes unit lower triangular. Here it is

```julia-auto
using LinearAlgebra

n=10
r = 5
A = randn(n,r)
A = A * A'
tol = 1e-15

F = cholesky(Hermitian(A), RowMaximum(); tol = tol, check = false)
r = F.rank # rank
L = F.L # lower triangular Cholesky factor
p = F.p # permutation of the rows/columns of A
d = diag(F.L) # diagonal of L
L[:, 1:r] = L[:,1:r] / Diagonal(d[1:r]) # Scale to make L unit lower.
L = UnitLowerTriangular(L)
d = vcat(d[1:r], zeros(n-r)) # last n-r diagonal elements should be zero. (A has rank r.)
D = Diagonal(d.^2) # The diagonal has a contribution from $L$ and $L'$, which square.
@show opnorm(A[p, p] - L * D * L') # check the backward error.

```

In most applications you could probably work with the Cholesky factor directly, so I’m not sure there’s much advantage in pulling out D from the triangular factors.

---

<div class="post-metadata">

**Author:** ![RoyiAvital](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/royiavital/32/571_2.png) [@RoyiAvital](https://discourse.julialang.org/u/RoyiAvital)\
**Post date:** [August 18, 2025, 6:17am UTC](https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356/28 "2025-08-18T06:17:59Z")

</div>

> [@mstewart](#):
>
> In most applications you could probably work with the Cholesky factor directly, so I’m not sure there’s much advantage in pulling out D from the triangular factors.

Just to align my thought, I’ll state the trivial.

Assume \boldsymbol{A} = \boldsymbol{C}^{T} \boldsymbol{C} for some matrix \boldsymbol{C}.  
Mathematically \boldsymbol{A} is guaranteed to be SPSD. Yet numerical issues might cause it to have some small negative eigen values.

My idea is that using LDL Decomposition I will be able to clip the small negative values (I know the \boldsymbol{D} in LDL is not the \boldsymbol{D} in the Eigen Decomposition, just borrowed the concept).  
So, given what’s available in Julia, is there a way to get the LDL of an SPSD matrix?

---

<div class="post-metadata">

**Author:** ![mstewart](https://avatars.discourse-cdn.com/v4/letter/m/b5a626/32.png) [@mstewart](https://discourse.julialang.org/u/mstewart)\
**Post date:** [August 18, 2025, 10:16am UTC](https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356/29 "2025-08-18T10:16:10Z")

</div>

This is handled by the code I posted. (Note I made an edit to the scaling of L; I had ignored that you would be dividing by a small or even zero element at L\_{rr}). You can stop pivoted Cholesky at the first pivot that is sufficiently small or zero. The built in pivoted Cholesky does this for you.

It is perhaps worth noting that the block `L[r+1:n, r+1:n]` is essentially arbitrary. I returned what was stored in the Cholesky factor at the end of the factorization, but that isn’t significant and you could just as easily make that block equal the identity.

[Previous page](https://discourse.julialang.org/t/ldlt-factorization-for-full-matrices/75356.md?page=1)
