From 9d13d35f0afc7409873d77f6ba734e8cb0369ddc Mon Sep 17 00:00:00 2001 From: Jutho Date: Mon, 11 Nov 2024 00:47:39 +0100 Subject: [PATCH 1/2] small patch to complex, real and imag --- src/tensors/tensor.jl | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/tensors/tensor.jl b/src/tensors/tensor.jl index f476f349a..dd5d72104 100644 --- a/src/tensors/tensor.jl +++ b/src/tensors/tensor.jl @@ -389,7 +389,7 @@ function Base.complex(t::AbstractTensorMap) if scalartype(t) <: Complex return t else - return copy!(similar(t, complex(scalartype(t))), t) + return TensorMap(complex(t.data), space(t)) end end function Base.complex(r::AbstractTensorMap{<:Real}, i::AbstractTensorMap{<:Real}) @@ -581,27 +581,19 @@ end # Real and imaginary parts #--------------------------- function Base.real(t::AbstractTensorMap) - # `isreal` for a `Sector` returns true iff the F and R symbols are real. This guarantees - # that the real/imaginary part of a tensor `t` can be obtained by just taking - # real/imaginary part of the degeneracy data. - if isreal(sectortype(t)) - return TensorMap(real(t.data), codomain(t), domain(t)) - else - msg = "`real` has not been implemented for `$(typeof(t))`." - throw(ArgumentError(msg)) - end + # TODO: should we reformulate the old checks in terms of `sectorscalartype` + # For anyonic categories, complex numbers typically come into play only in the + # braiding and not in the fusion. Hence, it can make sense to work with real + # tensors if no braiding is required. + return TensorMap(real(t.data), codomain(t), domain(t)) end function Base.imag(t::AbstractTensorMap) - # `isreal` for a `Sector` returns true iff the F and R symbols are real. This guarantees - # that the real/imaginary part of a tensor `t` can be obtained by just taking - # real/imaginary part of the degeneracy data. - if isreal(sectortype(t)) - return TensorMap(imag(t.data), codomain(t), domain(t)) - else - msg = "`imag` has not been implemented for `$(typeof(t))`." - throw(ArgumentError(msg)) - end + # TODO: should we reformulate the old checks in terms of `sectorscalartype`? + # For anyonic categories, complex numbers typically come into play only in the + # braiding and not in the fusion. Hence, it can make sense to work with real + # tensors if no braiding is required. + return TensorMap(imag(t.data), codomain(t), domain(t)) end # Conversion and promotion: From 641c603f28b6f9a68521a1544f83eee9fd6d943a Mon Sep 17 00:00:00 2001 From: Jutho Date: Mon, 11 Nov 2024 13:42:15 +0100 Subject: [PATCH 2/2] better patches to complex, real and imag --- src/tensors/abstracttensor.jl | 36 ++++++++++++++++++++++++++++++++ src/tensors/tensor.jl | 39 +++++++++++------------------------ 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/tensors/abstracttensor.jl b/src/tensors/abstracttensor.jl index 2e9c0f074..ebc1788fc 100644 --- a/src/tensors/abstracttensor.jl +++ b/src/tensors/abstracttensor.jl @@ -451,6 +451,42 @@ function Base.isapprox(t1::AbstractTensorMap, t2::AbstractTensorMap; end end +# Complex, real and imaginary +#---------------------------- +function Base.complex(t::AbstractTensorMap) + if scalartype(t) <: Complex + return t + else + return copy!(similar(t, complex(scalartype(t))), t) + end +end +function Base.complex(r::AbstractTensorMap{<:Real}, i::AbstractTensorMap{<:Real}) + return add(r, i, im * one(scalartype(i))) +end + +function Base.real(t::AbstractTensorMap) + if scalartype(t) <: Real + return t + else + tr = similar(t, real(scalartype(t))) + for (c, b) in blocks(t) + block(tr, c) .= real(b) + end + return tr + end +end +function Base.imag(t::AbstractTensorMap) + if scalartype(t) <: Real + return zerovector(t) + else + ti = similar(t, real(scalartype(t))) + for (c, b) in blocks(t) + block(ti, c) .= imag(b) + end + return ti + end +end + # Conversion to Array: #---------------------- # probably not optimized for speed, only for checking purposes diff --git a/src/tensors/tensor.jl b/src/tensors/tensor.jl index dd5d72104..90596086f 100644 --- a/src/tensors/tensor.jl +++ b/src/tensors/tensor.jl @@ -27,6 +27,10 @@ struct TensorMap{T,S<:IndexSpace,N₁,N₂,A<:DenseVector{T}} <: AbstractTensorM N₁,N₂, A<:DenseVector{T}} T ⊆ field(S) || @warn("scalartype(data) = $T ⊈ $(field(S)))", maxlog = 1) + I = sectortype(S) + T <: Real && !(sectorscalartype(I) <: Real) && + @warn("Tensors with real data might be incompatible with sector type $I", + maxlog = 1) return new{T,S,N₁,N₂,A}(data, space) end end @@ -385,17 +389,6 @@ end #----------------------------- Base.copy(t::TensorMap) = typeof(t)(copy(t.data), t.space) -function Base.complex(t::AbstractTensorMap) - if scalartype(t) <: Complex - return t - else - return TensorMap(complex(t.data), space(t)) - end -end -function Base.complex(r::AbstractTensorMap{<:Real}, i::AbstractTensorMap{<:Real}) - return add(r, i, im * one(scalartype(i))) -end - # Conversion between TensorMap and Dict, for read and write purpose #------------------------------------------------------------------ function Base.convert(::Type{Dict}, t::AbstractTensorMap) @@ -578,22 +571,14 @@ function Base.show(io::IO, t::TensorMap) end end -# Real and imaginary parts -#--------------------------- -function Base.real(t::AbstractTensorMap) - # TODO: should we reformulate the old checks in terms of `sectorscalartype` - # For anyonic categories, complex numbers typically come into play only in the - # braiding and not in the fusion. Hence, it can make sense to work with real - # tensors if no braiding is required. - return TensorMap(real(t.data), codomain(t), domain(t)) -end - -function Base.imag(t::AbstractTensorMap) - # TODO: should we reformulate the old checks in terms of `sectorscalartype`? - # For anyonic categories, complex numbers typically come into play only in the - # braiding and not in the fusion. Hence, it can make sense to work with real - # tensors if no braiding is required. - return TensorMap(imag(t.data), codomain(t), domain(t)) +# Complex, real and imaginary parts +#----------------------------------- +for f in (:real, :imag, :complex) + @eval begin + function Base.$f(t::TensorMap) + return TensorMap($f(t.data), space(t)) + end + end end # Conversion and promotion: