
    ukiF                    :   d dl mZ d dlmZ d dl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 d dlmZ d dlmZmZ d dlmZ d dlmZ d dlm Z m!Z!m"Z" 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ#	 	 	 	 	 	 	 	 	 	 	 	 ddZ$d Z%	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d dZ&	 	 	 	 	 d!	 	 	 	 	 	 	 	 	 	 	 	 	 d"dZ'	 	 	 	 	 d!	 	 	 	 	 	 	 	 	 	 	 	 	 d"dZ(	 	 	 	 	 d!	 	 	 	 	 	 	 	 	 	 	 	 	 d"dZ)	 	 	 	 	 d!	 	 	 	 	 	 	 	 	 	 	 	 	 d"dZ*y)#    )annotations)Callable)partial)AnyN)config)core)dtypes)numpy)	tree_util)util)lax)slicing)indexing)
reductions)check_arraylikepromote_dtypes)	auto_axes)NamedSharding)Array	ArrayLikeIndexc	           	        t        j                  |       } t        |t              rt	        j
                  | j                  t        j                        r~t	        j                  | j                        j                  |cxk  r,t	        j                  | j                        j                  k  r%n n"t        j                  || j                        }nt        j                  |      }t        j                  j                  || j                        j                         }	t!        j"                  |	      \  }
}t%        t&        ||||||      }|* t)        |||j*                  j,                        | ||
      S  || |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)
scatter_optreedefindices_are_sortedunique_indicesmodenormalize_indices)out_shardingaxes)jnpasarray
isinstanceintnp
issubdtyper   integeriinfominmaxr   	NDIndexerfrom_raw_indicesshapeexpand_bool_indicesr   tree_flattenr   _scatter_implr   meshexplicit_axestuple)xidxyr   r   r   r   r    r!   indexerdynamic_idxr   internal_scatters                O/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/jax/_src/ops/scatter.py_scatter_updater=   *   s,   2 
kk!n!CR]]177BJJ?hhqwwq9BHHQWW$5$9$99AQWW%AAA //QWW=QQS'"//8+w
G+#$)	+
 9%L&++99![* * 
!Qk 2	33    c          	     z   t        j                  |       }	t        j                  |       }
t        j                  ||       sbt        j                  dt        j                  |       dt        j                  |        dt        j                  j                   dt               t        j                  ||      }|j                  t        j                  |       j                   |      }t        j"                  |j$                        r| S t'        | |      \  } }t)        j*                  |t-        |j$                        |j.                        }t)        j0                  ||j2                        }|j4                  r t        j6                  ||j4                        }|j8                  r t        j:                  | |j8                        } t=        j>                  |j@                  jB                  |j@                  jD                  |j@                  jF                  |j@                  jH                  |j@                  jJ                        } || |jL                  |||jN                  xs ||jP                  xs ||	      }|j8                  r t        j0                  ||j8                        }t        jR                  ||	|
      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    )r!   axis)update_window_dimsinserted_window_dimsscatter_dims_to_operand_dimsoperand_batching_dimsscatter_indices_batching_dims)r   r   r   )*r   r   r	   is_weakly_typedsafe_to_castwarningswarnr   numpy_dtype_promotionvalueFutureWarningr   tree_unflatten	to_gatherr   typeofshardingis_empty_shapeslice_shaper   r#   broadcast_tor5   slice_shardingsqueezenewaxis_dimsreversed_y_dimsrevscalar_bool_dimsexpand_dimsr   ScatterDimensionNumbersdnumsoffset_dimscollapsed_slice_dimsstart_index_maprE   start_indices_batching_dimsgather_indicesr   r   _convert_element_type)r6   r8   r:   r   r   r   r   r   r    r   	weak_typegeneral_indexerr9   r]   outs                  r<   r2   r2   ^   s+   
 ))A,%$$Q')			Q	"MMIIaL>CIIaL> :##)#?#?#E#E"F G==  ,,WkB/%%dkk!n&=&=Qb%c' 
,,-H	1	$!Q 
q% 3 34$+$:$:<! 
kk!'../!7**+A7334A 
)
)}}00 ;;!(!>!>!--==")--"K"K% 	wq%11G5G));^			#
 
++c733
4C		"	"3y	99r>   c                <   | t         j                  u ry| t         j                  u ry| t         j                  u rb|t        j
                  k(  ryt	        j                  |t        j                        rt	        j                  |      j                  S t        d      S | t         j                  u rc|t        j
                  k(  ry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_identityrr      s    7	W   	W   			5"**	-\\% $$$<	W   			5"**	-\\% $$$%L=
(-
..r>   c
           
     Z   t        | ||       |	t        j                  j                  n|	}	t	        j
                  |      }t	        j
                  |      }|j                  }
|t        j                  |      dz   }t        j                  |d      }||dk  rt        d      |Ft	        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      j+                  |
      S )	Nrh   z&segment_sum() `num_segments` argument.r   z"num_segments must be non-negative.r   F)r    r   r@   )r   r   GatherScatterModeFILL_OR_DROPr#   r$   r   r'   r,   r   concrete_dim_or_errorrp   fullr/   rr   r=   r   ceil_of_ratiosize	index_exparangeastype)namedatasegment_idsr   num_segmentsr   r   bucket_sizereducerr   r   rf   num_bucketss                r<   _segment_updater      s    $k*37<	"	"	/	/T$	T	$K(+
**%66+&*L++L:bc,,"2
9
::
((L?TZZ^3 U35BC	;j*<D: : 
		"";#3#3[A++|,tzz!"~=z51	@#cjj!2!21!56+E!$'*+ 
,*(e$		8#
 
1		$	$U	++r>   c                d    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   )r   r   rj   r   sumr~   r   r   r   r   r   r   s          r<   r   r      s4    d 
T;(;(;\.+z~~D
R Rr>   c                d    t        d| |t        j                  ||||t        j                  |
      S )aX  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.
    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.
      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 result.

  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   )r   r   rk   r   prodr   s          r<   r   r     s4    d 
dK)<)<l.+zT
S Sr>   c                d    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.
    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 result.

  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   )r   r   ro   r   r,   r   s          r<   r   r   E  4    b 
T;(;(;\.+z~~D
R Rr>   c                d    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.
    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 result.

  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   )r   r   rl   r   r+   r   s          r<   r   r   {  r   r>   )NTN)r6   r   r7   zIndex | tuple[Index, ...]r8   r   r   Callable[..., Array]r   boolr   r   r   &slicing.GatherScatterMode | str | Noner    r   r!   zNamedSharding | None)r6   r   r8   r   r:   ztuple[Any, ...]r   r   r   ztree_util.PyTreeDefr   r   r   r   r   r   r    r   )NFFNNN)r}   strr~   r   r   r   r   r   r   
int | Noner   r   r   r   r   r   r   zCallable | Noner   r   returnr   )NFFNN)r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )+
__future__r   collections.abcr   	functoolsr   typingr   rI   r
   r'   jax._srcr   r   r	   r#   r   r   jax._src.laxr   r   jax._src.numpyr   r   jax._src.numpy.utilr   r   jax._src.pjitr   jax._src.sharding_implsr   jax._src.typingr   r   r   r=   r2   rr   r   r   r   r   r    r>   r<   <module>r      s  " # $        !      # % ? # 1 3 3 dh9=	.4 .4.B.4(,.4>B.4 A.4 ]a.4 #7	.4h6:26:.6: '+6: =A6: ?	6: TX	6:r/4 04/4+0.2/3CG',#',!*', !)', #-	',
 )-', %)', ",', -', A', MR',X ,0+0',*.?C4R&4R(4R %)4R !%	4R
 (4R =4R IN4Rr -1,1(-+/@D4S'4S)4S &*4S "&	4S
 )4S >4S JO4Sr ,0+0',*.?C3R&3R(3R %)3R !%	3R
 (3R =3R IN3Rp ,0+0',*.?C3R&3R(3R %)3R !%	3R
 (3R =3R IN3Rr>   