Skip to content

Commit 03b7bf5

Browse files
let the build script point to master
add wrapper and examples
1 parent 9d3012c commit 03b7bf5

File tree

4 files changed

+188
-6
lines changed

4 files changed

+188
-6
lines changed

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/sphericalisometries.jl

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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_ZY_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+
98+
# Random orthogonal transformation
99+
Random.seed!(0)
100+
Q = qr(rand(3, 3)).Q
101+
102+
# Transform the sampling grid, note that `Q` is transposed here.
103+
u = Q[1,1]*x + Q[2,1]*y + Q[3,1]*z
104+
v = Q[1,2]*x + Q[2,2]*y + Q[3,2]*z
105+
w = Q[1,3]*x + Q[2,3]*y + Q[3,3]*z
106+
107+
F = f.(x, y, z)
108+
V = PA*F
109+
U = threshold!(P\V, 100eps())
110+
FastTransforms.execute_sph_orthogonal_transformation!(J, Q, U)
111+
FR = f.(u, v, w)
112+
VR = PA*FR
113+
UR = threshold!(P\VR, 100eps())
114+
@test U UR
115+
norm(U-UR)

src/FastTransforms.jl

Lines changed: 1 addition & 1 deletion
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

src/libfasttransforms.jl

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ const TETRAHEDRONSYNTHESIS = 25
134134
const TETRAHEDRONANALYSIS = 26
135135
const SPINSPHERESYNTHESIS = 27
136136
const SPINSPHEREANALYSIS = 28
137+
const SPHERICALISOMETRY = 29
137138

138139

139140
let k2s = Dict(LEG2CHEB => "Legendre--Chebyshev",
@@ -164,7 +165,8 @@ let k2s = Dict(LEG2CHEB => "Legendre--Chebyshev",
164165
TETRAHEDRONSYNTHESIS => "FFTW Chebyshev synthesis on the tetrahedron",
165166
TETRAHEDRONANALYSIS => "FFTW Chebyshev analysis on the tetrahedron",
166167
SPINSPHERESYNTHESIS => "FFTW Fourier synthesis on the sphere (spin-weighted)",
167-
SPINSPHEREANALYSIS => "FFTW Fourier analysis on the sphere (spin-weighted)")
168+
SPINSPHEREANALYSIS => "FFTW Fourier analysis on the sphere (spin-weighted)",
169+
SPHERICALISOMETRY => "Spherical isometry")
168170
global kind2string
169171
kind2string(k::Integer) = k2s[Int(k)]
170172
end
@@ -204,6 +206,7 @@ show(io::IO, p::FTPlan{T, 3, TETRAHEDRON}) where T = print(io, "FastTransforms "
204206
show(io::IO, p::FTPlan{T, 2, SPINSPHERE}) where T = print(io, "FastTransforms ", kind2string(SPINSPHERE), " plan for $(p.n)×$(2p.n-1)-element array of ", T)
205207
show(io::IO, p::FTPlan{T, 2, K}) where {T, K} = print(io, "FastTransforms plan for ", kind2string(K), " for $(p.n)×$(p.m)-element array of ", T)
206208
show(io::IO, p::FTPlan{T, 3, K}) where {T, K} = print(io, "FastTransforms plan for ", kind2string(K), " for $(p.n)×$(p.l)×$(p.m)-element array of ", T)
209+
show(io::IO, p::FTPlan{T, 2, SPHERICALISOMETRY}) where T = print(io, "FastTransforms ", kind2string(SPHERICALISOMETRY), " plan for $(p.n)×$(2p.n-1)-element array of ", T)
207210

208211
function checksize(p::FTPlan{T}, x::Array{T}) where T
209212
if p.n != size(x, 1)
@@ -222,6 +225,12 @@ for K in (SPHERE, SPHEREV, DISK, SPINSPHERE)
222225
end
223226
end
224227

228+
function checksize(p::FTPlan{T, 2, SPHERICALISOMETRY}, x::Matrix{T}) where T
229+
if p.n != size(x, 1) || 2p.n-1 != size(x, 2)
230+
throw(DimensionMismatch("This FTPlan must operate on arrays of size $(p.n) × $(2p.n-1)."))
231+
end
232+
end
233+
225234
unsafe_convert(::Type{Ptr{ft_plan_struct}}, p::FTPlan) = p.plan
226235
unsafe_convert(::Type{Ptr{mpfr_t}}, p::FTPlan) = unsafe_convert(Ptr{mpfr_t}, p.plan)
227236

@@ -243,6 +252,7 @@ destroy_plan(p::FTPlan{Float64, 3, TETRAHEDRONSYNTHESIS}) = ccall((:ft_destroy_t
243252
destroy_plan(p::FTPlan{Float64, 3, TETRAHEDRONANALYSIS}) = ccall((:ft_destroy_tetrahedron_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
244253
destroy_plan(p::FTPlan{Complex{Float64}, 2, SPINSPHERESYNTHESIS}) = ccall((:ft_destroy_spinsphere_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
245254
destroy_plan(p::FTPlan{Complex{Float64}, 2, SPINSPHEREANALYSIS}) = ccall((:ft_destroy_spinsphere_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
255+
destroy_plan(p::FTPlan{Float64, 2, SPHERICALISOMETRY}) = ccall((:ft_destroy_sph_isometry_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
246256

247257
struct AdjointFTPlan{T, S}
248258
parent::S
@@ -595,6 +605,11 @@ function lmul!(p::FTPlan{Complex{Float64}, 2, SPINSPHEREANALYSIS}, x::Matrix{Com
595605
return x
596606
end
597607

608+
function plan_sph_isometry(::Type{Float64}, n::Integer)
609+
plan = ccall((:ft_plan_sph_isometry, libfasttransforms), Ptr{ft_plan_struct}, (Cint, ), n)
610+
return FTPlan{Float64, 2, SPHERICALISOMETRY}(plan, n)
611+
end
612+
598613
*(p::FTPlan{T}, x::Array{T}) where T = lmul!(p, deepcopy(x))
599614
*(p::AdjointFTPlan{T}, x::Array{T}) where T = lmul!(p, deepcopy(x))
600615
*(p::TransposeFTPlan{T}, x::Array{T}) where T = lmul!(p, deepcopy(x))
@@ -738,6 +753,59 @@ function ldiv!(p::FTPlan{Complex{Float64}, 2, SPINSPHERE}, x::Matrix{Complex{Flo
738753
return x
739754
end
740755

756+
function execute_sph_polar_rotation!(x::Matrix{Float64}, α)
757+
ccall((:ft_execute_sph_polar_rotation, libfasttransforms), Cvoid, (Ptr{Float64}, Cint, Cint, Float64, Float64), x, size(x, 1), size(x, 2), sin(α), cos(α))
758+
return x
759+
end
760+
761+
function execute_sph_polar_reflection!(x::Matrix{Float64})
762+
ccall((:ft_execute_sph_polar_reflection, libfasttransforms), Cvoid, (Ptr{Float64}, Cint, Cint), x, size(x, 1), size(x, 2))
763+
return x
764+
end
765+
766+
struct ft_orthogonal_transformation
767+
Q::NTuple{9, Float64}
768+
end
769+
770+
function convert(::Type{ft_orthogonal_transformation}, Q::AbstractMatrix)
771+
@assert size(Q, 1) 3 && size(Q, 2) 3
772+
return ft_orthogonal_transformation((Q[1, 1], Q[2, 1], Q[3, 1], Q[1, 2], Q[2, 2], Q[3, 2], Q[1, 3], Q[2, 3], Q[3, 3]))
773+
end
774+
775+
function execute_sph_orthogonal_transformation!(p::FTPlan{Float64, 2, SPHERICALISOMETRY}, Q, x::Matrix{Float64})
776+
checksize(p, x)
777+
ccall((:ft_execute_sph_orthogonal_transformation, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ft_orthogonal_transformation, Ptr{Float64}, Cint, Cint), p, Q, x, size(x, 1), size(x, 2))
778+
return x
779+
end
780+
781+
function execute_sph_ZY_axis_exchange!(p::FTPlan{Float64, 2, SPHERICALISOMETRY}, x::Matrix{Float64})
782+
checksize(p, x)
783+
ccall((:ft_execute_sph_ZY_axis_exchange, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, Ptr{Float64}, Cint, Cint), p, x, size(x, 1), size(x, 2))
784+
return x
785+
end
786+
787+
function execute_sph_rotation!(p::FTPlan{Float64, 2, SPHERICALISOMETRY}, α, β, γ, x::Matrix{Float64})
788+
checksize(p, x)
789+
ccall((:ft_execute_sph_rotation, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, Float64, Float64, Float64, Ptr{Float64}, Cint, Cint), p, α, β, γ, x, size(x, 1), size(x, 2))
790+
return x
791+
end
792+
793+
struct ft_reflection
794+
w::NTuple{3, Float64}
795+
end
796+
797+
function convert(::Type{ft_reflection}, w::AbstractVector)
798+
@assert length(w) 3
799+
return ft_reflection((w[1], w[2], w[3]))
800+
end
801+
802+
function execute_sph_reflection!(p::FTPlan{Float64, 2, SPHERICALISOMETRY}, w, x::Matrix{Float64})
803+
checksize(p, x)
804+
ccall((:ft_execute_sph_reflection, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ft_reflection, Ptr{Float64}, Cint, Cint), p, w, x, size(x, 1), size(x, 2))
805+
return x
806+
end
807+
execute_sph_reflection!(p::FTPlan{Float64, 2, SPHERICALISOMETRY}, w1, w2, w3, x::Matrix{Float64}) = execute_sph_reflection!(p, ft_reflection(w1, w2, w3), x)
808+
741809
*(p::FTPlan{T}, x::Array{Complex{T}}) where T = lmul!(p, deepcopy(x))
742810
*(p::AdjointFTPlan{T}, x::Array{Complex{T}}) where T = lmul!(p, deepcopy(x))
743811
*(p::TransposeFTPlan{T}, x::Array{Complex{T}}) where T = lmul!(p, deepcopy(x))

0 commit comments

Comments
 (0)