1
+ export ChebyshevDisk, ZernikeDisk
2
+
3
+ struct ZernikeDisk{V,T} <: Space{Disk{V},T}
4
+ domain:: Disk{V}
5
+ end
6
+
7
+ ZernikeDisk (d:: Disk{V} ) where V = ZernikeDisk {V,complex(eltype(V))} (d)
8
+ ZernikeDisk () = ZernikeDisk (Disk ())
9
+
10
+ spacescompatible (:: ZernikeDisk , :: ZernikeDisk ) = true
11
+
12
+ @containsconstants ZernikeDisk
13
+
14
+ points (K:: ZernikeDisk , n:: Integer ) =
15
+ fromcanonical .(Ref (K), points (ChebyshevDisk (), n))
16
+
17
+ evaluate (cfs:: AbstractVector , Z:: ZernikeDisk , xy) =
18
+ Fun (Fun (Z, cfs), ChebyshevDisk ())(xy)
19
+
20
+ Space (d:: Disk ) = ZernikeDisk (d)
21
+
22
+ struct ChebyshevDisk{V,T} <: Space{Disk{V},T}
23
+ domain:: Disk{V}
24
+ end
25
+
26
+ @containsconstants ChebyshevDisk
27
+
28
+ ChebyshevDisk (d:: Disk{V} ) where V = ChebyshevDisk {V,eltype(V)} (d)
29
+ ChebyshevDisk () = ChebyshevDisk (Disk ())
30
+
31
+ rectspace (_) = Chebyshev () * Fourier ()
32
+
33
+ spacescompatible (K1:: ChebyshevDisk , K2:: ChebyshevDisk ) = domainscompatible (K1, K2)
34
+
35
+ function points (S:: ChebyshevDisk , N)
36
+ pts = points (rectspace (S), N)
37
+ polar .(pts)
38
+ end
39
+
40
+ DiskTensorizer () = Tensorizer ((Ones {Int} (∞),Ones {Int} (∞)))
41
+
42
+ tensorizer (K:: ChebyshevDisk ) = DiskTensorizer ()
43
+
44
+ # we have each polynomial
45
+ blocklengths (K:: ChebyshevDisk ) = 1 : ∞
46
+
47
+ for OP in (:block ,:blockstart ,:blockstop )
48
+ @eval begin
49
+ $ OP (s:: ChebyshevDisk ,M:: Block ) = $ OP (tensorizer (s),M)
50
+ $ OP (s:: ChebyshevDisk ,M) = $ OP (tensorizer (s),M)
51
+ end
52
+ end
53
+
54
+
55
+ plan_transform (S:: ChebyshevDisk , n:: AbstractVector ) =
56
+ TransformPlan (S, plan_transform (rectspace (S),n), Val{false })
57
+ plan_itransform (S:: ChebyshevDisk , n:: AbstractVector ) =
58
+ ITransformPlan (S, plan_itransform (rectspace (S),n), Val{false })
59
+
60
+ # drop every other entry
61
+ function checkerboard (A:: AbstractMatrix{T} ) where T
62
+ m,n = size (A)
63
+ C = zeros (T, (m+ 1 )÷ 2 , n)
64
+ z = @view (A[1 : 2 : end ,1 ])
65
+ e1,e2 = @view (A[1 : 2 : end ,4 : 4 : end ]),@view (A[1 : 2 : end ,5 : 4 : end ])
66
+ o1,o2 = @view (A[2 : 2 : end ,2 : 4 : end ]),@view (A[2 : 2 : end ,3 : 4 : end ])
67
+ C[1 : size (z,1 ),1 ] .= z
68
+ C[1 : size (e1,1 ),4 : 4 : n] .= e1
69
+ C[1 : size (e2,1 ),5 : 4 : n] .= e2
70
+ C[1 : size (o1,1 ),2 : 4 : n] .= o1
71
+ C[1 : size (o2,1 ),3 : 4 : n] .= o2
72
+ C
73
+ end
74
+
75
+ function icheckerboard (C:: AbstractMatrix{T} ) where T
76
+ m,n = size (C)
77
+ A = zeros (T, 2 * m, n)
78
+ A[1 : 2 : end ,1 ] .= C[:,1 ]
79
+ A[1 : 2 : end ,4 : 4 : end ] .= C[:,4 : 4 : end ]
80
+ A[1 : 2 : end ,5 : 4 : end ] .= C[:,5 : 4 : end ]
81
+ A[2 : 2 : end ,2 : 4 : end ] .= C[:,2 : 4 : end ]
82
+ A[2 : 2 : end ,3 : 4 : end ] .= C[:,3 : 4 : end ]
83
+ A
84
+ end
85
+
86
+ torectcfs (S, v) = fromtensor (rectspace (S), icheckerboard (totensor (S, v)))
87
+ fromrectcfs (S, v) = fromtensor (S, checkerboard (totensor (rectspace (S),v)))
88
+
89
+ * (P:: TransformPlan{<:Any,<:ChebyshevDisk} , v:: AbstractArray ) = fromrectcfs (P. space, P. plan* v)
90
+ * (P:: ITransformPlan{<:Any,<:ChebyshevDisk} , v:: AbstractArray ) = P. plan* torectcfs (P. space, v)
91
+
92
+ evaluate (cfs:: AbstractVector , S:: ChebyshevDisk , x) = evaluate (torectcfs (S,cfs), rectspace (S), ipolar (x))
93
+
94
+
95
+ function _coefficients (disk2cxf, v̂:: AbstractVector{T} , :: ChebyshevDisk , :: ZernikeDisk ) where T
96
+ F = totensor (ChebyshevDisk (), v̂)
97
+ F *= sqrt (convert (T,π))
98
+ n = size (F,1 )
99
+ F̌ = disk2cxf \ pad (F,n,4 n- 3 )
100
+ trivec (F̌)
101
+ end
102
+
103
+ function _coefficients (disk2cxf, v:: AbstractVector{T} , :: ZernikeDisk , :: ChebyshevDisk ) where T
104
+ F̌ = tridevec (v)
105
+ n = size (F̌,1 )
106
+ F = disk2cxf * pad (F̌,n,4 n- 3 )
107
+ F /= sqrt (convert (T,π))
108
+ fromtensor (ChebyshevDisk (), F)
109
+ end
110
+
111
+ function coefficients (cfs:: AbstractVector , CD:: ChebyshevDisk , ZD:: ZernikeDisk )
112
+ c = totensor (ChebyshevDisk (), cfs) # TODO : wasteful
113
+ n = size (c,1 )
114
+ _coefficients (CDisk2CxfPlan (n), cfs, CD, ZD)
115
+ end
116
+
117
+ function coefficients (cfs:: AbstractVector , ZD:: ZernikeDisk , CD:: ChebyshevDisk )
118
+ c = tridevec (cfs) # TODO : wasteful
119
+ n = size (c,1 )
120
+ _coefficients (CDisk2CxfPlan (n), cfs, ZD, CD)
121
+ end
122
+
123
+
124
+ struct FastZernikeDiskTransformPlan{DUF,CHEB}
125
+ cxfplan:: DUF
126
+ disk2cxf:: CHEB
127
+ end
128
+
129
+ function FastZernikeDiskTransformPlan (S:: ZernikeDisk , v:: AbstractVector{T} ) where T
130
+ # n = floor(Integer,sqrt(2length(v)) + 1/2)
131
+ # v = Array{T}(undef, sum(1:n))
132
+ cxfplan = plan_transform (ChebyshevDisk (),v)
133
+ c = totensor (ChebyshevDisk (), cxfplan* v) # TODO : wasteful
134
+ n = size (c,1 )
135
+ FastZernikeDiskTransformPlan (cxfplan, CDisk2CxfPlan (n))
136
+ end
137
+
138
+ * (P:: FastZernikeDiskTransformPlan , v:: AbstractVector ) =
139
+ _coefficients (P. disk2cxf, P. cxfplan* v, ChebyshevDisk (), ZernikeDisk ())
140
+
141
+ plan_transform (K:: ZernikeDisk , v:: AbstractVector ) = FastZernikeDiskTransformPlan (K, v)
142
+
143
+ struct FastZernikeDiskITransformPlan{DUF,CHEB}
144
+ icxfplan:: DUF
145
+ disk2cxf:: CHEB
146
+ end
147
+
148
+ function FastZernikeDiskITransformPlan (S:: ZernikeDisk , v:: AbstractVector{T} ) where T
149
+ # n = floor(Integer,sqrt(2length(v)) + 1/2)
150
+ # v = Array{T}(undef, sum(1:n))
151
+ FastZernikeDiskITransformPlan (plan_itransform (ChebyshevDisk (), v), CDisk2CxfPlan (n))
152
+ end
153
+
154
+ function * (P:: FastZernikeDiskITransformPlan , v)
155
+ # n = floor(Integer,sqrt(2length(v)) + 1/2)
156
+ # v = pad(v, sum(1:n))
157
+ F̌ = trinormalize! (tridevec (v))
158
+ F = P. disk2cxf * F̌
159
+ v̂ = trivec (transpose (F))
160
+ P. icxfplan* v̂
161
+ end
162
+
163
+
164
+ plan_itransform (K:: ZernikeDisk , v:: AbstractVector ) = FastZernikeDiskITransformPlan (K, v)
165
+ Base. sum (f:: Fun{<:ZernikeDisk} ) = Fun (f,ZernikeDisk ()). coefficients[1 ]/ π
0 commit comments