o
    X۷iJ                     @  s   d dl mZ 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 )"    )annotations)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}||||f}t }|durI|j}|j}||j |j!|du r9dn|j"j#|du rCdn|j"j#f7 }t$ }|%|}|durZ|}|S |du rj|j&||||d}|S |rqt'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 both cases the user created ``plan`` will be used.

    .. 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   N/home/ubuntu/vllm_env/lib/python3.10/site-packages/cupyx/scipy/fftpack/_fft.py	<genexpr>W   s    zget_fft_plan.<locals>.<genexpr>   z?The chosen axis ({}) exceeds the number of dimensions of a ({})   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   r   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   5

 



&






	
rT   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_xrL   )r"   r   r   CUFFT_FORWARDxrD   rI   rW   rL   r   r   r   r   fft      r[   c              	   C  rU   )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   NrV   )r"   r   r   CUFFT_INVERSErY   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.

    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   NrV   r"   r   r   rX   rZ   r/   r   rW   rL   r   funcr   r   r   fft2   
   re   c              	   C  ra   )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.

    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   NrV   r"   r   r   r]   rc   r   r   r   ifft2  rf   rh   c              	   C  ra   )ay  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.

    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   NrV   rb   rc   r   r   r   fftn7  rf   ri   c              	   C  ra   )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.

    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   NrV   rg   rc   r   r   r   ifftn[  rf   rj   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 )a  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.

    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R2CrV   r   r   )r"   r   r/   r.   r   rX   r2   emptyrealr1   slicer*   r+   imag)rZ   rD   rI   rW   rL   r   r/   fzslice_zslice_fr   r   r   rfft  s*   $

rt   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   )r1   r   )rW   )r"   r   r/   minr.   r1   r2   float16float32zeros	complex64
complex128rn   r*   r+   rm   ro   r   r]   )
rZ   rD   rI   rW   r   mr/   rq   slice_xrr   r   r   r   irfft  s.   

r}   )NNr   )Nr   FN)Nr_   FN)NNFN)Nr   F)
__future__r   numpyr   r2   cupy.fftr   cupy.fft._fftr   r   r   r   r	   r
   cupy.fft._cacher   rT   r[   r^   re   rh   ri   rj   rt   r}   r   r   r   r   <module>   s      
 

"
"
$
$
$
$A