388 lines
10 KiB
Python
388 lines
10 KiB
Python
|
"""
|
||
|
A NumPy sub-namespace that conforms to the Python array API standard.
|
||
|
|
||
|
This submodule accompanies NEP 47, which proposes its inclusion in NumPy. It
|
||
|
is still considered experimental, and will issue a warning when imported.
|
||
|
|
||
|
This is a proof-of-concept namespace that wraps the corresponding NumPy
|
||
|
functions to give a conforming implementation of the Python array API standard
|
||
|
(https://data-apis.github.io/array-api/latest/). The standard is currently in
|
||
|
an RFC phase and comments on it are both welcome and encouraged. Comments
|
||
|
should be made either at https://github.com/data-apis/array-api or at
|
||
|
https://github.com/data-apis/consortium-feedback/discussions.
|
||
|
|
||
|
NumPy already follows the proposed spec for the most part, so this module
|
||
|
serves mostly as a thin wrapper around it. However, NumPy also implements a
|
||
|
lot of behavior that is not included in the spec, so this serves as a
|
||
|
restricted subset of the API. Only those functions that are part of the spec
|
||
|
are included in this namespace, and all functions are given with the exact
|
||
|
signature given in the spec, including the use of position-only arguments, and
|
||
|
omitting any extra keyword arguments implemented by NumPy but not part of the
|
||
|
spec. The behavior of some functions is also modified from the NumPy behavior
|
||
|
to conform to the standard. Note that the underlying array object itself is
|
||
|
wrapped in a wrapper Array() class, but is otherwise unchanged. This submodule
|
||
|
is implemented in pure Python with no C extensions.
|
||
|
|
||
|
The array API spec is designed as a "minimal API subset" and explicitly allows
|
||
|
libraries to include behaviors not specified by it. But users of this module
|
||
|
that intend to write portable code should be aware that only those behaviors
|
||
|
that are listed in the spec are guaranteed to be implemented across libraries.
|
||
|
Consequently, the NumPy implementation was chosen to be both conforming and
|
||
|
minimal, so that users can use this implementation of the array API namespace
|
||
|
and be sure that behaviors that it defines will be available in conforming
|
||
|
namespaces from other libraries.
|
||
|
|
||
|
A few notes about the current state of this submodule:
|
||
|
|
||
|
- There is a test suite that tests modules against the array API standard at
|
||
|
https://github.com/data-apis/array-api-tests. The test suite is still a work
|
||
|
in progress, but the existing tests pass on this module, with a few
|
||
|
exceptions:
|
||
|
|
||
|
- DLPack support (see https://github.com/data-apis/array-api/pull/106) is
|
||
|
not included here, as it requires a full implementation in NumPy proper
|
||
|
first.
|
||
|
|
||
|
The test suite is not yet complete, and even the tests that exist are not
|
||
|
guaranteed to give a comprehensive coverage of the spec. Therefore, when
|
||
|
reviewing and using this submodule, you should refer to the standard
|
||
|
documents themselves. There are some tests in numpy.array_api.tests, but
|
||
|
they primarily focus on things that are not tested by the official array API
|
||
|
test suite.
|
||
|
|
||
|
- There is a custom array object, numpy.array_api.Array, which is returned by
|
||
|
all functions in this module. All functions in the array API namespace
|
||
|
implicitly assume that they will only receive this object as input. The only
|
||
|
way to create instances of this object is to use one of the array creation
|
||
|
functions. It does not have a public constructor on the object itself. The
|
||
|
object is a small wrapper class around numpy.ndarray. The main purpose of it
|
||
|
is to restrict the namespace of the array object to only those dtypes and
|
||
|
only those methods that are required by the spec, as well as to limit/change
|
||
|
certain behavior that differs in the spec. In particular:
|
||
|
|
||
|
- The array API namespace does not have scalar objects, only 0-D arrays.
|
||
|
Operations on Array that would create a scalar in NumPy create a 0-D
|
||
|
array.
|
||
|
|
||
|
- Indexing: Only a subset of indices supported by NumPy are required by the
|
||
|
spec. The Array object restricts indexing to only allow those types of
|
||
|
indices that are required by the spec. See the docstring of the
|
||
|
numpy.array_api.Array._validate_indices helper function for more
|
||
|
information.
|
||
|
|
||
|
- Type promotion: Some type promotion rules are different in the spec. In
|
||
|
particular, the spec does not have any value-based casting. The spec also
|
||
|
does not require cross-kind casting, like integer -> floating-point. Only
|
||
|
those promotions that are explicitly required by the array API
|
||
|
specification are allowed in this module. See NEP 47 for more info.
|
||
|
|
||
|
- Functions do not automatically call asarray() on their input, and will not
|
||
|
work if the input type is not Array. The exception is array creation
|
||
|
functions, and Python operators on the Array object, which accept Python
|
||
|
scalars of the same type as the array dtype.
|
||
|
|
||
|
- All functions include type annotations, corresponding to those given in the
|
||
|
spec (see _typing.py for definitions of some custom types). These do not
|
||
|
currently fully pass mypy due to some limitations in mypy.
|
||
|
|
||
|
- Dtype objects are just the NumPy dtype objects, e.g., float64 =
|
||
|
np.dtype('float64'). The spec does not require any behavior on these dtype
|
||
|
objects other than that they be accessible by name and be comparable by
|
||
|
equality, but it was considered too much extra complexity to create custom
|
||
|
objects to represent dtypes.
|
||
|
|
||
|
- All places where the implementations in this submodule are known to deviate
|
||
|
from their corresponding functions in NumPy are marked with "# Note:"
|
||
|
comments.
|
||
|
|
||
|
Still TODO in this module are:
|
||
|
|
||
|
- DLPack support for numpy.ndarray is still in progress. See
|
||
|
https://github.com/numpy/numpy/pull/19083.
|
||
|
|
||
|
- The copy=False keyword argument to asarray() is not yet implemented. This
|
||
|
requires support in numpy.asarray() first.
|
||
|
|
||
|
- Some functions are not yet fully tested in the array API test suite, and may
|
||
|
require updates that are not yet known until the tests are written.
|
||
|
|
||
|
- The spec is still in an RFC phase and may still have minor updates, which
|
||
|
will need to be reflected here.
|
||
|
|
||
|
- Complex number support in array API spec is planned but not yet finalized,
|
||
|
as are the fft extension and certain linear algebra functions such as eig
|
||
|
that require complex dtypes.
|
||
|
|
||
|
"""
|
||
|
|
||
|
import warnings
|
||
|
|
||
|
warnings.warn(
|
||
|
"The numpy.array_api submodule is still experimental. See NEP 47.", stacklevel=2
|
||
|
)
|
||
|
|
||
|
__array_api_version__ = "2022.12"
|
||
|
|
||
|
__all__ = ["__array_api_version__"]
|
||
|
|
||
|
from ._constants import e, inf, nan, pi, newaxis
|
||
|
|
||
|
__all__ += ["e", "inf", "nan", "pi", "newaxis"]
|
||
|
|
||
|
from ._creation_functions import (
|
||
|
asarray,
|
||
|
arange,
|
||
|
empty,
|
||
|
empty_like,
|
||
|
eye,
|
||
|
from_dlpack,
|
||
|
full,
|
||
|
full_like,
|
||
|
linspace,
|
||
|
meshgrid,
|
||
|
ones,
|
||
|
ones_like,
|
||
|
tril,
|
||
|
triu,
|
||
|
zeros,
|
||
|
zeros_like,
|
||
|
)
|
||
|
|
||
|
__all__ += [
|
||
|
"asarray",
|
||
|
"arange",
|
||
|
"empty",
|
||
|
"empty_like",
|
||
|
"eye",
|
||
|
"from_dlpack",
|
||
|
"full",
|
||
|
"full_like",
|
||
|
"linspace",
|
||
|
"meshgrid",
|
||
|
"ones",
|
||
|
"ones_like",
|
||
|
"tril",
|
||
|
"triu",
|
||
|
"zeros",
|
||
|
"zeros_like",
|
||
|
]
|
||
|
|
||
|
from ._data_type_functions import (
|
||
|
astype,
|
||
|
broadcast_arrays,
|
||
|
broadcast_to,
|
||
|
can_cast,
|
||
|
finfo,
|
||
|
isdtype,
|
||
|
iinfo,
|
||
|
result_type,
|
||
|
)
|
||
|
|
||
|
__all__ += [
|
||
|
"astype",
|
||
|
"broadcast_arrays",
|
||
|
"broadcast_to",
|
||
|
"can_cast",
|
||
|
"finfo",
|
||
|
"iinfo",
|
||
|
"result_type",
|
||
|
]
|
||
|
|
||
|
from ._dtypes import (
|
||
|
int8,
|
||
|
int16,
|
||
|
int32,
|
||
|
int64,
|
||
|
uint8,
|
||
|
uint16,
|
||
|
uint32,
|
||
|
uint64,
|
||
|
float32,
|
||
|
float64,
|
||
|
complex64,
|
||
|
complex128,
|
||
|
bool,
|
||
|
)
|
||
|
|
||
|
__all__ += [
|
||
|
"int8",
|
||
|
"int16",
|
||
|
"int32",
|
||
|
"int64",
|
||
|
"uint8",
|
||
|
"uint16",
|
||
|
"uint32",
|
||
|
"uint64",
|
||
|
"float32",
|
||
|
"float64",
|
||
|
"bool",
|
||
|
]
|
||
|
|
||
|
from ._elementwise_functions import (
|
||
|
abs,
|
||
|
acos,
|
||
|
acosh,
|
||
|
add,
|
||
|
asin,
|
||
|
asinh,
|
||
|
atan,
|
||
|
atan2,
|
||
|
atanh,
|
||
|
bitwise_and,
|
||
|
bitwise_left_shift,
|
||
|
bitwise_invert,
|
||
|
bitwise_or,
|
||
|
bitwise_right_shift,
|
||
|
bitwise_xor,
|
||
|
ceil,
|
||
|
conj,
|
||
|
cos,
|
||
|
cosh,
|
||
|
divide,
|
||
|
equal,
|
||
|
exp,
|
||
|
expm1,
|
||
|
floor,
|
||
|
floor_divide,
|
||
|
greater,
|
||
|
greater_equal,
|
||
|
imag,
|
||
|
isfinite,
|
||
|
isinf,
|
||
|
isnan,
|
||
|
less,
|
||
|
less_equal,
|
||
|
log,
|
||
|
log1p,
|
||
|
log2,
|
||
|
log10,
|
||
|
logaddexp,
|
||
|
logical_and,
|
||
|
logical_not,
|
||
|
logical_or,
|
||
|
logical_xor,
|
||
|
multiply,
|
||
|
negative,
|
||
|
not_equal,
|
||
|
positive,
|
||
|
pow,
|
||
|
real,
|
||
|
remainder,
|
||
|
round,
|
||
|
sign,
|
||
|
sin,
|
||
|
sinh,
|
||
|
square,
|
||
|
sqrt,
|
||
|
subtract,
|
||
|
tan,
|
||
|
tanh,
|
||
|
trunc,
|
||
|
)
|
||
|
|
||
|
__all__ += [
|
||
|
"abs",
|
||
|
"acos",
|
||
|
"acosh",
|
||
|
"add",
|
||
|
"asin",
|
||
|
"asinh",
|
||
|
"atan",
|
||
|
"atan2",
|
||
|
"atanh",
|
||
|
"bitwise_and",
|
||
|
"bitwise_left_shift",
|
||
|
"bitwise_invert",
|
||
|
"bitwise_or",
|
||
|
"bitwise_right_shift",
|
||
|
"bitwise_xor",
|
||
|
"ceil",
|
||
|
"cos",
|
||
|
"cosh",
|
||
|
"divide",
|
||
|
"equal",
|
||
|
"exp",
|
||
|
"expm1",
|
||
|
"floor",
|
||
|
"floor_divide",
|
||
|
"greater",
|
||
|
"greater_equal",
|
||
|
"isfinite",
|
||
|
"isinf",
|
||
|
"isnan",
|
||
|
"less",
|
||
|
"less_equal",
|
||
|
"log",
|
||
|
"log1p",
|
||
|
"log2",
|
||
|
"log10",
|
||
|
"logaddexp",
|
||
|
"logical_and",
|
||
|
"logical_not",
|
||
|
"logical_or",
|
||
|
"logical_xor",
|
||
|
"multiply",
|
||
|
"negative",
|
||
|
"not_equal",
|
||
|
"positive",
|
||
|
"pow",
|
||
|
"remainder",
|
||
|
"round",
|
||
|
"sign",
|
||
|
"sin",
|
||
|
"sinh",
|
||
|
"square",
|
||
|
"sqrt",
|
||
|
"subtract",
|
||
|
"tan",
|
||
|
"tanh",
|
||
|
"trunc",
|
||
|
]
|
||
|
|
||
|
from ._indexing_functions import take
|
||
|
|
||
|
__all__ += ["take"]
|
||
|
|
||
|
# linalg is an extension in the array API spec, which is a sub-namespace. Only
|
||
|
# a subset of functions in it are imported into the top-level namespace.
|
||
|
from . import linalg
|
||
|
|
||
|
__all__ += ["linalg"]
|
||
|
|
||
|
from .linalg import matmul, tensordot, matrix_transpose, vecdot
|
||
|
|
||
|
__all__ += ["matmul", "tensordot", "matrix_transpose", "vecdot"]
|
||
|
|
||
|
from ._manipulation_functions import (
|
||
|
concat,
|
||
|
expand_dims,
|
||
|
flip,
|
||
|
permute_dims,
|
||
|
reshape,
|
||
|
roll,
|
||
|
squeeze,
|
||
|
stack,
|
||
|
)
|
||
|
|
||
|
__all__ += ["concat", "expand_dims", "flip", "permute_dims", "reshape", "roll", "squeeze", "stack"]
|
||
|
|
||
|
from ._searching_functions import argmax, argmin, nonzero, where
|
||
|
|
||
|
__all__ += ["argmax", "argmin", "nonzero", "where"]
|
||
|
|
||
|
from ._set_functions import unique_all, unique_counts, unique_inverse, unique_values
|
||
|
|
||
|
__all__ += ["unique_all", "unique_counts", "unique_inverse", "unique_values"]
|
||
|
|
||
|
from ._sorting_functions import argsort, sort
|
||
|
|
||
|
__all__ += ["argsort", "sort"]
|
||
|
|
||
|
from ._statistical_functions import max, mean, min, prod, std, sum, var
|
||
|
|
||
|
__all__ += ["max", "mean", "min", "prod", "std", "sum", "var"]
|
||
|
|
||
|
from ._utility_functions import all, any
|
||
|
|
||
|
__all__ += ["all", "any"]
|