
    VpfLD                       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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 d dlmZmZ d dlmZ ee z  ee         z  ez  ez  dz  Z!ee!e"e!df         f         Z#ee$e%ee	j&        f         Z'	 d-dZ(d Z)d Z*	 	 	 	 	 	 d.d/d(Z+	 	 	 	 	 d0d1d)Z,	 	 	 	 	 d0d1d*Z-	 	 	 	 	 d0d1d+Z.	 	 	 	 	 d0d1d,Z/dS )2    )annotations)CallableSequence)UnionN)lax)config)core)dtypes)util)	lax_numpy)
reductions)check_arraylikepromote_dtypes)Array	ArrayLike)EllipsisType.Tc                   t          j        |           } t          |t                    rt	          j        | j        t          j                  rdt	          j        | j                  j	        |cxk    r"t	          j        | j                  j
        k    rn nt          j        || j                  }nt          j        |          }t          j        || j                  \  }}	}
t          | ||||	|
||||
  
        S )a  Helper for indexed updates.

  Computes the value of x that would result from computing::
    x[idx] op= y
  except in a pure functional way, with no in-place updating.

  Args:
    x: ndarray to be updated.
    idx: None, an integer, a slice, an ellipsis, an ndarray with integer dtype,
      or a tuple of those indicating the locations of `x` into which to scatter-
      update the values in `y`.
    y: values to be scattered.
    scatter_op: callable, one of lax.scatter, lax.scatter_add, lax.scatter_min,
      or lax_scatter_max.
    indices_are_sorted: whether `idx` is known to be sorted
    unique_indices: whether `idx` is known to be free of duplicates

  Returns:
    An ndarray representing an updated `x` after performing the scatter-update.
  dtype)jnpasarray
isinstanceintnp
issubdtyper   integeriinfominmax_split_index_for_jitshape_scatter_impl)xidxy
scatter_opindices_are_sortedunique_indicesmodenormalize_indicestreedef
static_idxdynamic_idxs              T/var/www/html/nettyfy-visnx/env/lib/python3.11/site-packages/jax/_src/ops/scatter.py_scatter_updater/   ,   s    , 
k!nn!C R]17BJ?? hqwq9999BHQW$5$5$999999AQW%%%AAAA &)%=c17%K%K"':{	q!Z*k)>4(
* 
* *    c
           	     .   t          j        |           }
t          j        |           }t          j        ||           sWt          j        dt          j        |           dt          j        |            dt          j        j	        dt                     t          j        |||          }t          j        t          j        |           ||	          }t          j        |j                  r| S t%          | |          \  } }t          j        |t)          |j                            }t          j        ||j                  }|j        rt          j        ||j                  }|j        rt          j        | |j                  } t          j        |j        j        |j        j        |j        j                  } || |j         |||j!        p||j"        p||          }|j        rt          j        ||j                  }tG          j$        ||
|          S )	NzLscatter inputs have incompatible types: cannot safely cast value from dtype=z
 to dtype=z  with jax_numpy_dtype_promotion=z6. In future JAX releases this will result in an error.)r*   axis)update_window_dimsinserted_window_dimsscatter_dims_to_operand_dims)r'   r(   r)   )%r   r   r
   is_weakly_typedsafe_to_castwarningswarnr   numpy_dtype_promotionvalueFutureWarningr   !_merge_static_and_dynamic_indices_index_to_gatherr!   r	   is_empty_shapeslice_shaper   broadcast_totuplesqueezenewaxis_dimsreversed_y_dimsrevscalar_bool_dimsexpand_dimsScatterDimensionNumbersdnumsoffset_dimscollapsed_slice_dimsstart_index_mapgather_indicesr'   r(   lax_internal_convert_element_type)r#   r%   r&   r+   r,   r-   r'   r(   r)   r*   r   	weak_typer$   indexerrK   outs                   r.   r"   r"   T   s    )A,,%$Q'')		Q	"	" M=IaLL= =,/IaLL= =#)#?#E= = =    	-gz;OO# 1s3DF F F'
 
,-- H	1		$!Q 
q% 34455!	k!'.///! ,7*++A 57344A 
%}0 ;!(!>  %
 	
wq%1G5G);^			 	 	#
  5
+c73
4
4C		+C		B	BBr0   c                   | t           j        u rdS | t           j        u rdS | t           j        u rY|t          j        k    rdS t          j        |t          j                  rt          j	        |          j
        S t          d          S | t           j        u rZ|t          j        k    rdS t          j        |t          j                  rt          j	        |          j        S t          d           S t          d|            )zCGet an appropriate identity for a given operation in a given dtype.r      TinfFzUnrecognized op: )r   scatter_addscatter_mulscatter_minr
   bool_r   r   r   r   r   floatscatter_maxr   
ValueError)opr   s     r.   _get_identityr`      s    3?1	S_1	S_T	s{	+	+ "Yu!!<<	S_U	s{	+	+ "Yu!!%LL=
---
.
..r0   Fnamestrdatar   segment_idsr&   r   num_segments
int | Noner'   boolr(   bucket_sizereducerCallable | Noner)   lax.GatherScatterMode | Nonereturnr   c
           
     d   t          | ||           |	t          j        j        n|	}	t	          j        |          }t	          j        |          }|j        }
|t          j        |          dz   }t          j
        |d          }||dk     rt          d          |Mt	          j        |f|j        dd          z   t          ||
          |
          }t          ||||||d|	          S |J t!          j        |j        |          }t	          j        ||f|j        dd          z   t          ||
          |
          }t          |t          j        t	          j        |j        d                   |z  |d d d f         f         ||||d|	          } ||d                              |
          S )	NrV   z&segment_sum() `num_segments` argument.r   z"num_segments must be non-negative.r   F)r*   r)   r2   )r   r   GatherScatterModeFILL_OR_DROPr   r   r   r   r   r	   concrete_dim_or_errorr^   fullr!   r`   r/   r   ceil_of_ratiosize	index_exparangeastype)ra   rc   rd   r&   re   r'   r(   rh   ri   r)   r   rT   num_bucketss                r.   _segment_updaterx      s    $k***/3|		+	+$	T		$K((+
*%6+&&*L+L:bcc,,"2"2
9
:
::
(L?TZ^3 U335B B BC	;j*<D: : : : 
			";#3[AA++|,tz!""~=z511	@ 	@ 	@#cj!21!566+E!$'*+ 
,*(e$		8 	8 	8#
 
1				$	$U	+	++r0   c                \    t          d| |t          j        ||||t          j        |
  
        S )aD  Computes the sum within segments of an array.

  Similar to TensorFlow's `segment_sum
  <https://www.tensorflow.org/api_docs/python/tf/math/segment_sum>`_

  Args:
    data: an array with the values to be summed.
    segment_ids: an array with integer dtype that indicates the segments of
      `data` (along its leading axis) to be summed. Values can be repeated and
      need not be sorted.
    num_segments: optional, an int with nonnegative value indicating the number
      of segments. The default is set to be the minimum number of segments that
      would support all indices in ``segment_ids``, calculated as
      ``max(segment_ids) + 1``.
      Since `num_segments` determines the size of the output, a static value
      must be provided to use ``segment_sum`` in a JIT-compiled function.
    indices_are_sorted: whether ``segment_ids`` is known to be sorted.
    unique_indices: whether `segment_ids` is known to be free of duplicates.
    bucket_size: size of bucket to group indices into. ``segment_sum`` is
      performed on each bucket separately to improve numerical stability of
      addition. Default ``None`` means no bucketing.
    mode: a :class:`jax.lax.GatherScatterMode` value describing how
      out-of-bounds indices should be handled. By default, values outside of the
      range [0, num_segments) are dropped and do not contribute to the sum.

  Returns:
    An array with shape :code:`(num_segments,) + data.shape[1:]` representing the
    segment sums.

  Examples:
    Simple 1D segment sum:

    >>> data = jnp.arange(5)
    >>> segment_ids = jnp.array([0, 0, 1, 1, 2])
    >>> segment_sum(data, segment_ids)
    Array([1, 5, 4], dtype=int32)

    Using JIT requires static `num_segments`:

    >>> from jax import jit
    >>> jit(segment_sum, static_argnums=2)(data, segment_ids, 3)
    Array([1, 5, 4], dtype=int32)
  segment_sumr)   )rx   r   rX   r   sumrc   rd   re   r'   r(   rh   r)   s          r.   rz   rz      :    d 
T;.+z~D
R 
R 
R Rr0   c                \    t          d| |t          j        ||||t          j        |
  
        S )a  Computes the product within segments of an array.

  Similar to TensorFlow's `segment_prod
  <https://www.tensorflow.org/api_docs/python/tf/math/segment_prod>`_

  Args:
    data: an array with the values to be reduced.
    segment_ids: an array with integer dtype that indicates the segments of
      `data` (along its leading axis) to be reduced. Values can be repeated and
      need not be sorted. Values outside of the range [0, num_segments) are
      dropped and do not contribute to the result.
    num_segments: optional, an int with nonnegative value indicating the number
      of segments. The default is set to be the minimum number of segments that
      would support all indices in ``segment_ids``, calculated as
      ``max(segment_ids) + 1``.
      Since `num_segments` determines the size of the output, a static value
      must be provided to use ``segment_prod`` in a JIT-compiled function.
    indices_are_sorted: whether ``segment_ids`` is known to be sorted.
    unique_indices: whether `segment_ids` is known to be free of duplicates.
    bucket_size: size of bucket to group indices into. ``segment_prod`` is
      performed on each bucket separately to improve numerical stability of
      addition. Default ``None`` means no bucketing.
    mode: a :class:`jax.lax.GatherScatterMode` value describing how
      out-of-bounds indices should be handled. By default, values outside of the
      range [0, num_segments) are dropped and do not contribute to the sum.

  Returns:
    An array with shape :code:`(num_segments,) + data.shape[1:]` representing the
    segment products.

  Examples:
    Simple 1D segment product:

    >>> data = jnp.arange(6)
    >>> segment_ids = jnp.array([0, 0, 1, 1, 2, 2])
    >>> segment_prod(data, segment_ids)
    Array([ 0,  6, 20], dtype=int32)

    Using JIT requires static `num_segments`:

    >>> from jax import jit
    >>> jit(segment_prod, static_argnums=2)(data, segment_ids, 3)
    Array([ 0,  6, 20], dtype=int32)
  segment_prodr{   )rx   r   rY   r   prodr}   s          r.   r   r      s:    f 
dK,.+zT
S 
S 
S Sr0   c                \    t          d| |t          j        ||||t          j        |
  
        S )a  Computes the maximum within segments of an array.

  Similar to TensorFlow's `segment_max
  <https://www.tensorflow.org/api_docs/python/tf/math/segment_max>`_

  Args:
    data: an array with the values to be reduced.
    segment_ids: an array with integer dtype that indicates the segments of
      `data` (along its leading axis) to be reduced. Values can be repeated and
      need not be sorted. Values outside of the range [0, num_segments) are
      dropped and do not contribute to the result.
    num_segments: optional, an int with nonnegative value indicating the number
      of segments. The default is set to be the minimum number of segments that
      would support all indices in ``segment_ids``, calculated as
      ``max(segment_ids) + 1``.
      Since `num_segments` determines the size of the output, a static value
      must be provided to use ``segment_max`` in a JIT-compiled function.
    indices_are_sorted: whether ``segment_ids`` is known to be sorted.
    unique_indices: whether `segment_ids` is known to be free of duplicates.
    bucket_size: size of bucket to group indices into. ``segment_max`` is
      performed on each bucket separately. Default ``None`` means no bucketing.
    mode: a :class:`jax.lax.GatherScatterMode` value describing how
      out-of-bounds indices should be handled. By default, values outside of the
      range [0, num_segments) are dropped and do not contribute to the sum.

  Returns:
    An array with shape :code:`(num_segments,) + data.shape[1:]` representing the
    segment maximums.

  Examples:
    Simple 1D segment max:

    >>> data = jnp.arange(6)
    >>> segment_ids = jnp.array([0, 0, 1, 1, 2, 2])
    >>> segment_max(data, segment_ids)
    Array([1, 3, 5], dtype=int32)

    Using JIT requires static `num_segments`:

    >>> from jax import jit
    >>> jit(segment_max, static_argnums=2)(data, segment_ids, 3)
    Array([1, 3, 5], dtype=int32)
  segment_maxr{   )rx   r   r]   r   r   r}   s          r.   r   r   8  r~   r0   c                \    t          d| |t          j        ||||t          j        |
  
        S )a  Computes the minimum within segments of an array.

  Similar to TensorFlow's `segment_min
  <https://www.tensorflow.org/api_docs/python/tf/math/segment_min>`_

  Args:
    data: an array with the values to be reduced.
    segment_ids: an array with integer dtype that indicates the segments of
      `data` (along its leading axis) to be reduced. Values can be repeated and
      need not be sorted. Values outside of the range [0, num_segments) are
      dropped and do not contribute to the result.
    num_segments: optional, an int with nonnegative value indicating the number
      of segments. The default is set to be the minimum number of segments that
      would support all indices in ``segment_ids``, calculated as
      ``max(segment_ids) + 1``.
      Since `num_segments` determines the size of the output, a static value
      must be provided to use ``segment_min`` in a JIT-compiled function.
    indices_are_sorted: whether ``segment_ids`` is known to be sorted.
    unique_indices: whether `segment_ids` is known to be free of duplicates.
    bucket_size: size of bucket to group indices into. ``segment_min`` is
      performed on each bucket separately. Default ``None`` means no bucketing.
    mode: a :class:`jax.lax.GatherScatterMode` value describing how
      out-of-bounds indices should be handled. By default, values outside of the
      range [0, num_segments) are dropped and do not contribute to the sum.

  Returns:
    An array with shape :code:`(num_segments,) + data.shape[1:]` representing the
    segment minimums.

  Examples:
    Simple 1D segment min:

    >>> data = jnp.arange(6)
    >>> segment_ids = jnp.array([0, 0, 1, 1, 2, 2])
    >>> segment_min(data, segment_ids)
    Array([0, 2, 4], dtype=int32)

    Using JIT requires static `num_segments`:

    >>> from jax import jit
    >>> jit(segment_min, static_argnums=2)(data, segment_ids, 3)
    Array([0, 2, 4], dtype=int32)
  segment_minr{   )rx   r   rZ   r   r   r}   s          r.   r   r   o  r~   r0   )NT)NFFNNN)ra   rb   rc   r   rd   r   r&   r   re   rf   r'   rg   r(   rg   rh   rf   ri   rj   r)   rk   rl   r   )NFFNN)rc   r   rd   r   re   rf   r'   rg   r(   rg   rh   rf   r)   rk   rl   r   )0
__future__r   collections.abcr   r   typingr   r9   numpyr   jaxr   jax._srcr   r	   r
   r   jax._src.laxrP   jax._src.numpyr   r   r   jax._src.numpy.utilr   r   jax._src.typingr   r   typesr   r   sliceSingleIndexrC   Indexcomplexr\   numberScalarr/   r"   r`   rx   rz   r   r   r    r0   r.   <module>r      s  " # " " " " " . . . . . . . .                                          , , , , , , + + + + + + % % % % % % ? ? ? ? ? ? ? ? , , , , , , , ,      EkHSM)E1L@4Gk5c!1223	wsBI-	. BF"* "* "* "*P2C 2C 2Cj/ / /4 04/4+0.2/39=', ', ', ', ',X ,0+0',*.594R 4R 4R 4R 4Rr -1,1(-+/6:5S 5S 5S 5S 5St ,0+0',*.594R 4R 4R 4R 4Rr ,0+0',*.594R 4R 4R 4R 4R 4R 4Rr0   