
    uki                       d dl mZ d dlmZmZ d dlmZ d dlZd dlZd dl	m
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mZmZm Z  d dl!m"Z" d dl#m$Z$m%Z% d dl&m'Z'm(Z(m)Z) 	 	 d#	 	 	 d$dZ*d%dZ+d&dZ,	 	 d'	 	 	 d(dZ-	 	 d)	 	 	 	 	 d*dZ.	 	 d'	 	 	 d(dZ/	 	 d)	 	 	 	 	 d*dZ0	 	 d+	 	 	 d,dZ1	 	 	 	 	 	 	 	 	 	 d-dZ2d.d/dZ3	 	 	 	 	 	 	 d0	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d1dZ4	 	 	 	 d2	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d3dZ5	 	 	 	 	 d4	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d5dZ6	 	 	 	 	 d4	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d6d Z7d7d!Z8	 	 	 	 	 d8	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d9d"Z9y):    )annotations)CallableSequence)partialN)Any)api)core)dtypes)lax)numpy)_ensure_index_tuple)PrecisionLike)fft)linalg)check_arraylikeensure_arraylikepromote_dtypes_complexpromote_dtypes_inexact)signal_helper)Array	ArrayLike)canonicalize_axistuple_deletetuple_insertc                J    t        d        t               \    j                  j                  k7  rt        d      |dvrt        d      t	        t
        |      }|	 |       S t        |      }t         fd|D              }t        t         j                              t        |      z
  }t         fd|D              r(t        d j                  d	j                  d
|      t        |      D ]  }t        j                  |||      }  |       S )a&  
  Convolve two N-dimensional arrays using Fast Fourier Transform (FFT).

  JAX implementation of :func:`scipy.signal.fftconvolve`.

  Args:
    in1: left-hand input to the convolution.
    in2: right-hand input to the convolution. Must have ``in1.ndim == in2.ndim``.
    mode: controls the size of the output. Available operations are:

      * ``"full"``: (default) output the full convolution of the inputs.
      * ``"same"``: return a centered portion of the ``"full"`` output which
        is the same size as ``in1``.
      * ``"valid"``: return the portion of the ``"full"`` output which do not
        depend on padding at the array edges.

    axes: optional sequence of axes along which to apply the convolution.

  Returns:
    Array containing the convolved result.

  See Also:
    - :func:`jax.numpy.convolve`: 1D convolution
    - :func:`jax.scipy.signal.convolve`: direct convolution

  Examples:
    A few 1D convolution examples. Because FFT-based convolution is approximate,
    We use :func:`jax.numpy.printoptions` below to adjust the printing precision:

    >>> x = jnp.array([1, 2, 3, 2, 1])
    >>> y = jnp.array([1, 1, 1])

    Full convolution uses implicit zero-padding at the edges:

    >>> with jax.numpy.printoptions(precision=3):
    ...   print(jax.scipy.signal.fftconvolve(x, y, mode='full'))
    [1. 3. 6. 7. 6. 3. 1.]

    Specifying ``mode = 'same'`` returns a centered convolution the same size
    as the first input:

    >>> with jax.numpy.printoptions(precision=3):
    ...   print(jax.scipy.signal.fftconvolve(x, y, mode='same'))
    [3. 6. 7. 6. 3.]

    Specifying ``mode = 'valid'`` returns only the portion where the two arrays
    fully overlap:

    >>> with jax.numpy.printoptions(precision=3):
    ...   print(jax.scipy.signal.fftconvolve(x, y, mode='valid'))
    [6. 7. 6.]
  fftconvolvez/in1 and in2 should have the same dimensionality)samefullvalidz-mode must be one of ['same', 'full', 'valid']modec              3  J   K   | ]  }t        |j                          y wN)r   ndim).0axin1s     P/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/jax/_src/scipy/signal.py	<genexpr>zfftconvolve.<locals>.<genexpr>n   s     >2 SXX.>s    #c              3  \   K   | ]#  }j                   |   j                   |   k7   % y wr#   shape)r%   ir'   in2s     r(   r)   zfftconvolve.<locals>.<genexpr>p   s&     ;!11	%;s   ),z0mapped axes must have same shape; got in1.shape=z in2.shape=z axes=)in_axesout_axes)r   r   r$   
ValueErrorr   _fftconvolve_unbatchedr   tuplesetrangeanyr,   sortedr   vmap)r'   r.   r!   axes_fftconvolvemapped_axesr&   s   ``     r(   r   r   .   s   l -c*#C-(#sXX
F
GG	**
D
EE/d;,	\S!!	T	"$	>>	>$E#((O$s4y0+;{;;
Hcii\399,V]X\W^_
``; Cb88L"rBLC	c3	    c                    t        d t        | j                  |j                        D              }|}|dk(  rut        d t        | j                  |j                        D              }t        d t        | j                  |j                        D              }|s|st	        d      |r|| }} t        d t        | j                  |j                        D              r| |z  }nt        j                  |       r5t
        j                  j                  t
        j                  j                  }	}n4t
        j                  j                  t
        j                  j                  }	} || |      }
 |||      } |	|
|z  |      }|dk(  r|}nV|dk(  r| j                  }nD|dk(  r1t        d	 t        | j                  |j                        D              }nt	        d
|      t        d t        ||      D              }t        j                  |||      S )Nc              3  2   K   | ]  \  }}||z   d z
    yw   N r%   s1s2s      r(   r)   z)_fftconvolve_unbatched.<locals>.<genexpr>w   s     IVRR"Wq[I   r   c              3  ,   K   | ]  \  }}||k\    y wr#   rA   rB   s      r(   r)   z)_fftconvolve_unbatched.<locals>.<genexpr>}   s     Cvr2"(C   c              3  ,   K   | ]  \  }}||k    y wr#   rA   rB   s      r(   r)   z)_fftconvolve_unbatched.<locals>.<genexpr>~   s     @FBrRx@rG   zVFor 'valid' mode, One input must be at least as large as the other in every dimension.c              3  :   K   | ]  \  }}|d k(  xs |d k(    ywr?   rA   rB   s      r(   r)   z)_fftconvolve_unbatched.<locals>.<genexpr>   s$     	ER"'
R1W
	Es   r   r   c              3  2   K   | ]  \  }}||z
  d z     ywr?   rA   rB   s      r(   r)   z)_fftconvolve_unbatched.<locals>.<genexpr>   s     Jfb"b2gkJrE   zUnrecognized mode=c              3  2   K   | ]  \  }}||z
  d z    yw)   NrA   )r%   	full_sizeout_sizes      r(   r)   z)_fftconvolve_unbatched.<locals>.<genexpr>   s(      O/Ix #X-!3 OrE   )r3   zipr,   allr1   jnpiscomplexobjr   fftnifftnrfftnirfftnr   dynamic_slice)r'   r.   r!   
full_shape	fft_shapeno_swapswapconvr   ifftsp1sp2	out_shapestart_indicess                 r(   r2   r2   v   s   Is399cii/HII* )	W_CSYY		)BCCG@c#))SYY&?@@Dt @ A Ac3c		E3syy#))+D	EE9D
'',,4c''--4c
c9
C
c9
Cc	9%D	V^Iv~		IwJCIIsyy0IJJI
*TG,
-- O36z93MO O-			4		::r<   c                  |dvrt        d      | j                  |j                  k7  rt        d      | j                  dk(  s|j                  dk(  r&t        d| j                   d|j                   d      t	        | |      \  } }t        d t        | j                  |j                        D              }t        d	 t        | j                  |j                        D              }|s|st        d
      |j                  }|r|| }} |j                  }t        j                  |      }|dk(  r|D cg c]  }d }	}nZ|dk(  r9t        ||      D 
cg c]!  \  }}
|dz
  |
dz
  dz  z
  ||
z
  |
dz
  dz  z   f# }	}}
n|dk(  r|D cg c]  }|dz
  |dz
  f }	}t        d |D              }t        j                  | d   |d   |	|      }|d   S c c}w c c}
}w c c}w )N)r   r   r   z-mode must be one of ['full', 'same', 'valid']z3in1 and in2 must have the same number of dimensionsr   z;zero-size arrays not supported in convolutions, got shapes z and .c              3  ,   K   | ]  \  }}||k\    y wr#   rA   rB   s      r(   r)   z_convolve_nd.<locals>.<genexpr>   s     AVRbArG   c              3  ,   K   | ]  \  }}||k    y wr#   rA   rB   s      r(   r)   z_convolve_nd.<locals>.<genexpr>        >&"bR2X>rG   z<One input must be smaller than the other in every dimension.r   r   r   r   r@   rL   r   c              3      K   | ]  }d   ywr?   rA   )r%   ss     r(   r)   z_convolve_nd.<locals>.<genexpr>   s     #!#s   )NN	precision)r1   r$   sizer,   r   rP   rO   rQ   flipr3   r   conv_general_dilated)r'   r.   r!   rk   rZ   r[   shape_or,   ri   paddings_ostridesresults                r(   _convolve_ndrt      s   	**
D
EEXX
J
KKXX]chh!m
RSVS\S\R]]bcfclclbmmno
pp#C-(#sAs399cii'@AA'	>C		399$=>	>$
T
S
TTII'	CC
))%#	W_$%!v%G%v~"5'24As AqQ&C37q.(@A 4G 4v~',-!Aq1u~-G-#U##'##C
OS_g$+yB&	 &4 .s   2	G&GGc                l    |dk(  rt        | ||      S |dv rt        | |||      S t        d|d      )a  Convolution of two N-dimensional arrays.

  JAX implementation of :func:`scipy.signal.convolve`.

  Args:
    in1: left-hand input to the convolution.
    in2: right-hand input to the convolution. Must have ``in1.ndim == in2.ndim``.
    mode: controls the size of the output. Available operations are:

      * ``"full"``: (default) output the full convolution of the inputs.
      * ``"same"``: return a centered portion of the ``"full"`` output which
        is the same size as ``in1``.
      * ``"valid"``: return the portion of the ``"full"`` output which do not
        depend on padding at the array edges.

    method: controls the computation method. Options are

      * ``"auto"``: (default) always uses the ``"direct"`` method.
      * ``"direct"``: lower to :func:`jax.lax.conv_general_dilated`.
      * ``"fft"``: compute the result via a fast Fourier transform.

    precision: Specify the precision of the computation. Refer to
      :class:`jax.lax.Precision` for a description of available values.

  Returns:
    Array containing the convolved result.

  See Also:
    - :func:`jax.numpy.convolve`: 1D convolution
    - :func:`jax.scipy.signal.convolve2d`: 2D convolution
    - :func:`jax.scipy.signal.correlate`: ND correlation

  Examples:
    A few 1D convolution examples:

    >>> x = jnp.array([1, 2, 3, 2, 1])
    >>> y = jnp.array([1, 1, 1])

    Full convolution uses implicit zero-padding at the edges:

    >>> jax.scipy.signal.convolve(x, y, mode='full')
    Array([1., 3., 6., 7., 6., 3., 1.], dtype=float32)

    Specifying ``mode = 'same'`` returns a centered convolution the same size
    as the first input:

    >>> jax.scipy.signal.convolve(x, y, mode='same')
    Array([3., 6., 7., 6., 3.], dtype=float32)

    Specifying ``mode = 'valid'`` returns only the portion where the two arrays
    fully overlap:

    >>> jax.scipy.signal.convolve(x, y, mode='valid')
    Array([6., 7., 6.], dtype=float32)
  r   r    )directautorj   zGot method=z&; expected 'auto', 'fft', or 'direct'.)r   rt   r1   r'   r.   r!   methodrk   s        r(   convolverz      sJ    r u_sCd++##S$)<<
|F9$JK
LLr<   c                    |dk7  s|dk7  rt        d      t        j                  |       dk7  st        j                  |      dk7  rt        d      t	        | |||      S )a	  Convolution of two 2-dimensional arrays.

  JAX implementation of :func:`scipy.signal.convolve2d`.

  Args:
    in1: left-hand input to the convolution. Must have ``in1.ndim == 2``.
    in2: right-hand input to the convolution. Must have ``in2.ndim == 2``.
    mode: controls the size of the output. Available operations are:

      * ``"full"``: (default) output the full convolution of the inputs.
      * ``"same"``: return a centered portion of the ``"full"`` output which
        is the same size as ``in1``.
      * ``"valid"``: return the portion of the ``"full"`` output which do not
        depend on padding at the array edges.

    boundary: only ``"fill"`` is supported.
    fillvalue: only ``0`` is supported.
    method: controls the computation method. Options are

      * ``"auto"``: (default) always uses the ``"direct"`` method.
      * ``"direct"``: lower to :func:`jax.lax.conv_general_dilated`.
      * ``"fft"``: compute the result via a fast Fourier transform.

    precision: Specify the precision of the computation. Refer to
      :class:`jax.lax.Precision` for a description of available values.

  Returns:
    Array containing the convolved result.

  See Also:
    - :func:`jax.numpy.convolve`: 1D convolution
    - :func:`jax.scipy.signal.convolve`: ND convolution
    - :func:`jax.scipy.signal.correlate`: ND correlation

  Examples:
    A few 2D convolution examples:

    >>> x = jnp.array([[1, 2],
    ...                [3, 4]])
    >>> y = jnp.array([[2, 1, 1],
    ...                [4, 3, 4],
    ...                [1, 3, 2]])

    Full 2D convolution uses implicit zero-padding at the edges:

    >>> jax.scipy.signal.convolve2d(x, y, mode='full')
    Array([[ 2.,  5.,  3.,  2.],
           [10., 22., 17., 12.],
           [13., 30., 32., 20.],
           [ 3., 13., 18.,  8.]], dtype=float32)

    Specifying ``mode = 'same'`` returns a centered 2D convolution of the same size
    as the first input:

    >>> jax.scipy.signal.convolve2d(x, y, mode='same')
    Array([[22., 17.],
           [30., 32.]], dtype=float32)

    Specifying ``mode = 'valid'`` returns only the portion of 2D convolution
    where the two arrays fully overlap:

    >>> jax.scipy.signal.convolve2d(x, y, mode='valid')
    Array([[22., 17.],
           [30., 32.]], dtype=float32)
  fillr   z7convolve2d() only supports boundary='fill', fillvalue=0rL   z0convolve2d() only supports 2-dimensional inputs.rj   )NotImplementedErrornpr$   r1   rt   )r'   r.   r!   boundary	fillvaluerk   s         r(   
convolve2dr     s[    F 9>
W
XXWWS\Q"''#,!+
G
HH	c3		::r<   c                d    t        | t        j                  |j                               |||      S )a  Cross-correlation of two N-dimensional arrays.

  JAX implementation of :func:`scipy.signal.correlate`.

  Args:
    in1: left-hand input to the cross-correlation.
    in2: right-hand input to the cross-correlation. Must have ``in1.ndim == in2.ndim``.
    mode: controls the size of the output. Available operations are:

      * ``"full"``: (default) output the full cross-correlation of the inputs.
      * ``"same"``: return a centered portion of the ``"full"`` output which
        is the same size as ``in1``.
      * ``"valid"``: return the portion of the ``"full"`` output which do not
        depend on padding at the array edges.

    method: controls the computation method. Options are

      * ``"auto"``: (default) always uses the ``"direct"`` method.
      * ``"direct"``: lower to :func:`jax.lax.conv_general_dilated`.
      * ``"fft"``: compute the result via a fast Fourier transform.

    precision: Specify the precision of the computation. Refer to
      :class:`jax.lax.Precision` for a description of available values.

  Returns:
    Array containing the cross-correlation result.

  See Also:
    - :func:`jax.numpy.correlate`: 1D cross-correlation
    - :func:`jax.scipy.signal.correlate2d`: 2D cross-correlation
    - :func:`jax.scipy.signal.convolve`: ND convolution

  Examples:
    A few 1D correlation examples:

    >>> x = jnp.array([1, 2, 3, 2, 1])
    >>> y = jnp.array([1, 3, 2])

    Full 1D correlation uses implicit zero-padding at the edges:

    >>> jax.scipy.signal.correlate(x, y, mode='full')
    Array([ 2.,  7., 13., 15., 11.,  5.,  1.], dtype=float32)

    Specifying ``mode = 'same'`` returns a centered 1D correlation of the same
    size as the first input:

    >>> jax.scipy.signal.correlate(x, y, mode='same')
    Array([ 7., 13., 15., 11.,  5.], dtype=float32)

    Specifying ``mode = 'valid'`` returns only the portion of 1D correlation
    where the two arrays fully overlap:

    >>> jax.scipy.signal.correlate(x, y, mode='valid')
    Array([13., 15., 11.], dtype=float32)
  )rk   ry   )rz   rQ   rm   conjrx   s        r(   	correlater   N  s'    r 
#sxx
+TYv	VVr<   c                ,   |dk7  s|dk7  rt        d      t        j                  |       dk7  st        j                  |      dk7  rt        d      t	        d t        | j                  |j                        D              }t	        d t        | j                  |j                        D              }|dk(  rIt        j                  |       |j                         }} t        j                  t        | |||	            }|S |d
k(  r|r8|s6t        j                  |      | j                         }} t        | |||	      }|S t        j                  |       |j                         }} t        j                  t        | |||	            }|S |rDt        j                  |      | j                         }} t        | |||	      j                         }|S t        j                  |       |j                         }} t        j                  t        | |||	            }|S )aX	  Cross-correlation of two 2-dimensional arrays.

  JAX implementation of :func:`scipy.signal.correlate2d`.

  Args:
    in1: left-hand input to the cross-correlation. Must have ``in1.ndim == 2``.
    in2: right-hand input to the cross-correlation. Must have ``in2.ndim == 2``.
    mode: controls the size of the output. Available operations are:

      * ``"full"``: (default) output the full cross-correlation of the inputs.
      * ``"same"``: return a centered portion of the ``"full"`` output which
        is the same size as ``in1``.
      * ``"valid"``: return the portion of the ``"full"`` output which do not
        depend on padding at the array edges.

    boundary: only ``"fill"`` is supported.
    fillvalue: only ``0`` is supported.
    method: controls the computation method. Options are

      * ``"auto"``: (default) always uses the ``"direct"`` method.
      * ``"direct"``: lower to :func:`jax.lax.conv_general_dilated`.
      * ``"fft"``: compute the result via a fast Fourier transform.

    precision: Specify the precision of the computation. Refer to
      :class:`jax.lax.Precision` for a description of available values.

  Returns:
    Array containing the cross-correlation result.

  See Also:
    - :func:`jax.numpy.correlate`: 1D cross-correlation
    - :func:`jax.scipy.signal.correlate`: ND cross-correlation
    - :func:`jax.scipy.signal.convolve`: ND convolution

  Examples:
    A few 2D correlation examples:

    >>> x = jnp.array([[2, 1, 3],
    ...                [1, 3, 1],
    ...                [4, 1, 2]])
    >>> y = jnp.array([[1, 3],
    ...                [4, 2]])

    Full 2D correlation uses implicit zero-padding at the edges:

    >>> jax.scipy.signal.correlate2d(x, y, mode='full')
    Array([[ 4., 10., 10., 12.],
           [ 8., 15., 24.,  7.],
           [11., 28., 14.,  9.],
           [12.,  7.,  7.,  2.]], dtype=float32)

    Specifying ``mode = 'same'`` returns a centered 2D correlation of the same
    size as the first input:

    >>> jax.scipy.signal.correlate2d(x, y, mode='same')
    Array([[15., 24.,  7.],
           [28., 14.,  9.],
           [ 7.,  7.,  2.]], dtype=float32)

    Specifying ``mode = 'valid'`` returns only the portion of 2D correlation
    where the two arrays fully overlap:

    >>> jax.scipy.signal.correlate2d(x, y, mode='valid')
    Array([[15., 24.],
           [28., 14.]], dtype=float32)
  r|   r   z8correlate2d() only supports boundary='fill', fillvalue=0rL   z1correlate2d() only supports 2-dimensional inputs.c              3  ,   K   | ]  \  }}||k    y wr#   rA   rB   s      r(   r)   zcorrelate2d.<locals>.<genexpr>  rf   rG   c              3  ,   K   | ]  \  }}||k(    y wr#   rA   rB   s      r(   r)   zcorrelate2d.<locals>.<genexpr>  s     ERB"HErG   r   rj   r   )r}   r~   r$   r1   rP   rO   r,   rQ   rm   r   rt   )	r'   r.   r!   r   r   rk   r[   
same_shapers   s	            r(   correlate2dr     s   H 9>
X
YYWWS\Q"''#,!+
H
II	>C		399$=>	>$E3syy#))+DEE*	V^xx}chhjCXXl3TYGHF 
- wJ#
3cCdi@f 
- #
3cxxS#tyIJf 
- #
3cCdi@EEGf 
- #
3cxxS#tyIJf	-r<   c           	        |t        d      |dvrt        d      t        t        j                  |             \  }|dk(  r||j                  |d      z
  S |j                  |   }t        j                  t        j                  t        j                  d||f               }|d   dk  s|d   |kD  rt        d	      t        j                  ||d      }|j                  }|j                  |d      }t        t        |      d
z
        D ]  }	||	d
z      ||	   z
  }
t        j                  t        j                   |
|j"                        t        j$                  d
|
d
z   |j"                        |
j'                  |j"                        z  g      j(                  }t+        ||	   ||	d
z            }t-        j.                  |||         ^}}|j0                  |   j3                  t        j4                  ||t6        j8                  j:                               } t        j                  |j                  |      d|      S )a  
  Remove linear or piecewise linear trends from data.

  JAX implementation of :func:`scipy.signal.detrend`.

  Args:
    data: The input array containing the data to detrend.
    axis: The axis along which to detrend. Default is -1 (the last axis).
    type: The type of detrending. Can be:

      * ``'linear'``: Fit a single linear trend for the entire data.
      * ``'constant'``: Remove the mean value of the data.

    bp: A sequence of breakpoints. If given, piecewise linear trends
      are fit between these breakpoints.
    overwrite_data: This argument is not supported by JAX's implementation.

  Returns:
    The detrended data array.

  Examples:
    A simple detrend operation in one dimension:

    >>> data = jnp.array([1., 4., 8., 8., 9.])

    Removing a linear trend from the data:

    >>> detrended = jax.scipy.signal.detrend(data)
    >>> with jnp.printoptions(precision=3, suppress=True):  # suppress float error
    ...   print("Detrended:", detrended)
    ...   print("Underlying trend:", data - detrended)
    Detrended: [-1. -0.  2. -0. -1.]
    Underlying trend: [ 2.  4.  6.  8. 10.]

    Removing a constant trend from the data:

    >>> detrended = jax.scipy.signal.detrend(data, type='constant')
    >>> with jnp.printoptions(precision=3):  # suppress float error
    ...   print("Detrended:", detrended)
    ...   print("Underlying trend:", data - detrended)
    Detrended: [-5. -2.  2.  2.  3.]
    Underlying trend: [6. 6. 6. 6. 6.]
  z(overwrite_data argument not implemented.)constantlinearz*Trend type must be 'linear' or 'constant'.r   T)keepdimsr   zOBreakpoints must be non-negative and less than length of data along given axis.r@   dtyperj   )r}   r1   r   rQ   asarraymeanr,   r~   sortuniquer_moveaxisreshaper5   lenvstackonesr   arangeastypeTslicer   lstsqataddmatmulr   	PrecisionHIGHEST)dataaxistypebpoverwrite_datadata_arrNbp_arrr,   mNptsAslcoef_s                  r(   detrendr     s   Z 
H
II	''
A
BB$S[[%67)(	ZhmmD4m888tAWWRYYruuQAX/0Fay1}r
Qhii||HdA.HNNE2&H3v;?# \AE]VAY&d
**X^^,

1dQhhnn5HNN8SS 	 
  F1q5M*ba".hdQR$$cjjDCMMDYDY&Z%Z[h\ <<((/D99r<   c                   | j                   j                  dk(  r| j                  |j                         } | j                  ^ }}|dk(  r|dk(  r| dt        j
                  f   }	n]||z
  }
t        j                  ||z
  dz   |
      }t        t        j                  | |d      } t        j                  |d	      |
      }	 ||	      }	t        j                  |      rt        |	      \  }	|j                  dt!        |      z  d|fz         |	z  }	|dk(  rt#        j$                  |	|      S t#        j&                  |	j(                  |      S )zBCalculate windowed FFT in the same way the original SciPy does.
  r-   r@   r   .)stepr   )operand
slice_sizer   )r0   )start_index)r@   twosided)n)r   kindr   r,   r~   newaxisrQ   r   r   r   dynamic_slice_in_dimr   r8   rR   r   r   r   jnp_fftr   rfftreal)xwindetrend_funcnpersegnoverlapnfftsidesbatch_shapesignal_lengthrs   r   starts
slice_funcs                r(   _fft_helperr   3  s#    WW\\S	A !;\h!msBJJFXDZZ/!3$?F111WYZJ.SXXj2.6BF & 	c$V,GF;;tc+..!W=>G& j;;v&&<<t,,r<   c                   |dk  r| S || j                   |   dz
  kD  r"t        d| d| j                   |   dz
   d      t        j                  | dd|      }t	        j
                  t        j                  | d|dz   |      |      }t        j                  | dd|      }t	        j
                  t        j                  | |dz    d|      |      }t	        j                  d	|z  |z
  | d	|z  |z
  f|      }|S )
a  Extends `x` along with `axis` by odd-extension.

  This function was previously a part of "scipy.signal.signaltools" but is no
  longer exposed.

  Args:
    x : input array
    n : the number of points to be added to the both end
    axis: the axis to be extended
  r@   zThe extension length n (z;) is too big. It must not exceed x.shape[axis]-1, which is rc   r   r   r   NrL   )r,   r1   r   slice_in_dimrQ   rm   concatenate)r   r   r   left_endleft_ext	right_end	right_extexts           r(   odd_extr   S  s    UH	

"1# &8898I7J!	MN N aAD1(XXc&&q!QU>TJ(q"d6)hhs''QU8RdC$O)X0Y24 #	$# 
*r<   c           
       
 |dvrt        d| d      d } |d      t         |d       |dd	      d
 d}||vr(t        d| dt        |j                                      t	        j
                  t        j                  
d      
t        
| j                        
|2t        d|        t        |       \  } | }t        | j                  
      }n|dk7  rt        d      t        d| |       t        | |      \  } }| j                  |j                  k7  rt        d      	 t        j                  t        | j                  
      t        |j                  
            }t!        j"                  | j$                        }t'        j(                  |      j$                  }d}d}d}|+t	        j
                  t*        |d      }|dk  rt        d      t-        j.                  |||n|| j                  
   | j$                        \  }}||dz  }nt	        j
                  t*        |d      }||}nt	        j
                  t*        |d      }|n| j0                  dk(  rt        j2                  | j                  |      t        j2                  | j                  |      t        j2                  | j                  |      fS | j0                  dk(  s|j0                  dk(  rrt5        |t7        | j                  
   |j                  
         
      }t        j2                  ||      t        j2                  ||      t        j2                  ||      fS t        j8                  | 
d      } |&|j                  dkD  rt        j8                  |
d      }|| j                  d   |j                  d   k7  r| j                  d   |j                  d   k  ret        | j                        }|j                  d   | j                  d   z
  |d<   t        j:                  | t        j<                  | |      fd      } ndt        |j                        }| j                  d   |j                  d   z
  |d<   t        j:                  |t        j<                  | |      fd      }||k  rt        d      ||k\  rt        d       ||z
  }|#||   } || |dz  d!      } | |||dz  d!      }|r| j                  d   |z
   |z  |z  }t        j:                  | t        j<                  | g | j                  dd |      fd!      } |@t        j:                  |t        j<                  | g |j                  dd |      fd!      }t?        t@              rtC        tD        d"      }n.tG              r
dk7  r
fd#}n}nsd$ }nt        d%       |	d&k(  rd'|||z  jI                         z  z  }n*|	d(k(  rd'|jI                         dz  z  }nt        d)|	       |d*k(  rt        jJ                  |      }tM        |      \  }|rDd+} t        jN                  |       st        jN                  |      rd,} tQ        jR                  d-       nd,} | d,k(  rtU        jV                  |d|z  |.      }!n | d+k(  rtU        jX                  |d|z  |.      }!t[        | ||||||       }"|*t[        |||||||       }#t        j\                  |"      |#z  }"n|dk(  rt        j\                  |"      |"z  }"|"|z  }"| d+k(  r0|dk(  r+|dz  rdnd}$|"j^                  d/d|$f   ja                  d      }"t        jb                  |dz  | j                  d   |dz  z
  dz   ||z
  |.      |z  }%||%|dz  |z  z  }%|"je                  |      }"||d*k7  r|"jf                  }"t        j8                  |"d
      }"!|%|"fS # t         $ r}t        d      |d}~ww xY w)0a3  LAX-backend implementation of `scipy.signal._spectral_helper`.

  Unlike the original helper function, `y` can be None for explicitly
  indicating auto-spectral (non cross-spectral) computation.  In addition to
  this, `detrend` argument is renamed to `detrend_type` for avoiding internal
  name overlap.
  )psdstftzUnknown value for mode z!, must be one of: ('psd', 'stft')c                     d fd	}|S )Nc                    t        | j                        D cg c]  }d }}||f||<   t        j                  | |fi S c c}w )Nrg   )r5   r$   rQ   pad)r   r   r   unused_n	pad_widthkwargsr!   s        r(   r   z/_spectral_helper.<locals>.make_pad.<locals>.pad  sH    */-8h68i8AioWWQ	42622 9s   	Ar   rA   )r!   r   r   s   `` r(   make_padz"_spectral_helper.<locals>.make_pad  s    3 Jr<   reflectedger   g        )constant_valuesc                    | S r#   rA   )r   argsr   s      r(   <lambda>z"_spectral_helper.<locals>.<lambda>  s    q r<   )evenoddr   zerosNzUnknown boundary option 'z', must be one of: zaxis of windowed-FFTNspectral_helperr   z4two-argument mode is available only when mode=='psd'z=two-arguments must have the same rank ({x.ndim} vs {y.ndim}).z%x and y cannot be broadcast together.r   znperseg of windowed-FFTr@   "nperseg must be a positive integer)input_lengthr   rL   znoverlap of windowed-FFTznfft of windowed-FFTr   r+   z.nfft must be greater than or equal to nperseg.#noverlap must be less than nperseg.r   )r   r   c                p    t        j                  | d      }  |       } t        j                  | d      S )Nr   )rQ   r   )dr   detrend_types    r(   r   z&_spectral_helper.<locals>.detrend_func  s1    LLD"%O||Ar4((r<   c                    | S r#   rA   )r   s    r(   r   z"_spectral_helper.<locals>.<lambda>  s    Q r<   zUnsupported detrend type: density      ?spectrumzUnknown scaling: r   onesidedr   z9Input data is complex, switching to return_onesided=Falser   .)4r1   r   listkeysr	   concrete_or_erroroperatorindexr   r$   r   r   r   r,   rQ   broadcast_shapesr
   to_complex_dtyper   r~   finfointr   _triage_segmentsrl   r   r   minr   r   
zeros_like
isinstancestrr   r   callablesumsqrtr   rR   warningswarnr   fftfreqrfftfreqr   	conjugater   mulr   r   r   )&r   yfswindowr   r   r   r   return_onesidedscalingr   r!   r   paddedr   boundary_funcsy_arr
outershapeerrresult_dtype
freq_dtypenperseg_intnfft_intnoverlap_intr   r,   	pad_shapenstepext_funcnaddr   scaler   freqsrs   result_yendtimes&          `  `                           r(   _spectral_helperr'  o  s    
 
.tf 57 7 8 8 y!6"
C8(. ^#

#H: . 3 3 567	9: : 
		6L	M$	4	($Y%q)		"BAEaggt,Ju}MNN%q!,%a+HAuvvVWWI''QWWd(C(4U[[$(GIj
 ((1,xx%++*+(,((W/1KQ;<<"33gk774=1#{ !#L))X13L 
\H%%c41GHH Yvv{YYqww
+SYYqww
-KSYYWXW^W^`lMmmmvv{ejjAo:s1774=%++d:K'LdSeYYuj)399UJ+GSXZfIggg 
ll1dB!]uzzA~LLb)E ]qwwr{ekk"o5wwr{U[[_$qww-ikk"o3im
//1cnnQi@A2
Fau{{#iggbkEKKO3imooucnnQi&HI2Ne
E
FF[ 
:
;;

$% h'HK1$2.A}ukQ.R8e ggbk+%&.+=DCNN14Iaggcrl4ID4IJKRTUA}ooucnnQ>WCR@P>WRV>W&XY`bce c"7B?Lrz)
 "lL
1,@
AA 	2s))*E*#'')Q,E
(	2
33	V^HHUOE!%(&% E
c..q1emm , - E
jOOHad*=E
Xqt:>E q#|"L(EC& ]5#|&hGH]]6"X-Fu}]]6"V+FE/&
jTU]Q,$BCYYsAcEz"&&q)F	K!OQWWR[;?%BQ%F,.j
BDF
G$[1_""D==&& Y46>[[F <<D)&	f	u  I>?SHIs   &>_" "	_<+_77_<c                4    t        | d|||||||d|
d||	      S )a  
  Compute the short-time Fourier transform (STFT).

  JAX implementation of :func:`scipy.signal.stft`.

  Args:
    x: Array representing a time series of input values.
    fs: Sampling frequency of the time series (default: 1.0).
    window: Data tapering window to apply to each segment. Can be a window function name,
      a tuple specifying a window length and function, or an array (default: ``'hann'``).
    nperseg: Length of each segment (default: 256).
    noverlap: Number of points to overlap between segments (default: ``nperseg // 2``).
    nfft: Length of the FFT used, if a zero-padded FFT is desired. If ``None`` (default),
      the FFT length is ``nperseg``.
    detrend: Specifies how to detrend each segment. Can be ``False`` (default: no detrending),
      ``'constant'`` (remove mean), ``'linear'`` (remove linear trend), or a callable
      accepting a segment and returning a detrended segment.
    return_onesided: If True (default), return a one-sided spectrum for real inputs.
      If False, return a two-sided spectrum.
    boundary: Specifies whether the input signal is extended at both ends, and how.
      Options are ``None`` (no extension), ``'zeros'`` (default), ``'even'``, ``'odd'``,
      or ``'constant'``.
    padded: Specifies whether the input signal is zero-padded at the end to make its
      length a multiple of `nperseg`. If True (default), the padded signal length is
      the next multiple of ``nperseg``.
    axis: Axis along which the STFT is computed; the default is over the last axis (-1).

  Returns:
    A length-3 tuple of arrays ``(f, t, Zxx)``. ``f`` is the Array of sample frequencies.
    ``t`` is the Array of segment times, and ``Zxx`` is the STFT of ``x``.

  See Also:
    :func:`jax.scipy.signal.istft`: inverse short-time Fourier transform.
  Nr   r   )r  r   r!   r   r  )r'  )r   r  r  r   r   r   r   r  r   r  r   s              r(   r   r   F  s2    L 
!T2vw",4%!'	
) )r<   c                   t        | |||||||||	|
d      \  }}}||dz   }|j                  dk\  r<|j                  dkD  r,|j                  d   dkD  r|d	k(  rt	        j
                  |j                  d         j                  |j                        }t        j                  |      rYt        j                  t        j                  |      d
      dt        j                  t        j                  |      d
      z  z   }nt        j                  |d
      }||z  }||fS |dk(  r|j                  d
      }||fS t        d|       t        j                  ||j                  dd       }||fS )aM	  
  Estimate cross power spectral density (CSD) using Welch's method.

  This is a JAX implementation of :func:`scipy.signal.csd`. It is similar to
  :func:`jax.scipy.signal.welch`, but it operates on two input signals and
  estimates their cross-spectral density instead of the power spectral density
  (PSD).

  Args:
    x: Array representing a time series of input values.
    y: Array representing the second time series of input values, the same length as ``x``
      along the specified ``axis``. If not specified, then assume ``y = x`` and compute
      the PSD ``Pxx`` of ``x`` via Welch's  method.
    fs: Sampling frequency of the inputs (default: 1.0).
    window: Data tapering window to apply to each segment. Can be a window function name,
      a tuple specifying a window length and function, or an array (default: ``'hann'``).
    nperseg: Length of each segment (default: 256).
    noverlap: Number of points to overlap between segments (default: ``nperseg // 2``).
    nfft: Length of the FFT used, if a zero-padded FFT is desired. If ``None`` (default),
      the FFT length is ``nperseg``.
    detrend: Specifies how to detrend each segment. Can be ``False`` (default: no detrending),
      ``'constant'`` (remove mean), ``'linear'`` (remove linear trend), or a callable
      accepting a segment and returning a detrended segment.
    return_onesided: If True (default), return a one-sided spectrum for real inputs.
      If False, return a two-sided spectrum.
    scaling: Selects between computing the power spectral density (``'density'``, default)
      or the power spectrum (``'spectrum'``)
    axis: Axis along which the CSD is computed (default: -1).
    average: The type of averaging to use on the periodograms; one of ``'mean'`` (default)
      or ``'median'``.

  Returns:
    A length-2 tuple of arrays ``(f, Pxy)``. ``f`` is the array of sample frequencies,
    and ``Pxy`` is the cross spectral density of `x` and `y`

  Notes:
    The original SciPy function exhibits slightly different behavior between
    ``csd(x, x)`` and ``csd(x, x.copy())``.  The LAX-backend version is designed
    to follow the latter behavior.  To replicate the former, call this function
    function as ``csd(x, None)``.

  See Also:
    - :func:`jax.scipy.signal.welch`: Power spectral density.
    - :func:`jax.scipy.signal.stft`: Short-time Fourier transform.
  r   r    Ny                rL   r   r   r@   medianr   y              ?r   z(average must be "median" or "mean", got )r'  r$   rl   r,   r   _median_biasr   r   rQ   rR   r*  r   imagr   r1   r   )r   r  r  r  r   r   r   r   r  r  r   averager#  r   Pxybiass                   r(   csdr0  s  sa   d #1aVWh")?GT',.-%C ]
(C 	XX]sxx!|
yy}q	H	))#))B-8??		JC CHHSM3CHHSM;;<# 

3R(#t 
 fhhBh 
	 CG9MNNKKSYYs^,c	r<   c                R    t        | d|||||||||	|
      \  }}||j                  fS )aE  
  Estimate power spectral density (PSD) using Welch's method.

  This is a JAX implementation of :func:`scipy.signal.welch`. It divides the
  input signal into overlapping segments, computes the modified periodogram for
  each segment, and averages the results to obtain a smoother estimate of the PSD.

  Args:
    x: Array representing a time series of input values.
    fs: Sampling frequency of the inputs (default: 1.0).
    window: Data tapering window to apply to each segment. Can be a window function name,
      a tuple specifying a window length and function, or an array (default: ``'hann'``).
    nperseg: Length of each segment (default: 256).
    noverlap: Number of points to overlap between segments (default: ``nperseg // 2``).
    nfft: Length of the FFT used, if a zero-padded FFT is desired. If ``None`` (default),
      the FFT length is ``nperseg``.
    detrend: Specifies how to detrend each segment. Can be ``False`` (default: no detrending),
      ``'constant'`` (remove mean), ``'linear'`` (remove linear trend), or a callable
      accepting a segment and returning a detrended segment.
    return_onesided: If True (default), return a one-sided spectrum for real inputs.
      If False, return a two-sided spectrum.
    scaling: Selects between computing the power spectral density (``'density'``, default)
      or the power spectrum (``'spectrum'``)
    axis: Axis along which the PSD is computed (default: -1).
    average: The type of averaging to use on the periodograms; one of ``'mean'`` (default)
      or ``'median'``.

  Returns:
    A length-2 tuple of arrays ``(f, Pxx)``. ``f`` is the array of sample frequencies,
    and ``Pxx`` is the power spectral density of ``x``.

  See Also:
    - :func:`jax.scipy.signal.csd`: Cross power spectral density.
    - :func:`jax.scipy.signal.stft`: Short-time Fourier transform.
  N)
r  r  r   r   r   r   r  r  r   r-  )r0  r   )r   r  r  r   r   r   r   r  r  r   r-  r#  Pxxs                r(   welchr3    s>    P 1dr&'$4#2Gg/*%
 
r<   c                   t        d|        t        j                  t        |d      }| j                  dk  rt        d      | j                  ^ }}}t        j                  |      }| j                  |||f      } ||dz
  z  |z   }d|dz
  |z  z   }||z  }t        j                  | ddd||z
  ff      } | j                  ||||f      } | j                  d      } t        j                  | ddd|fdf      } | j                  d   dz
  }	| j                  |d	f      } | d
d
d
||	z  |z  f   } | j                  |||	|z  f      } | j                  d      d
d
d
|f   } | j                  t        |      dz         S )a4  Utility function compatible with tf.signal.overlap_and_add.

  Args:
    x: An array with `(..., frames, frame_length)`-shape.
    step_size: An integer denoting overlap offsets. Must be less than
      `frame_length`.

  Returns:
    An array with `(..., output_size)`-shape containing overlapped signal.
  _overlap_and_addzstep_size for overlap_and_addrL   z2Input must have (..., frames, frame_length) shape.r@   rg   r   )r   rL   r@      r   Nr   r   )r   r	   r   r   r$   r1   r,   mathprodr   rQ   r   	transposer  r3   )
r   	step_sizer   nframessegment_lenflat_batchsizeoutput_sizenstep_per_segmentpadded_segment_lenshrunkens
             r(   r5  r5    s    $a($$	957)VVaZ
I
JJ'(ww$;99[).ii+67!Wq[)K7+;?y88 )94	gga&&1&8;&F"GHI!ii*;YGH! kk,!	gga&&1g,78!WWQZ!^(ii$%!6)I5667!ii!2Hy4HIJ! eeemA||O$!	
5%-	..r<   c
                	  	 t        d|       } | j                  dk  rt        d      t        	| j                        	t        | j                        	k(  rt        d      t	        j
                  | t        j                  | j                              } |rd| j                  	   dz
  z  n| j                  	   }
t        j                  t        |xs |
d      }|dk  rt        d      d	}||
}|r)||
dz   k(  r!|dz  }nt        j                  t        |d      }||k  rt        d| d| d      t        j                  t        |xs |dz  d      }||k\  rt        d      ||z
  }| j                  dz
  k7  s	| j                  dz
  k7  rCt        	fdt        | j                        D              }t	        j                  | |	fz         } |rt         j"                  nt         j$                  } || d|      dd
|d
d
f   }t'        |t(              ry|dk(  rt|dk(  rt	        j*                  dg      n<t	        j,                  t	        j.                  d	t0        j2                  |d            dz  }|j5                  |j                        }nt'        |t(        t        f      r2	 d	dlm}  |||      }t	        j*                  ||j                        }nXt	        j
                  |      }t=        |j                        dk7  rt        d      |j                  d	   |k7  rt        d|       ||j?                         z  }tA        jB                  |g t        |j                  dz
        d      }tE        ||z  jG                  dd      |      }t	        jH                  ||z  |j                  d   d      }tE        |jG                  dd      |      }|r |d|dz  |dz   f   }|d|dz  |dz   f   }|t	        jJ                  |dkD  |d      z  }|j                  dkD  r3| j                  dz
  k7  r!	k  rdz  t	        jL                  |d      }t	        jN                  |j                  d	   t1        jP                  |j                        j                        |z  }||fS # t:        $ r}t;        d|      |d
}~ww xY w) a7  
  Perform the inverse short-time Fourier transform (ISTFT).

  JAX implementation of :func:`scipy.signal.istft`; computes the inverse of
  :func:`jax.scipy.signal.stft`.

  Args:
    Zxx: STFT of the signal to be reconstructed.
    fs: Sampling frequency of the time series (default: 1.0)
    window: Data tapering window to apply to each segment. Can be a window function name,
      a tuple specifying a window length and function, or an array (default: ``'hann'``).
    nperseg: Number of data points per segment in the STFT. If ``None`` (default), the
      value is determined from the size of ``Zxx``.
    noverlap: Number of points to overlap between segments (default: ``nperseg // 2``).
    nfft: Number of FFT points used in the STFT. If ``None`` (default), the
      value is determined from the size of ``Zxx``.
    input_onesided: If True (default), interpret the input as a one-sided STFT
      (positive frequencies only). If False, interpret the input as a two-sided STFT.
    boundary: If True (default), it is assumed that the input signal was extended at
      its boundaries by ``stft``. If `False`, the input signal is assumed to have been truncated at the boundaries by `stft`.
    time_axis: Axis in `Zxx` corresponding to time segments (default: -1).
    freq_axis: Axis in `Zxx` corresponding to frequency bins (default: -2).

  Returns:
    A length-2 tuple of arrays ``(t, x)``. ``t`` is the Array of signal times, and ``x``
    is the reconstructed time series.

  See Also:
    :func:`jax.scipy.signal.stft`: short-time Fourier transform.

  Examples:
    Demonstrate that this gives the inverse of :func:`~jax.scipy.signal.stft`:

    >>> x = jnp.array([1., 2., 3., 2., 1., 0., 1., 2.])
    >>> f, t, Zxx = jax.scipy.signal.stft(x, nperseg=4)
    >>> print(Zxx)  # doctest: +SKIP
    [[ 1. +0.j   2.5+0.j   1. +0.j   1. +0.j   0.5+0.j ]
     [-0.5+0.5j -1.5+0.j  -0.5-0.5j -0.5+0.5j  0. -0.5j]
     [ 0. +0.j   0.5+0.j   0. +0.j   0. +0.j  -0.5+0.j ]]
    >>> t, x_reconstructed = jax.scipy.signal.istft(Zxx)
    >>> print(x_reconstructed)
    [1. 2. 3. 2. 1. 0. 1. 2.]
  istftrL   zInput stft must be at least 2d!z/Must specify differing time and frequency axes!r   r@   znperseg: segment length of STFTr   r   Nznfft of STFTzFFT length (z) must be longer than nperseg (z).znoverlap of STFTr   c              3  0   K   | ]  }|hvs
|  y wr#   rA   )r%   idx	freq_axis	time_axiss     r(   r)   zistft.<locals>.<genexpr>v  s$      M#i5K*KMs   r   )r   r   .hannr   F)endpoint)
get_windowz&scipy must be available to use window=zwindow must be 1-Dzwindow must have length of r   r   g|=))r   r$   r1   r   rQ   r   r
   r   r   r,   r	   r   r   r3   r5   r9  r   irfftr]   r  r  arraysinlinspacer~   pir   scipy.signalrJ  ImportErrorr   r  r   expand_dimsr5  swapaxesrepeatwherer   r   r   )Zxxr  r  r   r   r   input_onesidedr   rG  rF  	n_defaultr  r  r  r  
outer_idxsifuncxsubsr   rJ  r  r   win_squarednormr&  s           ``               r(   rC  rC     s   b 	#&#XX\
6
77	3884)	3884))
F
GGCv66syyAB#1?qCIIi(1,-IIi(  &&sG,@y+LN+1_
9
::(	\H+Q6!mh%%c4@H

xj ?}BOQ Q ''	8'{a');=,[ 
:
;;

$% #((Q,)sxx!|"; MSXXM MJ
--Z9i*@@
AC *'--w||%
"
%c<K<&:
;% 6!1)Q.#))SE
CGGCLLBEES^in<o4ptu4uC
**U[[
!C&3,'N) V[
)C
))Cu{{
+C
++f
C
399~+,,
yy|{"4[MBCC3779% 	9uUZZ!^49b9:#--b"5u=!

C#IBbA+	+..r26	>$ 	#{A~Q//
/0A[!^k1n$5556DsyytS))! VVaZCHHqL 	Y	Q	
,,q"i
(a	AGGAJbhhqww&7&=&=	>	C$	q.A  NA&CD#MNs   +R. .	S7SS)r   N)
r'   r   r.   r   r!   r  r9   zSequence[int] | Nonereturnr   )r'   r   r.   r   r!   r  r^  r   )
r'   r   r.   r   r!   r  rk   r   r^  r   )r   rw   N)r'   r   r.   r   r!   r  ry   r  rk   r   r^  r   )r   r|   r   N)r'   r   r.   r   r!   r  r   r  r   floatrk   r   r^  r   )r   r   r   N)r   r   r   r   r   r  r   r   r   Noner^  r   )r   r   r   r   r   zCallable[[Array], Array]r   r   r   r   r   
int | Noner   r  r^  r   r   )r   r   r   r   r   r   r^  r   )r   rH  NNNr   Tr   r   r   NF)r   r   r  ArrayLike | Noner  r   r  r  r   ra  r   ra  r   ra  r   z%bool | str | Callable[[Array], Array]r  boolr  r  r   r   r!   r  r   
str | Noner  rc  r^  tuple[Array, Array, Array])
r   rH     NNFTr   Tr   )r   r   r  r   r  r  r   r   r   ra  r   ra  r   rc  r  rc  r   rd  r  rc  r   r   r^  re  )
r   rH  NNNr   Tr   r   r   )r   r   r  rb  r  r   r  r  r   ra  r   ra  r   ra  r   r  r  rc  r  r  r   r   r-  r  r^  tuple[Array, Array])r   r   r  r   r  r  r   ra  r   ra  r   ra  r   r  r  rc  r  r  r   r   r-  r  r^  rg  )r   r   r:  r   r^  r   )	r   rH  NNNTTr   r   )rV  r   r  r   r  r  r   ra  r   ra  r   ra  rW  rc  r   rc  rG  r   rF  r   r^  rg  ):
__future__r   collections.abcr   r   	functoolsr   r7  r   typingr   r	  r   r~   jax._srcr   r	   r
   r   rQ   jax._src.api_utilr   jax._src.lax.laxr   jax._src.numpyr   r   r   jax._src.numpy.utilr   r   r   r   jax._src.third_party.scipyr   jax._src.typingr   r   jax._src.utilr   r   r   r   r2   rt   rz   r   r   r   r   r   r   r'  r   r0  r3  r5  rC  rA   r<   r(   <module>rt     s   # .           ! 1 * ) !  5 , G G =C-1F *F 6;F P%;VD HN(,>M%>M16>MB LR@DG;G;0=G;ING;T IO)-9W&9W279Wx MSAE] ]1>]JO]@ NO#'F: F:,1F:R--(+-3=-FI-NS-@8 EHAEEIKUBKOS$)T T4>T)T8BT $IT '+	T =@	T
 T
 ,/T
 CMT "T /ITn NQ9=U\*,*)*),6*)*)15*)HR*) *) %(*) 2L*)Z KQ;?0:5>'-	JJ.8JJ*-J J 03J 	J "%	J 3F	JZ 8>=A2<7@)/	--0:--,/-  - 25- 	- $'	- 5H	-`-/` :@=A:>24	HH0:HH37H H -0H 	H #6	Hr<   