o
    ?eUH                     @   s  d Z ddlZddlZddlmZ ddlmZ ddlm	Z
 ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ dd Zdd ZdPddZdd Zdd ZejZejZejZej Z ej!Z!ej"Z"eej#ddZ#edddgde$e# eej%ddZ%edddgde$e% eej&d d!Z&ed"d"d#gde$e& eej'd d$Z'ed%d%d&gde$e' eej(d'd(Z(ed)d)d*gde$e( eej)d'd+Z)ed,d,d-gde$e) d.d/ Z*e+d0d1d2 Z,e+d3d4d5 Z-e+d6d7d8 Z.e+d9d:d; Z/e+d<d=d> Z0e+d?d@dA Z1dBdC Z2dDdE Z3edFej$dQdGdHZ4edIej$dQdJdKZ5e+dLe2de% e+dMe3de# e+dNe2d e' e+dOe3d e& dS )RzFast-Fourier Transform ops.    N)dtypes)ops)tensor_util)	array_ops)array_ops_stack)gen_spectral_ops)	manip_ops)math_ops)dispatch)	tf_exportc                 C   s@   |   | d }| st| | d S t| tjS )zGInfers the `fft_length` argument for a `rank` RFFT from `input_tensor`.N)		get_shapeis_fully_defined
_array_opsshape_opsconvert_to_tensoras_list_dtypesint32)input_tensorfft_rank	fft_shape r   e/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/ops/signal/fft_ops.py_infer_fft_length_for_rfft    s   r   c                 C   s   |   | d }| s-tt| | d }tdd|d d  |d< t|S |	 }|r@t
dd|d d  |d< t|tjS )zHInfers the `fft_length` argument for a `rank` IRFFT from `input_tensor`.Nr         )r   r   _array_ops_stackZunstackr   r   	_math_opsmaximumstackr   maxr   r   r   r   )r   r   r   
fft_lengthr   r   r   _infer_fft_length_for_irfft-   s   
r$   Fc                 C   s  t |}| jjdurtdd | jjD r| S | rp| jjdurp| j|j d }| rp|rB|dd |jd jd d }dd t	|j|jD }td	d |D rnd
d
ggt
| jj|j d
 }t| || S | S t| }t| | d }td
|| }	t|	g|j}|rt|dd |dd d d gd
}td
|| }
t||
gd
}tjt||gdd}t| |S )zFPads `input_tensor` to `fft_length` on its inner-most `fft_rank` dims.Nc                 s   s    | ]}|j d kV  qdS r   N)value).0dimr   r   r   	<genexpr>F   s    z&_maybe_pad_for_rfft.<locals>.<genexpr>r   r   r   c                 S   s&   g | ]\}}d t |j|j d gqS )r   )r"   r&   )r'   Zfft_dimZ	input_dimr   r   r   
<listcomp>V   s    z'_maybe_pad_for_rfft.<locals>.<listcomp>c                 s   s    | ]	\}}|d kV  qdS r%   r   )r'   _padr   r   r   r)   Y   s    r   )Zaxis)_tensor_utilZconstant_value_as_shaper   ndimsanydimsr   Zconcatenater&   zipr"   r   r,   rankr   r    Zzerosdtypeconcatr   r!   Z
zeros_like)r   r   r#   
is_reverser   Zinput_fft_shapeZpaddingsZouter_paddingsZ
input_rankZ
outer_dimsZfft_paddingsr   r   r   _maybe_pad_for_rfft@   sR   

r6   c                    s(   d fdd	}t ddj|_|S )FWrapper around gen_spectral_ops.rfft* that infers fft_length argument.Nc                    s   t | | |ge}t j| tjd} | jtjtjfvr!td|  | j}|tjkr-tj}n
|tjks4J tj	}| j
 |du rGt| }nt |tj}t| |} t|}|dur_|}| |||dW  d   S 1 sqw   Y  dS )r7   Zpreferred_dtypez6RFFT requires tf.float32 or tf.float64 inputs, got: %sN)ZTcomplexname)r   
name_scoper   r   float32r3   float64
ValueError	complex64
complex128r   with_rank_at_leastr   r   r6   r-   constant_value)r   r#   r9   
real_dtypecomplex_dtypefft_length_staticdefault_namefft_fnr   r   r   _rffts   s8   

$z_rfft_wrapper.<locals>._rfftz    Tcomplex.*?
 NNresub__doc__)rG   r   rF   rH   r   rE   r   _rfft_wrapperp   s   rO   c              	      s2   d fdd	}t ddt ddj|_|S )	zGWrapper around gen_spectral_ops.irfft* that infers fft_length argument.Nc                    s   t | | |gW}t j| tjd} | j | jtjtjfvr't	d|  | j}|j
}|du r7t| }nt |tj}t| |dd} t|}|durQ|}| |||dW  d   S 1 scw   Y  dS )z/Wrapper irfft* that infers fft_length argument.r8   z<IRFFT requires tf.complex64 or tf.complex128 inputs, got: %sNT)r5   )ZTrealr9   )r   r:   r   r   r>   r   r@   r3   r?   r=   rB   r$   r   r6   r-   rA   )r   r#   r9   rC   rB   rD   rF   r   ifft_fnr   r   _irfft   s6   
$z_irfft_wrapper.<locals>._irfftz`input`z`input_tensor`z    Treal.*?
rI   rJ   rK   )rQ   r   rF   rR   r   rP   r   _irfft_wrapper   s
   rS   r   rfftzsignal.rfftzspectral.rfft)v1irfftzsignal.irfftzspectral.irfftr   rfft2dzsignal.rfft2dzspectral.rfft2dirfft2dzsignal.irfft2dzspectral.irfft2d   rfft3dzsignal.rfft3dzspectral.rfft3dirfft3dzsignal.irfft3dzspectral.irfft3dc                 C   s   t t| | d  S )N)r   Zreduce_prodr   r   )gradr2   r   r   r   _fft_size_for_grad   s   r]   ZFFTc                 C       t t|d|j}t|| S )Nr   )r   castr]   r3   ifftr+   r\   sizer   r   r   	_fft_grad      rc   ZIFFTc                 C   0   t dt t|d|jj |j}t|| S )N      ?r   )r   r_   r]   r3   rB   fftr+   r\   rsizer   r   r   
_ifft_grad   
   rj   ZFFT2Dc                 C   r^   )Nr   )r   r_   r]   r3   ifft2dra   r   r   r   _fft2d_grad   rd   rm   ZIFFT2Dc                 C   re   )Nrf   r   )r   r_   r]   r3   rB   fft2drh   r   r   r   _ifft2d_grad   rk   ro   ZFFT3Dc                 C   r^   )NrY   )r   r_   r]   r3   ifft3dra   r   r   r   _fft3d_grad   rd   rq   ZIFFT3Dc                 C   re   )Nrf   rY   )r   r_   r]   r3   rB   fft3drh   r   r   r   _ifft3d_grad   rk   rs   c                    s"   dv sJ d fdd}|S )z=Returns a gradient function for an RFFT of the provided rank.r   r   z'Gradient for RFFT3D is not implemented.c              
      s~  | j d }|j  j}t| j d }td|d d   }dd } fdd} fd	d
}|dddf }	dkrP|dddf }
|	||
 ||d   }nQdkr||d }|||	}t|t|	}|}|dddf }
t|t|
}|d }t	|t
tt|d gtj|ggd|| }||| 7 }tt| j d |}||}d|| t|  dfS )zEA gradient function for RFFT with the provided `rank` and `irfft_fn`.r   r   r   r   c              
   S   s^   t | t t t |d gtjt | gd}t |t t |d d ddggdS )Nr   r   r   )	r   Zreshaper4   onesr2   r   r   r   tile)matrixtexpandedr   r   r   _tile_for_broadcasting	  s   "z@_rfft_grad_helper.<locals>._grad.<locals>._tile_for_broadcastingc                    sZ   t t t| d| df}t |ddg}tdtj t	||   t	|   S )z3Computes t_n = exp(sqrt(-1) * pi * n^2 / line_len).r   r   y              )
r   rw   Zexpand_dimsr   rangeZ	transposeexpnppir_   )lengthabrC   r   r   _mask_matrix  s   
z6_rfft_grad_helper.<locals>._grad.<locals>._mask_matrixc                    s   t ddt | d    S )zCA sequence of [1+0j, -1+0j, 1+0j, -1+0j, ...] with length `length`.r   r   )r   r_   r|   )r   r   r   r   _ymask"  s   z0_rfft_grad_helper.<locals>._grad.<locals>._ymask.Nru   g      ?)inputsr3   rB   r   r   r   r_   matmulZconjrw   r4   rv   r2   r   r   r]   real)opr\   r#   rB   Zinput_shapeZis_evenr{   r   r   Zy0ZymZextra_termsZ	base_maskZ
tiled_maskZy0_termZym_termZ	inner_dimZ
input_sizeZ	the_irfftirfft_fnr2   r   r   _grad  sJ   



z _rfft_grad_helper.<locals>._gradr   )r2   r   r   r   r   r   _rfft_grad_helper   s   Jr   c                    s"    dv sJ d fdd}|S )z>Returns a gradient function for an IRFFT of the provided rank.rt   z(Gradient for IRFFT3D is not implemented.c                    s   | j d }t|}|dur|}|j}|tjkrtj}n|tjkr$tj}t	
|d d}t| j d d }tdgdt|d | g| td| g|gd}t	t	t| |}	||}
|
t	|	| | dfS )zEA gradient function for IRFFT with the provided `rank` and `rfft_fn`.r   Nr   r   r   rf   g       @)r   r-   rA   r3   r   r;   r>   r<   r?   r   modr   r   r4   rv   Z
reciprocalr_   r]   )r   r\   r#   rD   rB   rC   Zis_oddZinput_last_dimensionmaskri   Zthe_rfftr2   rfft_fnr   r   r   S  s0   






z!_irfft_grad_helper.<locals>._gradr   )r2   r   r   r   r   r   _irfft_grad_helperN  s    r   zsignal.fftshiftc                 C   s   t |dU}t | } |du r tt| jj}t| d }n,t|t	r/t| | d }nt
| }tt|d|| |}tt| |d }t| |||W  d   S 1 s^w   Y  dS )a+  Shift the zero-frequency component to the center of the spectrum.

  This function swaps half-spaces for all axes listed (defaults to all).
  Note that ``y[0]`` is the Nyquist component only if ``len(x)`` is even.

  @compatibility(numpy)
  Equivalent to numpy.fft.fftshift.
  https://docs.scipy.org/doc/numpy/reference/generated/numpy.fft.fftshift.html
  @end_compatibility

  For example:

  ```python
  x = tf.signal.fftshift([ 0.,  1.,  2.,  3.,  4., -5., -4., -3., -2., -1.])
  x.numpy() # array([-5., -4., -3., -2., -1.,  0.,  1.,  2.,  3.,  4.])
  ```

  Args:
    x: `Tensor`, input tensor.
    axes: `int` or shape `tuple`, optional Axes over which to shift.  Default is
      None, which shifts all axes.
    name: An optional name for the operation.

  Returns:
    A `Tensor`, The shifted tensor.
  fftshiftNr   r   r   r:   r   tupler|   r   r.   r   
isinstanceintr2   wherer   lessgatherr   ZrollxZaxesr9   shiftr2   r   r   r   r   v  s   


$r   zsignal.ifftshiftc                 C   s   t |dX}t | } |du r!tt| jj}t| d  }n.t|t	r1t| | d  }nt
| }tt|d|| |}tt| |d  }t| |||W  d   S 1 saw   Y  dS )a  The inverse of fftshift.

  Although identical for even-length x,
  the functions differ by one sample for odd-length x.

  @compatibility(numpy)
  Equivalent to numpy.fft.ifftshift.
  https://docs.scipy.org/doc/numpy/reference/generated/numpy.fft.ifftshift.html
  @end_compatibility

  For example:

  ```python
  x = tf.signal.ifftshift([[ 0.,  1.,  2.],[ 3.,  4., -4.],[-3., -2., -1.]])
  x.numpy() # array([[ 4., -4.,  3.],[-2., -1., -3.],[ 1.,  2.,  0.]])
  ```

  Args:
    x: `Tensor`, input tensor.
    axes: `int` or shape `tuple` Axes over which to calculate. Defaults to None,
      which shifts all axes.
    name: An optional name for the operation.

  Returns:
    A `Tensor`, The shifted tensor.
  	ifftshiftNr   r   r   r   r   r   r   r     s   


$r   ZRFFTZIRFFTZRFFT2DZIRFFT2D)FrJ   )6rN   rL   numpyr~   Ztensorflow.python.frameworkr   r   r   r   r   r-   Ztensorflow.python.opsr   r   r   r   r   r   r	   r   Ztensorflow.python.utilr
   Z tensorflow.python.util.tf_exportr   r   r$   r6   rO   rS   rg   r`   rn   rl   rr   rp   rT   Zadd_dispatch_supportrV   rW   rX   rZ   r[   r]   ZRegisterGradientrc   rj   rm   ro   rq   rs   r   r   r   r   r   r   r   r   <module>   s   
0""





R(++