Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopt the numpy.array_api module as cupy.array_api #5698

Merged
merged 165 commits into from
Sep 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
165 commits
Select commit Hold shift + click to select a range
f290297
Add initial array_api sub-namespace
asmeurer Jan 11, 2021
6e0b163
Add dtypes to the _array_api namespace
asmeurer Jan 11, 2021
bc6cd91
Fix array API functions that are named differently or not in the defa…
asmeurer Jan 11, 2021
0d2f35d
Fix the bool name in the array API namespace
asmeurer Jan 12, 2021
2a9765a
Fix different names for some bitwise functions in the array apis
asmeurer Jan 12, 2021
94980e5
Fix different behavior of norm() with axis=None in the array API name…
asmeurer Jan 12, 2021
7940635
Correct some differing keyword arguments in the array API namespace
asmeurer Jan 12, 2021
a45d744
Add the device keyword to the array creation functions
asmeurer Jan 12, 2021
5d602a5
Make the array_api submodules private, and remove __all__ from indivi…
asmeurer Jan 12, 2021
5dfd723
Add missing returns to the array API sorting functions
asmeurer Jan 12, 2021
1587e46
Fix the array_api submodule __init__.py imports
asmeurer Jan 12, 2021
dad5148
Use "import numpy as np" in the array_api submodule
asmeurer Jan 12, 2021
58140bc
Fix array API functions that need to use np.linalg
asmeurer Jan 12, 2021
f2f5039
Add basic docstrings to the array API wrapper functions
asmeurer Jan 12, 2021
0da4b09
Add an explanatory docstring to _array_api/__init__.py
asmeurer Jan 13, 2021
adefed2
Add type annotations to the array api submodule function definitions
asmeurer Jan 20, 2021
d2c4fcf
Fix some incorrect type annotations in the array API submodule
asmeurer Jan 21, 2021
70155e6
Use np.asarray in the array API submodule for any function that can r…
asmeurer Jan 21, 2021
76eb888
Use _implementation on all functions that have it in the array API su…
asmeurer Jan 21, 2021
9639de2
Add some more notes to the array API module docstring
asmeurer Jan 21, 2021
9c2f8b8
Update array_api namespace with latest changes from the spec
asmeurer Feb 23, 2021
d185d4b
Start implementing wrapper object for the array API
asmeurer Feb 24, 2021
e1ff4f9
Add some missing names in the array_api namespace __all__
asmeurer Feb 24, 2021
0d7999a
Fix the copy keyword argument in the array_api namespace asarray()
asmeurer Feb 24, 2021
19ecbe7
Implement a simple passthrough __str__ and __repr__ on the array_api …
asmeurer Feb 24, 2021
29f8cc2
Only allow supported dtypes in the array_api namespace asarray()
asmeurer Feb 24, 2021
1ae8959
Support array_api.ndarray in array_api.asarray()
asmeurer Feb 24, 2021
89016b0
Return ndarray in the array_api namespace elementwise functions
asmeurer Feb 27, 2021
783595e
Use a different repr form for array_api.ndarray than array
asmeurer Feb 27, 2021
e71addb
Fix the dunder methods on array_api.ndarray
asmeurer Feb 27, 2021
e753072
Use ndarray in the array API creation functions
asmeurer Feb 27, 2021
26c6348
Only allow the spec guaranteed dtypes in the array API elementwise fu…
asmeurer Feb 27, 2021
5463790
Make an error message easier to read
asmeurer Feb 27, 2021
2e56f8e
Don't check if a dtype is in all_dtypes
asmeurer Feb 27, 2021
0223975
Allow dimension 0 arrays in the array API namespace full() and full_l…
asmeurer Feb 27, 2021
e6fa443
Make the array API constants into dimension 0 arrays
asmeurer Feb 27, 2021
c09758c
Clean up some imports
asmeurer Feb 27, 2021
2c63f78
Fix some dunder methods on that should not be converting things to ar…
asmeurer Mar 2, 2021
e8055d1
Make the array API manipulation functions use the array API ndarray o…
asmeurer Mar 2, 2021
cdef60d
Only allow __bool__, __int__, and __float__ on arrays with shape ()
asmeurer Mar 2, 2021
f523a11
Remove _implementation from the array API functions
asmeurer Mar 2, 2021
bdb60bd
Make sure the array API ndarray object cannot wrap an array scalar
asmeurer Mar 2, 2021
e0adef8
Support the ndarray object in the remaining array API functions
asmeurer Mar 5, 2021
d9df101
Only allow indices that are required by the spec in the array API nam…
asmeurer Mar 9, 2021
2151f10
Update the state of the array API in the __init__.py docstring
asmeurer Mar 9, 2021
73fb624
Implement __array_namespace__ on the array API ndarray object
asmeurer Mar 10, 2021
4154f92
Use 'self' and 'other' for the array API ndarray method parameter names
asmeurer Mar 10, 2021
da01464
Update the array API namespace __init__.py docstring with todos
asmeurer Mar 10, 2021
b954e7e
Add a small docstring to the array API ndarray object
asmeurer Mar 10, 2021
f64447c
Use the array API types for the array API type annotations
asmeurer Mar 10, 2021
a085278
Only return the same array in asarray if the dtype is the same
asmeurer Mar 11, 2021
6e00aee
Use more robust code for converting an array scalar to a shape () array
asmeurer Mar 11, 2021
1e0d72f
Fix circular imports from types
asmeurer Mar 18, 2021
c48dc90
bitwise_left_shift and bitwise_right_shift should return the dtype of…
asmeurer Mar 18, 2021
bdeb4ab
bitwise_left_shift and bitwise_right_shift are only defined for x2 >= 0
asmeurer Mar 18, 2021
bac32a2
Update some annotations updated from the spec
asmeurer Mar 30, 2021
c0a330c
Make the array API follow the spec Python scalar promotion rules
asmeurer Mar 31, 2021
8a38161
Give a better error message in the array API asarray for out of bound…
asmeurer Mar 31, 2021
e629546
Fix int bounds checking in asarray() to only happen when dtype=None
asmeurer Apr 13, 2021
07b92f2
Fix ceil() and floor() in the array API to always return the same dtype
asmeurer Apr 14, 2021
ffbe9c1
Move function name change notes to before the def line
asmeurer Apr 14, 2021
936db17
Use dtype objects instead of classes in the array API
asmeurer Apr 15, 2021
a26de3b
Fix type promotion consistency for the array API elementwise function…
asmeurer Apr 15, 2021
e33d630
Add meshgrid(), broadcast_arrays(), broadcast_to(), and can_cast() to…
asmeurer Apr 26, 2021
674dbdd
Update signatures in the array API namespace from the latest version …
asmeurer Apr 28, 2021
b439d70
Fix some error messages
asmeurer Apr 30, 2021
c71899b
Fix the array API norm() function
asmeurer May 10, 2021
b543e3d
Fix array API squeeze() and stack()
asmeurer May 10, 2021
5e9fda2
Make the array API constants Python floats
asmeurer May 10, 2021
66d9a39
Ignore warnings in array API functions that can raise them
asmeurer May 17, 2021
1a1ddf8
Update signatures from the latest version of the array API spec
asmeurer May 20, 2021
c94883a
Update a function signature from the array API spec
asmeurer Jun 14, 2021
bbd6b04
Update the linear algebra functions in the array API namespace
asmeurer Jul 1, 2021
2af28f4
Fix in-place operators to not recreate the wrapper class
asmeurer Jul 8, 2021
3eb5d22
Fix the __imatmul__ method in the array API namespace
asmeurer Jul 8, 2021
0c13a3e
Capitalize the names of the type hint types in the array API
asmeurer Jul 8, 2021
9e232ff
Rename the array class in the array API namespace from ndarray to Array
asmeurer Jul 8, 2021
797150c
Update the docstring of numpy/_array_api/__init__.py
asmeurer Jul 8, 2021
285cc0b
Remove typing exports from numpy/_array_api/_types.py
asmeurer Jul 9, 2021
a703bed
Use better type definitions for the array API custom types
asmeurer Jul 9, 2021
994ce07
Use better type signatures in the array API module
asmeurer Jul 9, 2021
5026ed9
Small code cleanup
asmeurer Jul 9, 2021
c38c6b8
Rename numpy/_array_api/_types.py to numpy/_array_api/_typing.py
asmeurer Jul 9, 2021
f5a2310
Only allow floating-point dtypes in the array API __pow__ and __trued…
asmeurer Jul 9, 2021
e89d82a
Update the type hints for the array API __pow__ and __truediv__
asmeurer Jul 9, 2021
0dda4e6
Use tuples for internal type lists in the array API
asmeurer Jul 9, 2021
a086d8c
Fix some typing imports
asmeurer Jul 9, 2021
3f46d66
Fix the type hints for argmin/argmax in the array API
asmeurer Jul 9, 2021
207d779
Fix typo
asmeurer Jul 9, 2021
783d157
Make the array API left and right shift do type promotion
asmeurer Jul 10, 2021
379b2ad
Use ndim == 0 instead of shape == () in the array API code
asmeurer Jul 15, 2021
1ddbd5c
Correct disallow things like a[(0, 1), (0, 1)] in the array API names…
asmeurer Jul 15, 2021
575e019
Add a comment about the _normalize_two_args trick
asmeurer Jul 15, 2021
084b819
Move _validate_index above the methods that are actually part of the …
asmeurer Jul 15, 2021
330eac2
Remove error ignoring in the array API namespace
asmeurer Jul 16, 2021
229a9b3
Fix some spelling errors
asmeurer Jul 16, 2021
654ecf4
Make numpy._array_api.Array.device return "cpu"
asmeurer Jul 16, 2021
9fdfac2
Guard against non-array API inputs in the array API result_type()
asmeurer Jul 16, 2021
8d1ee76
Move the dtype check to the array API Array._new constructor
asmeurer Jul 16, 2021
12129c8
Use asarray to convert a scalar into an array in the array API Array …
asmeurer Jul 16, 2021
4e28c9e
Remove an unnecessary indexing
asmeurer Jul 16, 2021
a96a571
Add type hints to the array API __setitem__
asmeurer Jul 16, 2021
bf2890f
Change the type hint for stream __dlpack__ to just None
asmeurer Jul 16, 2021
30778f7
Start adding tests for the array API submodule
asmeurer Jul 19, 2021
e688ea0
Always include the dtype in the array API Array repr
asmeurer Jul 21, 2021
ccbe442
Add bool and int explicitly to the array API asarray() input type hints
asmeurer Jul 21, 2021
29535ad
Implement the array API result_type() manually
asmeurer Jul 21, 2021
8f771de
Fix a typo in an error message
asmeurer Jul 21, 2021
b2c4246
Restrict the array API namespace array operator type promotions
asmeurer Jul 21, 2021
898e3d9
Use ValueError instead of TypeError for array API @=
asmeurer Jul 22, 2021
b82fcbc
Add some more comments about array API type promotion stuff
asmeurer Jul 22, 2021
3e56849
Prevent unwanted type promotions everywhere in the array API namespace
asmeurer Jul 22, 2021
8316e68
Remove some dead code
asmeurer Jul 22, 2021
caf16dc
Add tests for Python scalar constructors on array API arrays
asmeurer Jul 22, 2021
5d62c00
Fix the array API __abs__() to restrict to numeric dtypes
asmeurer Jul 23, 2021
dab0e39
Fix the array API trunc() to return the same dtype as the input
asmeurer Jul 23, 2021
75dba89
Fix the array API Array.__setitem__
asmeurer Jul 23, 2021
eebbc67
Add tests for error cases for the array API elementwise functions
asmeurer Jul 23, 2021
409e79b
Assume the current array API version is 2021.<something>
asmeurer Jul 23, 2021
a0976d0
Only allow dtypes to be spelled with their names in the array API
asmeurer Jul 23, 2021
0878800
Allow setting device='cpu' in the array API creation functions
asmeurer Jul 24, 2021
866b5e5
Enable asarray(copy=True) in the array API namespace
asmeurer Jul 24, 2021
8f9955a
Add a TODO comment
asmeurer Jul 24, 2021
694651a
Add tests for the array API creation functions
asmeurer Jul 24, 2021
29de791
Rename numpy._array_api to numpy.array_api
asmeurer Aug 4, 2021
6b1684b
Print a warning when importing the numpy.array_api submodule
asmeurer Aug 4, 2021
46f568a
Remove no longer comment about the keepdims argument to argmin
asmeurer Aug 5, 2021
ac57827
Remove asarray() calls from the array API statistical functions
asmeurer Aug 5, 2021
bb92224
Remove unused import
asmeurer Aug 5, 2021
61140a7
Move the array API dtype categories into the top level
asmeurer Aug 5, 2021
cd31414
Move some imports out of functions to the top of the file
asmeurer Aug 5, 2021
04be0e0
Fix casting for the array API concat() and stack()
asmeurer Aug 5, 2021
c69663a
Give a better error when numpy.array_api is imported in Python 3.7
asmeurer Aug 5, 2021
c7d5fd0
Add a setup.py to the array_api submodule
asmeurer Aug 6, 2021
62cc871
Fix some dictionary key mismatches in the array API tests
asmeurer Aug 6, 2021
becc418
Fix the array API __len__ method
asmeurer Aug 6, 2021
356891c
Fix the array API unique() function
asmeurer Aug 6, 2021
dbcb237
Make the axis argument to squeeze() in the array_api module positiona…
asmeurer Aug 6, 2021
e080ea1
Fix the array API nonzero() function
asmeurer Aug 6, 2021
e55dc3c
Update the docstring of numpy.array_api
asmeurer Aug 7, 2021
729b359
Run (selective) black on the array_api submodule
asmeurer Aug 7, 2021
3a2dbc5
Fix the return annotation for numpy.array_api.Array.__setitem__
asmeurer Aug 12, 2021
1114fa1
Add smallest_normal to the array API finfo
asmeurer Aug 12, 2021
8692831
Remove Python 3.7 checks from the array API code
asmeurer Aug 23, 2021
9febe14
Add a release note entry for #18585
asmeurer Aug 23, 2021
fb93033
Remove an unused import
asmeurer Aug 23, 2021
370c7db
move array_api from numpy to cupyx
leofang Sep 5, 2021
e3104ec
replace most numpy/np by cupy/cp
leofang Sep 5, 2021
c271454
enable very basic array_api operations
leofang Sep 5, 2021
5fecd61
remove irrelevant files
leofang Sep 5, 2021
d2a7803
avoid linting on the array_api module
leofang Sep 5, 2021
55e6a54
move numpy/array_api/tests to tests/cupyx_tests/array_api_tests
leofang Sep 6, 2021
d65bde2
fix doc build
leofang Sep 6, 2021
7972a88
more linter fixes...
leofang Sep 6, 2021
c70c449
try adding the comparison table
leofang Sep 6, 2021
f154282
comment out the comparison table addition for now
leofang Sep 6, 2021
03280a0
add device support
leofang Sep 6, 2021
df769af
provide basic array api docs
leofang Sep 6, 2021
3e9c65d
require PY38+ to run the local array api tests
leofang Sep 6, 2021
ce6d809
fix for dlpack and smallest_normal
leofang Sep 6, 2021
b81eb39
build a skeleton for docs
leofang Sep 7, 2021
d3a6f0d
expand docs
leofang Sep 8, 2021
9e6f428
Merge branch 'master' into array_api_from_numpy
leofang Sep 24, 2021
05b7dd6
move array_api from cupyx to cupy
leofang Sep 24, 2021
7e8191c
revert cupy/cp back to numpy/np for easier patch application
leofang Sep 24, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/pretest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ jobs:
- name: setup python
uses: actions/setup-python@v2
with:
python-version: '3.7'
# cupyx.array_api uses Python 3.8 syntaxes
python-version: '3.8'

- name: install
run: |
Expand Down
370 changes: 370 additions & 0 deletions cupy/array_api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,370 @@
"""
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.

- The linear algebra extension in the spec will be added in a future pull
request.

- 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
)

__all__ = []

from ._constants import e, inf, nan, pi

__all__ += ["e", "inf", "nan", "pi"]

from ._creation_functions import (
asarray,
arange,
empty,
empty_like,
eye,
from_dlpack,
full,
full_like,
linspace,
meshgrid,
ones,
ones_like,
zeros,
zeros_like,
)

__all__ += [
"asarray",
"arange",
"empty",
"empty_like",
"eye",
"from_dlpack",
"full",
"full_like",
"linspace",
"meshgrid",
"ones",
"ones_like",
"zeros",
"zeros_like",
]

from ._data_type_functions import (
broadcast_arrays,
broadcast_to,
can_cast,
finfo,
iinfo,
result_type,
)

__all__ += [
"broadcast_arrays",
"broadcast_to",
"can_cast",
"finfo",
"iinfo",
"result_type",
]

from ._dtypes import (
int8,
int16,
int32,
int64,
uint8,
uint16,
uint32,
uint64,
float32,
float64,
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,
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,
)

__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",
]

# einsum is not yet implemented in the array API spec.

# from ._linear_algebra_functions import einsum
# __all__ += ['einsum']

from ._linear_algebra_functions import matmul, tensordot, transpose, vecdot

__all__ += ["matmul", "tensordot", "transpose", "vecdot"]

from ._manipulation_functions import (
concat,
expand_dims,
flip,
reshape,
roll,
squeeze,
stack,
)

__all__ += ["concat", "expand_dims", "flip", "reshape", "roll", "squeeze", "stack"]

from ._searching_functions import argmax, argmin, nonzero, where

__all__ += ["argmax", "argmin", "nonzero", "where"]

from ._set_functions import unique

__all__ += ["unique"]

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"]