|
1 | 1 | """
|
2 | 2 | A NumPy sub-namespace that conforms to the Python array API standard.
|
3 | 3 |
|
| 4 | +This submodule accompanies NEP 47, which proposes its inclusion in NumPy. |
| 5 | +
|
4 | 6 | This is a proof-of-concept namespace that wraps the corresponding NumPy
|
5 | 7 | functions to give a conforming implementation of the Python array API standard
|
6 | 8 | (https://data-apis.github.io/array-api/latest/). The standard is currently in
|
7 | 9 | an RFC phase and comments on it are both welcome and encouraged. Comments
|
8 | 10 | should be made either at https://github.com/data-apis/array-api or at
|
9 | 11 | https://github.com/data-apis/consortium-feedback/discussions.
|
10 | 12 |
|
11 |
| -This submodule will be accompanied with a NEP (not yet written) proposing its |
12 |
| -inclusion in NumPy. |
13 |
| -
|
14 | 13 | NumPy already follows the proposed spec for the most part, so this module
|
15 | 14 | serves mostly as a thin wrapper around it. However, NumPy also implements a
|
16 | 15 | lot of behavior that is not included in the spec, so this serves as a
|
17 | 16 | restricted subset of the API. Only those functions that are part of the spec
|
18 | 17 | are included in this namespace, and all functions are given with the exact
|
19 | 18 | signature given in the spec, including the use of position-only arguments, and
|
20 | 19 | omitting any extra keyword arguments implemented by NumPy but not part of the
|
21 |
| -spec. Note that the array object itself is unchanged, as implementing a |
22 |
| -restricted subclass of ndarray seems unnecessarily complex for the purposes of |
23 |
| -this namespace, so the API of array methods and other behaviors of the array |
24 |
| -object will include things that are not part of the spec. |
25 |
| -
|
26 |
| -The spec is designed as a "minimal API subset" and explicitly allows libraries |
27 |
| -to include behaviors not specified by it. But users of this module that intend |
28 |
| -to write portable code should be aware that only those behaviors that are |
29 |
| -listed in the spec are guaranteed to be implemented across libraries. |
| 20 | +spec. The behavior of some functions is also modified from the NumPy behavior |
| 21 | +to conform to the standard. Note that the underlying array object itself is |
| 22 | +wrapped in a wrapper Array() class, but is otherwise unchanged. This submodule |
| 23 | +is implemented in pure Python with no C extensions. |
| 24 | +
|
| 25 | +The array API spec is designed as a "minimal API subset" and explicitly allows |
| 26 | +libraries to include behaviors not specified by it. But users of this module |
| 27 | +that intend to write portable code should be aware that only those behaviors |
| 28 | +that are listed in the spec are guaranteed to be implemented across libraries. |
| 29 | +Consequently, the NumPy implementation was chosen to be both conforming and |
| 30 | +minimal, so that users can use this implementation of the array API namespace |
| 31 | +and be sure that behaviors that it defines will be available in conforming |
| 32 | +namespaces from other libraries. |
30 | 33 |
|
31 | 34 | A few notes about the current state of this submodule:
|
32 | 35 |
|
|
45 | 48 | not included here, as it requires a full implementation in NumPy proper
|
46 | 49 | first.
|
47 | 50 |
|
48 |
| - - np.argmin and np.argmax do not implement the keepdims keyword argument. |
49 |
| -
|
50 | 51 | - The linear algebra extension in the spec will be added in a future pull
|
51 | 52 | request.
|
52 | 53 |
|
53 |
| - - Some tests in the test suite are still not fully correct in that they test |
54 |
| - all datatypes whereas certain functions are only defined for a subset of |
55 |
| - datatypes. |
56 |
| -
|
57 |
| - The test suite is yet complete, and even the tests that exist are not |
| 54 | + The test suite is not yet complete, and even the tests that exist are not |
58 | 55 | guaranteed to give a comprehensive coverage of the spec. Therefore, those
|
59 | 56 | reviewing this submodule should refer to the standard documents themselves.
|
60 | 57 |
|
|
68 | 65 | dtypes and only those methods that are required by the spec, as well as to
|
69 | 66 | limit/change certain behavior that differs in the spec. In particular:
|
70 | 67 |
|
| 68 | + - The array API namespace does not have scalar objects, only 0-d arrays. |
| 69 | + Operations in on Array that would create a scalar in NumPy create a 0-d |
| 70 | + array. |
| 71 | +
|
71 | 72 | - Indexing: Only a subset of indices supported by NumPy are required by the
|
72 | 73 | spec. The Array object restricts indexing to only allow those types of
|
73 | 74 | indices that are required by the spec. See the docstring of the
|
74 | 75 | numpy._array_api.Array._validate_indices helper function for more
|
75 | 76 | information.
|
76 | 77 |
|
77 | 78 | - Type promotion: Some type promotion rules are different in the spec. In
|
78 |
| - particular, the spec does not have any value-based casting. Note that the |
79 |
| - code to correct the type promotion rules on numpy._array_api.Array is |
80 |
| - not yet implemented. |
| 79 | + particular, the spec does not have any value-based casting. The |
| 80 | + Array._promote_scalar method promotes Python scalars to arrays, |
| 81 | + disallowing cross-type promotions like int -> float64 that are not allowed |
| 82 | + in the spec. Array._normalize_two_args works around some type promotion |
| 83 | + quirks in NumPy, particularly, value-based casting that occurs when one |
| 84 | + argument of an operation is a 0-d array. |
81 | 85 |
|
82 | 86 | - All functions include type annotations, corresponding to those given in the
|
83 |
| - spec (see _types.py for definitions of the types 'array', 'device', and |
84 |
| - 'dtype'). These do not currently fully pass mypy due to some limitations in |
85 |
| - mypy. |
| 87 | + spec (see _types.py for definitions of some custom types). These do not |
| 88 | + currently fully pass mypy due to some limitations in mypy. |
| 89 | +
|
| 90 | +- Dtype objects are just the NumPy dtype objects, e.g., float64 = |
| 91 | + np.dtype('float64'). The spec does not require any behavior on these dtype |
| 92 | + objects other than that they be accessible by name and be comparable by |
| 93 | + equality, but it was considered too much extra complexity to create custom |
| 94 | + objects to represent dtypes. |
86 | 95 |
|
87 | 96 | - The wrapper functions in this module do not do any type checking for things
|
88 |
| - that would be impossible without leaving the _array_api namespace. |
| 97 | + that would be impossible without leaving the _array_api namespace. For |
| 98 | + example, since the array API dtype objects are just the NumPy dtype objects, |
| 99 | + one could pass in a non-spec NumPy dtype into a function. |
89 | 100 |
|
90 | 101 | - All places where the implementations in this submodule are known to deviate
|
91 | 102 | from their corresponding functions in NumPy are marked with "# Note"
|
92 | 103 | comments. Reviewers should make note of these comments.
|
93 | 104 |
|
94 | 105 | Still TODO in this module are:
|
95 | 106 |
|
96 |
| -- Implement the spec type promotion rules on the Array object. |
97 |
| -
|
98 |
| -- Disable NumPy warnings in the API functions. |
99 |
| -
|
100 |
| -- Implement keepdims on argmin and argmax. |
101 |
| -
|
102 | 107 | - Device support and DLPack support are not yet implemented. These require
|
103 | 108 | support in NumPy itself first.
|
104 | 109 |
|
|
0 commit comments