|
| 1 | +struct ContinuousSpace{T,R,P<:PiecewiseSegment{T}} <: Space{P,R} |
| 2 | + domain::P |
| 3 | +end |
| 4 | + |
| 5 | +ContinuousSpace(d::PiecewiseSegment{T}) where {T} = |
| 6 | + ContinuousSpace{T,real(eltype(T)),typeof(d)}(d) |
| 7 | + |
| 8 | +# This should be uncommented when ApproxFunOrthogonalPolynomials |
| 9 | +# uses ContinuousSpace from this package |
| 10 | +# Space(d::PiecewiseSegment) = ContinuousSpace(d) |
| 11 | + |
| 12 | +isperiodic(C::ContinuousSpace) = isperiodic(domain(C)) |
| 13 | + |
| 14 | +spacescompatible(a::ContinuousSpace, b::ContinuousSpace) = domainscompatible(a,b) |
| 15 | + |
| 16 | +plan_transform(sp::ContinuousSpace, vals::AbstractVector) = |
| 17 | + TransformPlan{eltype(vals),typeof(sp),false,Nothing}(sp,nothing) |
| 18 | + |
| 19 | +function *(P::TransformPlan{T,<:ContinuousSpace,false}, vals::AbstractVector{T}) where {T} |
| 20 | + S = P.space |
| 21 | + n=length(vals) |
| 22 | + d=domain(S) |
| 23 | + K=ncomponents(d) |
| 24 | + k=div(n,K) |
| 25 | + |
| 26 | + PT=promote_type(prectype(d),eltype(vals)) |
| 27 | + if k==0 |
| 28 | + vals |
| 29 | + elseif isperiodic(d) |
| 30 | + ret=Array{PT}(undef, max(K,n-K)) |
| 31 | + r=n-K*k |
| 32 | + |
| 33 | + for j=1:r |
| 34 | + cfs=transform(component(S,j), vals[(j-1)*(k+1)+1:j*(k+1)]) |
| 35 | + if j==1 |
| 36 | + ret[1]=cfs[1]-cfs[2] |
| 37 | + ret[2]=cfs[1]+cfs[2] |
| 38 | + elseif j < K |
| 39 | + ret[j+1]=cfs[1]+cfs[2] |
| 40 | + end |
| 41 | + ret[K+j:K:end]=cfs[3:end] |
| 42 | + end |
| 43 | + |
| 44 | + for j=r+1:K |
| 45 | + cfs=transform(component(S,j), vals[r*(k+1)+(j-r-1)*k+1:r*(k+1)+(j-r)*k]) |
| 46 | + if length(cfs)==1 && j <K |
| 47 | + ret[j+1]=cfs[1] |
| 48 | + elseif j==1 |
| 49 | + ret[1]=cfs[1]-cfs[2] |
| 50 | + ret[2]=cfs[1]+cfs[2] |
| 51 | + elseif j < K |
| 52 | + ret[j+1]=cfs[1]+cfs[2] |
| 53 | + end |
| 54 | + ret[K+j:K:end]=cfs[3:end] |
| 55 | + end |
| 56 | + |
| 57 | + ret |
| 58 | + else |
| 59 | + ret=Array{PT}(undef, n-K+1) |
| 60 | + r=n-K*k |
| 61 | + |
| 62 | + for j=1:r |
| 63 | + cfs=transform(component(S,j), vals[(j-1)*(k+1)+1:j*(k+1)]) |
| 64 | + if j==1 |
| 65 | + ret[1]=cfs[1]-cfs[2] |
| 66 | + end |
| 67 | + |
| 68 | + ret[j+1]=cfs[1]+cfs[2] |
| 69 | + ret[K+j+1:K:end]=cfs[3:end] |
| 70 | + end |
| 71 | + |
| 72 | + for j=r+1:K |
| 73 | + cfs=transform(component(S,j), vals[r*(k+1)+(j-r-1)*k+1:r*(k+1)+(j-r)*k]) |
| 74 | + |
| 75 | + if length(cfs) ≤ 1 |
| 76 | + ret .= cfs |
| 77 | + else |
| 78 | + if j==1 |
| 79 | + ret[1]=cfs[1]-cfs[2] |
| 80 | + end |
| 81 | + ret[j+1]=cfs[1]+cfs[2] |
| 82 | + ret[K+j+1:K:end]=cfs[3:end] |
| 83 | + end |
| 84 | + end |
| 85 | + |
| 86 | + ret |
| 87 | + end |
| 88 | +end |
| 89 | + |
| 90 | +canonicalspace(S::ContinuousSpace) = PiecewiseSpace(components(S)) |
| 91 | +convert(::Type{PiecewiseSpace}, S::ContinuousSpace) = canonicalspace(S) |
| 92 | + |
| 93 | +blocklengths(C::ContinuousSpace) = Fill(ncomponents(C.domain),∞) |
| 94 | + |
| 95 | +block(C::ContinuousSpace,k) = Block((k-1)÷ncomponents(C.domain)+1) |
| 96 | + |
| 97 | + |
| 98 | +## components |
| 99 | + |
| 100 | +components(f::Fun{<:ContinuousSpace},j::Integer) = components(Fun(f,canonicalspace(f)),j) |
| 101 | +components(f::Fun{<:ContinuousSpace}) = components(Fun(f,canonicalspace(space(f)))) |
| 102 | + |
| 103 | + |
| 104 | +function points(f::Fun{<:ContinuousSpace}) |
| 105 | + n=ncoefficients(f) |
| 106 | + d=domain(f) |
| 107 | + K=ncomponents(d) |
| 108 | + |
| 109 | + m=isperiodic(d) ? max(K,n+2K-1) : n+K |
| 110 | + points(f.space,m) |
| 111 | +end |
| 112 | + |
| 113 | +## Conversion |
| 114 | + |
| 115 | +coefficients(cfsin::AbstractVector,A::ContinuousSpace,B::PiecewiseSpace) = |
| 116 | + defaultcoefficients(cfsin,A,B) |
| 117 | + |
| 118 | +coefficients(cfsin::AbstractVector,A::PiecewiseSpace,B::ContinuousSpace) = |
| 119 | + default_Fun(Fun(A,cfsin),B).coefficients |
| 120 | + |
| 121 | +coefficients(cfsin::AbstractVector,A::ContinuousSpace,B::ContinuousSpace) = |
| 122 | + default_Fun(Fun(A,cfsin),B).coefficients |
| 123 | + |
| 124 | +union_rule(A::PiecewiseSpace, B::ContinuousSpace) = union(A, strictconvert(PiecewiseSpace, B)) |
| 125 | +union_rule(A::ConstantSpace, B::ContinuousSpace) = B |
| 126 | + |
| 127 | +function approx_union(a::AbstractVector{T}, b::AbstractVector{V}) where {T,V} |
| 128 | + ret = sort!(union(a,b)) |
| 129 | + for k in length(ret)-1:-1:1 |
| 130 | + isapprox(ret[k] , ret[k+1]; atol=10eps()) && deleteat!(ret, k+1) |
| 131 | + end |
| 132 | + ret |
| 133 | +end |
| 134 | + |
| 135 | + |
| 136 | +function union_rule(A::ContinuousSpace{<:Real}, B::ContinuousSpace{<:Real}) |
| 137 | + p_A,p_B = domain(A).points, domain(B).points |
| 138 | + a,b = minimum(p_A), maximum(p_A) |
| 139 | + c,d = minimum(p_B), maximum(p_B) |
| 140 | + @assert !isempty((a..b) ∩ (c..d)) |
| 141 | + ContinuousSpace(PiecewiseSegment(approx_union(p_A, p_B))) |
| 142 | +end |
| 143 | + |
| 144 | +function integrate(f::Fun{<:ContinuousSpace}) |
| 145 | + cs = [cumsum(x) for x in components(f)] |
| 146 | + for k=1:length(cs)-1 |
| 147 | + cs[k+1] += last(cs[k]) |
| 148 | + end |
| 149 | + Fun(Fun(cs, PiecewiseSpace), space(f)) |
| 150 | +end |
| 151 | + |
| 152 | +cumsum(f::Fun{<:ContinuousSpace}) = integrate(f) |
0 commit comments