
    Vpf                   n   d Z ddlmZ ddlZddlmZmZmZmZm	Z	 ddl
mZmZ ddlZddlZddlZddlmZmZmZmZmZmZ ddlZddlZddlmZmZ ddlmZ dd	lmZ dd
l m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z. ddlm/Z/ ddlm0Z0 ddlm1Z1 ddlm2Z2 ddlm3Z3 ddlm4Z4 ddlm5Z5 ddlm6Z6 ddlm7Z7 ddlm8Z8 ddlm9Z9 ddlm:Z: ddlm;Z; ddlm<Z= ddl>m?Z?m@Z@mAZA ddlBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZRmSZSmTZT ddlUmVZW ddlXmYZY ddlXmZZ[ ddlXm\Z\ ddl]m^Z^ dd l_m`Z`maZa dd!lbmcZcmdZd dd"lemfZf dd#lmgZg dd$lhmiZimjZjmkZkmlZlmmZmmnZn dd%lmoZo dd&lpmqZq dd'lpmrZr dd(lpmsZs dd)lpmtZu dd*lpmvZv dd+lpmwZw  e:jx        ey            ee6jz        d,-          Z{eZ|e[j}        Z} ed.e/          Z~ ed0          Z ed1          ZejecZZekecZZd2 Zd3 Zd4 Ze0j                            ee           e0j                            ee           e6j        Ze7j        e7j        ddddd5ddd5dfddIZedddK            Z	 	 	 	 	 	 	 	 dddTZ	 	 	 	 ddd\Z	 	 	 ddd^Zd_ Zd` Z eeda          Zdb Z eeda          Z	 	 dddcZddgZdh Z	 	 dddiZeZ eedj          Z eedj          Z	 	 dddkZdl Zdm Zdn Zdo Zdp Zdq Z	 	 	 	 	 ddd{Zd| Z	 ddddLddddLdd}ddZ G d de          ZddZd Zd Z G d de          Z	 ddddLddddLdddZ ej                    Z	 dddZdddZed5ddd            Zedd            Zd5dddZd Zd ZddZed5dLddd            ZedLddd            Zd5dLdddZd5dddZdLdddZddZe	 	 	 	 ddd            Ze	 	 	 	 ddd            Z	 	 	 	 dddZddZ ed          d             Z	 dddddZddÄZddĄZdń ZddƄZ G dǄ dȦ          ZdɄ e1j        e<   efddʄ            Zdd˜dd̈́Zeddτ            ZdЄ Zdф Zd҄ ZddӄZdԄ ZdS (   a\  JAX user-facing transformations and utilities.

The transformations here mostly wrap internal transformations, providing
convenience flags to control behavior and handling Python containers of
arguments and outputs. The Python containers handled are pytrees (see
tree_util.py), which include nested tuples/lists/dicts, where the leaves are
arrays.
    )annotationsN)Callable	GeneratorHashableIterableSequence)partial	lru_cache)AnyLiteral
NamedTupleTypeVaroverloadcast)contextmanager	ExitStack)linear_util)stages)tree_maptree_flattentree_unflattentree_structuretree_transposetree_leavesPartial	PyTreeDef
all_leaveskeystrbroadcast_prefixprefix_errorsgenerate_key_pathstree_flatten_with_path)api_util)config)core)dispatch)effects)array)	basearray)dtypes)sharding_impls)sharding_specs)source_info_util)traceback_util)pjit)
xla_bridge)
eval_jaxprShapedArrayConcreteArray)flatten_funflatten_fun_nokwargsflatten_fun_nokwargs2argnums_partialargnums_partial_exceptflatten_axesdonation_vectorrebase_donate_argnums_ensure_index_ensure_index_tupleshaped_abstractifyapply_flat_fun_nokwargscheck_callable
debug_inforesult_pathsflat_out_axesdebug_info_finalfun_sourceinfo)lax)jax_jit)
xla_client)pmap_lib)Sharding)PmapShardingTransferToMemoryKind)Layout
AutoLayout)api_boundary)	tree_util)unzip2safe_mapsafe_zip	wrap_namewraps
split_list)util)ad)batching)mlir)partial_eval)pxla)xlaT)canonicalizeF)boundTUc                   g }t          |          D ]6}t          |d          r$|                    d |j        D                        7	 t	          j        t          j        j        |           dS # t          $ rJ t          j        j        st          j        j        sJ t          d            | j        |i |d          Y dS w xY w)zAHook function called by the C++ jit/pmap to perform NaN checking.addressable_shardsc                    g | ]	}|j         
S  )data).0shards     L/var/www/html/nettyfy-visnx/env/lib/python3.11/site-packages/jax/_src/api.py
<listcomp>z'_nan_check_posthook.<locals>.<listcomp>m   s    FFFUejFFF    ziInvalid nan value encountered in the output of a C++-jit/pmap function. Calling the de-optimized version.r   N)r   hasattrextendrd   r&   check_specialr/   pjit_pnameFloatingPointErrorr$   
debug_nansvalue
debug_infsprint_cache_miss)funargskwargsoutputbuffersleafs         rj   _nan_check_posthookr~   h   s    '&!! H Hdt)** HnnFFd.EFFFGGG(4;+W55555	 ( ( ("=f&7&====	 8 9 9 9COT$V$$Q'''''(s   
$A0 0ACCc                    t          j        d          st          j        d          rt          t          j                    _        d S d t          j                    _        d S )Njax_debug_nansjax_debug_infs)r$   _readr~   rG   global_state	post_hook_s    rj   _update_debug_special_globalr   x   sU    \"## ,v|4D'E'E ,':G$$$'+G$$$rl   c                    t          t          j        dd          st          t          j        dd          rt          t	          j                    _        d S d t	          j                    _        d S )Nr   Fr   )getattrr$   _thread_local_stater~   rG   thread_local_stater   r   s    rj   "_update_debug_special_thread_localr   ~   s`    f(*:EBB 2f(*:EBB2-@G  ***-1G  ***rl   Frx   r   static_argnumsint | Sequence[int] | Nonestatic_argnamesstr | Iterable[str] | Nonedonate_argnumsdonate_argnameskeep_unusedbooldevicexc.Device | Nonebackend
str | Noneinlineabstracted_axes
Any | Nonereturnpjit.JitWrappedc                D    t          j        | ||||||||	|||
d          S )a  Sets up ``fun`` for just-in-time compilation with XLA.

  Args:
    fun: Function to be jitted. ``fun`` should be a pure function.

      The arguments and return value of ``fun`` should be arrays, scalar, or
      (nested) standard Python containers (tuple/list/dict) thereof. Positional
      arguments indicated by ``static_argnums`` can be any hashable type. Static
      arguments are included as part of a compilation cache key, which is why
      hash and equality operators must be defined. JAX keeps a weak reference to
      ``fun`` for use as a compilation cache key, so the object ``fun`` must be
      weakly-referenceable.
    in_shardings: optional, a :py:class:`Sharding` or pytree with
      :py:class:`Sharding` leaves and structure that is a tree prefix of the
      positional arguments tuple to ``fun``. If provided, the positional
      arguments passed to ``fun`` must have shardings that are compatible with
      ``in_shardings`` or an error is raised, and the compiled computation has
      input shardings corresponding to ``in_shardings``. If not provided, the
      compiled computation's input shardings are inferred from argument
      shardings.
    out_shardings: optional, a :py:class:`Sharding` or pytree with
      :py:class:`Sharding` leaves and structure that is a tree prefix of the
      output of ``fun``. If provided, it has the same effect as applying
      corresponding :py:func:`jax.lax.with_sharding_constraint`s to the output
      of ``fun``.
    static_argnums: optional, an int or collection of ints that specify which
      positional arguments to treat as static (trace- and compile-time
      constant).

      Static arguments should be hashable, meaning both ``__hash__`` and
      ``__eq__`` are implemented, and immutable. Otherwise they can be arbitrary
      Python objects. Calling the jitted function with different values for
      these constants will trigger recompilation. Arguments that are not
      array-like or containers thereof must be marked as static.

      If neither ``static_argnums`` nor ``static_argnames`` is provided, no
      arguments are treated as static. If ``static_argnums`` is not provided but
      ``static_argnames`` is, or vice versa, JAX uses
      :code:`inspect.signature(fun)` to find any positional arguments that
      correspond to ``static_argnames``
      (or vice versa). If both ``static_argnums`` and ``static_argnames`` are
      provided, ``inspect.signature`` is not used, and only actual
      parameters listed in either ``static_argnums`` or ``static_argnames`` will
      be treated as static.
    static_argnames: optional, a string or collection of strings specifying
      which named arguments to treat as static (compile-time constant). See the
      comment on ``static_argnums`` for details. If not
      provided but ``static_argnums`` is set, the default is based on calling
      ``inspect.signature(fun)`` to find corresponding named arguments.
    donate_argnums: optional, collection of integers to specify which positional
      argument buffers can be overwritten by the computation and marked deleted
      in the caller. It is safe to donate argument buffers if you no longer need
      them once the computation has started. In some cases XLA can make use of
      donated buffers to reduce the amount of memory needed to perform a
      computation, for example recycling one of your input buffers to store a
      result. You should not reuse buffers that you donate to a computation; JAX
      will raise an error if you try to. By default, no argument buffers are
      donated.

      If neither ``donate_argnums`` nor ``donate_argnames`` is provided, no
      arguments are donated. If ``donate_argnums`` is not provided but
      ``donate_argnames`` is, or vice versa, JAX uses
      :code:`inspect.signature(fun)` to find any positional arguments that
      correspond to ``donate_argnames``
      (or vice versa). If both ``donate_argnums`` and ``donate_argnames`` are
      provided, ``inspect.signature`` is not used, and only actual
      parameters listed in either ``donate_argnums`` or ``donate_argnames`` will
      be donated.

      For more details on buffer donation see the
      `FAQ <https://jax.readthedocs.io/en/latest/faq.html#buffer-donation>`_.
    donate_argnames: optional, a string or collection of strings specifying
      which named arguments are donated to the computation. See the
      comment on ``donate_argnums`` for details. If not
      provided but ``donate_argnums`` is set, the default is based on calling
      ``inspect.signature(fun)`` to find corresponding named arguments.
    keep_unused: optional boolean. If `False` (the default), arguments that JAX
      determines to be unused by `fun` *may* be dropped from resulting compiled
      XLA executables. Such arguments will not be transferred to the device nor
      provided to the underlying executable. If `True`, unused arguments will
      not be pruned.
    device: This is an experimental feature and the API is likely to change.
      Optional, the Device the jitted function will run on. (Available devices
      can be retrieved via :py:func:`jax.devices`.) The default is inherited
      from XLA's DeviceAssignment logic and is usually to use
      ``jax.devices()[0]``.
    backend: This is an experimental feature and the API is likely to change.
      Optional, a string representing the XLA backend: ``'cpu'``, ``'gpu'``, or
      ``'tpu'``.
    inline: Optional boolean. Specify whether this function should be inlined
      into enclosing jaxprs. Default False.

  Returns:
    A wrapped version of ``fun``, set up for just-in-time compilation.

  Examples:
    In the following example, ``selu`` can be compiled into a single fused kernel
    by XLA:

    >>> import jax
    >>>
    >>> @jax.jit
    ... def selu(x, alpha=1.67, lmbda=1.05):
    ...   return lmbda * jax.numpy.where(x > 0, x, alpha * jax.numpy.exp(x) - alpha)
    >>>
    >>> key = jax.random.key(0)
    >>> x = jax.random.normal(key, (10,))
    >>> print(selu(x))  # doctest: +SKIP
    [-0.54485  0.27744 -0.29255 -0.91421 -0.62452 -0.24748
    -0.85743 -0.78232  0.76827  0.59566 ]

    To pass arguments such as ``static_argnames`` when decorating a function, a
    common pattern is to use :func:`functools.partial`:

    >>> from functools import partial
    >>>
    >>> @partial(jax.jit, static_argnames=['n'])
    ... def g(x, n):
    ...   for i in range(n):
    ...     x = x ** 2
    ...   return x
    >>>
    >>> g(jnp.arange(4), 3)
    Array([   0,    1,  256, 6561], dtype=int32)
  F)use_resource_env)r/   make_jit)rx   in_shardingsout_shardingsr   r   r   r   r   r   r   r   r   s               rj   jitr      s;    V 
\=.//Ve
5 
5 
5 5rl   disablec              #  l   K   t          j        |           5  dV  ddd           dS # 1 swxY w Y   dS )a  Context manager that disables :py:func:`jit` behavior under its dynamic context.

  For debugging it is useful to have a mechanism that disables :py:func:`jit`
  everywhere in a dynamic context. Note that this not only disables explicit
  uses of :func:`jit` by the user, but will also remove any implicit JIT compilation
  used by the JAX library: this includes implicit JIT computation of `body` and
  `cond` functions passed to higher-level primitives like :func:`~jax.lax.scan` and
  :func:`~jax.lax.while_loop`, JIT used in implementations of :mod:`jax.numpy` functions,
  and any other case where :func:`jit` is used within an API's implementation.
  Note however that even under `disable_jit`, individual primitive operations
  will still be compiled by XLA as in normal eager op-by-op execution.

  Values that have a data dependence on the arguments to a jitted function are
  traced and abstracted. For example, an abstract value may be a
  :py:class:`ShapedArray` instance, representing the set of all possible arrays
  with a given shape and dtype, but not representing one concrete array with
  specific values. You might notice those if you use a benign side-effecting
  operation in a jitted function, like a print:

  >>> import jax
  >>>
  >>> @jax.jit
  ... def f(x):
  ...   y = x * 2
  ...   print("Value of y is", y)
  ...   return y + 3
  ...
  >>> print(f(jax.numpy.array([1, 2, 3])))  # doctest:+ELLIPSIS
  Value of y is Traced<ShapedArray(int32[3])>with<DynamicJaxprTrace...>
  [5 7 9]

  Here ``y`` has been abstracted by :py:func:`jit` to a :py:class:`ShapedArray`,
  which represents an array with a fixed shape and type but an arbitrary value.
  The value of ``y`` is also traced. If we want to see a concrete value while
  debugging, and avoid the tracer too, we can use the :py:func:`disable_jit`
  context manager:

  >>> import jax
  >>>
  >>> with jax.disable_jit():
  ...   print(f(jax.numpy.array([1, 2, 3])))
  ...
  Value of y is [2 4 6]
  [5 7 9]
  N)r$   disable_jit)r   s    rj   r   r     s      ^ '"" 
 
	EEE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
s   )--rf   int | Iterable[int]axis_env%Sequence[tuple[AxisName, int]] | None
tuple_argsinstantiate_const_outputsbool | Nonereturn_shapec
                   	 |t          d          |t          d          |t          d          t                      t                    t          	          	t          	          	t	           dd          nt          j                    j        fdt                     t          	 f
d                        }
|
S )	a  Creates a function that produces its XLA computation given example args.

  .. warning::

    This function is deprecated as of JAX v0.4.30, and will be removed in a future
    JAX release. You can replace it with :ref:`ahead-of-time-lowering` APIs; for
    example, ``jax.xla_computation(fn)(*args)`` can be replaced with
    ``jax.jit(fn).lower(*args).compiler_ir('hlo')``.
    See the `JAX 0.4.30 Change log`_ for more examples.

  Args:
    fun: Function from which to form XLA computations.
    static_argnums: See the :py:func:`jax.jit` docstring.
    axis_env: Optional, a sequence of pairs where the first element is an axis
      name and the second element is a positive integer representing the size of
      the mapped axis with that name. This parameter is useful when lowering
      functions that involve parallel communication collectives, and it
      specifies the axis name/size environment that would be set up by
      applications of :py:func:`jax.pmap`. See the examples below.
    in_parts: Optional, how each argument to ``fun`` should be partitioned or
      replicated. This is used to specify partitioned XLA computations, see
      ``sharded_jit`` for more info.
    out_parts: Optional, how each output of ``fun`` should be partitioned or
      replicated. This is used to specify partitioned XLA computations, see
      ``sharded_jit`` for more info.
    backend: This is an experimental feature and the API is likely to change.
      Optional, a string representing the XLA backend: ``'cpu'``, ``'gpu'``, or
      ``'tpu'``.
    tuple_args: Optional bool, defaults to ``False``. If ``True``, the resulting
      XLA computation will have a single tuple argument that is unpacked into
      the specified function arguments. If `None`, tupling will be enabled when
      there are more than 100 arguments, since some platforms have limits on
      argument arity.
    instantiate_const_outputs: Deprecated argument, does nothing.
    return_shape: Optional boolean, defaults to ``False``. If ``True``, the
      wrapped function returns a pair where the first element is the XLA
      computation and the second element is a pytree with the same structure as
      the output of ``fun`` and where the leaves are objects with ``shape`` and
      ``dtype`` attributes representing the corresponding types of the output
      leaves.
    donate_argnums: Specify which arguments are "donated" to the computation.
      It is safe to donate arguments if you no longer need them once the
      computation has finished. In some cases XLA can make use of donated
      buffers to reduce the amount of memory needed to perform a computation,
      for example recycling one of your input buffers to store a result. You
      should not reuse buffers that you donate to a computation, JAX will raise
      an error if you try to.

  Returns:
    A wrapped version of ``fun`` that when applied to example arguments returns
    a built XLA Computation (see xla_client.py), from which representations of
    the unoptimized XLA HLO computation can be extracted using methods like
    ``as_hlo_text``, ``as_serialized_hlo_module_proto``, and
    ``as_hlo_dot_graph``. If the argument ``return_shape`` is ``True``, then the
    wrapped function returns a pair where the first element is the XLA
    Computation and the second element is a pytree representing the structure,
    shapes, dtypes, and named shapes of the output of ``fun``.

    Concrete example arguments are not always necessary. For those arguments not
    indicated by ``static_argnums``, any object with ``shape`` and ``dtype``
    attributes is acceptable (excepting namedtuples, which are treated as Python
    containers).

  For example:

  >>> import jax
  >>>
  >>> def f(x): return jax.numpy.sin(jax.numpy.cos(x))
  >>> c = jax.xla_computation(f)(3.)  # doctest: +SKIP
  >>> print(c.as_hlo_text())  # doctest: +SKIP
  HloModule xla_computation_f.6
  <BLANKLINE>
  ENTRY xla_computation_f.6 {
    constant.2 = pred[] constant(false)
    parameter.1 = f32[] parameter(0)
    cosine.3 = f32[] cosine(parameter.1)
    sine.4 = f32[] sine(cosine.3)
    ROOT tuple.5 = (f32[]) tuple(sine.4)
  }
  <BLANKLINE>
  <BLANKLINE>


  Alternatively, the assignment to ``c`` above could be written:

  >>> import types
  >>> scalar = types.SimpleNamespace(shape=(), dtype=np.dtype(np.float32))
  >>> c = jax.xla_computation(f)(scalar)  # doctest: +SKIP


  Here's an example that involves a parallel collective and axis name:

  >>> def f(x): return x - jax.lax.psum(x, 'i')
  >>> c = jax.xla_computation(f, axis_env=[('i', 4)])(2)  # doctest: +SKIP
  >>> print(c.as_hlo_text())  # doctest: +SKIP
  HloModule jaxpr_computation.9
  primitive_computation.3 {
    parameter.4 = s32[] parameter(0)
    parameter.5 = s32[] parameter(1)
    ROOT add.6 = s32[] add(parameter.4, parameter.5)
  }
  ENTRY jaxpr_computation.9 {
    tuple.1 = () tuple()
    parameter.2 = s32[] parameter(0)
    all-reduce.7 = s32[] all-reduce(parameter.2), replica_groups={{0,1,2,3}}, to_apply=primitive_computation.3
    ROOT subtract.8 = s32[] subtract(parameter.2, all-reduce.7)
  }
  <BLANKLINE>
  <BLANKLINE>

  Notice the ``replica_groups`` that were generated. Here's an example that
  generates more interesting ``replica_groups``:

  >>> from jax import lax
  >>> def g(x):
  ...   rowsum = lax.psum(x, 'i')
  ...   colsum = lax.psum(x, 'j')
  ...   allsum = lax.psum(x, ('i', 'j'))
  ...   return rowsum, colsum, allsum
  ...
  >>> axis_env = [('i', 4), ('j', 2)]
  >>> c = jax.xla_computation(g, axis_env=axis_env)(5.)  # doctest: +SKIP
  >>> print(c.as_hlo_text())  # doctest: +SKIP
  HloModule jaxpr_computation__1.19
  [removed uninteresting text here]
  ENTRY jaxpr_computation__1.19 {
    tuple.1 = () tuple()
    parameter.2 = f32[] parameter(0)
    all-reduce.7 = f32[] all-reduce(parameter.2), replica_groups={{0,2,4,6},{1,3,5,7}}, to_apply=primitive_computation__1.3
    all-reduce.12 = f32[] all-reduce(parameter.2), replica_groups={{0,1},{2,3},{4,5},{6,7}}, to_apply=primitive_computation__1.8
    all-reduce.17 = f32[] all-reduce(parameter.2), replica_groups={{0,1,2,3,4,5,6,7}}, to_apply=primitive_computation__1.13
    ROOT tuple.18 = (f32[], f32[], f32[]) tuple(all-reduce.7, all-reduce.12, all-reduce.17)
  }

  .. _JAX 0.4.30 Change log: https://jax.readthedocs.io/en/latest/changelog.html#jax-0-4-30-june-18-2024
  Nzinstantiate_const_outputs has been deprecated. Please use the ahead of time APIs. You can read more here: https://jax.readthedocs.io/en/latest/aot.htmlzin_parts has been deprecated. Please use the ahead of time APIs. You can read more here: https://jax.readthedocs.io/en/latest/aot.htmlzout_parts has been deprecated. Please use the ahead of time APIs. You can read more here: https://jax.readthedocs.io/en/latest/aot.html__name__unknownc                    t          j        | dd          S | t          j        d D                       z  } t	                    \  }}t          j        | ||          S )Nrf   c              3      K   | ]	\  }}|V  
d S Nrf   )rh   rq   sizes      rj   	<genexpr>z9xla_computation.<locals>.make_axis_env.<locals>.<genexpr>  s&      @@t@@@@@@rl   )r+   AxisEnvmathprodrQ   )nrepsnamessizesr   s      rj   make_axis_envz&xla_computation.<locals>.make_axis_env  sg    #E2r222di@@x@@@@@@eH%%leU#E5%888rl   c                   
 t           z   d          t          |           k    r&t          d ddt          |            d          t          j                  }t          | | d          \  }}t          ||f          \  }}rt          d	|          }nd
t          |          z  }t          ||          \  }}t          t          |          }	t                      5 }
pg D ].\  }}|
                    t          j        ||d                      /t          j        ||	          \  }}}\   t#          j        |          }rt          j        |d D                       } t#          j        |                    }t+          t,          j                            |j                            }t3          j        d t          j        ||          |gt9          j        |          t=          j        tA          d                    |d d t3          j!                              }t3          j"        |j#                  }tH          j%        j        &                    |!d          }d d d            n# 1 swxY w Y   d |D             }d |D             }tO           |            |          }|D ]&}tQ          |tR                    stU          d          'r||fS |S )N)defaultz#jitted function has static_argnums=z, donate_argnums= but was called with only  positional arguments.F)allow_invalidrf   Fc                    h | ]\  }}|S rf   rf   )rh   	axis_namer   s      rj   	<setcomp>z=xla_computation.<locals>.computation_maker.<locals>.<setcomp>  s    ;;;,)QI;;;rl   xla_computation_xla_computation)	ordered_effectsbackend_or_name	platformsaxis_context
name_stackdonated_argsarg_shardingsresult_shardingslowering_parametersT)use_tuple_argsreturn_tuplec                B    g | ]}t          |j        |j                  S rf   ShapeDtypeStructshapedtyperh   as     rj   rk   z>xla_computation.<locals>.computation_maker.<locals>.<listcomp>0  '    MMMa'99MMMrl   c                B    g | ]}t          |j        |j                  S rf   r   r   s     rj   rk   z>xla_computation.<locals>.computation_maker.<locals>.<listcomp>1  r   rl   zgAs we want to propagate the weak_type, we need to get a ShapedArray, otherwise this information is lost)+maxlen
ValueErrorlu	wrap_initr8   r   r:   r4   mapr>   r   enter_contextr%   extend_axis_envpetrace_to_jaxpr_dynamicr&   apply_outfeed_rewriterremove_named_axis_effectsjaxpr_replicaslistr'   r   	filter_inrZ   lower_jaxpr_to_moduleClosedJaxprr+   ReplicaAxisContextr-   new_name_stackrT   LoweringParametersmodule_to_bytecodemodulexc_xlamlir_module_to_xla_computationr   
isinstancer2   RuntimeError)"ry   rz   fdyn_args	args_flatin_treedonated_invarsjaxtree_funout_treeavalsstackr   r   jaxpr	out_avalsconsts	axis_env_r   lowering_resultmbuiltout_shapes_flat	out_shapeout_avalr   r   r   rx   fun_namer   platformr   r   r   s"                           rj   computation_makerz*xla_computation.<locals>.computation_maker  s    >N*B7773t99DD Qn Q Q Q Q/24yyQ Q Q R R R 	SA(NDPUVVVKAx%x&899Iw 1&~r7CCnn#i..0n'733K"I..E	 ;%^ I I/)TD0D$GGHHHH%'%>{E%R%R"eY-e44e	 
.;;(;;;
 
  - 7 > >??i

!
+
+EM
:
:< <o2
'X
'
'

5&
)
))!J%8CC%4"3446 6%"5779 9 9o 
!/"8
9
9agl99
JT : ; ;e7; ; ; ; ; ; ; ; ; ; ; ; ; ; ;: NM9MMMOMM9MMMOxxzz?;;I 2 2+.. 2 1 2 2 	22
  Ils   'FI>>JJ)
r   r@   r=   r;   r   xbget_backendr  rU   rO   )rx   r   r   in_parts	out_partsr   r   r   r   r   r  r  r   r  s   ```  `` `` @@@rj   r   r   R  sY   b *
	9: : : 
	MN N N 
	MN N N &~66.&~66.(HH.S*i00(+WW1A1A1J(9 9 9 9 9 	::8 8 8 8 8 8 8 8 8 8 8 8 8 < :8t 
rl   argnumsint | Sequence[int]has_auxholomorphic	allow_intreduce_axesSequence[AxisName]c                  	 |rt          d          ~t          | ||||          	d}t          | ||          t          	fd                        }t          | ||          t          	fd                        }|r|n|S )a  Creates a function that evaluates the gradient of ``fun``.

  Args:
    fun: Function to be differentiated. Its arguments at positions specified by
      ``argnums`` should be arrays, scalars, or standard Python containers.
      Argument arrays in the positions specified by ``argnums`` must be of
      inexact (i.e., floating-point or complex) type. It
      should return a scalar (which includes arrays with shape ``()`` but not
      arrays with shape ``(1,)`` etc.)
    argnums: Optional, integer or sequence of integers. Specifies which
      positional argument(s) to differentiate with respect to (default 0).
    has_aux: Optional, bool. Indicates whether ``fun`` returns a pair where the
      first element is considered the output of the mathematical function to be
      differentiated and the second element is auxiliary data. Default False.
    holomorphic: Optional, bool. Indicates whether ``fun`` is promised to be
      holomorphic. If True, inputs and outputs must be complex. Default False.
    allow_int: Optional, bool. Whether to allow differentiating with
      respect to integer valued inputs. The gradient of an integer input will
      have a trivial vector-space dtype (float0). Default False.

  Returns:
    A function with the same arguments as ``fun``, that evaluates the gradient
    of ``fun``. If ``argnums`` is an integer then the gradient has the same
    shape and type as the positional argument indicated by that integer. If
    argnums is a tuple of integers, the gradient is a tuple of values with the
    same shapes and types as the corresponding arguments. If ``has_aux`` is True
    then a pair of (gradient, auxiliary_data) is returned.

  For example:

  >>> import jax
  >>>
  >>> grad_tanh = jax.grad(jax.numpy.tanh)
  >>> print(grad_tanh(0.2))
  0.961043
  *reduce_axes argument to grad is deprecated)r  r  r  zGradient of {fun} with respect to positional argument(s) {argnums}. Takes the same arguments as {fun} but returns the gradient, which has the same shape as the arguments at positions {argnums}.docstrr  c                      | i |\  }}|S r   rf   )ry   rz   r   gvalue_and_grad_fs       rj   grad_fzgrad.<locals>.grad_ft  s#     T,V,,DAqHrl   c                 (     | i |\  \  }}}||fS r   rf   )ry   rz   r   auxr  r  s        rj   
grad_f_auxzgrad.<locals>.grad_f_auxz  s+     #"D3F33KHQac6Mrl   )NotImplementedErrorvalue_and_gradrU   rO   )
rx   r  r  r  r  r  r  r   r#  r  s
            @rj   gradr&  @  s    P  L
J
K
KK#C'0;.79 9 9#&
 	VW---    < .- 	VW---    < .- 	*F*rl   Callable[..., tuple[Any, Any]]c                     |rt          d          ~d}t                      t          j        t                    t           |          t           fd                        }|S )a{  Create a function that evaluates both ``fun`` and the gradient of ``fun``.

  Args:
    fun: Function to be differentiated. Its arguments at positions specified by
      ``argnums`` should be arrays, scalars, or standard Python containers. It
      should return a scalar (which includes arrays with shape ``()`` but not
      arrays with shape ``(1,)`` etc.)
    argnums: Optional, integer or sequence of integers. Specifies which
      positional argument(s) to differentiate with respect to (default 0).
    has_aux: Optional, bool. Indicates whether ``fun`` returns a pair where the
      first element is considered the output of the mathematical function to be
      differentiated and the second element is auxiliary data. Default False.
    holomorphic: Optional, bool. Indicates whether ``fun`` is promised to be
      holomorphic. If True, inputs and outputs must be complex. Default False.
    allow_int: Optional, bool. Whether to allow differentiating with
      respect to integer valued inputs. The gradient of an integer input will
      have a trivial vector-space dtype (float0). Default False.

  Returns:
    A function with the same arguments as ``fun`` that evaluates both ``fun``
    and the gradient of ``fun`` and returns them as a pair (a two-element
    tuple). If ``argnums`` is an integer then the gradient has the same shape
    and type as the positional argument indicated by that integer. If argnums is
    a sequence of integers, the gradient is a tuple of values with the same
    shapes and types as the corresponding arguments. If ``has_aux`` is True
    then a tuple of ((value, auxiliary_data), gradient) is returned.
  r  a'  Value and gradient of {fun} with respect to positional argument(s) {argnums}. Takes the same arguments as {fun} but returns a two-element tuple where the first element is the value of {fun} and the second element is the gradient, which has the same shape as the arguments at positions {argnums}.r  c            
        t          t                    rnt                    }|t          |           k    r)t	          dd|dz    dt          |            d          t          j        |          }t          || d          \  }}t          |          D ]}t          |           st          |g|R  \  }}nt          |g|R dd	i\  }}}	t          |           t          t          t                    |            |t          j        |                    }
t          t                    r|
d
         n|
}
s||
fS ||	f|
fS )Nz(differentiating with respect to argnums=z requires at least    z? positional arguments to be passed by the caller, but got only r   Frequire_static_args_hashabler  Tr   )r   intr   r   	TypeErrorr   r   r7   r   _check_input_dtype_grad_vjp_check_scalarr   r	   _check_output_dtype_gradlax_internal_one)ry   rz   
max_argnumr   	f_partialr   r}   ansvjp_pyr"  r  r  r  rx   r  r  s              rj   r  z(value_and_grad.<locals>.value_and_grad_f  s    'w44F#g,,JSYY H H H#aH H&)$iiH H H I I I 	S&!!A)!WdGLN N NIxH%% < <k9d;;;; ..X...kc66
.. . .(,. .c63#W-{;;SAAA| %%&&A7C((/!aA !Vm3Z]rl   )r$  r@   r%   concrete_or_errorr<   rU   rO   )rx   r  r  r  r  r  r  r  s   `````   rj   r%  r%    s    >  L
J
K
KKB& "='::'VW---        < .-4 
rl   c                P   dj         }	 t          j        |           }t          |t                    r-|j        dk    r t           |d|j                             d S t           |d|                     # t          $ r!}t           |d|                      |d }~ww xY w)Nz=Gradient only defined for scalar-output functions. Output {}.rf   zhad shape: zhad abstract value zwas )formatr%   get_avalr   r2   r   r.  )xmsgavales       rj   r1  r1    s    GN#	9=D $$$ 9	r		6$*6677888 
	 cc66677888 
 , , ,
CC
q

OO
$
$!+,s   A: :
B%B  B%c                   t          j        |           t          j        |          }|rCt	          j        |j        t          j                  st          |  d|j        j
         d          t	          j        |j        t          j                  sHt	          j        |j        t          j                  s$t	          j        |j        t          j                  r#|st          |  d|j        j
         d          d S t	          j        |j        t          j                  st          |  d|j        j
         d          d S )NzC with holomorphic=True requires inputs with complex dtype, but got .zb requires real- or complex-valued inputs (input dtype that is a sub-dtype of np.inexact), but got zY. If you want to use Boolean- or integer-valued inputs, use vjp or set allow_int to True.zf requires numerical-valued inputs (input dtype that is a sub-dtype of np.bool_ or np.number), but got )r&   	check_argr%   r<  r*   
issubdtyper   npcomplexfloatingr.  rq   extendedintegerbool_inexact)rq   r  r  r=  r?  s        rj   _check_input_dtype_revderivrK    sr   
Q	q		$ 5TZ);<< 5 4 4!%4 4 4 5 5 5
FO44 
X
BJ//
X
BH--
X  3 2 2EIZ_2 2 2 3 3 33 3
 TZ44 X
t W WDHJOW W W X X XX Xrl   r&  c                L   t          j        |          }t          j        |j        t          j                  rt          |  d|j        j                   |rEt          j        |j        t          j	                  st          |  d|j        j         d          d S t          j        |j        t          j	                  rt          |  d|j        j         d          t          j        |j        t          j
                  st          |  d|j        j         d          d S )Nz with output element type zD with holomorphic=True requires outputs with complex dtype, but got rB  zY requires real-valued outputs (output dtype that is a sub-dtype of np.floating), but got z. For holomorphic differentiation, pass holomorphic=True. For differentiation of non-holomorphic functions involving complex outputs, use jax.vjp directly.zN. For differentiation of functions with integer outputs, use jax.vjp directly.)r%   r<  r*   rD  r   rG  r.  rq   rE  rF  floating)rq   r  r=  r?  s       rj   _check_output_dtype_revderivrN    sZ   	q		$tz6?33 >
<<4:?<<> > > )TZ);<< 5 4 4!%4 4 4 5 5 55 5 R%788 
)
t 5 5<@JO5 5 5 6 6 6
 TZ55 )
t ( (<@JO( ( ( ) ) )) )rl   c                     t                      t                    d}t           |           fd            }|S )a  Jacobian of ``fun`` evaluated column-by-column using forward-mode AD.

  Args:
    fun: Function whose Jacobian is to be computed.
    argnums: Optional, integer or sequence of integers. Specifies which
      positional argument(s) to differentiate with respect to (default ``0``).
    has_aux: Optional, bool. Indicates whether ``fun`` returns a pair where the
      first element is considered the output of the mathematical function to be
      differentiated and the second element is auxiliary data. Default False.
    holomorphic: Optional, bool. Indicates whether ``fun`` is promised to be
      holomorphic. Default False.

  Returns:
    A function with the same arguments as ``fun``, that evaluates the Jacobian of
    ``fun`` using forward-mode automatic differentiation. If ``has_aux`` is True
    then a pair of (jacobian, auxiliary_data) is returned.

  >>> import jax
  >>> import jax.numpy as jnp
  >>>
  >>> def f(x):
  ...   return jnp.asarray(
  ...     [x[0], 5*x[2], 4*x[1]**2 - 2*x[2], x[2] * jnp.sin(x[0])])
  ...
  >>> print(jax.jacfwd(f)(jnp.array([1., 2., 3.])))
  [[ 1.       0.       0.     ]
   [ 0.       0.       5.     ]
   [ 0.      16.      -2.     ]
   [ 1.6209   0.       0.84147]]
  Jacobian of {fun} with respect to positional argument(s) {argnums}. Takes the same arguments as {fun} but returns the jacobian of the output with respect to the arguments at positions {argnums}.r  c                    t          j        |          }t          || d          \  }}t          t	          t
                    |           sAt	          t          ||          } t          |d          t          |                    \  }}nCt	          t          ||d          } t          |d          t          |                    \  }}}t          t	          t                    |           t          t                    r|d         n|}	t          t	          t          |	          ||          }
s|
S |
|fS )	NFr+  Nr   )out_axesTr  )Nr   Nr   )r   r   r7   r   r	   _check_input_dtype_jacfwd_jvpvmap
_std_basis_check_output_dtype_jacfwdr   r-  _jacfwd_unravel)ry   rz   r   r6  r   pushfwdyjacr"  example_argsjac_treer  rx   r  r  s              rj   jacfunzjacfwd.<locals>.jacfun,  sB   
S&!!A)!WdGLN N NIxW.<<hGGG S!$	8<<g1tGj111*X2F2FGGfa!$	8TJJJg<D+;<<<Z=Q=QRRkacW/==qAAA",Wc":":H8A;;L>>3GGH os]rl   )r@   r<   rU   )rx   r  r  r  r  r`  s   ````  rj   jacfwdra    sv    @ '""'#&
 	VW---       .-& 
-rl   r=  r   Nonec                   t          j        |           t          j        |          }t	          j        |j        t          j                  rt          d|j        j	                   | rCt	          j        |j        t          j                  st          d|j        j	         d          d S t	          j        |j        t          j                  st          d|j        j	         d          d S )Nzjacfwd with input element type zIjacfwd with holomorphic=True requires inputs with complex dtype, but got rB  z]jacfwd requires real-valued inputs (input dtype that is a sub-dtype of np.floating), but got z. For holomorphic differentiation, pass holomorphic=True. For differentiation of non-holomorphic functions involving complex inputs or integer inputs, use jax.jvp directly.)r&   rC  r%   r<  r*   rD  r   rG  r.  rq   rE  rF  rM  r  r=  r?  s      rj   rU  rU  B  s   
Q	q		$tz6?33 =
;$*/;;= = = 	OTZ);<< < ;(,
; ; ; < < << < TZ55 O
 N<@JON N N O O OO Orl   c                    t          j        |          }| rAt          j        |j        t
          j                  st          d|j        j         d          d S d S )NzJjacfwd with holomorphic=True requires outputs with complex dtype, but got rB  )	r%   r<  r*   rD  r   rE  rF  r.  rq   rd  s      rj   rY  rY  S  st    	q		$ 5TZ);<< 5 4!%4 4 4 5 5 55 55 5rl   c                t     t                      d}t           |           fd            }|S )a  Jacobian of ``fun`` evaluated row-by-row using reverse-mode AD.

  Args:
    fun: Function whose Jacobian is to be computed.
    argnums: Optional, integer or sequence of integers. Specifies which
      positional argument(s) to differentiate with respect to (default ``0``).
    has_aux: Optional, bool. Indicates whether ``fun`` returns a pair where the
      first element is considered the output of the mathematical function to be
      differentiated and the second element is auxiliary data. Default False.
    holomorphic: Optional, bool. Indicates whether ``fun`` is promised to be
      holomorphic. Default False.
    allow_int: Optional, bool. Whether to allow differentiating with
      respect to integer valued inputs. The gradient of an integer input will
      have a trivial vector-space dtype (float0). Default False.

  Returns:
    A function with the same arguments as ``fun``, that evaluates the Jacobian of
    ``fun`` using reverse-mode automatic differentiation. If ``has_aux`` is True
    then a pair of (jacobian, auxiliary_data) is returned.

  >>> import jax
  >>> import jax.numpy as jnp
  >>>
  >>> def f(x):
  ...   return jnp.asarray(
  ...     [x[0], 5*x[2], 4*x[1]**2 - 2*x[2], x[2] * jnp.sin(x[0])])
  ...
  >>> print(jax.jacrev(f)(jnp.array([1., 2., 3.])))
  [[ 1.       0.       0.     ]
   [ 0.       0.       5.     ]
   [ 0.      16.      -2.     ]
   [ 1.6209   0.       0.84147]]
  rP  r  c                    t          j        |          }t          || d          \  }}t          t	          t
                    |           st          |g|R  \  }}nt          |g|R ddi\  }}}t          t	          t                    |            t          |          t          |                    }t          t                    r|d         n|}t          t                    r|d         n|}	t          t	          t          |          |	|          }
t          t          |	          t          |          |
          }
s|
S |
|fS )NFr+  r  Tr   )r   r   r7   r   r	   _check_input_dtype_jacrevr0  _check_output_dtype_jacrevrW  rX  r   r-  _jacrev_unravelr   r   )ry   rz   r   r6  r   r\  pullbackr"  r]  r^  r_  r  r  rx   r  r  s              rj   r`  zjacrev.<locals>.jacfun  s_   
S&!!A)!WdGLN N NIxW.YGGRRR B.X...kaiA(AAADAAa3W/==qAAA
$x..A
'
'Cw,,
5#a&&#C",Wc":":H8A;;L33\3GGHn\::N1<M<MxXXH os]rl   )r@   rU   )rx   r  r  r  r  r  r`  s   `````  rj   jacrevrl  Z  so    F #&
 	VW---        .-( 
-rl   rl  c                J    t          t          | |||          |||          S )a|  Hessian of ``fun`` as a dense array.

  Args:
    fun: Function whose Hessian is to be computed.  Its arguments at positions
      specified by ``argnums`` should be arrays, scalars, or standard Python
      containers thereof. It should return arrays, scalars, or standard Python
      containers thereof.
    argnums: Optional, integer or sequence of integers. Specifies which
      positional argument(s) to differentiate with respect to (default ``0``).
    has_aux: Optional, bool. Indicates whether ``fun`` returns a pair where the
      first element is considered the output of the mathematical function to be
      differentiated and the second element is auxiliary data. Default False.
    holomorphic: Optional, bool. Indicates whether ``fun`` is promised to be
      holomorphic. Default False.

  Returns:
    A function with the same arguments as ``fun``, that evaluates the Hessian of
    ``fun``.

  >>> import jax
  >>>
  >>> g = lambda x: x[0]**3 - 2*x[0]*x[1] - x[1]**6
  >>> print(jax.hessian(g)(jax.numpy.array([1., 2.])))
  [[   6.   -2.]
   [  -2. -480.]]

  :py:func:`hessian` is a generalization of the usual definition of the Hessian
  that supports nested Python containers (i.e. pytrees) as inputs and outputs.
  The tree structure of ``jax.hessian(fun)(x)`` is given by forming a tree
  product of the structure of ``fun(x)`` with a tree product of two copies of
  the structure of ``x``. A tree product of two tree structures is formed by
  replacing each leaf of the first tree with a copy of the second. For example:

  >>> import jax.numpy as jnp
  >>> f = lambda dct: {"c": jnp.power(dct["a"], dct["b"])}
  >>> print(jax.hessian(f)({"a": jnp.arange(2.) + 1., "b": jnp.arange(2.) + 2.}))
  {'c': {'a': {'a': Array([[[ 2.,  0.], [ 0.,  0.]],
                           [[ 0.,  0.], [ 0., 12.]]], dtype=float32),
               'b': Array([[[ 1.      ,  0.      ], [ 0.      ,  0.      ]],
                           [[ 0.      ,  0.      ], [ 0.      , 12.317766]]], dtype=float32)},
         'b': {'a': Array([[[ 1.      ,  0.      ], [ 0.      ,  0.      ]],
                           [[ 0.      ,  0.      ], [ 0.      , 12.317766]]], dtype=float32),
               'b': Array([[[0.      , 0.      ], [0.      , 0.      ]],
                           [[0.      , 0.      ], [0.      , 3.843624]]], dtype=float32)}}}

  Thus each leaf in the tree structure of ``jax.hessian(fun)(x)`` corresponds to
  a leaf of ``fun(x)`` and a pair of leaves of ``x``. For each leaf in
  ``jax.hessian(fun)(x)``, if the corresponding array leaf of ``fun(x)`` has
  shape ``(out_1, out_2, ...)`` and the corresponding array leaves of ``x`` have
  shape ``(in_1_1, in_1_2, ...)`` and ``(in_2_1, in_2_2, ...)`` respectively,
  then the Hessian leaf has shape ``(out_1, out_2, ..., in_1_1, in_1_2, ...,
  in_2_1, in_2_2, ...)``. In other words, the Python tree structure represents
  the block structure of the Hessian, with blocks determined by the input and
  output pytrees.

  In particular, an array is produced (with no pytrees involved) when the
  function input ``x`` and output ``fun(x)`` are each a single array, as in the
  ``g`` example above. If ``fun(x)`` has shape ``(out1, out2, ...)`` and ``x``
  has shape ``(in1, in2, ...)`` then ``jax.hessian(fun)(x)`` has shape
  ``(out1, out2, ..., in1, in2, ..., in1, in2, ...)``. To flatten pytrees into
  1D vectors, consider using :py:func:`jax.flatten_util.flatten_pytree`.
  )r  r  )ra  rl  )rx   r  r  r  s       rj   hessianrn    s:    @ 
sGW+NNNk
C 
C 
C Crl   c                    dd l m} t          |           \  }}t          t	          t
          j        |                    }t          j        | }|	                    ||          }t          | dd |          S )Nr   )r   r*  )	jax.numpynumpyr   sumr   rE  r   r*   result_typeeye_unravel_array_into_pytree)pytreejnpleavesr   ndimr   
flat_basiss          rj   rX  rX    st    6"")&!	S&!!	"	"$

f
%%wwt5w))*	#FAtZ	@	@@rl   c                &    t          | d||          S rR  ru  )input_pytreeoutput_pytree_leafarrs      rj   rZ  rZ    s    	#"(#
/ 
/ /rl   c                &    t          | d||          S Nr   r|  )output_pytreeinput_pytree_leafr  s      rj   rj  rj    s    	#1'
. 
. .rl   c                2   t          j        | j        t          j                  r3t          j        t          |          t          j                  s| j        } |d nt          |          }|d nt          j        |          }t          j	        | ||          S r   )
r*   rD  r   rE  rF  _dtyperealis_weakly_typedr3  _convert_element_type)r=  exampler   	weak_types       rj   _possible_downcastr    s    !344 

F7OOR-?
@
@	A/$$vg%odd6+A'+J+J)		+Aui	@	@@rl   c                >   t          |           \  }}j        z  fd|D             }t          t          j        t          t          j        |dd                                       }fdt          |||          D             }t          ||          S )a  Unravel an array into a PyTree with a given structure.
  Args:
      pytree: The pytree that provides the structure.
      axis: The parameter axis is either -1, 0, or 1.  It controls the
        resulting shapes.
      example: If specified, cast the components to the matching dtype/weak_type,
        or else use the pytree leaf type if example is None.
      arr: The array to be unraveled.
  c                ~    g | ]9}j         d          t          j         |          z   j         dz   d          z   :S )Nr*  )r   rE  )rh   lr  axiss     rj   rk   z._unravel_array_into_pytree.<locals>.<listcomp>  sE    PPPACIeterx{{*SYtAvww-??PPPrl   Nr   c                f    g | ]-\  }}}t          t          j        ||          |n          .S r   )r  rE  reshape)rh   r=  r   r}   r  s       rj   rk   z._unravel_array_into_pytree.<locals>.<listcomp>	  sM     8 8 8
!UD Au--wttGTT8 8 8rl   )	r   ry  _splitrE  cumsumr   r   zipr   )	rv  r  r  r  rx  treedefshapespartsreshaped_partss	    ```     rj   ru  ru    s     !((/&'	$PPPPPPPP&
biBGVCRC[ 9 9::D
A
A%8 8 8 8vv668 8 8. 
	0	00rl   c                    t          | t          j                  rt          j        | ||          S |                     ||          S r   )r   rE  ndarraysplitr  )r=  indicesr  s      rj   r  r    s>    2: #8Aw%%%88GT"""rl   in_axesint | None | Sequence[Any]rS  r   AxisName | None	axis_size
int | Nonespmd_axis_name&AxisName | tuple[AxisName, ...] | Nonec                    t                      d} j        r|dz  }| j        z  }t          j        nt	                    t
          urft          t                    rt                    <t	                    t          t
          ht          j
        v st          d d          t          d t                    D                       st          d d          t          d t                    D                       st          d	 d          t           |
          t           fd                        }t!          t"          |          S )a0  Vectorizing map. Creates a function which maps ``fun`` over argument axes.

  Args:
    fun: Function to be mapped over additional axes.
    in_axes: An integer, None, or sequence of values specifying which input
      array axes to map over.

      If each positional argument to ``fun`` is an array, then ``in_axes`` can
      be an integer, a None, or a tuple of integers and Nones with length equal
      to the number of positional arguments to ``fun``. An integer or ``None``
      indicates which array axis to map over for all arguments (with ``None``
      indicating not to map any axis), and a tuple indicates which axis to map
      for each corresponding positional argument. Axis integers must be in the
      range ``[-ndim, ndim)`` for each array, where ``ndim`` is the number of
      dimensions (axes) of the corresponding input array.

      If the positional arguments to ``fun`` are container (pytree) types, ``in_axes``
      must be a sequence with length equal to the number of positional arguments to
      ``fun``, and for each argument the corresponding element of ``in_axes`` can
      be a container with a matching pytree structure specifying the mapping of its
      container elements. In other words, ``in_axes`` must be a container tree prefix
      of the positional argument tuple passed to ``fun``. See this link for more detail:
      https://jax.readthedocs.io/en/latest/pytrees.html#applying-optional-parameters-to-pytrees

      Either ``axis_size`` must be provided explicitly, or at least one
      positional argument must have ``in_axes`` not None. The sizes of the
      mapped input axes for all mapped positional arguments must all be equal.

      Arguments passed as keywords are always mapped over their leading axis
      (i.e. axis index 0).

      See below for examples.

    out_axes: An integer, None, or (nested) standard Python container
      (tuple/list/dict) thereof indicating where the mapped axis should appear
      in the output. All outputs with a mapped axis must have a non-None
      ``out_axes`` specification. Axis integers must be in the range ``[-ndim,
      ndim)`` for each output array, where ``ndim`` is the number of dimensions
      (axes) of the array returned by the :func:`vmap`-ed function, which is one
      more than the number of dimensions (axes) of the corresponding array
      returned by ``fun``.
    axis_name: Optional, a hashable Python object used to identify the mapped
      axis so that parallel collectives can be applied.
    axis_size: Optional, an integer indicating the size of the axis to be
      mapped. If not provided, the mapped axis size is inferred from arguments.

  Returns:
    Batched/vectorized version of ``fun`` with arguments that correspond to
    those of ``fun``, but with extra array axes at positions indicated by
    ``in_axes``, and a return value that corresponds to that of ``fun``, but
    with extra array axes at positions indicated by ``out_axes``.

  For example, we can implement a matrix-matrix product using a vector dot
  product:

  >>> import jax.numpy as jnp
  >>>
  >>> vv = lambda x, y: jnp.vdot(x, y)  #  ([a], [a]) -> []
  >>> mv = vmap(vv, (0, None), 0)      #  ([b,a], [a]) -> [b]      (b is the mapped axis)
  >>> mm = vmap(mv, (None, 1), 1)      #  ([b,a], [a,c]) -> [b,c]  (c is the mapped axis)

  Here we use ``[a,b]`` to indicate an array with shape (a,b). Here are some
  variants:

  >>> mv1 = vmap(vv, (0, 0), 0)   #  ([b,a], [b,a]) -> [b]        (b is the mapped axis)
  >>> mv2 = vmap(vv, (0, 1), 0)   #  ([b,a], [a,b]) -> [b]        (b is the mapped axis)
  >>> mm2 = vmap(mv2, (1, 1), 0)  #  ([b,c,a], [a,c,b]) -> [c,b]  (c is the mapped axis)

  Here's an example of using container types in ``in_axes`` to specify which
  axes of the container elements to map over:

  >>> A, B, C, D = 2, 3, 4, 5
  >>> x = jnp.ones((A, B))
  >>> y = jnp.ones((B, C))
  >>> z = jnp.ones((C, D))
  >>> def foo(tree_arg):
  ...   x, (y, z) = tree_arg
  ...   return jnp.dot(x, jnp.dot(y, z))
  >>> tree = (x, (y, z))
  >>> print(foo(tree))
  [[12. 12. 12. 12. 12.]
   [12. 12. 12. 12. 12.]]
  >>> from jax import vmap
  >>> K = 6  # batch size
  >>> x = jnp.ones((K, A, B))  # batch axis in different locations
  >>> y = jnp.ones((B, K, C))
  >>> z = jnp.ones((C, D, K))
  >>> tree = (x, (y, z))
  >>> vfoo = vmap(foo, in_axes=((0, (1, 2)),))
  >>> print(vfoo(tree).shape)
  (6, 2, 5)

  Here's another example using container types in ``in_axes``, this time a
  dictionary, to specify the elements of the container to map over:

  >>> dct = {'a': 0., 'b': jnp.arange(5.)}
  >>> x = 1.
  >>> def foo(dct, x):
  ...  return dct['a'] + dct['b'] + x
  >>> out = vmap(foo, in_axes=({'a': None, 'b': 0}, None))(dct, x)
  >>> print(out)
  [1. 2. 3. 4. 5.]

  The results of a vectorized function can be mapped or unmapped. For example,
  the function below returns a pair with the first element mapped and the second
  unmapped. Only for unmapped results we can specify ``out_axes`` to be ``None``
  (to keep it unmapped).

  >>> print(vmap(lambda x, y: (x + y, y * 2.), in_axes=(0, None), out_axes=(0, None))(jnp.arange(2.), 4.))
  (Array([4., 5.], dtype=float32), 8.0)

  If the ``out_axes`` is specified for an unmapped result, the result is
  broadcast across the mapped axis:

  >>> print(vmap(lambda x, y: (x + y, y * 2.), in_axes=(0, None), out_axes=0)(jnp.arange(2.), 4.))
  (Array([4., 5.], dtype=float32), Array([8., 8.], dtype=float32, weak_type=True))

  If the ``out_axes`` is specified for a mapped result, the result is transposed
  accordingly.

  Finally, here's an example using ``axis_name`` together with collectives:

  >>> xs = jnp.arange(3. * 4.).reshape(3, 4)
  >>> print(vmap(lambda x: lax.psum(x, 'i'), axis_name='i')(xs))
  [[12. 15. 18. 21.]
   [12. 15. 18. 21.]
   [12. 15. 18. 21.]]

  See the :py:func:`jax.pmap` docstring for more examples involving collectives.
  zxVectorized version of {fun}. Takes similar arguments as {fun} but with additional array axes over which {fun} is mapped.z

Original documentation:

Nzvmap in_axes must be an int, None, or a tuple of entries corresponding to the positional arguments passed to the function, but got rB  c              3  \   K   | ]'}t          |          t          ht          j        v V  (d S r   typer-  rY   
spec_typesrh   r  s     rj   r   zvmap.<locals>.<genexpr>  s8      RRT!WW3x233RRRRRRrl   z]vmap in_axes must be an int, None, or (nested) container with those types as leaves, but got c              3  \   K   | ]'}t          |          t          ht          j        v V  (d S r   r  r  s     rj   r   zvmap.<locals>.<genexpr>  s8      SST!WW3x233SSSSSSrl   z^vmap out_axes must be an int, None, or (nested) container with those types as leaves, but got )r  c            	     x   t          t                    rOt                    t          |           k    r/t          dt                    dt          |                     t	          | |ft
          j                  \  }}t          j                  }t          j	        ||          \  }t          d|dfd          }nt          |||d          }	  t          j        |||fd	
          j        | }n# t
          j        $ r}	t          d                       }
t                       |
          }t!          |d           \  }}||	j                 \  }}t          dt%          |           d|	j         d|	j                   d d }	~	ww xY wt                       |          S )Nzvmap in_axes must be an int, None, or a tuple of entries corresponding to the positional arguments passed to the function, but got len(in_axes)=z, len(args)=is_leafzvmap in_axesr   T)kwsrW  c                 6    t          d                        S )Nvmap out_axes)r9   )rS  r   s   rj   <lambda>z&vmap.<locals>.vmap_f.<locals>.<lambda>  s    ,

HEE rl   )r  r  c                
    | d u S r   rf   r=  s    rj   r  z&vmap.<locals>.vmap_f.<locals>.<lambda>  s
    d rl   zat vmap out_axesz, got axis spec z  but output was batched on axis )r   tupler   r   r   rY   is_vmappabler   r   flatten_fun_for_vmapr9   _mapped_axis_sizebatchcall_wrappedSpecMatchErrorr   r"   leaf_idxr   dstsrc)ry   rz   r   r   r   flat_funin_axes_flat
axis_size_out_flatr@  out_axes_flatout_axes_fullpairsr   pathr   r   r  rx   r  rS  r  s                  @rj   vmap_fzvmap.<locals>.vmap_f  s(    '5!! Ac'llc$ii&?&? @"%g,,@ @36t99@ @ A A A 'f~x?TUUUIw
SA!6q'BBHh'14PPPL(4))#C)\6RR L
Iz<
E
E
E
E
E'   	i	!hh
 " L L L"?HHJJIIm$XXZZ??m'?R?RSSSheQaj!gdA A&,, A A A A9:A A B BGKLL ((**h///s    &D F!BFF!)r@   __doc__r%   no_axis_namer  r  r   r   r-  rY   r  r.  allr   rU   rO   r   r_   )rx   r  rS  r   r  r  r  r  s   ``````  rj   rW  rW    s   R I&[ 
//F
ckF#,#4d))D$8$8$E$E$&N  GnnG
/T']]sE.PH<O.PPP
 ^SZ^ ^ ^ _ _ _	RR[=Q=QRRR	R	R G
 F;BF F F G G G	SS[=R=RSSS	S	S H
 G;CG G G H H H 	V0 0 0 0 0 0 0 0 0 < 06 
arl   c                D   |s*t          ||          \  }}t           d| d|           d#dt          j        fdt	          |          D                       }t          |          dk    r|\  }|S |s d}	t          |	          d  dg}	t          ||          \  }}	  t          j        |           j        |i |}
n# t          t          f$ r d }
Y nw xY w|
=fdt          |          D             }fdt          |          D             }g ||n%fd|
j                                        D             fdt	          |          D             t          j        d D                       }|                                x^\  }}}}fdfd|D             ^}}fd|D             ^}}|dk    r |	                    d| d| d| d           n"|	                    d| d| d| d| d	           t	          |||          D ]Q\  }}\  }}|dk    r |	                    d| d| d| d           /|	                    d | d| d| d| d	           Rt          d!                    |	          d d"                   )$Nz\ wrapped function must be passed at least one argument containing an array, got empty *args=z and **kwargs=rq   strr   tuple[core.AxisSize, ...]r  r-  r   core.AxisSizec                    	 ||         S # t           t          f$ r?}|dk    r|dz   n| }t          |  d| d| dt          |           d| d
          |d }~ww xY w)Nr   r*  z. was requested to map its argument along axis z1, which implies that its rank should be at least z, but is only z (its shape is ))
IndexErrorr.  r   r   )rq   r   r  r@  min_ranks        rj   _get_axis_sizez)_mapped_axis_size.<locals>._get_axis_size  s    E4[	" E E E!QYYTEh = = = =<D= =U= =49= = => > DEEEs   
 A:AAc              3  `   K   | ](\  }}| t          j        |          |          V  )d S r   rE  r   rh   r=  dr  rq   s      rj   r   z$_mapped_axis_size.<locals>.<genexpr>  sN       M M#'1aam  .~dBHQKKCC>KmmmM Mrl   r*  z1 must have at least one non-None value in in_axesc                h    	 t          |                                           S # t          $ r Y dS w xY w)Nr   )r>   	str_shortr.  r  s    rj   _get_argument_typez-_mapped_axis_size.<locals>._get_argument_type  sC    "",,...   YYs    # 
11z5 got inconsistent sizes for array axes to be mapped:
c                R    g | ]#\  }}d t          |           d |           $S )ry   	 of type r   rh   pr=  r  s      rj   rk   z%_mapped_axis_size.<locals>.<listcomp>  sW     8 8 8a5 5 5//225 5 8 8 8rl   c                R    g | ]#\  }}d t          |           d |           $S )rz   r  r  r  s      rj   rk   z%_mapped_axis_size.<locals>.<listcomp>  sW     < < <17VAYY 7 711!447 7 < < <rl   c           
         g | ]:\  }}t          |          D ]%\  }}d | t          |           d |           &;S )z	argument r  )r!   r   )rh   rq   argr  r=  r  s        rj   rk   z%_mapped_axis_size.<locals>.<listcomp>  s     6 6 6T3/446 6 Q4T 46!99 4 4..q114 4 6 6 6 6rl   c                \    g | ](\  }}| t          j        |          |          nd )S r   r  r  s      rj   rk   z%_mapped_axis_size.<locals>.<listcomp>  sL     , , ,1a 89}~~dBHQKK333$ , , ,rl   c              3     K   | ]}||V  	d S r   rf   )rh   ss     rj   r   z$_mapped_axis_size.<locals>.<genexpr>  s"      #J#J!AMAMMMM#J#Jrl   c                x    t                    D ]\  }}t          j        ||           r|c S J | f            r   )	enumerater%   definitely_equal)sziisz	all_sizess      rj   _all_sizes_indexz+_mapped_axis_size.<locals>._all_sizes_index  sN    I&& 2 23		sB	'	'11!2y/!!!rl   c              3  @   K   | ]\  }} |                   V  d S r   rf   )rh   r  r   r  	key_pathss      rj   r   z$_mapped_axis_size.<locals>.<genexpr>  s8      GGur19--b112GGGGGGrl   c              3  @   K   | ]\  }} |                   V  d S r   rf   )rh   r  r   r  dimss      rj   r   z$_mapped_axis_size.<locals>.<genexpr>  s8      ==URd##B''(======rl   z  * one axis had size z: axis z of z;
z  * most axes (z of them) had size z, e.g. axis z  * some axes ( )rq   r  r   r  r  r-  r   r  )r   r   r%   dedup_referentsr  r   inspect	signaturebindr.  r!   	argumentsitemscollectionsCountermost_commonappendjoin)fntreevalsr  rq   ry   rz   r   r  r>  ba
args_pathskwargs_pathssize_countsctother_countscountsexexamplesaxaxsr  r  r  r  r  s      ``                @@@@@rj   r  r    s;   	 !$--LD&
 	M 	M04	M 	MDJ	M 	M  

E 
E 
E 
E 
 M M M M M+.tT??M M M M M%ZZ1__
CBI	 
D
D
DC
S//  
 	H	H	HI#d++,$	#	2			#T	4V	4	4BB
Z	    	BBBZ8 8 8 80668 8 8J< < < < 26 : :< < <L -*,|,II6 6 6 6"$,"4"4"6"66 6 6I, , , , ,tT??, , ,)##J#Jy#J#J#JJJ+%0%<%<%>%>>(2r\F" " " " "
 HGGGGGGG-"x=====f===("s1WWJJBBB2BB2BBBCCCCJJWWWWWWWPRWWWXXXh\:: [ [b"hr2	Qww	jjD"DDRDDRDDDEEEE	jjY2YY"YY"YYRTYYYZZZZ2773<<$%%%s   3C C)(C))r  rS  static_broadcasted_argnumsdevicesr   r  r   global_arg_shapesr  r  Sequence[xc.Device] | Noner  "tuple[tuple[int, ...], ...] | Nonec                   |	t          d          t          j        j        rddlm}
  |
| ||||||||	  	        S t          | ||||||||	  	        S )a*  Parallel map with support for collective operations.

  The purpose of :py:func:`pmap` is to express single-program multiple-data
  (SPMD) programs. Applying :py:func:`pmap` to a function will compile the
  function with XLA (similarly to :py:func:`jit`), then execute it in parallel
  on XLA devices, such as multiple GPUs or multiple TPU cores. Semantically it
  is comparable to :py:func:`vmap` because both transformations map a function
  over array axes, but where :py:func:`vmap` vectorizes functions by pushing the
  mapped axis down into primitive operations, :py:func:`pmap` instead replicates
  the function and executes each replica on its own XLA device in parallel.

  The mapped axis size must be less than or equal to the number of local XLA
  devices available, as returned by :py:func:`jax.local_device_count()` (unless
  ``devices`` is specified, see below). For nested :py:func:`pmap` calls, the
  product of the mapped axis sizes must be less than or equal to the number of
  XLA devices.

  .. note::
    :py:func:`pmap` compiles ``fun``, so while it can be combined with
    :py:func:`jit`, it's usually unnecessary.

  :py:func:`pmap` requires that all of the participating devices are identical.
  For example, it is not possible to use :py:func:`pmap` to parallelize a
  computation across two different models of GPU. It is currently an error for
  the same device to participate twice in the same `pmap`.

  **Multi-process platforms:** On multi-process platforms such as TPU pods,
  :py:func:`pmap` is designed to be used in SPMD Python programs, where every
  process is running the same Python code such that all processes run the same
  pmapped function in the same order. Each process should still call the pmapped
  function with mapped axis size equal to the number of *local* devices (unless
  ``devices`` is specified, see below), and an array of the same leading axis
  size will be returned as usual. However, any collective operations in ``fun``
  will be computed over *all* participating devices, including those on other
  processes, via device-to-device communication.  Conceptually, this can be
  thought of as running a pmap over a single array sharded across processes,
  where each process "sees" only its local shard of the input and output. The
  SPMD model requires that the same multi-process pmaps must be run in the same
  order on all devices, but they can be interspersed with arbitrary operations
  running in a single process.

  Args:
    fun: Function to be mapped over argument axes. Its arguments and return
      value should be arrays, scalars, or (nested) standard Python containers
      (tuple/list/dict) thereof. Positional arguments indicated by
      ``static_broadcasted_argnums`` can be anything at all, provided they are
      hashable and have an equality operation defined.
    axis_name: Optional, a hashable Python object used to identify the mapped
      axis so that parallel collectives can be applied.
    in_axes: A non-negative integer, None, or nested Python container thereof
      that specifies which axes of positional arguments to map over. Arguments
      passed as keywords are always mapped over their leading axis (i.e. axis
      index 0). See :py:func:`vmap` for details.
    out_axes: A non-negative integer, None, or nested Python container thereof
      indicating where the mapped axis should appear in the output. All outputs
      with a mapped axis must have a non-None ``out_axes`` specification
      (see :py:func:`vmap`).
    static_broadcasted_argnums: An int or collection of ints specifying which
      positional arguments to treat as static (compile-time constant).
      Operations that only depend on static arguments will be constant-folded.
      Calling the pmapped function with different values for these constants
      will trigger recompilation. If the pmapped function is called with fewer
      positional arguments than indicated by ``static_broadcasted_argnums`` then
      an error is raised. Each of the static arguments will be broadcasted to
      all devices. Arguments that are not arrays or containers thereof must be
      marked as static. Defaults to ().

      Static arguments must be hashable, meaning both ``__hash__`` and
      ``__eq__`` are implemented, and should be immutable.

    devices: This is an experimental feature and the API is likely to change.
      Optional, a sequence of Devices to map over. (Available devices can be
      retrieved via jax.devices()). Must be given identically for each process
      in multi-process settings (and will therefore include devices across
      processes). If specified, the size of the mapped axis must be equal to
      the number of devices in the sequence local to the given process. Nested
      :py:func:`pmap` s with ``devices`` specified in either the inner or outer
      :py:func:`pmap` are not yet supported.
    backend: This is an experimental feature and the API is likely to change.
      Optional, a string representing the XLA backend. 'cpu', 'gpu', or 'tpu'.
    axis_size: Optional; the size of the mapped axis.
    donate_argnums: Specify which positional argument buffers are "donated" to
      the computation. It is safe to donate argument buffers if you no longer need
      them once the computation has finished. In some cases XLA can make use of
      donated buffers to reduce the amount of memory needed to perform a
      computation, for example recycling one of your input buffers to store a
      result. You should not reuse buffers that you donate to a computation, JAX
      will raise an error if you try to.
      Note that donate_argnums only work for positional arguments, and keyword
      arguments will not be donated.

      For more details on buffer donation see the
      `FAQ <https://jax.readthedocs.io/en/latest/faq.html#buffer-donation>`_.

  Returns:
    A parallelized version of ``fun`` with arguments that correspond to those of
    ``fun`` but with extra array axes at positions indicated by ``in_axes`` and
    with output that has an additional leading array axis (with the same size).

  For example, assuming 8 XLA devices are available, :py:func:`pmap` can be used
  as a map along a leading array axis:

  >>> import jax.numpy as jnp
  >>>
  >>> out = pmap(lambda x: x ** 2)(jnp.arange(8))  # doctest: +SKIP
  >>> print(out)  # doctest: +SKIP
  [0, 1, 4, 9, 16, 25, 36, 49]

  When the leading dimension is smaller than the number of available devices JAX
  will simply run on a subset of devices:

  >>> x = jnp.arange(3 * 2 * 2.).reshape((3, 2, 2))
  >>> y = jnp.arange(3 * 2 * 2.).reshape((3, 2, 2)) ** 2
  >>> out = pmap(jnp.dot)(x, y)  # doctest: +SKIP
  >>> print(out)  # doctest: +SKIP
  [[[    4.     9.]
    [   12.    29.]]
   [[  244.   345.]
    [  348.   493.]]
   [[ 1412.  1737.]
    [ 1740.  2141.]]]

  If your leading dimension is larger than the number of available devices you
  will get an error:

  >>> pmap(lambda x: x ** 2)(jnp.arange(9))  # doctest: +SKIP
  ValueError: ... requires 9 replicas, but only 8 XLA devices are available

  As with :py:func:`vmap`, using ``None`` in ``in_axes`` indicates that an
  argument doesn't have an extra axis and should be broadcasted, rather than
  mapped, across the replicas:

  >>> x, y = jnp.arange(2.), 4.
  >>> out = pmap(lambda x, y: (x + y, y * 2.), in_axes=(0, None))(x, y)  # doctest: +SKIP
  >>> print(out)  # doctest: +SKIP
  ([4., 5.], [8., 8.])

  Note that :py:func:`pmap` always returns values mapped over their leading axis,
  equivalent to using ``out_axes=0`` in :py:func:`vmap`.

  In addition to expressing pure maps, :py:func:`pmap` can also be used to express
  parallel single-program multiple-data (SPMD) programs that communicate via
  collective operations. For example:

  >>> f = lambda x: x / jax.lax.psum(x, axis_name='i')
  >>> out = pmap(f, axis_name='i')(jnp.arange(4.))  # doctest: +SKIP
  >>> print(out)  # doctest: +SKIP
  [ 0.          0.16666667  0.33333334  0.5       ]
  >>> print(out.sum())  # doctest: +SKIP
  1.0

  In this example, ``axis_name`` is a string, but it can be any Python object
  with ``__hash__`` and ``__eq__`` defined.

  The argument ``axis_name`` to :py:func:`pmap` names the mapped axis so that
  collective operations, like :func:`jax.lax.psum`, can refer to it. Axis names
  are important particularly in the case of nested :py:func:`pmap` functions,
  where collective operations can operate over distinct axes:

  >>> from functools import partial
  >>> import jax
  >>>
  >>> @partial(pmap, axis_name='rows')
  ... @partial(pmap, axis_name='cols')
  ... def normalize(x):
  ...   row_normed = x / jax.lax.psum(x, 'rows')
  ...   col_normed = x / jax.lax.psum(x, 'cols')
  ...   doubly_normed = x / jax.lax.psum(x, ('rows', 'cols'))
  ...   return row_normed, col_normed, doubly_normed
  >>>
  >>> x = jnp.arange(8.).reshape((4, 2))
  >>> row_normed, col_normed, doubly_normed = normalize(x)  # doctest: +SKIP
  >>> print(row_normed.sum(0))  # doctest: +SKIP
  [ 1.  1.]
  >>> print(col_normed.sum(1))  # doctest: +SKIP
  [ 1.  1.  1.  1.]
  >>> print(doubly_normed.sum((0, 1)))  # doctest: +SKIP
  1.0

  On multi-process platforms, collective operations operate over all devices,
  including those on other processes. For example, assuming the following code
  runs on two processes with 4 XLA devices each:

  >>> f = lambda x: x + jax.lax.psum(x, axis_name='i')
  >>> data = jnp.arange(4) if jax.process_index() == 0 else jnp.arange(4, 8)
  >>> out = pmap(f, axis_name='i')(data)  # doctest: +SKIP
  >>> print(out)  # doctest: +SKIP
  [28 29 30 31] # on process 0
  [32 33 34 35] # on process 1

  Each process passes in a different length-4 array, corresponding to its 4
  local devices, and the psum operates over all 8 values. Conceptually, the two
  length-4 arrays can be thought of as a sharded length-8 array (in this example
  equivalent to jnp.arange(8)) that is mapped over, with the length-8 mapped
  axis given name 'i'. The pmap call on each process then returns the
  corresponding length-4 output shard.

  The ``devices`` argument can be used to specify exactly which devices are used
  to run the parallel computation. For example, again assuming a single process
  with 8 devices, the following code defines two parallel computations, one
  which runs on the first six devices and one on the remaining two:

  >>> from functools import partial
  >>> @partial(pmap, axis_name='i', devices=jax.devices()[:6])
  ... def f1(x):
  ...   return x / jax.lax.psum(x, axis_name='i')
  >>>
  >>> @partial(pmap, axis_name='i', devices=jax.devices()[-2:])
  ... def f2(x):
  ...   return jax.lax.psum(x ** 2, axis_name='i')
  >>>
  >>> print(f1(jnp.arange(6.)))  # doctest: +SKIP
  [0.         0.06666667 0.13333333 0.2        0.26666667 0.33333333]
  >>> print(f2(jnp.array([2., 3.])))  # doctest: +SKIP
  [ 13.  13.]
  Nzglobal_arg_shapes only worked with sharded_jit which has long been removed from JAX. Please migrate to pjit and remove global_arg_shapes from pmap.r   )pmapr  rS  r  r  r   r  r   )r   r$   pmap_shmap_mergert   jax.experimental.shard_mapr  	_cpp_pmap)rx   r   r  rS  r  r  r   r  r   r  r  s              rj   r  r  &  s    J "
	   " ///////4Y(+E#-	/ / / / 
	!;#	
% 	
% 	
% 	%rl   c                  ~    e Zd ZU ded<   ded<   ded<   ded<   d	ed
<   ded<   ded<   ded<   ded<   ded<   ded<   dS )PmapCallInfolu.WrappedFunr  r   r   zCallable[[], PyTreeDef]r   Sequence[Any]	flat_argszSequence[bool]r   zSequence[int | None]r  r-  local_axis_sizer   out_axes_thunkr  r  global_axis_sizer   is_explicit_global_axis_sizeNr   
__module____qualname____annotations__rf   rl   rj   r  r  '  s         ####    $$$$%%%%$$$$$$rl   r  r  r-  backend_namer  r  c                   t          j                    dk    r||| k    rt          d| d|  d          ||t          j        |d                   nt          j        |          |t          j                  dk    r| }ne|rt          |          }nS| t          j                  z  }t          fdt          t          j                            D                       sJ |S )z/Determine global_axis_size for multi-host pmap.r*  NzSpecified axis_size z" doesn't match received axis_size rB  r   c              3     K   | ]<}t          t          j        |                    t          j                  k    V  =d S r   )r   r  local_deviceslocal_device_count)rh   pir   s     rj   r   z(_get_global_axis_size.<locals>.<genexpr>M  s\       6 6 br7++
,
,0Eg0N0N
N6 6 6 6 6 6rl   )r  process_countr   get_device_backendr  r   r  range)r  
in_devicesr$  r  r   s       @rj   _get_global_axis_sizer.  5  sA    	A"2">/))
	(/ 	( 	($	( 	( 	() ) )  4#JqM22GGn\**G	  A%%(	 6Z(2+;G+D+DD 6 6 6 6"*733446 6 6 6 6 6 6 6 
rl   c
                V   |"t          |          dk    rt          d          t          |           }
t          j        |           }t          d|
|||	d          }t          j        |           }rt                    t          |          k    r;t          d dt          |           dt          |          dk    rd	nd
 d          fdt          t          |                    D             }t          |||          \  }}t          t                    rt          fd|D                       }n}n|}}t          ||	f          \  }}|r#t          j        j        st#          |d|          }ndt          |          z  }	 t          t%          |df||	fd                     }nY# t          $ rL t'          |df||	f          ^}} |d          }|j        \  }|dz  }|	r|dz  }|dz  }t          |          d w xY wt+          | |||d          }t-          |          \  }}t/          ||          \  }}t1          ||          \  }}t3          |||          }|d u}t5          ||||          }t7          |||||||||d nt          |          ||          S )Nr   z6'devices' argument to pmap must be non-empty, or None.r  rf   z0pmapped function has static_broadcasted_argnums=r   z positional argumentr*  r  r  z?. All static broadcasted arguments must be passed positionally.c                    g | ]}|v|	S rf   rf   )rh   r  static_broadcasted_tuples     rj   rk   z!_prepare_pmap.<locals>.<listcomp>g  s.     9 9 9777 777rl   c              3  (   K   | ]}|         V  d S r   rf   )rh   r  r  s     rj   r   z _prepare_pmap.<locals>.<genexpr>l  s'      ::'!*::::::rl   r   c                
    | d u S r   rf   r  s    rj   r  z_prepare_pmap.<locals>.<lambda>y  s
    AI rl   r  zpmap in_axesz

The 'full pytree' here is the tuple of arguments passed positionally to the pmapped function, and the value of `in_axes` must be a tree prefix of that tuple. But it was not a prefix.aG  

When some arguments are passed by keyword to the pmapped function, they are not included in the comparison to `in_axes`. Instead, each argument passed by keyword is mapped over its leading axis. See the description of `in_axes` in the `pmap` docstring: https://jax.readthedocs.io/en/latest/_autosummary/jax.pmap.html#jax.pmapz

Check that the value of the `in_axes` argument to `pmap` is a tree prefix of the tuple of arguments passed positionally to the pmapped function.)r  r   r   r  r   r  r  r  r  r  r  )r   r   rE   r#   fun_signaturerA   r   r   r   r,  r7   r   r  r   r$   rs   rt   r:   r   r    ry   r  rB   rC   r4   rD   r.  r  )rx   r  rS  r1  donate_tupler-  r$  r  ry   rz   r  r  dbgr   dyn_argnumsr   dyn_in_axesr   r   r  r@  r   r  r>  r  	res_pathsr  r  r   r  r  s    ` `                           rj   _prepare_pmapr:  S  s    J1 4 4
M
N
NNs#$S)))63	4+R	1 	1# 	l3! *
#$$D		11J=U J J'*4yyJ JIIMMSSrJ J JK K K
9 9 9 9eCII.. 9 9 9K!![$77KAx'5!! ::::k:::::kkkk 'kH&122-$ *&+1 *$\2w??NND		)N$);*:Xv<N2E2EG G G H HLL	 $ $ $;*Xv,>??EA	
>		B7DC L MC  Z	 Y Zc  $ %C S//t##$$ &c7D,OO/a,!Y#Ax00!^"1g..(HhY77(!*$!6*?J+7D D	x%' $%3#/&5%3&0&8ddeJ>O>O'73O

Q 

Q 

Q 
Qs   $F5 5AHc                   t          |            |t          j        |           n|}t          |          }t	          t          |          |          }t          d t          |          D                       st          d| d          t          d t          |          D                       st          d| d          |||fS )Nc              3  B   K   | ]}t          |          t          u V  d S r   r  r-  r  s     rj   r   z$_shared_code_pmap.<locals>.<genexpr>  s,      ::T!WW^::::::rl   z]pmap in_axes must be an int, None, or (nested) container with those types as leaves, but got rB  c              3  B   K   | ]}t          |          t          u V  d S r   r=  r  s     rj   r   z$_shared_code_pmap.<locals>.<genexpr>  s,      ;;T!WW^;;;;;;rl   z^pmap out_axes must be an int, None, or (nested) container with those types as leaves, but got )r@   r%   _TempAxisNamer=   r;   r  r   r.  )rx   r   r  r   r  rS  r1  r5  s           rj   _shared_code_pmapr@    s   
 )2):d %%%	)01KLL&.))+CE E, 
::[%9%9:::	:	: G
 F;BF F F G G G	;;[%:%:;;;	;	; H
 G;CG G G H H H 
,l	::rl   c                  ~    e Zd ZU ded<   ded<   ded<   ded<   ded<   d	ed
<   ded<   ded<   ded<   ded<   ded<   dS )_PmapFastpathDatar-  versionzxc.LoadedExecutablexla_executabler   
in_handlerout_handlerout_pytree_defSequence[xc.Device]input_deviceszSequence[sharding_specs.Index]input_indicesr  input_array_shardingsr  out_array_shardingsout_committedNr   rf   rl   rj   rB  rB    s         ,,,%%%%///$$$$////&&&&$$$$rl   rB  r  c          
         t           ||          \  ~~t           f	d            }	t          j         |	d t          j                  }
t                              |
            t                     |
          }t          fd            }t           f	d            ||_	        |_
        |S )Nc                 F  	 t          | |
  
        }|j        D ]}t          j        |           t	          |j        |j        |j        |j        |j	        |j
        j        |j        |j        
  
        }t          j        t           j        |j
        g|j        R i |\  }}}}}d }	t%          |t          j                  r$t!          j        |g|R i |}	 | |	|           }
n+ |t           j                            ||||                    }
|j        |
}} |            }t/          ||          }
d}|	bt%          |	t           j                  rHt3          j        t           j        |	          }|j         o |j         ot;          d |D                       }|ryt3          j        t           j        |	          }|j        }|j        }d |D             }d |D             }tA          d|j!        ||||j"        |j#        |j$        |j%        ||          }nd }|
|fS )N)
r   r   r  r  r  r  r  rq   r   r  Fc              3  J   K   | ]}t          |t          j                  V  d S r   )r   r   	ArrayImplrh   r=  s     rj   r   z0_cpp_pmap.<locals>.cache_miss.<locals>.<genexpr>  s.      ::AJq",''::::::rl   c                    g | ]	}|j         
S rf   )shardingrh   outs     rj   rk   z1_cpp_pmap.<locals>.cache_miss.<locals>.<listcomp>  s    >>>cS\>>>rl   c                    g | ]	}|j         
S rf   )
_committedrU  s     rj   rk   z1_cpp_pmap.<locals>.cache_miss.<locals>.<listcomp>  s    :::#s~:::rl   r*  )rC  rD  rE  rF  rG  rI  rJ  rK  r  rL  rM  )&r:  r  r&   rC  dictr  r  r  r  r  r  r   r   r  r%   map_bind_with_continuationr\   
xla_pmap_pr   	EvalTracexla_pmap_impl_lazyprocessr   r   ExecuteReplicatedtypingr   has_unordered_effectshas_host_callbacksr  rF  rE  rB  rD  r'  rJ  r   r  )ry   rz   r  r  paramsmap_bind_continuation	top_tracefun_tracersexecuterV  r   r  rG  use_fastpathexecute_replicatedrF  rE  rL  rM  fastpath_datar   r  r   r  r5  rx   r  rS  r1  s                        rj   
cache_missz_cpp_pmap.<locals>.cache_miss  s   c7H.F"GWv	/ 	/A {  #+	'Z '%&%C  F 	' 	@)*	@ 	@ 	@8>	@ 	@ <9dGV  $G)T^,, E'AwAAA&AAg!!''7"344cc!!
/
!
!)T7F
C
CE Ec ShHXZZN

2
2C Lz'43IJJ!;t'=wGG 44 	;"55	; 	:::::::   !;t'=wGG&2k%0j>>X>>>:::::m'+:!'"0"0 * 7)1%  mm mrl   c                <    t          j        |g| g          d         S r  )r\   
shard_args)r=  r  s     rj   r  z_cpp_pmap.<locals>.<lambda>%  s    4?A3,,Q/ rl   )pytree_registryc                 8     | i |                                 S r   )lower)ry   rz   traces     rj   rq  z_cpp_pmap.<locals>.lower+  s$    5$!&!!'')))rl   c                 d  	 t          | |
  
        }t          t          t          |j                            }t          j        |j        |j        |j	        |j
        |j        j        |j        |j        |
  
        \  }}}}}t          t
          j        |j        |j        |j	        |j
        |j        j        |j        |j        |j        ||||||          }	t%          j        |j        |          }
t%          j        ||
|j        j        |                                |	          S )N)r  r  r  rq   r  r  r   )r  r  r  rq   r  r   r  r   closed_jaxprr   replicasshardspci)r:  r   r   r>   r  r\   get_pmap_jaxprr  r  r  r  r   r  r  r	   lower_parallel_callabler   r  r   make_args_infor   Tracedr   )ry   rz   r  abstract_argsrt  
xc_backendru  rv  rw  lower_callable	args_infor   r  r   r  r5  rx   r  rS  r1  s              rj   rr  z_cpp_pmap.<locals>.trace/  s7   Wh 8,)T6	3 	3A /==>>M6:6I	
GY#a6H	Z '7 7 73L*h $aj)#a6H	Z '%&%C!  N %aiMMI=y!*2E~7 7 7rl   )r@  rO   rI   r  rP   default_registry_pmap_cache_clearsaddrU   rq  rr  )rx   r   r  rS  r  r  r   r  r   rl  cpp_mapped_fpmap_frq  r5  r1  rr  s   ```` ```     @@@rj   r  r    sq    7H	90.'7 73)%| !.G G G G G G G G G G G G <GR 	:///02 2 2, &&&5::l##&* * * * <* 7 7 7 7 7 7 7 7 7 7 7 7 <7> &,&,	-rl   tuple[Any, ...]c                j    t          |            t          t          j        |           |||          S )a  Computes a (forward-mode) Jacobian-vector product of ``fun``.

  Args:
    fun: Function to be differentiated. Its arguments should be arrays, scalars,
      or standard Python containers of arrays or scalars. It should return an
      array, scalar, or standard Python container of arrays or scalars.
    primals: The primal values at which the Jacobian of ``fun`` should be
      evaluated. Should be either a tuple or a list of arguments,
      and its length should be equal to the number of positional parameters of
      ``fun``.
    tangents: The tangent vector for which the Jacobian-vector product should be
      evaluated. Should be either a tuple or a list of tangents, with the same
      tree structure and array shapes as ``primals``.
    has_aux: Optional, bool. Indicates whether ``fun`` returns a pair where the
     first element is considered the output of the mathematical function to be
     differentiated and the second element is auxiliary data. Default False.

  Returns:
    If ``has_aux`` is ``False``, returns a ``(primals_out, tangents_out)`` pair,
    where ``primals_out`` is ``fun(*primals)``,
    and ``tangents_out`` is the Jacobian-vector product of
    ``function`` evaluated at ``primals`` with ``tangents``. The
    ``tangents_out`` value has the same Python tree structure and shapes as
    ``primals_out``. If ``has_aux`` is ``True``, returns a
    ``(primals_out, tangents_out, aux)`` tuple where ``aux``
    is the auxiliary data returned by ``fun``.

  For example:

  >>> import jax
  >>>
  >>> primals, tangents = jax.jvp(jax.numpy.sin, (0.1,), (0.2,))
  >>> print(primals)
  0.09983342
  >>> print(tangents)
  0.19900084
  rT  )r@   rV  r   r   )rx   primalstangentsr  s       rj   jvpr  W  s4    P 	bl3(G	D	D	DDrl   r  c                F   t          |t          t          f          rt          |t          t          f          s:t          dt	          |          j         dt	          |          j         d          t          |          \  }}t          |          \  }}||k    rt          d| d| d          t          ||          D ]\  }}	t          j	        t          |                    t          |	          k    rRt          dt          |           dt          j	        t          |                     dt          |	           d	          t          j        |          t          j        |	          k    r9t          d
t          j        |           dt          j        |	                     |sht          | |          \  }
}t          j        |
                              ||          \  }} |            }t%          ||          t%          ||          fS t'          | |          \  }
}t          j        |
d          \  }}|                    ||          \  }} |            \  }}t%          ||          t%          ||          t%          | |                      fS )z-Variant of jvp() that takes an lu.WrappedFun.zGprimal and tangent arguments to jax.jvp must be tuples or lists; found  and rB  zgprimal and tangent arguments to jax.jvp must have the same tree structure; primals have tree structure z& whereas tangents have tree structure zprimal and tangent arguments to jax.jvp do not match; dtypes must be equal, or in case of int/bool primal dtype the tangent dtype must be float0.Got primal dtype z and so expected tangent dtype z, but got tangent dtype z	 instead.zEjvp called with different primal and tangent shapes;Got primal shape z and tangent shape as TrT  )r   r  r   r.  r  r   r   r  r%   primal_dtype_to_tangent_dtyper  rE  r   r   r5   rX   r  r  r   r6   )rx   r  r  r  ps_flattree_defts_flat
tree_def_2r  tr  r   out_primalsout_tangentsout_aux_treesjvp_funr"  aux_trees                     rj   rV  rV    s   
Wudm
,
, V
Xt}
-
-V
 U!']]3U U:>x..:QU U U V V V #7++'8$X..':
 4>F4 4&04 4 4 5 5 5 '7## 
] 
]da)&))44q		AA < +1))< < ;F1IIFF	< <
 (.ayy< < < = = = 
x{{bhqkk!! \+-8A;;\ \NPhWXkk\ \ ] ] ] " 
 --c8<<Hh "x 0 0 = =gw O OKxzzH8[118\224 4 4CBBHm6(D111LGS ' 4 4Wg F FK&Hh8[118\228SSUU++- -rl   rT  Literal[False]tuple[Any, Callable]c                   d S r   rf   rx   r  r  s      rj   	linearizer    	     #rl   Literal[True]tuple[Any, Callable, Any]c                   d S r   rf   r  s      rj   r  r    r  rl   0tuple[Any, Callable] | tuple[Any, Callable, Any]c          	     $   t          |            t          j        |           }t          |          \  }}|rt	          ||          \  }}nt          ||          \  }}t          j        |g|R d|i^}}	}
}}|r |            \  }}n
 |            }t          ||          }t          t          t          j        |                    }t          t          t          |
|||f|	          |          }|r|\  }||t          ||          fS |\   ||fS )a  Produces a linear approximation to ``fun`` using :py:func:`jvp` and partial eval.

  Args:
    fun: Function to be differentiated. Its arguments should be arrays, scalars,
      or standard Python containers of arrays or scalars. It should return an
      array, scalar, or standard python container of arrays or scalars.
    primals: The primal values at which the Jacobian of ``fun`` should be
      evaluated. Should be a tuple of arrays, scalar, or standard Python
      container thereof. The length of the tuple is equal to the number of
      positional parameters of ``fun``.
    has_aux: Optional, bool. Indicates whether ``fun`` returns a pair where the first
      element is considered the output of the mathematical function to be linearized,
      and the second is auxiliary data. Default False.

  Returns:
    If ``has_aux`` is ``False``, returns a pair where the first element is the value of
    ``f(*primals)`` and the second element is a function that evaluates the
    (forward-mode) Jacobian-vector product of ``fun`` evaluated at ``primals`` without
    re-doing the linearization work. If ``has_aux`` is ``True``, returns a
    ``(primals_out, lin_fn, aux)`` tuple where ``aux`` is the auxiliary data returned by
    ``fun``.

  In terms of values computed, :py:func:`linearize` behaves much like a curried
  :py:func:`jvp`, where these two code blocks compute the same values::

    y, out_tangent = jax.jvp(f, (x,), (in_tangent,))

    y, f_jvp = jax.linearize(f, x)
    out_tangent = f_jvp(in_tangent)

  However, the difference is that :py:func:`linearize` uses partial evaluation
  so that the function ``f`` is not re-linearized on calls to ``f_jvp``. In
  general that means the memory usage scales with the size of the computation,
  much like in reverse-mode. (Indeed, :py:func:`linearize` has a similar
  signature to :py:func:`vjp`!)

  This function is mainly useful if you want to apply ``f_jvp`` multiple times,
  i.e. to evaluate a pushforward for many different input tangent vectors at the
  same linearization point. Moreover if all the input tangent vectors are known
  at once, it can be more efficient to vectorize using :py:func:`vmap`, as in::

    pushfwd = partial(jvp, f, (x,))
    y, out_tangents = vmap(pushfwd, out_axes=(None, 0))((in_tangents,))

  By using :py:func:`vmap` and :py:func:`jvp` together like this we avoid the stored-linearization
  memory cost that scales with the depth of the computation, which is incurred
  by both :py:func:`linearize` and :py:func:`vjp`.

  Here's a more complete example of using :py:func:`linearize`:

  >>> import jax
  >>> import jax.numpy as jnp
  >>>
  >>> def f(x): return 3. * jnp.sin(x) + jnp.cos(x / 2.)
  ...
  >>> jax.jvp(f, (2.,), (3.,))
  (Array(3.26819, dtype=float32, weak_type=True), Array(-5.00753, dtype=float32, weak_type=True))
  >>> y, f_jvp = jax.linearize(f, 2.)
  >>> print(y)
  3.2681944
  >>> print(f_jvp(3.))
  -5.007528
  >>> print(f_jvp(4.))
  -6.676704
  r  )r@   r   r   r   r6   r5   rX   r  r   r   r   r%   r<  r   r	   _lift_linearized)rx   r  r  r   primals_flatr   r   r   r  	out_pvalsr  r  	maybe_auxr  out_primal_pyprimal_avals
lifted_jvpr"  s                     rj   r  r    sS   F l3!&w//, =1!W==K0G<<K68l73 73 73 73*173 733+y%) !HhhxzzH ;77-c$-6677,w/ '2I? ?@FH H* %ES*nXs&C&CCC	B*$$rl   c                <      fd}t          |||          S )Nc                 v   t          t          t          j        |                     }t	          
|          D ]A\  }}t          j        |                                |          st          d| d|           Bt          g| R  }t          |          fd	D             }t          d           J |S )Nz_linearized function called on tangent values inconsistent with the original primal values: got z for primal aval c                ~    g | ]9}|                                 r|                                nt                    :S rf   )is_known	get_knownnext)rh   pvaltangents_out_s     rj   rk   z1_lift_linearized.<locals>.fun.<locals>.<listcomp>  sM     ' ' ' %)MMOOL   m9L9L ' ' 'rl   )r   r   r%   r<  r  
typecompatat_least_vspacer   r1   iterr  )r  tangent_avalsprimal_avaltangent_avaltangents_outfull_outr  r  r  r  r  s         @rj   rx   z_lift_linearized.<locals>.fun  s   T]H5566M%(}%E%E N N!\_[88::LII N M ,M M?JM M N N 	NN eV7h777L&&M' ' ' '%' ' 'Ht$$,,,Orl   )r?   )r  r  io_treer  r  py_argsrx   s   `` ``  rj   r  r    sB            
!gw	7	77rl   c                l   t          |          dk    r(d|  dt          |           d|  d}t          |          |\  }|\  }}t          |          \  }	}
|
|k    rt          d|
 d|           t	          |	|          D ]\  }}t          |          }|                                }t          j        ||          sat          ||          sQt          d|
                                 d	|
                                 d
|  d|
                                            ||	 }t          ||          S )Nr*  z.The function returned by `jax.vjp` applied to z was called with z arguments, but functions returned by `jax.vjp` must be called with a single argument corresponding to the single value returned by a   (even if that returned value is a tuple or other container).

For example, if we have:

  def f(x):
    return (x, x)
  _, f_vjp = jax.vjp(f, 1.0)

the function `f` returns a single tuple as output, and so we call `f_vjp` with a single tuple as its argument:

  x_bar, = f_vjp((2.0, 2.0))

If we instead call `f_vjp(2.0, 2.0)`, with the values 'splatted out' as arguments rather than in a tuple, this error can arise.z;unexpected tree structure of argument to vjp function: got z, but expected to match zIunexpected JAX type (e.g. shape/dtype) for argument to vjp function: got z, but expected z2 because the corresponding output of the function z had JAX type )r   r.  r   r   r  r>   r  r%   r  _temporary_dtype_exceptionr  r   )rq   out_primal_avalsr  rx   py_args_r>  r  in_tree_expectedr   ry   r   r  r?  ct_avalct_aval_expectedr7  s                   rj   _vjp_pullback_wrapperr  !  s   ]]aMD M Mx==M M ,0M M MC& C..('&Hw''-$   
 P#P P=MP P Q Q Qt-.. 	! 	!ic4 %%G++--OG%566 !&w0@AA! ""$$   5E5O5O5Q5Q   >B    ^^   ! ! !
 	T
#	#	&	&&rl   c                    t          | t          j                  r:t          |t          j                  r | j        |j        k    o|j        t
          k    S dS NF)r   r%   r2   r   r   float0)r   a_s     rj   r  r  K  sK    4#$$ 6B8H)I)I 67bh528v#55	rl   )r  r  Callable[..., T]r  tuple[T, Callable]c                   d S r   rf   rx   r  r  r  s       rj   vjpr  P  s	    
 #rl   )r  Callable[..., tuple[T, U]]tuple[T, Callable, U]c                   d S r   rf   r  s       rj   r  r  W  s	     #rl   c                   |rt          d          ~t          |            t          t          j        |           g|R d|iS )a  Compute a (reverse-mode) vector-Jacobian product of ``fun``.

  :py:func:`grad` is implemented as a special case of :py:func:`vjp`.

  Args:
    fun: Function to be differentiated. Its arguments should be arrays, scalars,
      or standard Python containers of arrays or scalars. It should return an
      array, scalar, or standard Python container of arrays or scalars.
    primals: A sequence of primal values at which the Jacobian of ``fun``
      should be evaluated. The number of ``primals`` should be equal to the
      number of positional parameters of ``fun``. Each primal value should be
      an array, a scalar, or a pytree (standard Python containers) thereof.
    has_aux: Optional, bool. Indicates whether ``fun`` returns a pair where the
     first element is considered the output of the mathematical function to be
     differentiated and the second element is auxiliary data. Default False.

  Returns:
    If ``has_aux`` is ``False``, returns a ``(primals_out, vjpfun)`` pair, where
    ``primals_out`` is ``fun(*primals)``. If ``has_aux`` is ``True``, returns a
    ``(primals_out, vjpfun, aux)`` tuple where ``aux`` is the auxiliary data
    returned by ``fun``.

    ``vjpfun`` is a function from a cotangent vector with the same shape as
    ``primals_out`` to a tuple of cotangent vectors with the same number and
    shapes as ``primals``, representing the vector-Jacobian product of ``fun``
    evaluated at ``primals``.

  >>> import jax
  >>>
  >>> def f(x, y):
  ...   return jax.numpy.sin(x), jax.numpy.cos(y)
  ...
  >>> primals, f_vjp = jax.vjp(f, 0.5, 1.0)
  >>> xbar, ybar = f_vjp((-0.7, 0.3))
  >>> print(xbar)
  -0.61430776
  >>> print(ybar)
  -0.2524413
  z)reduce_axes argument to vjp is deprecatedr  )r$  r@   r0  r   r   r  s       rj   r  r  \  sg    T  K
I
J
JJ	l3
4!
4 
4 
4+2
4 
4 4rl   c          	        t          |          \  }}|D ]}t          j        |           |s6t          | |          \  }}t	          j        ||          \  }}	 |            }n;t          | |          \  }}
t	          j        ||d          \  }}	} |
            \  }}t          t          |          }t          ||          }t          t          t          | j        |||f          |	          }|s||fS ||t          ||          fS )z-Variant of vjp() that takes an lu.WrappedFun.TrT  )r   r&   rC  r5   rX   r  r6   r   r>   r   r   r	   r  r   )rx   r  r  r  r   r  r  r   r  r  r  r"  r  r  r  r8  s                   rj   r0  r0    s0   &w//,22c8-c2222	 )-c7;;Hhvh55KxzzHH3CAAHmF8\4HHHKc&Hh+[99 ;77-70#,+h-@B BCFH H&	 @&  &.3"?"???rl   c                  |rt          d          ~t          |          \  }t          t          j        |                     \  }t          t          |          t          t          j                  }t          t          j
        j                  }t          j        ||d          \  }}t          j        dgt          j                  z  d          \  }	t!          |          \  }	t          t          j                  }
t#          d ||
z   D                       s2t#          d ||
z   D                       st%          d| d|
 d          t&          fd	            }t)          ||          S )
a  Transpose a function that is promised to be linear.

  For linear functions, this transformation is equivalent to :py:func:`vjp`, but
  avoids the overhead of computing the forward pass.

  The outputs of the transposed function will always have the exact same dtypes
  as ``primals``, even if some values are truncated (e.g., from complex to
  float, or from float64 to float32). To avoid truncation, use dtypes in
  ``primals`` that match the full range of desired outputs from the transposed
  function. Integer dtypes are not supported.

  Args:
    fun: the linear function to be transposed.
    *primals: a positional argument tuple of arrays, scalars, or (nested)
      standard Python containers (tuples, lists, dicts, namedtuples, i.e.,
      pytrees) of those types used for evaluating the shape/dtype of
      ``fun(*primals)``. These arguments may be real scalars/ndarrays, but that
      is not required: only the ``shape`` and ``dtype`` attributes are accessed.
      See below for an example. (Note that the duck-typed objects cannot be
      namedtuples because those are treated as standard Python containers.)

  Returns:
    A callable that calculates the transpose of ``fun``. Valid input into this
    function must have the same shape/dtypes/structure as the result of
    ``fun(*primals)``. Output will be a tuple, with the same
    shape/dtypes/structure as ``primals``.

  >>> import jax
  >>> import types
  >>>
  >>> f = lambda x, y: 0.5 * x - 0.5 * y
  >>> scalar = types.SimpleNamespace(shape=(), dtype=np.dtype(np.float32))
  >>> f_transpose = jax.linear_transpose(f, scalar, scalar)
  >>> f_transpose(1.0)
  (Array(0.5, dtype=float32), Array(-0.5, dtype=float32))
  z/reduce_axes argument to transpose is deprecatedT)instantiatec              3  T   K   | ]#}t          j        |t          j                  V  $d S r   )r*   rD  rE  rJ  rh   r  s     rj   r   z#linear_transpose.<locals>.<genexpr>  s1      OO1f2:..OOOOOOrl   c              3  T   K   | ]#}t          j        |t          j                  V  $d S r   )r*   rD  rE  rH  r  s     rj   r   z#linear_transpose.<locals>.<genexpr>  sE       2 2 "1bj11 2 2 2 2 2 2rl   zslinear_transpose only supports [float or complex] -> [float or complex], and integer -> integer functions, but got z -> rB  c                   t          |          \  }} 
            |k    rt          d 
             d|           t          t          t          j        	|                    st          d	 d|           d D             }t          j        d| ||          }t          t          j        |          }t          |          S )Nz8cotangent tree does not match function output, expected z	 but got z8cotangent type does not match function output, expected c                6    g | ]}t          j        |          S rf   )rX   UndefinedPrimalr   s     rj   rk   z<linear_transpose.<locals>.transposed_fun.<locals>.<listcomp>  s#    777r!!$$777rl   T)
r   r.  r  r   r%   	typecheckrX   backward_passinstantiate_zerosr   )constout_cotangentout_cts	out_tree2dummiesin_ctsin_avalsr   r  r  r   s         rj   transposed_funz(linear_transpose.<locals>.transposed_fun  s
   %m44GYxzzY C"*(**C C7@C C D D Ds4>9g6677 A @"+@ @6=@ @ A A A77h777GeT5'7CCF%v..F'6***rl   )r$  r   r5   r   r   r   r>   r*   r   r   
PartialValr   trace_to_jaxpr_nounits	dce_jaxprr   outvarsrQ   r  r.  rO   r   )rx   r  r  r  r  	in_dtypesin_pvalsr  r  r   
out_dtypesr  r  r   r  r  r   s               @@@@@rj   linear_transposer    s   J  Q
O
P
PP&w//,+BL,=,=wGG(H#\22(&,)))&11(5hBFH H H%E\%$#em*<*<!<dCC(%	"",)Q6<++*
OO	J8NOOO
O
O = 2 2#j02 2 2 2 2=  <(< <.8< < < = = = + + + + + + + + <+ 
	'	''rl   list[pe.AbstractedAxesSpec]c                <    |rt           d }t          | ||          S )Nc                    t          | t                    r!t          |                                           p%t          | t                    ot          | d           S )Nc                
    | d u S r   rf   r  s    rj   r  z3_flat_axes_specs.<locals>.ax_leaf.<locals>.<lambda>  s
    Q$Y rl   )r   rY  r   valuesr  )r  s    rj   ax_leafz!_flat_axes_specs.<locals>.ax_leaf  sP    q$:Jqxxzz$:$: Hq%  GZ3F3F%G%GIrl   )r$  r   )r   ry   rz   r  s       rj   _flat_axes_specsr    s4    &&&I I I 
/4	9	99rl   .Callable[..., core.ClosedJaxpr]c                    d S r   rf   rx   r   r   r   r   s        rj   
make_jaxprr    	     #rl   +Callable[..., tuple[core.ClosedJaxpr, Any]]c                    d S r   rf   r  s        rj   r  r  	  r  rl   >Callable[..., core.ClosedJaxpr | tuple[core.ClosedJaxpr, Any]]c                |    	 t                      t          j                    n# t          $ r t	                      Y nw xY wt                     t           fd                        }d|_        t           d          rd j	         d|_	        t           d          rd j
         d|_
        |S )aZ
  Creates a function that produces its jaxpr given example args.

  Args:
    fun: The function whose ``jaxpr`` is to be computed. Its positional
      arguments and return value should be arrays, scalars, or standard Python
      containers (tuple/list/dict) thereof.
    static_argnums: See the :py:func:`jax.jit` docstring.
    axis_env: Optional, a sequence of pairs where the first element is an axis
      name and the second element is a positive integer representing the size of
      the mapped axis with that name. This parameter is useful when lowering
      functions that involve parallel communication collectives, and it
      specifies the axis name/size environment that would be set up by
      applications of :py:func:`jax.pmap`.
    return_shape: Optional boolean, defaults to ``False``. If ``True``, the
      wrapped function returns a pair where the first element is the
      ``ClosedJaxpr`` representation of ``fun`` and the second element is a
      pytree with the same structure as the output of ``fun`` and where the
      leaves are objects with ``shape`` and ``dtype`` attributes representing
      the corresponding types of the output leaves.

  Returns:
    A wrapped version of ``fun`` that when applied to example arguments returns
    a ``ClosedJaxpr`` representation of ``fun`` on those arguments. If the
    argument ``return_shape`` is ``True``, then the returned function instead
    returns a pair where the first element is the ``ClosedJaxpr``
    representation of ``fun`` and the second element is a pytree representing
    the structure, shape, dtypes, and named shapes of the output of ``fun``.

  A ``jaxpr`` is JAX's intermediate representation for program traces. The
  ``jaxpr`` language is based on the simply-typed first-order lambda calculus
  with let-bindings. :py:func:`make_jaxpr` adapts a function to return its
  ``jaxpr``, which we can inspect to understand what JAX is doing internally.
  The ``jaxpr`` returned is a trace of ``fun`` abstracted to
  :py:class:`ShapedArray` level. Other levels of abstraction exist internally.

  We do not describe the semantics of the ``jaxpr`` language in detail here, but
  instead give a few examples.

  >>> import jax
  >>>
  >>> def f(x): return jax.numpy.sin(jax.numpy.cos(x))
  >>> print(f(3.0))
  -0.83602
  >>> jax.make_jaxpr(f)(3.0)
  { lambda ; a:f32[]. let b:f32[] = cos a; c:f32[] = sin b in (c,) }
  >>> jax.make_jaxpr(jax.grad(f))(3.0)
  { lambda ; a:f32[]. let
      b:f32[] = cos a
      c:f32[] = sin a
      _:f32[] = sin b
      d:f32[] = cos b
      e:f32[] = mul 1.0 d
      f:f32[] = neg e
      g:f32[] = mul f c
    in (g,) }
  c            	     .   t                      5 }pg D ].\  }}|                    t          j        ||d                      / t	                    j        | i |}d d d            n# 1 swxY w Y   |j        rXt          |j        |j        g          \  }}t          j
        |j        j        |j                  }t          j        ||          }	n|j        }	r5d |	j        D             }
|	t          t          |j                  |
          fS |	S )N)r   r   c                B    g | ]}t          |j        |j                  S rf   r   )rh   os     rj   rk   z4make_jaxpr.<locals>.make_jaxpr_f.<locals>.<listcomp>c	  s'    IIIAagqw//IIIrl   )r   r   r%   r   r   rr  _num_constsrV   
_args_flatr   convert_invars_to_constvarsr  r   r  r   r   out_info)ry   rz   r   r   r   tracedr  r   jaxpr_r  rV  r   r   rx   r   r   s              rj   make_jaxpr_fz make_jaxpr.<locals>.make_jaxpr_fQ	  s    
 K%^ I I/)TD0D$GGHHHH:s3~#24 4 4494KCIK KfK K K K K K K K K K K K K K K  V.1C0DEEifa-fl.@.4.@B Bfvv..eele IIIIIIcN>&/#B#BCHHHHLs   AA--A14A1jaxr"  zmake_jaxpr(r  r   )hashweakrefrefr.  r	   rU   rO   r!  rm   r"  r   )rx   r   r   r   r   r  s   ````` rj   r  r  	  s    ~IIIK	   
#,,CCC 	::        < :( ",S.!! B Ac.> A A ALS* :9#,999L	s   #+ AASharding | Nonec                ,   | | S t          |t          j                  r|j        S t          |t          j                  rTt	          j        |          }t          |t                    r+t          |j        t          j                  r|j        j        S d S r   )	r   r(   rQ  rT  r%   Tracerr<  r3   val)r  r=  r?  s      rj   _infer_src_shardingr  n	  s    _J5?## :!T[!! =D$&& :dh+P+P X	rl   i   )maxsizec                   |?t          |t          j        t          t          t
          f          st          d|           t          |t                    rrt          | t          j                  rt          j	        } t          |t                    st          j        |f| fd dd           |                    | j                   d S d S )Nz`jax.device_put` only accepts `None`, `jax.sharding.Sharding`, `jax.Device`, `Layout` or a pytree of these values. Received invalid value: zdevice_put argsF)allow_uneven_sharding)r   r   DevicerJ   rM   rL   r   r%   AbstractTokentoken_shaped_arrayrK   r/   pjit_check_aval_shardingshard_shaper   )r?  r  s     rj   _check_shardingr  }	  s    m
QHf6JK
L
L 
		 	      8 $*++ %$da&& O
#$0O O O OMM$* rl   )r  ANone | xc.Device | Sharding | Layout | Any | TransferToMemoryKindr  c                  t          j                    5  t          |           \  }}|'t          |t          j        t          t          f          r|gt          |          z  }nt          d||          }'t          t          j        t          t          f          rfd|D             }n4t          d|          }t          t          t          ||                    }t          ||          D ]"\  }}t          t          |          |           #t!          j        j        |||d}	t'          ||	          cddd           S # 1 swxY w Y   dS )a  Transfers ``x`` to ``device``.

  Args:
    x: An array, scalar, or (nested) standard Python container thereof.
    device: The (optional) :py:class:`Device`, :py:class:`Sharding`, or a
      (nested) :py:class:`Sharding` in standard Python container (must be a tree
      prefix of ``x``), representing the device(s) to which ``x`` should be
      transferred. If given, then the result is committed to the device(s).

  Returns:
    A copy of ``x`` that resides on ``device``.

  If the ``device`` parameter is ``None``, then this operation behaves like the
  identity function if the operand is on any device already, otherwise it
  transfers the data to the default device, uncommitted.

  For more details on data placement see the
  :ref:`FAQ on data placement <faq-data-placement>`.

  This function is always asynchronous, i.e. returns immediately without
  blocking the calling Python thread until any transfers are completed.
  Nzdevice_put devicec                0    g | ]}t          |          S rf   )r  )rh   xfr  s     rj   rk   zdevice_put.<locals>.<listcomp>	  s$    @@@2%c2..@@@rl   zdevice_put source)r  srcs)r$   explicit_device_put_scoper   r   r   r  rJ   rL   r   r9   r   r   r  r  r  r>   r&   device_put_pr  r   )
r=  r   r  x_flatr  device_flatsrc_flatr  r  r  s
     `       rj   
device_putr"  	  s   4 ')) - -"1ooOFG6BIx1EFGG 	Hs6{{*kk !4gvFFk3H.BCDD 	@@@@@@@hh17C@@hc-x@@AAhV[)) 1 1A(,,a0000$)	8  H '8,,)- - - - - - - - - - - - - - - - - -s   D&EEErv  r  rH  c                   t          | t                    st          dt          |                      t	          |           t	                    k    r0t          dt	          |            dt	                     d          fd}t          j                    5  t          |g| R  cddd           S # 1 swxY w Y   dS )a  Transfer array shards to specified devices and form Array(s).

  Args:
    shards: A sequence of arrays, scalars, or (nested) standard Python
      containers thereof representing the shards to be stacked together to form
      the output. The length of ``shards`` must equal the length of ``devices``.
    devices: A sequence of :py:class:`Device` instances representing the devices
      to which corresponding shards in ``shards`` will be transferred.

  This function is always asynchronous, i.e. returns immediately.

  Returns:
    A Array or (nested) Python container thereof representing the
    elements of ``shards`` stacked together, with each shard backed by physical
    device memory specified by the corresponding entry in ``devices``.

  Examples:
    Passing a list of arrays for ``shards`` results in a sharded array
    containing a stacked version of the inputs:

    >>> import jax
    >>> devices = jax.local_devices()
    >>> x = [jax.numpy.ones(5) for device in devices]
    >>> y = jax.device_put_sharded(x, devices)
    >>> np.allclose(y, jax.numpy.stack(x))
    True

    Passing a list of nested container objects with arrays at the leaves for
    ``shards`` corresponds to stacking the shards at each leaf. This requires
    all entries in the list to have the same tree structure:

    >>> x = [(i, jax.numpy.arange(i, i + 4)) for i in range(len(devices))]
    >>> y = jax.device_put_sharded(x, devices)
    >>> type(y)
    <class 'tuple'>
    >>> y0 = jax.device_put_sharded([a for a, b in x], devices)
    >>> y1 = jax.device_put_sharded([b for a, b in x], devices)
    >>> np.allclose(y[0], y0)
    True
    >>> np.allclose(y[1], y1)
    True

  See Also:
    - device_put
    - device_put_replicated
  z:device_put_sharded `shards` input must be a sequence; got zlen(shards) = z must equal len(devices) = rB  c            	        d | D             }t          d t          |d d         |dd                    D                       sPt          d t          |d d         |dd                    D                       \  }}t          d| d| d          |d	                             t          	          f|d	         j        z   
          }t          j        |j                  }t          t          j        	          |          }t          j        |j        t          j                  r"|j        j                            | ||	          S t$          j        j        r]g }| D ]W}t+          |t          j        t.          j        f          st          j        |          }|                    |d                     Xn| }t7          j        |||t;          	                    S )Nc                Z    g | ](}t          j        t          j        |                    )S rf   )r%   raise_to_shapedr<  rR  s     rj   rk   zCdevice_put_sharded.<locals>._device_put_sharded.<locals>.<listcomp>	  s-    @@@T!$-"2"233@@@rl   c              3  (   K   | ]\  }}||k    V  d S r   rf   rh   a1a2s      rj   r   zBdevice_put_sharded.<locals>._device_put_sharded.<locals>.<genexpr>	  s*      AAFBrRxAAAAAArl   r   r*  c              3  0   K   | ]\  }}||k    ||fV  d S r   rf   r(  s      rj   r   zBdevice_put_sharded.<locals>._device_put_sharded.<locals>.<genexpr>	  s;       ! !RRxx Hxxx! !rl   zVthe shards passed to device_put_sharded must have consistent shape and dtype, but got r  rB  r   )r   )r  r  r  r   updater   r   r,   create_pmap_sharding_specrK   rE  r(   r*   rD  r   rG  _rulesdevice_put_shardedr$   pmap_no_rank_reductionrt   r   r  r)   Arrayasarrayr  r\   batched_device_putr   )
xsr   r)  r*  stacked_avalsharding_specrT  ysr=  r  s
            rj   _device_put_shardedz/device_put_sharded.<locals>._device_put_sharded	  s   @@R@@@EAAc%*eABBi&@&@AAAAA N ! !3uSbSz59+E+E ! ! ! ! !fb" M>@M MGIM M M N N N8??#g,,58>)I?JJL"<\=OPPMBHW--}==H+V_== _&99"lHV]^^^$* b  !!bj)/:;; 	jmm!
		!D'
 b"<2tG}}MMMrl   N)	r   r   r.  r  r   r   r$   r  r   )rv  r  r8  s    ` rj   r/  r/  	  sA   b 
FH	%	% ,
 + LL+ + , , ,[[CLL  
 7c&kk 7 7'*7||7 7 7 8 8 8N N N N N. ')) 2 2'1&1112 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2s   B88B<?B<c                    t          t                    rst          d          fd}t          j                    5  t          ||           cddd           S # 1 swxY w Y   dS )a  Transfer array(s) to each specified device and form Array(s).

  Args:
    x: an array, scalar, or (nested) standard Python container thereof
      representing the array to be replicated to form the output.
    devices: A sequence of :py:class:`Device` instances representing the devices
      to which ``x`` will be transferred.

  This function is always asynchronous, i.e. returns immediately.

  Returns:
    An Array or (nested) Python container thereof representing the
    value of ``x`` broadcasted along a new leading axis of size
    ``len(devices)``, with each slice along that new leading axis backed by
    memory on the device specified by the corresponding entry in ``devices``.

  Examples:
    Passing an array:

    >>> import jax
    >>> devices = jax.local_devices()
    >>> x = jax.numpy.array([1., 2., 3.])
    >>> y = jax.device_put_replicated(x, devices)
    >>> np.allclose(y, jax.numpy.stack([x for _ in devices]))
    True

  See Also:
    - device_put
    - device_put_sharded
  zJ`devices` argument to `device_put_replicated must be a non-empty sequence.c           
        t          j        t                    t           j        dt          j        t          j        |                               }t          |t                    sJ t          j	        |j
                  }t          j        j        r`t          | t          j        t           j        f          rt%          | d          d                   }n3t%          | d                   d          }nt%          | d                   }t'          t          j                  |          }t+          j        |j        t*          j                  r"|j        j                            |||          S t          t7          j        |                    dk    sJ t;          j        |||gt                    z            S )Nr   r*  )r%   unmapped_avalr   r  r&  r<  r   r2   r,   r-  r   r$   r0  rt   rE  r  r)   r1  r"  rK   r(   r*   rD  r   rG  r.  device_put_replicatedr]   aval_to_xla_shapesr\   r3  )r=  r?  r6  bufrT  r  s        rj   _device_put_replicatedz5device_put_replicated.<locals>._device_put_replicated4
  so   c'llD,=q"24=3C3CDDF FDdK((((("<TZHHM$* &	A
IO4	5	5 .4'!*--GAJ''-q'!*%%cBHW--}==HV_55 SZ44S$'RRRs%d++,,1111"4C53w<<3GQQQrl   N)r   r   r   r$   r  r   )r=  r  r?  s    ` rj   r<  r<  
  s    > 
GX	&	& .g .
 - . . .R R R R R$ ')) / /*A../ / / / / / / / / / / / / / / / / /s    AA!$A!c                    t          | t          j                  r| S 	 | j        } |            S # t          $ r | cY S w xY wr   )r   r%   r  	__array__AttributeError)r=  toarrays     rj   _device_getrD  K
  s[    4; HkG 799 
   HHHs   / >>c                    t          j                    5  t          |           D ]'}	 |                                 # t          $ r Y $w xY wt          t          |           cddd           S # 1 swxY w Y   dS )a  Transfer ``x`` to host.

  If ``x`` is a pytree, then the individual buffers are copied in parallel.

  Args:
    x: An array, scalar, Array or (nested) standard Python container thereof
      representing the array to be transferred to host.

  Returns:
    An array or (nested) Python container thereof representing the
    value of ``x``.

  Examples:
    Passing a Array:

    >>> import jax
    >>> x = jax.numpy.array([1., 2., 3.])
    >>> jax.device_get(x)
    array([1., 2., 3.], dtype=float32)

    Passing a scalar (has no effect):

    >>> jax.device_get(1)
    1

  See Also:
    - device_put
    - device_put_sharded
    - device_put_replicated
  N)r$   explicit_device_get_scoper   copy_to_host_asyncrB  r   rD  )r=  r\  s     rj   
device_getrH  U
  s    > ')) $ $^^  	   K##$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $s1   A-<A-
A	A-A		A--A14A1c                      e Zd ZdZg dZi ZddZ ed           Z ed           Z	ed             Z
d Zd	 ZeZd
 Zd ZdS )r   a=  A container for the shape, dtype, and other static attributes of an array.

  ``ShapeDtypeStruct`` is often used in conjunction with :func:`jax.eval_shape`.

  Args:
    shape: a sequence of integers representing an array shape
    dtype: a dtype-like object
    sharding: (optional) a :class:`jax.Sharding` object
  )r   r   rT  _dllNc                V   ~t          |          | _        |t          d          t          j        |t          j                  r|nt          j        |          | _        |?t          |t          t          f          s#t          d| dt          |           d          t          |t                    r,t          |j        t                    rt          d|           t          |t                    r|j        n|| _        t          |t                    r|j        nd | _        d S )Nz*ShapeDtypeStruct: dtype must be specified.zcsharding should be an instance of `jax.sharding.Sharding` or `jax.experimental.layout.Layout`. Got r  rB  zg`DeviceLocalLayout.AUTO` cannot be used in place of a device-local layout in a `ShapeDtypeStruct`. Got )r  r   r   r*   rD  rG  rE  r   r   rJ   rM   r  device_local_layoutrN   r.  rT  rJ  )selfr   r   named_shaperT  s        rj   __init__zShapeDtypeStruct.__init__
  s4   uDJ}CDDD +E6?CCXRWDJJx(F9K$L$L 4<   8nn     ! ! ! 	8V$$ >8/<<>=2:= => > > *4Hf)E)ESH%%8DM0:8V0L0LV,,RVDIIIrl   c                4    t          j        | j                  S r   )r   r   r   rM  s    rj   r  zShapeDtypeStruct.<lambda>
  s    ty44 rl   c                *    t          | j                  S r   )r   r   rQ  s    rj   r  zShapeDtypeStruct.<lambda>
  s    s4: rl   c                6    t          | j        | j                  S r   )rM   rJ  rT  rQ  s    rj   layoutzShapeDtypeStruct.layout
  s    $)T]+++rl   c                b    	 | j         d         S # t          $ r}t          d          |d }~ww xY w)Nr   zlen() of unsized object)r   r  r.  )rM  r@  s     rj   __len__zShapeDtypeStruct.__len__
  sC    8Z] 8 8 8/00a78s    
.).c                    | j         
d| j          nd}| j        
d| j         nd}t          |           j         d| j         d| j        j         | | dS )Nz, sharding=r  z	, layout=z(shape=z, dtype=r  )rT  rJ  rT  r  r   r   r   rq   )rM  shr  s      rj   __repr__zShapeDtypeStruct.__repr__
  s    *.-*C	&t}	&	&	&B%)Y%:!DK!!!ADzz" / /4: / /Z_/&(/*+/ / / 0rl   c                    t          |t                    sdS |j        |j        |j        |j        f| j        | j        | j        | j        fk    S r  )r   r   r   r   rT  rT  )rM  others     rj   __eq__zShapeDtypeStruct.__eq__
  sO    e-.. DU{EKFz4:t}dkBC Drl   c                P    t          | j        | j        | j        | j        f          S r   )r  r   r   rT  rT  rQ  s    rj   __hash__zShapeDtypeStruct.__hash__
  s#     TZDEEErl   )NN)r   r!  r"  r  	__slots__rN  rO  propertyr   ry  rT  rV  rY  __str__r\  r^  rf   rl   rj   r   r   }
  s          544)+W W W W& 
44	5	5$	..	/	/$, , 8,8 8 80 0 0 'D D DF F F F Frl   r   c                b    t          | j        t          j        | j        d          d          S )NT)allow_extended_dtypeF)r  )r2   r   r*   canonicalize_dtyper   r  s    rj   r  r  
  s1    k!'6#<QW[_#`#`#`$)+ + + rl   c                    t          |            n# t          $ r t          |           } Y nw xY w t          |           j        |i |S )a	  Compute the shape/dtype of ``fun`` without any FLOPs.

  This utility function is useful for performing shape inference. Its
  input/output behavior is defined by::

    def eval_shape(fun, *args, **kwargs):
      out = fun(*args, **kwargs)
      shape_dtype_struct = lambda x: jax.ShapeDtypeStruct(x.shape, x.dtype)
      return jax.tree_util.tree_map(shape_dtype_struct, out)

  But instead of applying ``fun`` directly, which might be expensive, it uses
  JAX's abstract interpretation machinery to evaluate the shapes without doing
  any FLOPs.

  Using :py:func:`eval_shape` can also catch shape errors, and will raise same
  shape errors as evaluating ``fun(*args, **kwargs)``.

  Args:
    fun: The function whose output shape should be evaluated.
    *args: a positional argument tuple of arrays, scalars, or (nested) standard
      Python containers (tuples, lists, dicts, namedtuples, i.e. pytrees) of
      those types. Since only the ``shape`` and ``dtype`` attributes are
      accessed, one can use :class:`jax.ShapeDtypeStruct` or another container
      that duck-types as ndarrays (note however that duck-typed objects cannot
      be namedtuples because those are treated as standard Python containers).
    **kwargs: a keyword argument dict of arrays, scalars, or (nested) standard
      Python containers (pytrees) of those types. As in ``args``, array values
      need only be duck-typed to have ``shape`` and ``dtype`` attributes.

  Returns:
    out: a nested PyTree containing :class:`jax.ShapeDtypeStruct` objects as leaves.

  For example:

  >>> import jax
  >>> import jax.numpy as jnp
  >>>
  >>> f = lambda A, x: jnp.tanh(jnp.dot(A, x))
  >>> A = jax.ShapeDtypeStruct((2000, 3000), jnp.float32)
  >>> x = jax.ShapeDtypeStruct((3000, 1000), jnp.float32)
  >>> out = jax.eval_shape(f, A, x)  # no FLOPs performed
  >>> print(out.shape)
  (2000, 1000)
  >>> print(out.dtype)
  float32

  All arguments passed via :func:`eval_shape` will be treated as dynamic;
  static arguments can be included via closure, for example using :func:`functools.partial`:

  >>> import jax
  >>> from jax import lax
  >>> from functools import partial
  >>> import jax.numpy as jnp
  >>>
  >>> x = jax.ShapeDtypeStruct((1, 1, 28, 28), jnp.float32)
  >>> kernel = jax.ShapeDtypeStruct((32, 1, 3, 3), jnp.float32)
  >>>
  >>> conv_same = partial(lax.conv_general_dilated, window_strides=(1, 1), padding="SAME")
  >>> out = jax.eval_shape(conv_same, x, kernel)
  >>> print(out.shape)
  (1, 32, 28, 28)
  >>> print(out.dtype)
  float32
  )r  r.  r	   r   
eval_shape)rx   ry   rz   s      rj   rf  rf  
  sQ    D Cyyyy	&&&'#,,CCC&	S	d	-f	-	--s    --rq   rq   c               N    || j         } t          j        |          |           S )a  Adds a user specified name to a function when staging out JAX computations.

  When staging out computations for just-in-time compilation to XLA (or other
  backends such as TensorFlow) JAX runs your Python program but by default does
  not preserve any of the function names or other metadata associated with it.
  This can make debugging the staged out (and/or compiled) representation of
  your program complicated because there is limited context information for each
  operation being executed.

  `named_call` tells JAX to stage the given function out as a subcomputation
  with a specific name. When the staged out program is compiled with XLA these
  named subcomputations are preserved and show up in debugging utilities like
  the TensorFlow Profiler in TensorBoard. Names are also preserved when staging
  out JAX programs to TensorFlow using :func:`experimental.jax2tf.convert`.

  Args:
    fun: Function to be wrapped. This can be any Callable.
    name: Optional. The prefix to use to name all sub computations created
      within the name scope. Use the fun.__name__ if not specified.

  Returns:
    A version of `fun` that is wrapped in a name_scope.
  )r   r-   extend_name_stack)rx   rq   s     rj   
named_callrj  
  s,    8 
\<D	1		+D	1	1#	6	66rl   Generator[None, None, None]c              #     K   t          | t                    st          d          t          j        |           5  dV  ddd           dS # 1 swxY w Y   dS )a  A context manager that adds a user specified name to the JAX name stack.

  When staging out computations for just-in-time compilation to XLA (or other
  backends such as TensorFlow) JAX does not, by default, preserve the names
  (or other source metadata) of Python functions it encounters.
  This can make debugging the staged out (and/or compiled) representation of
  your program complicated because there is limited context information for each
  operation being executed.

  ``named_scope`` tells JAX to stage the given function with additional
  annotations on the underlying operations. JAX internally keeps track of these
  annotations in a name stack. When the staged out program is compiled with XLA
  these annotations are preserved and show up in debugging utilities like the
  TensorFlow Profiler in TensorBoard. Names are also preserved when staging out
  JAX programs to TensorFlow using :func:`experimental.jax2tf.convert`.


  Args:
    name: The prefix to use to name all operations created within the name
      scope.
  Yields:
    Yields ``None``, but enters a context in which `name` will be appended to
    the active name stack.

  Examples:
    ``named_scope`` can be used as a context manager inside compiled functions:

    >>> import jax
    >>>
    >>> @jax.jit
    ... def layer(w, x):
    ...   with jax.named_scope("dot_product"):
    ...     logits = w.dot(x)
    ...   with jax.named_scope("activation"):
    ...     return jax.nn.relu(logits)

    It can also be used as a decorator:

    >>> @jax.jit
    ... @jax.named_scope("layer")
    ... def layer(w, x):
    ...   logits = w.dot(x)
    ...   return jax.nn.relu(logits)
  z+named_scope name argument must be a string.N)r   r  r.  r-   ri  rg  s    rj   named_scoperm  ,  s      ` 
D#		 C
A
B
BB)$// 
 
	EEE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
s   AAAc                 B    t           j                                         dS )z?Waits until existing functions have completed any side-effects.N)r&   runtime_tokensblock_until_readyrf   rl   rj   effects_barrierrq  a  s    
++-----rl   c                "   d }g }t          |           D ]=}t          |t          j                  r|                    |           2 ||           >|sn9t          |          dk    r ||d                    nt          j        |           | S )a  
  Tries to call a ``block_until_ready`` method on pytree leaves.

  Args:
    x: a pytree, usually with at least some JAX array instances at its leaves.

  Returns:
    A pytree with the same structure and values of the input, where the values
    of all JAX array leaves are ready.
  c                P    	 |                                  S # t          $ r | cY S w xY wr   )rp  rB  r  s    rj   try_to_blockz'block_until_ready.<locals>.try_to_blockp  s=      """   hhhs    %%r*  r   )r   r   r(   rQ  r  r   r   batched_block_until_ready)r=  rt  arraysr}   s       rj   rp  rp  e  s       &!nn  d$(( mmDl4	 	) 	
6{{aL  (((	
(rl   c                    t          j                     t           j                                         t           j                                         t
          j                                         t          j                                         t          j	                                         t          j
                                         t          j                                         t          j        j                                         dS )zQ
  Clear all backend clients so that new backend clients can be created later.
  N)r  _clear_backendsr'  cache_clearr*  r&   xla_primitive_callabler/   _infer_params_cached_pjit_lower_cached_create_pjit_jaxpr_cpp_pjit_cacheclearr   r   PjitFunctionCache	clear_allrf   rl   rj   clear_backendsr    s           
!--///'')))%%'''%%''''%%'''''rl   c                N    t          j        |                                           S )zkReturn all live arrays in the backend for `platform`.

  If platform is None, it is the default backend.
  )r  r  live_arrays)r  s    rj   r  r    s     
 
	!	!	-	-	/	//rl   c                    t          j                     t          j                     t          j                                         t          j                                         t          j	        j
                                         t          D ]} |                                  t          j                                         dS )zClear all compilation and staging caches.

  This doesn't clear the persistent cache; to disable it (e.g. for benchmarks),
  set the jax_enable_compilation_cache config option to False.
  N)rW   clear_all_cachesclear_all_weakref_lru_cachesr/   r~  r  r{  ry  r   r   r  r  r  _cache_clearr&   rz  )rx   s    rj   clear_cachesr    s     #%%% '')))'%%'''    c !--/////rl   )rx   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )T)r   r   )	rf   NNNNFNFrf   )rx   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   FFFrf   )rx   r   r  r  r  r   r  r   r  r   r  r  r   r   )rx   r   r  r  r  r   r  r   r  r   r  r  r   r'  )r   FF)
rx   r   r  r  r  r   r  r   r   r   )r  r   r=  r   r   rb  )r   FFF)rx   r   r  r  r  r   r  r   r  r   r   r   )r   r   NNN)rx   r_   r  r  rS  r   r   r  r  r  r  r  r   r_   r   )rx   r   r   r  r  r   r  r  r   r   r  r  r   r   r  r  r   r   )r  r-  r$  r  r  r  )rx   r   r   r  r  r   r  r  r   r   r  r  r   r   r   r   r   )rx   r   r  r   r   r  )rx   r  )rx   r   r  r  r   r  )rx   r   r  r  r   r  )rx   r   r  r   r   r  )r   r   )
rx   r  r  r   r  r  r  r  r   r  )
rx   r  r  r   r  r  r  r  r   r  )rx   r   r   r   )r   r  )rf   N.N)rx   r   r   r   r   r   r   r  r   r   r   r  )rx   r   r   r   r   r   r   r  r   r   r   r  )rf   NFN)rx   r   r   r   r   r   r   r   r   r   r   r  )r   r
  )r   r  r  r  )rv  r  r  rH  )r=  r   r  rH  )r=  r   )rx   r   )rx   r_   rq   r   r   r_   )rq   r  r   rk  )r  
__future__r   r  collections.abcr   r   r   r   r   	functoolsr	   r
   r  r   r`  r   r   r   r   r   r   r  rq  rE  
contextlibr   r   jax._srcr   r   r   jax._src.tree_utilr   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r  jax._src.corer1   r2   r3   jax._src.api_utilr4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   jax._src.laxrF   r3  jax._src.librG   rH   r   rI   jax._src.shardingrJ   jax._src.sharding_implsrK   rL   jax._src.layoutrM   rN   jax._src.traceback_utilrO   rP   jax._src.utilrQ   rR   rS   rT   rU   rV   rW   jax._src.interpretersrX   rY   rZ   r[   r   r\   r]   register_exclusion__file__r   r  AxisNamer  r_   ra   rb   r   
unsafe_mapr  
unsafe_zipr~   r   r   rs   
_add_hooksru   r  UNSPECIFIEDr   r   r   r&  r%  r1  rK  r/  rN  r2  ra  rU  rY  rl  jacobianrh  ri  rn  rX  rZ  rj  r  ru  r  rW  r  r  r  r.  r:  r@  rB  r  WeakSetr  r  rV  r  r  r  r  r  r0  r  r  r  r  r  r"  r/  r<  rD  rH  r   pytype_aval_mappingsrf  rj  rm  rq  rp  r  r  r  rf   rl   rj   <module>r     sy    # " " " " "     M M M M M M M M M M M M M M ( ( ( ( ( ( ( (                        0 0 0 0 0 0 0 0 & & & & & &      ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?                                                 # # # # # # # # # # # # % % % % % % # # # # # #       % % % % % % @ @ @ @ @ @ @ @ @ @C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C - , , , , ,             ) ) ) ) ) ) ! ! ! ! ! ! & & & & & & F F F F F F F F . . . . . . . . 0 0 0 0 0 0      ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '       $ $ $ $ $ $ * * * * * * & & & & & & 4 4 4 4 4 4 & & & & & & % % % % % % " !( + + +	D	1	1	1	 GCx   GCLLGCLLCZCZ( ( ( , , ,2 2 2    9?A A A    9?A A A 

 )*/304/304! $N5 N5 N5 N5 N5b /
 /
 /
 /
 /
f ;=FJ-1*.',=A).:<l l l l l\ 8949 +-@+ @+ @+ @+ @+D BC>CNPH H H H HT9 9 9X X X$ "'"=vFF ) ) )( #7#?HH  :;6;< < < < <|O O O O"5 5 5 :;OT? ? ? ? ?@ #G$?JJ $W%A8LL  ;<7<AC AC AC AC ACFA A A/ / /. . .A A A1 1 1&# # # 01&*!%BFC C C C CJI& I& I&\ "&~% 68*. *,<@~% ~% ~% ~% ~% ~%B% % % % %: % % %   <MQ MQ MQ`; ; ;*    
   $ "&J 68*. *,J J J J J JX %W_&&  7<)E )E )E )E )EV&- &- &- &- &-P 
AF      
 
   
 8= Z% Z% Z% Z% Z% Z%x8 8 8"'' '' ''T   
 
 #(*,     
 
 +-     

 .3/4 /4 /4 /4 /4 /4b 05 @ @ @ @ @ @, ;= I( I( I( I( I( I(X: : : : 
57AE.1-1	    
 
57AE-0-1	    
 68AE$)-1	` ` ` ` `D
 
 
 
 4  $ QU.- QU.- .- .- .- .- .-bP2 P2 P2 P2f5/ 5/ 5/ 5/r  %$ %$ %$ %$P?F ?F ?F ?F ?F ?F ?F ?FD+ +  * +
 C. C. C. C.R 7 7 7 7 7 7D 2
 2
 2
 2
h. . .# # #L( ( (0 0 0 00 0 0 0 0rl   