From 56ae34a3082cea0d0ba19599602373dd009c6713 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 25 Mar 2025 10:51:10 +0100 Subject: [PATCH 1/6] Add dtype to fftfreq/rfftfreq --- dpnp/fft/dpnp_iface_fft.py | 52 ++++++++++++++++++++++++++------------ dpnp/fft/dpnp_utils_fft.py | 16 ++++++++++++ 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/dpnp/fft/dpnp_iface_fft.py b/dpnp/fft/dpnp_iface_fft.py index c82daad70d0..af0305d6bd5 100644 --- a/dpnp/fft/dpnp_iface_fft.py +++ b/dpnp/fft/dpnp_iface_fft.py @@ -41,6 +41,7 @@ from .dpnp_utils_fft import ( dpnp_fft, dpnp_fftn, + dpnp_fillfreq, ) __all__ = [ @@ -257,7 +258,9 @@ def fft2(a, s=None, axes=(-2, -1), norm=None, out=None): ) -def fftfreq(n, d=1.0, device=None, usm_type=None, sycl_queue=None): +def fftfreq( + n, /, *, d=1.0, dtype=None, device=None, usm_type=None, sycl_queue=None +): """ Return the Discrete Fourier Transform sample frequencies. @@ -279,6 +282,12 @@ def fftfreq(n, d=1.0, device=None, usm_type=None, sycl_queue=None): d : scalar, optional Sample spacing (inverse of the sampling rate). Default: ``1.0``. + dtype : {None, str, dtype object}, optional + The output array data type. Must be a real-valued floating-point data + type. If `dtype` is ``None``, the output array data type must be the + default real-valued floating-point data type. + + Default: ``None``. device : {None, string, SyclDevice, SyclQueue, Device}, optional An array API concept of device where the output array is created. `device` can be ``None``, a oneAPI filter selector string, an instance @@ -342,23 +351,19 @@ def fftfreq(n, d=1.0, device=None, usm_type=None, sycl_queue=None): if not dpnp.isscalar(d): raise ValueError("`d` should be an scalar") - cfd_kwarg = { - "device": device, - "usm_type": usm_type, - "sycl_queue": sycl_queue, - } + if dtype and not dpnp.issubdtype(dtype, dpnp.floating): + raise ValueError( + "dtype must a real-valued floating-point data type, " + f"but got {dtype}" + ) val = 1.0 / (n * d) - results = dpnp.empty(n, dtype=dpnp.intp, **cfd_kwarg) + results = dpnp.empty( + n, dtype=dtype, device=device, usm_type=usm_type, sycl_queue=sycl_queue + ) m = (n - 1) // 2 + 1 - p1 = dpnp.arange(0, m, dtype=dpnp.intp, **cfd_kwarg) - - results[:m] = p1 - p2 = dpnp.arange(m - n, 0, dtype=dpnp.intp, **cfd_kwarg) - - results[m:] = p2 - return results * val + return dpnp_fillfreq(results, m, n, val) def fftn(a, s=None, axes=None, norm=None, out=None): @@ -1507,7 +1512,9 @@ def rfft2(a, s=None, axes=(-2, -1), norm=None, out=None): ) -def rfftfreq(n, d=1.0, device=None, usm_type=None, sycl_queue=None): +def rfftfreq( + n, /, *, d=1.0, dtype=None, device=None, usm_type=None, sycl_queue=None +): """ Return the Discrete Fourier Transform sample frequencies (for usage with :obj:`dpnp.fft.rfft`, :obj:`dpnp.fft.irfft`). @@ -1533,6 +1540,12 @@ def rfftfreq(n, d=1.0, device=None, usm_type=None, sycl_queue=None): d : scalar, optional Sample spacing (inverse of the sampling rate). Default: ``1.0``. + dtype : {None, str, dtype object}, optional + The output array data type. Must be a real-valued floating-point data + type. If `dtype` is ``None``, the output array data type must be the + default real-valued floating-point data type. + + Default: ``None``. device : {None, string, SyclDevice, SyclQueue, Device}, optional An array API concept of device where the output array is created. `device` can be ``None``, a oneAPI filter selector string, an instance @@ -1598,12 +1611,19 @@ def rfftfreq(n, d=1.0, device=None, usm_type=None, sycl_queue=None): raise ValueError("`n` should be an integer") if not dpnp.isscalar(d): raise ValueError("`d` should be an scalar") + + if dtype and not dpnp.issubdtype(dtype, dpnp.floating): + raise ValueError( + "dtype must a real-valued floating-point data type, " + f"but got {dtype}" + ) + val = 1.0 / (n * d) m = n // 2 + 1 results = dpnp.arange( 0, m, - dtype=dpnp.intp, + dtype=dtype, device=device, usm_type=usm_type, sycl_queue=sycl_queue, diff --git a/dpnp/fft/dpnp_utils_fft.py b/dpnp/fft/dpnp_utils_fft.py index c6978eddb12..2da2735df83 100644 --- a/dpnp/fft/dpnp_utils_fft.py +++ b/dpnp/fft/dpnp_utils_fft.py @@ -60,6 +60,7 @@ __all__ = [ "dpnp_fft", "dpnp_fftn", + "dpnp_fillfreq", ] @@ -698,3 +699,18 @@ def dpnp_fftn(a, forward, real, s=None, axes=None, norm=None, out=None): return _complex_nd_fft( a, s, norm, out, forward, in_place, c2c, axes, a.ndim != len_axes ) + + +def dpnp_fillfreq(a, m, n, val): + """Fill an array with the sample frequencies""" + + exec_q = a.sycl_queue + _manager = dpctl.utils.SequentialOrderManager[exec_q] + + # it's assumed there is no dependent events to fill the array + ht_lin_ev, lin_ev = ti._linspace_step(0, m, a[:m].get_array(), exec_q) + _manager.add_event_pair(ht_lin_ev, lin_ev) + + ht_lin_ev, lin_ev = ti._linspace_step(m - n, 0, a[m:].get_array(), exec_q) + _manager.add_event_pair(ht_lin_ev, lin_ev) + return a * val From 4f4921de801aac43133555397aede43e4c2c396e Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 25 Mar 2025 11:14:40 +0100 Subject: [PATCH 2/6] Add a blank line prior Defaults in docstrings --- dpnp/fft/dpnp_iface_fft.py | 126 ++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 24 deletions(-) diff --git a/dpnp/fft/dpnp_iface_fft.py b/dpnp/fft/dpnp_iface_fft.py index af0305d6bd5..403a735d67f 100644 --- a/dpnp/fft/dpnp_iface_fft.py +++ b/dpnp/fft/dpnp_iface_fft.py @@ -102,19 +102,24 @@ def fft(a, n=None, axis=-1, norm=None, out=None): If `n` is smaller than the length of the input, the input is cropped. If it is larger, the input is padded with zeros. If `n` is not given, the length of the input along the axis specified by `axis` is used. + Default: ``None``. axis : int, optional Axis over which to compute the FFT. If not given, the last axis is - used. Default: ``-1``. + used. + + Default: ``-1``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray or usm_ndarray of complex dtype}, optional If provided, the result will be placed in this array. It should be of the appropriate shape (consistent with the choice of `n`) and dtype. + Default: ``None``. Returns @@ -184,7 +189,9 @@ def fft2(a, s=None, axes=(-2, -1), norm=None, out=None): If it is ``-1``, the whole input is used (no padding/trimming). If `s` is not given, the shape of the input along the axes specified by `axes` is used. If `s` is not ``None``, `axes` must not be ``None`` - either. Default: ``None``. + either. + + Default: ``None``. axes : {None, sequence of ints}, optional Axes over which to compute the FFT. If not given, the last two axes are used. A repeated index in `axes` means the transform over that axis is @@ -192,16 +199,19 @@ def fft2(a, s=None, axes=(-2, -1), norm=None, out=None): to be transformed must be explicitly specified too. A one-element sequence means that a one-dimensional FFT is performed. An empty sequence means that no FFT is performed. + Default: ``(-2, -1)``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray or usm_ndarray of complex dtype}, optional If provided, the result will be placed in this array. It should be of the appropriate shape (consistent with the choice of `s`) and dtype. + Default: ``None``. Returns @@ -281,6 +291,7 @@ def fftfreq( Window length. d : scalar, optional Sample spacing (inverse of the sampling rate). + Default: ``1.0``. dtype : {None, str, dtype object}, optional The output array data type. Must be a real-valued floating-point data @@ -299,12 +310,14 @@ def fftfreq( Default: ``None``. usm_type : {None, "device", "shared", "host"}, optional The type of SYCL USM allocation for the output array. + Default: ``None``. sycl_queue : {None, SyclQueue}, optional A SYCL queue to use for output array allocation and copying. The `sycl_queue` can be passed as ``None`` (the default), which means to get the SYCL queue from `device` keyword if present or to use a default queue. + Default: ``None``. Returns @@ -389,7 +402,9 @@ def fftn(a, s=None, axes=None, norm=None, out=None): If it is ``-1``, the whole input is used (no padding/trimming). If `s` is not given, the shape of the input along the axes specified by `axes` is used. If `s` is not ``None``, `axes` must not be ``None`` - either. Default: ``None``. + either. + + Default: ``None``. axes : {None, sequence of ints}, optional Axes over which to compute the FFT. If not given, the last ``len(s)`` axes are used, or all axes if `s` is also not specified. @@ -398,16 +413,19 @@ def fftn(a, s=None, axes=None, norm=None, out=None): to be transformed must be explicitly specified too. A one-element sequence means that a one-dimensional FFT is performed. An empty sequence means that no FFT is performed. + Default: ``None``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray or usm_ndarray of complex dtype}, optional If provided, the result will be placed in this array. It should be of the appropriate shape (consistent with the choice of `s`) and dtype. + Default: ``None``. Returns @@ -481,8 +499,9 @@ def fftshift(x, axes=None): x : {dpnp.ndarray, usm_ndarray} Input array. axes : {None, int, list or tuple of ints}, optional - Axes over which to shift. - Default is ``None``, which shifts all axes. + Axes over which to shift. By default, it shifts over all axes. + + Default: ``None``. Returns ------- @@ -546,19 +565,25 @@ def hfft(a, n=None, axis=-1, norm=None, out=None): input is longer than this, it is cropped. If it is shorter than this, it is padded with zeros. If `n` is not given, it is taken to be ``2*(m-1)`` where `m` is the length of the input along the axis - specified by `axis`. Default: ``None``. + specified by `axis`. + + Default: ``None``. axis : int, optional Axis over which to compute the FFT. If not given, the last axis is - used. Default: ``-1``. + used. + + Default: ``-1``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray, usm_ndarray}, optional If provided, the result will be placed in this array. It should be of the appropriate shape and dtype. + Default: ``None``. Returns @@ -656,19 +681,24 @@ def ifft(a, n=None, axis=-1, norm=None, out=None): If `n` is smaller than the length of the input, the input is cropped. If it is larger, the input is padded with zeros. If `n` is not given, the length of the input along the axis specified by `axis` is used. + Default: ``None``. axis : int, optional Axis over which to compute the inverse FFT. If not given, the last - axis is used. Default: ``-1``. - norm : {"backward", "ortho", "forward"}, optional + axis is used. + + Default: ``-1``. + norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray or usm_ndarray of complex dtype}, optional If provided, the result will be placed in this array. It should be of the appropriate shape (consistent with the choice of `n`) and dtype. + Default: ``None``. Returns @@ -741,7 +771,9 @@ def ifft2(a, s=None, axes=(-2, -1), norm=None, out=None): If `s` is not given, the shape of the input along the axes specified by `axes` is used. See notes for issue on :obj:`dpnp.fft.ifft` zero padding. If `s` is not ``None``, `axes` must not be ``None`` - either. Default: ``None``. + either. + + Default: ``None``. axes : {None, sequence of ints}, optional Axes over which to compute the inverse FFT. If not given, the last two axes are used. A repeated index in `axes` means the transform over that @@ -749,16 +781,19 @@ def ifft2(a, s=None, axes=(-2, -1), norm=None, out=None): corresponding `axes` to be transformed must be explicitly specified too. A one-element sequence means that a one-dimensional FFT is performed. An empty sequence means that no FFT is performed. + Default: ``(-2, -1)``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray or usm_ndarray of complex dtype}, optional If provided, the result will be placed in this array. It should be of the appropriate shape (consistent with the choice of `s`) and dtype. + Default: ``None``. Returns @@ -839,7 +874,9 @@ def ifftn(a, s=None, axes=None, norm=None, out=None): If it is ``-1``, the whole input is used (no padding/trimming). if `s` is not given, the shape of the input along the axes specified by `axes` is used. If `s` is not ``None``, `axes` must not be ``None`` - either. Default: ``None``. + either. + + Default: ``None``. axes : {None, sequence of ints}, optional Axes over which to compute the inverse FFT. If not given, the last ``len(s)`` axes are used, or all axes if `s` is also not specified. @@ -848,16 +885,19 @@ def ifftn(a, s=None, axes=None, norm=None, out=None): to be transformed must be explicitly specified too. A one-element sequence means that a one-dimensional FFT is performed. An empty sequence means that no FFT is performed. + Default: ``None``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray or usm_ndarray of complex dtype}, optional If provided, the result will be placed in this array. It should be of the appropriate shape (consistent with the choice of `s`) and dtype. + Default: ``None``. Returns @@ -919,8 +959,9 @@ def ifftshift(x, axes=None): x : {dpnp.ndarray, usm_ndarray} Input array. axes : {None, int, list or tuple of ints}, optional - Axes over which to calculate. - Defaults to ``None``, which shifts all axes. + Axes over which to shift. By default, it shifts over all axes. + + Default: ``None``. Returns ------- @@ -976,19 +1017,24 @@ def ihfft(a, n=None, axis=-1, norm=None, out=None): the length of the input, the input is cropped. If it is larger, the input is padded with zeros. If `n` is not given, the length of the input along the axis specified by `axis` is used. + Default: ``None``. axis : int, optional Axis over which to compute the FFT. If not given, the last axis is - used. Default: ``-1``. + used. + + Default: ``-1``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray or usm_ndarray of complex dtype}, optional If provided, the result will be placed in this array. It should be of the appropriate shape and dtype. + Default: ``None``. Returns @@ -1060,19 +1106,25 @@ def irfft(a, n=None, axis=-1, norm=None, out=None): input is longer than this, it is cropped. If it is shorter than this, it is padded with zeros. If `n` is not given, it is taken to be ``2*(m-1)`` where `m` is the length of the input along the axis - specified by `axis`. Default: ``None``. + specified by `axis`. + + Default: ``None``. axis : int, optional Axis over which to compute the FFT. If not given, the last axis is - used. Default: ``-1``. + used. + + Default: ``-1``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray, usm_ndarray}, optional If provided, the result will be placed in this array. It should be of the appropriate shape and dtype. + Default: ``None``. Returns @@ -1158,7 +1210,8 @@ def irfft2(a, s=None, axes=(-2, -1), norm=None, out=None): If `s` is not given, the shape of the input along the axes specified by `axes` is used. Except for the last axis which is taken to be ``2*(m-1)`` where `m` is the length of the input along that axis. - If `s` is not ``None``, `axes` must not be ``None`` + If `s` is not ``None``, `axes` must not be ``None`` either. + Default: ``None``. axes : {None, sequence of ints}, optional Axes over which to compute the inverse FFT. If not given, the last @@ -1168,17 +1221,20 @@ def irfft2(a, s=None, axes=(-2, -1), norm=None, out=None): to be transformed must be explicitly specified too. A one-element sequence means that a one-dimensional FFT is performed. An empty sequence means that no FFT is performed. + Default: ``(-2, -1)``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. - out : {None, dpnp.ndarray or usm_ndarray}, optional + out : {None, dpnp.ndarray, usm_ndarray}, optional If provided, the result will be placed in this array. It should be of the appropriate dtype and shape for the last transformation (consistent with the choice of `s`). + Default: ``None``. Returns @@ -1255,9 +1311,10 @@ def irfftn(a, s=None, axes=None, norm=None, out=None): the input is cropped. If it is larger, the input is padded with zeros. If it is ``-1``, the whole input is used (no padding/trimming). If `s` is not given, the shape of the input along the axes - specified by axes is used. Except for the last axis which is taken to + specified by `axes` is used. Except for the last axis which is taken to be ``2*(m-1)`` where `m` is the length of the input along that axis. - If `s` is not ``None``, `axes` must not be ``None`` + If `s` is not ``None``, `axes` must not be ``None`` either. + Default: ``None``. axes : {None, sequence of ints}, optional Axes over which to compute the inverse FFT. If not given, the last @@ -1267,17 +1324,20 @@ def irfftn(a, s=None, axes=None, norm=None, out=None): to be transformed must be explicitly specified too. A one-element sequence means that a one-dimensional FFT is performed. An empty sequence means that no FFT is performed. + Default: ``None``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. - out : {None, dpnp.ndarray or usm_ndarray}, optional + out : {None, dpnp.ndarray, usm_ndarray}, optional If provided, the result will be placed in this array. It should be of the appropriate dtype and shape for the last transformation (consistent with the choice of `s`). + Default: ``None``. Returns @@ -1361,19 +1421,24 @@ def rfft(a, n=None, axis=-1, norm=None, out=None): If `n` is smaller than the length of the input, the input is cropped. If it is larger, the input is padded with zeros. If `n` is not given, the length of the input along the axis specified by `axis` is used. + Default: ``None``. axis : int, optional Axis over which to compute the FFT. If not given, the last axis is - used. Default: ``-1``. + used. + + Default: ``-1``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray or usm_ndarray of complex dtype}, optional If provided, the result will be placed in this array. It should be of the appropriate shape and dtype. + Default: ``None``. Returns @@ -1453,7 +1518,9 @@ def rfft2(a, s=None, axes=(-2, -1), norm=None, out=None): If it is ``-1``, the whole input is used (no padding/trimming). If `s` is not given, the shape of the input along the axes specified by `axes` is used. If `s` is not ``None``, `axes` must not be ``None`` - either. Default: ``None``. + either. + + Default: ``None``. axes : {None, sequence of ints}, optional Axes over which to compute the FFT. If not given, the last two axes are used. A repeated index in `axes` means the transform over that axis is @@ -1461,17 +1528,20 @@ def rfft2(a, s=None, axes=(-2, -1), norm=None, out=None): to be transformed must be explicitly specified too. A one-element sequence means that a one-dimensional FFT is performed. An empty sequence means that no FFT is performed. + Default: ``(-2, -1)``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray or usm_ndarray of complex dtype}, optional If provided, the result will be placed in this array. It should be of the appropriate dtype and shape for the last transformation (consistent with the choice of `s`). + Default: ``None``. Returns @@ -1539,6 +1609,7 @@ def rfftfreq( Window length. d : scalar, optional Sample spacing (inverse of the sampling rate). + Default: ``1.0``. dtype : {None, str, dtype object}, optional The output array data type. Must be a real-valued floating-point data @@ -1557,12 +1628,14 @@ def rfftfreq( Default: ``None``. usm_type : {None, "device", "shared", "host"}, optional The type of SYCL USM allocation for the output array. + Default: ``None``. sycl_queue : {None, SyclQueue}, optional A SYCL queue to use for output array allocation and copying. The `sycl_queue` can be passed as ``None`` (the default), which means to get the SYCL queue from `device` keyword if present or to use a default queue. + Default: ``None``. Returns @@ -1657,7 +1730,9 @@ def rfftn(a, s=None, axes=None, norm=None, out=None): If it is ``-1``, the whole input is used (no padding/trimming). If `s` is not given, the shape of the input along the axes specified by `axes` is used. If `s` is not ``None``, `axes` must not be ``None`` - either. Default: ``None``. + either. + + Default: ``None``. axes : {None, sequence of ints}, optional Axes over which to compute the FFT. If not given, the last ``len(s)`` axes are used, or all axes if `s` is also not specified. @@ -1666,17 +1741,20 @@ def rfftn(a, s=None, axes=None, norm=None, out=None): to be transformed must be explicitly specified too. A one-element sequence means that a one-dimensional FFT is performed. An empty sequence means that no FFT is performed. + Default: ``None``. norm : {None, "backward", "ortho", "forward"}, optional Normalization mode (see :obj:`dpnp.fft`). Indicates which direction of the forward/backward pair of transforms is scaled and with what normalization factor. ``None`` is an alias of the default option ``"backward"``. + Default: ``"backward"``. out : {None, dpnp.ndarray or usm_ndarray of complex dtype}, optional If provided, the result will be placed in this array. It should be of the appropriate dtype and shape for the last transformation (consistent with the choice of `s`). + Default: ``None``. Returns From 3857ffcdffb417591df9dac086c9315624a22a19 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 25 Mar 2025 11:47:10 +0100 Subject: [PATCH 3/6] Resolve issues detected by legacing testing --- dpnp/fft/dpnp_iface_fft.py | 4 ++-- dpnp/fft/dpnp_utils_fft.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dpnp/fft/dpnp_iface_fft.py b/dpnp/fft/dpnp_iface_fft.py index 403a735d67f..52753e5362e 100644 --- a/dpnp/fft/dpnp_iface_fft.py +++ b/dpnp/fft/dpnp_iface_fft.py @@ -269,7 +269,7 @@ def fft2(a, s=None, axes=(-2, -1), norm=None, out=None): def fftfreq( - n, /, *, d=1.0, dtype=None, device=None, usm_type=None, sycl_queue=None + n, /, d=1.0, *, dtype=None, device=None, usm_type=None, sycl_queue=None ): """ Return the Discrete Fourier Transform sample frequencies. @@ -1583,7 +1583,7 @@ def rfft2(a, s=None, axes=(-2, -1), norm=None, out=None): def rfftfreq( - n, /, *, d=1.0, dtype=None, device=None, usm_type=None, sycl_queue=None + n, /, d=1.0, *, dtype=None, device=None, usm_type=None, sycl_queue=None ): """ Return the Discrete Fourier Transform sample frequencies diff --git a/dpnp/fft/dpnp_utils_fft.py b/dpnp/fft/dpnp_utils_fft.py index 2da2735df83..2266c4c624e 100644 --- a/dpnp/fft/dpnp_utils_fft.py +++ b/dpnp/fft/dpnp_utils_fft.py @@ -708,9 +708,9 @@ def dpnp_fillfreq(a, m, n, val): _manager = dpctl.utils.SequentialOrderManager[exec_q] # it's assumed there is no dependent events to fill the array - ht_lin_ev, lin_ev = ti._linspace_step(0, m, a[:m].get_array(), exec_q) + ht_lin_ev, lin_ev = ti._linspace_step(0, 1, a[:m].get_array(), exec_q) _manager.add_event_pair(ht_lin_ev, lin_ev) - ht_lin_ev, lin_ev = ti._linspace_step(m - n, 0, a[m:].get_array(), exec_q) + ht_lin_ev, lin_ev = ti._linspace_step(m - n, 1, a[m:].get_array(), exec_q) _manager.add_event_pair(ht_lin_ev, lin_ev) return a * val From cb055f197b8b1bf6fb1a36ef009940175b34e5be Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 25 Mar 2025 11:49:01 +0100 Subject: [PATCH 4/6] Update the comment where pipulating input array with frequencies --- dpnp/fft/dpnp_utils_fft.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpnp/fft/dpnp_utils_fft.py b/dpnp/fft/dpnp_utils_fft.py index 2266c4c624e..1393d22255e 100644 --- a/dpnp/fft/dpnp_utils_fft.py +++ b/dpnp/fft/dpnp_utils_fft.py @@ -707,7 +707,7 @@ def dpnp_fillfreq(a, m, n, val): exec_q = a.sycl_queue _manager = dpctl.utils.SequentialOrderManager[exec_q] - # it's assumed there is no dependent events to fill the array + # it's assumed there are no dependent events to populate the array ht_lin_ev, lin_ev = ti._linspace_step(0, 1, a[:m].get_array(), exec_q) _manager.add_event_pair(ht_lin_ev, lin_ev) From 3e3bd0abf3338af1278bddf0e76c35b404524ba4 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 25 Mar 2025 11:58:11 +0100 Subject: [PATCH 5/6] Add tests for dtype keyword --- dpnp/tests/test_fft.py | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/dpnp/tests/test_fft.py b/dpnp/tests/test_fft.py index b60ecbba2b5..8a65d2857a7 100644 --- a/dpnp/tests/test_fft.py +++ b/dpnp/tests/test_fft.py @@ -411,22 +411,35 @@ def test_fft_error(self, xp): assert_raises(IndexError, xp.fft.fft2, a) +@pytest.mark.parametrize("func", ["fftfreq", "rfftfreq"]) class TestFftfreq: - @pytest.mark.parametrize("func", ["fftfreq", "rfftfreq"]) @pytest.mark.parametrize("n", [10, 20]) @pytest.mark.parametrize("d", [0.5, 2]) def test_fftfreq(self, func, n, d): - expected = getattr(dpnp.fft, func)(n, d) - result = getattr(numpy.fft, func)(n, d) - assert_dtype_allclose(expected, result) + result = getattr(dpnp.fft, func)(n, d) + expected = getattr(numpy.fft, func)(n, d) + assert_dtype_allclose(result, expected) - @pytest.mark.parametrize("func", ["fftfreq", "rfftfreq"]) - def test_error(self, func): - # n should be an integer - assert_raises(ValueError, getattr(dpnp.fft, func), 10.0) + @pytest.mark.parametrize("dt", [None] + get_float_dtypes()) + def test_dtype(self, func, dt): + n = 15 + result = getattr(dpnp.fft, func)(n, dtype=dt) + expected = getattr(numpy.fft, func)(n).astype(dt) + assert_dtype_allclose(result, expected) - # d should be an scalar - assert_raises(ValueError, getattr(dpnp.fft, func), 10, (2,)) + def test_error(self, func): + func = getattr(dpnp.fft, func) + # n must be an integer + assert_raises(ValueError, func, 10.0) + + # d must be an scalar + assert_raises(ValueError, func, 10, (2,)) + + # dtype must be None or a real-valued floating-point dtype + # which is passed as a keyword argument only + assert_raises(TypeError, func, 10, 2, None) + assert_raises(ValueError, func, 10, 2, dtype=dpnp.intp) + assert_raises(ValueError, func, 10, 2, dtype=dpnp.complex64) class TestFftn: From fd45a546c2d01bbbbe549326960ad152da47a7dc Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 25 Mar 2025 12:10:09 +0100 Subject: [PATCH 6/6] Add entry to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb1c5b78f90..2a64541ae09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +* Extended `dpnp.fft.fftfreq` and `dpnp.fft.rfftfreq` functions to support `dtype` keyword per Python Array API spec 2024.12 [#2384](https://github.com/IntelPython/dpnp/pull/2384) * Allowed input array of `uint64` dtype in `dpnp.bincount` [#2361](https://github.com/IntelPython/dpnp/pull/2361) * The vector norms `ord={None, 1, 2, inf}` and the matrix norms `ord={None, 1, 2, inf, "fro", "nuc"}` now consistently return zero for empty arrays, which are arrays with at least one axis of size zero. This change affects `dpnp.linalg.norm`, `dpnp.linalg.vector_norm`, and `dpnp.linalg.matrix_norm`. Previously, dpnp would either raise errors or return zero depending on the parameters provided [#2371](https://github.com/IntelPython/dpnp/pull/2371)