From 21744b9777e429ef1f22056a9d0676c74a92a604 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 19 Oct 2026 10:39:28 -0400 Subject: [PATCH 1/5] Specialize norm(t, Inf) a bit so we can use it on GPU backed TensorMaps --- src/tensors/linalg.jl | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/tensors/linalg.jl b/src/tensors/linalg.jl index 16d595ba7..c83471027 100644 --- a/src/tensors/linalg.jl +++ b/src/tensors/linalg.jl @@ -256,7 +256,13 @@ LinearAlgebra.dot(t1::AbstractTensorMap, t2::AbstractTensorMap) = inner(t1, t2) function LinearAlgebra.norm(t::AbstractTensorMap, p::Real = 2) InnerProductStyle(t) === EuclideanInnerProduct() || throw_invalid_innerproduct(:norm) - return _norm(blocks(t), p, float(zero(real(scalartype(t))))) + init = float(zero(real(scalartype(t)))) + if p == Inf + # can bypass the block iterator for the Inf case + return maximum(abs, t.data; init) + else + return _norm(blocks(t), p, init) + end end function _norm(blockiter, p::Real, init::Number) if p == Inf @@ -276,9 +282,13 @@ function _norm(blockiter, p::Real, init::Number) end function LinearAlgebra.norm(t::TensorMap, p::Real = 2) InnerProductStyle(t) === EuclideanInnerProduct() || throw_invalid_innerproduct(:norm) + init = float(zero(real(scalartype(t)))) # performance specialization: - FusionStyle(sectortype(t)) isa UniqueFusion && return norm(t.data, p) - return _norm(blocks(t), p, float(zero(real(scalartype(t))))) + if FusionStyle(sectortype(t)) isa UniqueFusion + return p == Inf ? maximum(abs, t.data; init) : norm(t.data, p) + else + return _norm(blocks(t), p, init) + end end _default_rtol(t) = eps(real(float(scalartype(t)))) * min(dim(domain(t)), dim(codomain(t))) From ae8f35020ccc23846ea677672fa991f0ee4558fa Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 19 Oct 2026 10:53:50 -0400 Subject: [PATCH 2/5] Formatter --- src/tensors/linalg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tensors/linalg.jl b/src/tensors/linalg.jl index c83471027..7ba92ed7f 100644 --- a/src/tensors/linalg.jl +++ b/src/tensors/linalg.jl @@ -258,7 +258,7 @@ function LinearAlgebra.norm(t::AbstractTensorMap, p::Real = 2) InnerProductStyle(t) === EuclideanInnerProduct() || throw_invalid_innerproduct(:norm) init = float(zero(real(scalartype(t)))) if p == Inf - # can bypass the block iterator for the Inf case + # can bypass the block iterator for the Inf case return maximum(abs, t.data; init) else return _norm(blocks(t), p, init) From 955ac91adb7dfa1314f637bdf06203358cd98170 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 20 Oct 2026 01:17:27 -0400 Subject: [PATCH 3/5] Specialize for Adjoint and Diagonal instead --- src/tensors/adjoint.jl | 6 ++++++ src/tensors/diagonal.jl | 6 ++++++ src/tensors/linalg.jl | 7 +------ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/tensors/adjoint.jl b/src/tensors/adjoint.jl index 6aa5810e4..6138d7fbc 100644 --- a/src/tensors/adjoint.jl +++ b/src/tensors/adjoint.jl @@ -53,6 +53,12 @@ end Adapt.adapt_structure(to, x::AdjointTensorMap) = adjoint(Adapt.adapt(to, parent(x))) +function LinearAlgebra.norm(t::AdjointTensorMap, p::Real = 2) + InnerProductStyle(t) === EuclideanInnerProduct() || throw_invalid_innerproduct(:norm) + p == Inf && return norm(parent(t), p) + return _norm(blocks(t), p, float(zero(real(scalartype(t))))) +end + # Show #------ function Base.showarg(io::IO, t::AdjointTensorMap, toplevel::Bool) diff --git a/src/tensors/diagonal.jl b/src/tensors/diagonal.jl index be0290b24..630f1866a 100644 --- a/src/tensors/diagonal.jl +++ b/src/tensors/diagonal.jl @@ -375,6 +375,12 @@ end function LinearAlgebra.isposdef(d::DiagonalTensorMap) return all(isposdef, d.data) end +function LinearAlgebra.norm(t::DiagonalTensorMap, p::Real = 2) + InnerProductStyle(t) === EuclideanInnerProduct() || throw_invalid_innerproduct(:norm) + init = float(zero(real(scalartype(t)))) + p == Inf && return maximum(abs, t.data; init) + return _norm(blocks(t), p, init) +end # matrix functions for f in diff --git a/src/tensors/linalg.jl b/src/tensors/linalg.jl index 7ba92ed7f..f848fb175 100644 --- a/src/tensors/linalg.jl +++ b/src/tensors/linalg.jl @@ -257,12 +257,7 @@ LinearAlgebra.dot(t1::AbstractTensorMap, t2::AbstractTensorMap) = inner(t1, t2) function LinearAlgebra.norm(t::AbstractTensorMap, p::Real = 2) InnerProductStyle(t) === EuclideanInnerProduct() || throw_invalid_innerproduct(:norm) init = float(zero(real(scalartype(t)))) - if p == Inf - # can bypass the block iterator for the Inf case - return maximum(abs, t.data; init) - else - return _norm(blocks(t), p, init) - end + return _norm(blocks(t), p, init) end function _norm(blockiter, p::Real, init::Number) if p == Inf From 879652e4a94dc24859164a524b39081f7bec2609 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 21 Oct 2026 07:03:42 +0200 Subject: [PATCH 4/5] Respond to comments --- src/tensors/adjoint.jl | 6 +----- src/tensors/linalg.jl | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/tensors/adjoint.jl b/src/tensors/adjoint.jl index 6138d7fbc..2297643ce 100644 --- a/src/tensors/adjoint.jl +++ b/src/tensors/adjoint.jl @@ -53,11 +53,7 @@ end Adapt.adapt_structure(to, x::AdjointTensorMap) = adjoint(Adapt.adapt(to, parent(x))) -function LinearAlgebra.norm(t::AdjointTensorMap, p::Real = 2) - InnerProductStyle(t) === EuclideanInnerProduct() || throw_invalid_innerproduct(:norm) - p == Inf && return norm(parent(t), p) - return _norm(blocks(t), p, float(zero(real(scalartype(t))))) -end +LinearAlgebra.norm(t::AdjointTensorMap, p::Real = 2) = norm(parent(t), p) # Show #------ diff --git a/src/tensors/linalg.jl b/src/tensors/linalg.jl index f848fb175..b7c4020ad 100644 --- a/src/tensors/linalg.jl +++ b/src/tensors/linalg.jl @@ -262,7 +262,7 @@ end function _norm(blockiter, p::Real, init::Number) if p == Inf return mapreduce(max, blockiter; init = init) do (c, b) - return isempty(b) ? init : oftype(init, LinearAlgebra.normInf(b)) + return maximum(abs, b; init) end elseif p > 0 # finite positive p np = init From f9d03617e7d6537253e3b8d6d54762a159060b4c Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 21 Oct 2026 07:40:54 +0200 Subject: [PATCH 5/5] Help inference --- src/tensors/linalg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tensors/linalg.jl b/src/tensors/linalg.jl index b7c4020ad..549595596 100644 --- a/src/tensors/linalg.jl +++ b/src/tensors/linalg.jl @@ -262,7 +262,7 @@ end function _norm(blockiter, p::Real, init::Number) if p == Inf return mapreduce(max, blockiter; init = init) do (c, b) - return maximum(abs, b; init) + return oftype(init, maximum(abs, b; init)) end elseif p > 0 # finite positive p np = init