From 2527bf223da4a5440cae818e2e0da48b2e916333 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Fri, 9 Aug 2024 16:28:26 +0100 Subject: [PATCH 1/2] Fix #133 Support sortby --- .github/workflows/ci.yml | 59 +++++++++++++++++++++------------------- Project.toml | 2 +- src/eigenSelfAdjoint.jl | 38 +++++++++++++------------- test/eigenselfadjoint.jl | 10 ++++++- 4 files changed, 60 insertions(+), 49 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed99e8e..e2124e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,56 +1,59 @@ name: CI -env: - JULIA_NUM_THREADS: 2 on: - pull_request: push: branches: - master - tags: '*' - merge_group: + tags: [v*] + paths-ignore: + - 'LICENSE' + - 'README.md' + - '.github/workflows/TagBot.yml' + pull_request: + paths-ignore: + - 'LICENSE' + - 'README.md' + - '.github/workflows/TagBot.yml' + + +concurrency: + group: build-${{ github.event.pull_request.number || github.ref }}-${{ github.workflow }} + cancel-in-progress: true + jobs: - finalize: - timeout-minutes: 10 - needs: [test] - if: always() + pre_job: + # continue-on-error: true # Uncomment once integration is finished runs-on: ubuntu-latest + # Map a step output to a job output + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: - - run: | - echo test: ${{ needs.test.result }} - - run: exit 1 - if: | - (needs.test.result != 'success') + - id: skip_check + uses: fkirc/skip-duplicate-actions@v5 test: + needs: pre_job + if: needs.pre_job.outputs.should_skip != 'true' name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: version: - - 'nightly' + - 'lts' - '1' + - 'nightly' os: - ubuntu-latest -# - macos-latest -# - windows-latest + - macOS-latest + - windows-latest arch: - x64 steps: - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v1 + - uses: julia-actions/setup-julia@v2.2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: actions/cache@v4 - env: - cache-name: cache-artifacts - with: - path: ~/.julia/artifacts - key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} - restore-keys: | - ${{ runner.os }}-test-${{ env.cache-name }}- - ${{ runner.os }}-test- - ${{ runner.os }}- + - uses: julia-actions/cache@v2 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 diff --git a/Project.toml b/Project.toml index 6a42cf0..1efa285 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "GenericLinearAlgebra" uuid = "14197337-ba66-59df-a3e3-ca00e7dcff7a" -version = "0.3.11" +version = "0.3.12" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/src/eigenSelfAdjoint.jl b/src/eigenSelfAdjoint.jl index c0b6a2a..d8008d3 100644 --- a/src/eigenSelfAdjoint.jl +++ b/src/eigenSelfAdjoint.jl @@ -162,7 +162,7 @@ function eig2x2!(d::StridedVector, e::StridedVector, j::Integer, vectors::Matrix return c, s end -function eigvalsPWK!(S::SymTridiagonal{T}; tol = eps(T)) where {T<:Real} +function eigvalsPWK!(S::SymTridiagonal{T}; tol = eps(T), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) where {T<:Real} d = S.dv e = S.ev n = length(d) @@ -216,7 +216,7 @@ function eigvalsPWK!(S::SymTridiagonal{T}; tol = eps(T)) where {T<:Real} end end end - sort!(d) + LinearAlgebra.sorteig!(d, sortby) end function eigQL!( @@ -570,39 +570,39 @@ function symtriUpper!( end -_eigvals!(A::SymmetricTridiagonalFactorization; tol = eps(real(eltype(A)))) = - eigvalsPWK!(A.diagonals, tol = tol) +_eigvals!(A::SymmetricTridiagonalFactorization; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = + eigvalsPWK!(A.diagonals; tol, sortby) -_eigvals!(A::SymTridiagonal; tol = eps(real(eltype(A)))) = eigvalsPWK!(A, tol = tol) +_eigvals!(A::SymTridiagonal; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = eigvalsPWK!(A; tol, sortby) -_eigvals!(A::Hermitian; tol = eps(real(eltype(A)))) = eigvals!(symtri!(A), tol = tol) +_eigvals!(A::Hermitian; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = eigvals!(symtri!(A); tol, sortby) -LinearAlgebra.eigvals!(A::SymmetricTridiagonalFactorization; tol = eps(real(eltype(A)))) = - _eigvals!(A, tol = tol) +LinearAlgebra.eigvals!(A::SymmetricTridiagonalFactorization; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = + _eigvals!(A; tol, sortby) -LinearAlgebra.eigvals!(A::SymTridiagonal; tol = eps(real(eltype(A)))) = - _eigvals!(A, tol = tol) +LinearAlgebra.eigvals!(A::SymTridiagonal; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = + _eigvals!(A; tol, sortby) -LinearAlgebra.eigvals!(A::Hermitian; tol = eps(real(eltype(A)))) = _eigvals!(A, tol = tol) +LinearAlgebra.eigvals!(A::Hermitian; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = _eigvals!(A; tol, sortby) -_eigen!(A::SymmetricTridiagonalFactorization; tol = eps(real(eltype(A)))) = - LinearAlgebra.Eigen(eigQL!(A.diagonals, vectors = Array(A.Q), tol = tol)...) +_eigen!(A::SymmetricTridiagonalFactorization; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = + LinearAlgebra.Eigen(LinearAlgebra.sorteig!(eigQL!(A.diagonals, vectors = Array(A.Q), tol = tol)..., sortby)...) -_eigen!(A::SymTridiagonal; tol = eps(real(eltype(A)))) = LinearAlgebra.Eigen( +_eigen!(A::SymTridiagonal; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = LinearAlgebra.Eigen( eigQL!(A, vectors = Matrix{eltype(A)}(I, size(A, 1), size(A, 1)), tol = tol)..., ) -_eigen!(A::Hermitian; tol = eps(real(eltype(A)))) = _eigen!(symtri!(A), tol = tol) +_eigen!(A::Hermitian; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = _eigen!(symtri!(A), tol = tol) -LinearAlgebra.eigen!(A::SymmetricTridiagonalFactorization; tol = eps(real(eltype(A)))) = - _eigen!(A, tol = tol) +LinearAlgebra.eigen!(A::SymmetricTridiagonalFactorization; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = + _eigen!(A; tol, sortby) -LinearAlgebra.eigen!(A::SymTridiagonal; tol = eps(real(eltype(A)))) = _eigen!(A, tol = tol) +LinearAlgebra.eigen!(A::SymTridiagonal; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = _eigen!(A; tol, sortby) -LinearAlgebra.eigen!(A::Hermitian; tol = eps(real(eltype(A)))) = _eigen!(A, tol = tol) +LinearAlgebra.eigen!(A::Hermitian; tol = eps(real(eltype(A))), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) = _eigen!(A; tol, sortby) function eigen2!( diff --git a/test/eigenselfadjoint.jl b/test/eigenselfadjoint.jl index a5a7508..8f097d9 100644 --- a/test/eigenselfadjoint.jl +++ b/test/eigenselfadjoint.jl @@ -1,5 +1,4 @@ using Test, GenericLinearAlgebra, LinearAlgebra, Quaternions -Base.isreal(q::Quaternion) = q.v1 == q.v2 == q.v3 == 0 @testset "The selfadjoint eigen problem" begin n = 50 @@ -157,4 +156,13 @@ Base.isreal(q::Quaternion) = q.v1 == q.v2 == q.v3 == 0 @test hypot(c, s) ≈ 1 end end + + @testset "#133" begin + A = SymTridiagonal{BigFloat}(randn(5), randn(4)) + T = Tridiagonal(A) + @test eigvals(A) == eigvals(T) == eigvals(A; sortby=LinearAlgebra.eigsortby) == eigvals(T; sortby=LinearAlgebra.eigsortby) == eigvals!(deepcopy(A); sortby=LinearAlgebra.eigsortby) + @test eigen(A).values == eigen(T).values == eigen(A; sortby=LinearAlgebra.eigsortby).values == eigen(T; sortby=LinearAlgebra.eigsortby).values + # compare abs to avoid sign issues + @test abs.(eigen(A).vectors) == abs.(eigen(T).vectors) == abs.(eigen(A; sortby=LinearAlgebra.eigsortby).vectors) == abs.(eigen(T; sortby=LinearAlgebra.eigsortby).vectors) + end end From da5462c51c59d18e63151ba1f1476e8774d3ac6c Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sat, 10 Aug 2024 08:40:00 +0100 Subject: [PATCH 2/2] restore CI --- .github/workflows/ci.yml | 59 +++++++++++++++++++--------------------- .gitignore | 2 +- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e2124e6..ed99e8e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,59 +1,56 @@ name: CI +env: + JULIA_NUM_THREADS: 2 on: + pull_request: push: branches: - master - tags: [v*] - paths-ignore: - - 'LICENSE' - - 'README.md' - - '.github/workflows/TagBot.yml' - pull_request: - paths-ignore: - - 'LICENSE' - - 'README.md' - - '.github/workflows/TagBot.yml' - - -concurrency: - group: build-${{ github.event.pull_request.number || github.ref }}-${{ github.workflow }} - cancel-in-progress: true - + tags: '*' + merge_group: jobs: - pre_job: - # continue-on-error: true # Uncomment once integration is finished + finalize: + timeout-minutes: 10 + needs: [test] + if: always() runs-on: ubuntu-latest - # Map a step output to a job output - outputs: - should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: - - id: skip_check - uses: fkirc/skip-duplicate-actions@v5 + - run: | + echo test: ${{ needs.test.result }} + - run: exit 1 + if: | + (needs.test.result != 'success') test: - needs: pre_job - if: needs.pre_job.outputs.should_skip != 'true' name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: version: - - 'lts' - - '1' - 'nightly' + - '1' os: - ubuntu-latest - - macOS-latest - - windows-latest +# - macos-latest +# - windows-latest arch: - x64 steps: - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v2.2 + - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: julia-actions/cache@v2 + - uses: actions/cache@v4 + env: + cache-name: cache-artifacts + with: + path: ~/.julia/artifacts + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} + restore-keys: | + ${{ runner.os }}-test-${{ env.cache-name }}- + ${{ runner.os }}-test- + ${{ runner.os }}- - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 diff --git a/.gitignore b/.gitignore index c10b7b2..1699e29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ Manifest.toml docs/build/ -.github/.DS_Store +.DS_Store