Skip to content

Commit 0fe95f4

Browse files
authored
Fix eltype propagation in embed and LazySums. (#82)
1 parent e96f8a4 commit 0fe95f4

File tree

4 files changed

+29
-13
lines changed

4 files changed

+29
-13
lines changed

src/operators.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
9090
(opsb.basis_r == basis_r.bases[idxsb]) || throw(IncompatibleBases())
9191
end
9292

93-
embed_op = tensor([i indices_sb ? ops_sb[indexin(i, indices_sb)[1]] : identityoperator(T, basis_l.bases[i], basis_r.bases[i]) for i=1:N]...)
93+
S = length(operators) > 1 ? mapreduce(eltype, promote_type, operators) : Any
94+
embed_op = tensor([i indices_sb ? ops_sb[indexin(i, indices_sb)[1]] : identityoperator(T, S, basis_l.bases[i], basis_r.bases[i]) for i=1:N]...)
9495

9596
# Embed all joint-subspace operators.
9697
idxop_comp = [x for x in zip(indices, operators) if x[1] isa Array]
@@ -116,7 +117,7 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
116117
reduce(tensor, basis_r.bases[indices]) == op.basis_r || throw(IncompatibleBases())
117118

118119
index_order = [idx for idx in 1:length(basis_l.bases) if idx indices]
119-
all_operators = AbstractOperator[identityoperator(T, basis_l.bases[i], basis_r.bases[i]) for i in index_order]
120+
all_operators = AbstractOperator[identityoperator(T, eltype(op), basis_l.bases[i], basis_r.bases[i]) for i in index_order]
120121

121122
for idx in indices
122123
pushfirst!(index_order, idx)
@@ -209,21 +210,22 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
209210
end
210211
indices, operator_list = zip(operators...)
211212
operator_list = [operator_list...;]
213+
S = mapreduce(eltype, promote_type, operator_list)
212214
indices_flat = [indices...;]::Vector{Int} # type assertion to help type inference
213215
start_indices_flat = [i[1] for i in indices]
214216
complement_indices_flat = Int[i for i=1:N if i indices_flat]
215217
operators_flat = AbstractOperator[]
216218
if all([minimum(I):maximum(I);]==I for I in indices)
217219
for i in 1:N
218220
if i in complement_indices_flat
219-
push!(operators_flat, identityoperator(T, basis_l.bases[i], basis_r.bases[i]))
221+
push!(operators_flat, identityoperator(T, S, basis_l.bases[i], basis_r.bases[i]))
220222
elseif i in start_indices_flat
221223
push!(operators_flat, operator_list[indexin(i, start_indices_flat)[1]])
222224
end
223225
end
224226
return tensor(operators_flat...)
225227
else
226-
complement_operators = [identityoperator(T, basis_l.bases[i], basis_r.bases[i]) for i in complement_indices_flat]
228+
complement_operators = [identityoperator(T, S, basis_l.bases[i], basis_r.bases[i]) for i in complement_indices_flat]
227229
op = tensor([operator_list; complement_operators]...)
228230
perm = sortperm([indices_flat; complement_indices_flat])
229231
return permutesystems(op, perm)

src/operators_lazysum.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ function LazySum(factors, operators)
5555
LazySum(Tf, factors, operators)
5656
end
5757
LazySum(::Type{Tf}, operators::AbstractOperator...) where Tf = LazySum(ones(Tf, length(operators)), (operators...,))
58-
LazySum(operators::AbstractOperator...) = LazySum(ComplexF64, operators...)
58+
LazySum(operators::AbstractOperator...) = LazySum(mapreduce(eltype, promote_type, operators), operators...)
5959
LazySum() = throw(ArgumentError("LazySum needs a basis, or at least one operator!"))
6060

6161
Base.copy(x::LazySum) = @samebases LazySum(x.basis_l, x.basis_r, copy(x.factors), copy.(x.operators))

test/test_operators_lazysum.jl

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,19 @@ op2 = sparse(randoperator(b_l, b_r))
4747
@test 0.1*sparse(op1) + 0.3*op2 == sparse(LazySum([0.1, 0.3], (op1, op2)))
4848

4949
# Test embed
50-
x1 = randoperator(b1a,b1b)
51-
y1 = randoperator(b1a,b1b)
52-
xy1 = LazySum([1., 2.], (x1, y1))
53-
x = LazySum([1.], (embed(b_l, b_r, 1, x1),))
54-
y = LazySum([2.], (embed(b_l, b_r, 1, y1),))
55-
xy = x + y
56-
@test embed(b_l, b_r, [1], xy1) == xy
50+
for T in (Float32, Float64, ComplexF32, ComplexF64)
51+
x1 = randoperator(T, b1a,b1b)
52+
y1 = randoperator(T, b1a,b1b)
53+
xy1 = LazySum(T[1., 2.], (x1, y1))
54+
x = LazySum(T[1.], (embed(b_l, b_r, 1, x1),))
55+
y = LazySum(T[2.], (embed(b_l, b_r, 1, y1),))
56+
@test eltype(x) == T
57+
@test eltype(y) == T
58+
xy = x + y
59+
@test embed(b_l, b_r, [1], xy1) == xy
60+
@test eltype(xy) == T
61+
end
62+
5763

5864
# Arithmetic operations
5965
# =====================

test/test_operators_lazytensor.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,15 @@ x = LazyTensor(b_l, b_r, [1, 3], (op1, sparse(op3)), 0.3)
6262
@test 1e-12 > D(0.3*sparse(op1)I2sparse(op3), sparse(x))
6363

6464
# Test eltype
65-
@test eltype(x) == ComplexF64
65+
for T in (Float32, Float64, ComplexF32, ComplexF64)
66+
I2_T = identityoperator(T, b2a, b2b)
67+
op1_T = randoperator(T, b1a, b1b)
68+
op3_T = randoperator(T, b3a, b3b)
69+
x_T = LazyTensor(b_l, b_r, [1, 3], (op1_T, sparse(op3_T)), T(0.3))
70+
@test eltype(x_T) == T
71+
@test eltype(dense(x_T)) == T
72+
@test eltype(sparse(x_T)) == T
73+
end
6674

6775
# Test suboperators
6876
@test QuantumOpticsBase.suboperator(x, 1) == op1

0 commit comments

Comments
 (0)