o
    װ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)	npfloat16float32	complex64
complex128dtypecharlowerfloat64)r
   
value_type r   A/home/ubuntu/.local/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
   astype)ar   	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cupy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   r8   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)2r0   r.   r8   r
   r"   swapaxesbaseflagsc_contiguouscopyr$   cudaruntimeis_hipr   r7   imagsizeget_current_planRuntimeErrorr   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
isinstancefft_typenxbatchgpuscheck_output_arrayget_output_arrayfftr2   r5   CUFFT_INVERSEmathsqrtCUFFT_FORWARD)r   	directionr   normr)   overwrite_xout_sizeoutplanr.   r\   nr^   	curr_planr;   keysmgrload_aux	store_auxcachecached_planr(   r   r   r   	_exec_fftQ   s   
















ru   c              
   C   s$   |D ]}t | |d||||d} q| S )Nr/   rl   )ru   )r   rg   rh   r'   ri   rl   r)   r   r   r   _fft_c2c   s   rw   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@   rA   CInvalid norm value %s, should be "backward", "ortho", or "forward".rv   r   r   )r[   r$   ndarray	TypeErrorlenr7   r"   ranger#   
IndexErrorr   r,   rw   ru   _get_fftn_out_sizer   )
r   r&   r'   rh   rg   r   ri   rl   dimrj   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.
    Nry   c                    s   g | ]}|  qS r   r   rz   r"   r   r   r}         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   r{   axr   r   r   r}     r   c                    r   r   r   r   r   r   r   r}      r   r   )	r   r7   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   )r{   rm   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   )r{   dr   r   r   r}   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)r0   r.   r   r1   r4   r3   r6   r#   r   r   r   r7   r   r2   r5   r   r   _prodr   rP   rQ   rR   rS   rT   rU   rV   r   rW   r   rY   rZ   )r   r\   r'   r   rj   to_cacher.   r"   r   fft_axes_in_dimensionsout_dimensionsplan_dimensionsinembedonembednbatchidistodististrideostridemin_axis_fftnum_axes_batchrm   ro   rp   rq   rr   rs   rt   rl   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   )in_shaper&   	last_axisr   rj   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   rj   z'expected plan to have type cufft.PlanNdz+array orders mismatch (plan: {}, input: {})c                       g | ]} j | qS r   r   r   r   r   r   r}         z_exec_fftn.<locals>.<listcomp>r   c                    r   r   r   r   r   r   r   r}     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   r}   4  r   r?   r@   rA   )#r0   r.   r8   r
   rD   rE   f_contiguousr7   rF   r$   rG   rH   rI   rL   r   r   r[   r   r   formatr#   r\   r   	last_sizera   r`   rK   rb   r2   r5   r   rc   rd   re   rf   )r   rg   r   rh   r'   ri   rl   rk   rj   r.   r\   r   rn   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 )Nrx   r?   r   r   r/   r~   r   r   r   r   zUnsupported order: {}r   r   r9   r   )rh   r'   ri   rl   rk   rj   )r[   r$   r   r   r7   r   r"   r   r   rD   r   rE   ascontiguousarrayr   r,   r   asfortranarrayr   r   )r   r&   r'   rh   rg   r   r   rl   ri   rk   r   rm   rj   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-   r:   r   r/   r   )r0   r.   rL   rM   r[   r   r   r<   r"   r   enable_nd_planningr   rD   r   r   r   r   r$   rG   rH   rI   rE   )	r   r&   r'   rl   r   r.   rn   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-   r0   r.   r   rf   r   rm   r)   rh   r.   r   r   r   rb        rb   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-   r0   r.   r   rc   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-   r0   r.   r   rf   r   r&   r'   rh   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-   r0   r.   r   rc   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?   rA   r?   r@   zCInvalid norm value %s; should be "backward", "ortho", or "forward".)r7   )rh   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   rm   r)   rh   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$   hstackaranger   r   rm   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   r{   r)   xr   r   r}   O  s    zfftshift.<locals>.<listcomp>r$   asarrayr   r   r"   r[   int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   r}   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	functoolsrd   numpyr   r$   cupy.fftr   cupy.fft._cacher   reducer   _coreinternalprodr   _utilmemoizer   r   r,   r8   ru   rw   r   r   r   r   r   r   r   r   rb   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
'










	




