@@ -11,11 +11,27 @@ spacescompatible(::ZernikeDisk, ::ZernikeDisk) = true
11
11
12
12
@containsconstants ZernikeDisk
13
13
14
- points (K:: ZernikeDisk , n:: Integer ) =
15
- fromcanonical .(Ref (K), points (ChebyshevDisk (), n))
14
+ # M = 2N-1
15
+ # N*M == 2N^2 -N == n
16
+ # N = (1 + sqrt(1 + 8n)/4)
17
+ function points (d:: ZernikeDisk , n)
18
+ a,b = rectspace (ZernikeDisk ()). spaces
19
+ pts= Array {float(eltype(domain(d)))} (undef,0 )
20
+ N = (1 + isqrt (1 + 8 n)) ÷ 4
21
+ M = 2 N- 1
22
+
23
+ for y in points (b,M),
24
+ x in points (a,N)
25
+ push! (pts,polar (Vec (x... ,y... )))
26
+ end
27
+ pts
28
+ end
16
29
17
- evaluate (cfs:: AbstractVector , Z:: ZernikeDisk , xy) =
18
- Fun (Fun (Z, cfs), ChebyshevDisk ())(xy)
30
+ function evaluate (cfs:: AbstractVector , Z:: ZernikeDisk , xy)
31
+ C = totensor (ZernikeDisk (), cfs)
32
+ F = _coefficients (CDisk2CxfPlan (size (C,1 )), C, ZernikeDisk (), ChebyshevDisk ())
33
+ ProductFun (icheckerboard (F), rectspace (ChebyshevDisk ()))(ipolar (xy... )... )
34
+ end
19
35
20
36
Space (d:: Disk ) = ZernikeDisk (d)
21
37
@@ -37,9 +53,42 @@ function points(S::ChebyshevDisk, N)
37
53
polar .(pts)
38
54
end
39
55
40
- DiskTensorizer () = Tensorizer ((Ones {Int} (∞),Ones {Int} (∞)))
56
+ struct DiskTensorizer end
57
+
58
+ function fromtensor (:: DiskTensorizer , A:: AbstractMatrix{T} ) where T
59
+ N = size (A,1 )
60
+ M = 4 (N- 1 )+ 1
61
+ @assert size (A,2 ) == M
62
+ B = PseudoBlockArray (A, Ones {Int} (N), [1 ; Fill (2 ,2 * (N- 1 ))])
63
+ a = Vector {T} ()
64
+ for N = 1 : nblocks (B,2 ), K= 1 : (N+ 1 )÷ 2
65
+ append! (a, vec (view (B,Block (K,N- 2 K+ 2 ))))
66
+ end
67
+ a
68
+ end
69
+
70
+ # N + 4 * sum(1:N-1)
71
+ # N + 4 * N (N-1)/2 == n
72
+ function totensor (:: DiskTensorizer , a:: AbstractVector{T} ) where T
73
+ n = length (a)
74
+ N = round (Int,1 / 4 * (1 + sqrt (1 + 8 n)),RoundUp)
75
+ M = 4 * (N- 1 )+ 1
76
+ Ã = zeros (eltype (a), N, M)
77
+ B = PseudoBlockArray (Ã, Ones {Int} (N), [1 ; Fill (2 ,2 * (N- 1 ))])
78
+ k = 1
79
+ for N = 1 : nblocks (B,2 ), K= 1 : (N+ 1 )÷ 2
80
+ V = view (B, Block (K,N- 2 K+ 2 ))
81
+ for j = 1 : length (V)
82
+ V[j] = a[k]
83
+ k += 1
84
+ k > length (a) && return Ã
85
+ end
86
+ end
87
+ Ã
88
+ end
41
89
42
- tensorizer (K:: ChebyshevDisk ) = DiskTensorizer ()
90
+ tensorizer (K:: ZernikeDisk ) = DiskTensorizer ()
91
+ tensorizer (K:: ChebyshevDisk ) = Tensorizer ((Ones {Int} (∞),Ones {Int} (∞)))
43
92
44
93
# we have each polynomial
45
94
blocklengths (K:: ChebyshevDisk ) = Base. OneTo (∞)
@@ -61,7 +110,11 @@ plan_itransform(S::ChebyshevDisk, n::AbstractVector) =
61
110
# drop every other entry
62
111
function checkerboard (A:: AbstractMatrix{T} ) where T
63
112
m,n = size (A)
64
- C = zeros (T, (m+ 1 )÷ 2 , n)
113
+ # 4(N-1) == n-1
114
+ N = (n- 1 )÷ 4 + 1
115
+ 4 (N- 1 )+ 1 == n || (N += 1 ) # round up
116
+ M = 4 (N- 1 )+ 1
117
+ C = zeros (T, N, M)
65
118
z = @view (A[1 : 2 : end ,1 ])
66
119
e1,e2 = @view (A[1 : 2 : end ,4 : 4 : end ]),@view (A[1 : 2 : end ,5 : 4 : end ])
67
120
o1,o2 = @view (A[2 : 2 : end ,2 : 4 : end ]),@view (A[2 : 2 : end ,3 : 4 : end ])
@@ -95,64 +148,68 @@ evaluate(cfs::AbstractVector, S::ChebyshevDisk, x) = evaluate(torectcfs(S,cfs),
95
148
96
149
function _coefficients (disk2cxf, v̂:: AbstractVector{T} , :: ChebyshevDisk , :: ZernikeDisk ) where T
97
150
F = totensor (ChebyshevDisk (), v̂)
98
- F *= sqrt (convert (T,π))
99
- n = size (F,1 )
151
+ n = disk2cxf. n
100
152
F̌ = disk2cxf \ pad (F,n,4 n- 3 )
101
- trivec ( F̌)
153
+ fromtensor ( ZernikeDisk (), F̌)
102
154
end
103
155
104
- function _coefficients (disk2cxf, v:: AbstractVector{T} , :: ZernikeDisk , :: ChebyshevDisk ) where T
105
- F̌ = tridevec (v)
106
- n = size (F̌,1 )
107
- F = disk2cxf * pad (F̌,n,4 n- 3 )
108
- F /= sqrt (convert (T,π))
109
- fromtensor (ChebyshevDisk (), F)
156
+ function _coefficients (disk2cxf, F̌:: AbstractMatrix{T} , :: ZernikeDisk , :: ChebyshevDisk ) where T
157
+ n = disk2cxf. n
158
+ disk2cxf * pad (F̌,n,4 n- 3 )
110
159
end
111
160
161
+ _coefficients (disk2cxf, v:: AbstractVector{T} , :: ZernikeDisk , :: ChebyshevDisk ) where T =
162
+ fromtensor (ChebyshevDisk (), _coefficients (disk2cxf, totensor (ZernikeDisk (), v), ZernikeDisk (), ChebyshevDisk ()))
163
+
112
164
function coefficients (cfs:: AbstractVector , CD:: ChebyshevDisk , ZD:: ZernikeDisk )
113
165
c = totensor (ChebyshevDisk (), cfs) # TODO : wasteful
114
166
n = size (c,1 )
115
167
_coefficients (CDisk2CxfPlan (n), cfs, CD, ZD)
116
168
end
117
169
118
170
function coefficients (cfs:: AbstractVector , ZD:: ZernikeDisk , CD:: ChebyshevDisk )
119
- c = tridevec ( cfs) # TODO : wasteful
171
+ c = totensor ( ZernikeDisk (), cfs) # TODO : wasteful
120
172
n = size (c,1 )
121
173
_coefficients (CDisk2CxfPlan (n), cfs, ZD, CD)
122
174
end
123
175
124
176
125
- struct FastZernikeDiskTransformPlan {DUF,CHEB}
177
+ struct ZernikeDiskTransformPlan {DUF,CHEB}
126
178
cxfplan:: DUF
127
179
disk2cxf:: CHEB
128
180
end
129
181
130
- function FastZernikeDiskTransformPlan (S:: ZernikeDisk , v:: AbstractVector{T} ) where T
131
- # n = floor(Integer,sqrt(2length(v)) + 1/2)
132
- # v = Array{T}(undef, sum(1:n))
133
- cxfplan = plan_transform (ChebyshevDisk (),v)
134
- c = totensor (ChebyshevDisk (), cxfplan* v) # TODO : wasteful
135
- n = size (c,1 )
136
- FastZernikeDiskTransformPlan (cxfplan, CDisk2CxfPlan (n))
182
+ function ZernikeDiskTransformPlan (S:: ZernikeDisk , v:: AbstractVector{T} ) where T
183
+ n = length (v)
184
+ N = (1 + isqrt (1 + 8 n)) ÷ 4
185
+ M = 2 N- 1
186
+ D = plan_transform! (rectspace (ChebyshevDisk ()), Array {T} (undef,N,M))
187
+ N = (M- 1 )÷ 4 + 1
188
+ 4 (N- 1 )+ 1 == M || (N += 1 ) # round up
189
+ ZernikeDiskTransformPlan (D, CDisk2CxfPlan (N))
137
190
end
138
191
139
- * (P:: FastZernikeDiskTransformPlan , v:: AbstractVector ) =
140
- _coefficients (P. disk2cxf, P. cxfplan* v, ChebyshevDisk (), ZernikeDisk ())
192
+ function * (P:: ZernikeDiskTransformPlan , v:: AbstractVector )
193
+ N,M = P. cxfplan. plan[1 ][2 ],P. cxfplan. plan[2 ][2 ]
194
+ V = P. cxfplan* reshape (copy (v),N,M)
195
+ C = checkerboard (V)
196
+ fromtensor (ZernikeDisk (), P. disk2cxf\ C)
197
+ end
141
198
142
- plan_transform (K:: ZernikeDisk , v:: AbstractVector ) = FastZernikeDiskTransformPlan (K, v)
199
+ plan_transform (K:: ZernikeDisk , v:: AbstractVector ) = ZernikeDiskTransformPlan (K, v)
143
200
144
- struct FastZernikeDiskITransformPlan {DUF,CHEB}
201
+ struct ZernikeDiskITransformPlan {DUF,CHEB}
145
202
icxfplan:: DUF
146
203
disk2cxf:: CHEB
147
204
end
148
205
149
- function FastZernikeDiskITransformPlan (S:: ZernikeDisk , v:: AbstractVector{T} ) where T
206
+ function ZernikeDiskITransformPlan (S:: ZernikeDisk , v:: AbstractVector{T} ) where T
150
207
# n = floor(Integer,sqrt(2length(v)) + 1/2)
151
208
# v = Array{T}(undef, sum(1:n))
152
- FastZernikeDiskITransformPlan (plan_itransform (ChebyshevDisk (), v), CDisk2CxfPlan (n))
209
+ ZernikeDiskITransformPlan (plan_itransform (ChebyshevDisk (), v), CDisk2CxfPlan (n))
153
210
end
154
211
155
- function * (P:: FastZernikeDiskITransformPlan , v)
212
+ function * (P:: ZernikeDiskITransformPlan , v)
156
213
# n = floor(Integer,sqrt(2length(v)) + 1/2)
157
214
# v = pad(v, sum(1:n))
158
215
F̌ = trinormalize! (tridevec (v))
@@ -162,5 +219,5 @@ function *(P::FastZernikeDiskITransformPlan, v)
162
219
end
163
220
164
221
165
- plan_itransform (K:: ZernikeDisk , v:: AbstractVector ) = FastZernikeDiskITransformPlan (K, v)
222
+ plan_itransform (K:: ZernikeDisk , v:: AbstractVector ) = ZernikeDiskITransformPlan (K, v)
166
223
Base. sum (f:: Fun{<:ZernikeDisk} ) = Fun (f,ZernikeDisk ()). coefficients[1 ]/ π
0 commit comments