
    ukiL                   x   U d dl mZ d dlmZmZ d dlZd dlZd dlm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 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( d dl)m*Z* d dl+m,Z, d dl-m.Z. d dl/m0Z1 d dl2m3Z3m4Z4m5Z5 d dl6m7Z7 d dl8m9Z9m:Z: e9e;cZ;Z<e:e=cZ=Z>ej~                  Z@eAZB	 d	 	 	 	 	 ddZAdd	 	 	 	 	 	 	 	 	 dd ZCdd	 	 	 	 	 	 	 	 	 dd!ZD G d" d#e      ZE G d$ d%ej                        ZGd&d&ddd'	 	 	 	 	 	 	 	 	 	 	 dd(ZH G d) d*e      ZI eed+,      d&d&dd-	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd.       ZJ eed/,      d&d&dd-	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd0       ZK eed1,      d&d&dd-	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd2       ZL eed3,      d&d&dd-	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd4       ZM eed5,      d&d&dd-	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd6       ZN ej                         ZPd7eQd8<   d9d&d&dd:	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd;ZRd< ZSd&d&dd-	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd=ZTdd>ZU	 d	 	 	 	 	 	 	 dd?ZV	 	 d	 	 	 dd@ZW	 ddd	 	 	 	 	 	 	 	 	 ddAZX	 ddd	 	 	 	 	 	 	 	 	 ddBZYdd	 	 	 	 	 	 	 	 	 ddCZZdd	 	 	 	 	 	 	 	 	 ddDZ[dE Z\dF Z]dG Z^dH Z_dI Z`dJ ZadK Zb e(e\e'dLe_ eej                  dL      M      Zd ej                  ede`       eaej                  ed<   ebej                  ed<   edj                  dN        ZidO Zj ej                  edej       dP ZldQ ZmdR ZndS ZodT ZpdU ZqdV ZrdW ZsdX ZtdY ZudZ Zv e(eleod[ e&d       em eej                  d[      en\      Zwepej                  ew<   eqej                  ew<   erej                  ew<   etej                  ew<   eue j                  ew<   evej                  ew<   d] Z| ej                  ewe|       d^ Z}d_ Z~d` Zda Zdb Zdc Zdd Zde Z e(e}edfe~ eej                  df      eeg      Zeej                  e<   eej                  e<   eej                  e<   dh Z ej                  ee       di Zdj Zdk Zdl Zdm Zdn Zdo Zdp Zdq Zdr ZddsZdt Zdu Zdv Zdw Zdx Z e(eedy e&d       e eej                  dy      z      Z ej0                  eed       eej                  e<   eej                  e<   	 	 dd{Zd| Z ej                  ee       d} Zd~ Zd ZddZ	 	 ddZd Zd Zd Zd Zd Zd Zd Z e(eed e&d       e eej                  d      e      Z eee      ej                  e<    eee      ej                  e<    eee      ejP                  e<   d ejR                  e<    e(eed e&d       e eej                  d      e      Z eee      ej                  e<    eee      ej                  e<    eee      ejP                  e<   d ejR                  e<    e(eed e&d       e eej                  d      e      Zd Z ej0                  ed de       eej                  e<    eee      ejP                  e<   d ejR                  e<   d Z e(eed e&d       e eej                  d      e      Z eee      ejP                  e<   d ejR                  e<    eee      ej                  e<    e(eed e&d       e eej                  d      e      Z eee      ejP                  e<   d ejR                  e<    eee      ej                  e<   d Zd Z e(eed e&d       e eej                  d      e      Zeej                  e<   eej                  e<    eee      ejP                  e<   d ejR                  e<   d Z	 	 ddZ ej                  ee        ej                  ee        ej                  ee        ej                  ee        ej                  ee        ej                  ee       d Zd Z ej                  e eee,jn                        d        ej                  e eee,jp                        d       	 	 	 	 	 	 	 	 ddZy)    )annotations)CallableSequenceN)partial)
NamedTuple)ad_util)api)core)dispatch)dtypes)source_info_util)api_boundary)util)mesh)ad)batching)mlir)partial_eval)lax)utils)_argnum_weak_typeinput_dtypestandard_primitive)ir)hlo)NamedSharding)PartitionSpec)Array	ArrayLikeShape)ds)safe_mapsafe_zipc                |    t         j                  | t        |      t        |      |d      S t        |            S )a  Wraps XLA's `Slice
  <https://www.openxla.org/xla/operation_semantics#slice>`_
  operator.

  Args:
    operand: an array to slice
    start_indices: a sequence of ``operand.ndim`` start indices.
    limit_indices: a sequence of ``operand.ndim`` limit indices.
    strides: an optional sequence of ``operand.ndim`` strides.

  Returns:
    The sliced array

  Examples:
    Here are some examples of simple two-dimensional slices:

    >>> x = jnp.arange(12).reshape(3, 4)
    >>> x
    Array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]], dtype=int32)

    >>> lax.slice(x, (1, 0), (3, 2))
    Array([[4, 5],
           [8, 9]], dtype=int32)

    >>> lax.slice(x, (0, 0), (3, 4), (1, 2))
    Array([[ 0,  2],
           [ 4,  6],
           [ 8, 10]], dtype=int32)

    These two examples are equivalent to the following Python slicing syntax:

    >>> x[1:3, 0:2]
    Array([[4, 5],
           [8, 9]], dtype=int32)

    >>> x[0:3, 0:4:2]
    Array([[ 0,  2],
           [ 4,  6],
           [ 8, 10]], dtype=int32)

  See Also:
    - :attr:`jax.numpy.ndarray.at`
    - :func:`jax.lax.slice_in_dim`
    - :func:`jax.lax.index_in_dim`
    - :func:`jax.lax.dynamic_slice`
  Nstart_indiceslimit_indicesstrides)slice_pbindtuple)operandr&   r'   r(   s       O/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/jax/_src/lax/slicing.pyslicer.   >   sM    f 
gU=-A$)-$8&-od 
 
K K;@> 
 
K K    Tallow_negative_indicesc                   t        | ||      }t        j                  |      }t        j                  | g| ^} }t	        j
                  | g|dt        |      iS )a  Wraps XLA's `DynamicSlice
  <https://www.openxla.org/xla/operation_semantics#dynamicslice>`_
  operator.

  Args:
    operand: an array to slice.
    start_indices: a list of scalar indices, one per dimension. These values
      may be dynamic.
    slice_sizes: the size of the slice. Must be a sequence of non-negative
      integers with length equal to `ndim(operand)`. Inside a JIT compiled
      function, only static values are supported (all JAX arrays inside JIT
      must have statically known size).
    allow_negative_indices: a bool or sequence of bools, one per dimension; if
      a bool is passed, it applies to all dimensions. For each dimension,
      if true, negative indices are permitted and are are interpreted relative
      to the end of the array. If false, negative indices are treated as if they
      were out of bounds and the result is implementation defined, typically
      clamped to the first index.

  Returns:
    An array containing the slice.

  Examples:
    Here is a simple two-dimensional dynamic slice:

    >>> x = jnp.arange(12).reshape(3, 4)
    >>> x
    Array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]], dtype=int32)

    >>> dynamic_slice(x, (1, 1), (2, 3))
    Array([[ 5,  6,  7],
           [ 9, 10, 11]], dtype=int32)

    Note the potentially surprising behavior for the case where the requested slice
    overruns the bounds of the array; in this case the start index is adjusted to
    return a slice of the requested size:

    >>> dynamic_slice(x, (1, 1), (2, 4))
    Array([[ 4,  5,  6,  7],
           [ 8,  9, 10, 11]], dtype=int32)

  See Also:
    - :attr:`jax.numpy.ndarray.at`
    - :func:`jax.lax.slice`
    - :func:`jax.lax.dynamic_slice_in_dim`
    - :func:`jax.lax.dynamic_index_in_dim`
  slice_sizes)_dynamic_slice_indicesr
   canonicalize_shapestandard_insert_pvarydynamic_slice_pr*   r+   )r,   r&   r3   r1   sizess        r-   dynamic_slicer9   v   s`    p )}46-

!
!+
.% 66wOO'M			g	P	P5<	PPr/   c               ~    t        | ||      }t        j                  | |g| ^} }}t        j                  | |g| S )a  Wraps XLA's `DynamicUpdateSlice
  <https://www.openxla.org/xla/operation_semantics#dynamicupdateslice>`_
  operator.

  Args:
    operand: an array to slice.
    update: an array containing the new values to write onto `operand`.
    start_indices: a list of scalar indices, one per dimension.
    allow_negative_indices: a bool or sequence of bools, one per dimension; if
      a bool is passed, it applies to all dimensions. For each dimension,
      if true, negative indices are permitted and are are interpreted relative
      to the end of the array. If false, negative indices are treated as if they
      were out of bounds and the result is implementation defined, typically
      clamped to the first index.

  Returns:
    An array containing the slice.

  Examples:
    Here is an example of updating a one-dimensional slice update:

    >>> x = jnp.zeros(6)
    >>> y = jnp.ones(3)
    >>> dynamic_update_slice(x, y, (2,))
    Array([0., 0., 1., 1., 1., 0.], dtype=float32)

    If the update slice is too large to fit in the array, the start
    index will be adjusted to make it fit

    >>> dynamic_update_slice(x, y, (3,))
    Array([0., 0., 0., 1., 1., 1.], dtype=float32)
    >>> dynamic_update_slice(x, y, (5,))
    Array([0., 0., 0., 1., 1., 1.], dtype=float32)

    Here is an example of a two-dimensional slice update:

    >>> x = jnp.zeros((4, 4))
    >>> y = jnp.ones((2, 2))
    >>> dynamic_update_slice(x, y, (1, 2))
    Array([[0., 0., 0., 0.],
           [0., 0., 1., 1.],
           [0., 0., 1., 1.],
           [0., 0., 0., 0.]], dtype=float32)

  See Also:
    - :attr:`jax.numpy.ndarray.at`
    - :attr:`lax.dynamic_update_index_in_dim`
    - :attr:`lax.dynamic_update_slice_in_dim`
  )r4   r
   r6   dynamic_update_slice_pr*   )r,   updater&   r1   s       r-   dynamic_update_slicer=      sS    n )}46-$($>$>v%'%%'!'6M		$	$Wf	E}	EEr/   c                  L    e Zd ZU dZded<   ded<   ded<   dZded<   dZded<   y	)
GatherDimensionNumbersa#  
  Describes the dimension number arguments to an `XLA's Gather operator
  <https://www.openxla.org/xla/operation_semantics#gather>`_. See the XLA
  documentation for more details of what the dimension numbers mean.

  Args:
    offset_dims: the set of dimensions in the `gather` output that offset into
      an array sliced from `operand`. Must be a tuple of integers in ascending
      order, each representing a dimension number of the output.
    collapsed_slice_dims: the set of dimensions `i` in `operand` that have
      `slice_sizes[i] == 1` and that should not have a corresponding dimension
      in the output of the gather. Must be a tuple of integers in ascending
      order.
    start_index_map: for each dimension in `start_indices`, gives the
      corresponding dimension in the `operand` that is to be sliced. Must be a
      tuple of integers with size equal to `start_indices.shape[-1]`.
    operand_batching_dims: the set of batching dimensions `i` in `operand` that
      have `slice_sizes[i] == 1` and that should have a corresponding dimension
      in both the `start_indices` (at the same index in
      `start_indices_batching_dims`) and output of the gather. Must be a tuple
      of integers in ascending order.
    start_indices_batching_dims: the set of batching dimensions `i` in
      `start_indices` that should have a corresponding dimension in both the
      `operand` (at the same index in `operand_batching_dims`) and output of the
      gather. Must be a tuple of integers (order is fixed based on
      correspondence with `operand_batching_dims`).

  Unlike XLA's `GatherDimensionNumbers` structure, `index_vector_dim` is
  implicit; there is always an index vector dimension and it must always be the
  last dimension. To gather scalar indices, add a trailing dimension of size 1.
  ztuple[int, ...]offset_dimscollapsed_slice_dimsstart_index_map operand_batching_dimsstart_indices_batching_dimsN)__name__
__module____qualname____doc____annotations__rD   rE   rC   r/   r-   r?   r?      s1    > ''""+--133r/   r?   c                      e Zd ZdZ ej
                         Z ej
                         Z ej
                         Z ej
                         Z	e
dd       Zy)GatherScatterModea^  
  Describes how to handle out-of-bounds indices in a gather or scatter.

  Possible values are:

  CLIP:
    Indices will be clamped to the nearest in-range value, i.e., such that the
    entire window to be gathered is in-range.
  FILL_OR_DROP:
    If any part of a gathered window is out of bounds, the entire window
    that is returned, even those elements that were otherwise in-bounds, will be
    filled with a constant.
    If any part of a scattered window is out of bounds, the entire window
    will be discarded.
  PROMISE_IN_BOUNDS:
    The user promises that indices are in bounds. No additional checking will be
    performed. In practice, with the current XLA implementation this means
    that out-of-bounds gathers will be clamped but out-of-bounds scatters will
    be discarded. Gradients will not be correct if indices are out-of-bounds.
  c                    t        | t              r| S | dk(  rt        j                  S | 
| dk(  s| dk(  rt        j                  S | dk(  rt        j                  S | dk(  rt        j
                  S t        d|  d      )Nclipfilldroppromise_in_boundsone_hotzUnknown gather mode "")
isinstancerL   CLIPFILL_OR_DROPPROMISE_IN_BOUNDSONE_HOT
ValueError)ss    r-   from_anyzGatherScatterMode.from_any4  s    !&'hF{###yAK1;+++000I~&&&.qc344r/   N)rZ   str | GatherScatterMode | NonereturnrL   )rF   rG   rH   rI   enumautorU   rV   rW   rX   staticmethodr[   rC   r/   r-   rL   rL     sP    ( 
$,diikDIIK'5 5r/   rL   Funique_indicesindices_are_sortedmode
fill_valuec          
        |t         j                  }t         j                  |      }|t         j                  k(  r3|2t	        |       }	t        j                  |	t        j                        rt        j                  }nt        j                  |	t        j                        r t        j                  |	      j                  }nt        j                  |	t        j                        r t        j                  |	      j                  }nj|	t
        j                  k(  rd}nTt        j                  |	t
        j                         r t        j                  d      j                  }nt#        d|	       d}t%        j&                  | |      \  } }t(        j+                  | ||t%        j,                  |      t/        |      t/        |      ||      S )aZ  Gather operator.

  Wraps `XLA's Gather operator
  <https://www.openxla.org/xla/operation_semantics#gather>`_.

  :func:`gather` is a low-level operator with complicated semantics, and most JAX
  users will never need to call it directly. Instead, you should prefer using
  `Numpy-style indexing`_, and/or :func:`jax.numpy.ndarray.at`, perhaps in combination
  with :func:`jax.vmap`.

  Args:
    operand: an array from which slices should be taken
    start_indices: the indices at which slices should be taken
    dimension_numbers: a `lax.GatherDimensionNumbers` object that describes
      how dimensions of `operand`, `start_indices` and the output relate.
    slice_sizes: the size of each slice. Must be a sequence of non-negative
      integers with length equal to `ndim(operand)`.
    indices_are_sorted: whether `indices` is known to be sorted. If
      true, may improve performance on some backends.
    unique_indices: whether the elements gathered from ``operand`` are
      guaranteed not to overlap with each other. If ``True``, this may improve
      performance on some backends. JAX does not check this promise: if
      the elements overlap the behavior is undefined.
    mode: how to handle indices that are out of bounds: when set to ``'clip'``,
      indices are clamped so that the slice is within bounds, and when
      set to ``'fill'`` or ``'drop'`` gather returns a slice full of
      ``fill_value`` for the affected slice. The behavior for out-of-bounds
      indices when set to ``'promise_in_bounds'`` is implementation-defined.
    fill_value: the fill value to return for out-of-bounds slices when `mode`
      is ``'fill'``. Ignored otherwise. Defaults to ``NaN`` for inexact types,
      the largest negative value for signed types, the largest positive value
      for unsigned types, and ``True`` for booleans.

  Returns:
    An array containing the gather output.

  Examples:
    As mentioned above, you should basically never use :func:`gather` directly,
    and instead use NumPy-style indexing expressions to gather values from
    arrays.

    For example, here is how you can extract values at particular indices using
    straightforward indexing semantics, which will lower to XLA's Gather operator:

    >>> import jax.numpy as jnp
    >>> x = jnp.array([10, 11, 12])
    >>> indices = jnp.array([0, 1, 1, 2, 2, 2])

    >>> x[indices]
    Array([10, 11, 11, 12, 12, 12], dtype=int32)

    For control over settings like ``indices_are_sorted``, ``unique_indices``, ``mode``,
    and ``fill_value``, you can use the :attr:`jax.numpy.ndarray.at` syntax:

    >>> x.at[indices].get(indices_are_sorted=True, mode="promise_in_bounds")
    Array([10, 11, 11, 12, 12, 12], dtype=int32)

    By comparison, here is the equivalent function call using :func:`gather` directly,
    which is not something typical users should ever need to do:

    >>> from jax import lax
    >>> lax.gather(x, indices[:, None], slice_sizes=(1,),
    ...            dimension_numbers=lax.GatherDimensionNumbers(
    ...                offset_dims=(),
    ...                collapsed_slice_dims=(0,),
    ...                start_index_map=(0,)),
    ...            indices_are_sorted=True,
    ...            mode=lax.GatherScatterMode.PROMISE_IN_BOUNDS)
    Array([10, 11, 11, 12, 12, 12], dtype=int32)

  .. _Numpy-style indexing: https://numpy.org/doc/stable/reference/arrays.indexing.html
  NTuint32z(Unsupported dtype for gather fill_value dimension_numbersr3   rb   rc   rd   re   )rL   rW   r[   rV   _dtyper   
issubdtypenpinexactnansignedintegeriinfominunsignedintegermaxbool_prng_keyrY   r
   r6   gather_pr*   r5   bool)
r,   r&   ri   r3   rb   rc   rd   re   parsed_modedtypes
             r-   gatherrz   D  s_   ` 
\..D!**40+%222Woe			5"**	-VV
UB$4$45\\%(,,
UB$6$67\\%(,,
FLL 
UFOO4XXh'++
CE7KLLJ55g}M'=	}0A))+6.)01 
 
 r/   c                  L    e Zd ZU dZded<   ded<   ded<   dZded<   dZded<   y	)
ScatterDimensionNumbersa  
  Describes the dimension number arguments to an `XLA's Scatter operator
  <https://www.openxla.org/xla/operation_semantics#scatter>`_. See the XLA
  documentation for more details of what the dimension numbers mean.

  Args:
    update_window_dims: the set of dimensions in the `updates` that are window
      dimensions. Must be a tuple of integers in ascending
      order, each representing a dimension number.
    inserted_window_dims: the set of size 1 window dimensions that must be
      inserted into the shape of `updates`. Must be a tuple of integers in
      ascending order, each representing a dimension number of the output. These
      are the mirror image of `collapsed_slice_dims` in the case of `gather`.
    scatter_dims_to_operand_dims: for each dimension in `scatter_indices`, gives
      the corresponding dimension in `operand`. Must be a sequence of integers
      with size equal to `scatter_indices.shape[-1]`.
    operand_batching_dims: the set of batching dimensions `i` in `operand` that
      should have a corresponding dimension in both the `scatter_indices` (at
      the same index in `scatter_indices_batching_dims`) and `updates`. Must be
      a tuple of integers in ascending order. These are the mirror image of
      `operand_batching_dims` in the case of `gather`.
    scatter_indices_batching_dims: the set of batching dimensions `i` in
      `scatter_indices` that should have a corresponding dimension in both the
      `operand` (at the same index in `operand_batching_dims`) and output of the
      gather. Must be a tuple of integers (order is fixed based on
      correspondence with `input_batching_dims`). These are the mirror image of
      `start_indices_batching_dims` in the case of `gather`.

  Unlike XLA's `ScatterDimensionNumbers` structure, `index_vector_dim` is
  implicit; there is always an index vector dimension and it must always be the
  last dimension. To scatter scalar indices, add a trailing dimension of size 1.
  Sequence[int]update_window_dimsinserted_window_dimsscatter_dims_to_operand_dimsrC   rD   scatter_indices_batching_dimsN)rF   rG   rH   rI   rJ   rD   r   rC   r/   r-   r|   r|     s2    @ $#%% --)++133r/   r|   zlax.scatter_add)repro_api_namerc   rb   rd   c               6   t        j                  t         j                  t        j                  t        j
                  | d                  \  }}t        j                  | ||      \  } }}t        j                  | |||||||t        j                  |      	      S )aO  Scatter-add operator.

  Wraps `XLA's Scatter operator
  <https://www.openxla.org/xla/operation_semantics#scatter>`_, where
  addition is used to combine updates and values from `operand`.

  The semantics of scatter are complicated, and its API might change in the
  future. For most use cases, you should prefer the
  :attr:`jax.numpy.ndarray.at` property on JAX arrays which uses
  the familiar NumPy indexing syntax.

  Args:
    operand: an array to which the scatter should be applied
    scatter_indices: an array that gives the indices in `operand` to which each
      update in `updates` should be applied.
    updates: the updates that should be scattered onto `operand`.
    dimension_numbers: a `lax.ScatterDimensionNumbers` object that describes how
      dimensions of `operand`, `scatter_indices`, `updates` and the output
      relate.
    indices_are_sorted: whether `scatter_indices` is known to be sorted. If
      true, may improve performance on some backends.
    unique_indices: whether the elements to be updated in ``operand`` are
      guaranteed to not overlap with each other. If true, may improve
      performance on some backends. JAX does not check this promise: if the
      updated elements overlap when ``unique_indices`` is ``True`` the behavior
      is undefined.
    mode: how to handle indices that are out of bounds: when set to 'clip',
      indices are clamped so that the slice is within bounds, and when set to
      'fill' or 'drop' out-of-bounds updates are dropped. The behavior for
      out-of-bounds indices when set to 'promise_in_bounds' is
      implementation-defined.

  Returns:
    An array containing the sum of `operand` and the scattered updates.

  Examples:
    As mentioned above, you should basically never use :func:`scatter_add`
    directly, and instead perform scatter-style operations using NumPy-style
    indexing expressions via :attr:`jax.numpy.ndarray.at`.

    Here is and example of updating entries in an array using
    :attr:`jax.numpy.ndarray.at`, which lowers to an XLA Scatter operation:

    >>> x = jnp.ones(5)
    >>> indices = jnp.array([1, 2, 4])
    >>> values = jnp.array([2.0, 3.0, 4.0])

    >>> x.at[indices].add(values)
    Array([1., 3., 4., 1., 5.], dtype=float32)

    This syntax also supports several of the optional arguments to
    :func:`scatter_add`, for example:

    >>> x.at[indices].add(values, indices_are_sorted=True,
    ...                   mode='promise_in_bounds')
    Array([1., 3., 4., 1., 5.], dtype=float32)

    By comparison, here is the equivalent function call using
    :func:`scatter_add` directly, which is not something typical users should
    ever need to do:

    >>> lax.scatter_add(x, indices[:, None], values,
    ...                 dimension_numbers=lax.ScatterDimensionNumbers(
    ...                     update_window_dims=(),
    ...                     inserted_window_dims=(0,),
    ...                     scatter_dims_to_operand_dims=(0,)),
    ...                 indices_are_sorted=True,
    ...                 mode=lax.GatherScatterMode.PROMISE_IN_BOUNDS)
    Array([1., 3., 4., 1., 5.], dtype=float32)
  r   update_jaxprupdate_constsri   rc   rb   rd   )r   _reduction_jaxpraddr
   get_aval_constr6   scatter_add_pr*   rL   r[   	r,   scatter_indicesupdatesri   rc   rb   rd   jaxprconstss	            r-   scatter_addr     s    X &&sww'+}}SZZ5K'LN-%&*&@&@')#'?G			e.?+N%%d+	 
 
- -r/   zlax.scatter_subc               6   t        j                  t         j                  t        j                  t        j
                  | d                  \  }}t        j                  | ||      \  } }}t        j                  | |||||||t        j                  |      	      S )a  Scatter-sub operator.

  Wraps `XLA's Scatter operator
  <https://www.openxla.org/xla/operation_semantics#scatter>`_, where
  subtraction is used to combine updates and values from `operand`.

  The semantics of scatter are complicated, and its API might change in the
  future. For most use cases, you should prefer the
  :attr:`jax.numpy.ndarray.at` property on JAX arrays which uses
  the familiar NumPy indexing syntax.

  Args:
    operand: an array to which the scatter should be applied
    scatter_indices: an array that gives the indices in `operand` to which each
      update in `updates` should be applied.
    updates: the updates that should be scattered onto `operand`.
    dimension_numbers: a `lax.ScatterDimensionNumbers` object that describes how
      dimensions of `operand`, `start_indices`, `updates` and the output relate.
    indices_are_sorted: whether `scatter_indices` is known to be sorted. If
      true, may improve performance on some backends.
    unique_indices: whether the elements to be updated in ``operand`` are
      guaranteed to not overlap with each other. If true, may improve
      performance on some backends. JAX does not check this promise: if the
      updated elements overlap when ``unique_indices`` is ``True`` the behavior
      is undefined.
    mode: how to handle indices that are out of bounds: when set to 'clip',
      indices are clamped so that the slice is within bounds, and when set to
      'fill' or 'drop' out-of-bounds updates are dropped. The behavior for
      out-of-bounds indices when set to 'promise_in_bounds' is
      implementation-defined.

  Returns:
    An array containing the difference between `operand` and the scattered
    updates.
  r   r   )r   r   subr
   r   r   r6   scatter_sub_pr*   rL   r[   r   s	            r-   scatter_subr   /  s    \ &&	ggt}}SZZ34-% '+&@&@')#'?G			)+#%%d+ 
 

 
r/   zlax.scatter_mulc               6   t        j                  t         j                  t        j                  t        j
                  | d                  \  }}t        j                  | ||      \  } }}t        j                  | |||||||t        j                  |      	      S )a  Scatter-multiply operator.

  Wraps `XLA's Scatter operator
  <https://www.openxla.org/xla/operation_semantics#scatter>`_, where
  multiplication is used to combine updates and values from `operand`.

  The semantics of scatter are complicated, and its API might change in the
  future. For most use cases, you should prefer the
  :attr:`jax.numpy.ndarray.at` property on JAX arrays which uses
  the familiar NumPy indexing syntax.

  Args:
    operand: an array to which the scatter should be applied
    scatter_indices: an array that gives the indices in `operand` to which each
      update in `updates` should be applied.
    updates: the updates that should be scattered onto `operand`.
    dimension_numbers: a `lax.ScatterDimensionNumbers` object that describes
      how dimensions of `operand`, `start_indices`, `updates` and the output
      relate.
    indices_are_sorted: whether `scatter_indices` is known to be sorted. If
      true, may improve performance on some backends.
    unique_indices: whether the elements to be updated in ``operand`` are
      guaranteed to not overlap with each other. If true, may improve performance on
      some backends. JAX does not check this promise: if the updated elements
      overlap when ``unique_indices`` is ``True`` the behavior is undefined.
    mode: how to handle indices that are out of bounds: when set to 'clip',
      indices are clamped so that the slice is within bounds, and when
      set to 'fill' or 'drop' out-of-bounds updates are dropped. The behavior
      for out-of-bounds indices when set to 'promise_in_bounds' is
      implementation-defined.

  Returns:
    An array containing the product of `operand` and the scattered updates.
     r   )r   r   mulr
   r   r   r6   scatter_mul_pr*   rL   r[   r   s	            r-   scatter_mulr   o      P &&sww'+}}SZZ5K'LN-%&*&@&@')#'?G			e.?+N%%d+	 
 
- -r/   zlax.scatter_minc               6   t        j                  t         j                  t        j                  t        j
                  | d                  \  }}t        j                  | ||      \  } }}t        j                  | |||||||t        j                  |      	      S )a  Scatter-min operator.

  Wraps `XLA's Scatter operator
  <https://www.openxla.org/xla/operation_semantics#scatter>`_, where
  the `min` function is used to combine updates and values from `operand`.

  The semantics of scatter are complicated, and its API might change in the
  future. For most use cases, you should prefer the
  :attr:`jax.numpy.ndarray.at` property on JAX arrays which uses
  the familiar NumPy indexing syntax.

  Args:
    operand: an array to which the scatter should be applied
    scatter_indices: an array that gives the indices in `operand` to which each
      update in `updates` should be applied.
    updates: the updates that should be scattered onto `operand`.
    dimension_numbers: a `lax.ScatterDimensionNumbers` object that describes
      how dimensions of `operand`, `start_indices`, `updates` and the output
      relate.
    indices_are_sorted: whether `scatter_indices` is known to be sorted. If
      true, may improve performance on some backends.
    unique_indices: whether the elements to be updated in ``operand`` are
      guaranteed to not overlap with each other. If true, may improve performance on
      some backends. JAX does not check this promise: if the updated elements
      overlap when ``unique_indices`` is ``True`` the behavior is undefined.
    mode: how to handle indices that are out of bounds: when set to 'clip',
      indices are clamped so that the slice is within bounds, and when
      set to 'fill' or 'drop' out-of-bounds updates are dropped. The behavior
      for out-of-bounds indices when set to 'promise_in_bounds' is
      implementation-defined.

  Returns:
    An array containing the min of `operand` and the scattered updates.
  r   r   )r   r   rq   r
   r   r   r6   scatter_min_pr*   rL   r[   r   s	            r-   scatter_minr     r   r/   zlax.scatter_maxc               6   t        j                  t         j                  t        j                  t        j
                  | d                  \  }}t        j                  | ||      \  } }}t        j                  | |||||||t        j                  |      	      S )a  Scatter-max operator.

  Wraps `XLA's Scatter operator
  <https://www.openxla.org/xla/operation_semantics#scatter>`_, where
  the `max` function is used to combine updates and values from `operand`.

  The semantics of scatter are complicated, and its API might change in the
  future. For most use cases, you should prefer the
  :attr:`jax.numpy.ndarray.at` property on JAX arrays which uses
  the familiar NumPy indexing syntax.

  Args:
    operand: an array to which the scatter should be applied
    scatter_indices: an array that gives the indices in `operand` to which each
      update in `updates` should be applied.
    updates: the updates that should be scattered onto `operand`.
    dimension_numbers: a `lax.ScatterDimensionNumbers` object that describes
      how dimensions of `operand`, `start_indices`, `updates` and the output
      relate.
    indices_are_sorted: whether `scatter_indices` is known to be sorted. If
      true, may improve performance on some backends.
    unique_indices: whether the elements to be updated in ``operand`` are
      guaranteed to not overlap with each other. If true, may improve performance on
      some backends. JAX does not check this promise: if the updated elements
      overlap when ``unique_indices`` is ``True`` the behavior is undefined.
    mode: how to handle indices that are out of bounds: when set to 'clip',
      indices are clamped so that the slice is within bounds, and when
      set to 'fill' or 'drop' out-of-bounds updates are dropped. The behavior
      for out-of-bounds indices when set to 'promise_in_bounds' is
      implementation-defined.

  Returns:
    An array containing the max of `operand` and the scattered updates.
  r   r   )r   r   rs   r
   r   r   r6   scatter_max_pr*   rL   r[   r   s	            r-   scatter_maxr     r   r/   zweakref.WeakKeyDictionary_scatter_apply_cacherC   )update_shaperc   rb   rd   c                  t        j                  |d| j                        }fd}		 t        j	                  |	      }	t        j                  |	t        j                  t        j                  |                   \  }
}t        j                  | ||      \  } }}t        j                  | |||
||||t        j                  |      	      S # t
        $ r Y w xY w)a  Scatter-apply operator.

  Wraps `XLA's Scatter operator
  <https://www.openxla.org/xla/operation_semantics#scatter>`_, where values
  from ``operand`` are replaced with ``func(operand)``, with duplicate indices
  resulting in multiple applications of ``func``.

  The semantics of scatter are complicated, and its API might change in the
  future. For most use cases, you should prefer the
  :attr:`jax.numpy.ndarray.at` property on JAX arrays which uses
  the familiar NumPy indexing syntax.

  Note that in the current implementation, ``scatter_apply`` is not compatible
  with automatic differentiation.

  Args:
    operand: an array to which the scatter should be applied
    scatter_indices: an array that gives the indices in `operand` to which each
      update in `updates` should be applied.
    func: unary function that will be applied at each index.
    dimension_numbers: a `lax.ScatterDimensionNumbers` object that describes
      how dimensions of `operand`, `start_indices`, `updates` and the output
      relate.
    update_shape: the shape of the updates at the given indices.
    indices_are_sorted: whether `scatter_indices` is known to be sorted. If
      true, may improve performance on some backends.
    unique_indices: whether the elements to be updated in ``operand`` are
      guaranteed to not overlap with each other. If true, may improve performance on
      some backends. JAX does not check this promise: if the updated elements
      overlap when ``unique_indices`` is ``True`` the behavior is undefined.
    mode: how to handle indices that are out of bounds: when set to 'clip',
      indices are clamped so that the slice is within bounds, and when
      set to 'fill' or 'drop' out-of-bounds updates are dropped. The behavior
      for out-of-bounds indices when set to 'promise_in_bounds' is
      implementation-defined.

  Returns:
    An array containing the result of applying `func` to `operand` at the given indices.
  r   c                     |       S NrC   )x_funcs     r-   <lambda>zscatter_apply.<locals>.<lambda>8  s    Q r/   r   )r   fullry   r   
setdefault	TypeErrorr   r
   r   _zeror6   	scatter_pr*   rL   r[   )r,   r   r   ri   r   rc   rb   rd   unused_applyr   r   s     `         r-   scatter_applyr     s    ^ 88L!W]]3&&	!,,T6:F &&vt}}SYYw=O/PQ-%%)%?%?&("'?F	U.?+N%%d+	 
 
- - 
 		s   C
 
	CCc                    |S r   rC   )r   ys     r-   r   r   H  s    a r/   c                   t        j                  | ||      \  } }}t        j                  | ||dd|||t        j                  |      	      S )a_  Scatter-update operator.

  Wraps `XLA's Scatter operator
  <https://www.openxla.org/xla/operation_semantics#scatter>`_, where updates
  replace values from `operand`.

  If multiple updates are performed to the same index of operand, they may be
  applied in any order.

  :func:`scatter` is a low-level operator with complicated semantics, and most
  JAX users will never need to call it directly. Instead, you should prefer using
  :func:`jax.numpy.ndarray.at` for more familiary NumPy-style indexing syntax.

  Args:
    operand: an array to which the scatter should be applied
    scatter_indices: an array that gives the indices in `operand` to which each
      update in `updates` should be applied.
    updates: the updates that should be scattered onto `operand`.
    dimension_numbers: a `lax.ScatterDimensionNumbers` object that describes
      how dimensions of `operand`, `start_indices`, `updates` and the output
      relate.
    indices_are_sorted: whether `scatter_indices` is known to be sorted. If
      true, may improve performance on some backends.
    unique_indices: whether the elements to be updated in ``operand`` are
      guaranteed to not overlap with each other. If true, may improve performance on
      some backends. JAX does not check this promise: if the updated elements
      overlap when ``unique_indices`` is ``True`` the behavior is undefined.
    mode: how to handle indices that are out of bounds: when set to 'clip',
      indices are clamped so that the slice is within bounds, and when
      set to 'fill' or 'drop' out-of-bounds updates are dropped. The behavior
      for out-of-bounds indices when set to 'promise_in_bounds' is
      implementation-defined.

  Returns:
    An array containing the values of `operand` and the scattered updates.

  Examples:
    As mentioned above, you should basically never use :func:`scatter` directly,
    and instead perform scatter-style operations using NumPy-style indexing
    expressions via :attr:`jax.numpy.ndarray.at`.

    Here is and example of updating entries in an array using :attr:`jax.numpy.ndarray.at`,
    which lowers to an XLA Scatter operation:

    >>> x = jnp.ones(5)
    >>> indices = jnp.array([1, 2, 4])
    >>> values = jnp.array([2.0, 3.0, 4.0])

    >>> x.at[indices].set(values)
    Array([1., 2., 3., 1., 4.], dtype=float32)

    This syntax also supports several of the optional arguments to :func:`scatter`,
    for example:

    >>> x.at[indices].set(values, indices_are_sorted=True, mode='promise_in_bounds')
    Array([1., 2., 3., 1., 4.], dtype=float32)

    By comparison, here is the equivalent function call using :func:`scatter` directly,
    which is not something typical users should ever need to do:

    >>> lax.scatter(x, indices[:, None], values,
    ...             dimension_numbers=lax.ScatterDimensionNumbers(
    ...                 update_window_dims=(),
    ...                 inserted_window_dims=(0,),
    ...                 scatter_dims_to_operand_dims=(0,)),
    ...             indices_are_sorted=True,
    ...             mode=lax.GatherScatterMode.PROMISE_IN_BOUNDS)
    Array([1., 2., 3., 1., 4.], dtype=float32)
  NrC   r   )r
   r6   r   r*   rL   r[   )r,   r   r   ri   rc   rb   rd   s          r-   scatterr   J  s[    T '+&@&@')#'?G	d*;+N%%d+	 
 
- -r/   c           	     l   t        j                  |D cg c]  }t        j                  |d       c}d      }t        j                  t        j                  |D cg c]  }| j
                  |    c}      t        t        |j                  dz
                    }||z  }t        | j
                        }|D ]  }d||<   	 t        t        d| j                  |j
                  d   z
  dz               }t        |t        |      t        |            }	t        | ||	t        |            S c c}w c c}w )Nr   r   r@   rA   rB   ri   r3   )r   concatenateexpand_dimsrl   arrayshaper+   rangendimlistr?   rz   )
srcidxsaxesiindicesaxmax_idxr3   r@   dnumss
             r-   
index_taker     s   OOtD!S__Q5DaH'OOBHHd%Cciim%CD!%q(8"9:<'g'SYY+ bKOeAsxx'--*::Q>?@+
  ;Dk%
 
W!+.
0 0 E%Cs   D,D1c                   dg| j                   z  }t        | j                        }dg| j                   z  }| j                  |   }|t        j                  |      nd}	|t        j                  |      n|}
|	dk  r|	|z   }	|
dk  r|
|z   }
t        |      }|	||<   |
||<   t        j                  |      ||<   t        | |||      S )a  Convenience wrapper around :func:`lax.slice` applying to only one dimension.

  This is effectively equivalent to ``operand[..., start_index:limit_index:stride]``
  with the indexing applied on the specified axis.

  Args:
    operand: an array to slice.
    start_index: an optional start index (defaults to zero)
    limit_index: an optional end index (defaults to operand.shape[axis])
    stride: an optional stride (defaults to 1)
    axis: the axis along which to apply the slice (defaults to 0)

  Returns:
    An array containing the slice.

  Examples:
    Here is a one-dimensional example:

    >>> x = jnp.arange(4)
    >>> lax.slice_in_dim(x, 1, 3)
    Array([1, 2], dtype=int32)

    Here are some two-dimensional examples:

    >>> x = jnp.arange(12).reshape(4, 3)
    >>> x
    Array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11]], dtype=int32)

    >>> lax.slice_in_dim(x, 1, 3)
    Array([[3, 4, 5],
           [6, 7, 8]], dtype=int32)

    >>> lax.slice_in_dim(x, 1, 3, axis=1)
    Array([[ 1,  2],
           [ 4,  5],
           [ 7,  8],
           [10, 11]], dtype=int32)

  See Also:
    - :attr:`jax.numpy.ndarray.at`
    - :func:`jax.lax.slice`
    - :func:`jax.lax.index_in_dim`
    - :func:`jax.lax.dynamic_slice_in_dim`
  r   r   )r   r   r   r
   _canonicalize_dimensionintr.   )r,   start_indexlimit_indexstrideaxisr&   r'   r(   len_axisstart_index_intlimit_index_ints              r-   slice_in_dimr     s    d #$-w}}%-C',,' ]]4 (#/ 11+>56  $/ 11+>5=  q%0Oq%0O	T$'-'-..v6'$-	w}g	>>r/   c                (   t        j                  |      t        |      }}| j                  |   }|dk  r||z   n|}d|cxk  r|k  s n d}t	        |j                  |||            t        | ||dz   d|      }|r|S t        j                  ||f      S )a  Convenience wrapper around :func:`lax.slice` to perform int indexing.

  This is effectively equivalent to ``operand[..., index]``
  with the indexing applied on the specified axis.

  Args:
    operand: an array to index.
    index: integer index
    axis: the axis along which to apply the index (defaults to 0)
    keepdims: boolean specifying whether the output array should preserve the
      rank of the input (default=True)

  Returns:
    The subarray at the specified index.

  Examples:
    Here is a one-dimensional example:

    >>> x = jnp.arange(4)
    >>> lax.index_in_dim(x, 2)
    Array([2], dtype=int32)

    >>> lax.index_in_dim(x, 2, keepdims=False)
    Array(2, dtype=int32)

    Here are some two-dimensional examples:

    >>> x = jnp.arange(12).reshape(3, 4)
    >>> x
    Array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]], dtype=int32)

    >>> lax.index_in_dim(x, 1)
    Array([[4, 5, 6, 7]], dtype=int32)

    >>> lax.index_in_dim(x, 1, axis=1, keepdims=False)
    Array([1, 5, 9], dtype=int32)

  See Also:
    - :attr:`jax.numpy.ndarray.at`
    - :func:`jax.lax.slice`
    - :func:`jax.lax.slice_in_dim`
    - :func:`jax.lax.dynamic_index_in_dim`
  r   z2index {} is out of bounds for axis {} with size {}r   )	r
   r   r   r   
IndexErrorformatr   r   squeeze)r,   indexr   keepdims	axis_sizewrapped_indexmsgresults           r-   index_in_dimr     s    ^ ,,U3SY%mmD!)',qy%)#e-	
m	'i	'
>C
SZZtY7
880A1dK&M;;vw''r/   c                  t        j                  |d      g| j                  z  }t        | j                        }t        |      }dg| j                  z  }|||<   |||<   t        j                  |      ||<   t        | |||      S )a	  Convenience wrapper around :func:`lax.dynamic_slice` applied to one dimension.

  This is roughly equivalent to the following Python indexing syntax applied
  along the specified axis: ``operand[..., start_index:start_index + slice_size]``.

  Args:
    operand: an array to slice.
    start_index: the (possibly dynamic) start index
    slice_size: the static slice size
    axis: the axis along which to apply the slice (defaults to 0)
    allow_negative_indices: boolean specifying whether negative indices are
      allowed. If true, negative indices are taken relative to the end of the
      array. If false, negative indices are out of bounds and the result is
      implementation defined.

  Returns:
    An array containing the slice.

  Examples:
    Here is a one-dimensional example:

    >>> x = jnp.arange(5)
    >>> dynamic_slice_in_dim(x, 1, 3)
    Array([1, 2, 3], dtype=int32)

    Like `jax.lax.dynamic_slice`, out-of-bound slices will be clipped to the
    valid range:

    >>> dynamic_slice_in_dim(x, 4, 3)
    Array([2, 3, 4], dtype=int32)

    Here is a two-dimensional example:

    >>> x = jnp.arange(12).reshape(3, 4)
    >>> x
    Array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]], dtype=int32)

    >>> dynamic_slice_in_dim(x, 1, 2, axis=1)
    Array([[ 1,  2],
           [ 5,  6],
           [ 9, 10]], dtype=int32)

  See Also:
    - :attr:`jax.numpy.ndarray.at`
    - :func:`jax.lax.slice_in_dim`
    - :func:`jax.lax.dynamic_slice`
    - :func:`jax.lax.dynamic_index_in_dim`
  r   Fr0   )	r   r   r   r   r   r   r
   r   r9   )r,   r   
slice_sizer   r1   r&   r3   allow_negatives           r-   dynamic_slice_in_dimr   7  s    l %(JJ{A$>#?',,#N-W]]#+	T$7W\\)./.#-22:>+d	w{.<
> >r/   c               X    t        | |d||      }|r|S t        j                  ||f      S )a  Convenience wrapper around dynamic_slice to perform int indexing.

  This is roughly equivalent to the following Python indexing syntax applied
  along the specified axis: ``operand[..., index]``.

  Args:
    operand: an array to slice.
    index: the (possibly dynamic) start index
    axis: the axis along which to apply the slice (defaults to 0)
    keepdims: boolean specifying whether the output should have the same rank as
      the input (default = True)
    allow_negative_indices: boolean specifying whether negative indices are
      allowed. If true, negative indices are taken relative to the end of the
      array. If false, negative indices are out of bounds and the result is
      implementation defined.

  Returns:
    An array containing the slice.

  Examples:
    Here is a one-dimensional example:

    >>> x = jnp.arange(5)
    >>> dynamic_index_in_dim(x, 1)
    Array([1], dtype=int32)

    >>> dynamic_index_in_dim(x, 1, keepdims=False)
    Array(1, dtype=int32)

    Here is a two-dimensional example:

    >>> x = jnp.arange(12).reshape(3, 4)
    >>> x
    Array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]], dtype=int32)

    >>> dynamic_index_in_dim(x, 1, axis=1, keepdims=False)
    Array([1, 5, 9], dtype=int32)

  See Also:
    - :attr:`jax.numpy.ndarray.at`
    - :func:`jax.lax.index_in_dim`
    - :func:`jax.lax.dynamic_slice`
    - :func:`jax.lax.dynamic_slice_in_dim`
  r   r0   )r   r   r   )r,   r   r   r   r1   r   s         r-   dynamic_index_in_dimr   x  s6    f  47MO&M;;vw''r/   c                   t        |      }t        j                  |d      gt        j                  |       z  }|||<   dg| j                  z  }|||<   t        | |||      S )aj  Convenience wrapper around :func:`dynamic_update_slice` to update
  a slice in a single ``axis``.

  Args:
    operand: an array to slice.
    update: an array containing the new values to write onto `operand`.
    start_index: a single scalar index
    axis: the axis of the update.
    allow_negative_indices: boolean specifying whether negative indices are
      allowed. If true, negative indices are taken relative to the end of the
      array. If false, negative indices are out of bounds and the result is
      implementation defined.

  Returns:
    The updated array

  Examples:

    >>> x = jnp.zeros(6)
    >>> y = jnp.ones(3)
    >>> dynamic_update_slice_in_dim(x, y, 2, axis=0)
    Array([0., 0., 1., 1., 1., 0.], dtype=float32)

    If the update slice is too large to fit in the array, the start
    index will be adjusted to make it fit:

    >>> dynamic_update_slice_in_dim(x, y, 3, axis=0)
    Array([0., 0., 0., 1., 1., 1.], dtype=float32)
    >>> dynamic_update_slice_in_dim(x, y, 5, axis=0)
    Array([0., 0., 0., 1., 1., 1.], dtype=float32)

    Here is an example of a two-dimensional slice update:

    >>> x = jnp.zeros((4, 4))
    >>> y = jnp.ones((2, 4))
    >>> dynamic_update_slice_in_dim(x, y, 1, axis=0)
    Array([[0., 0., 0., 0.],
           [1., 1., 1., 1.],
           [1., 1., 1., 1.],
           [0., 0., 0., 0.]], dtype=float32)

    Note that the shape of the additional axes in ``update`` need not
    match the associated dimensions of the ``operand``:

    >>> y = jnp.ones((2, 3))
    >>> dynamic_update_slice_in_dim(x, y, 1, axis=0)
    Array([[0., 0., 0., 0.],
           [1., 1., 1., 0.],
           [1., 1., 1., 0.],
           [0., 0., 0., 0.]], dtype=float32)

  See Also:
    - :attr:`jax.numpy.ndarray.at`
    - :func:`jax.lax.dynamic_update_slice`
    - :func:`jax.lax.dynamic_update_index_in_dim`
    - :func:`jax.lax.dynamic_slice_in_dim`
  r   Fr0   )r   r   r   _ndimr   r=   )r,   r<   r   r   r1   r&   r   s          r-   dynamic_update_slice_in_dimr     sk    | 
T$$'JJ{A$>#?#))GBT#T-#-7W\\)./.	gv}5C
E Er/   c                  t        |      }t        j                  |      t        j                  |       k7  rGt        j                  |      dz   t        j                  |       k(  sJ t        j                  ||f      }t	        | ||||      S )ap  Convenience wrapper around :func:`dynamic_update_slice` to update a slice
  of size 1 in a single ``axis``.

  Args:
    operand: an array to slice.
    update: an array containing the new values to write onto `operand`.
    index: a single scalar index
    axis: the axis of the update.
    allow_negative_indices: boolean specifying whether negative indices are
      allowed. If true, negative indices are taken relative to the end of the
      array. If false, negative indices are out of bounds and the result is
      implementation defined.

  Returns:
    The updated array

  Examples:

    >>> x = jnp.zeros(6)
    >>> y = 1.0
    >>> dynamic_update_index_in_dim(x, y, 2, axis=0)
    Array([0., 0., 1., 0., 0., 0.], dtype=float32)

    >>> y = jnp.array([1.0])
    >>> dynamic_update_index_in_dim(x, y, 2, axis=0)
    Array([0., 0., 1., 0., 0., 0.], dtype=float32)

    If the specified index is out of bounds, the index will be clipped to the
    valid range:

    >>> dynamic_update_index_in_dim(x, y, 10, axis=0)
    Array([0., 0., 0., 0., 0., 1.], dtype=float32)

    Here is an example of a two-dimensional dynamic index update:

    >>> x = jnp.zeros((4, 4))
    >>> y = jnp.ones(4)
    >>> dynamic_update_index_in_dim(x, y, 1, axis=0)
    Array([[0., 0., 0., 0.],
          [1., 1., 1., 1.],
          [0., 0., 0., 0.],
          [0., 0., 0., 0.]], dtype=float32)

    Note that the shape of the additional axes in ``update`` need not
    match the associated dimensions of the ``operand``:

    >>> y = jnp.ones((1, 3))
    >>> dynamic_update_index_in_dim(x, y, 1, 0)
    Array([[0., 0., 0., 0.],
           [1., 1., 1., 0.],
           [0., 0., 0., 0.],
           [0., 0., 0., 0.]], dtype=float32)

  See Also:
    - :attr:`jax.numpy.ndarray.at`
    - :func:`jax.lax.dynamic_update_slice`
    - :func:`jax.lax.dynamic_update_index_in_dim`
    - :func:`jax.lax.dynamic_index_in_dim`
  r   r0   )r   r   r   r   r   )r,   r<   r   r   r1   s        r-   dynamic_update_index_in_dimr     sx    ~ 
T$YYv#))G,,99Vq CIIg$6666__VdW-F	$vud3
5 5r/   c                  t        j                  dd|       t        j                  dd|       | j                  t        |      k7  r'd}t	        |j                  || j                              t        |      t        |      k7  rd}t	        |j                  ||            t        t        t        j                  | j                  |            s'd}t	        |j                  || j                              t        d |D              sd}t	        |j                  |            t        t        t        j                  ||            sd	}t	        |j                  ||            t        t        t        j                  ||            }|$t        |      d
t        | j                        z  k(  r|S t        j                  dd|       t        |      | j                  k7  r'd}t	        |j                  || j                              t        d |D              sd}t	        |j                  |            t        d t        ||      D              S )Nr.   r&   r'   z{slice start_indices must have length equal to the number of dimensions of the operand, got indices {} for operand shape {}.zjslice limit_indices must have the same length as start_indices, got start_indices {} and limit_indices {}.zkslice limit_indices must be less than or equal to operand shape, got limit_indices {} for operand shape {}.c              3  &   K   | ]	  }|d k\    ywr   NrC   ).0sis     r-   	<genexpr>z$_slice_shape_rule.<locals>.<genexpr>Q  s     -R1W-   zSslice start_indices must be greater than or equal to zero, got start_indices of {}.znslice limit_indices must be greater than or equal to start_indices, got start_indices {} and limit_indices {}.r   r(   zuslice strides must have length equal to the number of dimensions of the operand, got strides {} for operand shape {}.c              3  &   K   | ]	  }|d k\    ywr   rC   r   rZ   s     r-   r   z$_slice_shape_rule.<locals>.<genexpr>b  s     %Q!V%r   z&slice strides must be positive, got {}c              3  R   K   | ]  \  }}t        j                  |d |       ! yw)r   )window_sizewindow_strideN)r
   
stride_dim)r   drZ   s      r-   r   z$_slice_shape_rule.<locals>.<genexpr>e  s,      /1a qaqAA /   %')r   _check_shapeliker   lenr   r   r   allmapoperatorger+   r   zip)r,   r&   r'   r(   r   diffs         r-   _slice_shape_ruler  B  s   w?w?\\S''MC
CJJ}gmm<
==3}--8C
CJJ}m<
==	Sgmm];	<8C
CJJ}gmm<
==	-}-	-&C
CJJ}-
..	Sm];	<8C
CJJ}m<
==	s8<<>	?$_g$W]]1C*CCKw	73\W\\!CC
CJJw6
77	%W%	%
2C
CJJw'
((	 /tW-/ 
/ /r/   c                ~     t        |t              rt        j                   fd|D              S  j                  |   S )Nc              3  <   K   | ]  }j                   |     y wr   r   )r   rZ   r   s     r-   r   z%_get_sub_spec_size.<locals>.<genexpr>j  s     5qTZZ]5   )rT   r+   mathprodr   )r   sub_specs   ` r-   _get_sub_spec_sizer  h  s1    % 995H555	H	r/   c                :   |j                   j                  }t        |j                  | |j                   j                        D ]L  \  }}}||k7  s||t        ||      z  dk7  s#t        j                  | d| dt        ||       d| d       |j                   S )zFReturns a sharding when out_shape may not be the same as operand shaper   z  on sharded dims where out dim (z!) is not divisible by mesh axes (z) with spec (z) is not implemented.)shardingr   r#   r   specr  r
   ShardingTypeError)	out_shaper,   namer   op_shout_shop_specs          r-   #_get_sharding_for_varying_out_shaper  m  s    					$ (mmY 0 0 5 5!7 eVWG/#D'22a7""F26( ;+D':; <i,. 	" 
		r/   c               :    t        | |||      }t        || d      S )Nr%   slicing)r  r  )r,   r&   r'   r(   r  s        r-   _slice_sharding_ruler    s'      }.;WN)	,Y	KKr/   c                  |j                   j                  }|)t        j                  t        j                  |d            r.t        |t        j                  ||      dt        |      z        }nt        j                  |t        j                  t        j                  | j                        dk(  dt        j                  dt        j                  t        j                  | j                  d      |                        }t        |t        j                  ||      t        j                  |d            }t        j                  | t        j                  | d      |      }|j                  |k(  sJ d|j                  d|       |gS )Nr   r   r   zresult.shape=z operand_shape=)avalr   rl   r   equalr  subtractr   r   wherer   multiplyr   padr   )	tr,   r&   r'   r(   operand_shapepadsreal_limitsr   s	            r-   _slice_transpose_ruler&    s(   ,,$$-_rxx34}bkk-Gc-((*D &&hhrxx A%qvvaR[[!%<gFGIJK }bkk-E{{7A&(D771cjjA&-&		&K=6<</9I=:J(KK	&
/r/   c                  t        |t        j                        sJ t        |       t        j
                  u ry t        |t        j                        r8t        t        |||      }|j                  j                  | t        |             y |)t        j                  t        j                  |d            rBt        |t        j                   |j"                  j$                  |      dt'        |      z        }nt        j(                  |t        j*                  t        j,                  | j$                        dk(  dt        j(                  dt        j.                  t        j                   | j$                  d      |                        }t        |t        j                   |j"                  j$                  |      t        j                   |d            }|j1                  t3        j4                  | t3        j6                  | d      |             y )Nr   r  r   )rT   r   	GradAccumtyper   ZeroRefAccumr   _sliceref	addupdater+   rl   r   r  r  r  r  r   r   r   r  r   r   accumr   r!  r   )out_ctr,   r&   r'   r(   slicesr$  r%  s           r-   _slice_transpose_fancyr2    s_   	GR\\	**	*	&\W\\!6%w?FKK&%-0"&&'1!56GLL,>,> NM**,d FF
&,,'1,a2;;r{{6<<'CWMN	PQk GLL,>,> LWa(*dMM#''&#**VQ"7>?r/   c                  | \  }|\  }t        |      }|j                  |d       t        |      }|j                  ||j                  |          |d }	nt        |      }	|	j                  |d       t        ||||	      }
|
|fS )Nr   r   )r   insertr   r.   )batched_args
batch_dimsr&   r'   r(   r,   bdimnew_start_indicesnew_limit_indicesnew_stridesouts              r-   _slice_batching_ruler<    s    ('
%$=)4#=)4t!45_Kw-KtQg(*;[I#	dr/   r.   )sharding_rulevma_rulec                    |t        j                  t        | |||      S t        t	        j
                  |      t	        j
                  |      z
        }t        j                  t        | g|d|iS )Nr%   r3   )r   apply_primitiver)   r+   rl   r   r7   )r   r&   r'   r(   r3   s        r-   _slice_implrA    sp    ##q!74 4 bhh}-0GGH+		!	!/1 
;} 
;.9
; ;r/   c                   |xs dgt        |      z  }| j                  \  }t        j                  | |||||      }t        j                  | ||      gS )Nr   r%   )r   	avals_outr   slice_oplower_with_sharding_in_types)ctxr   r&   r'   r(   aval_outr;  s          r-   _slice_lowerrH    sW    /sS//'mm)(c1hm$17	D#

+
+Ch
?	@@r/   c               ^   t        t        t        j                  | j                  |            s'd}t        |j                  || j                              t        d |D              sd}t        |j                  |            t        d |D              rt        d|       t        |      S )Nzgslice slice_sizes must be less than or equal to operand shape, got slice_sizes {} for operand shape {}.c              3  &   K   | ]	  }|d k\    ywr   rC   )r   sszs     r-   r   z,_dynamic_slice_shape_rule.<locals>.<genexpr>  s     -#SAX-r   zOslice slice_sizes must be greater than or equal to zero, got slice_sizes of {}.c              3  :   K   | ]  }|j                   d k7    ywr   r   r   idxs     r-   r   z,_dynamic_slice_shape_rule.<locals>.<genexpr>       03Q0   zGstart_indices arguments to dynamic_slice must be scalars,  got indices )	r   r   r   r  r   r   r   anyr+   )r,   r3   r&   r   s       r-   _dynamic_slice_shape_rulerS    s    	Sgmm[9	:6C
CJJ{GMM:
;;	--	-$C
CJJ{+
,,0-00
 $$1?4 5 5	{	r/   c               :    t        | g|d|i}t        || d      S )Nr3   r9   )rS  r  )r,   r3   starts_and_dyn_sizesr  s       r-   _dynamic_slice_sharding_rulerV    s.    '?$?2=?)	,Y	QQr/   c                   | j                  | j                  j                  |j                  j                  j                              S )Nreducedr  )r<   r  r  rY  )out_sr,   r3   rU  s       r-   _dynamic_slice_reduced_ruler\    s@    	5::,,##++ - - 
. .r/   c                   t        j                  || j                  g      \  }t        fdD              r2d}t	        |j                  dj                  d D                          | j                  S )Nc              3     K   | ]Q  }|j                   d    j                   k7  xs/ t        j                  |j                   t        j                          S ywr   ry   r   rk   rl   integerr   r   r&   s     r-   r   z,_dynamic_slice_dtype_rule.<locals>.<genexpr>  T      	L89 
M!$**	* 
4qww

3	3
4 	L   AAzKindex arguments to dynamic_slice must be integers of the same type, got: {}, c              3  H   K   | ]  }|j                   j                    y wr   ry   r  r   r   s     r-   r   z,_dynamic_slice_dtype_rule.<locals>.<genexpr>        (M!(M    ")r   
split_listr   rR  r   r   joinry   )r,   r3   rU  dynr   r&   s        @r-   _dynamic_slice_dtype_rulerm    sk    ';gll^L- 	L=J	L LC
CJJtyy(M}(MMN
OO	r/   c                   |d   }t        |      t        j                  urt        j                  |g| dd  d|i}t        j                  | d   g| dd  d|i|fS )Nr   r   r3   )r)  r   r*  r7   r*   )primalstangentsr3   tangent_outs       r-   _dynamic_slice_jvprr    sg    +	+gll*!&&{ZWQR[ZkZK			gaj	P712;	PK	PR]	]]r/   c               N   t        j                  |      sJ t        d |D              sJ t        |       t        j
                  u r0t	        j
                  |j                        gd gt        |      z  z   S t        j                  |j                  j                  d|j                  j                  |j                  j                        }t        j                  |t        |j                  j                               }t#        j$                  || g| gd gt        |      z  z   S )Nc              3  H   K   | ]  }t        j                  |         y wr   r   is_undefined_primalr   s     r-   r   z0_dynamic_slice_transpose_rule.<locals>.<genexpr>       Bq''**Bri  r   r  )r   rv  r   r)  r   r*  r  r   r   r   r   ry   r  r
   pvaryr+   vmar;   r*   )r"  r,   r3   r&   zeross        r-   _dynamic_slice_transpose_ruler|  	  s    				((	(	BMB	BB	B	!WLL&'4&3}3E*EEEHHW\\''GLL,>,>%ll335EJJueGLL$4$456E#((BMBCFS''( )r/   c          
        t        |t        j                        sJ t        d |D              sJ t	        |       t
        j                  u ry t        |t        j                        r5|j                  j                  | t        t        t        ||                   y t        j                  |j                  j                   d|j                  j"                  |j                  j$                        }t'        j(                  |t        |j                  j*                              }|j-                  t/        j0                  || g|        y )Nc              3  R   K   | ]  }t        |t        j                          ! y wr   )rT   r   r(  r   s     r-   r   z1_dynamic_slice_transpose_fancy.<locals>.<genexpr>  s     DAr||,,Dr   r   rx  )rT   r   r(  r   r)  r   r*  r+  r-  r.  r+   r   r!   r   r   r  r   ry   r  r
   ry  rz  r/  r;   r*   )r0  r,   r3   r&   r{  s        r-   _dynamic_slice_transpose_fancyr    s    	GR\\	**	*	DmD	DD	D	&\W\\!6%KK&%B{(K"LMHHW\\''GLL,>,>%ll335EJJueGLL$4$456EMM(--eVLmLMr/   c                R   t        |       dk(  rt        j                  g d      d fS t               }t	        d t        | |      D        |      }t	        d t        | |      D        d       }||u r:t        j                  | D cg c]  }t        j                  |d       c}d      d fS |d nt        |d   t        |d   d             }t        j                  t        | |      D cg c]$  \  }}t        j                  ||df|dnd|	      & c}}d
      } | dfS c c}w c c}}w )Nr   int32c              3  F   K   | ]  \  }}|	|j                   |     y wr   r  r   r   r   s      r-   r   z/_batch_dynamic_slice_indices.<locals>.<genexpr>%  s      KdaQ]qwwqzKs   
!!c              3     K   | ]^  \  }}|Wt        j                  |      j                  j                  t        j                  |      j                  j                  |   f ` y wr   )r
   typeofr  r   r  r  s      r-   r   z/_batch_dynamic_slice_indices.<locals>.<genexpr>'  sT      @!Q {{1~&&++T[[^-D-D-I-I!-LM @s   A$A&r   r   r  rC   )broadcast_dimensionsout_sharding)	dimension)r   rl   r   objectnextr  r   r   	broadcastr   Pbroadcast_in_dim)r   bdimsempty_markersizer;  r   r[  r   s           r-   _batch_dynamic_slice_indicesr  !  s-   \Q88B $&&,	Kc'5&9K
$ @gu-@AE	G#	\??GDqCMM!T2DaH$NN+$=Q3q64#I%OO We$& 
A 		D!9AMDr & 23	4'
 
! E&s   D')D#
c          
     t   | ^}}|^}}|j                   |t        j                  u rdndz
  }t        t	        |            }t        j                  ||g      \  }	}
t        j                  ||g      \  }}t        |d|      }t        |	|      \  }}t        ||g|
||g|||ddt        j                  d       S )Nr   r   rC   r   Trh   )r   r   
not_mappedr+   r   r   rj  r?   r  _gather_batching_rulerL   rW   )r5  r6  r3   r,   start_indices_and_dyn
operand_bdstart_idx_and_dyn_bdsndimsdimsr&   dyn_slice_sizesstart_idx_bdsdyn_slice_size_bdsr   r   
index_bdims                   r-   _dynamic_slice_batching_ruler  3  s     %1!'!'1$*$
,,zX-@-@@!a
H%	uU|	$#'??3H5'#R -&*oo6KeW&U#-#
 %
 3=-P%	e&o&101UDT		,	,	
? ?r/   c               P    | j                  t        |g|t        |      |      S )N)r3   )source_info)default_process_primitiver7   dict)tracer  r   r3   r&   s        r-   _dynamic_slice_staging_ruler  L  s1    		(	(*M*D[,I 
) 
 r/   c               f    t        j                  |j                  gd |D        d|i\  }}|g|fS )Nc              3  4   K   | ]  }|j                     y wr   )r  r   r   s     r-   r   z0_dynamic_slice_typecheck_rule.<locals>.<genexpr>T  s     .1.s   r3   )r7   abstract_evalr  )r   r   r3   r&   out_avaleffectss         r-   _dynamic_slice_typecheck_ruler  R  sC    %33ffI..I<GI(G
W	r/   r9   )weak_type_ruler=  r>  reduced_rulec                   | j                   ^}}| j                  \  }t        j                  | |||      }t        j                  | ||      gS N)r&   )avals_inrC  r   r9   rE  )rF  r   r3   r&   x_avalr   rG  r;  s           r-   _dynamic_slice_lowerr  d  sH    ||*&1mm)(3!=I#

+
+Ch
?	@@r/   c                >   | j                   |j                   k7  r1d}t        |j                  |j                  | j                              | j                   t	        |      k7  r'd}t        |j                  || j                              t        t        t        j                  | j                  |j                              s1d}t        |j                  |j                  | j                              t        d |D              rt        d|       | j                  S )Nzidynamic_update_slice update must have the same rank as operand, got update shape {} for operand shape {}.zvdynamic_update_slice start_indices must have length equal to the rank of operand, got indices {} for operand shape {}.zodynamic_update_slice update shape must be smaller than operand shape, got update shape {} for operand shape {}.c              3  :   K   | ]  }|j                   d k7    ywr   rM  rN  s     r-   r   z3_dynamic_update_slice_shape_rule.<locals>.<genexpr>z  rP  rQ  zMstart_indices arguments to dynamic_update_slice must be scalars, got indices )
r   r   r   r   r   r   r   r   r  rR  r,   r<   r&   r   s       r-    _dynamic_update_slice_shape_ruler  m  s    \\V[[ 7C
CJJv||W]];
<<\\S''CC
CJJ}gmm<
==	SgmmV\\:	;>C
CJJv||W]];
<<0-00
 ,,9?< = =	r/   c                    | j                   |j                   k7  r<t        j                  d| j                  d       d|j                  d       d      | j                   S )Nz]dynamic_update_slice operand sharding must be equal to update sharding, got operand sharding Tmesh_axis_types and update sharding .)r  r
   r  	str_short)r,   r<   r&   s      r-   #_dynamic_update_slice_sharding_ruler    sn    (

 
 	d34 5T231	67 7
 
		r/   c                   |j                   j                  j                  |j                   j                  j                  k7  r<t        j                  d|j                  d       d|j                  d       d      | j                  | j                  j                  |j                   j                  j                              S )Nzddynamic_update_slice operand and update must be unreduced along the same axes. Got operand sharding Tr  r  r  )	unreducedrZ  )r  r  r  r
   r  r  r<   r[  r,   r<   r&   s       r-   $_dynamic_update_slice_unreduced_ruler    s    $$(<(<(F(FF

 
 	d34 5T231	67 7
 
5::,,  %%// - 1 
2 2r/   c                   |j                   j                  j                  |j                   j                  j                  k7  r<t        j                  d|j                  d       d|j                  d       d      | j                  | j                  j                  |j                   j                  j                              S )Nzbdynamic_update_slice operand and update must be reduced along the same axes. Got operand sharding Tr  r  r  rX  rZ  )r  r  rY  r
   r  r  r<   r  s       r-   "_dynamic_update_slice_reduced_ruler    s    ""foo&:&:&B&BB

 
 	d34 5T231	67 7
 
5::,,##++ - - 
. .r/   c                    t        j                  d| |       t        fdD              r2d}t        |j	                  dj                  d D                          | j                  S )Nr=   c              3     K   | ]Q  }|j                   d    j                   k7  xs/ t        j                  |j                   t        j                          S ywr   r_  ra  s     r-   r   z3_dynamic_update_slice_dtype_rule.<locals>.<genexpr>  rb  rc  zQindex arguments to dynamic_update_slice must be integers of the same type, got {}rd  c              3  H   K   | ]  }|j                   j                    y wr   rf  rg  s     r-   r   z3_dynamic_update_slice_dtype_rule.<locals>.<genexpr>  rh  ri  )r   check_same_dtypesrR  r   r   rk  ry   r  s     ` r-    _dynamic_update_slice_dtype_ruler    sb    .@ 	L=J	L LC
CJJtyy(M}(MMN
OO	r/   c                   | d d \  }}| dd  }|d d \  }}t        j                  ||g| }t        |      t        j                  u r>t        |      t        j                  u r#t        j                  j                  |      }||fS t        j                  |      }t        j                  |      }t        j                  ||g| }||fS )N   )r;   r*   r)  r   r*  from_primal_valuer   instantiate_zeros)	ro  rp  r,   r<   r&   	g_operandg_updateval_outrq  s	            r-   _dynamic_update_slice_jvpr    s    BQK/'6!"+- !)X"''H-H'	)_$h7<<)G,,009K
 
+	 $$Y/I##H-H(--iRMRK	+	r/   c                   t        d |D              sJ t        j                  |      r|j                  j                  n|j                  }|j                  j
                  }t        |       t        j                  u rmt        j                  |      rt        j                  |j                        nd }t        j                  |      rt        j                  |j                        nd }nvt        j                  | ||      }t        j                  |      rt        j                  | |g| nd }t        j                  |      rt        j                  | g|d|ind }||gd gt        |      z  z   S )Nc              3  H   K   | ]  }t        j                  |         y wr   ru  r   r   s     r-   r   z7_dynamic_update_slice_transpose_rule.<locals>.<genexpr>  rw  ri  )r   r  r3   )r   r   rv  r  r   r  r)  r   r*  r   _zerosr;   r*   r7   r   )	r"  r,   r<   r&   r   update_sharding	operand_tupdate_tr{  s	            r-   $_dynamic_update_slice_transpose_ruler    s,   	BMB	BB	B')'='=f'E&++##,, KK((/	!W.0.D.DW.MW\\*SWI,.,B,B6,Jw||FKK(PTHJJqGE**73 (,,QFF9=  ))&1  $$QQQLQ7; 
X	$#m*<!<	<<r/   c           
        | ^}}}|^}}}|t         j                  u rt        j                  |      n1t	        t        j
                  t        j                  |      |            }t	        t        t        |                  }	t        |	d|	      }
t        ||      \  }} t        j                  t        t        |
ddt        j                        |||fd      |||      dfS )NrC   )r~   r   r   Tri   rc   rb   rd   r   )in_axesout_axes)r   r  rl   r   r+   deleter   r   r|   r  r	   vmapr   r   rL   rU   )r5  r6  r,   r<   	start_idxr  	update_bdstart_idx_bdr   r  r   r   r  s                r-   #_dynamic_update_slice_batching_ruler    s    
 !-'6I)3&*i,&/83F3F&F"((6"RYYrxx'7CD 	uS&'	($
!#'%
 39lK%
Gu#D"'') Y/

 
(
 *+
+ +r/   r=   )r=  r>  unreduced_ruler  c                    | j                   \  }t        j                  | ||||      }t        j                  | ||      gS r  )rC  r   r=   rE  )rF  r   r<   r&   rG  r;  s         r-   _dynamic_update_slice_lowerr    s@    mm)(!!#xF0=	?#

+
+Ch
?	@@r/   c                   t        j                  |j                  t        j                        st        d      | j                  S )N!indices must have an integer type)r   rk   ry   rl   r`  rY   )r,   r   re   kwargss       r-   _gather_dtype_ruler    s0    			7=="**	5
8
99	r/   c                ,    t        | j                        S r   )r   r   )arrs    r-   r   r     s    C		N r/   c                z    t        dt        |             D ]#  }| |   | |dz
     k  st        | d| d|         y )Nr    in z op must be sorted; got )r   r   r   )r  op_namer  r   s       r-   
_is_sortedr    sO    CI LaAwa!ed7)+CD6JKKLr/   c                V    | D ]$  }|dk  s||k\  st        d| d| d| d| d	       y )Nr   Invalid  set in  op; valid range is [0, ); got: r  )r   )r  rankr  r  dims        r-   _dims_in_ranger    sN     3c
Qw#+hwi 8!F(3%q2 3 33r/   c                    t        |       dk(  ry d }| d   dk  r| d   }n| d   |k\  r| d   }|rt        d| d| d| d| d	      y )Nr   r  r  r  r  r  )r   r   )r  r  r  r  invalid_dims        r-   _sorted_dims_in_ranger    sv    Y!^
+	!Wq[q'KBx4r(K
htfHWI 6&Q8 9 9 r/   c                l    t        t        |             t        |       k7  rt        | d| d|  d      y )Nr  z op must not repeat; got: r  )r   setr   )r  r  r  s      r-   _no_duplicate_dimsr    s:    T^s4y 
tfD	)CD6K
LL !r/   c                ~    t        |       j                  t        |            st        | d| d| d|  d| d
      y )N and r  z op must be disjoint; got: r  )r  
isdisjointr   )dims1dims2r  name1name2s        r-   _disjoint_dimsr    sQ    	U		s5z	*
ugU5'gY 7!7%wa1 2 2 
+r/   c               ~    |j                   }|j                  }	|j                  }
|j                  }|j                  }t              dz
  }t              |k  s|dk  rt        dt               d| d      t        |dd       t        |dd       t        |      }t        |      t              z   dz
  }t        |      D ]&  }||   }|dk  s||k\  st        d| d	| d
| d       t        |      j                  |   k7  r+t        dt        |       d|dj                  |    d      t        t        |            D ]8  }||   }|dk  s|t               k\  st        dt                d| d| d       t        |dd       t        |	dd       t        |	t               dd       t        |	dd       t        |
dd       t        |
dd       t        |
t               dd       t        |	|
ddd       t        ||
ddd       t        |dd       t        |t              dd       ||v rt        d| d      t        |
      t        |      k7  rt        d|
 d| d      t         fd|
D              }t        fd|D              }t!        j"                  ||      st        d| d| d      t               t        |      k7  r#t        dt        |       dt                      t        |      t        |      t        |	      z   t        |
      z   k7  r!t        d t        |       d!| d"|	 d#|
 d	      t        t        |            D ]U  }||   } j                  |   }t!        j$                  j                        r7|dk\  r||k\  rBt        d$| d%| d&| d       t        t        |	            D ]'  }||	|      }|dk7  st        d'| d(|	|    d)| d       t        t        |
            D ]'  }||
|      }|dkD  st        d*| d(|
|    d)| d       t'        ||      S )+aF  Validates the well-formedness of the arguments to Gather.

  The code implements the checks based on the detailed operation semantics of
  XLA's `Gather <https://www.openxla.org/xla/operation_semantics#gather>`_
  operator and following the outline of the implementation of
  ShapeInference::InferGatherShape in TensorFlow.
  r   r   zTGather index leaf dimension must be within [0, rank(indices) + 1). rank(indices) is z$ and gather index leaf dimension is r  rz   r@   zOffset dimension z$ in gather op is out of bounds; got z, but should have been in [0, )zGather op has zI elements in start_index_map and the bound of dimension index_vector_dim= of indices is z". These two numbers must be equal.z'Invalid start_index_map; domain is [0, ), got: ->rB   rA   rD   rE   zNGather op cannot have the index vector dimension as a batching dimension; got z_Gather op requires equal numbers of operand_batching_dims and start_indices_batching_dims, got z andc              3  <   K   | ]  }j                   |     y wr   r  r   r   r,   s     r-   r   z%_gather_shape_rule.<locals>.<genexpr>~       N1gmmA.Nr  c              3  <   K   | ]  }j                   |     y wr   r  r   r   r   s     r-   r   z%_gather_shape_rule.<locals>.<genexpr>        gmmAr  zkGather op requires operand batching dimensions and indices batching dimensions to have the same shape, got r   zTGather op must have one slice size for every input dimension; got: len(slice_sizes)=z, input_shape.rank=zAll components of the offset index in a gather op must either be a offset dimension or explicitly collapsed/batching; got len(slice_sizes)=z, output_slice_sizes=z, collapsed_slice_dims=z, operand_batching_dims=zSlice size at index z2 in gather op is out of range, must be within [0, z + 1), got zBGather op can only collapse slice dims with bound 1, but bound is z for index z at position zKGather op can only have operand batching dims with bound 0/1, but bound is )r@   rA   rD   rE   rB   _rankr   r  r  r   r   r   r  r  r  r+   r
   definitely_equal_shapeis_empty_shape_gather_shape_computation)r,   r   ri   r3   rb   rc   rd   re   r@   rA   rD   rE   rB   index_vector_dimoutput_offset_dim_countoutput_shape_rankr   
offset_dimoperand_dim_for_start_index_ioperand_batch_shapeindices_batch_shaper   corresponding_input_sizebounds   ``                      r-   _gather_shape_ruler    s    "--+*??+AA 1 M M%55/ 7^a' 7^&&*:Q*>
 77<W~6F G66F5GqJ K K [(M2[(M:,+&w7!;() 3aQJA~'88)! -'L )./q2 3 33 	W]]+;<<
nS%9$: ;)')}}%567 8-. / / _%& @a$3A$6!%)%w7 "7^,H2;<A? @ @	@ _h0AB !8-CD,eGnh.0)85KL*H6MN"H.EFU7^X7N %'<h')@B"7"$;= !8-J !Gn#	 44
	56a	9 
 		3'B#CC
	,,A+B$&
'q	*  N8MNN  ;  
	$	$%8:M	N
	22E1Fe
q	"  7^s;''
 88;K8H7I J((-g'79 : : 	[)C0D,EEI   	  #K 01 2)]*A
  8 
!	$  [!" 	,aQJ&}}Q/w}}-a4
B,QC 0,,D+E F'L+ , ,	, )*+ Ea,Q/0Ez &&+WK-a01qcD E EE *+, a-a01Eqy 116{.q12-s!E   
#7,={	KKr/   c                  	
 |j                   	|j                  |j                  
t        	      t	        |       z   dz
  }t	        |       dz
  }t        | j                        }t        |      |k(  r|j                  d       |j                  |       t        |      
fdt        |      D        t        	fdt        |      D              }|S )Nr   c              3  8   K   | ]  \  }}|vr|vr|  y wr   rC   r   r   rZ   rA   rD   s      r-   r   z,_gather_shape_computation.<locals>.<genexpr>  s.      
!Q	
&	&14I+I s   c              3  R   K   | ]  }|v rt              n
t                 y wr   )r  )r   r   indices_shape_genr@   slice_sizes_gens     r-   r   z,_gather_shape_computation.<locals>.<genexpr>  s5      N/0 ()K'7d?#)*+ N   $')r@   rA   rD   r   r  r   r   appendpopiter	enumerater+   r   )r   ri   r3   r  r  expanded_indices_shapeansrA   r$  r@   rD   r%  s          @@@@@r-   r  r    s    !--+*??+AA+&w7!;7^a'. 		 $44!!!$-.12K(/
 	 N49:K4LN 	N#	*r/   c                    |j                   }|j                  |j                  |j                  |j                  t        |      |j                  z   dz
  }|j                  dz
  } j                  j                  t        |j                  j                        t        d D              rt        d D              r
t               S t        fdD              sJ t         fdD              }t        fdt              D              }t        fdt              D              }	|r|r|	rt              D ]+  \  }
}|   |
   k(  s|   |
   J |   xs |
   |<   - fd	t              D        }t              }g }t        |      D ]\  }||v r<t!        |      \  }
}| j"                  |
   k(  s|
   J |j%                  |
          C|j%                  t!        |             ^ t        | S y)
a  Returns gather output sharding spec if unambiguous, else None.

  Operand dimensions can be split into:
    1. Batching dims which must resolve unambiguously with the corresponding
      indices batching dims. `operand_batching_dims` in GatherDimensionNumbers.
    2. Sliced dims which must be replicated. These are the subset of dims in
      `start_index_map` where the slice size is not equal to the operand size.
      A further subset of these (`collapsed_slice_dims`) are collapsed in the
      output.
    3. Unsliced dims, these correspond directly to dimensions in the
      output and so propagate their shardings. These are the dimensions not
      batched or sliced.

  Indices dimensions can be split into:
    1. Batching dims which must resolve unambiguously with the corresponding
      operand batching dims. `start_indices_batching_dims` in
      GatherDimensionNumbers.
    2. Index vector dim which contains the start indices for each dimension of
      the operand sliced in to. This must be replicated. It is the last
      dimension of indices.
    3. Other dims which correspond directly to dimensions in the output and
      so propagate their shardings. These are the dimensions not present in
      index batching dims and index vector dim.

  If the axes of the corresponding batching dims between operand and indices are
  both not None and do not match, then sharding propagation cannot be resolved
  unambiguously and so we return None.
  r   c              3  $   K   | ]  }|d u  
 y wr   rC   r   s     r-   r   z+_gather_spec_computation.<locals>.<genexpr>       	*!t)	*   c              3  $   K   | ]  }|d u  
 y wr   rC   r   s     r-   r   z+_gather_spec_computation.<locals>.<genexpr>  r/  r0  c              3  &   K   | ]  }|v  
 y wr   rC   )r   r   rB   s     r-   r   z+_gather_spec_computation.<locals>.<genexpr>   s     @aQ/!@s   c              3  Z   K   | ]"  }|   j                   |   k(  xs |   d u  $ y wr   r  )r   r   r,   operand_specr3   s     r-   r   z+_gather_spec_computation.<locals>.<genexpr>  s<      4 
 !na((CLOt,CC4 s   (+c              3  ^   K   | ]$  \  }}|   |   k(  xs |   d u xs |   d u  & y wr   rC   )r   operand_dimindices_dimindices_specr4  s      r-   r   z+_gather_spec_computation.<locals>.<genexpr>  sW      , %; ;<#<< +	k	"d	*+	k	"d	*+,s   *-c              3  4   K   | ]  \  }}|vr|d u   y wr   rC   )r   r   rZ   rE   s      r-   r   z+_gather_spec_computation.<locals>.<genexpr>  s*      *Aq	
-	- 4i*   Nc              3  <   K   | ]  \  }}|vr
|vr||f  y wr   rC   r"  s      r-   r   z+_gather_spec_computation.<locals>.<genexpr>"  s4      M1a((Q6K-K 
AMr  )r@   rB   rA   rD   rE   r   r   r  r  r   r   r  r  r*  r)  r   r  r   r'  )r,   r   ri   r3   r@   r  r  +operand_index_dims_full_slice_or_replicated#batching_dims_resolve_unambiguously!indices_non_batch_dims_replicatedr6  r7  r%  indices_spec_genout_specr   r   rA   r8  rD   r4  rB   rE   s   `  `             @@@@@@r-   _gather_spec_computationrA    sQ   : "--+%55/*??+AA 1 M M+&59\\A%!!&&,g&&++,,		*\	**		*\	**3J	@+?@	@@	@ 14 4 4  1 - ), , ),
!<)>	, )% '* *%l3* '#
 2
-
+$':%< Y [;'<+DDk*2k*24 3 #/{";"X|K?Xl;YM$[1MO L)H$% 0	
k	 #'"7Z gmmK88,4	6 5[12 	-./0 h<	r/   c                     | D ch c]  }|j                   r| }}t        |      dkD  rt        j                  d|      |st	        j
                         S |\  }|S c c}w )z'Resolves the mesh between given meshes.r   z0Conflicting meshes received. Got: unique_meshes=)emptyr   r
   r  mesh_libget_abstract_mesh)meshesr   unique_meshess      r-   _resolve_meshrH  :  sk    $*=D$**4=-=!

 
 
;],<=  
%%''
%$	+ >s
   AAc                   t        | j                  j                  |j                  j                        }t        | |||      }	|	t	        j
                  d| d|      t        ||	      S )NzUse `.at[...].get(out_sharding=)` to provide output PartitionSpec for the gather indexing as out sharding could not be resolved unambiguously (or would require collectives on inputs). Got operand=
, indices=)rH  r  r   rA  r
   r  r   )
r,   r   ri   r3   rb   rc   rd   re   out_meshr@  s
             r-   _gather_sharding_rulerL  G  s{     7++00'2B2B2G2GH(%gw8I&13(

 
 	 :[z	#$ $
 
x	**r/   c               f   |}t        j                  | j                  d      }	t        t        j
                  |	      }
t        j                  | j                        j                  |	      }t        j                  ||	      }t        |j                        dz
  }| |
|j                           t        j                  |       |
|j                           j                  |	      z
  }t        j                  t        j                  ||	j                  d            t        j                  |t        j                   |t#        t%        |                              }t        j&                  ||g      }|t        |j(                        z   }t	        j*                  t	        j,                  |      |j(                        }t/        | ||||t0        j2                        }t        j4                  t        j6                  ||||j8                  j:                        |t        j<                  ||            S )	zHLowers a FILL_OR_DROP gather as a PROMISE_IN_BOUNDS gather with masking.Tsignedry   r   r   )rc   rd   )r  )re   )	lax_utilsint_dtype_for_shaper   r   rl   r   r   shape_as_valueastypeconvert_element_typer   rB   bitwise_andr  r)  ler   r+   r   
reduce_andr@   r  arangerz   rL   rW   selectr  r  r  	full_like)r,   r   ri   r3   rb   rc   re   output_shaper   index_dtypeintarrayoperand_dimsnum_batch_dimsupper_boundmaskoutput_ndimsbatch_dims_in_output
gather_outs                     r-   _gather_fillrf  U  s    %--gmmDI+RXX[1(##GMM299+F,$$Wk:'w}}%).u$$%	%hu/D/D&EFMM+
 
	ffWk&&q)*	ffWcook5~9N3OPQ
S$ 
~.	/$  #e&7&7"88,299\#:#(#4#46
 gw{);,>>@* 
|-A&0oo&>&>@jZ@
B Br/   c          
     (    t        | ||||||d      S )Nr   ra   )rz   )	gr,   r   ri   r3   rb   rc   rd   re   s	            r-   _gather_jvp_ruleri  {  s%     
7-{-#5D
 r/   c          	     ~   t        j                  |      sJ t        |       t        j                  u r#t        j                  |j
                        }	|	d gS t        j                  |j
                  j                  dt        j                  |       j                  |j
                  j                        }
t        j                  |
t        |j
                  j                              }
t!        |j"                  |j$                  |j&                  |j(                  |j*                        }t-        |
|| ||||      }	|	d gS )Nr   rx  r~   r   r   rD   r   )rb   rc   rd   )r   rv  r)  r   r*  r  r   r   r   r
   r  ry   r  ry  r+   rz  r|   r@   rA   rB   rD   rE   r   )r"  r,   r   ri   r3   rb   rc   rd   re   r;  r{  scatter_dnumss               r-   _gather_transpose_rulerm    s     
			((	(	!W
,,w||
$C  t HHW\\''DKKN,@,@%ll335EJJueGLL$4$456E+,88.CC%6%F%F/EE&7&S&SM eWa%3);!C tr/   c          
        | \  }}	|\  }
}|
|t        j                  ||
d      }d}
|j                  d   f|z   }dt        t	        j
                  d|j                              z   }t        t	        j
                  d|j                              }t        t	        j
                  d|j                              }t        t	        j
                  d|j                              }t        |||||j                        }|
}t        ||	||||||      |fS |
|t        j                  |	|d      }	t        d |j                  D              }t        t	        j
                  d|j                              }t        ||j                  |j                  |j                  |      }t        ||	||dd||      dfS t        j                  ||
d      }t        j                  |	|d      }	t        j                  |j                  d   d      rd|z   }nd|z   }t        t	        j
                  d|j                              }dt        t	        j
                  d|j                              z   }dt        t	        j
                  d|j                              z   }t        t	        j
                  d|j                              }t        t	        j
                  d|j                              }t        |||||      }t        ||	||||||      dfS )	Nr   r  r   r@   rA   rB   rD   rE   rh   c              3  &   K   | ]	  }d |z     yw)r   NrC   r  s     r-   r   z(_gather_batching_rule.<locals>.<genexpr>  s     E!AEr   Fr   )r   moveaxisr   r+   rl   r   r@   rA   rD   rB   r?   rE   rz   r
   definitely_equal)r5  r6  ri   r3   rb   rc   rd   re   r,   r   operand_bdimindices_bdimr@   rA   rD   rB   r   bdim_outrE   s                      r-   r  r    s    "'7),,"6q9GL==#%3Krvva):)F)FGHHK +<+Q+Q!RS!
q#99: BFF1&7&G&GHIO"1'3$5$Q$QE HE%-D
 !)) )  8q9GE'8'D'DEEK"'
q#??@# #.CC)99/EE$?E '7e)%%**NOPQ Q q9Gq9GW]]1-q1;&k;&k 
q#889 !5
q#99:$  #'
q#??@* # q"3"?"?@AKBFF1&7&G&GHIO"1'3$?E '7e).%7d') +,, ,r/   rz   )r  r=  r>  c          
         | j                   \  }	}
| j                  \  }t        j                  |	j                        j
                  }t        t        |            D cg c]  }|j                  |z    }}|j                  g |j                  |      }g ||}t        t        ||||||      }t        j                  | |||t        j                  |	      |
gt        j                  |      g      \  }|S c c}w )N)r@   rh   r  rC  )r  rC  r
   physical_element_avalry   r   r   r   r   _replacer@   r   _gather_lowerr   delegate_loweringphysical_aval)rF  r,   r   ri   r3   rb   rc   rd   re   aval_xaval_indicesaval_y	elt_shaper   trailing_offset_dimsgather_lowerress                    r-   _gather_lower_opaquer    s    &,MM'&((6<<)38Y3HIa&++/II'00I%11I4HI 1 K*+*	*+'8n+$:O, 
			<'""6*L9##F+,
.$# 
* Js   C;c               b   | j                   \  }	}
| j                  \  }t        j                  |j                  t        j
                        rt        | ||||||||	      gS |t        j                  k(  r6t        j                  t        d      } || ||||||||j                  	      S |t        j                  t        j                  fv sJ |       t        j                   j#                  t%        |j&                        t%        |j(                        t%        |j*                        t-        |
j                        dz
  t%        |j.                        t%        |j0                              }t3        j4                  |      st        j6                  | |      }t        j8                  |      g}|||g}|t:        j<                  j#                  |      d}t        j>                  jA                  |||      jB                  S t3        jD                  |j                        r/t        jF                  | d	|      }t        jH                  | ||      gS t        jJ                  |||t        jL                  |      t:        j<                  j#                  |      
      }t        jH                  | ||      gS )Nrh   Fmultiple_results)ri   r3   rb   rc   re   r\  r   )rA   rD   rE   r  r@   rB   )ri   rc   )resultsoperands
attributesr   )rc   )'r  rC  r   rk   ry   extendedr  rL   rV   r   	lower_funrf  r   rW   rU   r   r?   getr   rA   rD   rE   r   r@   rB   r
   is_constant_shapeeval_dynamic_shape_as_tensoraval_to_ir_typer   BoolAttrDynamicGatherOpbuild_genericr  r  full_like_avalrE  rz   dense_int_array)rF  r,   r   ri   r3   rb   rc   rd   re   r   indices_avalrG  gather_fill_fnr   r  r  r  r;  s                     r-   rz  rz  
	  sk    LL/!\mm)(x~~v7 Wg1B-D	     
+++^^L5INWg+%:LHNN	< < 
#55#((* 
* 0+/0 
*

$
$
(
( 1 F FG !2!H!HI"&

7
7# <--.2(445,<<= ) 	% 
			,33CEK ##H-.G+.H" kkoo.@AJ ,,(z - CCJ7K8>>*


c1h
/C--c3ABB
**Wgud.B.B;.O(*8J(KMC--c3ABBr/   c                    t        j                  |j                  t        j                        st        d      t        j                  d| |       | j                  S )Nr  r   )r   rk   ry   rl   r`  rY   r   r  )r,   r   r   r  s       r-   _scatter_dtype_ruler  C	  sB    			7=="**	5
8
99	7G4	r/   c                    t        t        |            |D ]  }j                  |d         t              t        |      k(  sJ t	        fd| D              S )Nc              3  @   K   | ]  }j                  |        y wr   )r   )r   r   scatter_dim_in_updatess     r-   r   z-_get_updates_batching_dims.<locals>.<genexpr>O	  s     N1%++A.Ns   )r   r   r4  r   r+   )indices_batching_dimsr~   r  updates_shaper   r  s        @r-   _get_updates_batching_dimsr  I	  s^    &6 78 +a!!!T*+	#	$M(:	::	:	N8MN	NNr/   c          
     	    |j                   }	|j                  }
|j                  }|j                  }|j                  }t              dz
  }t              |k  s|dk  rt        dt               d| d      t        j                        }t        |      |k(  r|j                  d       t        |      dz
  t        |	      z   }t              |k7  rt        d| dt               d      t        |	dd	       t        |	dd	       t        |	t              dd	       t        |
dd
       t        |
dd
       t        |
t               dd
       t        |dd       t        |dd       t        |t               dd       t        |
|dd
d       t        ||ddd       t        |dd       t        |t              dd       ||v rt        d| d      t        |      t        |      k7  rt        d| d| d      t!         fd|D              }t!        fd|D              }t#        j$                  ||      st        d| d| d      t'        ||	|j                        }t!        fd|D              }t#        j$                  ||      st        d| d| d      t        |	      t        |
      z   t        |      z   }t               |k7  rt        d| dt                d      t        |      j                  |   k7  r+t        dt        |       d|dj                  |    d      t)        t        |            D ]8  }||   }|dk  s|t               k\  st        dt                d| d| d       t        |dd       t)        t         j                              D cg c]+  }|t+        |
      vr|t+        |      vr j                  |   - }}t)        t        |	            D ]A  }|	|   }||   j                  |   k  st        d| d j                  |    d!||    d       t)        t                    D cg c]  }|t+        |	      vs| }}d}|D ]\  }||k(  r|dz  }t#        j,                  j                  |   ||         s%t        d"| d j                  |    d#||    d      |dz  }^  j                  S c c}w c c}w )$aa  Validates the well-formedness of the ``dimension_numbers`` argument to
  Scatter.

  The code implements the checks based on the detailed operation semantics of
  XLA's `Scatter <https://www.openxla.org/xla/operation_semantics#scatter>`_
  operator and following the outline of the implementation of
  ShapeInference::InferScatterShape in TensorFlow.
  r   r   zUScatter index leaf dimension must be within [0, rank(indices) + 1). rank(indices) is z% and scatter index leaf dimension is r  zUpdates tensor must be of rank z; got r   r~   r   rD   r   r   zOScatter op cannot have the index vector dimension as a batching dimension; got zbScatter op requires equal numbers of operand_batching_dims and scatter_indices_batching_dims, got r   c              3  <   K   | ]  }j                   |     y wr   r  r  s     r-   r   z&_scatter_shape_rule.<locals>.<genexpr>	  r  r  c              3  <   K   | ]  }j                   |     y wr   r  r  s     r-   r   z&_scatter_shape_rule.<locals>.<genexpr>	  r  r  zlScatter op requires operand batching dimensions and indices batching dimensions to have the same shape, got c              3  <   K   | ]  }j                   |     y wr   r  )r   r   r   s     r-   r   z&_scatter_shape_rule.<locals>.<genexpr>	  r  r  zlScatter op requires operand batching dimensions and updates batching dimensions to have the same shape, got zScatter op has window of size z ; doesn't match operand of rank zScatter op has zV elements in scatter_dims_to_operand_dims and the bound of dimension index_vector_dim=r	  z!. These two numbers must be equalz<Invalid scatter_dims_to_operand_dims mapping; domain is [0, r
  r  zBounds of the window dimensions of updates must not exceed the bounds of the corresponding dimensions of operand. For dimension z, updates bound is z, operand bound is zBounds of the scatter dimensions of updates must be the same as the bounds of the corresponding dimensions of scatter indices. For scatter dimension z, indices bound is )r~   r   rD   r   r   r  r   r   r   r   r'  r  r  r  r  r  r+   r
   r  r  r   r  rr  )r,   r   r   r   r   ri   rc   rb   rd   r~   r   rD   r   r   r  r+  expected_updates_rankr  r  updates_batching_dimsupdates_batch_shaper   r   r  max_update_slice_sizesupdate_window_dimupdate_scatter_dimsscatter_dims_seens   ```                         r-   _scatter_shape_ruler  Q	  sd    );;*??+AA"3"Q"Q!2!O!O 7^a' 7^&&*:Q*>
 <<A'N;K L;;K:LAO P P  . 		 $44!!!$56:123 7^,,
56K5L M >*!- . . ,@A'4HI*E'NI,. !9.DE)96LM,eGni.0 "I/FG*I7NOU7^Y8O %'<i')@B-/Di/1HJ #Y0O #Gn%	 66
	78	;< < 		3'D#EE
	..C-DE(
)	,  N8MNN  =  
	$	$%8:M	N
	22E1Fe
q	" 
 5#%79Imm N8MNN		$	$%8:M	N
	22E1Fe
q	"  

	
 	
 ! 
 7^{"
4[M B--27^,<A? @ @ 

&'mm$%&
oc*F&G%H I6$4#6 7"")--0@"A!B C,- . . 123 Ea
&q
)C
Qw#w'   %g/xs"SED E EE 1935
 S'(

3+,
,s011	 mmA  '() @a*1-a 7==1B#CC 00A/B C"")--0A"B!C D""8";!<A	? @ @@ ).eGn(= 2/0B1 2 2  	a,,1  q!13IJ[3\] CCD# F"")--"2!33F/0ABC1	F G G
 	 
C$2s   60SS#)S#c                 t    t        |       dk\  sJ d       t        | D ch c]  }||	 c}      dk  S c c}w )z:Checks if given sharding axis names resolve unambiguously.r  z!At least two axis names expected.r   )r   )
axis_namesas     r-   _is_resolvabler  	  s<    	ZA	BBB		5Aq}a5	6!	;;5s   55c                F    |j                   }|j                  |j                  |j                  |j                  dz
  } j
                  j                  |j
                  j                  j
                  j                  t        d D              r.t        d D              rt        d D              r
t               S t        |j                        t         j                        D cg c]  }|vr||vr| }}t        fdt        |      D              }t         fdt        |      D              }	t        fdt              D              }
t        fdt              D              }t        fd	t        d
|       D              }|   d
u }|rj|	rh|
rf|rd|rb|r`t              }t        |      D ]  \  }}}||   |   xs |   ||<    t        |      D ]  \  }}||   |   ||<    t        | S y
c c}w )a  For a scatter, we consider the gather rules in inverse.

  We consider a gather, then convert to scatter as the inverse.
  A gather is a group of queries, each query slices a window out of `operand`.

  The `operand` dims sliced in to are those in `start_index_map`. Some of size 1
  dims in `start_index_map` are squeezed out of the gather output, termed
  `collapsed_slice_dims`. Hence `collapsed_slice_dims` is a subset of
  `start_index_map`. Confusingly, some of the slice sizes into `operand` can be
  full slices, hence it can be inferred that the corresponding start index of
  the window in that dim is 0 and hence the `operand` is not sliced in to.

  All dims of `indices`, except the final dim (`index_vector_dim`) are different
  queries in to `operand`. These queries may be batched with `operand`, and so
  are effectively N (query, operand) pairs so the queries are non-overlapping,
  each into different matching sized slices of `operand` (N being the batch
  dimension size), or unbatched where N queries are into the same `operand`. The
  actual indices of the start of the (fixed size) windows are contained in the
  final dimension of `indices`, the `index_vector_dim`.

  Some dims of `operand` are not sliced in to, these are `offset_dims`
  [offset_dims is defined from the gather output perspective (the `updates` in
  scatter) and by construction are the frontmost dims in `operand` after
  disregarding `collapsed_slice_dims` and `operand_batching_dims`].

  For a gather:
   - Batch dimensions must be resolvable unambiguously between `operand` and
   `indices`
   - Dims the `operand` is sliced in to are either full slices, or the `operand`
    is replicated in that dim (all the data for each query is present)
   - The `index_vector_dim` containing the actual start indices of the windows
   in to `operand` must be replicated

  A scatter is a group of queries, each of which has a corresponding window of
  `updates` to put in to `operand`.

  For a scatter:
   1 - Batch dimensions must resolve unambiguously between `operand`, `indices`
   and `updates`
   2 - Full slice dims must resolve unambiguously between `operand` and
   `updates`
   3 - Sub slice dims in `operand` and `updates` must be replicated.
   4 - `Indices` and `updates` must be replicated in dims where both are
   updating, possibly overlapping, subslices of operand. These are referred to
   as unbatched queries in the above description of gather.
   5 - The `index_vector_dim` containing the actual start indices of the windows
   in to `operand` must be replicated

  Not all dimensions updating slices in `operand` exist in `updates`. The
  `inserted_window_dims` provide size 1 updates into `operand` and are inserted
  into `updates`. We handle `operand` slices present in `updates`, then handle
  the inserted dims separately.

  Correspondance:
                Gather <-> Scatter
           offset_dims <-> update_window_dims
  collapsed_slice_dims <-> inserted_window_dims
       start_index_map <-> scatter_dims_to_operand_dims
  r   c              3  $   K   | ]  }|d u  
 y wr   rC   r   s     r-   r   z,_scatter_spec_computation.<locals>.<genexpr>G
  r/  r0  c              3  $   K   | ]  }|d u  
 y wr   rC   r   s     r-   r   z,_scatter_spec_computation.<locals>.<genexpr>H
  r/  r0  c              3  $   K   | ]  }|d u  
 y wr   rC   r   s     r-   r   z,_scatter_spec_computation.<locals>.<genexpr>I
  r/  r0  c              3  R   K   | ]  \  }}}t        |   |   |            y wr   )r  )r   odidudr8  r4  updates_specs       r-   r   z,_scatter_spec_computation.<locals>.<genexpr>V
  s9      P
"b" \"%|B'7b9IJPr&  c              3     K   | ]E  \  }}j                   |   j                   |   k(  xr |   |   k(  xs |   d u xr |   d u  G y wr   r  )r   
update_dimr6  r,   r4  r   r  s      r-   r   z,_scatter_spec_computation.<locals>.<genexpr>]
  su      24 "*k }}Z GMM+$>> =J<#<<R
z
"d
*
P|K/HD/PR24s   AAc              3  4   K   | ]  \  }}|v r|d u   y wr   rC   )r   r   r  r   s      r-   r   z,_scatter_spec_computation.<locals>.<genexpr>c
  s*      3$q$	
"	" dl3$r:  c              3  <   K   | ]  \  }}|vr
|vr|d u   y wr   rC   )r   r   r  r~   r  s      r-   r   z,_scatter_spec_computation.<locals>.<genexpr>j
  s4      3Iq$	
'	'A5G,G dl3Ir  c              3  4   K   | ]  \  }}|vr|d u   y wr   rC   )r   r   r  r  s      r-   r   z,_scatter_spec_computation.<locals>.<genexpr>m
  s*      3)q$	
'	' dl3)r:  N)rD   r   r~   r   r   r  r  r   r  r  r   r   r  r*  r   )r,   r   r   ri   rD   r  r   operand_window_dimsbatch_dims_resolvable)update_and_operand_window_dims_resolvable*inserted_window_dims_replicated_in_operand*unbatched_query_dims_in_updates_replicated*unbatched_query_dims_in_indices_replicatedindex_vector_dim_is_replicatedr@  r6  r7  updates_dimr  r  r8  r   r4  r~   r  r  s   ` `                @@@@@@@r-   _scatter_spec_computationr   
  s   z ,AA+II(;;*??\\A%!!&&,!!&&,!!&&,		*\	**		*\	**		*\	**3J4/1A7==R
 w||$K	
&	&14I+I K K  P
!68MOP P /2 24 &)
1&3	24 /4+ 03 3$"+L"93$ 0$, 03 3I"+L"93I 0I, 03 3)"+L9J:J,K"L3) 0), $00@#AT#I /000$L!H 2546K2M D-[+	+		&%Bk)B 	D $''9;N#O 9
K	+		& ,Z 89 h<	sKs   :Hc                   | j                   S r   )memory_space)	r,   r   r   r   r   ri   rc   rb   rd   s	            r-   _scatter_memory_space_ruler  
  s     
		r/   c                   t        d | ||fD         }	t        | |||      }
|
t        j                  d| d|d|      t	        |	|
      S )Nc              3  H   K   | ]  }|j                   j                    y wr   )r  r   r  s     r-   r   z)_scatter_sharding_rule.<locals>.<genexpr>
  s     =A

=ri  zUse `.at[...].set/add/mul/...(out_sharding=)` to provide output PartitionSpec for the scatter update as out sharding could not be resolved unambiguously (or would require collectives on inputs). Got operand=rJ  z
, updates=)rH  r  r
   r  r   )r,   r   r   r   r   ri   rc   rb   rd   rK  r@  s              r-   _scatter_sharding_ruler  
  su     ='7G!<=?(&w'8:(

 
 	 :[zG:	/0 0
 
x	**r/   c                   g d}t        t         j                              D ]`  }||j                  v s||j                  v rj                  d       1j                  |j                  |j                  |             |dz  }b t         fd|j                  D              }t        j                  |      }t        j                  ||j                  j                  t        t        j                  |j                        j                   t        j                  |j                        j                                     }t        j"                  ||j                        }t        j$                  ||j                  t        |j                        dz
  f      }t        j&                  |j                  j                  d      ||      S )z.Clamps `indices` to be in-range for a scatter.r   r   c              3  H   K   | ]  }j                   |   |   z
    y wr   r  )r   r   r,   r3   s     r-   r   z)_clamp_scatter_indices.<locals>.<genexpr>
  s-      #P'( $+==#3k!n#D #Ps   ")r   r   r   r   rD   r'  r~   r+   r   r   rS  rq   ry   r)  rl   rp   rs   rU  r  clamp)	r,   r   r   r   posr   upper_boundsra  r3   s	   `       @r-   _clamp_scatter_indicesr  
  sp   +	#W]]#$ aE&&&!u/J/J*Ju'?'?'DEF	Qhc # #P,1,N,N#P P, ""<0+
bhh{(()--rxx/F/J/J
K+ ((gmmD+$$['--&)'--&81&<%>@+	7==%%a(';	??r/   c                  |\  }	}
}|\  }}}~| j                  |	|
|||||||	      }t        |      t        j                  u r>t        |      t        j                  u r#t        j                  j	                  |      }||fS t        j                  |      }t        j                  |      }| j                  ||
|||||||	      }||fS )Nr   )r*   r)  r   r*  r  r   r  )primro  rp  r   r   ri   rc   rb   rd   r,   r   r   r  	g_indices	g_updatesr  rq  s                    r-   _scatter_addsub_jvpr  
  s     &'7G$,!)Y	IIwl!5F+N	  '
 
)_$iGLL)H,,009K 
+	 $$Y/I$$Y/I))7IL#7H-n	  K
 
+	r/   c                  t        j                  |      rJ t        j                  |      r|j                  j                  }n|j                  }t	        |      t
        j                  u rnt        j                  |      rt        j                  |j                        nd }t        j                  |      rt        j                  |j                        nd }nd x}}t        j                  |      r|}t        j                  |      rt        |j                  |j                  |j                  |j                  |j                        }g }d}t        t        |j                              D ]V  }||j                  v s||j                  v r|j                  d       1|j                  ||j                  |             |dz  }X t!        |||||
d      }| t"        u rt%        j&                  |      }|d |gS )Nro  r   r   ri   r3   rd   re   )r   rv  r  r   r)  r   r*  r?   r~   r   r   rD   r   r   r   r'  rz   r   r   neg)r  r"  r,   r   r   r   r   ri   rc   rb   rd   r  r  r  gather_dnumsr3   r  r   s                     r-   _scatter_addsub_transpose_ruler  
  s    ##G,,	,G$LL&&MMMM	!W.0.D.DW.MW\\*SWI-/-C-CG-Lw||GLL)RVHI	g&i	g&+'::0EE+HH 1 G G&7&U&Ul kcS\" !"777%;;;


Q



]+<+O+OPS+TU
V
(# 7l$/dqJh		778$
T8	$$r/   c          	        t        j                  |      rJ t        j                  |      r|j                  j                  }
n|j                  }
t	        |       t
        j                  u rnt        j                  |      rt        j                  |j                        nd }t        j                  |      rt        j                  |j                        nd }n/d x}}t        j                  |      rt        | ||||||	      }t        j                  |      r|st        d      t        |j                  |j                  |j                  |j                  |j                        }g }d}t        t!        | j                              D ]V  }||j                  v s||j                  v r|j#                  d       1|j#                  |
|j                  |             |dz  }X t%        t'        j(                  | |      ||||	d      }|d |gS )Nr  Cscatter_mul gradients are only implemented if `unique_indices=True`ro  r   r   r  )r   rv  r  r   r)  r   r*  r   NotImplementedErrorr?   r~   r   r   rD   r   r   r   r'  rz   r   r   )r"  r,   r   r   r   r   ri   rc   rb   rd   r  r  r  r  r3   r  r   s                    r-   _scatter_mul_transpose_ruler  
  s    ##G,,	,G$LL&&MMMM	!W.0.D.DW.MW\\*SWI-/-C-CG-Lw||GLL)RVHI	g&
Wg1B/i 
g&!
OQ 	Q+'::0EE+HH 1 G G&7&U&Ul kcS\" !"777%;;;


Q



]+<+O+OPS+TU
V
(# 7+W*6K!a1h T8	$$r/   c                  |\  }
}}|\  }}}t        d t        ||      D              }t        j                  |
|||j                        }
t        j                  ||||j                        }|t        t        j                  d|j                              }dt        t        j                  d|j                              z   }t        t        j                  d|j                              }t        t        j                  d|j                              }t        |||||j                        }| j                  |
||||||	||	      dfS t        j                  ||||j                        }t        t        j                  d|j                              }t        t        j                  d|j                              }dt        t        j                  d|j                              z   }dt        t        j                  d|j                              z   }t        t        j                  d|j                              }t        |||||      }| j                  |
||||||	||	      dfS )Nc              3  D   K   | ]  \  }}||j                   |     y wr   r  )r   r   r   s      r-   r   z)_scatter_batching_rule.<locals>.<genexpr>4  s(      !ea ggbk !s    r   r  rk  )ri   rc   rb   rd   r   r   r   )r  r  r   bdim_at_frontexplicit_mesh_axisr+   rl   r   r   r~   rD   r   r|   r   r*   )
scatter_op	axis_datar5  r6  r   r   ri   rc   rb   rd   r,   r   r   rs  rt  updates_bdimr  r   r~   rD   r   r   r   s                          r-   _scatter_batching_ruler  ,  s    +'7G-7*,l 
 !s<'D ! 
!$""7L$#,#?#?A'""7L$#,#?#?A'  +<+Q+Q!RSbffQ0A0T0T&U VV!
q#99: $)3D3a3a)b#c #-1%A3&7&U&UE ??w5+Nl-  I KLL L ""7L$#,#?#?A' RVVA'8'K'KLMrvva):)O)OPQffQ!778": :"&ffQ!??@*B #B!&ffQ!>>?"A
!+/#?1$AC% 
w5+Nl- 
 
I KL
L Lr/   zscatter-addr   )r  r=  r>  memory_space_rulec                     yNrC   rC   r   s    r-   r   r   m      r/   zscatter-subr   c                     yr  rC   r  s    r-   r   r   y  r  r/   zscatter-mulr   c                   |st        d      t        j                  |t        t	        j
                  |      || ||||            S )Nr  r  )r  r   r   r   r   zeros_like_jaxval)	rh  r   r   r   ri   rc   rb   rd   kws	            r-   _scatter_mul_jvp_rhsr    sN    	
KM M	K"Aq<M+N 
 r/   c                2    t        j                  | ||fi |S r   )r   r*   )rh  r   r   r   r  s        r-   r   r     s    =#5#5aA#D#D r/   c                     yr  rC   r  s    r-   r   r     r  r/   c	                   |\  }	}
}|\  }}}|}|j                   }| j                  |	|
|||||||	      }t        |      t        j                  u r>t        |      t        j                  u r#t        j                  j                  |      }||fS t        j                  |      }t        j                  |      }t        |j                  |j                  |j                  |j                  |j                        }g }d}t        t        |	j                               D ]V  }||j                  v s||j                  v r|j!                  d       1|j!                  ||j                  |             |dz  }X t#        |	|
|t%        j&                  |            }t#        ||
|t%        j&                  |            }||k(  }||k(  }t#        t)        t+        j,                  |	      |
t+        j.                  |t+        j0                  |      t+        j,                  |            |      |
|t%        j&                  |            }t#        t)        t+        j,                  |	      |
t+        j0                  |      |      |
|t%        j&                  |            }t+        j.                  |d|dz   z  d|z        }t+        j.                  ||t+        j,                  |            }t+        j.                  |d|dz   z  t+        j,                  |            }d|z   |z  } t#        ||
|t%        j&                  |            }!|!| z  ||z  z   }"t)        ||
|"||||      }||fS )Nr   ro  r   r   g      ?g      r   )r   r*   r)  r   r*  r  r   r  r?   r~   r   r   rD   r   r   r   r'  rz   rl   r   r   r   r  rZ  _ones)#r  ro  rp  r   r   ri   rc   rb   rd   r,   r   r   r  r  r  rl  r  r  rq  r  r3   r  r   initial_valstarget_valssuccessful_updatesretained_valuesnum_updatesnum_refsupdates_normalizerupdates_coefoperand_normalizeroperand_coeftarget_tangentstangent_updatess#                                      r-   _scatter_extremal_jvpr    sL    &'7G$,!)Y	#----OOwl!]+#$	  0' 
)_$iGLL)H,,009Kr 
+	o $$Y/I$$Y/I *!44*??%BB+AA$1$O$OL K
C3w}}%& 
}11
1-5551=)I)I#)NOPq ,(=?L ,(=?K "[0#{2OJJwJJ)399W+=zz'*,		
 	
K CJJw'IIg&!	# 	
H O$';?$;$'+$57 ::00!jj13L O$';?$;$'JJ{$;= --9L 7L"((;*?AO '5 </0O i%-+1C-;#')K 
+	r/   zscatter-minr   c                     yr  rC   r  s    r-   r   r     r  r/   zscatter-maxr   c                     yr  rC   r  s    r-   r   r     r  r/   c                  |t        d      | \  }}	}
|\  }}}|}t        |      t        j                  u rZt        |      t        j                  u r?t        j                  ||	|
||||||	      }|t        j                  j                  |      fS t        j                  |      }t        j                  |      }|r@t        j                  ||	|
||||d|	      }t        j                  ||	|||||d|	      }||fS t        |
j                        }|j                  D ]  }d||<   	 t        j                  |      }t        j                  |d      }t!        j"                  t!        j$                  t!        j&                  ||      |      t!        j(                  |
|            }t+        t!        j,                  |j                  d|      |	|||||	      }t/        |j                  |j0                  |j2                  |j4                  |j6                  
      }g }d}t9        t;        |j                              D ]`  }||j0                  v s||j4                  v r|j=                  d       1|j=                  |
j                  |j                  |             |dz  }b t?        ||	||      }t!        j@                  t!        jB                  |t!        jD                  |            |t!        jD                  |            }t!        j@                  t!        jB                  ||      |
t!        jD                  |
            }t!        j@                  t!        jB                  |t!        jD                  |            |t!        jD                  |            }t!        j@                  t!        jB                  ||      |t!        jD                  |            }tG        ||	|||||      }tG        ||	|||||      }||fS )Nz!scatter_apply JVP not implementedr   Tr   FrN  rP  r   r   ro  r   r  )$r  r)  r   r*  r   r*   r  r   r  r   r   r~   r	  r
  rQ  int_dtype_for_dimr   r   reshapeiotar  r   r   r?   r   r   rD   r   r   r   r'  rz   rZ  eqr  r   ) ro  rp  r   r   ri   rc   rb   rd   r,   r   r   r  r  r  r   r  rq  	ids_shaper  num_idsid_dtype
update_idsscattered_idsr  r3   r  r   gathered_update_idsmasked_operandmasked_updatesmasked_g_operandmasked_g_updatess                                    r-   _scatter_jvpr    s    
A
BB%'7G$,!)Y	
%	)_$iGLL)Hnnwl!U+N	  G
 GLL227;;;""9-)""9-) nnwl!U+Dt  MG ..),!U+Dt ! MK K 7==!),, jIjIIi '((?(wws{{388Hg#>	Jyy9;* #((7==!X>!:u-?)7dD- (** 5588!77"'"E"E, +	#](()* aE&&&!u/J/J*Ju'?'?'DEF	Qhc }g1=+68
 ::cff]CJJ}4MN%szz'':<.::cffZ2EF%szz'':<.ZZ}cjj6O P )3::i+@BZZz3F G )3::i+@B */+='5DB' ,g7G.3/A+9F+ 
+	r/   c          
        |st        d      t        j                  |      rJ t        j                  |      r-|j                  j                  }
|j                  j
                  }n+|j                  }
t        j                  |      j
                  }t        |       t        j                  u rnt        j                  |      rt        j                  |j                        nd }t        j                  |      rt        j                  |j                        nd }n/d x}}t        j                  |      r3t        | |t        j                  |
d| j                  |      ||d|	      }t        j                  |      rt        |j                   |j"                  |j$                  |j&                  |j(                        }g }d}t+        t-        | j                              D ]V  }||j"                  v s||j&                  v r|j/                  d       1|j/                  |
|j                   |             |dz  }X t1        | ||||	d      }|d |gS )	Nz?scatter transpose is only implemented where unique_indices=Truer   )ry   r  Tr  ro  r   r  )r  r   rv  r  r   r  r
   r  r)  r   r*  r   r   r   ry   r?   r~   r   r   rD   r   r   r   r'  rz   )r"  r,   r   r   r   r   ri   rc   rb   rd   r  updates_shardingr  r  r  r3   r  r   s                     r-   _scatter_transpose_ruler  w  s    

 4 5 5##G,,	,G$LL&&M||,,MMM{{7+44	!W.0.D.DW.MW\\*SWI-/-C-CG-Lw||GLL)RVHI	g&
W
((=!177=M
N-/4	Qi 
g&+'::0EE+HH 1 G G&7&U&Ul kcS\" !"777%;;;


Q



]+<+O+OPS+TU
V
(# 7l$/d#$&h T8	$$r/   r   c                     yr  rC   r  s    r-   r   r     r  r/   c                  | j                   \  }
}}| j                  \  }t        j                  |
j                        j
                  }t        t        |            D cg c]  }|j                  |z    }}|j                  g |j                  |      }t        t        ||||||	      }t        j                  | ||||t        j                  |
      |t        j                  |      gt        j                  |      g      \  }|S c c}w )N)r~   r   r   ri   rb   rc   rd   rw  )r  rC  r
   rx  ry   r   r   r   r   ry  r~   r   _scatter_lowerr   r{  r|  )rF  r,   r   r   r   r   ri   rb   rc   rd   r}  r~  aval_updatesr  r  r   trailing_window_dimsscatter_lowerr  s                      r-   _scatter_lower_opaquer     s    (+||$&,MM'&((6<<)9>s9~9NOA,++a/OO'001,?? 1/1 1 2 <}).+$8- 
			='7G""6*L""<02##F+,	
.$#
 
* Ps   D
c               4   |N|rJ | j                   d   j                  }
t        j                  t        t        j                  d|
            \  }}| j                  \  }t        j                  |j                  t        j                        rt        | |||||||||	
      gS |	t        j                  k(  r:t        j                  t         d      } || j#                  d       ||||      \  }|}t$        j&                  j)                  t+        |j,                        t+        |j.                        t+        |j0                        t+        |j2                        t+        |j4                        t7        | j                   d   j8                        dz
  	      }t        j:                  |      }|g}|g}t%        j<                  |f||||t>        j@                  j)                  |      t>        j@                  j)                  |      
      }t        j:                  t        j                  d|j                              }|jB                  jD                  jG                  ||      }t?        jH                  |      5  tK        jL                         }|jN                  rtQ        d      t        jR                  | jT                  ||t        jV                         ||jX                  d   |jX                  d   | jZ                  | j\                  	      \  }}t%        j^                  t        j`                  |             d d d        tc        |jd                  | j                        D cg c]  \  }}t        jf                  | ||       c}}S # 1 sw Y   QxY wc c}}w )Nr   rC   r  Fr  rC  r   r   r~   r   input_batching_dimsr   scattered_dims_to_operand_dimsr  rc   rb   z!Cannot lower effectful `scatter`.)dim_var_valuesconst_lowering)4r  ry   r   r   _scatter_reduction_computationr
   ShapedArrayrC  r   rk   r  r   rL   rU   r   r  r  replacer   r|   r  r   r~   r   rD   r   r   r   r   r  	ScatterOpr   r  update_computationblocksr'  InsertionPointr   new_name_stackr  r  jaxpr_subcompmodule_contextTokenSet	argumentsr(  r)  return_flatten_ir_valuesr#   r  rE  )rF  r,   r   r   r   r   ri   rc   rb   rd   operand_dtyperG  clip_fnr   rl  r   opscalar_typer<   
name_stack	out_nodesr   rr  s                           r-   r  r    s    LLO))M"%"6"6&(8(8](K#ML- mm)(x~~v7!Wgw!+N-D	: ; ; 
###nn3eLGt4gw!):<JW %--11e667 : :;u::;$()L)L$M%)%*L*L%M3<<?001A5 2 - )&I'I'
}}fY'=(*8J(K$&KKOON$CE" $$T%5%5b(..%IJ+  ''..{KH&	  3!002J CDD%%L*dmmov''*F,<,<Q,?))#:L:LNLIq KK&&y123 ""**cmm<
>a 
+
+CD
9 
> >3 3
>s   9B?N#!NNc                @    t        j                  |       j                  S r   )rl   finfory   rP  s    r-   _real_dtyperA    s    rxx444r/   c               4   
  j                   \  }}}|j                  t        j                  k7  rt	         ||||||	
      S |	t
        j                  k(  r:t        j                  t        d      } | j                  d       |||      \   j                  \  |}t        j                  j                  t        |j                         t        |j"                        t        |j$                        t        |j&                        t        |j(                        t+         j                   d   j,                        dz
        t/        j                        t        j0                  t3        j4                  j,                               
f	d} |t        j6                  |      t        j6                  |            } |t        j8                  |      t        j8                  |            }t        j:                  ||      gS )	Nr   Fr  r"  r#  r   r$  c                R  	 | g} |g}t        j                  	f| |t        j                  j	                        t        j                  j	                              }t        j                  t        j                  d
            }|j                  d   j                  j                  ||      }t        j                  |      5  t        j                   |j                   j                  g       d d d        t        j                   |j                        S # 1 sw Y   *xY w)Nr'  rC   r   )r   r-  r   r  r  r   r  r
   r+  regionsr/  r'  r0  r6  r5  r   rE  )operand_partupdates_partr   r;  reducerrG  rF  r   rc   operand_type_part
real_dtype	reduce_oprl  rb   s        r-   _scatterz+_scatter_addsub_lower_gpu.<locals>._scatter*  s     >L >Lmm	lG\=;;??+=>{{~68G &&t'7'7J'GHKooa ''..{KHG			7	# :	kk9g//07789:,,S'..(KK: :s   .DD&)r  ry   rl   
complex128r  rL   rU   r   r  r  r,  rC  r   r|   r  r   r~   r   rD   r   r   r   r   rA  r  r
   r+  realimagcomplex)rF  r,   r   r   r   r   ri   rc   rb   rd   rJ  operand_aval_inr   updates_aval_inr9  r   rK  rM  rN  rG  rH  rI  rl  s   ` `    `` `        @@@@r-   _scatter_addsub_lower_gpurR  
  s    ),%/1obmm+#w'3(5,=-?)7dD D 
###nn3eLGs{{T{2GWg.0HG mm)(
%--11e667 : :;u::;$()L)L$M%)%*L*L%M3<<?001A5 2 - 8>>****
x~~z24L L 
#((7#SXXg%6	7$	#((7#SXXg%6	7$
++dD
!	""r/   )rJ  gpu)platformc           
        t        |      | j                  k7  r0d}t        |j                  t        |      | j                              t        |t        t        f      s>|j                  dk7  r$t        dj                  |j                              t        |      }g }t        |t              r|gt        |      z  }t        || j                  |      D ]  \  }}}t        j                  t        |      t        j                        r|j                  |       Gt        |t         t        j"                  f      rt%        j&                  |      r|r9|j                  t)        j*                  |dk  r||z   n|t        |                   nE|dk  rt        d| d| d      |j                  t)        j*                  |t        |                   t%        j,                  |      }t        |t         t        j"                  f      re|r9|j                  |dk  r"|t)        j*                  |t        |            z   n|       n(|dk  rt        d| d| d      |j                  |       |rMt)        j*                  |t        |            }|j                  t)        j.                  |dk  ||z   |             |j                  |        |S )NzJLength of slice indices must match number of operand dimensions ({} vs {})r   z+Slice indices must be a 1D sequence, got {}r   zIndex z  is out of bounds for dimension z  if allow_negative_indices=False)r   r   rY   r   r   rT   r+   r   rw   r  r   rk   rj   rl   rr   r'  r   r`  r
   is_constant_dimr   rU  dimension_as_valuerZ  )	r,   r&   r1   r   r   r   r   allow_negative_indexd_arrs	            r-   r4   r4   I  sl    	7<<'C
SZZM 2GMMB
CC	ME4=	1QD}2235 5'M&&-45M8JJ$'W]]$:%  a  B$6$67mmA!c2::&'D,@,@,C	c..Aq1u1fQiPQq56!$DQC H9 9 : 	: 	c..q&)<="A!c2::&'	AEa#221fQi@@qQq56!$DQC H9 9 : 	: 	a&&q&)4emmCJJq1ua%i34mmA?@ 
-r/   r   )
r,   r   r&   r}   r'   r}   r(   zSequence[int] | Noner]   r   )
r,   Array | np.ndarrayr&   (Array | np.ndarray | Sequence[ArrayLike]r3   r    r1   bool | Sequence[bool]r]   r   )
r,   rZ  r<   r   r&   zArray | Sequence[ArrayLike]r1   r\  r]   r   )r,   r   r&   r   ri   r?   r3   r    rb   rw   rc   rw   rd   r\   r]   r   )r,   r   r   r   r   r   ri   r|   rc   rw   rb   rw   rd   r\   r]   r   )r,   r   r   r   r   zCallable[[Array], Array]ri   r|   r   r    rc   rw   rb   rw   rd   r\   r]   r   )r   r   r   r   r   r}   r]   r   )r   r   )r,   rZ  r   
int | Noner   r]  r   r   r   r   r]   r   )r   T)
r,   rZ  r   r   r   r   r   rw   r]   r   r  )r,   rZ  r   r   r   r   r   r   r1   rw   r]   r   )r,   rZ  r   r   r   r   r   rw   r1   rw   r]   r   )r,   rZ  r<   r   r   r   r   r   r1   rw   r]   r   )r,   rZ  r<   r   r   r   r   r   r1   rw   r]   r   )r]   zmesh_lib.AbstractMesh)r]   zir.Value)r  z
str | Noner]   rw   )r]   zP | None)rF  zmlir.LoweringRuleContextr   z
core.Jaxpr)r,   rZ  r&   r[  r1   r\  r]   zlist[ArrayLike])
__future__r   collections.abcr   r   r^   r   	functoolsr   r	  typingr   weakrefnumpyrl   jax._srcr   r	   r
   r   r   r   jax._src.traceback_utilr   r   r   rD  jax._src.interpretersr   r   r   r   pejax._src.laxr   r   rQ  jax._src.lax.utilsr   r   r   jax._src.lib.mlirr   jax._src.lib.mlir.dialectsr   jax._src.named_shardingr   jax._src.partition_specr   r  jax._src.typingr   r   r    jax._src.state.indexingr!   jax._src.utilr"   r#   r   
unsafe_mapr  
unsafe_zipry   rj   r.   r,  r9   r=   r?   EnumrL   rz   r|   r   r   r   r   r   WeakKeyDictionaryr   rJ   r   r*  r   r   r   r   r   r   r   r   r  r  r  r  r&  r2  r<  standard_vma_ruler)   
deflinear2fancy_transposesprimitive_batchersdef_implrA  rH  register_loweringrS  rV  r\  rm  rr  r|  r  r  r  r  r  r7   primitive_jvpsprimitive_transposescustom_staging_rulescustom_typechecksr  r  r  r  r  r  r  r  r  r;   r  r  r  r  r  r  r  r  r  r  rA  rH  rL  rf  ri  rm  r  rv   defjvpr  rz  r  r  r  r  r  r  r  r  r  r  r  r  r   fancy_primitive_batchersskippable_batchersr   r   r  r  r   r   r  r  r   r   r  rA  rR  AddOp
SubtractOpr4   rC   r/   r-   <module>r     s   # .             % 0  % $ * & 4  + 
 ! * 1 6 3 3 & ,CZCZ		
 +/5K&5K'5K385Kz 59<Q<Q;<Q <Q
 2<Q <QF 59	;F;F)2;F.;F 2	;F
 ;F|$4Z $4N'5		 '5\ #(&+26k4kk  	k
  $k 0k "'k\%4j %4N 	&78 #5)-	S-S-'0S-;DS-,S- S- 59S- 	'	S- 38	S- 9S-j 	&78  % +/<<< < /	< < < )< < 9<~ 	&78 #5)-	/-/-'0/-;D/-,/- /- 59/- 	'	/- 38	/- 9/-b 	&78 #5)-	/-/-'0/-;D/-,/- /- 59/- 	'	/- 38	/- 9/-b 	&78 #5)-	/-/-'0/-;D/-,/- /- 59/- 	'	/- 38	/- 9/-d 3L'2K2K2M / M "5)-=-=-#(=- =- -=- 	=-
 =-
 59=- 	'=- 38=-@ "0 
 #5)-	P-P-'0P-;DP-,P- P- 59P- 	'	P- 38	P-d0, /0H?(H?H?(+H?49H?V GH"&9(9(+09(| 78>> 9=>>&/>>%(>>03>> 26>> BG>>F :>8( 9=	8( )8("8(268( 26	8( BG	8(~ @D	DE(1DE-6DE>ADE 9=	DE IN	DET @DE5(1E5:CE5&)E5 9=E5 INE5P$/L
,L @(( .W+?&-d.D.Dg&NP g, -5  G ';  G $ 	; ;A   w -R
.
^
)
N$?2
 %8/$Q'.T++_=,. &8  / "+H   ('E  O $/K  O ,+F   (*G   'A   (< =$2.= +0 ,$&F*MT++-CD735  -F  ( )(   . / ( 	  2 3A   -/J K
 	#L
3
9M2
_LD8cL
+#BL.Q,f *H$Q'7LT++X68 
		($d +$:   !(=  H %BJ(5Cn   x /OfR<I5=IX+@80'%R+%\7Lr #,m$Q'7MT++];0	2
 $++>#N  -  )01OQ^)_   &3:;QS`3a ! !- 0-9  M *",m$Q'7MT++];0	 $++>#N  -  )01OQ^)_   &3:M4+ ! !- 0-9  M *",m$Q'7MT++];0	2 
		-
D

  *E   &	
 -0 	 ! !- 0-9  M *iV #,m$Q'7MT++];0	2 

 -0 	 ! !- 0-9  M *#*+@-#P  -  ",m$Q'7MT++];0	2 

 -0 	 ! !- 0-9  M *#*+@-#P  -  bH1%f ,i$Q'7MT++Y70	2	
  ,  ) %<  	 "	
 ), 	 ! !) ,)5  I &,1>!+1>f   y. 1   }n 5   }n 5   }n 5   }n 5   }n 5 50#f   %;
   %@33;3 23 	3r/   