From 04afc918bb8f3a827db61fcb1c2c8e78b5a62b28 Mon Sep 17 00:00:00 2001 From: Nikita Grigorian Date: Wed, 8 Oct 2025 12:21:27 -0700 Subject: [PATCH 1/3] revert vendoring of scipy functions, which caused circular dependencies in Intel NumPy --- mkl_fft/interfaces/_scipy_fft.py | 50 ++++++++++++++++ mkl_fft/interfaces/_scipy_helper.py | 93 ----------------------------- mkl_fft/interfaces/scipy_fft.py | 5 +- 3 files changed, 54 insertions(+), 94 deletions(-) delete mode 100644 mkl_fft/interfaces/_scipy_helper.py diff --git a/mkl_fft/interfaces/_scipy_fft.py b/mkl_fft/interfaces/_scipy_fft.py index 77429c7..76bf536 100644 --- a/mkl_fft/interfaces/_scipy_fft.py +++ b/mkl_fft/interfaces/_scipy_fft.py @@ -36,6 +36,7 @@ import mkl import numpy as np +import scipy import mkl_fft @@ -61,6 +62,10 @@ "ihfft2", "hfftn", "ihfftn", + "fftshift", + "ifftshift", + "fftfreq", + "rfftfreq", "get_workers", "set_workers", ] @@ -650,6 +655,51 @@ def ihfftn( return result +# define thin wrappers for scipy functions to avoid circular dependencies +def fftfreq(n, d=1.0, *, xp=None, device=None): + """ + Return the Discrete Fourier Transform sample frequencies. + + For full documentation refer to `scipy.fft.fftfreq`. + + """ + return scipy.fft.fftfreq(n, d=d, xp=xp, device=device) + + +def rfftfreq(n, d=1.0, *, xp=None, device=None): + """ + Return the Discrete Fourier Transform sample frequencies (for usage with + `rfft`, `irfft`). + + For full documentation refer to `scipy.fft.rfftfreq`. + + """ + return scipy.fft.rfftfreq(n, d=d, xp=xp, device=device) + + +def fftshift(x, axes=None): + """ + Shift the zero-frequency component to the center of the spectrum. + + For full documentation refer to `scipy.fft.fftshift`. + + """ + from scipy.fft import fftshift + + return fftshift(x, axes=axes) + + +def ifftshift(x, axes=None): + """ + The inverse of `fftshift`. Although identical for even-length `x`, the + functions differ by one sample for odd-length `x`. + + For full documentation refer to `scipy.fft.ifftshift`. + + """ + return scipy.fft.ifftshift(x, axes=axes) + + def get_workers(): """ Gets the number of workers used by mkl_fft by default. diff --git a/mkl_fft/interfaces/_scipy_helper.py b/mkl_fft/interfaces/_scipy_helper.py deleted file mode 100644 index 7f75c30..0000000 --- a/mkl_fft/interfaces/_scipy_helper.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2017, Intel Corporation -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of Intel Corporation nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -FFT helper functions copied from `scipy.fft` (with some modification) to -prevent circular dependencies when patching NumPy. -""" - -import numpy as np -from scipy._lib._array_api import array_namespace - -__all__ = ["fftshift", "ifftshift", "fftfreq", "rfftfreq"] - - -def fftfreq(n, d=1.0, *, xp=None, device=None): - """ - Return the Discrete Fourier Transform sample frequencies. - - For full documentation refer to `scipy.fft.fftfreq`. - - """ - xp = np if xp is None else xp - if hasattr(xp, "fft"): - return xp.fft.fftfreq(n, d=d, device=device) - return np.fft.fftfreq(n, d=d, device=device) - - -def rfftfreq(n, d=1.0, *, xp=None, device=None): - """ - Return the Discrete Fourier Transform sample frequencies (for usage with - `rfft`, `irfft`). - - For full documentation refer to `scipy.fft.rfftfreq`. - - """ - xp = np if xp is None else xp - if hasattr(xp, "fft"): - return xp.fft.rfftfreq(n, d=d, device=device) - return np.fft.rfftfreq(n, d=d, device=device) - - -def fftshift(x, axes=None): - """ - Shift the zero-frequency component to the center of the spectrum. - - For full documentation refer to `scipy.fft.fftshift`. - - """ - xp = array_namespace(x) - if hasattr(xp, "fft"): - return xp.fft.fftshift(x, axes=axes) - x = np.asarray(x) - y = np.fft.fftshift(x, axes=axes) - return xp.asarray(y) - - -def ifftshift(x, axes=None): - """ - The inverse of `fftshift`. Although identical for even-length `x`, the - functions differ by one sample for odd-length `x`. - - For full documentation refer to `scipy.fft.ifftshift`. - - """ - xp = array_namespace(x) - if hasattr(xp, "fft"): - return xp.fft.ifftshift(x, axes=axes) - x = np.asarray(x) - y = np.fft.ifftshift(x, axes=axes) - return xp.asarray(y) diff --git a/mkl_fft/interfaces/scipy_fft.py b/mkl_fft/interfaces/scipy_fft.py index 0f12841..4adce52 100644 --- a/mkl_fft/interfaces/scipy_fft.py +++ b/mkl_fft/interfaces/scipy_fft.py @@ -28,7 +28,9 @@ from ._scipy_fft import ( fft, fft2, + fftfreq, fftn, + fftshift, get_workers, hfft, hfft2, @@ -36,6 +38,7 @@ ifft, ifft2, ifftn, + ifftshift, ihfft, ihfft2, ihfftn, @@ -44,10 +47,10 @@ irfftn, rfft, rfft2, + rfftfreq, rfftn, set_workers, ) -from ._scipy_helper import fftfreq, fftshift, ifftshift, rfftfreq __all__ = [ "fft", From 24b5efa804fe6dc34504484b7642163dae56d88e Mon Sep 17 00:00:00 2001 From: Nikita Grigorian Date: Thu, 9 Oct 2025 07:46:18 -0700 Subject: [PATCH 2/3] add gh-233 to changelog --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abe864e..de58258 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.1.1] - 2025-10-09 + +### Fixed +* Fix a circular dependency in Intel NumPy: revert vendoring of `scipy.fft` functions, instead using thin wrappers to call from `scipy` directly [gh-233](https://github.com/IntelPython/mkl_fft/pull/233) + ## [2.1.0] - 2025-10-06 ### Added @@ -14,7 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Dropped support for `overwrite_x` parameter in `mkl_fft` [gh-185](https://github.com/IntelPython/mkl_fft/pull/185) * Replaced `fwd_scale` parameter with `norm` in `mkl_fft` [gh-189](https://github.com/IntelPython/mkl_fft/pull/189) * Conditionally import `scipy_fft` only if `scipy` is installed [gh-195](https://github.com/IntelPython/mkl_fft/pull/195) -* Added thin wrappers for `fftfreq`, `rfftfreq`, `fftshift`, and `ifftshift` to `scipy_fft` and `numpy_fft` interfaces [gh-226](https://github.com/IntelPython/mkl_fft/pull/226), [gh=229](https://github.com/IntelPython/mkl_fft/pull/229) +* Vendor `fftfreq`, `rfftfreq`, `fftshift`, and `ifftshift` to `scipy_fft` and `numpy_fft` interfaces [gh-226](https://github.com/IntelPython/mkl_fft/pull/226), [gh=229](https://github.com/IntelPython/mkl_fft/pull/229) ### Fixed * Fixed a bug for N-D FFTs when both `s` and `out` are given [gh-185](https://github.com/IntelPython/mkl_fft/pull/185) From fc12a0d69b168161cc03fa418570269ad39ad250 Mon Sep 17 00:00:00 2001 From: Nikita Grigorian Date: Thu, 9 Oct 2025 07:47:40 -0700 Subject: [PATCH 3/3] set version to 2.1.1 --- conda-recipe-cf/meta.yaml | 2 +- mkl_fft/_version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conda-recipe-cf/meta.yaml b/conda-recipe-cf/meta.yaml index d7e3eff..9265287 100644 --- a/conda-recipe-cf/meta.yaml +++ b/conda-recipe-cf/meta.yaml @@ -1,4 +1,4 @@ -{% set version = "2.1.0" %} +{% set version = "2.1.1" %} {% set buildnumber = 0 %} package: diff --git a/mkl_fft/_version.py b/mkl_fft/_version.py index 9aa3f90..58039f5 100644 --- a/mkl_fft/_version.py +++ b/mkl_fft/_version.py @@ -1 +1 @@ -__version__ = "2.1.0" +__version__ = "2.1.1"