From 47723f33f438171308f56fe42075213249b3025f Mon Sep 17 00:00:00 2001 From: Lyndon White Date: Tue, 7 Dec 2021 16:01:00 -0600 Subject: [PATCH 1/3] Remove unusued lambda in test file --- test/rulesets/LinearAlgebra/symmetric.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/rulesets/LinearAlgebra/symmetric.jl b/test/rulesets/LinearAlgebra/symmetric.jl index 35e20fa96..ea75a14d2 100644 --- a/test/rulesets/LinearAlgebra/symmetric.jl +++ b/test/rulesets/LinearAlgebra/symmetric.jl @@ -316,7 +316,6 @@ randn(real(T), n) end else - λ = randn(real(T), n) λ = if f === atanh 2 .* rand(real(T), n) .- 1 else From 9bc167ee790028ce6323a125748f3892fe0e61fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller-Widmann?= Date: Mon, 26 Oct 2026 09:00:45 +0100 Subject: [PATCH 2/3] Keep matrix function test inputs in the domain under finite differencing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Draw eigenvalues for acos/asin/atanh from (-0.9, 0.9) and frule tangents with unit spectral norm. Since `_fdm` evaluates at `A + ε * ΔA` with `|ε| ≤ max_range = 1e-2`, Weyl's inequality bounds the eigenvalue shift by 0.01, so inputs stay in the domain for any random draw. Co-Authored-By: Claude Opus 5.5 --- test/rulesets/LinearAlgebra/symmetric.jl | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/test/rulesets/LinearAlgebra/symmetric.jl b/test/rulesets/LinearAlgebra/symmetric.jl index 4a0a6eb3e..ef5d0b2ae 100644 --- a/test/rulesets/LinearAlgebra/symmetric.jl +++ b/test/rulesets/LinearAlgebra/symmetric.jl @@ -283,9 +283,10 @@ using ChainRulesTestUtils: _fdm U = Matrix(qr(randn(T, n, n)).Q) if hermout # f(A) will also be a TA λ = if f in (acos, asin, atanh) - # generate random number between -1 and 0.9. This would be between + # generate random number between -0.9 and 0.9. This would be between # -1 and 1 but we want to avoid domain errors from numerical error - T(1.9) .* rand(real(T), n) .- 1 + # and finite differencing (see `rand_matfun_tangent`) + 1.8 .* rand(real(T), n) .- 0.9 elseif f in (log, sqrt) abs.(randn(real(T), n)) elseif f === acosh @@ -295,7 +296,8 @@ using ChainRulesTestUtils: _fdm end else λ = if f === atanh - 2 .* rand(real(T), n) .- 1 + # see above + 1.8 .* rand(real(T), n) .- 0.9 else randn(real(T), n) end @@ -303,6 +305,14 @@ using ChainRulesTestUtils: _fdm return TA(U * Diagonal(λ) * U', uplo) end + # generate random tangents of type TA with unit spectral norm + # `_fdm` evaluates `f(A + ε * ΔA)` with `|ε| ≤ max_range = 1e-2`, so by Weyl's + # inequality the eigenvalues of `A` move by at most 0.01 and stay in the domain of `f` + function rand_matfun_tangent(TA, T, n, uplo=:U) + ΔA = TA(randn(T, n, n), uplo) + return TA(parent(ΔA) ./ opnorm(ΔA), uplo) + end + # Adapted From ChainRulesTestUtils._is_inferable function is_inferable(f, A) try @@ -325,7 +335,7 @@ using ChainRulesTestUtils: _fdm n = 10 @testset "frule" begin @testset for uplo in (:L, :U), hermout in (true, false) - A, ΔA = rand_matfun_input(f, TA, T, uplo, n, hermout), TA(randn(T, n, n), uplo) + A, ΔA = rand_matfun_input(f, TA, T, uplo, n, hermout), rand_matfun_tangent(TA, T, n, uplo) Y = f(A) if is_inferable(f, A) Y_ad, ∂Y_ad = @maybe_inferred frule((ZeroTangent(), ΔA), f, A) @@ -350,13 +360,13 @@ using ChainRulesTestUtils: _fdm m = div(n, 2) λ[1:m] .= λ[m+1:2m] .+ cbrt(eps(eltype(λ))) / 100 A = TA(U * Diagonal(λ) * U') - ΔA = TA(randn(T, n, n)) + ΔA = rand_matfun_tangent(TA, T, n) _, ∂Y = frule((ZeroTangent(), ΔA), f, A) @test parent(∂Y) ≈ jvp(_fdm, x -> Matrix{TC}(parent(f(TA(x)))), (A.data, ΔA.data)) λ[1:m] .= λ[m+1:2m] A2 = TA(U * Diagonal(λ) * U') - ΔA2 = TA(randn(T, n, n)) + ΔA2 = rand_matfun_tangent(TA, T, n) _, ∂Y2 = frule((ZeroTangent(), ΔA2), f, A2) @test parent(∂Y2) ≈ jvp(_fdm, x -> Matrix{TC}(parent(f(TA(x)))), (A2.data, ΔA2.data)) end @@ -365,7 +375,7 @@ using ChainRulesTestUtils: _fdm λ, U = eigen(rand_matfun_input(f, TA, T, :U, n, true)) λ[2:n] .= 0 A = TA(U * Diagonal(λ) * U') - ΔA = TA(randn(T, n, n)) + ΔA = rand_matfun_tangent(TA, T, n) _, ∂Y = frule((ZeroTangent(), ΔA), f, A) @test parent(∂Y) ≈ jvp(_fdm, x -> Matrix{TC}(parent(f(TA(x)))), (A.data, ΔA.data)) end From d6f43fa3fb77e3e9d5eb9969125e11063abe3477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller-Widmann?= Date: Mon, 26 Oct 2026 09:04:04 +0100 Subject: [PATCH 3/3] Format code Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- test/rulesets/LinearAlgebra/symmetric.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/rulesets/LinearAlgebra/symmetric.jl b/test/rulesets/LinearAlgebra/symmetric.jl index ef5d0b2ae..1292aa1d0 100644 --- a/test/rulesets/LinearAlgebra/symmetric.jl +++ b/test/rulesets/LinearAlgebra/symmetric.jl @@ -335,7 +335,8 @@ using ChainRulesTestUtils: _fdm n = 10 @testset "frule" begin @testset for uplo in (:L, :U), hermout in (true, false) - A, ΔA = rand_matfun_input(f, TA, T, uplo, n, hermout), rand_matfun_tangent(TA, T, n, uplo) + A, ΔA = rand_matfun_input(f, TA, T, uplo, n, hermout), + rand_matfun_tangent(TA, T, n, uplo) Y = f(A) if is_inferable(f, A) Y_ad, ∂Y_ad = @maybe_inferred frule((ZeroTangent(), ΔA), f, A)