Skip to content

Commit 75c5dd4

Browse files
committed
updates
1 parent 273fc71 commit 75c5dd4

File tree

10 files changed

+366
-65
lines changed

10 files changed

+366
-65
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
test/.ipynb_checkpoints
33
test/*.ipynb
44
Manifest.toml
5-
Manifest-v1.11.toml
5+
Manifest-v1.11.toml
6+
*.txt

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,31 @@ iphlct = iphlct2d(phlct, n)
121121

122122
Reference: [Professor Saito's paper][paper] page 30 Chapter 6.2.2.
123123

124+
## Examples
125+
126+
Basic DST/IDST round-trip:
127+
128+
```julia
129+
using .PolyHarmonicTrigTransforms
130+
131+
x = randn(8)
132+
y = dst(x)
133+
x_rec = idst(y)
134+
@assert maximum(abs.(x_rec - 4 .* x ./ 4)) < 1e-12 # numeric check
135+
```
136+
137+
PHLCT forward/backward round-trip (block size `N`):
138+
139+
```julia
140+
using .PolyHarmonicTrigTransforms
141+
142+
n = 8
143+
img = randn(n, n)
144+
coeffs = phlct_forward(img, n)
145+
img_rec = phlct_backward(coeffs, n)
146+
@assert norm(img - img_rec) / norm(img) < 1e-12
147+
```
148+
124149
#### Image Testing
125150

126151
To test images, first take your chosen image and convert it into a square image (i.e. size n x n where n is the new size of the image after using tools to square it).

src/dst.jl

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,83 @@
3030
# See also: IDST
3131

3232
module DST
33-
using AbstractFFTs, FFTW
33+
function _ensure_fftw()
34+
if !isdefined(@__MODULE__, :FFTW)
35+
Core.eval(Main, :(using FFTW))
36+
Core.eval(@__MODULE__, :(const FFTW = Main.FFTW))
37+
end
38+
return nothing
39+
end
3440

35-
export dst, dst_old
41+
export dst, dst!, dst_u, plan_dst, dst_old
42+
43+
"""
44+
dst(x; dims=1)
45+
46+
Compute the Type-I Discrete Sine Transform (DST) of `x` along `dims`.
3647
48+
Arguments
49+
- `x`: an `AbstractArray` (vector or matrix).
50+
- `dims`: dimension to transform (default `1`).
51+
52+
Returns
53+
- transformed array of the same shape as `x`.
54+
55+
Example
56+
```julia
57+
y = dst([1.0,2.0,3.0])
58+
```
59+
"""
3760
function dst(x::AbstractArray, dims=1)
61+
_ensure_fftw()
3862
N = size(x, dims)
3963
return FFTW.r2r(x, FFTW.RODFT00, dims) / 2
4064
end
4165

4266
function dst_u(x::AbstractArray, dims=1)
67+
_ensure_fftw()
4368
N = size(x, dims)
4469
new_x = FFTW.r2r(x, FFTW.RODFT00, dims)
4570

4671
return new_x / (sqrt(2*N)) #unitory value
4772
end
4873

74+
"""
75+
plan_dst(x; dims=1, flags=FFTW.MEASURE)
76+
77+
Create an FFTW r2r plan for the DST (RODFT00) on `x`. The returned plan
78+
can be executed with `plan * x`.
79+
"""
80+
function plan_dst(x::AbstractArray; dims=1, flags=FFTW.MEASURE)
81+
_ensure_fftw()
82+
return FFTW.r2r_plan(x, FFTW.RODFT00, dims; flags=flags)
83+
end
84+
85+
"""
86+
dst!(x; dims=1)
87+
88+
In-place DST that overwrites `x` with its transform when possible. Falls
89+
back to a safe out-of-place compute and copy if the in-place routine is
90+
not available on the current platform.
91+
"""
92+
function dst!(x::AbstractArray; dims=1)
93+
_ensure_fftw()
94+
try
95+
# Try to use FFTW in-place r2r if available
96+
FFTW.r2r!(x, FFTW.RODFT00, dims)
97+
x .*= 0.5
98+
return x
99+
catch _
100+
# Fallback: compute out-of-place and copy into x
101+
tmp = FFTW.r2r(x, FFTW.RODFT00, dims)
102+
tmp .*= 0.5
103+
x .= tmp
104+
return x
105+
end
106+
end
107+
49108
function dst_old(a::AbstractArray, n=nothing)
109+
_ensure_fftw()
50110
if minimum(size(a)) == 1
51111
if size(a, 2) > 1
52112
do_trans = 1
@@ -73,7 +133,7 @@ module DST
73133
y = zeros(2 * (n + 1), m)
74134
y[2:n+1, :] = aa
75135
y[n+3:2*(n+1), :] = -reverse(aa, dims=1)
76-
yy = fft(y, (1,))
136+
yy = FFTW.fft(y, (1,))
77137
b = yy[2:n+1, :] / (-2 * sqrt(-1 + 0im))
78138

79139

src/idst.jl

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,31 @@
2323
# See also: DST
2424
#
2525
module IDST
26-
2726
include("dst.jl")
2827
using .DST
2928

30-
export idst, idst_old
29+
# Lazily load FFTW when needed by IDST helpers.
30+
function _ensure_fftw()
31+
if !isdefined(@__MODULE__, :FFTW)
32+
Core.eval(Main, :(using FFTW))
33+
Core.eval(@__MODULE__, :(const FFTW = Main.FFTW))
34+
end
35+
return nothing
36+
end
37+
38+
export idst, idst!, plan_idst, idst_old
39+
"""
40+
idst(y; dims=1)
41+
42+
Inverse Type-I Discrete Sine Transform (IDST) of `y` along `dims`.
43+
44+
Arguments
45+
- `y`: an `AbstractArray` of DST coefficients.
46+
- `dims`: dimension to transform (default `1`).
47+
48+
Returns
49+
- reconstructed array in the original domain.
50+
"""
3151
function idst(y::AbstractArray, dims=1)
3252

3353
N = size(y, dims)
@@ -37,6 +57,36 @@ module IDST
3757
return x * 4
3858
end
3959

60+
"""
61+
plan_idst(y; dims=1, flags=FFTW.MEASURE)
62+
63+
Create an FFTW r2r plan suitable for the IDST (uses the DST plan internally).
64+
"""
65+
function plan_idst(y::AbstractArray; dims=1, flags=FFTW.MEASURE)
66+
_ensure_fftw()
67+
return FFTW.r2r_plan(y, FFTW.RODFT00, dims; flags=flags)
68+
end
69+
70+
"""
71+
idst!(y; dims=1)
72+
73+
In-place inverse DST: overwrite `y` with the reconstructed data when
74+
possible. Falls back to computing out-of-place and copying the result.
75+
"""
76+
function idst!(y::AbstractArray; dims=1)
77+
_ensure_fftw()
78+
try
79+
# In-place inverse DST: perform r2r in-place then scale by 1/(N+1)
80+
FFTW.r2r!(y, FFTW.RODFT00, dims)
81+
y ./= (size(y, dims) + 1)
82+
return y
83+
catch _
84+
tmp = idst(y, dims)
85+
y .= tmp
86+
return y
87+
end
88+
end
89+
4090
function idst_old(y::AbstractArray, n=nothing, dims=1)
4191
if n === nothing
4292
n = size(y, 1)

src/llst.jl

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module LLST
2323
using .SOLVELAPLACE
2424

2525
export llst2d, illst2d
26+
export llst2d!, illst2d!
2627

2728
# LLFT2D 2D Laplace Local Fourier Transform
2829
#
@@ -51,11 +52,24 @@ module LLST
5152
inIX1 = 2:m-1
5253
inIX2 = 2:n-1
5354
rnorm = sqrt(4 / (m - 1) / (n - 1))
54-
interior = data[inIX1, inIX2] .- solvelaplace(data)
55+
sl = solvelaplace(data)
56+
interior = data[inIX1, inIX2] .- sl[inIX1, inIX2]
5557
trans[inIX1, inIX2] = rnorm .* dst(dst(interior)')'
5658
return trans
5759
end
5860

61+
"""
62+
llst2d!(data)
63+
64+
In-place variant of `llst2d` that overwrites `data` with the transform
65+
result. Falls back to out-of-place computation and broadcasting assignment.
66+
"""
67+
function llst2d!(data::AbstractVecOrMat)
68+
res = llst2d(data)
69+
data .= res
70+
return data
71+
end
72+
5973
# ILLFT2D 2D Inverse Laplace Local Fourier Transform
6074
#
6175
# Applies the inverse LLFT transform to image (no blocking). Note that
@@ -94,10 +108,23 @@ module LLST
94108

95109
data = float(data)
96110
data[inIX1[:], inIX2[:]] = rnorm .* dst(dst(data[inIX1[:], inIX2[:]])')'
97-
trans[inIX1[:], inIX2[:]] = data[inIX1[:], inIX2[:]] .+ solvelaplace(trans)
111+
sl = solvelaplace(trans)
112+
trans[inIX1[:], inIX2[:]] = data[inIX1[:], inIX2[:]] .+ sl[inIX1[:], inIX2[:]]
98113

99114
return trans
100115
end
101116

117+
"""
118+
illst2d!(data)
119+
120+
In-place variant of `illst2d` that overwrites `data` with the inverse
121+
transform result.
122+
"""
123+
function illst2d!(data::AbstractVecOrMat)
124+
res = illst2d(data)
125+
data .= res
126+
return data
127+
end
128+
102129

103130
end

src/llst2.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module LLST2
1010
using .SOLVELAPLACE
1111

1212
export llst2
13+
export llst2!
1314

1415
function llst2(data::AbstractVecOrMat, ll::AbstractArray, inverse::Bool=false)
1516
if (inverse != false)
@@ -34,6 +35,18 @@ module LLST2
3435
end
3536
end
3637

38+
"""
39+
llst2!(data, ll; inverse=false)
40+
41+
In-place variant of `llst2` that overwrites `data` with the transformed
42+
result. Uses broadcasting assignment as a safe fallback.
43+
"""
44+
function llst2!(data::AbstractVecOrMat, ll::AbstractArray, inverse::Bool=false)
45+
res = llst2(data, ll, inverse)
46+
data .= res
47+
return data
48+
end
49+
3750

3851
# Function for forward transform of boundary
3952
function fbdrytrans(bdry::AbstractVecOrMat)

0 commit comments

Comments
 (0)