Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/gradgen_operator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ end

_exp_prop_convert_operator(::GradgenOperator) = Matrix{ComplexF64}

supports_inplace(::Type{GradgenOperator{N,GT,CGT}}) where {N,GT,CGT} =
(supports_inplace(GT) && supports_inplace(CGT))
supports_inplace(::Type{GradgenOperator{N,GT,CGT}}) where {N,GT,CGT} = supports_inplace(GT)
# Note: `evaluate!` for `GradgenOperator` reassigns `control_deriv_ops[i]` via
# vector element assignment, so the in-place capability of `CGT` is irrelevant.
# Only the underlying operator `GT` needs to support in-place evaluation.

supports_matrix_interface(::Type{<:GradgenOperator{N,GT,CGT}}) where {N,GT,CGT} =
supports_matrix_interface(GT) && supports_matrix_interface(CGT)
42 changes: 11 additions & 31 deletions src/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -241,52 +241,32 @@ function Base.fill!(Ψ::GradVector, v)
end


# === Matrix interface for GradgenOperator ===
#
# The following methods are part of the matrix interface and are only
# meaningful when `supports_matrix_interface` is true for both component types.
# Each method delegates to a private `_name(::Val{supports}, ...)` function:
# the Val{true} method contains the implementation, and the Val{false} method
# throws an error.

function _size(
::Val{true},
O::GradgenOperator{num_controls,GT,CGT}
) where {num_controls,GT,CGT}
function Base.size(O::GradgenOperator{num_controls,GT,CGT}) where {num_controls,GT,CGT}
return (num_controls + 1) .* size(O.G)
end

function _size(::Val{false}, O::GradgenOperator)
error("$(typeof(O)) does not support the matrix interface")
end

function Base.size(O::T) where {T<:GradgenOperator}
return _size(Val(supports_matrix_interface(T)), O)
end


function _size(
::Val{true},
function Base.size(
O::GradgenOperator{num_controls,GT,CGT},
dim::Integer
) where {num_controls,GT,CGT}
return (num_controls + 1) * size(O.G, dim)
end

function _size(::Val{false}, O::GradgenOperator, dim::Integer)
error("$(typeof(O)) does not support the matrix interface")
end

function Base.size(O::T, dim::Integer) where {T<:GradgenOperator}
return _size(Val(supports_matrix_interface(T)), O, dim)
end
# === Matrix interface for GradgenOperator ===
#
# The following methods are part of the matrix interface and are only
# meaningful when `supports_matrix_interface` is true for both component types.
# Each method delegates to a private `_name(::Val{supports}, ...)` function:
# the Val{true} method contains the implementation, and the Val{false} method
# throws an error. Note that this does not include `size`, which must be
# defined for _all_ operators, whether or not they define the full matrix
# interface.


# As for an `Operator`, we implement `similar` to return a standard `Array`
# because `GradgenOperator` does not `setindex!`, so it's arguably not a
# "mutable array" even if its components are mutable.
# similar(O) and similar(O, S) call size(O), which will error if
# !supports_matrix_interface. The dims-based variants need no guard.
Base.similar(G::GradgenOperator) = Array{eltype(G)}(undef, size(G))

Base.similar(O::GradgenOperator, ::Type{S}) where {S} = Array{S}(undef, size(O))
Expand Down
2 changes: 0 additions & 2 deletions test/test_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,6 @@ end

# Matrix interface methods must throw an error when not supported
@test_throws "does not support the matrix interface" op[1, 1]
@test_throws "does not support the matrix interface" size(op)
@test_throws "does not support the matrix interface" size(op, 1)
@test_throws "does not support the matrix interface" length(op)
@test_throws "does not support the matrix interface" iterate(op)

Expand Down
Loading