@@ -51,10 +51,113 @@ plan_transform(P::ContinuousPolynomial{0}, szs::NTuple{N,Union{Int,Block{1}}}, d
51
51
for grd in (:grid , :plotgrid )
52
52
@eval begin
53
53
$ grd (C:: ContinuousPolynomial , n:: Block{1} ) = $ grd (PiecewisePolynomial (C), n)
54
- $ grd (C:: ContinuousPolynomial , n:: Int ) = $ grd (PiecewisePolynomial (C ), n)
54
+ $ grd (C:: ContinuousPolynomial , n:: Int ) = $ grd (C, findblock ( axes (C, 2 ), n))
55
55
end
56
56
end
57
57
58
+ struct ContinuousPolynomialTransform{T, Pl<: Plan{T} , RRs, Dims} <: Plan{T}
59
+ legendretransform:: Pl
60
+ R:: RRs
61
+ dims:: Dims
62
+ end
63
+
64
+
65
+
66
+
67
+ function plan_transform (C:: ContinuousPolynomial{1,T} , Ns:: NTuple{N,Block{1}} , dims= ntuple (identity,Val (N))) where {N,T}
68
+ P = Legendre {T} ()
69
+ W = Weighted (Jacobi {T} (1 ,1 ))
70
+ # TODO : this is unnecessarily not triangular which makes it much slower than necessary and prevents in-place.
71
+ # However, the speed of the Legendre transform will far exceed this so its not high priority.
72
+ # Probably using Ultraspherical(-1/2) would be better.
73
+ R̃ = [[T[1 1 ; - 1 1 ]/ 2 ; Zeros {T} (∞,2 )] (P \ W)]
74
+ ContinuousPolynomialTransform (plan_transform (ContinuousPolynomial {0} (C), Ns .+ 1 , dims). F,
75
+ InvPlan (map (N -> R̃[1 : Int (N),1 : Int (N)], Ns .+ 1 ), _doubledims (dims... )),
76
+ dims)
77
+ end
78
+
79
+ _tensorsize2contblocks () = ()
80
+ _tensorsize2contblocks (M,N, Ns... ) = (Vcat (N+ 1 , Fill (N, M- 2 )), _tensorsize2contblocks (Ns... )... )
81
+
82
+
83
+ function * (Pl:: ContinuousPolynomialTransform{T,<:Any,<:Any,Int} , X:: AbstractMatrix{T} ) where T
84
+ dat = Pl. R * (Pl. legendretransform* X)
85
+ cfs = PseudoBlockArray {T} (undef, _tensorsize2contblocks (size (X)... )... )
86
+ dims = Pl. dims
87
+ @assert dims == 1
88
+
89
+ M,N = size (X,1 ), size (X,2 )
90
+ if size (dat,1 ) ≥ 1
91
+ cfs[Block (1 )[1 ]] = dat[1 ,1 ]
92
+ for j = 1 : N- 1
93
+ isapprox (dat[2 ,j], dat[1 ,j+ 1 ]; atol= 1000 * M* eps ()) || throw (ArgumentError (" Discontinuity in data on order of $(abs (dat[2 ,j]- dat[1 ,j+ 1 ])) ." ))
94
+ end
95
+ for j = 1 : N
96
+ cfs[Block (1 )[j+ 1 ]] = dat[2 ,j]
97
+ end
98
+ end
99
+ cfs[Block .(2 : M- 1 )] .= vec (dat[3 : end ,:]' )
100
+ cfs
101
+ end
102
+
103
+ function \ (Pl:: ContinuousPolynomialTransform{T,<:Any,<:Any,Int} , cfs:: AbstractVector{T} ) where T
104
+ dims = Pl. dims
105
+ @assert dims == 1
106
+
107
+ M,N = blocksize (cfs,1 )+ 1 , size (axes (cfs,1 )[Block (1 )],1 )- 1
108
+ dat = Matrix {T} (undef, M, N)
109
+
110
+ if M ≥ 1
111
+ dat[1 ,1 ] = cfs[Block (1 )[1 ]]
112
+ for j = 1 : N- 1
113
+ dat[2 ,j] = dat[1 ,j+ 1 ] = cfs[Block (1 )[j+ 1 ]]
114
+ end
115
+ dat[2 ,end ] = cfs[Block (1 )[N+ 1 ]]
116
+ end
117
+
118
+ for j = 1 : N, k = 3 : M
119
+ dat[k,j] = cfs[Block (k- 1 )[j]]
120
+ end
121
+
122
+ Pl. legendretransform \ (Pl. R \ dat)
123
+ end
124
+
125
+
126
+
127
+ function _contpolyinds2blocks (k, j)
128
+ k == 1 && return Block (1 )[j]
129
+ k == 2 && return Block (1 )[j+ 1 ]
130
+ Block (k- 1 )[j]
131
+ end
132
+ function * (Pl:: ContinuousPolynomialTransform{T} , X:: AbstractArray{T,4} ) where T
133
+ dat = Pl. R * (Pl. legendretransform* X)
134
+ cfs = PseudoBlockArray {T} (undef, _tensorsize2contblocks (size (X)... )... )
135
+ dims = Pl. dims
136
+ @assert dims == (1 ,2 )
137
+
138
+ M,N,O,P = size (X)
139
+ for k = 1 : M, j = 1 : N, l = 1 : O, m = 1 : P
140
+ cfs[_contpolyinds2blocks (k,j), _contpolyinds2blocks (l,m)] = dat[k,j,l,m]
141
+ end
142
+ cfs
143
+ end
144
+
145
+ function \ (Pl:: ContinuousPolynomialTransform{T} , cfs:: AbstractMatrix{T} ) where T
146
+ M,N = blocksize (cfs,1 )+ 1 , size (axes (cfs,1 )[Block (1 )],1 )- 1
147
+ O,P = blocksize (cfs,2 )+ 1 , size (axes (cfs,2 )[Block (1 )],1 )- 1
148
+
149
+ dat = Array {T} (undef, M, N, O, P)
150
+ dims = Pl. dims
151
+ @assert dims == (1 ,2 )
152
+
153
+ for k = 1 : M, j = 1 : N, l = 1 : O, m = 1 : P
154
+ dat[k,j,l,m] = cfs[_contpolyinds2blocks (k,j), _contpolyinds2blocks (l,m)]
155
+ end
156
+
157
+ Pl. legendretransform \ (Pl. R \ dat)
158
+ end
159
+
160
+
58
161
function adaptivetransform_ldiv (Q:: ContinuousPolynomial{1,V} , f:: AbstractQuasiVector ) where V
59
162
T = promote_type (V, eltype (f))
60
163
C₀ = ContinuousPolynomial {0,V} (Q)
88
191
adaptivetransform_ldiv (Q:: ContinuousPolynomial{1,V} , f:: AbstractQuasiMatrix ) where V =
89
192
BlockBroadcastArray (hcat, (Q \ f[:,j] for j = axes (f,2 )). .. )
90
193
91
- function grid (V:: SubQuasiArray{T,2,<:ContinuousPolynomial{1},<:Tuple{Inclusion,BlockSlice}} ) where {T}
92
- P = parent (V)
93
- _, JR = parentindices (V)
94
- pts = P. points
95
- grid (view (PiecewisePolynomial (Weighted (Jacobi {T} (1 , 1 )), pts), :, JR))
96
- end
194
+ grid (P:: ContinuousPolynomial{1} , M:: Block{1} ) = grid (ContinuousPolynomial {0} (P), M + 1 )
97
195
98
196
# ######
99
197
# Conversion
0 commit comments