class_docstr: Functions that operate element-by-element on whole arrays.
  
  This is a class for LAX-backed implementations of numpy ufuncs.
code: def __init__(
      self,
      func: Callable[..., Any],
      /,
      nin: int,
      nout: int,
      *,
      name: str | None = None,
      nargs: int | None = None,
      identity: Any = None,
      update_doc=False,
  ):
      # We want ufunc instances to work properly when marked as static,
      # and for this reason it's important that their properties not be
      # mutated. We prevent this by storing them in a dunder attribute,
      # and accessing them via read-only properties.
      if update_doc:
          self.__doc__ = func.__doc__
      self.__name__ = name or func.__name__
      self.__static_props = {
          "func": func,
          "call": vectorize(func),
          "nin": operator.index(nin),
          "nout": operator.index(nout),
          "nargs": operator.index(nargs or nin),
          "identity": identity,
      }
  
imports: from __future__ import annotations
  from functools import partial
  import math
  import operator
  from typing import Any, Callable
  import jax
  from jax._src.typing import Array, ArrayLike, DTypeLike
  from jax._src.lax import lax
  from jax._src.numpy import reductions
  from jax._src.numpy.lax_numpy import _eliminate_deprecated_list_indexing, append, take
  from jax._src.numpy.reductions import _moveaxis
  from jax._src.numpy.util import _wraps, check_arraylike, _broadcast_to, _where
  from jax._src.numpy.vectorize import vectorize
  from jax._src.util import canonicalize_axis, set_module
  import numpy
label_desc: Use image node_id 1 to create a new ufunc object  with example: obj = ufunc(nin, nout)