Example #1
0
File: fft.py Project: zivzone/cupy
def ifftn(x, s=None, axes=None, norm=None, overwrite_x=False, *, plan=None):
    """Compute the N-dimensional inverse FFT.

    Args:
        x (cupy.ndarray): Array to be transformed.
        s (None or tuple of ints): Shape of the transformed axes of the
            output. If ``s`` is not given, the lengths of the input along
            the axes specified by ``axes`` are used.
        axes (tuple of ints): Axes over which to compute the FFT.
        norm (None or ``'ortho'``): Normalization mode.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.
        plan (:class:`~cupy.cuda.cufft.PlanNd`) a cuFFT plan for transforming
            ``x`` over ``axis``, which can be obtained using::

                plan = cupyx.scipy.fftpack.get_fft_plan(x, s, axes)

            Note that ``plan`` is defaulted to ``None``, meaning CuPy will use
            an auto-generated plan behind the scene.

    Returns:
        cupy.ndarray:
            The transformed array which shape is specified by ``s`` and
            type will convert to complex if that of the input is another.

    .. seealso:: :func:`scipy.fft.ifftn`
    """
    s = _assequence(s)
    axes = _assequence(axes)
    func = _default_fft_func(x, s, axes)
    return func(x, s, axes, norm, cufft.CUFFT_INVERSE, overwrite_x=overwrite_x,
                plan=plan)
Example #2
0
def ifftn(x, shape=None, axes=None, overwrite_x=False, plan=None):
    """Compute the N-dimensional inverse FFT.

    Args:
        x (cupy.ndarray): Array to be transformed.
        shape (None or tuple of ints): Shape of the transformed axes of the
            output. If ``shape`` is not given, the lengths of the input along
            the axes specified by ``axes`` are used.
        axes (tuple of ints): Axes over which to compute the FFT.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.
        plan (cupy.cuda.cufft.PlanNd): a cuFFT plan for transforming ``x``
            over ``axes``, which can be obtained using::

                plan = cupyx.scipy.fftpack.get_fft_plan(x, axes)

            Note that `plan` is defaulted to None, meaning CuPy will either
            use an auto-generated plan behind the scene if cupy.fft.config.
            enable_nd_planning = True, or use no cuFFT plan if it is set to
            False.

    Returns:
        cupy.ndarray:
            The transformed array which shape is specified by ``shape`` and
            type will convert to complex if that of the input is another.

    .. seealso:: :func:`scipy.fftpack.ifftn`

    .. note::
       The argument `plan` is currently experimental and the interface may be
       changed in the future version.
    """
    func = _default_fft_func(x, shape, axes, plan)
    return func(x, shape, axes, None, cufft.CUFFT_INVERSE,
                overwrite_x=overwrite_x, plan=plan)
Example #3
0
File: fft.py Project: zivzone/cupy
def rfftn(x, s=None, axes=None, norm=None, overwrite_x=False, *, plan=None):
    """Compute the N-dimensional FFT for real input.

    Args:
        a (cupy.ndarray): Array to be transform.
        s (None or tuple of ints): Shape to use from the input. If ``s`` is not
            given, the lengths of the input along the axes specified by
            ``axes`` are used.
        axes (tuple of ints): Axes over which to compute the FFT.
        norm (None or ``"ortho"``): Keyword to specify the normalization mode.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.
        plan (None): This argument is currently not supported.

    Returns:
        cupy.ndarray:
            The transformed array which shape is specified by ``s`` and type
            will convert to complex if the input is other. The length of the
            last axis transformed will be ``s[-1]//2+1``.

    .. seealso:: :func:`scipy.fft.rfftn`
    """
    # TODO(leofang): support R2C & C2R plans
    if plan is not None:
        raise NotImplementedError('rfftn plan is currently not yet supported')
    s = _assequence(s)
    axes = _assequence(axes)
    func = _default_fft_func(x, s, axes, value_type='R2C')
    return func(x, s, axes, norm, cufft.CUFFT_FORWARD, 'R2C',
                overwrite_x=overwrite_x)
Example #4
0
def ifft2(x, shape=None, axes=(-2, -1), overwrite_x=False):
    """Compute the two-dimensional inverse FFT.

    Args:
        x (cupy.ndarray): Array to be transformed.
        shape (None or tuple of ints): Shape of the transformed axes of the
            output. If ``shape`` is not given, the lengths of the input along
            the axes specified by ``axes`` are used.
        axes (tuple of ints): Axes over which to compute the FFT.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.

    Returns:
        cupy.ndarray:
            The transformed array which shape is specified by ``shape`` and
            type will convert to complex if that of the input is another.

    .. seealso:: :func:`scipy.fftpack.ifft2`
    """
    func = _default_fft_func(x, shape, axes)
    return func(x,
                shape,
                axes,
                None,
                cufft.CUFFT_INVERSE,
                overwrite_x=overwrite_x)
Example #5
0
    def test_default_fft_func(self, enable_nd):
        # test cases where nd cuFFT plan is possible
        ca = cupy.ones((16, 16, 16))
        for axes in [(0, 1), (1, 2), None, (0, 1, 2)]:
            fft_func = _default_fft_func(ca, axes=axes)
            if enable_nd:
                assert fft_func is _fftn
            else:
                assert fft_func is _fft

        # only a single axis is transformed -> 1d plan preferred
        for axes in [(0, ), (1, ), (2, )]:
            assert _default_fft_func(ca, axes=axes) is _fft

        # non-contiguous axes -> nd plan not possible
        assert _default_fft_func(ca, axes=(0, 2)) is _fft

        # >3 axes transformed -> nd plan not possible
        ca = cupy.ones((2, 4, 6, 8))
        assert _default_fft_func(ca) is _fft

        # first or last axis not included -> nd plan not possible
        assert _default_fft_func(ca, axes=(1, )) is _fft

        # for rfftn
        ca = cupy.random.random((4, 2, 6))
        for s, axes in zip([(3, 4), None, (8, 7, 5)],
                           [(-2, -1), (0, 1), None]):
            fft_func = _default_fft_func(ca, s=s, axes=axes, value_type='R2C')
            if enable_nd:
                assert fft_func is _fftn
            else:
                assert fft_func is _fft

        # nd plan not possible if last axis is not 0 or ndim-1
        assert _default_fft_func(ca, axes=(2, 1), value_type='R2C') is _fft

        # for irfftn
        ca = cupy.random.random((4, 2, 6)).astype(cupy.complex128)
        for s, axes in zip([(3, 4), None, (8, 7, 5)],
                           [(-2, -1), (0, 1), None]):
            fft_func = _default_fft_func(ca, s=s, axes=axes, value_type='C2R')
            if enable_nd:
                assert fft_func is _fftn
            else:
                assert fft_func is _fft

        # nd plan not possible if last axis is not 0 or ndim-1
        assert _default_fft_func(ca, axes=(2, 1), value_type='C2R') is _fft
Example #6
0
 def test_fftn_multiple_plan_error(self, dtype):
     import cupy
     import cupyx.scipy.fftpack as fftpack
     x = testing.shaped_random(self.shape, cupy, dtype)
     # hack: avoid testing the cases when getting a cuFFT plan is impossible
     if _default_fft_func(x, s=self.s, axes=self.axes) is not _fftn:
         return
     plan = fftpack.get_fft_plan(x, shape=self.s, axes=self.axes)
     with pytest.raises(RuntimeError) as ex, plan:
         fftpack.fftn(x, shape=self.s, axes=self.axes, plan=plan)
     assert 'Use the cuFFT plan either as' in str(ex.value)
Example #7
0
    def test_default_fft_func(self, enable_nd):
        # test cases where nd CUFFT plan is possible
        ca = cupy.ones((16, 16, 16))
        for axes in [(0, 1), (1, 2), None, (0, 1, 2)]:
            fft_func = _default_fft_func(ca, axes=axes)
            if enable_nd:
                assert fft_func is _fftn
            else:
                assert fft_func is _fft

        # only a single axis is transformed -> 1d plan preferred
        for axes in [(0, ), (1, ), (2, )]:
            assert _default_fft_func(ca, axes=axes) is _fft

        # non-contiguous axes -> nd plan not possible
        assert _default_fft_func(ca, axes=(0, 2)) is _fft

        # >3 axes transformed -> nd plan not possible
        ca = cupy.ones((2, 4, 6, 8))
        assert _default_fft_func(ca) is _fft

        # first or last axis not included -> nd plan not possible
        assert _default_fft_func(ca, axes=(1, )) is _fft
Example #8
0
 def test_ifftn_plan(self, xp, scp, dtype):
     x = testing.shaped_random(self.shape, xp, dtype)
     # hack: avoid testing the cases when getting a cuFFT plan is impossible
     if _default_fft_func(x, s=self.s, axes=self.axes) is not _fftn:
         return x
     if scp is cupyx.scipy:
         import cupy.fft.config as config
         config.enable_nd_planning = False  # use explicit plan
         plan = scp.fftpack.get_fft_plan(x, shape=self.s, axes=self.axes)
         out = scp.fftpack.ifftn(x, shape=self.s, axes=self.axes, plan=plan)
         config.enable_nd_planning = True  # default
     else:  # scipy
         out = scp.fftpack.ifftn(x, shape=self.s, axes=self.axes)
     return out
Example #9
0
def irfftn(x, s=None, axes=None, norm=None, overwrite_x=False, *, plan=None):
    """Compute the N-dimensional inverse FFT for real input.

    Args:
        a (cupy.ndarray): Array to be transform.
        s (None or tuple of ints): Shape of the output. If ``s`` is not given,
            they are determined from the lengths of the input along the axes
            specified by ``axes``.
        axes (tuple of ints): Axes over which to compute the FFT.
        norm (None or ``"ortho"``): Keyword to specify the normalization mode.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.
        plan (:class:`cupy.cuda.cufft.PlanNd` or ``None``): a cuFFT plan for
            transforming ``x`` over ``axes``, which can be obtained using::

                plan = cupyx.scipy.fftpack.get_fft_plan(x, s, axes,
                                                        value_type='C2R')

            Note that ``plan`` is defaulted to ``None``, meaning CuPy will use
            an auto-generated plan behind the scene.

    Returns:
        cupy.ndarray:
            The transformed array which shape is specified by ``s`` and type
            will convert to complex if the input is other. If ``s`` is not
            given, the length of final transformed axis of output will be
            ``2*(m-1)`` where `m` is the length of the final transformed axis
            of the input.

    .. warning:: The input array may be modified in CUDA 10.1 and above, even
                 when `overwrite_x is False`.

    .. seealso:: :func:`scipy.fft.irfftn`
    """
    s = _assequence(s)
    axes = _assequence(axes)
    if (10020 >= cupy.cuda.runtime.runtimeGetVersion() >= 10010
            and int(cupy.cuda.device.get_compute_capability()) < 70
            and _size_last_transform_axis(x.shape, s, axes) == 2):
        warnings.warn('Output of irfftn might not be correct due to issue '
                      'of cuFFT in CUDA 10.1/10.2 on Pascal or older GPUs.')
    func = _default_fft_func(x, s, axes, value_type='C2R')
    return func(x,
                s,
                axes,
                norm,
                cufft.CUFFT_INVERSE,
                'C2R',
                overwrite_x=overwrite_x,
                plan=plan)
Example #10
0
 def test_ifftn_plan_manager(self, xp, scp, dtype):
     x = testing.shaped_random(self.shape, xp, dtype)
     # hack: avoid testing the cases when getting a cuFFT plan is impossible
     if _default_fft_func(x, s=self.s, axes=self.axes) is not _fftn:
         return x
     if scp is cupyx.scipy:
         from cupy.cuda.cufft import get_current_plan
         plan = scp.fftpack.get_fft_plan(x, shape=self.s, axes=self.axes)
         with plan:
             assert id(plan) == id(get_current_plan())
             out = scp.fftpack.ifftn(x, shape=self.s, axes=self.axes)
         assert get_current_plan() is None
     else:  # scipy
         out = scp.fftpack.ifftn(x, shape=self.s, axes=self.axes)
     return out
Example #11
0
    def test_fftn_orders(self, dtype, enable_nd):
        for order in ['C', 'F']:
            a = testing.shaped_random(self.shape, cupy, dtype)
            if order == 'F':
                a = cupy.asfortranarray(a)
            out = cupy.fft.fftn(a, s=self.s, axes=self.axes)

            fft_func = _default_fft_func(a, s=self.s, axes=self.axes)
            if fft_func is _fftn:
                # nd plans have output with contiguity matching the input
                self.assertEqual(out.flags.c_contiguous, a.flags.c_contiguous)
                self.assertEqual(out.flags.f_contiguous, a.flags.f_contiguous)
            else:
                # 1d planning case doesn't guarantee preserved contiguity
                pass
Example #12
0
 def test_ifftn_plan_manager(self, xp, dtype):
     x = testing.shaped_random(self.shape, xp, dtype)
     # hack: avoid testing the cases when getting a cuFFT plan is impossible
     if _default_fft_func(x, s=self.s, axes=self.axes) is not _fftn:
         return x
     x_orig = x.copy()
     if xp is cp:
         from cupy.cuda.cufft import get_current_plan
         plan = _fft_module(xp).get_fft_plan(x,
                                             shape=self.s,
                                             axes=self.axes)
         with plan:
             assert id(plan) == id(get_current_plan())
             out = _fft_module(xp).ifftn(x, s=self.s, axes=self.axes)
         assert get_current_plan() is None
     else:
         out = _fft_module(xp).ifftn(x, s=self.s, axes=self.axes)
     testing.assert_array_equal(x, x_orig)
     return _correct_np_dtype(xp, dtype, out)
Example #13
0
 def test_ifftn_overwrite_plan(self, xp, dtype):
     x = testing.shaped_random(self.shape, xp, dtype)
     # hack: avoid testing the cases when getting a cuFFT plan is impossible
     if _default_fft_func(x, s=self.s, axes=self.axes) is not _fftn:
         return x
     if xp is cp:
         overwrite_kw = {
             'plan':
             _fft_module(xp).get_fft_plan(x, shape=self.s, axes=self.axes),
             'overwrite_x':
             True
         }
     else:
         overwrite_kw = {}
     out = _fft_module(xp).ifftn(x,
                                 s=self.s,
                                 axes=self.axes,
                                 norm=self.norm,
                                 **overwrite_kw)
     return _correct_np_dtype(xp, dtype, out)
Example #14
0
 def test_ifftn_plan(self, xp, dtype):
     x = testing.shaped_random(self.shape, xp, dtype)
     # hack: avoid testing the cases when getting a cuFFT plan is impossible
     if _default_fft_func(x, s=self.s, axes=self.axes) is not _fftn:
         return x
     x_orig = x.copy()
     if xp is cp:
         overwrite_kw = {
             'plan':
             _fft_module(xp).get_fft_plan(x, shape=self.s, axes=self.axes)
         }
     else:
         overwrite_kw = {}
     out = _fft_module(xp).ifftn(x,
                                 s=self.s,
                                 axes=self.axes,
                                 norm=self.norm,
                                 **overwrite_kw)
     testing.assert_array_equal(x, x_orig)
     return _correct_np_dtype(xp, dtype, out)
Example #15
0
def rfftn(x, s=None, axes=None, norm=None, overwrite_x=False, *, plan=None):
    """Compute the N-dimensional FFT for real input.

    Args:
        a (cupy.ndarray): Array to be transform.
        s (None or tuple of ints): Shape to use from the input. If ``s`` is not
            given, the lengths of the input along the axes specified by
            ``axes`` are used.
        axes (tuple of ints): Axes over which to compute the FFT.
        norm (None or ``"ortho"``): Keyword to specify the normalization mode.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.
        plan (:class:`cupy.cuda.cufft.PlanNd` or ``None``): a cuFFT plan for
            transforming ``x`` over ``axes``, which can be obtained using::

                plan = cupyx.scipy.fftpack.get_fft_plan(x, s, axes,
                                                        value_type='R2C')

            Note that ``plan`` is defaulted to ``None``, meaning CuPy will use
            an auto-generated plan behind the scene.

    Returns:
        cupy.ndarray:
            The transformed array which shape is specified by ``s`` and type
            will convert to complex if the input is other. The length of the
            last axis transformed will be ``s[-1]//2+1``.

    .. seealso:: :func:`scipy.fft.rfftn`
    """
    s = _assequence(s)
    axes = _assequence(axes)
    func = _default_fft_func(x, s, axes, value_type='R2C')
    return func(x,
                s,
                axes,
                norm,
                cufft.CUFFT_FORWARD,
                'R2C',
                overwrite_x=overwrite_x,
                plan=plan)
Example #16
0
File: fft.py Project: yuhc/ava-cupy
def ifftn(x, s=None, axes=None, norm=None, overwrite_x=False):
    """Compute the N-dimensional inverse FFT.

    Args:
        x (cupy.ndarray): Array to be transformed.
        s (None or tuple of ints): Shape of the transformed axes of the
            output. If ``s`` is not given, the lengths of the input along
            the axes specified by ``axes`` are used.
        axes (tuple of ints): Axes over which to compute the FFT.
        norm (None or ``'ortho'``): Normalization mode.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.

    Returns:
        cupy.ndarray:
            The transformed array which shape is specified by ``s`` and
            type will convert to complex if that of the input is another.

    .. seealso:: :func:`scipy.fft.ifftn`
    """
    s = _assequence(s)
    axes = _assequence(axes)
    func = _default_fft_func(x, s, axes)
    return func(x, s, axes, norm, cufft.CUFFT_INVERSE, overwrite_x=overwrite_x)
Example #17
0
File: fft.py Project: zivzone/cupy
def irfftn(x, s=None, axes=None, norm=None, overwrite_x=False, *, plan=None):
    """Compute the N-dimensional inverse FFT for real input.

    Args:
        a (cupy.ndarray): Array to be transform.
        s (None or tuple of ints): Shape of the output. If ``s`` is not given,
            they are determined from the lengths of the input along the axes
            specified by ``axes``.
        axes (tuple of ints): Axes over which to compute the FFT.
        norm (None or ``"ortho"``): Keyword to specify the normalization mode.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.
        plan (None): This argument is currently not supported.

    Returns:
        cupy.ndarray:
            The transformed array which shape is specified by ``s`` and type
            will convert to complex if the input is other. If ``s`` is not
            given, the length of final transformed axis of output will be
            ``2*(m-1)`` where `m` is the length of the final transformed axis
            of the input.

    .. seealso:: :func:`scipy.fft.irfftn`
    """
    # TODO(leofang): support R2C & C2R plans
    if plan is not None:
        raise NotImplementedError('irfftn plan is currently not yet supported')
    s = _assequence(s)
    axes = _assequence(axes)
    if (10020 >= cupy.cuda.runtime.runtimeGetVersion() >= 10010
            and int(cupy.cuda.device.get_compute_capability()) < 70
            and _size_last_transform_axis(x.shape, s, axes) == 2):
        warnings.warn('Output of irfftn might not be correct due to issue '
                      'of cuFFT in CUDA 10.1/10.2 on Pascal or older GPUs.')
    func = _default_fft_func(x, s, axes, value_type='C2R')
    return func(x, s, axes, norm, cufft.CUFFT_INVERSE, 'C2R',
                overwrite_x=overwrite_x)