Skip to content

Commit 474131c

Browse files
[FastTransforms] v0.4 (#125)
* let the build script point to master add wrapper and examples * add extra conversions from NTuple{*, Float64} * rename ZY_ to yz_ * update disk2cxf, add rectdisk2cheb * remove nightly tests * remove unnecessary parentheses
1 parent 8a000df commit 474131c

10 files changed

+319
-42
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ jobs:
1111
version:
1212
- '1.3'
1313
- '1.5'
14-
- 'nightly'
1514
os:
1615
- ubuntu-latest
1716
- macOS-latest

Project.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "FastTransforms"
22
uuid = "057dd010-8810-581a-b7be-e3fc3b93f78c"
3-
version = "0.10.3"
3+
version = "0.11.0"
44

55
[deps]
66
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"
@@ -19,15 +19,15 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1919
ToeplitzMatrices = "c751599d-da0a-543b-9d20-d0a503d91d24"
2020

2121
[compat]
22-
AbstractFFTs = "0.4, 0.5"
23-
ArrayLayouts = "0.3.7, 0.4"
22+
AbstractFFTs = "0.5"
23+
ArrayLayouts = "0.4"
2424
BinaryProvider = "0.5"
2525
DSP = "0.6"
2626
FFTW = "1"
2727
FastGaussQuadrature = "0.4"
28-
FastTransforms_jll = "0.3.3"
29-
FillArrays = "0.8, 0.9, 0.10"
28+
FastTransforms_jll = "0.4.0"
29+
FillArrays = "0.9, 0.10"
3030
Reexport = "0.2"
31-
SpecialFunctions = "0.8, 0.9, 0.10"
31+
SpecialFunctions = "0.10, 1"
3232
ToeplitzMatrices = "0.6"
3333
julia = "1.3"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ julia> using FastTransforms, LinearAlgebra
1919

2020
## Fast orthogonal polynomial transforms
2121

22-
The 29 orthogonal polynomial transforms are listed in `FastTransforms.kind2string.(0:28)`. Univariate transforms may be planned with the standard normalization or with orthonormalization. For multivariate transforms, the standard normalization may be too severe for floating-point computations, so it is omitted. Here are two examples:
22+
The 33 orthogonal polynomial transforms are listed in `FastTransforms.kind2string.(0:32)`. Univariate transforms may be planned with the standard normalization or with orthonormalization. For multivariate transforms, the standard normalization may be too severe for floating-point computations, so it is omitted. Here are two examples:
2323

2424
### The Chebyshev--Legendre transform
2525

deps/build.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using BinaryProvider
22
import Libdl
33

4-
version = v"0.3.3"
5-
64
const extension = Sys.isapple() ? "dylib" : Sys.islinux() ? "so" : Sys.iswindows() ? "dll" : ""
75

86
print_error() = error(
@@ -26,10 +24,11 @@ if ft_build_from_source == "true"
2624
if [ -d "FastTransforms" ]; then
2725
cd FastTransforms
2826
git fetch
29-
git checkout v$version
27+
git checkout master
28+
git pull
3029
cd ..
3130
else
32-
git clone -b v$version https://github.com/MikaelSlevinsky/FastTransforms.git FastTransforms
31+
git clone https://github.com/MikaelSlevinsky/FastTransforms.git FastTransforms
3332
fi
3433
cd FastTransforms
3534
$make assembly

examples/disk.jl

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ r = [sinpi((N-n-0.5)/(2N)) for n in 0:N-1]
3737
# On the mapped tensor product grid, our function samples are:
3838
F = [f(r*cospi(θ), r*sinpi(θ)) for r in r, θ in θ]
3939

40-
# We precompute a Zernike--Chebyshev×Fourier plan:
41-
P = plan_disk2cxf(F)
40+
# We precompute a (generalized) Zernike--Chebyshev×Fourier plan:
41+
α, β = 0, 0
42+
P = plan_disk2cxf(F, α, β)
4243

4344
# And an FFTW Chebyshev×Fourier analysis plan on the disk:
4445
PA = plan_disk_analysis(F)
@@ -47,10 +48,57 @@ PA = plan_disk_analysis(F)
4748
U = P\(PA*F)
4849

4950
# The Zernike coefficients are useful for integration. The integral of $f(x,y)$
50-
# over the disk should be $\pi/2$ by harmonicity. The coefficient of $Z_0^0$
51+
# over the disk should be $\pi/2$ by harmonicity. The coefficient of $Z_{0,0}$
5152
# multiplied by `√π` is:
5253
U[1, 1]*sqrt(π)
5354

5455
# Using an orthonormal basis, the integral of $[f(x,y)]^2$ over the disk is
5556
# approximately the square of the 2-norm of the coefficients:
56-
norm(U)^2
57+
norm(U)^2, π/(2*sqrt(2))*log1p(sqrt(2))
58+
59+
# But there's more! Next, we repeat the experiment using the Dunkl-Xu
60+
# orthonormal polynomials supported on the rectangularized disk.
61+
N = 2N
62+
M = N
63+
64+
# We analyze the function on an $N\times M$ mapped tensor product $xy$-grid defined by:
65+
# ```math
66+
# \begin{aligned}
67+
# x_n & = \cos\left(\frac{2n+1}{2N}\pi\right) = \sin\left(\frac{N-2n-1}{2N}\pi\right),\quad {\rm for} \quad 0 \le n < N,\quad{\rm and}\\
68+
# z_m & = \cos\left(\frac{2m+1}{2M}\pi\right) = \sin\left(\frac{M-2m-1}{2M}\pi\right),\quad {\rm for} \quad 0 \le m < M,\\
69+
# y_{n,m} & = \sqrt{1-x_n^2}z_m.
70+
# \end{aligned}
71+
# ```
72+
# Slightly more accuracy can be expected by using an auxiliary array:
73+
# ```math
74+
# w_n = \sin\left(\frac{2n+1}{2N}\pi\right),\quad {\rm for} \quad 0 \le n < N,
75+
# ```
76+
# so that $y_{n,m} = w_nz_m$.
77+
#
78+
# The x grid
79+
w = [sinpi((n+0.5)/N) for n in 0:N-1]
80+
x = [sinpi((N-2n-1)/(2N)) for n in 0:N-1]
81+
82+
# The z grid
83+
z = [sinpi((M-2m-1)/(2M)) for m in 0:M-1]
84+
85+
# On the mapped tensor product grid, our function samples are:
86+
F = [f(x[n], w[n]*z) for n in 1:N, z in z]
87+
88+
# We precompute a Dunkl-Xu--Chebyshev plan:
89+
P = plan_rectdisk2cheb(F, β)
90+
91+
# And an FFTW Chebyshev² analysis plan on the rectangularized disk:
92+
PA = plan_rectdisk_analysis(F)
93+
94+
# Its Dunkl-Xu coefficients are:
95+
U = P\(PA*F)
96+
97+
# The Dunkl-Xu coefficients are useful for integration. The integral of $f(x,y)$
98+
# over the disk should be $\pi/2$ by harmonicity. The coefficient of $P_{0,0}$
99+
# multiplied by `√π` is:
100+
U[1, 1]*sqrt(π)
101+
102+
# Using an orthonormal basis, the integral of $[f(x,y)]^2$ over the disk is
103+
# approximately the square of the 2-norm of the coefficients:
104+
norm(U)^2, π/(2*sqrt(2))*log1p(sqrt(2))

examples/sphericalisometries.jl

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
function threshold!(A::AbstractArray, ϵ)
2+
for i in eachindex(A)
3+
if abs(A[i]) < ϵ A[i] = 0 end
4+
end
5+
A
6+
end
7+
8+
using FastTransforms, LinearAlgebra, Random, Test
9+
10+
# The colatitudinal grid (mod π):
11+
N = 10
12+
θ = (0.5:N-0.5)/N
13+
14+
# The longitudinal grid (mod π):
15+
M = 2*N-1
16+
φ = (0:M-1)*2/M
17+
18+
x = [cospi(φ)*sinpi(θ) for θ in θ, φ in φ]
19+
y = [sinpi(φ)*sinpi(θ) for θ in θ, φ in φ]
20+
z = [cospi(θ) for θ in θ, φ in φ]
21+
22+
P = plan_sph2fourier(Float64, N)
23+
PA = plan_sph_analysis(Float64, N, M)
24+
J = FastTransforms.plan_sph_isometry(Float64, N)
25+
26+
27+
f = (x, y, z) -> x^2+y^4+x^2*y*z^3-x*y*z^2
28+
29+
30+
F = f.(x, y, z)
31+
V = PA*F
32+
U = threshold!(P\V, 100eps())
33+
FastTransforms.execute_sph_yz_axis_exchange!(J, U)
34+
FR = f.(x, -z, -y)
35+
VR = PA*FR
36+
UR = threshold!(P\VR, 100eps())
37+
@test U UR
38+
norm(U-UR)
39+
40+
41+
α, β, γ = 0.123, 0.456, 0.789
42+
43+
# Isometry built up from ZYZR
44+
A = [cos(α) -sin(α) 0; sin(α) cos(α) 0; 0 0 1]
45+
B = [cos(β) 0 -sin(β); 0 1 0; sin(β) 0 cos(β)]
46+
C = [cos(γ) -sin(γ) 0; sin(γ) cos(γ) 0; 0 0 1]
47+
R = diagm([1, 1, 1.0])
48+
Q = A*B*C*R
49+
50+
# Transform the sampling grid. Note that `Q` is transposed here.
51+
u = Q[1,1]*x + Q[2,1]*y + Q[3,1]*z
52+
v = Q[1,2]*x + Q[2,2]*y + Q[3,2]*z
53+
w = Q[1,3]*x + Q[2,3]*y + Q[3,3]*z
54+
55+
F = f.(x, y, z)
56+
V = PA*F
57+
U = threshold!(P\V, 100eps())
58+
FastTransforms.execute_sph_rotation!(J, α, β, γ, U)
59+
FR = f.(u, v, w)
60+
VR = PA*FR
61+
UR = threshold!(P\VR, 100eps())
62+
@test U UR
63+
norm(U-UR)
64+
65+
66+
F = f.(x, y, z)
67+
V = PA*F
68+
U = threshold!(P\V, 100eps())
69+
FastTransforms.execute_sph_polar_reflection!(U)
70+
FR = f.(x, y, -z)
71+
VR = PA*FR
72+
UR = threshold!(P\VR, 100eps())
73+
@test U UR
74+
norm(U-UR)
75+
76+
77+
# Isometry built up from planar reflection
78+
W = [0.123, 0.456, 0.789]
79+
H = w -> I - 2/(w'w)*w*w'
80+
Q = H(W)
81+
82+
# Transform the sampling grid. Note that `Q` is transposed here.
83+
u = Q[1,1]*x + Q[2,1]*y + Q[3,1]*z
84+
v = Q[1,2]*x + Q[2,2]*y + Q[3,2]*z
85+
w = Q[1,3]*x + Q[2,3]*y + Q[3,3]*z
86+
87+
F = f.(x, y, z)
88+
V = PA*F
89+
U = threshold!(P\V, 100eps())
90+
FastTransforms.execute_sph_reflection!(J, W, U)
91+
FR = f.(u, v, w)
92+
VR = PA*FR
93+
UR = threshold!(P\VR, 100eps())
94+
@test U UR
95+
norm(U-UR)
96+
97+
F = f.(x, y, z)
98+
V = PA*F
99+
U = threshold!(P\V, 100eps())
100+
FastTransforms.execute_sph_reflection!(J, (W[1], W[2], W[3]), U)
101+
FR = f.(u, v, w)
102+
VR = PA*FR
103+
UR = threshold!(P\VR, 100eps())
104+
@test U UR
105+
norm(U-UR)
106+
107+
# Random orthogonal transformation
108+
Random.seed!(0)
109+
Q = qr(rand(3, 3)).Q
110+
111+
# Transform the sampling grid, note that `Q` is transposed here.
112+
u = Q[1,1]*x + Q[2,1]*y + Q[3,1]*z
113+
v = Q[1,2]*x + Q[2,2]*y + Q[3,2]*z
114+
w = Q[1,3]*x + Q[2,3]*y + Q[3,3]*z
115+
116+
F = f.(x, y, z)
117+
V = PA*F
118+
U = threshold!(P\V, 100eps())
119+
FastTransforms.execute_sph_orthogonal_transformation!(J, Q, U)
120+
FR = f.(u, v, w)
121+
VR = PA*FR
122+
UR = threshold!(P\VR, 100eps())
123+
@test U UR
124+
norm(U-UR)

src/FastTransforms.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import DSP
99
@reexport using FFTW
1010

1111
import Base: unsafe_convert, eltype, ndims, adjoint, transpose, show, *, \,
12-
inv, length, size, view, getindex
12+
inv, length, size, view, getindex, convert
1313

1414
import Base.GMP: Limb
1515

@@ -35,15 +35,16 @@ import LinearAlgebra: mul!, lmul!, ldiv!
3535
export leg2cheb, cheb2leg, ultra2ultra, jac2jac,
3636
lag2lag, jac2ultra, ultra2jac, jac2cheb,
3737
cheb2jac, ultra2cheb, cheb2ultra,
38-
sph2fourier, sphv2fourier, disk2cxf, tri2cheb, tet2cheb,
39-
fourier2sph, fourier2sphv, cxf2disk, cheb2tri, cheb2tet
38+
sph2fourier, sphv2fourier, disk2cxf, rectdisk2cheb, tri2cheb, tet2cheb,
39+
fourier2sph, fourier2sphv, cxf2disk, cheb2rectdisk, cheb2tri, cheb2tet
4040

4141
export plan_leg2cheb, plan_cheb2leg, plan_ultra2ultra, plan_jac2jac,
4242
plan_lag2lag, plan_jac2ultra, plan_ultra2jac, plan_jac2cheb,
4343
plan_cheb2jac, plan_ultra2cheb, plan_cheb2ultra,
4444
plan_sph2fourier, plan_sph_synthesis, plan_sph_analysis,
4545
plan_sphv2fourier, plan_sphv_synthesis, plan_sphv_analysis,
4646
plan_disk2cxf, plan_disk_synthesis, plan_disk_analysis,
47+
plan_rectdisk2cheb, plan_rectdisk_synthesis, plan_rectdisk_analysis,
4748
plan_tri2cheb, plan_tri_synthesis, plan_tri_analysis,
4849
plan_tet2cheb, plan_tet_synthesis, plan_tet_analysis,
4950
plan_spinsph2fourier, plan_spinsph_synthesis, plan_spinsph_analysis
@@ -91,6 +92,7 @@ include("gaunt.jl")
9192
export sphones, sphzeros, sphrand, sphrandn, sphevaluate,
9293
sphvones, sphvzeros, sphvrand, sphvrandn,
9394
diskones, diskzeros, diskrand, diskrandn,
95+
rectdiskones, rectdiskzeros, rectdiskrand, rectdiskrandn,
9496
triones, trizeros, trirand, trirandn, trievaluate,
9597
tetones, tetzeros, tetrand, tetrandn,
9698
spinsphones, spinsphzeros, spinsphrand, spinsphrandn

0 commit comments

Comments
 (0)