From 07248303c52a6f1877e890cb39c24335bf6275bb Mon Sep 17 00:00:00 2001 From: Matt Fishman Date: Wed, 2 Aug 2023 22:27:35 -0400 Subject: [PATCH] [NDTensors] Fix zero for EmptyStorage (#1173) --- NDTensors/src/NDTensors.jl | 2 ++ NDTensors/src/empty/EmptyTensor.jl | 2 +- NDTensors/src/empty/empty.jl | 31 -------------------- NDTensors/src/emptynumber.jl | 30 +++++++++++++++++++ NDTensors/src/nodata.jl | 6 ++++ NDTensors/src/tensorstorage/tensorstorage.jl | 6 ---- NDTensors/test/emptystorage.jl | 6 ++++ test/base/test_emptyitensor.jl | 6 ++++ 8 files changed, 51 insertions(+), 38 deletions(-) create mode 100644 NDTensors/src/emptynumber.jl create mode 100644 NDTensors/src/nodata.jl diff --git a/NDTensors/src/NDTensors.jl b/NDTensors/src/NDTensors.jl index fda640e036..d0ce248a29 100644 --- a/NDTensors/src/NDTensors.jl +++ b/NDTensors/src/NDTensors.jl @@ -44,6 +44,8 @@ include("abstractarray/ndims.jl") include("abstractarray/fill.jl") include("array/set_types.jl") include("tupletools.jl") +include("emptynumber.jl") +include("nodata.jl") include("tensorstorage/tensorstorage.jl") include("tensorstorage/set_types.jl") include("tensorstorage/default_storage.jl") diff --git a/NDTensors/src/empty/EmptyTensor.jl b/NDTensors/src/empty/EmptyTensor.jl index 9afae2dc69..f50cc34738 100644 --- a/NDTensors/src/empty/EmptyTensor.jl +++ b/NDTensors/src/empty/EmptyTensor.jl @@ -55,7 +55,7 @@ end getindex(T::EmptyTensor, I::Integer...) = zero(eltype(T)) function getindex(T::EmptyTensor{Complex{EmptyNumber}}, I::Integer...) - return Complex(NDTensors.EmptyNumber(), NDTensors.EmptyNumber()) + return Complex(EmptyNumber(), EmptyNumber()) end similar(T::EmptyTensor, inds::Tuple) = setinds(T, inds) diff --git a/NDTensors/src/empty/empty.jl b/NDTensors/src/empty/empty.jl index 92074e8a08..437d0d62ad 100644 --- a/NDTensors/src/empty/empty.jl +++ b/NDTensors/src/empty/empty.jl @@ -5,37 +5,6 @@ struct EmptyOrder end -# -# Represents a number that can be set to any type. -# - -struct EmptyNumber <: Real end - -zero(::Type{EmptyNumber}) = EmptyNumber() -zero(n::EmptyNumber) = zero(typeof(n)) - -# This helps handle a lot of basic algebra, like: -# EmptyNumber() + 2.3 == 2.3 -convert(::Type{T}, x::EmptyNumber) where {T<:Number} = T(zero(T)) - -# TODO: Should this be implemented? -#Complex(x::Real, ::EmptyNumber) = x - -# This is to help define `float(::EmptyNumber) = 0.0`. -# This helps with defining `norm` of `EmptyStorage{EmptyNumber}`. -AbstractFloat(::NDTensors.EmptyNumber) = zero(AbstractFloat) - -# Basic arithmetic -(::EmptyNumber + ::EmptyNumber) = EmptyNumber() -(::EmptyNumber - ::EmptyNumber) = EmptyNumber() -(::Number * ::EmptyNumber) = EmptyNumber() -(::EmptyNumber * ::Number) = EmptyNumber() -(::EmptyNumber * ::EmptyNumber) = EmptyNumber() -(::EmptyNumber / ::Number) = EmptyNumber() -(::Number / ::EmptyNumber) = throw(DivideError()) -(::EmptyNumber / ::EmptyNumber) = throw(DivideError()) --(::EmptyNumber) = EmptyNumber() - function similartype(StoreT::Type{<:TensorStorage{EmptyNumber}}, ElT::Type) return set_eltype(StoreT, ElT) end diff --git a/NDTensors/src/emptynumber.jl b/NDTensors/src/emptynumber.jl new file mode 100644 index 0000000000..d84abb52ca --- /dev/null +++ b/NDTensors/src/emptynumber.jl @@ -0,0 +1,30 @@ +# +# Represents a number that can be set to any type. +# + +struct EmptyNumber <: Real end + +zero(::Type{EmptyNumber}) = EmptyNumber() +zero(n::EmptyNumber) = zero(typeof(n)) + +# This helps handle a lot of basic algebra, like: +# EmptyNumber() + 2.3 == 2.3 +convert(::Type{T}, x::EmptyNumber) where {T<:Number} = T(zero(T)) + +# TODO: Should this be implemented? +#Complex(x::Real, ::EmptyNumber) = x + +# This is to help define `float(::EmptyNumber) = 0.0`. +# This helps with defining `norm` of `EmptyStorage{EmptyNumber}`. +AbstractFloat(::EmptyNumber) = zero(AbstractFloat) + +# Basic arithmetic +(::EmptyNumber + ::EmptyNumber) = EmptyNumber() +(::EmptyNumber - ::EmptyNumber) = EmptyNumber() +(::Number * ::EmptyNumber) = EmptyNumber() +(::EmptyNumber * ::Number) = EmptyNumber() +(::EmptyNumber * ::EmptyNumber) = EmptyNumber() +(::EmptyNumber / ::Number) = EmptyNumber() +(::Number / ::EmptyNumber) = throw(DivideError()) +(::EmptyNumber / ::EmptyNumber) = throw(DivideError()) +-(::EmptyNumber) = EmptyNumber() diff --git a/NDTensors/src/nodata.jl b/NDTensors/src/nodata.jl new file mode 100644 index 0000000000..324fdf8811 --- /dev/null +++ b/NDTensors/src/nodata.jl @@ -0,0 +1,6 @@ +# Denotes when a storage type has no data +struct NoData end + +size(::NoData) = (0,) +length(::NoData) = 0 +fill!(::NoData, ::EmptyNumber) = NoData() diff --git a/NDTensors/src/tensorstorage/tensorstorage.jl b/NDTensors/src/tensorstorage/tensorstorage.jl index 0c1a992115..0c9ddac70e 100644 --- a/NDTensors/src/tensorstorage/tensorstorage.jl +++ b/NDTensors/src/tensorstorage/tensorstorage.jl @@ -1,11 +1,5 @@ abstract type TensorStorage{ElT} <: AbstractVector{ElT} end -# Denotes when a storage type has no data -struct NoData end - -size(::NoData) = (0,) -length(::NoData) = 0 - data(S::TensorStorage) = S.data datatype(::Type{<:TensorStorage}) = error("Not implemented") diff --git a/NDTensors/test/emptystorage.jl b/NDTensors/test/emptystorage.jl index bf6aaf6e55..0bb37b7c1c 100644 --- a/NDTensors/test/emptystorage.jl +++ b/NDTensors/test/emptystorage.jl @@ -23,5 +23,11 @@ using Test @test blockoffsets(T) == BlockOffsets{2}() T = dev(EmptyBlockSparseTensor(Float64, ([1, 1], [1, 1]))) @test blockoffsets(T) == BlockOffsets{2}() + + T = dev(EmptyStorage(NDTensors.EmptyNumber)) + @test zero(T) isa typeof(T) + + T = dev(EmptyTensor(NDTensors.EmptyNumber, (2, 2))) + @test zero(T) isa typeof(T) end end diff --git a/test/base/test_emptyitensor.jl b/test/base/test_emptyitensor.jl index ff68b21d86..1cccd3fced 100644 --- a/test/base/test_emptyitensor.jl +++ b/test/base/test_emptyitensor.jl @@ -94,4 +94,10 @@ end @test blockoffsets(A) == NDTensors.BlockOffsets{2}() end +@testset "zero" for space in (2, [QN(0) => 1, QN(1) => 1]) + i = Index(space) + A = ITensor(i', dag(i)) + @test NDTensors.tensor(zero(A)) isa typeof(NDTensors.tensor(A)) +end + nothing