diff --git a/src/Operators/Operator.jl b/src/Operators/Operator.jl index cd6b7ccd..a2f7e462 100644 --- a/src/Operators/Operator.jl +++ b/src/Operators/Operator.jl @@ -900,3 +900,5 @@ diagindrow(S::SubOperator) = diagindrow(S,parentindices(S)[1],parentindices(S)[2 # Conversion between operator types convert(::Type{O}, c::Operator) where {O<:Operator} = c isa O ? c : O(c)::O +convert(::Type{Operator{T}}, c::Operator{S}) where {S,T} = c isa Operator{T} ? c : Operator{T}(c)::Operator{T} +Operator(A::Operator) = A diff --git a/src/Operators/SubOperator.jl b/src/Operators/SubOperator.jl index 96bc92ea..f6b7eda1 100644 --- a/src/Operators/SubOperator.jl +++ b/src/Operators/SubOperator.jl @@ -78,8 +78,16 @@ SubOperator(A,inds,dims) = SubOperator(A,inds,dims,(dims[1]-1,dims[2]-1)) SubOperator(A,inds) = SubOperator(A,inds,map(length,inds)) -convert(::Type{Operator{T}},SO::SubOperator) where {T} = +Operator{T}(SO::SubOperator) where {T} = SubOperator(Operator{T}(SO.parent),SO.indexes,SO.dims,SO.bandwidths)::Operator{T} +function SubOperator{T,B,I,DI,BI}(S::SubOperator) where {T,B,I,DI,BI} + SubOperator{T,B,I,DI,BI}( + strictconvert(B, S.parent), + strictconvert(I, S.indexes), + strictconvert(DI, S.dims), + strictconvert(BI, S.bandwidths), + ) +end function view(A::Operator,kr::InfRanges,jr::InfRanges) @assert isinf(size(A,1)) && isinf(size(A,2)) diff --git a/src/Operators/almostbanded/LowRankOperator.jl b/src/Operators/almostbanded/LowRankOperator.jl index 59a64256..4fa35bf2 100644 --- a/src/Operators/almostbanded/LowRankOperator.jl +++ b/src/Operators/almostbanded/LowRankOperator.jl @@ -6,7 +6,7 @@ struct LowRankOperator{S<:Space,T} <: AbstractLowRankOperator{T} U::Vector{VFun{S,T}} V::Vector{Operator{T}} - function LowRankOperator{S,T}(U::Vector{VFun{S,T}},V::Vector{Operator{T}}) where {S,T} + function LowRankOperator{S,T}(U::Vector{VFun{S,T}},V::Vector{Operator{T}}) where {S<:Space,T} @assert all(isafunctional,V) @assert length(U) == length(V) @@ -39,9 +39,12 @@ LowRankOperator(B::AbstractVector,S...) = LowRankOperator(strictconvert(Vector{O LowRankOperator(A::Fun,B::Operator) = LowRankOperator([A],[B]) -convert(::Type{Operator{T}},L::LowRankOperator{S}) where {S,T} = +function LowRankOperator{S,T}(L::LowRankOperator) where {S<:Space,T} LowRankOperator{S,T}(strictconvert(Vector{VFun{S,T}},L.U), strictconvert(Vector{Operator{T}},L.V)) +end + +Operator{T}(L::LowRankOperator{S}) where {S,T} = LowRankOperator{S,T}(L) datasize(L::LowRankOperator,k) = diff --git a/src/Operators/almostbanded/LowRankPertOperator.jl b/src/Operators/almostbanded/LowRankPertOperator.jl index aa789841..9f0894aa 100644 --- a/src/Operators/almostbanded/LowRankPertOperator.jl +++ b/src/Operators/almostbanded/LowRankPertOperator.jl @@ -20,9 +20,12 @@ function LowRankPertOperator(Bin::Operator,Lin::LowRankOperator) end - -convert(::Type{Operator{T}},L::LowRankPertOperator) where {T} = - LowRankPertOperator(Operator{T}(L.op),Operator{T}(L.pert))::Operator{T} +function LowRankPertOperator{OO,LR,T}(L::LowRankPertOperator) where {OO,LR,T} + LowRankPertOperator{OO,LR,T}(strictconvert(OO, L.op), strictconvert(LR, L.pert)) +end +function Operator{T}(L::LowRankPertOperator) where {T} + LowRankPertOperator(Operator{T}(L.op),Operator{T}(L.pert)) +end convert(::Type{Operator},V::AbstractVector{OT}) where {OT<:Operator}=LowRankPertOperator(V) diff --git a/src/Operators/banded/CalculusOperator.jl b/src/Operators/banded/CalculusOperator.jl index 369d870d..b22be7ad 100644 --- a/src/Operators/banded/CalculusOperator.jl +++ b/src/Operators/banded/CalculusOperator.jl @@ -18,12 +18,23 @@ macro calculus_operator(Op) space::S # the domain space order::OT end + function $ConcOp{S,OT,T}(C::$ConcOp) where {S<:Space,OT,T} + $ConcOp{S,OT,T}(strictconvert(S, C.space), strictconvert(OT, C.order)) + end struct $WrappOp{BT<:Operator,S<:Space,R<:Space,OT,T} <: $Op{S,OT,T} op::BT order::OT domainspace::S rangespace::R end + function $WrappOp{BT,S,R,OT,T}(C::$WrappOp) where {BT<:Operator,S<:Space,R<:Space,OT,T} + $WrappOp{BT,S,R,OT,T}( + strictconvert(BT, C.op), + strictconvert(OT, C.order), + strictconvert(S, C.domainspace), + strictconvert(R, C.rangespace), + ) + end ApproxFunBase.@wrapper $WrappOp false false ApproxFunBase.domainspace(A::$WrappOp) = A.domainspace @@ -58,26 +69,18 @@ macro calculus_operator(Op) $Op(x...) = $DefaultOp(x...) $ConcOp(S::Space) = $ConcOp(S,1) - function Base.convert(::Type{Operator{T}},D::$ConcOp) where T - if T==eltype(D) - D - else - $ConcOp{typeof(D.space),typeof(D.order),T}(D.space, D.order) - end + function Operator{T}(D::$ConcOp) where {T} + $ConcOp{typeof(D.space),typeof(D.order),T}(D)::Operator{T} end $WrappOp(op::Operator, order = 1, d = domainspace(op), r = rangespace(op)) = $WrappOp{typeof(op),typeof(d),typeof(r),typeof(order),eltype(op)}(op,order,d,r) - function Base.convert(::Type{Operator{T}},D::$WrappOp) where T - if T==eltype(D) - D - else - op=ApproxFunBase.strictconvert(Operator{T},D.op) - S = domainspace(D) - R = rangespace(D) - $WrappOp(op,D.order,S,R)::Operator{T} - end + function Operator{T}(D::$WrappOp) where {T} + op=ApproxFunBase.strictconvert(Operator{T},D.op) + S = domainspace(D) + R = rangespace(D) + $WrappOp{typeof(op),typeof(S),typeof(R),typeof(D.order),T}(op,D.order,S,R)::Operator{T} end ## Routines diff --git a/src/Operators/banded/ConstantOperator.jl b/src/Operators/banded/ConstantOperator.jl index 112710ff..0cf5b236 100644 --- a/src/Operators/banded/ConstantOperator.jl +++ b/src/Operators/banded/ConstantOperator.jl @@ -1,6 +1,6 @@ export ConstantOperator, IdentityOperator, BasisFunctional -struct ConstantOperator{T,DS} <: Operator{T} +struct ConstantOperator{T,DS<:Space} <: Operator{T} λ::T space::DS ConstantOperator{T,DS}(c::Number,sp::DS) where {T,DS} = new{T,DS}(strictconvert(T,c),sp) @@ -36,12 +36,11 @@ getindex(C::ConstantOperator,k::Integer,j::Integer) = ==(C1::ConstantOperator, C2::ConstantOperator) = C1.λ==C2.λ -function convert(::Type{Operator{T}}, C::ConstantOperator) where T - if T == eltype(C) - C - else - ConstantOperator{T,typeof(C.space)}(C.λ,C.space) - end +function ConstantOperator{T,DS}(C::ConstantOperator) where {T,DS} + ConstantOperator{T,DS}(strictconvert(T, C.λ), strictconvert(DS, C.space)) +end +function Operator{T}(C::ConstantOperator) where T + ConstantOperator{T,typeof(C.space)}(C.λ,C.space) end # zero needs to be different since it can take a space to diff --git a/src/Operators/banded/Conversion.jl b/src/Operators/banded/Conversion.jl index b179f55b..c7e8bdb9 100644 --- a/src/Operators/banded/Conversion.jl +++ b/src/Operators/banded/Conversion.jl @@ -16,12 +16,12 @@ function ConcreteConversion(a::Space,b::Space) ConcreteConversion(T, a, b) end -function convert(::Type{Operator{T}}, C::ConcreteConversion) where {T} - if T==eltype(C) - C - else - ConcreteConversion(T, C.domainspace,C.rangespace)::Operator{T} - end +function ConcreteConversion{D,R,T}(C::ConcreteConversion) where {D<:Space,R<:Space,T} + ConcreteConversion{D,R,T}(strictconvert(D,C.domainspace), strictconvert(R, C.rangespace)) +end + +function Operator{T}(C::ConcreteConversion) where {T} + ConcreteConversion(T, C.domainspace,C.rangespace)::Operator{T} end domainspace(C::ConcreteConversion)=C.domainspace @@ -126,15 +126,17 @@ Conversion(A::Space,B::Space,C::Space,D::Space...) = ==(A::ConversionWrapper,B::ConversionWrapper) = A.op==B.op - -function convert(::Type{Operator{T}},D::ConversionWrapper) where T - if T==eltype(D) - D - else - BO=strictconvert(Operator{T},D.op) - d, r = domainspace(D), rangespace(D) - ConversionWrapper(d, r, BO)::Operator{T} - end +function ConversionWrapper{D,R,T,O}(C::ConversionWrapper) where {D<:Space,R<:Space,T,O<:Operator{T}} + ConversionWrapper{D,R,T,O}( + strictconvert(D,C.domainspace), + strictconvert(R,C.rangespace), + strictconvert(O, C.op) + ) +end +function Operator{T}(D::ConversionWrapper) where T + BO=strictconvert(Operator{T},D.op) + d, r = domainspace(D), rangespace(D) + ConversionWrapper(d, r, BO)::Operator{T} end convert(::Type{T}, C::ConversionWrapper) where {T<:Number} = strictconvert(T, C.op) diff --git a/src/Operators/banded/Multiplication.jl b/src/Operators/banded/Multiplication.jl index 299e5743..3885b8eb 100644 --- a/src/Operators/banded/Multiplication.jl +++ b/src/Operators/banded/Multiplication.jl @@ -51,13 +51,11 @@ Multiplication(c::Number) = Multiplication(Fun(c) ) # This covers right multiplication unless otherwise specified. Multiplication(S::Space,f::Fun) = Multiplication(f,S) - -function convert(::Type{Operator{T}},C::ConcreteMultiplication{S,V}) where {S,V,T} - if T==eltype(C) - C - else - ConcreteMultiplication{S,V,T}(Fun{S,T}(C.f),C.space) - end +function ConcreteMultiplication{D,S,T}(C::ConcreteMultiplication) where {D<:Space,S<:Space,T} + ConcreteMultiplication{D,S,T}(strictconvert(VFun{D,T}, C.f), strictconvert(S, C.space)) +end +function Operator{T}(C::ConcreteMultiplication{S,V}) where {S,V,T} + ConcreteMultiplication{S,V,T}(Fun{S,T}(C.f),C.space) end domainspace(M::ConcreteMultiplication{D,S,T}) where {D,S,T} = M.space @@ -113,12 +111,11 @@ domainspace(M::MultiplicationWrapper) = M.space @wrapper MultiplicationWrapper false -function convert(::Type{Operator{TT}},C::MultiplicationWrapper{S,V,O,T}) where {TT,S,V,O,T} - if TT==T - C - else - MultiplicationWrapper(Fun{S,TT}(C.f),Operator{TT}(C.op), C.space)::Operator{TT} - end +function MultiplicationWrapper{D,S,T,O}(M::MultiplicationWrapper) where {D<:Space,S<:Space,T,O<:Operator{T}} + MultiplicationWrapper{D,S,T,O}(strictconvert(VFun{D,T}, M.f), strictconvert(O, M.op), strictconvert(S, M.space)) +end +function Operator{TT}(C::MultiplicationWrapper{S}) where {TT,S} + MultiplicationWrapper(Fun{S,TT}(C.f),Operator{TT}(C.op), C.space)::Operator{TT} end diff --git a/src/Operators/banded/PermutationOperator.jl b/src/Operators/banded/PermutationOperator.jl index a4d35927..6d55584c 100644 --- a/src/Operators/banded/PermutationOperator.jl +++ b/src/Operators/banded/PermutationOperator.jl @@ -1,6 +1,6 @@ # Creates a operator that permutes rows, in blocks of size # length(perm) -struct PermutationOperator{T,DS,RS} <: Operator{T} +struct PermutationOperator{T,DS<:Space,RS<:Space} <: Operator{T} perm::Vector{Int} domainspace::DS rangespace::RS @@ -13,8 +13,10 @@ PermutationOperator(prm) = PermutationOperator(prm, ℓ⁰, ℓ⁰) domainspace(P::PermutationOperator) = P.domainspace rangespace(P::PermutationOperator) = P.rangespace - -convert(::Type{Operator{T}},P::PermutationOperator) where {T} = +function PermutationOperator{T,DS,RS}(P::PermutationOperator) where {T,DS<:Space,RS<:Space} + PermutationOperator{T,DS,RS}(P.perm, strictconvert(DS, P.domainspace), strictconvert(RS, P.rangespace)) +end +Operator{T}(P::PermutationOperator) where {T} = PermutationOperator{T}(P.perm, P.domainspace, P.rangespace) function bandwidths(P::PermutationOperator) @@ -39,7 +41,7 @@ perm(a::Vector,b::Vector) = multiplyperm(invperm(sortperm(b)),sortperm(a)) perm(a::Tuple,b::Tuple) = perm(collect(a),collect(b)) -struct NegateEven{T,DS,RS} <: Operator{T} +struct NegateEven{T,DS<:Space,RS<:Space} <: Operator{T} domainspace::DS rangespace::RS end @@ -52,7 +54,10 @@ NegateEven() = NegateEven(ℓ⁰,ℓ⁰) domainspace(P::NegateEven) = P.domainspace rangespace(P::NegateEven) = P.rangespace -convert(::Type{Operator{T}},P::NegateEven) where {T} = +function NegateEven{T,DS,RS}(N::NegateEven) where {T,DS<:Space,RS<:Space} + NegateEven{T,DS,RS}(strictconvert(DS, N.domainspace), strictconvert(RS, N.rangespace)) +end +Operator{T}(P::NegateEven) where {T} = NegateEven{T}(P.domainspace, P.rangespace) bandwidths(P::NegateEven) = (0,0) diff --git a/src/Operators/banded/Reverse.jl b/src/Operators/banded/Reverse.jl index 1c1239cb..8373621b 100644 --- a/src/Operators/banded/Reverse.jl +++ b/src/Operators/banded/Reverse.jl @@ -10,8 +10,10 @@ for TYP in (:ReverseOrientation,:Reverse) end $WRAP(op::Operator) = $WRAP{typeof(op),eltype(op)}(op) - convert(::Type{Operator{T}},op::$TYP) where {T} = $TYP{T}() - convert(::Type{Operator{T}},op::$WRAP) where {T} = $WRAP(Operator{T}(op.op))::Operator{T} + $TYP{T}(op::$TYP) where {T} = $TYP{T}() + Operator{T}(op::$TYP) where {T} = $TYP{T}() + $WRAP{OS,T}(op::$WRAP) where {OS,T} = $WRAP{OS,T}(strictconvert(OS,op)) + Operator{T}(op::$WRAP) where {T} = $WRAP(Operator{T}(op.op))::Operator{T} @wrapper $WRAP end diff --git a/src/Operators/banded/ToeplitzOperator.jl b/src/Operators/banded/ToeplitzOperator.jl index 22eb0849..3850920e 100644 --- a/src/Operators/banded/ToeplitzOperator.jl +++ b/src/Operators/banded/ToeplitzOperator.jl @@ -12,7 +12,10 @@ ToeplitzOperator(V::Vector{T},W::Vector{Q}) where {T<:Number,Q<:Number} = ToeplitzOperator(V::AbstractVector,W::AbstractVector) = ToeplitzOperator(collect(V),collect(W)) -convert(::Type{Operator{TT}},T::ToeplitzOperator) where {TT} = +function ToeplitzOperator{T}(x::ToeplitzOperator) where {T<:Number} + ToeplitzOperator{T}(strictconvert(Vector{T}, x.negative), strictconvert(Vector{T}, x.nonnegative)) +end +Operator{TT}(T::ToeplitzOperator) where {TT<:Number} = ToeplitzOperator(strictconvert(Vector{TT},T.negative),strictconvert(Vector{TT},T.nonnegative)) for op in (:(Base.real), :(Base.imag)) @@ -106,8 +109,8 @@ HankelOperator(V::AbstractVector)=HankelOperator(collect(V)) HankelOperator(f::Fun)=HankelOperator(f.coefficients) - -@eval convert(::Type{Operator{TT}},T::HankelOperator) where {TT}=HankelOperator(strictconvert(Vector{TT},T.coefficients)) +HankelOperator{T}(H::HankelOperator) where {T<:Number} = HankelOperator{T}(strictconvert(Vector{T}, H.coefficients)) +Operator{TT}(H::HankelOperator) where {TT<:Number} = HankelOperator(strictconvert(Vector{TT},H.coefficients)) function hankel_getindex(v::AbstractVector,k::Integer,j::Integer) if k+j-1 ≤ length(v) diff --git a/src/Operators/functionals/CalculusFunctional.jl b/src/Operators/functionals/CalculusFunctional.jl index 9d304aa5..0ddce989 100644 --- a/src/Operators/functionals/CalculusFunctional.jl +++ b/src/Operators/functionals/CalculusFunctional.jl @@ -11,7 +11,7 @@ macro calculus_functional(Op) WrappOp = Symbol(Op, :Wrapper) return esc(quote abstract type $Op{SSS,TTT} <: ApproxFunBase.CalculusFunctional{SSS,TTT} end - struct $ConcOp{S,T} <: $Op{S,T} + struct $ConcOp{S<:Space,T} <: $Op{S,T} domainspace::S end struct $WrappOp{BT<:Operator,S<:Space,T} <: $Op{S,T} @@ -30,9 +30,11 @@ macro calculus_functional(Op) ApproxFunBase.promotedomainspace(::$Op,sp::Space) = $Op(sp) - - Base.convert(::Type{Operator{T}},Σ::$ConcOp) where {T} = - (T==eltype(Σ) ? Σ : $ConcOp{typeof(Σ.domainspace),T}(Σ.domainspace))::Operator{T} + function $ConcOp{S,T}(C::$ConcOp) where {S<:Space,T} + $ConcOp{S,T}(strictconvert(S, C.domainspace)) + end + Operator{T}(Σ::$ConcOp) where {T} = + $ConcOp{typeof(Σ.domainspace),T}(Σ.domainspace)::Operator{T} ApproxFunBase.domain(Σ::$ConcOp) = domain(Σ.domainspace) ApproxFunBase.domainspace(Σ::$ConcOp) = Σ.domainspace @@ -43,9 +45,11 @@ macro calculus_functional(Op) $WrappOp(op::Operator) = $WrappOp{typeof(op),typeof(domainspace(op)),eltype(op)}(op) - - Base.convert(::Type{Operator{T}},Σ::$WrappOp) where {T} = - (T==eltype(Σ) ? Σ : $WrappOp(strictconvert(Operator{T},Σ.op)))::Operator{T} + function $WrappOp{BT,S,T}(W::$WrappOp) where {BT<:Operator,S<:Space,T} + $WrappOp{BT,S,T}(strictconvert(BT, W.op)) + end + Operator{T}(Σ::$WrappOp) where {T} = + $WrappOp(strictconvert(Operator{T},Σ.op))::Operator{T} end) end diff --git a/src/Operators/functionals/Evaluation.jl b/src/Operators/functionals/Evaluation.jl index db568d60..f77a295f 100644 --- a/src/Operators/functionals/Evaluation.jl +++ b/src/Operators/functionals/Evaluation.jl @@ -7,7 +7,7 @@ abstract type Evaluation{T}<:Operator{T} end @functional Evaluation # M = leftendpoint/rightendpoint if endpoint -struct ConcreteEvaluation{S,M,OT,T} <: Evaluation{T} +struct ConcreteEvaluation{S<:Space,M,OT,T} <: Evaluation{T} space::S x::M order::OT @@ -45,13 +45,11 @@ Evaluation(x::Union{Number,typeof(leftendpoint),typeof(rightendpoint)},k::Intege rangespace(E::ConcreteEvaluation{<:AmbiguousSpace}) = ConstantSpace() rangespace(E::ConcreteEvaluation) = ConstantSpace(Point(E.x)) - -function convert(::Type{Operator{T}},E::ConcreteEvaluation) where T - if T == eltype(E) - E - else - ConcreteEvaluation{typeof(E.space),typeof(E.x),typeof(E.order),T}(E.space,E.x,E.order) - end +function ConcreteEvaluation{S,M,OT,T}(C::ConcreteEvaluation) where {S<:Space,M,OT,T} + ConcreteEvaluation{S,M,OT,T}(strictconvert(S, C.space), strictconvert(M, C.x), strictconvert(OT,C.order)) +end +function Operator{T}(E::ConcreteEvaluation) where T + ConcreteEvaluation{typeof(E.space),typeof(E.x),typeof(E.order),T}(E.space,E.x,E.order) end @@ -69,12 +67,12 @@ end for (dop, fop) in ((:leftendpoint,:first), (:rightendpoint,:last)) @eval begin rangespace(E::ConcreteEvaluation{<:AmbiguousSpace,typeof($dop)}) = UnsetSpace() - function rangespace(E::ConcreteEvaluation{<:Any,typeof($dop)}) + function rangespace(E::ConcreteEvaluation{<:Space,typeof($dop)}) d = domain(domainspace(E)) isambiguous(d) && return ConstantSpace() return ConstantSpace(Point($dop(d))) end - function getindex(D::ConcreteEvaluation{<:Any,typeof($dop)},k::Integer) + function getindex(D::ConcreteEvaluation{<:Space,typeof($dop)},k::Integer) P = prectype(domainspace(D)) R = eltype(D) R($fop(differentiate(Fun(D.space,[zeros(P,k-1);one(P)]),D.order))) @@ -106,13 +104,12 @@ domainspace(E::Evaluation) = E.space promotedomainspace(E::Evaluation,sp::Space) = Evaluation(sp,E.x,E.order) - -function convert(::Type{Operator{T}},E::EvaluationWrapper) where T - if T == eltype(E) - E - else - EvaluationWrapper(E.space,E.x,E.order,strictconvert(Operator{T},E.op))::Operator{T} - end +function EvaluationWrapper{S,M,FS,OT,T}(E::EvaluationWrapper) where {S<:Space,M,FS<:Operator,OT,T<:Number} + EvaluationWrapper{S,M,FS,OT,T}(strictconvert(S, E.space), strictconvert(M, E.x), + strictconvert(OT, E.order), strictconvert(FS, E.op)) +end +function Operator{T}(E::EvaluationWrapper) where T + EvaluationWrapper(E.space,E.x,E.order,strictconvert(Operator{T},E.op))::Operator{T} end ## Convenience routines @@ -155,7 +152,7 @@ end abstract type Dirichlet{S,T} <: Operator{T} end -struct ConcreteDirichlet{S,V,T} <: Dirichlet{S,T} +struct ConcreteDirichlet{S<:Space,V<:Space,T} <: Dirichlet{S,T} domainspace::S rangespace::V order::Int @@ -166,7 +163,10 @@ ConcreteDirichlet(sp::Space,rs::Space,order) = ConcreteDirichlet(sp::Space,order) = ConcreteDirichlet(sp,Space(∂(domain(sp))),order) ConcreteDirichlet(sp::Space) = ConcreteDirichlet(sp,0) -convert(::Type{Operator{T}},B::ConcreteDirichlet{S,V}) where {S,V,T} = +function ConcreteDirichlet{S,V,T}(C::ConcreteDirichlet) where {S<:Space,V<:Space,T} + ConcreteDirichlet{S,V,T}(strictconvert(S, C.domainspace), strictconvert(V, C.rangespace), C.order) +end +Operator{T}(B::ConcreteDirichlet{S,V}) where {S,V,T} = ConcreteDirichlet{S,V,T}(B.domainspace,B.rangespace,B.order) @@ -179,7 +179,10 @@ end DirichletWrapper(B::Operator,λ=0) = DirichletWrapper{typeof(B),eltype(B)}(B,λ) -convert(::Type{Operator{T}},B::DirichletWrapper) where {T} = +function DirichletWrapper{S,T}(D::DirichletWrapper) where {S,T} + DirichletWrapper{S,T}(strictconvert(S, D.op), D.order) +end +Operator{T}(B::DirichletWrapper) where {T} = DirichletWrapper(Operator{T}(B.op),B.order)::Operator{T} # Default is to use diffbca diff --git a/src/Operators/general/CachedOperator.jl b/src/Operators/general/CachedOperator.jl index 0fd6fffa..1bc10ebd 100644 --- a/src/Operators/general/CachedOperator.jl +++ b/src/Operators/general/CachedOperator.jl @@ -57,8 +57,18 @@ Caches the entries of an operator, to speed up multiplying a Fun by the operator cache(O::Operator;kwds...) = CachedOperator(O;kwds...) cache(::Type{MT},O::Operator;kwds...) where {MT<:AbstractMatrix} = CachedOperator(MT,O;kwds...) -convert(::Type{Operator{T}},S::CachedOperator{T}) where {T} = S -convert(::Type{Operator{T}},S::CachedOperator) where {T} = +function CachedOperator{T,DM,M,DS,RS,BI}(C::CachedOperator) where {T<:Number,DM<:AbstractMatrix,M<:Operator,DS,RS,BI} + CachedOperator{T,DM,M,DS,RS,BI}( + strictconvert(M, C.op), + strictconvert(DM, C.data), + C.datasize, + strictconvert(DS, C.domainspace), + strictconvert(RS, C.rangespace), + strictconvert(BI, C.bandwidths), + C.padding, + ) +end +Operator{T}(S::CachedOperator) where {T} = CachedOperator(strictconvert(Operator{T}, S.op),strictconvert(AbstractMatrix{T}, S.data), S.datasize,S.domainspace,S.rangespace,S.bandwidths) diff --git a/src/Operators/general/FiniteOperator.jl b/src/Operators/general/FiniteOperator.jl index ba92b107..2116f8a9 100644 --- a/src/Operators/general/FiniteOperator.jl +++ b/src/Operators/general/FiniteOperator.jl @@ -16,7 +16,14 @@ FiniteOperator(M::AbstractMatrix{<:Number},ds::Space,rs::Space) = FiniteOperator(M::AbstractMatrix{<:Number}) = FiniteOperator(M,EuclideanSpace(size(M,2)),EuclideanSpace(size(M,1))) -convert(::Type{Operator{T}},F::FiniteOperator) where {T} = +function FiniteOperator{AT,T,DS,RS}(F::FiniteOperator) where {AT<:AbstractMatrix,T<:Number,DS,RS} + FiniteOperator{AT,T,DS,RS}( + strictconvert(AT, F.matrix), + strictconvert(DS, F.domainspace), + strictconvert(RS, F.rangespace), + ) +end +Operator{T}(F::FiniteOperator) where {T} = FiniteOperator(strictconvert(AbstractMatrix{T},F.matrix),F.domainspace,F.rangespace)::Operator{T} ==(A::FiniteOperator, B::FiniteOperator) = A.matrix == B.matrix && A.domainspace == B.domainspace && A.rangespace == B.rangespace diff --git a/src/Operators/general/InterlaceOperator.jl b/src/Operators/general/InterlaceOperator.jl index ea8b2b2d..3b5a2f69 100644 --- a/src/Operators/general/InterlaceOperator.jl +++ b/src/Operators/general/InterlaceOperator.jl @@ -69,7 +69,7 @@ end ## Interlace operator -struct InterlaceOperator{T,p,DS,RS,DI,RI,BI} <: Operator{T} +struct InterlaceOperator{T,p,DS<:Space,RS<:Space,DI,RI,BI} <: Operator{T} ops::Array{Operator{T},p} domainspace::DS rangespace::RS @@ -78,8 +78,8 @@ struct InterlaceOperator{T,p,DS,RS,DI,RI,BI} <: Operator{T} bandwidths::BI end -const VectorInterlaceOperator = InterlaceOperator{T,1,DS,RS} where {T,DS,RS<:Space{D,R}} where {D,R<:AbstractVector} -const MatrixInterlaceOperator = InterlaceOperator{T,2,DS,RS} where {T,DS,RS<:Space{D,R}} where {D,R<:AbstractVector} +const VectorInterlaceOperator = InterlaceOperator{T,1,DS,RS} where {T,DS<:Space,RS<:Space{D,R}} where {D,R<:AbstractVector} +const MatrixInterlaceOperator = InterlaceOperator{T,2,DS,RS} where {T,DS<:Space,RS<:Space{D,R}} where {D,R<:AbstractVector} function InterlaceOperator(ops::AbstractMatrix{<:Operator},ds::Space,rs::Space) @@ -195,15 +195,20 @@ end InterlaceOperator(ops::AbstractArray) = InterlaceOperator(Array{Operator{promote_eltypeof(ops)}, ndims(ops)}(ops)) - -function convert(::Type{Operator{T}},S::InterlaceOperator) where T - if T == eltype(S) - S - else - ops = convert(AbstractArray{Operator{T}}, S.ops) - InterlaceOperator(ops,domainspace(S),rangespace(S), - S.domaininterlacer,S.rangeinterlacer,S.bandwidths) - end +function InterlaceOperator{T,p,DS,RS,DI,RI,BI}(S::InterlaceOperator) where {T,p,DS<:Space,RS<:Space,DI,RI,BI} + InterlaceOperator{T,p,DS,RS,DI,RI,BI}( + strictconvert(Array{Operator{T},p}, S.ops), + strictconvert(DS, S.domainspace), + strictconvert(RS, S.rangespace), + strictconvert(DI, S.domaininterlacer), + strictconvert(RI, S.rangeinterlacer), + strictconvert(BI, S.bandwidths), + ) +end +function Operator{T}(S::InterlaceOperator) where T + ops = convert(AbstractArray{Operator{T}}, S.ops) + InterlaceOperator(ops,domainspace(S),rangespace(S), + S.domaininterlacer,S.rangeinterlacer,S.bandwidths) end diff --git a/src/Operators/general/OperatorFunction.jl b/src/Operators/general/OperatorFunction.jl index 973616c0..9305e673 100644 --- a/src/Operators/general/OperatorFunction.jl +++ b/src/Operators/general/OperatorFunction.jl @@ -29,13 +29,19 @@ function getindex(OF::ConcreteOperatorFunction,k::Integer,j::Integer) end end -function convert(::Type{Operator{T}},D::ConcreteOperatorFunction) where T - if T==eltype(D) - D - else - DopT = strictconvert(Operator{T}, D.op) - ConcreteOperatorFunction(DopT, D.f)::Operator{T} - end +function ConcreteOperatorFunction{BT,FF,T}(C::ConcreteOperatorFunction) where {BT<:Operator,FF,T} + ConcreteOperatorFunction{BT,FF,T}( + strictconvert(BT, C.op), + strictconvert(FF, C.f), + ) +end +change_Fun_cfstype(::Type, x) = x +change_Fun_cfstype(::Type{T}, f::Fun{<:Any,T}) where {T} = f +change_Fun_cfstype(::Type{T}, f::Fun) where {T} = T.(f) +function Operator{T}(C::ConcreteOperatorFunction) where T + Cop = strictconvert(Operator{T}, C.op) + f = change_Fun_cfstype(T, C.f) + ConcreteOperatorFunction(Cop, f)::Operator{T} end diff --git a/src/Operators/general/OperatorLayout.jl b/src/Operators/general/OperatorLayout.jl index bd62b2b6..663c269d 100644 --- a/src/Operators/general/OperatorLayout.jl +++ b/src/Operators/general/OperatorLayout.jl @@ -9,7 +9,13 @@ struct HermitianOperator{T<:Number,B<:Operator} <: Operator{T} end HermitianOperator(B::Operator{T}, uplo::Symbol=:U) where {T<:Number} = HermitianOperator{T,typeof(B)}(B, char_uplo(uplo)) -convert(::Type{Operator{T}},A::HermitianOperator) where {T}=HermitianOperator(strictconvert(Operator{T},A.op), A.uplo) +Operator{T}(A::HermitianOperator) where {T}=HermitianOperator(strictconvert(Operator{T},A.op), Symbol(A.uplo)) +function HermitianOperator{T,B}(H::HermitianOperator) where {T<:Number,B<:Operator} + HermitianOperator{T,B}( + strictconvert(B, H.op), + H.uplo + ) +end domainspace(P::HermitianOperator)=domainspace(P.op) rangespace(P::HermitianOperator)=rangespace(P.op) @@ -42,7 +48,13 @@ struct SymmetricOperator{T<:Number,B<:Operator} <: Operator{T} end SymmetricOperator(B::Operator{T}, uplo::Symbol=:U) where {T<:Number} = SymmetricOperator{T,typeof(B)}(B, char_uplo(uplo)) -convert(::Type{Operator{T}},A::SymmetricOperator) where {T}=SymmetricOperator(strictconvert(Operator{T},A.op), A.uplo) +Operator{T}(A::SymmetricOperator) where {T}=SymmetricOperator(strictconvert(Operator{T},A.op), Symbol(A.uplo)) +function SymmetricOperator{T,B}(S::SymmetricOperator) where {T<:Number,B<:Operator} + SymmetricOperator{T,B}( + strictconvert(B, S.op), + S.uplo, + ) +end domainspace(P::SymmetricOperator)=domainspace(P.op) rangespace(P::SymmetricOperator)=rangespace(P.op) @@ -74,7 +86,10 @@ struct AdjointOperator{T<:Number,B<:Operator} <: Operator{T} end AdjointOperator(B::Operator{T}) where {T<:Number}=AdjointOperator{T,typeof(B)}(B) -convert(::Type{Operator{T}},A::AdjointOperator) where {T}=AdjointOperator(strictconvert(Operator{T},A.op)) +Operator{T}(A::AdjointOperator) where {T}=AdjointOperator(strictconvert(Operator{T},A.op)) +function AdjointOperator{T,B}(A::AdjointOperator) where {T<:Number,B<:Operator} + AdjointOperator{T,B}(strictconvert(B, A.op)) +end domainspace(P::AdjointOperator)=rangespace(P.op) rangespace(P::AdjointOperator)=domainspace(P.op) @@ -97,7 +112,10 @@ struct TransposeOperator{T<:Number,B<:Operator} <: Operator{T} end TransposeOperator(B::Operator{T}) where {T<:Number}=TransposeOperator{T,typeof(B)}(B) -convert(::Type{Operator{T}},A::TransposeOperator) where {T}=TransposeOperator(strictconvert(Operator{T},A.op)) +Operator{T}(A::TransposeOperator) where {T}=TransposeOperator(strictconvert(Operator{T},A.op)) +function TransposeOperator{T,B}(A::TransposeOperator) where {T<:Number,B<:Operator} + TransposeOperator{T,B}(strictconvert(B, A.op)) +end domainspace(P::TransposeOperator)=rangespace(P.op) rangespace(P::TransposeOperator)=domainspace(P.op) diff --git a/src/Operators/general/PartialInverseOperator.jl b/src/Operators/general/PartialInverseOperator.jl index f278e61a..ab06f596 100644 --- a/src/Operators/general/PartialInverseOperator.jl +++ b/src/Operators/general/PartialInverseOperator.jl @@ -62,8 +62,14 @@ function PartialInverseOperator(B::Operator, bandwidths = bandwidths(B)) PartialInverseOperator(cache(B), bandwidths) end -convert(::Type{Operator{T}},A::PartialInverseOperator) where {T} = +Operator{T}(A::PartialInverseOperator) where {T} = PartialInverseOperator(strictconvert(Operator{T},A.cache), A.bandwidths) +function PartialInverseOperator{T,CO,BI}(P::PartialInverseOperator) where {T<:Number,CO<:CachedOperator,BI<:Tuple{Any,Any}} + PartialInverseOperator{T,CO,BI}( + strictconvert(CO, P.cache), + strictconvert(BI, P.bandwidths), + ) +end domainspace(P::PartialInverseOperator)=rangespace(P.cache) rangespace(P::PartialInverseOperator)=domainspace(P.cache) diff --git a/src/Operators/general/ReImSpace.jl b/src/Operators/general/ReImSpace.jl index fd7719de..84d2ec1f 100644 --- a/src/Operators/general/ReImSpace.jl +++ b/src/Operators/general/ReImSpace.jl @@ -4,7 +4,10 @@ struct ReOperator{O,T} <: Operator{T} end ReOperator(op)=ReOperator{typeof(op),real(eltype(op))}(op) -convert(::Type{Operator{T}},R::ReOperator) where {T} = ReOperator{typeof(R.op),T}(R.op) +Operator{T}(R::ReOperator) where {T} = ReOperator{typeof(R.op),T}(R.op) +function ReOperator{O,T}(R::ReOperator) where {O,T} + ReOperator{O,T}(strictconvert(O, R.op)) +end @wrapperstructure ReOperator @wrapperspaces ReOperator diff --git a/src/Operators/general/algebra.jl b/src/Operators/general/algebra.jl index f27649a4..177ab748 100644 --- a/src/Operators/general/algebra.jl +++ b/src/Operators/general/algebra.jl @@ -21,6 +21,18 @@ struct PlusOperator{T,BW,SZ,O<:Operator{T},BBW,SBBW} <: Operator{T} end end +function PlusOperator{T,BW,SZ,O,BBW,SBBW}(P::PlusOperator) where {T,BW,SZ,O<:Operator{T},BBW,SBBW} + PlusOperator{T,BW,SZ,O,BBW,SBBW}( + strictconvert(Vector{O}, P.ops), + strictconvert(BW, P.bandwidths), + strictconvert(SZ, P.sz), + strictconvert(BBW, P.blockbandwidths), + strictconvert(SBBW, P.subblockbandwidths), + P.isbandedblockbanded, + P.israggedbelow, + ) +end + bandwidthsmax(ops, f=bandwidths) = mapreduce(f, (t1, t2) -> max.(t1, t2), ops, init=(-720, -720)) #= approximate (-∞,-∞) =# function PlusOperator(ops::Vector{O}, args...) where {O<:Operator} @@ -56,17 +68,13 @@ _convertops(::Type{Operator{T}}, ops) where {T} = map(x -> strictconvert(Operator{T}, x), ops) _convertops(::Type{Operator{T}}, ops::Vector{Operator{S}}) where {T,S} = Operator{T}[strictconvert(Operator{T}, op) for op in ops] -function convert(::Type{Operator{T}}, P::PlusOperator) where {T} - if T == eltype(P) - P - else - ops = P.ops - PlusOperator(eltype(ops) <: Operator{T} ? ops : - _convertops(Operator{T}, ops), - bandwidths(P), size(P), blockbandwidths(P), - subblockbandwidths(P), isbandedblockbanded(P), - israggedbelow(P))::Operator{T} - end +function Operator{T}(P::PlusOperator) where {T} + ops = P.ops + PlusOperator(eltype(ops) <: Operator{T} ? ops : + _convertops(Operator{T}, ops), + bandwidths(P), size(P), blockbandwidths(P), + subblockbandwidths(P), isbandedblockbanded(P), + israggedbelow(P))::Operator{T} end function promoteplus(opsin, sz=size(first(opsin))) @@ -188,14 +196,15 @@ for OP in (:promotedomainspace, :promoterangespace), SP in (:UnsetSpace, :Space) @eval $OP(C::ConstantTimesOperator, k::$SP) = ConstantTimesOperator(C.λ, $OP(C.op, k)) end - -function convert(::Type{Operator{T}}, C::ConstantTimesOperator) where {T} - if T == eltype(C) - C - else - op = strictconvert(Operator{T}, C.op) - ConstantTimesOperator(T(C.λ)::T, op)::Operator{T} - end +function ConstantTimesOperator{T,B}(C::ConstantTimesOperator) where {T<:Number,B<:Operator{T}} + ConstantTimesOperator{T,B}( + strictconvert(T, C.λ), + strictconvert(B, C.op), + ) +end +function Operator{T}(C::ConstantTimesOperator) where {T} + op = strictconvert(Operator{T}, C.op) + ConstantTimesOperator(T(C.λ)::T, op)::Operator{T} end getindex(P::ConstantTimesOperator, k::Integer...) = @@ -256,6 +265,18 @@ struct TimesOperator{T,BW,SZ,O<:Operator{T},BBW,SBBW} <: Operator{T} end end +function TimesOperator{T,BW,SZ,O,BBW,SBBW}(TO::TimesOperator) where {T,BW,SZ,O<:Operator{T},BBW,SBBW} + TimesOperator{T,BW,SZ,O,BBW,SBBW}( + strictconvert(Vector{O}, TO.ops), + strictconvert(BW, TO.bandwidths), + strictconvert(SZ, TO.sz), + strictconvert(BBW, TO.blockbandwidths), + strictconvert(SBBW, TO.subblockbandwidths), + TO.isbandedblockbanded, + TO.israggedbelow, + ) +end + const PlusOrTimesOp = Union{PlusOperator,TimesOperator} bandwidthssum(P, f=bandwidths) = mapreduce(f, (t1, t2) -> t1 .+ t2, P, init=(0, 0)) @@ -292,17 +313,13 @@ end ==(A::TimesOperator, B::TimesOperator) = A.ops == B.ops -function convert(::Type{Operator{T}}, P::TimesOperator) where {T} - if T == eltype(P) - P - else - ops = P.ops - TimesOperator(eltype(ops) <: Operator{T} ? ops : - _convertops(Operator{T}, ops), - bandwidths(P), size(P), blockbandwidths(P), - subblockbandwidths(P), isbandedblockbanded(P), - israggedbelow(P))::Operator{T} - end +function Operator{T}(P::TimesOperator) where {T} + ops = P.ops + TimesOperator(eltype(ops) <: Operator{T} ? ops : + _convertops(Operator{T}, ops), + bandwidths(P), size(P), blockbandwidths(P), + subblockbandwidths(P), isbandedblockbanded(P), + israggedbelow(P))::Operator{T} end diff --git a/src/Operators/qr.jl b/src/Operators/qr.jl index aeaf84c9..bfae2907 100644 --- a/src/Operators/qr.jl +++ b/src/Operators/qr.jl @@ -7,8 +7,14 @@ end QROperator(R::CachedOperator,H::AbstractArray,ncs::Int) = QROperator{typeof(R),typeof(H),eltype(H)}(R,H,ncs) - -convert(::Type{Operator{T}},QR::QROperator) where {T} = +function QROperator{CO,MT,T}(Q::QROperator) where {CO,MT,T} + QROperator{CO,MT,T}( + strictconvert(CO, Q.R_cache), + strictconvert(MT, Q.H), + Q.ncols, + ) +end +Operator{T}(QR::QROperator) where {T} = QROperator(strictconvert(Operator{T},QR.R_cache), strictconvert(AbstractArray{T}, QR.H),QR.ncols) qr(QR::QROperator) = QR diff --git a/src/Operators/spacepromotion.jl b/src/Operators/spacepromotion.jl index 431dbb05..bbad958e 100644 --- a/src/Operators/spacepromotion.jl +++ b/src/Operators/spacepromotion.jl @@ -33,15 +33,17 @@ SpaceOperator(o::Operator,s::Space,rs::Space) = SpaceOperator{typeof(o),typeof(s),typeof(rs),eltype(o)}(o,s,rs) SpaceOperator(o,s) = SpaceOperator(o,s,s) -function convert(::Type{Operator{T}},S::SpaceOperator) where T - if T==eltype(S) - S - else - op=strictconvert(Operator{T},S.op) - SpaceOperator{typeof(op),typeof(S.domainspace),typeof(S.rangespace),T}(op,S.domainspace,S.rangespace) - end +function Operator{T}(S::SpaceOperator) where T + op=strictconvert(Operator{T},S.op) + SpaceOperator{typeof(op),typeof(S.domainspace),typeof(S.rangespace),T}(op,S.domainspace,S.rangespace) +end +function SpaceOperator{O,S,V,T}(J::SpaceOperator) where {O<:Operator,S<:Space,V<:Space,T} + SpaceOperator{O,S,V,T}( + strictconvert(O, J.op), + strictconvert(S, J.domainspace), + strictconvert(V, J.rangespace), + ) end - # Similar to wrapper, but different domain/domainspace/rangespace diff --git a/src/PDE/KroneckerOperator.jl b/src/PDE/KroneckerOperator.jl index 635fc996..d998cd37 100644 --- a/src/PDE/KroneckerOperator.jl +++ b/src/PDE/KroneckerOperator.jl @@ -51,18 +51,22 @@ function promoterangespace(K::KroneckerOperator,rs::TensorSpace) KroneckerOperator(A,B,domainspace(K),rs) end - -function convert(::Type{Operator{T}},K::KroneckerOperator) where T<:Number - if T == eltype(K) - K - else - ops = map(Operator{T}, K.ops) - KroneckerOperator{map(typeof, ops)..., - typeof(K.domainspace),typeof(K.rangespace), - typeof(K.domaintensorizer),typeof(K.rangetensorizer),T}(ops, - K.domainspace,K.rangespace, - K.domaintensorizer,K.rangetensorizer)::Operator{T} - end +function KroneckerOperator{S,V,DS,RS,DI,RI,T}(K::KroneckerOperator) where {S,V,DS,RS,DI,RI,T} + KroneckerOperator{S,V,DS,RS,DI,RI,T}( + strictconvert(Tuple{S,V}, K.ops), + strictconvert(DS, K.domainspace), + strictconvert(RS, K.rangespace), + strictconvert(DI, K.domaintensorizer), + strictconvert(RI, K.rangetensorizer), + ) +end +function Operator{T}(K::KroneckerOperator) where T<:Number + ops = map(Operator{T}, K.ops) + KroneckerOperator{map(typeof, ops)..., + typeof(K.domainspace),typeof(K.rangespace), + typeof(K.domaintensorizer),typeof(K.rangetensorizer),T}(ops, + K.domainspace,K.rangespace, + K.domaintensorizer,K.rangetensorizer)::Operator{T} end diff --git a/src/Spaces/ArraySpace.jl b/src/Spaces/ArraySpace.jl index b084663b..22238900 100644 --- a/src/Spaces/ArraySpace.jl +++ b/src/Spaces/ArraySpace.jl @@ -26,6 +26,10 @@ ArraySpace(S::Space,n::Integer) = ArraySpace(S,(n,)) ArraySpace(S::Space,n,m) = ArraySpace(S,(n,m)) ArraySpace(d::Domain,n...) = ArraySpace(Space(d),n...) +function ArraySpace{S,n,DD,RR,A}(B::ArraySpace) where {S,n,DD,RR,A<:AbstractArray{S,n}} + ArraySpace{S,n,DD,RR,A}(strictconvert(A, B.spaces)) +end + Space(sp::AbstractArray{<:Space}) = ArraySpace(sp) convert(::Type{A}, sp::ArraySpace) where {A<:Array} = convert(A, sp.spaces)::A (::Type{A})(sp::ArraySpace) where {A<:Array} = A(sp.spaces) diff --git a/src/Spaces/ContinuousSpace.jl b/src/Spaces/ContinuousSpace.jl index e7066c15..6e75e6d0 100644 --- a/src/Spaces/ContinuousSpace.jl +++ b/src/Spaces/ContinuousSpace.jl @@ -2,6 +2,10 @@ struct ContinuousSpace{T,R,P<:PiecewiseSegment{T}} <: Space{P,R} domain::P end +function ContinuousSpace{T,R,P}(C::ContinuousSpace) where {T,R,P<:PiecewiseSegment{T}} + ContinuousSpace{T,R,P}(strictconvert(P, C.domain)) +end + ContinuousSpace(d::PiecewiseSegment{T}) where {T} = ContinuousSpace{T,real(eltype(T)),typeof(d)}(d) diff --git a/src/Spaces/DiracSpace.jl b/src/Spaces/DiracSpace.jl index 518d2bde..2d8c1c52 100644 --- a/src/Spaces/DiracSpace.jl +++ b/src/Spaces/DiracSpace.jl @@ -7,6 +7,10 @@ for TYP in (:DiracSpace,:PointSpace) $TYP{T,D,R}(pts::AbstractVector{T}) where {T,D,R} = new(sort(pts)) end + function $TYP{T,D,R}(x::$TYP) where {T,D,R} + $TYP{T,D,R}(strictconvert(Vector{T}, x.points)) + end + function $TYP(points::AbstractVector{T}) where T $TYP{eltype(points),UnionDomain{Vector{Point{T}},Point{T}},real(T)}(points) end diff --git a/src/Spaces/HeavisideSpace.jl b/src/Spaces/HeavisideSpace.jl index 29fa4a16..be375d2a 100644 --- a/src/Spaces/HeavisideSpace.jl +++ b/src/Spaces/HeavisideSpace.jl @@ -3,6 +3,10 @@ struct SplineSpace{order,T,R,P<:PiecewiseSegment} <: Space{P,R} domain::P end +function SplineSpace{order,T,R,P}(S::SplineSpace) where {order,T,R,P<:PiecewiseSegment} + SplineSpace{order,T,R,P}(strictconvert(P, S.domain)) +end + SplineSpace{m,T,R}(d::PiecewiseSegment{T}) where {m,T,R} = SplineSpace{m,T,R,typeof(d)}(d) SplineSpace{m,T}(d::PiecewiseSegment{T}) where {m,T} = SplineSpace{m,T,real(eltype(T))}(d) diff --git a/src/Spaces/QuotientSpace.jl b/src/Spaces/QuotientSpace.jl index cacc8fcd..aaa9913b 100644 --- a/src/Spaces/QuotientSpace.jl +++ b/src/Spaces/QuotientSpace.jl @@ -14,6 +14,15 @@ struct QuotientSpace{S,O,D,R} <: Space{D,R} end end +function QuotientSpace{S,O,D,R}(Q::QuotientSpace) where {S,O,D,R} + QuotientSpace{S,O,D,R}( + strictconvert(S, Q.space), + strictconvert(O, Q.bcs), + strictconvert(LU{R,Matrix{R}}, Q.F), + strictconvert(Vector{R}, Q.x), + ) +end + QuotientSpace(sp::Space{D,R}, bcs::Operator{T}) where {D,R,T} = QuotientSpace{typeof(sp), typeof(bcs), D, promote_type(R, T)}(sp, bcs) QuotientSpace(bcs::Operator) = QuotientSpace(domainspace(bcs), bcs) @@ -148,6 +157,24 @@ struct PathologicalQuotientSpace{S,O<:Operator,DD,T,RT} <: Space{DD,T} end end +function PathologicalQuotientSpace{S,O,DD,T,RT}(P::PathologicalQuotientSpace) where {S,O<:Operator,DD,T,RT} + PathologicalQuotientSpace{S,O,DD,T,RT}( + strictconvert(S, P.space), + strictconvert(O, P.bcs), + strictconvert(Matrix{T}, P.A), + strictconvert(Vector{T}, P.x), + strictconvert(Vector{T}, P.b), + strictconvert(Vector{T}, P.c), + strictconvert(Matrix{T}, P.U), + strictconvert(Diagonal{T,Vector{T}}, P.Σ), + strictconvert(Matrix{T}, P.VT), + strictconvert(Vector{T}, P.work), + strictconvert(Vector{BlasInt}, P.iwork), + strictconvert(Vector{RT}, P.rwork), + strictconvert(Ref{BlasInt}, P.info), + ) +end + PathologicalQuotientSpace(sp::Space, bcs::Operator) = PathologicalQuotientSpace{typeof(sp), typeof(bcs), domaintype(sp), rangetype(sp), real(rangetype(sp))}(sp, bcs) PathologicalQuotientSpace(bcs::Operator) = PathologicalQuotientSpace(domainspace(bcs), bcs) diff --git a/src/Spaces/SubSpace.jl b/src/Spaces/SubSpace.jl index ae767a56..05d31521 100644 --- a/src/Spaces/SubSpace.jl +++ b/src/Spaces/SubSpace.jl @@ -1,10 +1,16 @@ - struct SubSpace{DS,IT,DD,RR} <: Space{DD,RR} space::DS indexes::IT SubSpace{DS,IT,DD,RR}(sp::DS,ind::IT) where {DS,IT,DD,RR} = new(sp,ind) end +function SubSpace{DS,IT,DD,RR}(S::SubSpace) where {DS,IT,DD,RR} + SubSpace{DS,IT,DD,RR}( + strictconvert(DS, S.space), + strictconvert(IT, S.indexes), + ) +end + SubSpace(sp::Space,kr) = SubSpace{typeof(sp),typeof(kr),domaintype(sp),rangetype(sp)}(sp,kr) diff --git a/src/Spaces/SumSpace.jl b/src/Spaces/SumSpace.jl index c44198a5..f6985587 100644 --- a/src/Spaces/SumSpace.jl +++ b/src/Spaces/SumSpace.jl @@ -51,6 +51,10 @@ SumSpace(sp::Tuple) = SumSpace{typeof(sp),domaintype(first(sp)), mapreduce(rangetype,promote_type,sp)}(sp) +function SumSpace{SV,D,R}(S::SumSpace) where {SV,D,R} + SumSpace{SV,D,R}(strictconvert(SV, S.spaces)) +end + struct PiecewiseSpace{SV,D<:UnionDomain,R} <: DirectSumSpace{SV,D,R} spaces::SV PiecewiseSpace{SV,D,R}(dom::AnyDomain) where {SV,D,R} = @@ -72,7 +76,9 @@ end PiecewiseSpace(spin::Set) = PiecewiseSpace(collect(spin)) - +function PiecewiseSpace{SV,D,R}(P::PiecewiseSpace) where {SV,D<:UnionDomain,R} + PiecewiseSpace{SV,D,R}(strictconvert(SV, P.spaces)) +end for TYP in (:SumSpace,:PiecewiseSpace) @eval begin diff --git a/src/onehotvector.jl b/src/onehotvector.jl index 5435a351..7ce4b3fd 100644 --- a/src/onehotvector.jl +++ b/src/onehotvector.jl @@ -8,6 +8,7 @@ struct OneHotVector{T} <: AbstractVector{T} new{T}(n, len) end end +OneHotVector{T}(v::OneHotVector) where {T} = OneHotVector{T}(v.n, v.len) OneHotVector(n, len = n) = OneHotVector{Float64}(n, len) Base.size(v::OneHotVector) = (v.len,) Base.length(v::OneHotVector) = v.len diff --git a/test/runtests.jl b/test/runtests.jl index f2a484ca..a11238f7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -359,6 +359,62 @@ end ApproxFunBase.mul_coefficients!(Operator(2I), v) @test v ≈ Float64[2i^2 for i in 1:4] end + @testset "type parameter conversion" begin + psp = PointSpace(1:3) + psp2 = PointSpace(2:4) + function test_trivial_constructor_identity(C) + @test typeof(C)(C) == C + EC = Complex{eltype(C)} + O = Operator{EC}(C) + @test typeof(O)(O) == O + @test eltype(O) == EC + end + M = Multiplication(Fun(psp), psp) + for op in Any[ + Conversion(psp, psp), + M, + real(M), + PlusOperator([M,M]), + TimesOperator([M,M]), + 2M, + ApproxFunBase.SpaceOperator(M, psp2, psp2), + M ⊗ M, + view(M, 1:3, 1:3), + [M; M], + ApproxFunBase.HermitianOperator(M), + ApproxFunBase.SymmetricOperator(M), + M', + transpose(M), + Operator(2I, psp), + ApproxFunBase.ToeplitzOperator([1,2], [2,3]), + ApproxFunBase.HankelOperator([1,2,3]), + ApproxFunBase.PermutationOperator([2,1]), + ApproxFunBase.NegateEven(), + OperatorFunction(Multiplication(Fun(psp), psp), Fun(x -> x^2, psp)), + ] + + test_trivial_constructor_identity(op) + end + + function test_fields(Q) + Q2 = typeof(Q)(Q) + # For some reason (perhaps owing to mutability), this does't satisfy Q == Q2, + # so we check the fields + @test typeof(Q) == typeof(Q2) + @test all(x -> getfield(Q, x) === getfield(Q2, x), fieldnames(typeof(Q))) + EC = Complex{eltype(Q)} + QC = Operator{EC}(Q) + @test eltype(QC) == EC + end + + for op in Any[ + qr(M), + cache(M), + ] + + test_fields(op) + end + end end @testset "RowVector" begin