files: """
  Wrapper class around the ndarray object for the array API standard.
  
  The array API standard defines some behaviors differently than ndarray, in
  particular, type promotion rules are different (the standard has no
  value-based casting). The standard also specifies a more limited subset of
  array methods and functionalities than are implemented on ndarray. Since the
  goal of the array_api namespace is to be a minimal implementation of the array
  API standard, we need to define a separate wrapper class for the array_api
  namespace.
  
  The standard compliant class is only a wrapper class. It is *not* a subclass
  of ndarray.
  """
  
  from __future__ import annotations
  
  import operator
  from enum import IntEnum
  from ._creation_functions import asarray
  from ._dtypes import _boolean_dtypes, _integer_dtypes, _floating_dtypes
  
  from typing import TYPE_CHECKING, Any, Optional, Tuple, Union
  if TYPE_CHECKING:
      from ._typing import PyCapsule, Device, Dtype
  
  import numpy as np
  
  class Array:
      """
      n-d array object for the array API namespace.
  
      See the docstring of :py:obj:`np.ndarray <numpy.ndarray>` for more
      information.
  
      This is a wrapper around numpy.ndarray that restricts the usage to only
      those things that are required by the array API namespace. Note,
      attributes on this object that start with a single underscore are not part
      of the API specification and should only be used internally. This object
      should not be constructed directly. Rather, use one of the creation
      functions, such as asarray().
  
      """
      # Use a custom constructor instead of __init__, as manually initializing
      # this class is not supported API.
      @classmethod
      def _new(cls, x, /):
          """
          This is a private method for initializing the array API Array
          object.
  
          Functions outside of the array_api submodule should not use this
          method. Use one of the creation functions instead, such as
          ``asarray``.
  
          """
          obj = super().__new__(cls)
          # Note: The spec does not have array scalars, only shape () arrays.
          if isinstance(x, np.generic):
              # Convert the array scalar to a shape () array
              xa = np.empty((), x.dtype)
              xa[()] = x
              x = xa
          obj._array = x
          return obj
  
      # Prevent Array() from working
      def __new__(cls, *args, **kwargs):
          raise TypeError("The array_api Array object should not be instantiated directly. Use an array creation function, such as asarray(), instead.")
  
      # These functions are not required by the spec, but are implemented for
      # the sake of usability.
  
      def __str__(self: Array, /) -> str:
          """
          Performs the operation __str__.
          """
          return self._array.__str__().replace('array', 'Array')
  
      def __repr__(self: Array, /) -> str:
          """
          Performs the operation __repr__.
          """
          return self._array.__repr__().replace('array', 'Array')
  
      # Helper function to match the type promotion rules in the spec
      def _promote_scalar(self, scalar):
          """
          Returns a promoted version of a Python scalar appropriate for use with
          operations on self.
  
          This may raise an OverflowError in cases where the scalar is an
          integer that is too large to fit in a NumPy integer dtype, or
          TypeError when the scalar type is incompatible with the dtype of self.
          """
          if isinstance(scalar, bool):
              if self.dtype not in _boolean_dtypes:
                  raise TypeError("Python bool scalars can only be promoted with bool arrays")
          elif isinstance(scalar, int):
              if self.dtype in _boolean_dtypes:
                  raise TypeError("Python int scalars cannot be promoted with bool arrays")
          elif isinstance(scalar, float):
              if self.dtype not in _floating_dtypes:
                  raise TypeError("Python float scalars can only be promoted with floating-point arrays.")
          else:
              raise TypeError("'scalar' must be a Python scalar")
  
          # Note: the spec only specifies integer-dtype/int promotion
          # behavior for integers within the bounds of the integer dtype.
          # Outside of those bounds we use the default NumPy behavior (either
          # cast or raise OverflowError).
          return Array._new(np.array(scalar, self.dtype))
  
      @staticmethod
      def _normalize_two_args(x1, x2):
          """
          Normalize inputs to two arg functions to fix type promotion rules
  
          NumPy deviates from the spec type promotion rules in cases where one
          argument is 0-dimensional and the other is not. For example:
  
          >>> import numpy as np
          >>> a = np.array([1.0], dtype=np.float32)
          >>> b = np.array(1.0, dtype=np.float64)
          >>> np.add(a, b) # The spec says this should be float64
          array([2.], dtype=float32)
  
          To fix this, we add a dimension to the 0-dimension array before passing it
          through. This works because a dimension would be added anyway from
          broadcasting, so the resulting shape is the same, but this prevents NumPy
          from not promoting the dtype.
          """
          if x1.shape == () and x2.shape != ():
              # The _array[None] workaround was chosen because it is relatively
              # performant. broadcast_to(x1._array, x2.shape) is much slower. We
              # could also manually type promote x2, but that is more complicated
              # and about the same performance as this.
              x1 = Array._new(x1._array[None])
          elif x2.shape == () and x1.shape != ():
              x2 = Array._new(x2._array[None])
          return (x1, x2)
  
      # Everything below this line is required by the spec.
  
      def __abs__(self: Array, /) -> Array:
          """
          Performs the operation __abs__.
          """
          res = self._array.__abs__()
          return self.__class__._new(res)
  
      @np.errstate(all='ignore')
      def __add__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __add__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__add__(other._array)
          return self.__class__._new(res)
  
      def __and__(self: Array, other: Union[int, bool, Array], /) -> Array:
          """
          Performs the operation __and__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__and__(other._array)
          return self.__class__._new(res)
  
      def __array_namespace__(self: Array, /, *, api_version: Optional[str] = None) -> object:
          if api_version is not None:
              raise ValueError("Unrecognized array API version")
          from numpy import _array_api
          return _array_api
  
      def __bool__(self: Array, /) -> bool:
          """
          Performs the operation __bool__.
          """
          # Note: This is an error here.
          if self._array.shape != ():
              raise TypeError("bool is only allowed on arrays with shape ()")
          res = self._array.__bool__()
          return res
  
      def __dlpack__(self: Array, /, *, stream: Optional[Union[int, Any]] = None) -> PyCapsule:
          """
          Performs the operation __dlpack__.
          """
          res = self._array.__dlpack__(stream=None)
          return self.__class__._new(res)
  
      def __dlpack_device__(self: Array, /) -> Tuple[IntEnum, int]:
          """
          Performs the operation __dlpack_device__.
          """
          # Note: device support is required for this
          res = self._array.__dlpack_device__()
          return self.__class__._new(res)
  
      def __eq__(self: Array, other: Union[int, float, bool, Array], /) -> Array:
          """
          Performs the operation __eq__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__eq__(other._array)
          return self.__class__._new(res)
  
      def __float__(self: Array, /) -> float:
          """
          Performs the operation __float__.
          """
          # Note: This is an error here.
          if self._array.shape != ():
              raise TypeError("float is only allowed on arrays with shape ()")
          res = self._array.__float__()
          return res
  
      @np.errstate(all='ignore')
      def __floordiv__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __floordiv__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__floordiv__(other._array)
          return self.__class__._new(res)
  
      def __ge__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __ge__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__ge__(other._array)
          return self.__class__._new(res)
  
      # Note: A large fraction of allowed indices are disallowed here (see the
      # docstring below)
      @staticmethod
      def _validate_index(key, shape):
          """
          Validate an index according to the array API.
  
          The array API specification only requires a subset of indices that are
          supported by NumPy. This function will reject any index that is
          allowed by NumPy but not required by the array API specification. We
          always raise ``IndexError`` on such indices (the spec does not require
          any specific behavior on them, but this makes the NumPy array API
          namespace a minimal implementation of the spec).
  
          This function either raises IndexError if the index ``key`` is
          invalid, or a new key to be used in place of ``key`` in indexing. It
          only raises ``IndexError`` on indices that are not already rejected by
          NumPy, as NumPy will already raise the appropriate error on such
          indices. ``shape`` may be None, in which case, only cases that are
          independent of the array shape are checked.
  
          The following cases are allowed by NumPy, but not specified by the array
          API specification:
  
          - The start and stop of a slice may not be out of bounds. In
            particular, for a slice ``i:j:k`` on an axis of size ``n``, only the
            following are allowed:
  
            - ``i`` or ``j`` omitted (``None``).
            - ``-n <= i <= max(0, n - 1)``.
            - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``.
            - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``.
  
          - Boolean array indices are not allowed as part of a larger tuple
            index.
  
          - Integer array indices are not allowed (with the exception of shape
            () arrays, which are treated the same as scalars).
  
          Additionally, it should be noted that indices that would return a
          scalar in NumPy will return a shape () array. Array scalars are not allowed
          in the specification, only shape () arrays. This is done in the
          ``Array._new`` constructor, not this function.
  
          """
          if isinstance(key, slice):
              if shape is None:
                  return key
              if shape == ():
                  return key
              size = shape[0]
              # Ensure invalid slice entries are passed through.
              if key.start is not None:
                  try:
                      operator.index(key.start)
                  except TypeError:
                      return key
                  if not (-size <= key.start <= max(0, size - 1)):
                      raise IndexError("Slices with out-of-bounds start are not allowed in the array API namespace")
              if key.stop is not None:
                  try:
                      operator.index(key.stop)
                  except TypeError:
                      return key
                  step = 1 if key.step is None else key.step
                  if (step > 0 and not (-size <= key.stop <= size)
                      or step < 0 and not (-size - 1 <= key.stop <= max(0, size - 1))):
                      raise IndexError("Slices with out-of-bounds stop are not allowed in the array API namespace")
              return key
  
          elif isinstance(key, tuple):
              key = tuple(Array._validate_index(idx, None) for idx in key)
  
              for idx in key:
                  if isinstance(idx, np.ndarray) and idx.dtype in _boolean_dtypes or isinstance(idx, (bool, np.bool_)):
                      if len(key) == 1:
                          return key
                      raise IndexError("Boolean array indices combined with other indices are not allowed in the array API namespace")
  
              if shape is None:
                  return key
              n_ellipsis = key.count(...)
              if n_ellipsis > 1:
                  return key
              ellipsis_i = key.index(...) if n_ellipsis else len(key)
  
              for idx, size in list(zip(key[:ellipsis_i], shape)) + list(zip(key[:ellipsis_i:-1], shape[:ellipsis_i:-1])):
                  Array._validate_index(idx, (size,))
              return key
          elif isinstance(key, bool):
              return key
          elif isinstance(key, Array):
              if key.dtype in _integer_dtypes:
                  if key.shape != ():
                      raise IndexError("Integer array indices with shape != () are not allowed in the array API namespace")
              return key._array
          elif key is Ellipsis:
              return key
          elif key is None:
              raise IndexError("newaxis indices are not allowed in the array API namespace")
          try:
              return operator.index(key)
          except TypeError:
              # Note: This also omits boolean arrays that are not already in
              # Array() form, like a list of booleans.
              raise IndexError("Only integers, slices (`:`), ellipsis (`...`), and boolean arrays are valid indices in the array API namespace")
  
      def __getitem__(self: Array, key: Union[int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], Array], /) -> Array:
          """
          Performs the operation __getitem__.
          """
          # Note: Only indices required by the spec are allowed. See the
          # docstring of _validate_index
          key = self._validate_index(key, self.shape)
          res = self._array.__getitem__(key)
          return self._new(res)
  
      def __gt__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __gt__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__gt__(other._array)
          return self.__class__._new(res)
  
      def __int__(self: Array, /) -> int:
          """
          Performs the operation __int__.
          """
          # Note: This is an error here.
          if self._array.shape != ():
              raise TypeError("int is only allowed on arrays with shape ()")
          res = self._array.__int__()
          return res
  
      def __invert__(self: Array, /) -> Array:
          """
          Performs the operation __invert__.
          """
          res = self._array.__invert__()
          return self.__class__._new(res)
  
      def __le__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __le__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__le__(other._array)
          return self.__class__._new(res)
  
      # Note: __len__ may end up being removed from the array API spec.
      def __len__(self, /) -> int:
          """
          Performs the operation __len__.
          """
          res = self._array.__len__()
          return self.__class__._new(res)
  
      def __lshift__(self: Array, other: Union[int, Array], /) -> Array:
          """
          Performs the operation __lshift__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__lshift__(other._array)
          return self.__class__._new(res)
  
      def __lt__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __lt__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__lt__(other._array)
          return self.__class__._new(res)
  
      def __mat
  
  [... the rest is omitted ...]
files: numpy/_array_api/_array_object.py
files: """
  Wrapper class around the ndarray object for the array API standard.
  
  The array API standard defines some behaviors differently than ndarray, in
  particular, type promotion rules are different (the standard has no
  value-based casting). The standard also specifies a more limited subset of
  array methods and functionalities than are implemented on ndarray. Since the
  goal of the array_api namespace is to be a minimal implementation of the array
  API standard, we need to define a separate wrapper class for the array_api
  namespace.
  
  The standard compliant class is only a wrapper class. It is *not* a subclass
  of ndarray.
  """
  
  from __future__ import annotations
  
  import operator
  from enum import IntEnum
  from ._creation_functions import asarray
  from ._dtypes import _boolean_dtypes, _integer_dtypes, _floating_dtypes
  
  from typing import TYPE_CHECKING, Any, Optional, Tuple, Union
  if TYPE_CHECKING:
      from ._typing import PyCapsule, Device, Dtype
  
  import numpy as np
  
  class Array:
      """
      n-d array object for the array API namespace.
  
      See the docstring of :py:obj:`np.ndarray <numpy.ndarray>` for more
      information.
  
      This is a wrapper around numpy.ndarray that restricts the usage to only
      those things that are required by the array API namespace. Note,
      attributes on this object that start with a single underscore are not part
      of the API specification and should only be used internally. This object
      should not be constructed directly. Rather, use one of the creation
      functions, such as asarray().
  
      """
      # Use a custom constructor instead of __init__, as manually initializing
      # this class is not supported API.
      @classmethod
      def _new(cls, x, /):
          """
          This is a private method for initializing the array API Array
          object.
  
          Functions outside of the array_api submodule should not use this
          method. Use one of the creation functions instead, such as
          ``asarray``.
  
          """
          obj = super().__new__(cls)
          # Note: The spec does not have array scalars, only shape () arrays.
          if isinstance(x, np.generic):
              # Convert the array scalar to a shape () array
              xa = np.empty((), x.dtype)
              xa[()] = x
              x = xa
          obj._array = x
          return obj
  
      # Prevent Array() from working
      def __new__(cls, *args, **kwargs):
          raise TypeError("The array_api Array object should not be instantiated directly. Use an array creation function, such as asarray(), instead.")
  
      # These functions are not required by the spec, but are implemented for
      # the sake of usability.
  
      def __str__(self: Array, /) -> str:
          """
          Performs the operation __str__.
          """
          return self._array.__str__().replace('array', 'Array')
  
      def __repr__(self: Array, /) -> str:
          """
          Performs the operation __repr__.
          """
          return self._array.__repr__().replace('array', 'Array')
  
      # Helper function to match the type promotion rules in the spec
      def _promote_scalar(self, scalar):
          """
          Returns a promoted version of a Python scalar appropriate for use with
          operations on self.
  
          This may raise an OverflowError in cases where the scalar is an
          integer that is too large to fit in a NumPy integer dtype, or
          TypeError when the scalar type is incompatible with the dtype of self.
          """
          if isinstance(scalar, bool):
              if self.dtype not in _boolean_dtypes:
                  raise TypeError("Python bool scalars can only be promoted with bool arrays")
          elif isinstance(scalar, int):
              if self.dtype in _boolean_dtypes:
                  raise TypeError("Python int scalars cannot be promoted with bool arrays")
          elif isinstance(scalar, float):
              if self.dtype not in _floating_dtypes:
                  raise TypeError("Python float scalars can only be promoted with floating-point arrays.")
          else:
              raise TypeError("'scalar' must be a Python scalar")
  
          # Note: the spec only specifies integer-dtype/int promotion
          # behavior for integers within the bounds of the integer dtype.
          # Outside of those bounds we use the default NumPy behavior (either
          # cast or raise OverflowError).
          return Array._new(np.array(scalar, self.dtype))
  
      @staticmethod
      def _normalize_two_args(x1, x2):
          """
          Normalize inputs to two arg functions to fix type promotion rules
  
          NumPy deviates from the spec type promotion rules in cases where one
          argument is 0-dimensional and the other is not. For example:
  
          >>> import numpy as np
          >>> a = np.array([1.0], dtype=np.float32)
          >>> b = np.array(1.0, dtype=np.float64)
          >>> np.add(a, b) # The spec says this should be float64
          array([2.], dtype=float32)
  
          To fix this, we add a dimension to the 0-dimension array before passing it
          through. This works because a dimension would be added anyway from
          broadcasting, so the resulting shape is the same, but this prevents NumPy
          from not promoting the dtype.
          """
          if x1.shape == () and x2.shape != ():
              # The _array[None] workaround was chosen because it is relatively
              # performant. broadcast_to(x1._array, x2.shape) is much slower. We
              # could also manually type promote x2, but that is more complicated
              # and about the same performance as this.
              x1 = Array._new(x1._array[None])
          elif x2.shape == () and x1.shape != ():
              x2 = Array._new(x2._array[None])
          return (x1, x2)
  
      # Everything below this line is required by the spec.
  
      def __abs__(self: Array, /) -> Array:
          """
          Performs the operation __abs__.
          """
          res = self._array.__abs__()
          return self.__class__._new(res)
  
      @np.errstate(all='ignore')
      def __add__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __add__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__add__(other._array)
          return self.__class__._new(res)
  
      def __and__(self: Array, other: Union[int, bool, Array], /) -> Array:
          """
          Performs the operation __and__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__and__(other._array)
          return self.__class__._new(res)
  
      def __array_namespace__(self: Array, /, *, api_version: Optional[str] = None) -> object:
          if api_version is not None:
              raise ValueError("Unrecognized array API version")
          from numpy import _array_api
          return _array_api
  
      def __bool__(self: Array, /) -> bool:
          """
          Performs the operation __bool__.
          """
          # Note: This is an error here.
          if self._array.shape != ():
              raise TypeError("bool is only allowed on arrays with shape ()")
          res = self._array.__bool__()
          return res
  
      def __dlpack__(self: Array, /, *, stream: Optional[Union[int, Any]] = None) -> PyCapsule:
          """
          Performs the operation __dlpack__.
          """
          res = self._array.__dlpack__(stream=None)
          return self.__class__._new(res)
  
      def __dlpack_device__(self: Array, /) -> Tuple[IntEnum, int]:
          """
          Performs the operation __dlpack_device__.
          """
          # Note: device support is required for this
          res = self._array.__dlpack_device__()
          return self.__class__._new(res)
  
      def __eq__(self: Array, other: Union[int, float, bool, Array], /) -> Array:
          """
          Performs the operation __eq__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__eq__(other._array)
          return self.__class__._new(res)
  
      def __float__(self: Array, /) -> float:
          """
          Performs the operation __float__.
          """
          # Note: This is an error here.
          if self._array.shape != ():
              raise TypeError("float is only allowed on arrays with shape ()")
          res = self._array.__float__()
          return res
  
      @np.errstate(all='ignore')
      def __floordiv__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __floordiv__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__floordiv__(other._array)
          return self.__class__._new(res)
  
      def __ge__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __ge__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__ge__(other._array)
          return self.__class__._new(res)
  
      # Note: A large fraction of allowed indices are disallowed here (see the
      # docstring below)
      @staticmethod
      def _validate_index(key, shape):
          """
          Validate an index according to the array API.
  
          The array API specification only requires a subset of indices that are
          supported by NumPy. This function will reject any index that is
          allowed by NumPy but not required by the array API specification. We
          always raise ``IndexError`` on such indices (the spec does not require
          any specific behavior on them, but this makes the NumPy array API
          namespace a minimal implementation of the spec).
  
          This function either raises IndexError if the index ``key`` is
          invalid, or a new key to be used in place of ``key`` in indexing. It
          only raises ``IndexError`` on indices that are not already rejected by
          NumPy, as NumPy will already raise the appropriate error on such
          indices. ``shape`` may be None, in which case, only cases that are
          independent of the array shape are checked.
  
          The following cases are allowed by NumPy, but not specified by the array
          API specification:
  
          - The start and stop of a slice may not be out of bounds. In
            particular, for a slice ``i:j:k`` on an axis of size ``n``, only the
            following are allowed:
  
            - ``i`` or ``j`` omitted (``None``).
            - ``-n <= i <= max(0, n - 1)``.
            - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``.
            - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``.
  
          - Boolean array indices are not allowed as part of a larger tuple
            index.
  
          - Integer array indices are not allowed (with the exception of shape
            () arrays, which are treated the same as scalars).
  
          Additionally, it should be noted that indices that would return a
          scalar in NumPy will return a shape () array. Array scalars are not allowed
          in the specification, only shape () arrays. This is done in the
          ``Array._new`` constructor, not this function.
  
          """
          if isinstance(key, slice):
              if shape is None:
                  return key
              if shape == ():
                  return key
              size = shape[0]
              # Ensure invalid slice entries are passed through.
              if key.start is not None:
                  try:
                      operator.index(key.start)
                  except TypeError:
                      return key
                  if not (-size <= key.start <= max(0, size - 1)):
                      raise IndexError("Slices with out-of-bounds start are not allowed in the array API namespace")
              if key.stop is not None:
                  try:
                      operator.index(key.stop)
                  except TypeError:
                      return key
                  step = 1 if key.step is None else key.step
                  if (step > 0 and not (-size <= key.stop <= size)
                      or step < 0 and not (-size - 1 <= key.stop <= max(0, size - 1))):
                      raise IndexError("Slices with out-of-bounds stop are not allowed in the array API namespace")
              return key
  
          elif isinstance(key, tuple):
              key = tuple(Array._validate_index(idx, None) for idx in key)
  
              for idx in key:
                  if isinstance(idx, np.ndarray) and idx.dtype in _boolean_dtypes or isinstance(idx, (bool, np.bool_)):
                      if len(key) == 1:
                          return key
                      raise IndexError("Boolean array indices combined with other indices are not allowed in the array API namespace")
  
              if shape is None:
                  return key
              n_ellipsis = key.count(...)
              if n_ellipsis > 1:
                  return key
              ellipsis_i = key.index(...) if n_ellipsis else len(key)
  
              for idx, size in list(zip(key[:ellipsis_i], shape)) + list(zip(key[:ellipsis_i:-1], shape[:ellipsis_i:-1])):
                  Array._validate_index(idx, (size,))
              return key
          elif isinstance(key, bool):
              return key
          elif isinstance(key, Array):
              if key.dtype in _integer_dtypes:
                  if key.shape != ():
                      raise IndexError("Integer array indices with shape != () are not allowed in the array API namespace")
              return key._array
          elif key is Ellipsis:
              return key
          elif key is None:
              raise IndexError("newaxis indices are not allowed in the array API namespace")
          try:
              return operator.index(key)
          except TypeError:
              # Note: This also omits boolean arrays that are not already in
              # Array() form, like a list of booleans.
              raise IndexError("Only integers, slices (`:`), ellipsis (`...`), and boolean arrays are valid indices in the array API namespace")
  
      def __getitem__(self: Array, key: Union[int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], Array], /) -> Array:
          """
          Performs the operation __getitem__.
          """
          # Note: Only indices required by the spec are allowed. See the
          # docstring of _validate_index
          key = self._validate_index(key, self.shape)
          res = self._array.__getitem__(key)
          return self._new(res)
  
      def __gt__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __gt__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__gt__(other._array)
          return self.__class__._new(res)
  
      def __int__(self: Array, /) -> int:
          """
          Performs the operation __int__.
          """
          # Note: This is an error here.
          if self._array.shape != ():
              raise TypeError("int is only allowed on arrays with shape ()")
          res = self._array.__int__()
          return res
  
      def __invert__(self: Array, /) -> Array:
          """
          Performs the operation __invert__.
          """
          res = self._array.__invert__()
          return self.__class__._new(res)
  
      def __le__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __le__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          self, other = self._normalize_two_args(self, other)
          res = self._array.__le__(other._array)
          return self.__class__._new(res)
  
      # Note: __len__ may end up being removed from the array API spec.
      def __len__(self, /) -> int:
          """
          Performs the operation __len__.
          """
          res = self._array.__len__()
          return self.__class__._new(res)
  
      def __lshift__(self: Array, other: Union[int, Array], /) -> Array:
          """
          Performs the operation __lshift__.
          """
          if isinstance(other, (int, float, bool)):
              other = self._promote_scalar(other)
          # Note: The spec requires the return dtype of bitwise_left_shift, and
          # hence also __lshift__, to be the same as the first argument.
          # np.ndarray.__lshift__ returns a type that is the type promotion of
          # the two input types.
          res = self._array.__lshift__(other._array).astype(self.dtype)
          return self.__class__._new(res)
  
      def __lt__(self: Array, other: Union[int, float, Array], /) -> Array:
          """
          Performs the operation __lt__.
          """
          if isinstance(other, (int, float, bool)):
  
  
  [... the rest is omitted ...]
files: numpy/_array_api/_array_object.py
files: from __future__ import annotations
  
  from ._dtypes import (_boolean_dtypes, _floating_dtypes,
                        _integer_dtypes, _integer_or_boolean_dtypes,
                        _numeric_dtypes)
  from ._array_object import Array
  
  import numpy as np
  
  def abs(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.abs <numpy.abs>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in abs')
      return Array._new(np.abs(x._array))
  
  # Note: the function name is different here
  @np.errstate(all='ignore')
  def acos(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arccos <numpy.arccos>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in acos')
      return Array._new(np.arccos(x._array))
  
  # Note: the function name is different here
  @np.errstate(all='ignore')
  def acosh(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arccosh <numpy.arccosh>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in acosh')
      return Array._new(np.arccosh(x._array))
  
  @np.errstate(all='ignore')
  def add(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.add <numpy.add>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in add')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.add(x1._array, x2._array))
  
  # Note: the function name is different here
  @np.errstate(all='ignore')
  def asin(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arcsin <numpy.arcsin>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in asin')
      return Array._new(np.arcsin(x._array))
  
  # Note: the function name is different here
  @np.errstate(all='ignore')
  def asinh(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arcsinh <numpy.arcsinh>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in asinh')
      return Array._new(np.arcsinh(x._array))
  
  # Note: the function name is different here
  def atan(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arctan <numpy.arctan>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in atan')
      return Array._new(np.arctan(x._array))
  
  # Note: the function name is different here
  def atan2(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arctan2 <numpy.arctan2>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _floating_dtypes or x2.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in atan2')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.arctan2(x1._array, x2._array))
  
  # Note: the function name is different here
  @np.errstate(all='ignore')
  def atanh(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arctanh <numpy.arctanh>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in atanh')
      return Array._new(np.arctanh(x._array))
  
  def bitwise_and(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.bitwise_and <numpy.bitwise_and>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _integer_or_boolean_dtypes or x2.dtype not in _integer_or_boolean_dtypes:
          raise TypeError('Only integer_or_boolean dtypes are allowed in bitwise_and')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.bitwise_and(x1._array, x2._array))
  
  # Note: the function name is different here
  def bitwise_left_shift(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.left_shift <numpy.left_shift>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _integer_dtypes or x2.dtype not in _integer_dtypes:
          raise TypeError('Only integer dtypes are allowed in bitwise_left_shift')
      x1, x2 = Array._normalize_two_args(x1, x2)
      # Note: bitwise_left_shift is only defined for x2 nonnegative.
      if np.any(x2._array < 0):
          raise ValueError('bitwise_left_shift(x1, x2) is only defined for x2 >= 0')
      return Array._new(np.left_shift(x1._array, x2._array))
  
  # Note: the function name is different here
  def bitwise_invert(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.invert <numpy.invert>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _integer_or_boolean_dtypes:
          raise TypeError('Only integer or boolean dtypes are allowed in bitwise_invert')
      return Array._new(np.invert(x._array))
  
  def bitwise_or(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.bitwise_or <numpy.bitwise_or>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _integer_or_boolean_dtypes or x2.dtype not in _integer_or_boolean_dtypes:
          raise TypeError('Only integer or boolean dtypes are allowed in bitwise_or')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.bitwise_or(x1._array, x2._array))
  
  # Note: the function name is different here
  def bitwise_right_shift(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.right_shift <numpy.right_shift>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _integer_dtypes or x2.dtype not in _integer_dtypes:
          raise TypeError('Only integer dtypes are allowed in bitwise_right_shift')
      x1, x2 = Array._normalize_two_args(x1, x2)
      # Note: bitwise_right_shift is only defined for x2 nonnegative.
      if np.any(x2._array < 0):
          raise ValueError('bitwise_right_shift(x1, x2) is only defined for x2 >= 0')
      return Array._new(np.right_shift(x1._array, x2._array))
  
  def bitwise_xor(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.bitwise_xor <numpy.bitwise_xor>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _integer_or_boolean_dtypes or x2.dtype not in _integer_or_boolean_dtypes:
          raise TypeError('Only integer or boolean dtypes are allowed in bitwise_xor')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.bitwise_xor(x1._array, x2._array))
  
  def ceil(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.ceil <numpy.ceil>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in ceil')
      if x.dtype in _integer_dtypes:
          # Note: The return dtype of ceil is the same as the input
          return x
      return Array._new(np.ceil(x._array))
  
  @np.errstate(all='ignore')
  def cos(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.cos <numpy.cos>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in cos')
      return Array._new(np.cos(x._array))
  
  @np.errstate(all='ignore')
  def cosh(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.cosh <numpy.cosh>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in cosh')
      return Array._new(np.cosh(x._array))
  
  @np.errstate(all='ignore')
  def divide(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.divide <numpy.divide>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _floating_dtypes or x2.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in divide')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.divide(x1._array, x2._array))
  
  def equal(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.equal <numpy.equal>`.
  
      See its docstring for more information.
      """
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.equal(x1._array, x2._array))
  
  @np.errstate(all='ignore')
  def exp(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.exp <numpy.exp>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in exp')
      return Array._new(np.exp(x._array))
  
  @np.errstate(all='ignore')
  def expm1(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.expm1 <numpy.expm1>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in expm1')
      return Array._new(np.expm1(x._array))
  
  def floor(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.floor <numpy.floor>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in floor')
      if x.dtype in _integer_dtypes:
          # Note: The return dtype of floor is the same as the input
          return x
      return Array._new(np.floor(x._array))
  
  @np.errstate(all='ignore')
  def floor_divide(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.floor_divide <numpy.floor_divide>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in floor_divide')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.floor_divide(x1._array, x2._array))
  
  def greater(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.greater <numpy.greater>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in greater')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.greater(x1._array, x2._array))
  
  def greater_equal(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.greater_equal <numpy.greater_equal>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in greater_equal')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.greater_equal(x1._array, x2._array))
  
  def isfinite(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.isfinite <numpy.isfinite>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in isfinite')
      return Array._new(np.isfinite(x._array))
  
  def isinf(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.isinf <numpy.isinf>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in isinf')
      return Array._new(np.isinf(x._array))
  
  def isnan(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.isnan <numpy.isnan>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in isnan')
      return Array._new(np.isnan(x._array))
  
  def less(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.less <numpy.less>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in less')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.less(x1._array, x2._array))
  
  def less_equal(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.less_equal <numpy.less_equal>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in less_equal')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.less_equal(x1._array, x2._array))
  
  @np.errstate(all='ignore')
  def log(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.log <numpy.log>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in log')
      return Array._new(np.log(x._array))
  
  @np.errstate(all='ignore')
  def log1p(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.log1p <numpy.log1p>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in log1p')
      return Array._new(np.log1p(x._array))
  
  @np.errstate(all='ignore')
  def log2(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.log2 <numpy.log2>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in log2')
      return Array._new(np.log2(x._
  
  [... the rest is omitted ...]
files: numpy/_array_api/_elementwise_functions.py
files: from __future__ import annotations
  
  from ._dtypes import (_boolean_dtypes, _floating_dtypes,
                        _integer_dtypes, _integer_or_boolean_dtypes,
                        _numeric_dtypes)
  from ._array_object import Array
  
  import numpy as np
  
  def abs(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.abs <numpy.abs>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in abs')
      return Array._new(np.abs(x._array))
  
  # Note: the function name is different here
  @np.errstate(all='ignore')
  def acos(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arccos <numpy.arccos>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in acos')
      return Array._new(np.arccos(x._array))
  
  # Note: the function name is different here
  @np.errstate(all='ignore')
  def acosh(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arccosh <numpy.arccosh>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in acosh')
      return Array._new(np.arccosh(x._array))
  
  @np.errstate(all='ignore')
  def add(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.add <numpy.add>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in add')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.add(x1._array, x2._array))
  
  # Note: the function name is different here
  @np.errstate(all='ignore')
  def asin(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arcsin <numpy.arcsin>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in asin')
      return Array._new(np.arcsin(x._array))
  
  # Note: the function name is different here
  @np.errstate(all='ignore')
  def asinh(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arcsinh <numpy.arcsinh>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in asinh')
      return Array._new(np.arcsinh(x._array))
  
  # Note: the function name is different here
  def atan(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arctan <numpy.arctan>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in atan')
      return Array._new(np.arctan(x._array))
  
  # Note: the function name is different here
  def atan2(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arctan2 <numpy.arctan2>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _floating_dtypes or x2.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in atan2')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.arctan2(x1._array, x2._array))
  
  # Note: the function name is different here
  @np.errstate(all='ignore')
  def atanh(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.arctanh <numpy.arctanh>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in atanh')
      return Array._new(np.arctanh(x._array))
  
  def bitwise_and(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.bitwise_and <numpy.bitwise_and>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _integer_or_boolean_dtypes or x2.dtype not in _integer_or_boolean_dtypes:
          raise TypeError('Only integer_or_boolean dtypes are allowed in bitwise_and')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.bitwise_and(x1._array, x2._array))
  
  # Note: the function name is different here
  def bitwise_left_shift(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.left_shift <numpy.left_shift>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _integer_dtypes or x2.dtype not in _integer_dtypes:
          raise TypeError('Only integer dtypes are allowed in bitwise_left_shift')
      x1, x2 = Array._normalize_two_args(x1, x2)
      # Note: bitwise_left_shift is only defined for x2 nonnegative.
      if np.any(x2._array < 0):
          raise ValueError('bitwise_left_shift(x1, x2) is only defined for x2 >= 0')
      # Note: The spec requires the return dtype of bitwise_left_shift to be the
      # same as the first argument. np.left_shift() returns a type that is the
      # type promotion of the two input types.
      return Array._new(np.left_shift(x1._array, x2._array).astype(x1.dtype))
  
  # Note: the function name is different here
  def bitwise_invert(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.invert <numpy.invert>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _integer_or_boolean_dtypes:
          raise TypeError('Only integer or boolean dtypes are allowed in bitwise_invert')
      return Array._new(np.invert(x._array))
  
  def bitwise_or(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.bitwise_or <numpy.bitwise_or>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _integer_or_boolean_dtypes or x2.dtype not in _integer_or_boolean_dtypes:
          raise TypeError('Only integer or boolean dtypes are allowed in bitwise_or')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.bitwise_or(x1._array, x2._array))
  
  # Note: the function name is different here
  def bitwise_right_shift(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.right_shift <numpy.right_shift>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _integer_dtypes or x2.dtype not in _integer_dtypes:
          raise TypeError('Only integer dtypes are allowed in bitwise_right_shift')
      x1, x2 = Array._normalize_two_args(x1, x2)
      # Note: bitwise_right_shift is only defined for x2 nonnegative.
      if np.any(x2._array < 0):
          raise ValueError('bitwise_right_shift(x1, x2) is only defined for x2 >= 0')
      # Note: The spec requires the return dtype of bitwise_left_shift to be the
      # same as the first argument. np.left_shift() returns a type that is the
      # type promotion of the two input types.
      return Array._new(np.right_shift(x1._array, x2._array).astype(x1.dtype))
  
  def bitwise_xor(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.bitwise_xor <numpy.bitwise_xor>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _integer_or_boolean_dtypes or x2.dtype not in _integer_or_boolean_dtypes:
          raise TypeError('Only integer or boolean dtypes are allowed in bitwise_xor')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.bitwise_xor(x1._array, x2._array))
  
  def ceil(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.ceil <numpy.ceil>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in ceil')
      if x.dtype in _integer_dtypes:
          # Note: The return dtype of ceil is the same as the input
          return x
      return Array._new(np.ceil(x._array))
  
  @np.errstate(all='ignore')
  def cos(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.cos <numpy.cos>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in cos')
      return Array._new(np.cos(x._array))
  
  @np.errstate(all='ignore')
  def cosh(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.cosh <numpy.cosh>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in cosh')
      return Array._new(np.cosh(x._array))
  
  @np.errstate(all='ignore')
  def divide(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.divide <numpy.divide>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _floating_dtypes or x2.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in divide')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.divide(x1._array, x2._array))
  
  def equal(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.equal <numpy.equal>`.
  
      See its docstring for more information.
      """
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.equal(x1._array, x2._array))
  
  @np.errstate(all='ignore')
  def exp(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.exp <numpy.exp>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in exp')
      return Array._new(np.exp(x._array))
  
  @np.errstate(all='ignore')
  def expm1(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.expm1 <numpy.expm1>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in expm1')
      return Array._new(np.expm1(x._array))
  
  def floor(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.floor <numpy.floor>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in floor')
      if x.dtype in _integer_dtypes:
          # Note: The return dtype of floor is the same as the input
          return x
      return Array._new(np.floor(x._array))
  
  @np.errstate(all='ignore')
  def floor_divide(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.floor_divide <numpy.floor_divide>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in floor_divide')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.floor_divide(x1._array, x2._array))
  
  def greater(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.greater <numpy.greater>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in greater')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.greater(x1._array, x2._array))
  
  def greater_equal(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.greater_equal <numpy.greater_equal>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in greater_equal')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.greater_equal(x1._array, x2._array))
  
  def isfinite(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.isfinite <numpy.isfinite>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in isfinite')
      return Array._new(np.isfinite(x._array))
  
  def isinf(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.isinf <numpy.isinf>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in isinf')
      return Array._new(np.isinf(x._array))
  
  def isnan(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.isnan <numpy.isnan>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in isnan')
      return Array._new(np.isnan(x._array))
  
  def less(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.less <numpy.less>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in less')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.less(x1._array, x2._array))
  
  def less_equal(x1: Array, x2: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.less_equal <numpy.less_equal>`.
  
      See its docstring for more information.
      """
      if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
          raise TypeError('Only numeric dtypes are allowed in less_equal')
      x1, x2 = Array._normalize_two_args(x1, x2)
      return Array._new(np.less_equal(x1._array, x2._array))
  
  @np.errstate(all='ignore')
  def log(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.log <numpy.log>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point dtypes are allowed in log')
      return Array._new(np.log(x._array))
  
  @np.errstate(all='ignore')
  def log1p(x: Array, /) -> Array:
      """
      Array API compatible wrapper for :py:func:`np.log1p <numpy.log1p>`.
  
      See its docstring for more information.
      """
      if x.dtype not in _floating_dtypes:
          raise TypeError('Only floating-point
  
  [... the rest is omitted ...]
files: numpy/_array_api/_elementwise_functions.py