Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MatrixAlgebraKit"
uuid = "6c742aac-3347-4629-af66-fc926824e5e4"
authors = ["Jutho <[email protected]> and contributors"]
version = "0.5.0"
version = "0.6.0"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand Down
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ makedocs(;
],
"Developer Interface" => "dev_interface.md",
"Library" => "library.md",
"Changelog" => "changelog.md",
],
checkdocs = :exports,
doctest = true,
Expand Down
64 changes: 64 additions & 0 deletions docs/src/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Guidelines for updating this changelog

When making changes to this project, please update the "Unreleased" section with your changes under the appropriate category:

- **Added** for new features.
- **Changed** for changes in existing functionality.
- **Deprecated** for soon-to-be removed features.
- **Removed** for now removed features.
- **Fixed** for any bug fixes.
- **Security** in case of vulnerabilities.

When releasing a new version, move the "Unreleased" changes to a new version section with the release date.

[Unreleased]: https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/compare/v0.6.0...HEAD
[0.6.0]: https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/releases/tag/v0.6.0

## [Unreleased]

### Added

### Changed

### Deprecated

### Removed

### Fixed

### Security

## [0.6.0] - 2025-11-14

### Added
- New `project_isometric` function for projecting matrices onto isometric manifold ([#67](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/67))
- New `PolarNewton` algorithm for polar decomposition ([#67](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/67))
- New matrix property functions: `ishermitian`, `isantihermitian`, `hermitianpart!`, `hermitianpart`, `antihermitianpart!`, and `antihermitianpart` ([#64](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/64))
- Support for `BigFloat` via new `GenericLinearAlgebra` extension ([#87](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/87))
- Mooncake reverse-mode AD rules ([#85](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/85))
- GPU support for image and null space computations ([#82](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/82))
- GPU support for polar decomposition ([#83](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/83))
- GPU support for new projection operations ([#81](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/81))
- Output truncation error for truncated decompositions ([#75](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/75))
- Documentation for truncated decomposition keyword arguments ([#71](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/71))
- Default algorithm implementations for GPU wrapper array types ([#49](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/49))

### Changed

- Made `gaugefix!` optional ([#95](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/95))
- Renamed `isisometry` to `isisometric` for consistency with `project_isometric` ([#73](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/73))
- Refactored `left_orth`, `right_orth`, `left_null` and `right_null` interface ([#79](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/79))
- Improved GPU support for SVD operations ([#80](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/80))
- Loosened strictness on hermitian checks ([#78](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/78))
- Updated pullback tolerances ([#92](https://github.com/QuantumKitHub/MatrixAlgebraKit.jl/pull/92))

### Removed

### Fixed
8 changes: 4 additions & 4 deletions docs/src/user_interface/decompositions.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,21 +413,21 @@ This preserves the decomposition `A = U * Σ * Vᴴ` while fixing the gauge.
### Disabling Gauge Fixing

Gauge fixing is enabled by default for all eigenvalue and singular value decompositions.
If you prefer to obtain the raw results from the underlying computational routines without gauge fixing, you can disable it using the `gaugefix` keyword argument:
If you prefer to obtain the raw results from the underlying computational routines without gauge fixing, you can disable it using the `fixgauge` keyword argument:

```julia
# With gauge fixing (default)
D, V = eigh_full(A)

# Without gauge fixing
D, V = eigh_full(A; gaugefix = false)
D, V = eigh_full(A; fixgauge = false)
```

The same keyword is available for `eig_full`, `eig_trunc`, `svd_full`, `svd_compact`, and `svd_trunc` functions.
Additionally, the default value can also be controlled with a global toggle using [`MatrixAlgebraKit.default_gaugefix`](@ref).
Additionally, the default value can also be controlled with a global toggle using [`MatrixAlgebraKit.default_fixgauge`](@ref).

```@docs; canonical=false
MatrixAlgebraKit.gaugefix!
MatrixAlgebraKit.default_gaugefix
MatrixAlgebraKit.default_fixgauge
```

6 changes: 3 additions & 3 deletions ext/MatrixAlgebraKitGenericLinearAlgebraExt.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module MatrixAlgebraKitGenericLinearAlgebraExt

using MatrixAlgebraKit
using MatrixAlgebraKit: sign_safe, check_input, diagview, gaugefix!, default_gaugefix
using MatrixAlgebraKit: sign_safe, check_input, diagview, gaugefix!, default_fixgauge
using GenericLinearAlgebra: svd!, svdvals!, eigen!, eigvals!, Hermitian, qr!
using LinearAlgebra: I, Diagonal, lmul!

Expand All @@ -17,7 +17,7 @@ function MatrixAlgebraKit.svd_compact!(A::AbstractMatrix, USVᴴ, alg::GLA_QRIte
F = svd!(A)
U, S, Vᴴ = F.U, Diagonal(F.S), F.Vt

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
do_gauge_fix && gaugefix!(svd_compact!, U, Vᴴ)

return U, S, Vᴴ
Expand All @@ -29,7 +29,7 @@ function MatrixAlgebraKit.svd_full!(A::AbstractMatrix, USVᴴ, alg::GLA_QRIterat
S = MatrixAlgebraKit.zero!(similar(F.S, (size(U, 2), size(Vᴴ, 1))))
diagview(S) .= F.S

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
do_gauge_fix && gaugefix!(svd_full!, U, Vᴴ)

return U, S, Vᴴ
Expand Down
16 changes: 8 additions & 8 deletions src/common/defaults.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ Default tolerance for deciding to warn if the provided `A` is not hermitian.
default_hermitian_tol(A) = eps(norm(A, Inf))^(3 / 4)


const DEFAULT_GAUGEFIX = Ref(true)
const DEFAULT_FIXGAUGE = Ref(true)

@doc """
default_gaugefix() -> current_value
default_gaugefix(new_value::Bool) -> previous_value
default_fixgauge() -> current_value
default_fixgauge(new_value::Bool) -> previous_value

Global toggle for enabling or disabling the default behavior of gauge fixing the output of the eigen- and singular value decompositions.
""" default_gaugefix
""" default_fixgauge

default_gaugefix() = DEFAULT_GAUGEFIX[]
function default_gaugefix(new_value::Bool)
previous_value = DEFAULT_GAUGEFIX[]
DEFAULT_GAUGEFIX[] = new_value
default_fixgauge() = DEFAULT_FIXGAUGE[]
function default_fixgauge(new_value::Bool)
previous_value = DEFAULT_FIXGAUGE[]
DEFAULT_FIXGAUGE[] = new_value
return previous_value
end
12 changes: 6 additions & 6 deletions src/implementations/eig.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ function eig_full!(A::AbstractMatrix, DV, alg::LAPACK_EigAlgorithm)
check_input(eig_full!, A, DV, alg)
D, V = DV

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa LAPACK_Simple
isempty(alg_kwargs) ||
Expand All @@ -102,7 +102,7 @@ function eig_vals!(A::AbstractMatrix, D, alg::LAPACK_EigAlgorithm)
check_input(eig_vals!, A, D, alg)
V = similar(A, complex(eltype(A)), (size(A, 1), 0))

alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa LAPACK_Simple
isempty(alg_kwargs) ||
Expand Down Expand Up @@ -145,8 +145,8 @@ function eig_full!(A::AbstractMatrix, DV, alg::GPU_EigAlgorithm)
check_input(eig_full!, A, DV, alg)
D, V = DV

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa GPU_Simple
isempty(alg_kwargs) || @warn "invalid keyword arguments for GPU_Simple"
Expand All @@ -162,7 +162,7 @@ function eig_vals!(A::AbstractMatrix, D, alg::GPU_EigAlgorithm)
check_input(eig_vals!, A, D, alg)
V = similar(A, complex(eltype(A)), (size(A, 1), 0))

alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa GPU_Simple
isempty(alg_kwargs) || @warn "invalid keyword arguments for GPU_Simple"
Expand Down
12 changes: 6 additions & 6 deletions src/implementations/eigh.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ function eigh_full!(A::AbstractMatrix, DV, alg::LAPACK_EighAlgorithm)
D, V = DV
Dd = D.diag

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa LAPACK_MultipleRelativelyRobustRepresentations
YALAPACK.heevr!(A, Dd, V; alg_kwargs...)
Expand All @@ -114,7 +114,7 @@ function eigh_vals!(A::AbstractMatrix, D, alg::LAPACK_EighAlgorithm)
check_input(eigh_vals!, A, D, alg)
V = similar(A, (size(A, 1), 0))

alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa LAPACK_MultipleRelativelyRobustRepresentations
YALAPACK.heevr!(A, D, V; alg_kwargs...)
Expand Down Expand Up @@ -168,8 +168,8 @@ function eigh_full!(A::AbstractMatrix, DV, alg::GPU_EighAlgorithm)
D, V = DV
Dd = D.diag

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa GPU_Jacobi
_gpu_heevj!(A, Dd, V; alg_kwargs...)
Expand All @@ -192,7 +192,7 @@ function eigh_vals!(A::AbstractMatrix, D, alg::GPU_EighAlgorithm)
check_input(eigh_vals!, A, D, alg)
V = similar(A, (size(A, 1), 0))

alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa GPU_Jacobi
_gpu_heevj!(A, D, V; alg_kwargs...)
Expand Down
6 changes: 3 additions & 3 deletions src/implementations/gen_eig.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ function gen_eig_full!(A::AbstractMatrix, B::AbstractMatrix, WV, alg::LAPACK_Eig
check_input(gen_eig_full!, A, B, WV, alg)
W, V = WV

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa LAPACK_Simple
isempty(alg_kwargs) ||
Expand All @@ -78,7 +78,7 @@ function gen_eig_vals!(A::AbstractMatrix, B::AbstractMatrix, W, alg::LAPACK_EigA
check_input(gen_eig_vals!, A, B, W, alg)
V = similar(A, complex(eltype(A)), (size(A, 1), 0))

alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa LAPACK_Simple
isempty(alg_kwargs) ||
Expand Down
22 changes: 11 additions & 11 deletions src/implementations/svd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ function svd_full!(A::AbstractMatrix, USVᴴ, alg::LAPACK_SVDAlgorithm)
return USVᴴ
end

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa LAPACK_QRIteration
isempty(alg_kwargs) ||
Expand Down Expand Up @@ -153,8 +153,8 @@ function svd_compact!(A::AbstractMatrix, USVᴴ, alg::LAPACK_SVDAlgorithm)
check_input(svd_compact!, A, USVᴴ, alg)
U, S, Vᴴ = USVᴴ

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa LAPACK_QRIteration
isempty(alg_kwargs) ||
Expand Down Expand Up @@ -183,7 +183,7 @@ function svd_vals!(A::AbstractMatrix, S, alg::LAPACK_SVDAlgorithm)
check_input(svd_vals!, A, S, alg)
U, Vᴴ = similar(A, (0, 0)), similar(A, (0, 0))

alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa LAPACK_QRIteration
isempty(alg_kwargs) ||
Expand Down Expand Up @@ -336,8 +336,8 @@ function svd_full!(A::AbstractMatrix, USVᴴ, alg::GPU_SVDAlgorithm)
return USVᴴ
end

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa GPU_QRIteration
isempty(alg_kwargs) || @warn "invalid keyword arguments for GPU_QRIteration"
Expand Down Expand Up @@ -368,7 +368,7 @@ function svd_trunc!(A::AbstractMatrix, USVᴴ, alg::TruncatedAlgorithm{<:GPU_Ran
# normal `truncation_error!` does not work here since `S` is not the full singular value spectrum
ϵ = sqrt(norm(A)^2 - norm(diagview(Str))^2) # is there a more accurate way to do this?

do_gauge_fix = get(alg.alg.kwargs, :gaugefix, default_gaugefix())::Bool
do_gauge_fix = get(alg.alg.kwargs, :fixgauge, default_fixgauge())::Bool
do_gauge_fix && gaugefix!(svd_trunc!, Utr, Vᴴtr)

return Utr, Str, Vᴴtr, ϵ
Expand All @@ -378,8 +378,8 @@ function svd_compact!(A::AbstractMatrix, USVᴴ, alg::GPU_SVDAlgorithm)
check_input(svd_compact!, A, USVᴴ, alg)
U, S, Vᴴ = USVᴴ

do_gauge_fix = get(alg.kwargs, :gaugefix, default_gaugefix())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
do_gauge_fix = get(alg.kwargs, :fixgauge, default_fixgauge())::Bool
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa GPU_QRIteration
isempty(alg_kwargs) || @warn "invalid keyword arguments for GPU_QRIteration"
Expand All @@ -403,7 +403,7 @@ function svd_vals!(A::AbstractMatrix, S, alg::GPU_SVDAlgorithm)
check_input(svd_vals!, A, S, alg)
U, Vᴴ = similar(A, (0, 0)), similar(A, (0, 0))

alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:gaugefix,)})
alg_kwargs = Base.structdiff(alg.kwargs, NamedTuple{(:fixgauge,)})

if alg isa GPU_QRIteration
isempty(alg_kwargs) || @warn "invalid keyword arguments for GPU_QRIteration"
Expand Down
Loading