diff --git a/CHANGELOG.md b/CHANGELOG.md index d3d2368..9e34420 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * To set `mkl_fft` as the backend for SciPy is only possible through `mkl_fft.interfaces.scipy_fft` [gh-179](https://github.com/IntelPython/mkl_fft/pull/179) * SciPy interface `mkl_fft.interfaces.scipy_fft` uses the same function from SciPy for handling `s` and `axes` for N-D FFTs [gh-181](https://github.com/IntelPython/mkl_fft/pull/181) +### Fixed +* Fixed an issue for calling `mkl_fft.interfaces.numpy.fftn` with an empty axes [gh-139](https://github.com/IntelPython/mkl_fft/pull/139) +* Fixed an issue for calling `mkl_fft.interfaces.numpy.fftn` with a zero-size array [gh-139](https://github.com/IntelPython/mkl_fft/pull/139) +* Fixed inconsistency of input and output arrays dtype for `irfft` function [gh-180](https://github.com/IntelPython/mkl_fft/pull/180) + ## [1.3.14] (04/10/2025) resolves gh-152 by adding an explicit `mkl-service` dependency to `mkl-fft` when building the wheel diff --git a/mkl_fft/_pydfti.pyx b/mkl_fft/_pydfti.pyx index e6d1d22..5cfd20f 100644 --- a/mkl_fft/_pydfti.pyx +++ b/mkl_fft/_pydfti.pyx @@ -665,13 +665,12 @@ def _r2c_fft1d_impl( return f_arr -# this routine is functionally equivalent to numpy.fft.irfft def _c2r_fft1d_impl( x, n=None, axis=-1, overwrite_x=False, double fsc=1.0, out=None ): """ - Uses MKL to perform 1D FFT on the real input array x along the given axis, - producing complex output, but giving only half of the harmonics. + Uses MKL to perform 1D FFT on the real/complex input array x along the + given axis, producing real output. cf. numpy.fft.irfft """ @@ -704,13 +703,13 @@ def _c2r_fft1d_impl( else: # we must cast the input and allocate the output, # so we cast to complex double and operate in place - try: + if x_type is cnp.NPY_FLOAT: x_arr = cnp.PyArray_FROM_OTF( - x_arr, cnp.NPY_CDOUBLE, cnp.NPY_BEHAVED) - except: - raise ValueError( - "First argument should be a real or " - "a complex sequence of single or double precision" + x_arr, cnp.NPY_CFLOAT, cnp.NPY_BEHAVED + ) + else: + x_arr = cnp.PyArray_FROM_OTF( + x_arr, cnp.NPY_CDOUBLE, cnp.NPY_BEHAVED ) x_type = cnp.PyArray_TYPE(x_arr) in_place = 1 diff --git a/mkl_fft/interfaces/_numpy_fft.py b/mkl_fft/interfaces/_numpy_fft.py index 8557213..f2f72d5 100644 --- a/mkl_fft/interfaces/_numpy_fft.py +++ b/mkl_fft/interfaces/_numpy_fft.py @@ -295,13 +295,11 @@ def hfft(a, n=None, axis=-1, norm=None, out=None): """ norm = _swap_direction(norm) x = _downcast_float128_array(a) - x = np.array(x, copy=True) - np.conjugate(x, out=x) fsc = _compute_fwd_scale(norm, n, 2 * (x.shape[axis] - 1)) return _trycall( mkl_fft.irfft, - (x,), + (np.conjugate(x),), {"n": n, "axis": axis, "fwd_scale": fsc, "out": out}, ) @@ -317,9 +315,9 @@ def ihfft(a, n=None, axis=-1, norm=None, out=None): x = _downcast_float128_array(a) fsc = _compute_fwd_scale(norm, n, x.shape[axis]) - output = _trycall( + result = _trycall( mkl_fft.rfft, (x,), {"n": n, "axis": axis, "fwd_scale": fsc, "out": out} ) - np.conjugate(output, out=output) - return output + np.conjugate(result, out=result) + return result diff --git a/mkl_fft/tests/test_fft1d.py b/mkl_fft/tests/test_fft1d.py index 01631fe..fbff2bd 100644 --- a/mkl_fft/tests/test_fft1d.py +++ b/mkl_fft/tests/test_fft1d.py @@ -457,3 +457,12 @@ def test_irfft_out_strided(axis): expected = np.fft.irfft(x, axis=axis, out=out) assert_allclose(result, expected) + + +@requires_numpy_2 +@pytest.mark.parametrize("dt", ["i4", "f4", "f8", "c8", "c16"]) +def test_irfft_dtype(dt): + x = np.array(rnd.random((20, 20)), dtype=dt) + result = mkl_fft.irfft(x) + expected = np.fft.irfft(x) + assert_allclose(result, expected, rtol=1e-7, atol=1e-7, strict=True) diff --git a/mkl_fft/tests/third_party/scipy/test_basic.py b/mkl_fft/tests/third_party/scipy/test_basic.py index 19b00fa..f05034c 100644 --- a/mkl_fft/tests/third_party/scipy/test_basic.py +++ b/mkl_fft/tests/third_party/scipy/test_basic.py @@ -14,13 +14,11 @@ # pylint: disable=possibly-used-before-assignment if scipy.__version__ < "1.12": - # scipy from Intel channel is 1.10 - pytest.skip( - "This test file needs scipy>=1.12", - allow_module_level=True, - ) + # scipy from Intel channel is 1.10 with python 3.9 and 3.10 + pytest.skip("This test file needs scipy>=1.12", allow_module_level=True) elif scipy.__version__ < "1.14": - # For python<=3.9, scipy<1.14 is installed + # For python-3.11 and 3.12, scipy<1.14 is installed from Intel channel + # For python<=3.9, scipy<1.14 is installed from conda channel # pylint: disable=no-name-in-module from scipy._lib._array_api import size as xp_size else: