o
    0 iZ                     @   s  d dl Z d dlZd dlZd dlZd dlmZ d dlmZ e j	Z
ejjjZej dd Zdd ZdPd	d
Zdd Z	dQddZdRddZ		dSddZdTddZdd Z	dUddZdd Z	dQddZ		dVd!d"ZdWd#d$ZdXd&d'ZdXd(d)Z dYd+d,Z!dYd-d.Z"dQd/d0Z#dQd1d2Z$dXd3d4Z%dXd5d6Z&dYd7d8Z'dYd9d:Z(dQd;d<Z)d=d> Z*dQd?d@Z+dAdB Z,dXdCdDZ-dXdEdFZ.dZdHdIZ/dZdJdKZ0dRdLdMZ1dRdNdOZ2dS )[    N)config)get_plan_cachec                 C   s   |dkr| t jt jfv rt jS | t jt jfvrt jS | S | t jt jfv r,t | j S | t jkr4t jS | t jt jfvr?t jS | S )NR2C)	npZfloat16float32	complex64
complex128dtypecharlowerfloat64)r	   
value_type r   Y/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/cupy/fft/_fft.py_output_dtype   s   
r   c                 C   s$   t | j|}|| jkr| |} | S N)r   r	   Zastype)ar   Z	out_dtyper   r   r   _convert_dtype    s   

r   Cc           
      C   s  |d u s	|| j kr| S |dkr#|d d ur#t|}|d d d |d< t||D ]W\}}|d ur|| j | krt| j }|| |krXtd g| j }td|||< | t| } q(td g| j }td|| ||< |||< tj|| jj	|d}	| |	t|< |	} q(| S )NC2R      r   order)
shapelistzipslicendimtuplecupyZzerosr	   r
   )
r   saxesr   r   szaxisr   indexzr   r   r   _cook_shape'   s(   
r(   c                 C   s   ddl m} |dkr| tjkr|jS |dkr| tjkr|jS |dkr*| tjkr*|jS |dkr6| tjkr6|j	S |dkrB| tj
krB|jS |dkrN| tjkrN|jS t)Nr   cufftC2Cr   r   )	cupy.cudar*   r   r   	CUFFT_C2Cr   	CUFFT_R2C	CUFFT_C2Rr   	CUFFT_Z2Zr   	CUFFT_D2Z	CUFFT_Z2D
ValueError)r	   r   r*   r   r   r   _convert_fft_type>   s   r4   c	                 C   s  ddl m}	 t| j|}
|| j | jd kr| |d} | jd us%| jjs*| 	 } nt
jjjs:|dkr:|s:| 	 } nt
jjjrG|dkrG| 	 } | jd }|dk rVtd| t
jjjr}|dkr}d| d _|d u rnd| d	 _n|d
 dkr}d| d|d
 f _|d u r|}| j| }|	 }|d ur|d u r|}ntd|d u rtjsd ntj}||
||f}t }|d ur|j}|j}||j|j|d u rdn|jj|d u rdn|jjf7 }t }||}|d ur|}nf|d u r|	j ||
||d}|||< nT|rt!d|"d|d d f}|#| |||< n9t$||	j std|
|j%kr'td||j&kr4td||j&||j'kr>tdtj|j(d ukrKtd|rV|dkrV| }n|d urb|)| | n|*| }|dkrs|+| || |jd }|
|	j,ks|
|	j-kr|}|dkr||	j.kr|| }n|dkr|t/0| }n|dkr||	j1kr|| }|| j | jd kr||d}|S )Nr   r)   r   r   r   r+   1Invalid number of FFT data points (%d) specified.).r   ).r   r   .AUse the cuFFT plan either as a context manager or as an argument.)devicesz/multi-GPU cuFFT callbacks are not yet supportedPlan1dz'expected plan to have type cufft.Plan1dcuFFT plan dtype mismatch.z*Target array size does not match the plan.z#Batch size does not match the plan.z/Unclear if multiple GPUs are to be used or not.backwardorthoforward)2r,   r*   r4   r	   r   Zswapaxesbaseflagsc_contiguouscopyr!   cudaruntimeis_hipr   r3   imagsizeget_current_planRuntimeErrorr   Zuse_multi_gpusZ_devicesget_current_callback_managercb_load_aux_arrcb_store_aux_arrcb_loadcb_storedataptrr   getr8   NotImplementedErrorcreate_planset_callbacks
isinstancefft_typenxbatchZgpuscheck_output_arrayget_output_arrayfftr.   r1   CUFFT_INVERSEmathsqrtCUFFT_FORWARD)r   	directionr   normr%   overwrite_xout_sizeoutplanr*   rU   nrW   	curr_planr7   keysmgrload_aux	store_auxcachecached_planr$   r   r   r   	_exec_fftQ   s   
















rm   c              
   C   s$   |D ]}t | |d||||d} q| S )Nr+   rd   )rm   )r   r_   r`   r#   ra   rd   r%   r   r   r   _fft_c2c   s   ro   r+   Fc           
      C   sn  t | tjs
td|d ur|d urt|t|krtd|d u r:|d u r*| j}nt|}dd t| dD }nt|}|sJ|dkrF| S t	d|d u rPd}|d	vrZtd
| t
| |} t| |||} |dkrvt| |||||d} | S |dkrt| ||||d |} t| |||d d |} | S t| |||d d |} t| j||d |}	t| ||||d ||	} | S )N(The input array a must be a cupy.ndarray&Shape and axes have different lengths.c                 S   s   g | ]}|qS r   r   .0ir   r   r   
<listcomp>   s    z_fft.<locals>.<listcomp>r   r+   list index out of ranger;   r;   r<   r=   CInvalid norm value %s, should be "backward", "ortho", or "forward".rn   r   r   )rT   r!   ndarray	TypeErrorlenr3   r   ranger    
IndexErrorr   r(   ro   rm   _get_fftn_out_sizer   )
r   r"   r#   r`   r_   r   ra   rd   dimrb   r   r   r   _fft   sF    
r   c                    s  |dur|durt |t |krtd|du r8|du r }nt |}t fddt| dD }|}||fS t|}|s@dS tt|  k sQtt| d krUtd|d	krjtt fd
d|D }||fS t fdd|dd D }||d    t|}||fS )zwConfigure axes argument for an n-dimensional FFT.

    The axes to be transformed are returned in ascending order.
    Nrq   c                    s   g | ]}|  qS r   r   rr   r   r   r   ru         z#_prep_fftn_axes.<locals>.<listcomp>r   )r   r   r   z/The specified axes exceed the array dimensions.r+   c                       g | ]}|  qS r   r   rs   axr   r   r   ru     r   c                    r   r   r   r   r   r   r   ru      r   r   )	r{   r3   r    r|   _reduceminmaxsortedappend)r   r"   r#   r   r   axes_sortedr   r   r   _prep_fftn_axes  s*    "	r   c                    sR   dt    k odkn  o(d v p|d  v o(t fddtt  d D S )Nr      r   c                 3   s(    | ]} |d    |  d kV  qdS )r   Nr   )rs   re   r   r   r   	<genexpr>-  s     z'_nd_plan_is_possible.<locals>.<genexpr>)r{   allr|   )r   r   r   r   r   _nd_plan_is_possible(  s   r   Tc                    s"  ddl m} t }||j|jfv rd}n||j|jfv r d}nd}|du r-tt|}	n
t	|d||d\}
}	t
|	|s@td|d	vrHtd
	  fdd|	D }|dkr]|ddd }t|}||j|jfv rn|}|}nt|}|durz||d< t|}||j|jfv r|}n|}|}|}|	tt|krd}d }}d }}nhd|	vrtt|	}t d| }|dkrt|}t|}d}d}nF|dkrd}d}|}|}n9|d |	vr|t|	 }t | d }|dkrd}d}|}|}n|dkrt|}t|}d}d}ntd|D ]}|dk rtdq|||||||||||	d |f}t }|durT|j}|j}||j|j|du rDdn|jj|du rNdn|jjf7 }t }||}|dure|}|S |du rx|j| }|rv|||< |S |d|dd f}|| |r|||< |S )aF  Generate a CUDA FFT plan for transforming up to three axes.

    Args:
        shape (tuple of int): The shape of the array to transform
        fft_type (int): The FFT type to perform. Supported values are:
            `cufft.CUFFT_C2C`, `cufft.CUFFT_C2R`, `cufft.CUFFT_R2C`,
            `cufft.CUFFT_Z2Z`, `cufft.CUFFT_Z2D`, and `cufft.CUFFT_D2Z`.
        axes (None or int or tuple of int):  The axes of the array to
            transform. Currently, these must be a set of up to three adjacent
            axes and must include either the first or the last axis of the
            array.  If `None`, it is assumed that all axes are transformed.
        order ({'C', 'F'}): Specify whether the data to be transformed has C or
            Fortran ordered data layout.
        out_size (int): The output length along the last axis for R2C/C2R FFTs.
            For C2C FFT, this is ignored (and set to `None`).
        to_cache (bool): Whether to cache the generated plan. Default is
            ``True``.

    Returns:
        plan (cufft.PlanNd): A cuFFT Plan for the chosen `fft_type`.
    r   r)   r+   r   r   N)r"   r#   r   zAn n-dimensional cuFFT plan could not be created. The axes must be contiguous and non-repeating. Between one and three axes can be transformed and either the first or last axis must be included in axes.r   Fzorder must be 'C' or 'F'c                    s   g | ]} | qS r   r   )rs   dr   r   r   ru   w  r   z&_get_cufft_plan_nd.<locals>.<listcomp>r   r   r   r   zzGeneral subsets of FFT axes not currently supported for GPU case (Can only batch FFT over the first or last spatial axes).z,Invalid number of FFT data points specified.PlanNd)r,   r*   r{   r-   r0   r/   r2   r    r|   r   r   r3   r   r.   r1   r   r   _prodr   rI   rJ   rK   rL   rM   rN   rO   r   rP   r   rR   rS   )r   rU   r#   r   rb   Zto_cacher*   r   r   Zfft_axes_Zin_dimensionsZout_dimensionsZplan_dimensionsZinembedZonembedZnbatchZidistZodistZistrideZostrideZmin_axis_fftZnum_axes_batchre   rg   rh   ri   rj   rk   rl   rd   r   r   r   _get_cufft_plan_nd1  s   












r   c                 C   s`   |dkr|d u s|d d u rd| | d  }|S |d }|S |dkr,| | d d }|S d }|S )Nr   r   r   r   r   r   )Zin_shaper"   	last_axisr   rb   r   r   r   r~     s   r~   c	                    s\  ddl m}	 t j|}
 jjrd}n jjrd}ntd|dkr)|s)   nt	j
jjr6|dkr6   |	 }|d ur@|}|d u rOt j|
|||d}nqt||	jsYtd	||jkrgtd
|j| jjr} fdd|D }|dkr|||d< n fdd|d d d D }t|}||jkrtd|j| j|
|jkrtd|dkr|d |jkrtd||jkrtd|r|dkrɈ }n|d u r|j |d}n| | |jdkr| || |
|	j|	jfv r n|tfdd|D }|dkr||	jkr|| }|S |dkr|t !| }|S |dkr,||	j"kr,|| }|S )Nr   r)   r   r   za must be contiguousr   r+   )r#   r   rb   z'expected plan to have type cufft.PlanNdz+array orders mismatch (plan: {}, input: {})c                       g | ]} j | qS r   r   r   r   r   r   ru         z_exec_fftn.<locals>.<listcomp>r   c                    r   r   r   r   r   r   r   ru     r   zYThe cuFFT plan and a.shape do not match: plan.shape = {}, expected_shape={}, a.shape = {}r:   z"The last axis for R2C/C2R mismatchz-The size along the last R2C/C2R axis mismatchr   c                    r   r   r   r   )arrr   r   ru   4  r   r;   r<   r=   )#r,   r*   r4   r	   r?   r@   f_contiguousr3   rA   r!   rB   rC   rD   rG   r   r   rT   r   r   formatr    rU   r   Z	last_sizerY   rX   rF   rZ   r.   r1   r   r[   r\   r]   r^   )r   r_   r   r`   r#   ra   rd   rc   rb   r*   rU   r   rf   Zexpected_shaper$   r   )r   r   r   
_exec_fftn  s~   








r   Ac
                 C   sN  t | tjs
td|d u rd}|dvrtd| t| j|||\}}
|
s0|dkr,| S tdt| |} |dkrO| j	j
r@d}n| j	jrGd	}nt| } d	}n|d
vrZtd|t| ||||d} | jD ]}|dk rrtd| qf|d	kr| j	jst| } n|dkr| j	j
st| } t| j||
d |}t| ||||
|||	|d	} | S )Nrp   r;   rw   rx   r+   rv   r   r   r   r   zUnsupported order: {}r   r   r5   r   )r`   r#   ra   rd   rc   rb   )rT   r!   ry   rz   r3   r   r   r}   r   r?   r   r@   Zascontiguousarrayr   r(   r   Zasfortranarrayr~   r   )r   r"   r#   r`   r_   r   r   rd   ra   rc   r   re   rb   r   r   r   _fftn?  sP   



r   c           	      C   s   ddl m} | }|d ur|d u r|}ntdt||jr!tS t||js/| jdks/t	j
s1tS | jjr;|dkr;tS t| j|||\}}t|dkrqt|| jrqtjjjrod|d krit|| jkri| jjritS |dkrotS tS tS )Nr   r)   r6   r   r+   r   )r,   r*   rG   rH   rT   r   r   r8   r   r   Zenable_nd_planningr   r?   r   r   r{   r   r!   rB   rC   rD   r@   )	r   r"   r#   rd   r   r*   rf   r   r   r   r   r   _default_fft_funcr  s0   
r   r   c                 C   "   ddl m} t| |f|f||jS )a  Compute the one-dimensional FFT.

    Args:
        a (cupy.ndarray): Array to be transform.
        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.
        norm (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

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

    .. seealso:: :func:`numpy.fft.fft`
    r   r)   r,   r*   r   r^   r   re   r%   r`   r*   r   r   r   rZ        rZ   c                 C   r   )a  Compute the one-dimensional inverse FFT.

    Args:
        a (cupy.ndarray): Array to be transform.
        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.
        norm (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

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

    .. seealso:: :func:`numpy.fft.ifft`
    r   r)   r,   r*   r   r[   r   r   r   r   ifft  r   r   r   c                 C   *   ddl m} t| ||}|| ||||jS )a  Compute the two-dimensional FFT.

    Args:
        a (cupy.ndarray): Array to be transform.
        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 (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

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

    .. seealso:: :func:`numpy.fft.fft2`
    r   r)   r,   r*   r   r^   r   r"   r#   r`   r*   funcr   r   r   fft2     r   c                 C   r   )a  Compute the two-dimensional inverse FFT.

    Args:
        a (cupy.ndarray): Array to be transform.
        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 (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

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

    .. seealso:: :func:`numpy.fft.ifft2`
    r   r)   r,   r*   r   r[   r   r   r   r   ifft2  r   r   c                 C   r   )a  Compute the N-dimensional FFT.

    Args:
        a (cupy.ndarray): Array to be transform.
        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 (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

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

    .. seealso:: :func:`numpy.fft.fftn`
    r   r)   r   r   r   r   r   fftn  r   r   c                 C   r   )a
  Compute the N-dimensional inverse FFT.

    Args:
        a (cupy.ndarray): Array to be transform.
        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 (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

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

    .. seealso:: :func:`numpy.fft.ifftn`
    r   r)   r   r   r   r   r   ifftn  r   r   c                 C   $   ddl m} t| |f|f||jdS )aM  Compute the one-dimensional FFT for real input.

    Args:
        a (cupy.ndarray): Array to be transform.
        n (None or int): Number of points along transformation axis in the
            input to use. 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.
        norm (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

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

    .. seealso:: :func:`numpy.fft.rfft`
    r   r)   r   r   r   r   r   r   rfft1  s   r   c                 C   r   )a  Compute the one-dimensional inverse FFT for real input.

    Args:
        a (cupy.ndarray): Array to be transform.
        n (None or int): Length of the transformed axis of the output. For
            ``n`` output points, ``n//2+1`` input points are necessary. If
            ``n`` is not given, it is determined from the length of the input
            along the axis specified by ``axis``.
        axis (int): Axis over which to compute the FFT.
        norm (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

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

    .. seealso:: :func:`numpy.fft.irfft`
    r   r)   r   r   r   r   r   r   irfftK  s   r   c                 C   0   ddl m} t| ||dd}|| ||||jdS )aO  Compute the two-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 (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

    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:`numpy.fft.rfft2`
    r   r)   r   r   r   r   r   r   r   rfft2g     r   c                 C   r   )a  Compute the two-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 (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

    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:`numpy.fft.irfft2`
    r   r)   r   r   r   r   r   r   r   irfft2     r   c                 C   r   )aM  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 (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

    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:`numpy.fft.rfftn`
    r   r)   r   r   r   r   r   r   r   rfftn  r   r   c                 C   s@   |d ur|d d ur|d S | d S |d ur| |d  S | d S )Nr   r   )r   r"   r#   r   r   r   _size_last_transform_axis  s   r   c                 C   r   )a  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 (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

    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:`numpy.fft.irfftn`
    r   r)   r   r   r   r   r   r   r   irfftn  r   r   c                 C   s8   | dv rd} | S | dkrd} | S | dkrt d|  | S )N)Nr;   r=   r;   r<   zCInvalid norm value %s; should be "backward", "ortho", or "forward".)r3   )r`   r   r   r   _swap_direction  s   r   c                 C   s   t |  ||t|S )a  Compute the FFT of a signal that has Hermitian symmetry.

    Args:
        a (cupy.ndarray): Array to be transform.
        n (None or int): Length of the transformed axis of the output. For
            ``n`` output points, ``n//2+1`` input points are necessary. If
            ``n`` is not given, it is determined from the length of the input
            along the axis specified by ``axis``.
        axis (int): Axis over which to compute the FFT.
        norm (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

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

    .. seealso:: :func:`numpy.fft.hfft`
    )r   conjr   r   re   r%   r`   r   r   r   hfft  s   r   c                 C   s   t | ||t| S )aW  Compute the FFT of a signal that has Hermitian symmetry.

    Args:
        a (cupy.ndarray): Array to be transform.
        n (None or int): Number of points along transformation axis in the
            input to use. 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.
        norm (``"backward"``, ``"ortho"``, or ``"forward"``): Optional keyword
            to specify the normalization mode. Default is ``None``, which is
            an alias of ``"backward"``.

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

    .. seealso:: :func:`numpy.fft.ihfft`
    )r   r   r   r   r   r   r   ihfft  s   r         ?c                 C   sD   t t jd| d d d tjdt j| d  dtjdf| |  S )zReturn the FFT sample frequencies.

    Args:
        n (int): Window length.
        d (scalar): Sample spacing.

    Returns:
        cupy.ndarray: Array of length ``n`` containing the sample frequencies.

    .. seealso:: :func:`numpy.fft.fftfreq`
    r   r   r   r	   )r!   Zhstackaranger   r   re   r   r   r   r   fftfreq  s
    r   c                 C   s"   t jd| d d tjd| |  S )a   Return the FFT sample frequencies for real input.

    Args:
        n (int): Window length.
        d (scalar): Sample spacing.

    Returns:
        cupy.ndarray:
            Array of length ``n//2+1`` containing the sample frequencies.

    .. seealso:: :func:`numpy.fft.rfftfreq`
    r   r   r   r   )r!   r   r   r   r   r   r   r   rfftfreq-  s   "r   c                    N   t   |du rtt j}nt|tr|f}t   fdd|D |S )aS  Shift the zero-frequency component to the center of the spectrum.

    Args:
        x (cupy.ndarray): Input array.
        axes (int or tuple of ints): Axes over which to shift. Default is
            ``None``, which shifts all axes.

    Returns:
        cupy.ndarray: The shifted array.

    .. seealso:: :func:`numpy.fft.fftshift`
    Nc                    s   g | ]	} j | d  qS r   r   rs   r%   xr   r   ru   O  s    zfftshift.<locals>.<listcomp>r!   Zasarrayr   r|   r   rT   intZrollr   r#   r   r   r   fftshift=     

r   c                    r   )a3  The inverse of :meth:`fftshift`.

    Args:
        x (cupy.ndarray): Input array.
        axes (int or tuple of ints): Axes over which to shift. Default is
            ``None``, which shifts all axes.

    Returns:
        cupy.ndarray: The shifted array.

    .. seealso:: :func:`numpy.fft.ifftshift`
    Nc                    s   g | ]
} j | d   qS r   r   r   r   r   r   ru   d  s    zifftshift.<locals>.<listcomp>r   r   r   r   r   	ifftshiftR  r   r   )r   )NNNr   )r+   FN)NNr+   )Nr   NT)r+   r   NFN)NNNr+   )Nr   N)Nr   N)r   )3	functoolsr\   numpyr   r!   Zcupy.fftr   Zcupy.fft._cacher   reducer   Z_coreZinternalprodr   Z_utilmemoizer   r   r(   r4   rm   ro   r   r   r   r   r~   r   r   r   rZ   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sh    



 


-$

 *
X

3
'










	




