o
    iL                     @   s   d dl mZ d dlZd dlmZ d dlmZmZmZm	Z	m
Z
mZ d dlmZ dddZdddZdddZdddZdddZdddZdddZdddZd ddZdS )!    )prodN)config)_convert_fft_type_default_fft_func_fft_get_cufft_plan_nd_get_fftn_out_size_output_dtype)get_plan_cacheC2Cc                 C   s  ddl m} | jjrd}n| jjrd}ntdt|tr |f}t|tr(|f}|dur<|dur<t|t|kr<td|du r_|du rG| j	nt|}t
dd	 t| dD }|d
kr^d}n+t|}|d
kr|d }|| j	ksv|| j	 k rd|| j	}t|n|dkrtd|}	t| j}|	durt|	|D ]\}
}|
dur||d kr|dkr|
d d
 }
|
||< qt
|}t| j|}t||}|d
kr|dkr| jjrtd|d
krtjjjr|dkrtdt||	|d |}t|||||dd}|S |dkr|| }nt||	||}t|||  }tjsdntj}||||f}t }|durO|j}|j }||j!|j"|du r?dn|j#j$|du rIdn|j#j$f7 }t% }|&|}|dur`|}|S |du rp|j'||||d}|S |rwt(d|)d|dd f}|*| |S )a   Generate a CUDA FFT plan for transforming up to three axes.

    Args:
        a (cupy.ndarray): Array to be transform, assumed to be either C- or
            F- contiguous.
        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 (None or int or tuple of int):  The axes of the array to
            transform. If `None`, it is assumed that all axes are transformed.

            Currently, for performing N-D transform these must be a set of up
            to three adjacent axes, and must include either the first or the
            last axis of the array.
        value_type (str): The FFT type to perform. Acceptable values are:

            * 'C2C': complex-to-complex transform (default)
            * 'R2C': real-to-complex transform
            * 'C2R': complex-to-real transform

    Returns:
        a cuFFT plan for either 1D transform (``cupy.cuda.cufft.Plan1d``) or
        N-D transform (``cupy.cuda.cufft.PlanNd``).

    .. note::
        The returned plan can not only be passed as one of the arguments of
        the functions in ``cupyx.scipy.fftpack``, but also be used as a
        context manager for both ``cupy.fft`` and ``cupyx.scipy.fftpack``
        functions:

        .. code-block:: python

            x = cupy.random.random(16).reshape(4, 4).astype(complex)
            plan = cupyx.scipy.fftpack.get_fft_plan(x)
            with plan:
                y = cupy.fft.fftn(x)
                # alternatively:
                y = cupyx.scipy.fftpack.fftn(x)  # no explicit plan is given!
            # alternatively:
            y = cupyx.scipy.fftpack.fftn(x, plan=plan)  # pass plan explicitly

        In the first case, no cuFFT plan will be generated automatically,
        even if ``cupy.fft.config.enable_nd_planning = True`` is set.

    .. note::
        If this function is called under the context of
        :func:`~cupy.fft.config.set_cufft_callbacks`, the generated plan will
        have callbacks enabled.

    .. warning::
        This API is a deviation from SciPy's, is currently experimental, and
        may be changed in the future version.
    r   cufftCFz Input array a must be contiguousNz&Shape and axes have different lengths.c                 s   s    | ]}|V  qd S )N ).0ir   r   U/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/cupyx/scipy/fftpack/_fft.py	<genexpr>V   s    zget_fft_plan.<locals>.<genexpr>   zAThe chosen axis ({0}) exceeds the number of dimensions of a ({1})   z"Only up to three axes is supportedC2R   r   z2C2R/R2C PlanNd for F-order arrays is not supportedz,hipFFT's C2R PlanNd is buggy and unsupportedF)axesorderout_sizeto_cache)devicesz/multi-GPU cuFFT callbacks are not yet supportedPlan1d)+	cupy.cudar   flagsc_contiguousf_contiguous
ValueError
isinstanceintlenndimtuplerangeformatlistshapezipr	   dtyper   cupycudaruntimeis_hipRuntimeErrorr   r   r   r   use_multi_gpus_devicesget_current_callback_managercb_load_aux_arrcb_store_aux_arrcb_loadcb_storedataptrr
   getr   NotImplementedErrorcreate_planset_callbacks)ar.   r   
value_typer   r   naxis1Derrtransformed_shapesaxis	out_dtypefft_typer   planbatchr   keysmgrload_aux	store_auxcachecached_planr   r   r   get_fft_plan   s   6

 



&






	
rU   r   Fc              	   C   (   ddl m} t| |f|fd|j||dS )ac  Compute the one-dimensional FFT.

    Args:
        x (cupy.ndarray): Array to be transformed.
        n (None or int): Length of the transformed axis of the output. If ``n``
            is not given, the length of the input along the axis specified by
            ``axis`` is used.
        axis (int): Axis over which to compute the FFT.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.
        plan (:class:`cupy.cuda.cufft.Plan1d` or ``None``): a cuFFT plan for
            transforming ``x`` over ``axis``, which can be obtained using::

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

            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 ``n`` and type
            will convert to complex if that of the input is another.

    .. note::
       The argument `plan` is currently experimental and the interface may be
       changed in the future version.

    .. seealso:: :func:`scipy.fftpack.fft`
    r   r   Noverwrite_xrM   )r!   r   r   CUFFT_FORWARDxrE   rJ   rX   rM   r   r   r   r   fft      r\   c              	   C   rV   )al  Compute the one-dimensional inverse FFT.

    Args:
        x (cupy.ndarray): Array to be transformed.
        n (None or int): Length of the transformed axis of the output. If ``n``
            is not given, the length of the input along the axis specified by
            ``axis`` is used.
        axis (int): Axis over which to compute the FFT.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.
        plan (:class:`cupy.cuda.cufft.Plan1d` or ``None``): a cuFFT plan for
            transforming ``x`` over ``axis``, which can be obtained using::

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

            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 ``n`` and type
            will convert to complex if that of the input is another.

    .. note::
       The argument `plan` is currently experimental and the interface may be
       changed in the future version.

    .. seealso:: :func:`scipy.fftpack.ifft`
    r   r   NrW   )r!   r   r   CUFFT_INVERSErZ   r   r   r   ifft   r]   r_   r   c              	   C   2   ddl m} t| |||}|| ||d|j||dS )a  Compute the two-dimensional 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 (: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, 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.fft2`

    .. note::
       The argument `plan` is currently experimental and the interface may be
       changed in the future version.
    r   r   NrW   r!   r   r   rY   r[   r.   r   rX   rM   r   funcr   r   r   fft2   
   rf   c              	   C   rb   )a  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.
        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, 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.ifft2`

    .. note::
       The argument `plan` is currently experimental and the interface may be
       changed in the future version.
    r   r   NrW   r!   r   r   r^   rd   r   r   r   ifft2  rg   ri   c              	   C   rb   )a  Compute the N-dimensional 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 (: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, 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.fftn`

    .. note::
       The argument `plan` is currently experimental and the interface may be
       changed in the future version.
    r   r   NrW   rc   rd   r   r   r   fftn:  rg   rj   c              	   C   rb   )a  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 (: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, 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.
    r   r   NrW   rh   rd   r   r   r   ifftn`  rg   rk   c              
   C   s&  ddl m} |du r| j| }t| j}|||< t| |f|fd|jd||d}t||jj	}t
dg| j }	t
dg| j }
t
d|	|< t
d|
|< |t|
 j|t|	< t
ddd|	|< t
dd|
|< |t|
 j|t|	< t
ddd|	|< t
d||j|  d |
|< |t|
 j|t|	< |S )aq  Compute the one-dimensional FFT for real input.

    The returned real array contains

    .. code-block:: python

        [y(0),Re(y(1)),Im(y(1)),...,Re(y(n/2))]  # if n is even
        [y(0),Re(y(1)),Im(y(1)),...,Re(y(n/2)),Im(y(n/2))]  # if n is odd

    Args:
        x (cupy.ndarray): Array to be transformed.
        n (None or int): Length of the transformed axis of the output. If ``n``
            is not given, the length of the input along the axis specified by
            ``axis`` is used.
        axis (int): Axis over which to compute the FFT.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.
        plan (:class:`cupy.cuda.cufft.Plan1d` or ``None``): a cuFFT plan for
            transforming ``x`` over ``axis``, which can be obtained using::

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

            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.

    .. seealso:: :func:`scipy.fftpack.rfft`

    .. note::
       The argument `plan` is currently experimental and the interface may be
       changed in the future version.
    r   r   NR2CrW   r   r   )r!   r   r.   r-   r   rY   r1   emptyrealr0   slicer)   r*   imag)r[   rE   rJ   rX   rM   r   r.   fzslice_zslice_fr   r   r   rfft  s*   &

ru   c           
   	   C   s^  ddl m} |du r| j| }t|| j| }t| j}|d d ||< | jtjtjfv r6tj	|tj
d}ntj	|tjd}tdg| j }tdg| j }	td||< td|	|< | t| |t|	 _td|d||< td|d d |	|< | t| |t|	 _td|d||< td|d d |	|< | t| |t|	 _t||f|fd|jd|dS )	a  Compute the one-dimensional inverse FFT for real input.

    Args:
        x (cupy.ndarray): Array to be transformed.
        n (None or int): Length of the transformed axis of the output. If ``n``
            is not given, the length of the input along the axis specified by
            ``axis`` is used.
        axis (int): Axis over which to compute the FFT.
        overwrite_x (bool): If True, the contents of ``x`` can be destroyed.

    Returns:
        cupy.ndarray:
            The transformed array.

    .. seealso:: :func:`scipy.fftpack.irfft`

    .. note::
       This function does not support a precomputed `plan`. If you need this
       capability, please consider using :func:`cupy.fft.irfft` or :func:`
       cupyx.scipy.fft.irfft`.
    r   r   Nr   r   )r0   r   )rX   )r!   r   r.   minr-   r0   r1   float16float32zeros	complex64
complex128ro   r)   r*   rn   rp   r   r^   )
r[   rE   rJ   rX   r   mr.   rr   slice_xrs   r   r   r   irfft  s.   

r~   )NNr   )Nr   FN)Nr`   FN)NNFN)Nr   F)numpyr   r1   cupy.fftr   cupy.fft._fftr   r   r   r   r   r	   cupy.fft._cacher
   rU   r\   r_   rf   ri   rj   rk   ru   r~   r   r   r   r   <module>   s     
 
 
"
"
&
&
&
&C