Skip to content

Commit 8cbc6e5

Browse files
add tetrahedral transforms
1 parent c4f44ae commit 8cbc6e5

File tree

8 files changed

+202
-84
lines changed

8 files changed

+202
-84
lines changed

deps/build.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ if Sys.isapple()
44
const libfasttransforms = joinpath(dirname(@__DIR__), "deps", "libfasttransforms.dylib")
55
GCC = BinaryProvider.detect_compiler_abi().gcc_version
66
println("Building with ", GCC, ".")
7-
const release = "https://github.com/MikaelSlevinsky/FastTransforms/releases/download/v0.2.5/libfasttransforms.v0.2.5"
7+
const release = "https://github.com/MikaelSlevinsky/FastTransforms/releases/download/v0.2.6/libfasttransforms.v0.2.6"
88
if GCC == :gcc4
99
download(release*".gcc-4.9.dylib", libfasttransforms)
1010
elseif GCC == :gcc5
@@ -27,7 +27,7 @@ elseif Sys.islinux()
2727
else
2828
GCC = BinaryProvider.detect_compiler_abi().gcc_version
2929
println("Building with ", GCC, ".")
30-
const release = "https://github.com/MikaelSlevinsky/FastTransforms/releases/download/v0.2.5/libfasttransforms.v0.2.5"
30+
const release = "https://github.com/MikaelSlevinsky/FastTransforms/releases/download/v0.2.6/libfasttransforms.v0.2.6"
3131
if GCC == :gcc4
3232
download(release*".gcc-4.9.so", libfasttransforms)
3333
elseif GCC == :gcc5

src/FastTransforms.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,17 @@ import LinearAlgebra: mul!, lmul!, ldiv!
2424
export leg2cheb, cheb2leg, ultra2ultra, jac2jac,
2525
lag2lag, jac2ultra, ultra2jac, jac2cheb,
2626
cheb2jac, ultra2cheb, cheb2ultra,
27-
sph2fourier, sphv2fourier, disk2cxf, tri2cheb,
28-
fourier2sph, fourier2sphv, cxf2disk, cheb2tri
27+
sph2fourier, sphv2fourier, disk2cxf, tri2cheb, tet2cheb,
28+
fourier2sph, fourier2sphv, cxf2disk, cheb2tri, cheb2tet
2929

3030
export plan_leg2cheb, plan_cheb2leg, plan_ultra2ultra, plan_jac2jac,
3131
plan_lag2lag, plan_jac2ultra, plan_ultra2jac, plan_jac2cheb,
3232
plan_cheb2jac, plan_ultra2cheb, plan_cheb2ultra,
3333
plan_sph2fourier, plan_sph_synthesis, plan_sph_analysis,
3434
plan_sphv2fourier, plan_sphv_synthesis, plan_sphv_analysis,
3535
plan_disk2cxf, plan_disk_synthesis, plan_disk_analysis,
36-
plan_tri2cheb, plan_tri_synthesis, plan_tri_analysis
36+
plan_tri2cheb, plan_tri_synthesis, plan_tri_analysis,
37+
plan_tet2cheb, plan_tet_synthesis, plan_tet_analysis
3738

3839
include("libfasttransforms.jl")
3940

@@ -62,7 +63,7 @@ export plan_fejer1, fejernodes1, fejerweights1,
6263
include("clenshawcurtis.jl")
6364
include("fejer.jl")
6465

65-
export hermitepoints, weightedhermitetransform, iweightedhermitetransform
66+
export weightedhermitetransform, iweightedhermitetransform
6667

6768
include("hermite.jl")
6869

@@ -75,7 +76,8 @@ include("gaunt.jl")
7576
export sphones, sphzeros, sphrand, sphrandn, sphevaluate,
7677
sphvones, sphvzeros, sphvrand, sphvrandn,
7778
diskones, diskzeros, diskrand, diskrandn,
78-
triones, trizeros, trirand, trirandn, trievaluate
79+
triones, trizeros, trirand, trirandn, trievaluate,
80+
tetones, tetzeros, tetrand, tetrandn
7981

8082
lgamma(x) = logabsgamma(x)[1]
8183

src/hermite.jl

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,31 @@
1-
2-
3-
hermitepoints(n) = unweightedgausshermite( n )[1]
4-
5-
61
# exp(-x^2/2) H_n(x) / sqrt(π*prod(1:n))
7-
struct ForwardWeightedHermitePlan <: FastTransformPlan{FORWARD,Float64}
8-
Vtw::Matrix{Float64} # vandermonde
9-
end
102

11-
struct BackwardWeightedHermitePlan <: FastTransformPlan{BACKWARD,Float64}
12-
V::Matrix{Float64} # vandermonde
3+
struct ForwardWeightedHermitePlan{T}
4+
Vtw::Matrix{T} # vandermonde
135
end
146

7+
struct BackwardWeightedHermitePlan{T}
8+
V::Matrix{T} # vandermonde
9+
end
1510

1611
function _weightedhermite_vandermonde(n)
17-
V = Array{Float64}(undef,n,n)
18-
x,w = unweightedgausshermite( n )
12+
V = Array{Float64}(undef, n, n)
13+
x,w = unweightedgausshermite(n)
1914
for k=1:n
2015
V[k,:] = FastGaussQuadrature.hermpoly_rec(0:n-1, sqrt(2)*x[k])
2116
end
2217
V,w
2318
end
24-
function ForwardWeightedHermitePlan(n::Integer)
19+
20+
function ForwardWeightedHermitePlan(n::Integer)
2521
V,w = _weightedhermite_vandermonde(n)
2622
ForwardWeightedHermitePlan(V' * Diagonal(w / sqrt(π)))
2723
end
28-
BackwardWeightedHermitePlan(n::Integer) = BackwardWeightedHermitePlan(_weightedhermite_vandermonde(n)[1])
2924

25+
BackwardWeightedHermitePlan(n::Integer) = BackwardWeightedHermitePlan(_weightedhermite_vandermonde(n)[1])
3026

3127
*(P::ForwardWeightedHermitePlan, v::AbstractVector) = P.Vtw*v
32-
*(P::ForwardWeightedHermitePlan, v::AbstractVector{Float64}) = P.Vtw*v
3328
*(P::BackwardWeightedHermitePlan, v::AbstractVector) = P.V*v
34-
*(P::BackwardWeightedHermitePlan, v::AbstractVector{Float64}) = P.V*v
3529

3630
weightedhermitetransform(v) = ForwardWeightedHermitePlan(length(v))*v
3731
iweightedhermitetransform(v) = BackwardWeightedHermitePlan(length(v))*v
38-

src/libfasttransforms.jl

Lines changed: 128 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ if !(find_library(libfasttransforms) ≡ libfasttransforms)
2121
"and restart Julia.")
2222
end
2323

24+
function ft_fftw_plan_with_nthreads(n::Integer)
25+
ccall((:ft_fftw_plan_with_nthreads, libfasttransforms), Cvoid, (Cint, ), n)
26+
end
27+
28+
function __init__()
29+
ccall((:ft_fftw_init_threads, libfasttransforms), Cint, ())
30+
ft_fftw_plan_with_nthreads(ceil(Int, Sys.CPU_THREADS/2))
31+
end
32+
33+
2434
"""
2535
mpfr_t <: AbstractFloat
2636
@@ -44,53 +54,59 @@ end
4454

4555
set_num_threads(n::Integer) = ccall((:ft_set_num_threads, libfasttransforms), Cvoid, (Cint, ), n)
4656

47-
const LEG2CHEB = 0
48-
const CHEB2LEG = 1
49-
const ULTRA2ULTRA = 2
50-
const JAC2JAC = 3
51-
const LAG2LAG = 4
52-
const JAC2ULTRA = 5
53-
const ULTRA2JAC = 6
54-
const JAC2CHEB = 7
55-
const CHEB2JAC = 8
56-
const ULTRA2CHEB = 9
57-
const CHEB2ULTRA = 10
58-
const SPHERE = 11
59-
const SPHEREV = 12
60-
const DISK = 13
61-
const TRIANGLE = 14
62-
const SPHERESYNTHESIS = 15
63-
const SPHEREANALYSIS = 16
64-
const SPHEREVSYNTHESIS = 17
65-
const SPHEREVANALYSIS = 18
66-
const DISKSYNTHESIS = 19
67-
const DISKANALYSIS = 20
68-
const TRIANGLESYNTHESIS = 21
69-
const TRIANGLEANALYSIS = 22
70-
71-
let k2s = Dict(LEG2CHEB => "Legendre--Chebyshev",
72-
CHEB2LEG => "Chebyshev--Legendre",
73-
ULTRA2ULTRA => "ultraspherical--ultraspherical",
74-
JAC2JAC => "Jacobi--Jacobi",
75-
LAG2LAG => "Laguerre--Laguerre",
76-
JAC2ULTRA => "Jacobi--ultraspherical",
77-
ULTRA2JAC => "ultraspherical--Jacobi",
78-
JAC2CHEB => "Jacobi--Chebyshev",
79-
CHEB2JAC => "Chebyshev--Jacobi",
80-
ULTRA2CHEB => "ultraspherical--Chebyshev",
81-
CHEB2ULTRA => "Chebyshev--ultraspherical",
82-
SPHERE => "Spherical harmonic--Fourier",
83-
SPHEREV => "Spherical vector field--Fourier",
84-
DISK => "Zernike--Chebyshev×Fourier",
85-
TRIANGLE => "Proriol--Chebyshev",
86-
SPHERESYNTHESIS => "FFTW Fourier synthesis on the sphere",
87-
SPHEREANALYSIS => "FFTW Fourier analysis on the sphere",
88-
SPHEREVSYNTHESIS => "FFTW Fourier synthesis on the sphere (vector field)",
89-
SPHEREVANALYSIS => "FFTW Fourier analysis on the sphere (vector field)",
90-
DISKSYNTHESIS => "FFTW Chebyshev×Fourier synthesis on the disk",
91-
DISKANALYSIS => "FFTW Chebyshev×Fourier analysis on the disk",
92-
TRIANGLESYNTHESIS => "FFTW Chebyshev synthesis on the triangle",
93-
TRIANGLEANALYSIS => "FFTW Chebyshev analysis on the triangle")
57+
const LEG2CHEB = 0
58+
const CHEB2LEG = 1
59+
const ULTRA2ULTRA = 2
60+
const JAC2JAC = 3
61+
const LAG2LAG = 4
62+
const JAC2ULTRA = 5
63+
const ULTRA2JAC = 6
64+
const JAC2CHEB = 7
65+
const CHEB2JAC = 8
66+
const ULTRA2CHEB = 9
67+
const CHEB2ULTRA = 10
68+
const SPHERE = 11
69+
const SPHEREV = 12
70+
const DISK = 13
71+
const TRIANGLE = 14
72+
const TETRAHEDRON = 15
73+
const SPHERESYNTHESIS = 16
74+
const SPHEREANALYSIS = 17
75+
const SPHEREVSYNTHESIS = 18
76+
const SPHEREVANALYSIS = 19
77+
const DISKSYNTHESIS = 20
78+
const DISKANALYSIS = 21
79+
const TRIANGLESYNTHESIS = 22
80+
const TRIANGLEANALYSIS = 23
81+
const TETRAHEDRONSYNTHESIS = 24
82+
const TETRAHEDRONANALYSIS = 25
83+
84+
let k2s = Dict(LEG2CHEB => "Legendre--Chebyshev",
85+
CHEB2LEG => "Chebyshev--Legendre",
86+
ULTRA2ULTRA => "ultraspherical--ultraspherical",
87+
JAC2JAC => "Jacobi--Jacobi",
88+
LAG2LAG => "Laguerre--Laguerre",
89+
JAC2ULTRA => "Jacobi--ultraspherical",
90+
ULTRA2JAC => "ultraspherical--Jacobi",
91+
JAC2CHEB => "Jacobi--Chebyshev",
92+
CHEB2JAC => "Chebyshev--Jacobi",
93+
ULTRA2CHEB => "ultraspherical--Chebyshev",
94+
CHEB2ULTRA => "Chebyshev--ultraspherical",
95+
SPHERE => "Spherical harmonic--Fourier",
96+
SPHEREV => "Spherical vector field--Fourier",
97+
DISK => "Zernike--Chebyshev×Fourier",
98+
TRIANGLE => "Proriol--Chebyshev²",
99+
TETRAHEDRON => "Proriol--Chebyshev³",
100+
SPHERESYNTHESIS => "FFTW Fourier synthesis on the sphere",
101+
SPHEREANALYSIS => "FFTW Fourier analysis on the sphere",
102+
SPHEREVSYNTHESIS => "FFTW Fourier synthesis on the sphere (vector field)",
103+
SPHEREVANALYSIS => "FFTW Fourier analysis on the sphere (vector field)",
104+
DISKSYNTHESIS => "FFTW Chebyshev×Fourier synthesis on the disk",
105+
DISKANALYSIS => "FFTW Chebyshev×Fourier analysis on the disk",
106+
TRIANGLESYNTHESIS => "FFTW Chebyshev synthesis on the triangle",
107+
TRIANGLEANALYSIS => "FFTW Chebyshev analysis on the triangle",
108+
TETRAHEDRONSYNTHESIS => "FFTW Chebyshev synthesis on the tetrahedron",
109+
TETRAHEDRONANALYSIS => "FFTW Chebyshev analysis on the tetrahedron")
94110
global kind2string
95111
kind2string(k::Integer) = k2s[Int(k)]
96112
end
@@ -100,14 +116,20 @@ struct ft_plan_struct end
100116
mutable struct FTPlan{T, N, K}
101117
plan::Ptr{ft_plan_struct}
102118
n::Int
119+
l::Int
103120
m::Int
104121
function FTPlan{T, N, K}(plan::Ptr{ft_plan_struct}, n::Int) where {T, N, K}
105122
p = new(plan, n)
106123
finalizer(destroy_plan, p)
107124
p
108125
end
109126
function FTPlan{T, N, K}(plan::Ptr{ft_plan_struct}, n::Int, m::Int) where {T, N, K}
110-
p = new(plan, n, m)
127+
p = new(plan, n, -1, m)
128+
finalizer(destroy_plan, p)
129+
p
130+
end
131+
function FTPlan{T, N, K}(plan::Ptr{ft_plan_struct}, n::Int, l::Int, m::Int) where {T, N, K}
132+
p = new(plan, n, l, m)
111133
finalizer(destroy_plan, p)
112134
p
113135
end
@@ -120,7 +142,9 @@ show(io::IO, p::FTPlan{T, 2, SPHERE}) where T = print(io, "FastTransforms ", kin
120142
show(io::IO, p::FTPlan{T, 2, SPHEREV}) where T = print(io, "FastTransforms ", kind2string(SPHEREV), " plan for $(p.n)×$(2p.n-1)-element array of ", T)
121143
show(io::IO, p::FTPlan{T, 2, DISK}) where T = print(io, "FastTransforms ", kind2string(DISK), " plan for $(p.n)×$(4p.n-3)-element array of ", T)
122144
show(io::IO, p::FTPlan{T, 2, TRIANGLE}) where T = print(io, "FastTransforms ", kind2string(TRIANGLE), " plan for $(p.n)×$(p.n)-element array of ", T)
145+
show(io::IO, p::FTPlan{T, 3, TETRAHEDRON}) where T = print(io, "FastTransforms ", kind2string(TETRAHEDRON), " plan for $(p.n)×$(p.n)×$(p.n)-element array of ", T)
123146
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)
147+
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)
124148

125149
function checksize(p::FTPlan{T}, x::Array{T}) where T
126150
if p.n != size(x, 1)
@@ -135,6 +159,7 @@ destroy_plan(p::FTPlan{Float32, 1}) = ccall((:ft_destroy_tb_eigen_FMMf, libfastt
135159
destroy_plan(p::FTPlan{Float64, 1}) = ccall((:ft_destroy_tb_eigen_FMM, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
136160
destroy_plan(p::FTPlan{BigFloat, 1}) = ccall((:ft_mpfr_destroy_plan, libfasttransforms), Cvoid, (Ptr{mpfr_t}, Cint), p, p.n)
137161
destroy_plan(p::FTPlan{Float64, 2}) = ccall((:ft_destroy_harmonic_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
162+
destroy_plan(p::FTPlan{Float64, 3}) = ccall((:ft_destroy_tetrahedral_harmonic_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
138163
destroy_plan(p::FTPlan{Float64, 2, SPHERESYNTHESIS}) = ccall((:ft_destroy_sphere_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
139164
destroy_plan(p::FTPlan{Float64, 2, SPHEREANALYSIS}) = ccall((:ft_destroy_sphere_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
140165
destroy_plan(p::FTPlan{Float64, 2, SPHEREVSYNTHESIS}) = ccall((:ft_destroy_sphere_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
@@ -143,6 +168,8 @@ destroy_plan(p::FTPlan{Float64, 2, DISKSYNTHESIS}) = ccall((:ft_destroy_disk_fft
143168
destroy_plan(p::FTPlan{Float64, 2, DISKANALYSIS}) = ccall((:ft_destroy_disk_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
144169
destroy_plan(p::FTPlan{Float64, 2, TRIANGLESYNTHESIS}) = ccall((:ft_destroy_triangle_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
145170
destroy_plan(p::FTPlan{Float64, 2, TRIANGLEANALYSIS}) = ccall((:ft_destroy_triangle_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
171+
destroy_plan(p::FTPlan{Float64, 3, TETRAHEDRONSYNTHESIS}) = ccall((:ft_destroy_tetrahedron_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
172+
destroy_plan(p::FTPlan{Float64, 3, TETRAHEDRONANALYSIS}) = ccall((:ft_destroy_tetrahedron_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
146173

147174
struct AdjointFTPlan{T, S}
148175
parent::S
@@ -189,7 +216,7 @@ unsafe_convert(::Type{Ptr{mpfr_t}}, p::TransposeFTPlan{T, FTPlan{T, N, K}}) wher
189216
for f in (:leg2cheb, :cheb2leg, :ultra2ultra, :jac2jac,
190217
:lag2lag, :jac2ultra, :ultra2jac, :jac2cheb,
191218
:cheb2jac, :ultra2cheb, :cheb2ultra,
192-
:sph2fourier, :sphv2fourier, :disk2cxf, :tri2cheb)
219+
:sph2fourier, :sphv2fourier, :disk2cxf, :tri2cheb, :tet2cheb)
193220
plan_f = Symbol("plan_", f)
194221
@eval begin
195222
$plan_f(x::AbstractArray{T}, y...; z...) where T = $plan_f(T, size(x, 1), y...; z...)
@@ -198,7 +225,8 @@ for f in (:leg2cheb, :cheb2leg, :ultra2ultra, :jac2jac,
198225
end
199226

200227
for (f, plan_f) in ((:fourier2sph, :plan_sph2fourier), (:fourier2sphv, :plan_sphv2fourier),
201-
(:cxf2disk2, :plan_disk2cxf), (:cheb2tri, :plan_tri2cheb))
228+
(:cxf2disk2, :plan_disk2cxf), (:cheb2tri, :plan_tri2cheb),
229+
(:cheb2tet, :plan_tet2cheb))
202230
@eval begin
203231
$f(x::AbstractArray{T}, y...; z...) where T = $plan_f(x, y...; z...)\x
204232
end
@@ -393,6 +421,11 @@ function plan_tri2cheb(::Type{Float64}, n::Integer, α::Float64, β::Float64, γ
393421
return FTPlan{Float64, 2, TRIANGLE}(plan, n)
394422
end
395423

424+
function plan_tet2cheb(::Type{Float64}, n::Integer, α::Float64, β::Float64, γ::Float64, δ::Float64)
425+
plan = ccall((:ft_plan_tet2cheb, libfasttransforms), Ptr{ft_plan_struct}, (Cint, Float64, Float64, Float64, Float64), n, α, β, γ, δ)
426+
return FTPlan{Float64, 3, TETRAHEDRON}(plan, n)
427+
end
428+
396429
for (fJ, fC, fE, K) in ((:plan_sph_synthesis, :ft_plan_sph_synthesis, :ft_execute_sph_synthesis, SPHERESYNTHESIS),
397430
(:plan_sph_analysis, :ft_plan_sph_analysis, :ft_execute_sph_analysis, SPHEREANALYSIS),
398431
(:plan_sphv_synthesis, :ft_plan_sphv_synthesis, :ft_execute_sphv_synthesis, SPHEREVSYNTHESIS),
@@ -416,12 +449,39 @@ for (fJ, fC, fE, K) in ((:plan_sph_synthesis, :ft_plan_sph_synthesis, :ft_execut
416449
end
417450
end
418451

419-
*(p::FTPlan{T}, x::VecOrMat{T}) where T = lmul!(p, deepcopy(x))
420-
*(p::AdjointFTPlan{T}, x::VecOrMat{T}) where T = lmul!(p, deepcopy(x))
421-
*(p::TransposeFTPlan{T}, x::VecOrMat{T}) where T = lmul!(p, deepcopy(x))
422-
\(p::FTPlan{T}, x::VecOrMat{T}) where T = ldiv!(p, deepcopy(x))
423-
\(p::AdjointFTPlan{T}, x::VecOrMat{T}) where T = ldiv!(p, deepcopy(x))
424-
\(p::TransposeFTPlan{T}, x::VecOrMat{T}) where T = ldiv!(p, deepcopy(x))
452+
function plan_tet_synthesis(::Type{Float64}, n::Integer, l::Integer, m::Integer)
453+
plan = ccall((:ft_plan_tet_synthesis, libfasttransforms), Ptr{ft_plan_struct}, (Cint, Cint, Cint), n, l, m)
454+
return FTPlan{Float64, 3, TETRAHEDRONSYNTHESIS}(plan, n, l, m)
455+
end
456+
457+
function lmul!(p::FTPlan{Float64, 3, TETRAHEDRONSYNTHESIS}, x::Array{Float64, 3})
458+
if p.n != size(x, 1) || p.l != size(x, 2) || p.m != size(x, 3)
459+
throw(DimensionMismatch("FTPlan has dimensions $(p.n) × $(p.l) × $(p.m), x has dimensions $(size(x, 1)) × $(size(x, 2)) × $(size(x, 3))"))
460+
end
461+
ccall((:ft_execute_tet_synthesis, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, Ptr{Float64}, Cint, Cint, Cint), p, x, size(x, 1), size(x, 2), size(x, 3))
462+
return x
463+
end
464+
465+
function plan_tet_analysis(::Type{Float64}, n::Integer, l::Integer, m::Integer)
466+
plan = ccall((:ft_plan_tet_analysis, libfasttransforms), Ptr{ft_plan_struct}, (Cint, Cint, Cint), n, l, m)
467+
return FTPlan{Float64, 3, TETRAHEDRONANALYSIS}(plan, n, l, m)
468+
end
469+
470+
function lmul!(p::FTPlan{Float64, 3, TETRAHEDRONANALYSIS}, x::Array{Float64, 3})
471+
if p.n != size(x, 1) || p.l != size(x, 2) || p.m != size(x, 3)
472+
throw(DimensionMismatch("FTPlan has dimensions $(p.n) × $(p.l) × $(p.m), x has dimensions $(size(x, 1)) × $(size(x, 2)) × $(size(x, 3))"))
473+
end
474+
ccall((:ft_execute_tet_analysis, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, Ptr{Float64}, Cint, Cint, Cint), p, x, size(x, 1), size(x, 2), size(x, 3))
475+
return x
476+
end
477+
478+
479+
*(p::FTPlan{T}, x::Array{T}) where T = lmul!(p, deepcopy(x))
480+
*(p::AdjointFTPlan{T}, x::Array{T}) where T = lmul!(p, deepcopy(x))
481+
*(p::TransposeFTPlan{T}, x::Array{T}) where T = lmul!(p, deepcopy(x))
482+
\(p::FTPlan{T}, x::Array{T}) where T = ldiv!(p, deepcopy(x))
483+
\(p::AdjointFTPlan{T}, x::Array{T}) where T = ldiv!(p, deepcopy(x))
484+
\(p::TransposeFTPlan{T}, x::Array{T}) where T = ldiv!(p, deepcopy(x))
425485

426486
for (fJ, fC, elty) in ((:lmul!, :ft_bfmvf, :Float32),
427487
(:ldiv!, :ft_bfsvf, :Float32),
@@ -545,3 +605,15 @@ for (fJ, fC, K) in ((:lmul!, :ft_execute_sph2fourier, SPHERE),
545605
end
546606
end
547607
end
608+
609+
function lmul!(p::FTPlan{Float64, 3, TETRAHEDRON}, x::Array{Float64, 3})
610+
checksize(p, x)
611+
ccall((:ft_execute_tet2cheb, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, Ptr{Float64}, Cint, Cint, Cint), p, x, size(x, 1), size(x, 2), size(x, 3))
612+
return x
613+
end
614+
615+
function ldiv!(p::FTPlan{Float64, 3, TETRAHEDRON}, x::Array{Float64, 3})
616+
checksize(p, x)
617+
ccall((:ft_execute_cheb2tet, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, Ptr{Float64}, Cint, Cint, Cint), p, x, size(x, 1), size(x, 2), size(x, 3))
618+
return x
619+
end

0 commit comments

Comments
 (0)