Skip to content

Add ContourletOperators subpackage wrapping Contourlets.jl - #46

Draft
hakkelt wants to merge 5 commits into
kul-optec:masterfrom
hakkelt:add-contourlet-operators
Draft

Add ContourletOperators subpackage wrapping Contourlets.jl#46
hakkelt wants to merge 5 commits into
kul-optec:masterfrom
hakkelt:add-contourlet-operators

Conversation

@hakkelt

@hakkelt hakkelt commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Adds ContourletOperators subpackage: ContourletOp/NSCTOp wrapping Contourlets.jl (Contourlet Transform and NSCT) as LinearOperators.

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown

Benchmark Results (Julia v1.12.7)

No significant performance or memory regressions detected.

Time benchmarks
Benchmark base head Ratio (base/head)
batching/SimpleBatchOp/adjoint-single 45.5 ± 2.4 μs 45 ± 2.3 μs 1.01 ± 0.15
batching/SimpleBatchOp/forward-single 41.7 ± 2.9 μs 40.2 ± 2.9 μs 1.04 ± 0.21
batching/SpreadingBatchOp/adjoint-single 23.4 ± 2.3 μs 24.6 ± 1.6 μs 0.951 ± 0.22
batching/SpreadingBatchOp/forward-single 20.8 ± 2.4 μs 23.3 ± 2.5 μs 0.891 ± 0.28
calculus/AffineAdd/adjoint 6.71 ± 0.4 μs 6.59 ± 0.5 μs 1.02 ± 0.2
calculus/AffineAdd/forward 20.8 ± 1.5 μs 18.8 ± 1.2 μs 1.11 ± 0.21
calculus/Ax_mul_Bx/forward 49.7 ± 0.41 μs 49.6 ± 0.4 μs 1 ± 0.023
calculus/Ax_mul_Bx/jacobian-adjoint 74.1 ± 3 μs 70 ± 1.8 μs 1.06 ± 0.1
calculus/Ax_mul_Bxt/forward 49.9 ± 0.39 μs 49.7 ± 0.65 μs 1 ± 0.031
calculus/Ax_mul_Bxt/jacobian-adjoint 72.9 ± 1.3 μs 67.6 ± 0.97 μs 1.08 ± 0.049
calculus/Axt_mul_Bx/forward 49.8 ± 0.32 μs 49.9 ± 0.71 μs 0.997 ± 0.031
calculus/Axt_mul_Bx/jacobian-adjoint 69.4 ± 1.1 μs 71 ± 1.4 μs 0.976 ± 0.048
calculus/BroadCast/identity-single 63.4 ± 3.9 μs 72.6 ± 8.5 μs 0.872 ± 0.23
calculus/BroadCast/operator-single-adjoint 1.77 ± 0.09 μs 1.83 ± 0.09 μs 0.967 ± 0.14
calculus/BroadCast/operator-single-forward 330 ± 50 ns 391 ± 40 ns 0.844 ± 0.31
calculus/Compose/adjoint 14.6 ± 1 μs 12.8 ± 0.87 μs 1.15 ± 0.22
calculus/Compose/forward 17.5 ± 1.3 μs 15.7 ± 0.94 μs 1.11 ± 0.22
calculus/DCAT/adjoint 27.7 ± 1.8 μs 24.7 ± 0.69 μs 1.12 ± 0.16
calculus/DCAT/forward 28.8 ± 1.9 μs 26.2 ± 0.72 μs 1.1 ± 0.16
calculus/HCAT/adjoint 27.8 ± 1.7 μs 27.6 ± 1.6 μs 1.01 ± 0.17
calculus/HCAT/forward 41.2 ± 2.5 μs 43.2 ± 1.9 μs 0.955 ± 0.14
calculus/HadamardProd/forward 822 ± 4.2 μs 815 ± 5.1 μs 1.01 ± 0.016
calculus/HadamardProd/jacobian-adjoint 871 ± 7.8 μs 879 ± 7.6 μs 0.992 ± 0.025
calculus/Jacobian/sigmoid-adjoint 162 ± 3.5 μs 161 ± 2.8 μs 1.01 ± 0.056
calculus/Reshape/adjoint 6.41 ± 0.17 μs 6.55 ± 0.32 μs 0.979 ± 0.11
calculus/Reshape/forward 9.69 ± 0.64 μs 9.44 ± 0.54 μs 1.03 ± 0.18
calculus/Scale/adjoint 9.84 ± 0.36 μs 10.1 ± 0.51 μs 0.97 ± 0.12
calculus/Scale/forward 13.4 ± 0.58 μs 14.7 ± 1 μs 0.912 ± 0.15
calculus/Sum/adjoint 33.8 ± 2.4 μs 35.6 ± 3.3 μs 0.947 ± 0.22
calculus/Sum/forward 36.3 ± 2.8 μs 38.2 ± 3.3 μs 0.951 ± 0.22
calculus/VCAT/adjoint 36.7 ± 2.9 μs 39.1 ± 2.8 μs 0.94 ± 0.2
calculus/VCAT/forward 28 ± 1.7 μs 25.8 ± 0.77 μs 1.08 ± 0.15
contourletoperators/ContourletOp/adjoint 3.38 ± 0.052 ms
contourletoperators/ContourletOp/forward 3.66 ± 0.059 ms
contourletoperators/NSCTOp/adjoint 6.38 ± 0.082 ms
contourletoperators/NSCTOp/forward 10.5 ± 0.26 ms
dspoperators/Filt/adjoint 222 ± 5.3 μs 221 ± 5.2 μs 1.01 ± 0.068
dspoperators/Filt/forward 230 ± 5.1 μs 228 ± 5.3 μs 1.01 ± 0.065
dspoperators/MIMOFilt/adjoint 180 ± 2.2 μs 180 ± 1.6 μs 1 ± 0.031
dspoperators/MIMOFilt/forward 187 ± 2.2 μs 187 ± 2.2 μs 0.999 ± 0.033
dspoperators/Xcorr/adjoint 51.2 ± 1.7 μs 52 ± 1.9 μs 0.985 ± 0.097
dspoperators/Xcorr/forward 483 ± 60 μs 478 ± 91 μs 1.01 ± 0.46
fftwoperators/DFT/adjoint 172 ± 6.8 μs 172 ± 7.3 μs 0.995 ± 0.12
fftwoperators/DFT/forward 144 ± 7.4 μs 150 ± 8 μs 0.961 ± 0.14
linearoperators/DiagOp/adjoint-single 243 ± 24 μs 257 ± 11 μs 0.946 ± 0.2
linearoperators/DiagOp/adjoint-threaded 252 ± 17 μs 240 ± 6.8 μs 1.05 ± 0.16
linearoperators/DiagOp/forward-single 250 ± 19 μs 254 ± 8.9 μs 0.986 ± 0.17
linearoperators/DiagOp/forward-threaded 252 ± 16 μs 243 ± 8.8 μs 1.04 ± 0.15
linearoperators/Eye/forward 428 ± 24 μs 452 ± 37 μs 0.946 ± 0.19
linearoperators/FiniteDiff/adjoint 361 ± 18 μs 418 ± 39 μs 0.864 ± 0.18
linearoperators/FiniteDiff/forward 365 ± 20 μs 430 ± 38 μs 0.847 ± 0.18
linearoperators/GetIndex/adjoint 783 ± 24 μs 878 ± 56 μs 0.892 ± 0.13
linearoperators/GetIndex/forward 506 ± 22 μs 557 ± 40 μs 0.91 ± 0.15
linearoperators/LBFGS/mul 52.9 ± 1.9 μs 54.3 ± 2.2 μs 0.974 ± 0.11
linearoperators/LBFGS/update 13 ± 0.88 μs 12.4 ± 0.69 μs 1.04 ± 0.18
linearoperators/LMatrixOp/adjoint 227 ± 12 μs 269 ± 22 μs 0.845 ± 0.17
linearoperators/LMatrixOp/forward 258 ± 27 μs 250 ± 22 μs 1.03 ± 0.28
linearoperators/MatrixOp/adjoint 184 ± 5.6 μs 186 ± 6.3 μs 0.99 ± 0.09
linearoperators/MatrixOp/forward 190 ± 5.5 μs 194 ± 7.5 μs 0.982 ± 0.095
linearoperators/MyLinOp/adjoint 264 ± 19 μs 277 ± 13 μs 0.954 ± 0.17
linearoperators/MyLinOp/forward 269 ± 20 μs 279 ± 16 μs 0.965 ± 0.18
linearoperators/Variation/adjoint-single 864 ± 1.8 μs 865 ± 2.7 μs 0.998 ± 0.0075
linearoperators/Variation/forward-single 86.5 ± 6.1 μs 92.8 ± 8.2 μs 0.932 ± 0.21
linearoperators/ZeroPad/adjoint 164 ± 1 μs 165 ± 1.7 μs 0.998 ± 0.024
linearoperators/ZeroPad/forward 81.9 ± 8.2 μs 80.4 ± 12 μs 1.02 ± 0.37
linearoperators/Zeros/forward 782 ± 19 μs 787 ± 57 μs 0.993 ± 0.15
nfftoperators/NFFTOp/adjoint 257 ± 7.2 μs 260 ± 7.9 μs 0.988 ± 0.082
nfftoperators/NFFTOp/forward 213 ± 3.9 μs 212 ± 6.8 μs 1 ± 0.074
nonlinearoperators/Atan/forward 449 ± 6.2 μs 449 ± 6.5 μs 1 ± 0.04
nonlinearoperators/Atan/jacobian-adjoint 14.7 ± 1.1 μs 13.8 ± 0.85 μs 1.07 ± 0.21
nonlinearoperators/Cos/forward 393 ± 5.9 μs 395 ± 5.8 μs 0.995 ± 0.042
nonlinearoperators/Cos/jacobian-adjoint 410 ± 7.1 μs 407 ± 7.8 μs 1.01 ± 0.052
nonlinearoperators/Exp/forward 514 ± 6 μs 527 ± 5.9 μs 0.975 ± 0.032
nonlinearoperators/Exp/jacobian-adjoint 598 ± 6.1 μs 598 ± 6.3 μs 0.999 ± 0.029
nonlinearoperators/Pow/forward 452 ± 5.7 μs 453 ± 5.7 μs 0.999 ± 0.036
nonlinearoperators/Pow/jacobian-adjoint 389 ± 5.8 μs 384 ± 6.1 μs 1.01 ± 0.044
nonlinearoperators/Sech/forward 240 ± 4.5 μs 240 ± 4.8 μs 1 ± 0.056
nonlinearoperators/Sech/jacobian-adjoint 645 ± 6.7 μs 650 ± 6.2 μs 0.991 ± 0.028
nonlinearoperators/Sigmoid/forward 341 ± 5.3 μs 349 ± 5.4 μs 0.976 ± 0.043
nonlinearoperators/Sigmoid/jacobian-adjoint 331 ± 7.1 μs 337 ± 5.4 μs 0.984 ± 0.053
nonlinearoperators/Sin/forward 388 ± 5.5 μs 383 ± 5.8 μs 1.01 ± 0.042
nonlinearoperators/Sin/jacobian-adjoint 412 ± 5.7 μs 409 ± 6.9 μs 1.01 ± 0.044
nonlinearoperators/SoftMax/forward 335 ± 6 μs 326 ± 5.7 μs 1.03 ± 0.051
nonlinearoperators/SoftMax/jacobian-adjoint 373 ± 8.9 μs 373 ± 7 μs 1 ± 0.061
nonlinearoperators/SoftPlus/forward 916 ± 1.4 μs 916 ± 1.4 μs 1 ± 0.0043
nonlinearoperators/SoftPlus/jacobian-adjoint 411 ± 6.7 μs 416 ± 7.2 μs 0.988 ± 0.047
nonlinearoperators/Tanh/forward 331 ± 5.6 μs 332 ± 5.3 μs 0.998 ± 0.046
nonlinearoperators/Tanh/jacobian-adjoint 267 ± 5.2 μs 276 ± 5.1 μs 0.966 ± 0.052
normaloperators/DFT/mul 5 ± 0.18 μs 4.96 ± 0.26 μs 1.01 ± 0.13
normaloperators/DiagOp/mul 274 ± 14 μs 256 ± 6.7 μs 1.07 ± 0.12
normaloperators/NFFTOp/mul 163 ± 2.1 μs 163 ± 8.5 μs 1 ± 0.11
waveletoperators/WaveletOp/adjoint 3.14 ± 0.042 ms 3.09 ± 0.088 ms 1.02 ± 0.064
waveletoperators/WaveletOp/forward 1.24 ± 0.015 ms 1.22 ± 0.018 ms 1.01 ± 0.039
Memory benchmarks
Benchmark base head Ratio (base/head)
batching/SimpleBatchOp/adjoint-single 768 allocs (277.00 KiB) 768 allocs (277.00 KiB) 1
batching/SimpleBatchOp/forward-single 384 allocs (265.00 KiB) 384 allocs (265.00 KiB) 1
batching/SpreadingBatchOp/adjoint-single 418 allocs (140.09 KiB) 418 allocs (140.09 KiB) 1
batching/SpreadingBatchOp/forward-single 224 allocs (134.00 KiB) 224 allocs (134.00 KiB) 1
calculus/AffineAdd/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/AffineAdd/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Ax_mul_Bx/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Ax_mul_Bx/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Ax_mul_Bxt/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Ax_mul_Bxt/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Axt_mul_Bx/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Axt_mul_Bx/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/BroadCast/identity-single 1 allocs (48 bytes) 1 allocs (48 bytes) 1
calculus/BroadCast/operator-single-adjoint 31 allocs (1.08 KiB) 31 allocs (1.08 KiB) 1
calculus/BroadCast/operator-single-forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Compose/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Compose/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/DCAT/adjoint 1 allocs (32 bytes) 1 allocs (32 bytes) 1
calculus/DCAT/forward 1 allocs (32 bytes) 1 allocs (32 bytes) 1
calculus/HCAT/adjoint 131 allocs (4.70 KiB) 131 allocs (4.70 KiB) 1
calculus/HCAT/forward 70 allocs (2.52 KiB) 70 allocs (2.52 KiB) 1
calculus/HadamardProd/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/HadamardProd/jacobian-adjoint 6 allocs (512.14 KiB) 6 allocs (512.14 KiB) 1
calculus/Jacobian/sigmoid-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Reshape/adjoint 1 allocs (32 bytes) 1 allocs (32 bytes) 1
calculus/Reshape/forward 1 allocs (32 bytes) 1 allocs (32 bytes) 1
calculus/Scale/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Scale/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Sum/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Sum/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/VCAT/adjoint 130 allocs (4.67 KiB) 130 allocs (4.67 KiB) 1
calculus/VCAT/forward 71 allocs (2.55 KiB) 71 allocs (2.55 KiB) 1
contourletoperators/ContourletOp/adjoint 6 allocs (256 bytes)
contourletoperators/ContourletOp/forward 7 allocs (336 bytes)
contourletoperators/NSCTOp/adjoint 462 allocs (24.75 KiB)
contourletoperators/NSCTOp/forward 463 allocs (24.83 KiB)
dspoperators/Filt/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
dspoperators/Filt/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
dspoperators/MIMOFilt/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
dspoperators/MIMOFilt/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
dspoperators/Xcorr/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
dspoperators/Xcorr/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
fftwoperators/DFT/adjoint 45 allocs (258.34 KiB) 45 allocs (258.34 KiB) 1
fftwoperators/DFT/forward 45 allocs (258.34 KiB) 45 allocs (258.34 KiB) 1
linearoperators/DiagOp/adjoint-single 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/DiagOp/adjoint-threaded 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/DiagOp/forward-single 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/DiagOp/forward-threaded 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/Eye/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/FiniteDiff/adjoint 12 allocs (4.00 MiB) 12 allocs (4.00 MiB) 1
linearoperators/FiniteDiff/forward 6 allocs (4.00 MiB) 6 allocs (4.00 MiB) 1
linearoperators/GetIndex/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/GetIndex/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/LBFGS/mul 65 allocs (1.33 KiB) 65 allocs (1.33 KiB) 1
linearoperators/LBFGS/update 3 allocs (48 bytes) 3 allocs (48 bytes) 1
linearoperators/LMatrixOp/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/LMatrixOp/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/MatrixOp/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/MatrixOp/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/MyLinOp/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/MyLinOp/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/Variation/adjoint-single 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/Variation/forward-single 512 allocs (16.00 KiB) 512 allocs (16.00 KiB) 1
linearoperators/ZeroPad/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/ZeroPad/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/Zeros/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nfftoperators/NFFTOp/adjoint 152 allocs (5.28 KiB) 152 allocs (5.28 KiB) 1
nfftoperators/NFFTOp/forward 149 allocs (5.17 KiB) 149 allocs (5.17 KiB) 1
nonlinearoperators/Atan/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Atan/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Cos/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Cos/jacobian-adjoint 6 allocs (512.14 KiB) 6 allocs (512.14 KiB) 1
nonlinearoperators/Exp/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Exp/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Pow/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Pow/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Sech/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Sech/jacobian-adjoint 6 allocs (512.14 KiB) 6 allocs (512.14 KiB) 1
nonlinearoperators/Sigmoid/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Sigmoid/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Sin/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Sin/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/SoftMax/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/SoftMax/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/SoftPlus/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/SoftPlus/jacobian-adjoint 3 allocs (512.07 KiB) 3 allocs (512.07 KiB) 1
nonlinearoperators/Tanh/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Tanh/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
normaloperators/DFT/mul 0 allocs (0 bytes) 0 allocs (0 bytes) 1
normaloperators/DiagOp/mul 0 allocs (0 bytes) 0 allocs (0 bytes) 1
normaloperators/NFFTOp/mul 7 allocs (208 bytes) 7 allocs (208 bytes) 1
waveletoperators/WaveletOp/adjoint 12 allocs (512.46 KiB) 12 allocs (512.46 KiB) 1
waveletoperators/WaveletOp/forward 12 allocs (512.46 KiB) 12 allocs (512.46 KiB) 1

Ratio interpretation: values > 1 mean the PR is faster; values < 1 mean slower.
🚀 significant speedup · 🐢 significant slowdown

@codecov

codecov Bot commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.13%. Comparing base (a9c6167) to head (878c4d7).

Additional details and impacted files
@@           Coverage Diff           @@
##           master      #46   +/-   ##
=======================================
  Coverage   90.13%   90.13%           
=======================================
  Files          51       51           
  Lines        3678     3678           
=======================================
  Hits         3315     3315           
  Misses        363      363           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

hakkelt and others added 2 commits August 25, 2026 21:15
Adds ContourletOp and NSCTOp linear operators wrapping the discrete
Contourlet Transform and Nonsubsampled Contourlet Transform from
Contourlets.jl, following the existing subpackage pattern (WaveletOperators,
FFTWOperators, DSPOperators, NFFTOperators). Coefficients (coarse band +
directional subbands) are exposed as a flat RecursiveArrayTools.ArrayPartition
codomain, matching this repo's HCAT/DCAT multi-component convention.

Each operator owns a preallocated Contourlets.ContourletWorkspace and
coefficient buffer, so forward and adjoint mul! reuse scratch memory across
calls instead of allocating per call; a threading keyword exposes
Contourlets.jl's ThreadingPolicy (Auto/Enabled/Disabled) to control the
directional filter bank stage.

With the default biorthogonal (CDF97/Q2345) filters neither transform is
self-adjoint, so the adjoint operator is wired to the declared inverse
transform (a perfect-reconstruction left inverse) rather than the literal
linear-algebra transpose; documented on both operator types, and covered
by round-trip/in-place tests instead of the usual adjoint dot-product
invariant test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SUAy2tC1kyndjCrhNfZdoc
Fixes 'expected package ContourletOperators to be registered' failure
on the LTS matrix job — it wasn't in the rm/develop lists alongside
the other local subpackages.
@hakkelt
hakkelt force-pushed the add-contourlet-operators branch from c9c9783 to ce27237 Compare August 25, 2026 19:15
hakkelt and others added 3 commits August 25, 2026 23:31
similar_coefficients was using the raw requested T instead of the
promoted Td that make_workspace already computes internally, causing
a MethodError on the first mul! whenever T was narrower than the
params' filter precision. Also unify ContourletOp/NSCTOp into a
single ContourletTransformOp struct distinguished by a Kind trait,
removing the ~110-line duplication between the two operators.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016vzNfSioXkuA1P84Y7BzzP
…IDCT convention

The runtime Kind-field + const-alias approach diverged from the codebase's
established pattern for near-duplicate transform pairs (FFTWOperators'
DCT/IDCT: one abstract supertype for shared traits, two separate concrete
structs for the rest). Switch to that pattern instead: ContourletTransform
carries size/domain_type/codomain_type/is_invertible/is_thread_safe once,
while ContourletOp/NSCTOp keep their own constructors, dispatch barriers,
mul! pairs, and fun_name. Drops the fun_name/kind-field indirection and the
confusing ContourletTransformOp name (it backed NSCT too). Behavior and
public API unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016vzNfSioXkuA1P84Y7BzzP
Adds an array_type constructor keyword (mirrors WaveletOp) so domain_array_type/
codomain_array_type report GPU storage. Contourlets.jl itself stays CPU-only (FFTW
plans, scalar filter-bank loops), so mul! stages x/y through an internal CPU buffer
(copyto! in, run the CPU transform, copyto! out) instead of executing on-device.

Verified on real CUDA hardware (Quadro RTX 6000): exact forward/adjoint round-trip
with array_type = CuArray{Float64}. Extended test_jet.jl's @test_call coverage for
the new array_type kwarg.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016vzNfSioXkuA1P84Y7BzzP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant