Skip to content

Commit dc65b11

Browse files
committed
fix: norm scaling
1 parent f83b9d4 commit dc65b11

4 files changed

Lines changed: 506 additions & 4 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
* Pinned Cython in the Coverity Scan workflow so generated code stays stable between scans, and added `coverity/README.md` documenting the known false-positive families and the scan review checklist [gh-374](https://github.com/IntelPython/mkl_fft/pull/374)
1515

1616
### Fixed
17+
* Fixed `norm="forward"`/`"ortho"` scaling in `fftn`, `ifftn`, `rfftn`, `irfftn` and the `fft2` family when only a subset of axes is transformed: the scale used the full array shape instead of the transformed axes [gh-336](https://github.com/IntelPython/mkl_fft/issues/336), [gh-370](https://github.com/IntelPython/mkl_fft/pull/370)
18+
* Fixed `norm="forward"`/`"ortho"` scaling in `irfftn` and `irfft2`, which normalized over the input length `n` rather than the complex-to-real output length `2 * (n - 1)` [gh-370](https://github.com/IntelPython/mkl_fft/pull/370)
1719
* Declared `f_ndim` as a C `int` in `_allocate_result` so the buffer size is computed in C rather than through a Python object, resolving a Coverity out-of-bounds (OVERRUN) false positive [gh-364](https://github.com/IntelPython/mkl_fft/pull/364)
1820
* Silenced a Coverity `UNUSED_VALUE` finding in `__create_descriptor_1d` by marking the `DftiFreeDescriptor` status (used only by a debug-only `assert`) as intentionally unused [gh-365](https://github.com/IntelPython/mkl_fft/pull/365)
1921
* Fixed possible memory leaks when `PyMem_Malloc` fails, and raise `MemoryError` [gh-373](https://github.com/IntelPython/mkl_fft/pull/373)

‎mkl_fft/_fft_utils.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,22 @@ def _cook_nd_args(a, s=None, axes=None, invreal=False):
102102
return s, axes
103103

104104

105+
def _nd_fwd_scale(x, s, axes, norm, invreal=False):
106+
"""Forward scale for an N-D transform, over the transformed axes only.
107+
108+
``_compute_fwd_scale`` falls back to the full array shape when ``s`` is
109+
None, which over-normalizes a subset of axes; ``_cook_nd_args`` already
110+
resolves the right lengths, including c2r's ``2 * (n - 1)``.
111+
"""
112+
113+
_check_norm(norm)
114+
if norm in (None, "backward"):
115+
return 1.0
116+
if s is None:
117+
s, _ = _cook_nd_args(x, s, axes, invreal=invreal)
118+
return _compute_fwd_scale(norm, s, x.shape)
119+
120+
105121
# copied from scipy.fft module
106122
# https://github.com/scipy/scipy/blob/main/scipy/fft/_pocketfft/helper.py
107123
def _datacopied(arr, original):

‎mkl_fft/_mkl_fft.py‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
_c2c_fftnd_impl,
2828
_c2r_fftnd_impl,
2929
_compute_fwd_scale,
30+
_nd_fwd_scale,
3031
_r2c_fftnd_impl,
3132
)
3233

@@ -68,12 +69,12 @@ def ifft2(x, s=None, axes=(-2, -1), norm=None, out=None):
6869

6970

7071
def fftn(x, s=None, axes=None, norm=None, out=None):
71-
fsc = _compute_fwd_scale(norm, s, x.shape)
72+
fsc = _nd_fwd_scale(x, s, axes, norm)
7273
return _c2c_fftnd_impl(x, s=s, axes=axes, out=out, direction=+1, fsc=fsc)
7374

7475

7576
def ifftn(x, s=None, axes=None, norm=None, out=None):
76-
fsc = _compute_fwd_scale(norm, s, x.shape)
77+
fsc = _nd_fwd_scale(x, s, axes, norm)
7778
return _c2c_fftnd_impl(x, s=s, axes=axes, out=out, direction=-1, fsc=fsc)
7879

7980

@@ -96,10 +97,10 @@ def irfft2(x, s=None, axes=(-2, -1), norm=None, out=None):
9697

9798

9899
def rfftn(x, s=None, axes=None, norm=None, out=None):
99-
fsc = _compute_fwd_scale(norm, s, x.shape)
100+
fsc = _nd_fwd_scale(x, s, axes, norm)
100101
return _r2c_fftnd_impl(x, s=s, axes=axes, out=out, fsc=fsc)
101102

102103

103104
def irfftn(x, s=None, axes=None, norm=None, out=None):
104-
fsc = _compute_fwd_scale(norm, s, x.shape)
105+
fsc = _nd_fwd_scale(x, s, axes, norm, invreal=True)
105106
return _c2r_fftnd_impl(x, s=s, axes=axes, out=out, fsc=fsc)

0 commit comments

Comments
 (0)