Skip to content

Commit 8e3af86

Browse files
authored
Rewrite special-purpose constructors to use in-place operations (#232)
* Rewrite special-purpose constructors in terms of in-place operations * Fix error messages
1 parent daf2f53 commit 8e3af86

File tree

2 files changed

+39
-23
lines changed

2 files changed

+39
-23
lines changed

src/TensorKit.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ export blocksectors, blockdim, block, blocks
6161
export randisometry, randisometry!, rand, rand!, randn, randn!
6262

6363
# special purpose constructors
64-
export zero, one, one!, id, isomorphism, unitary, isometry
64+
export zero, one, one!, id, id!, isomorphism, isomorphism!, unitary, unitary!, isometry,
65+
isometry!
6566

6667
# reexport most of VectorInterface and some more tensor algebra
6768
export zerovector, zerovector!, zerovector!!, scale, scale!, scale!!, add, add!, add!!

src/tensors/linalg.jl

+37-22
Original file line numberDiff line numberDiff line change
@@ -64,24 +64,31 @@ function one!(t::AbstractTensorMap)
6464
return t
6565
end
6666

67-
"""
67+
@doc """
6868
id([T::Type=Float64,] V::TensorSpace) -> TensorMap
69+
id!(t::AbstractTensorMap) -> AbstractTensorMap
6970
7071
Construct the identity endomorphism on space `V`, i.e. return a `t::TensorMap` with
7172
`domain(t) == codomain(t) == V`, where either `scalartype(t) = T` if `T` is a `Number` type
7273
or `storagetype(t) = T` if `T` is a `DenseVector` type.
73-
"""
74+
75+
See also [`one!`](@ref).
76+
""" id, id!
77+
7478
id(V::TensorSpace) = id(Float64, V)
7579
function id(A::Type, V::TensorSpace{S}) where {S}
7680
W = V V
7781
N = length(codomain(W))
78-
return one!(tensormaptype(S, N, N, A)(undef, W))
82+
dst = tensormaptype(S, N, N, A)(undef, W)
83+
return id!(dst)
7984
end
85+
const id! = one!
8086

81-
"""
87+
@doc """
8288
isomorphism([T::Type=Float64,] codomain::TensorSpace, domain::TensorSpace) -> TensorMap
8389
isomorphism([T::Type=Float64,] codomain ← domain) -> TensorMap
8490
isomorphism([T::Type=Float64,] domain → codomain) -> TensorMap
91+
isomorphism!(t::AbstractTensorMap) -> AbstractTensorMap
8592
8693
Construct a specific isomorphism between the codomain and the domain, i.e. return a
8794
`t::TensorMap` where either `scalartype(t) = T` if `T` is a `Number` type or
@@ -93,21 +100,22 @@ error will be thrown.
93100
that `isomorphism(cod, dom) == inv(isomorphism(dom, cod))`.
94101
95102
See also [`unitary`](@ref) when `InnerProductStyle(cod) === EuclideanInnerProduct()`.
96-
"""
97-
function isomorphism(A::Type, V::TensorMapSpace{S,N₁,N₂}) where {S,N₁,N₂}
98-
codomain(V) domain(V) ||
99-
throw(SpaceMismatch("codomain and domain are not isomorphic: $V"))
100-
t = tensormaptype(S, N₁, N₂, A)(undef, V)
103+
""" isomorphism, isomorphism!
104+
105+
function isomorphism!(t::AbstractTensorMap)
106+
domain(t) codomain(t) ||
107+
throw(SpaceMismatch(lazy"domain and codomain are not isomorphic: $(space(t))"))
101108
for (_, b) in blocks(t)
102109
MatrixAlgebra.one!(b)
103110
end
104111
return t
105112
end
106113

107-
"""
114+
@doc """
108115
unitary([T::Type=Float64,] codomain::TensorSpace, domain::TensorSpace) -> TensorMap
109116
unitary([T::Type=Float64,] codomain ← domain) -> TensorMap
110117
unitary([T::Type=Float64,] domain → codomain) -> TensorMap
118+
unitary!(t::AbstractTensorMap) -> AbstractTensorMap
111119
112120
Construct a specific unitary morphism between the codomain and the domain, i.e. return a
113121
`t::TensorMap` where either `scalartype(t) = T` if `T` is a `Number` type or
@@ -119,16 +127,18 @@ the spacetype does not have a Euclidean inner product, an error will be thrown.
119127
`unitary(cod, dom) == inv(unitary(dom, cod)) = adjoint(unitary(dom, cod))`.
120128
121129
See also [`isomorphism`](@ref) and [`isometry`](@ref).
122-
"""
123-
function unitary(A::Type, V::TensorMapSpace{S,N₁,N₂}) where {S,N₁,N₂}
124-
InnerProductStyle(S) === EuclideanInnerProduct() || throw_invalid_innerproduct(:unitary)
125-
return isomorphism(A, V)
130+
""" unitary, unitary!
131+
132+
function unitary!(t::AbstractTensorMap)
133+
InnerProductStyle(t) === EuclideanInnerProduct() || throw_invalid_innerproduct(:unitary)
134+
return isomorphism!(t)
126135
end
127136

128-
"""
137+
@doc """
129138
isometry([T::Type=Float64,] codomain::TensorSpace, domain::TensorSpace) -> TensorMap
130139
isometry([T::Type=Float64,] codomain ← domain) -> TensorMap
131140
isometry([T::Type=Float64,] domain → codomain) -> TensorMap
141+
isometry!(t::AbstractTensorMap) -> AbstractTensorMap
132142
133143
Construct a specific isometry between the codomain and the domain, i.e. return a
134144
`t::TensorMap` where either `scalartype(t) = T` if `T` is a `Number` type or
@@ -137,13 +147,13 @@ Construct a specific isometry between the codomain and the domain, i.e. return a
137147
isometric inclusion, an error will be thrown.
138148
139149
See also [`isomorphism`](@ref) and [`unitary`](@ref).
140-
"""
141-
function isometry(A::Type, V::TensorMapSpace{S,N₁,N₂}) where {S,N₁,N₂}
142-
InnerProductStyle(S) === EuclideanInnerProduct() ||
150+
""" isometry, isometry!
151+
152+
function isometry!(t::AbstractTensorMap)
153+
InnerProductStyle(t) === EuclideanInnerProduct() ||
143154
throw_invalid_innerproduct(:isometry)
144-
domain(V) codomain(V) ||
145-
throw(SpaceMismatch("$V does not allow for an isometric inclusion"))
146-
t = tensormaptype(S, N₁, N₂, A)(undef, V)
155+
domain(t) codomain(t) ||
156+
throw(SpaceMismatch(lazy"domain and codomain are not isometrically embeddable: $(space(t))"))
147157
for (_, b) in blocks(t)
148158
MatrixAlgebra.one!(b)
149159
end
@@ -152,13 +162,18 @@ end
152162

153163
# expand methods with default arguments
154164
for morphism in (:isomorphism, :unitary, :isometry)
165+
morphism! = Symbol(morphism, :!)
155166
@eval begin
156167
$morphism(V::TensorMapSpace) = $morphism(Float64, V)
157168
$morphism(codomain::TensorSpace, domain::TensorSpace) = $morphism(codomain domain)
158169
function $morphism(A::Type, codomain::TensorSpace, domain::TensorSpace)
159170
return $morphism(A, codomain domain)
160171
end
161-
$morphism(t::AbstractTensorMap) = $morphism(storagetype(t), space(t))
172+
function $morphism(A::Type, V::TensorMapSpace{S,N₁,N₂}) where {S,N₁,N₂}
173+
t = tensormaptype(S, N₁, N₂, A)(undef, V)
174+
return $morphism!(t)
175+
end
176+
$morphism(t::AbstractTensorMap) = $morphism!(similar(t))
162177
end
163178
end
164179

0 commit comments

Comments
 (0)