From e170b0e48ac8d6555ee5bd8baf05004b4dfcb8af Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 4 Oct 2021 10:46:41 -0700 Subject: [PATCH 1/9] Add examples to note --- spec/API_specification/indexing.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/API_specification/indexing.md b/spec/API_specification/indexing.md index c448b01be..c58afcee8 100644 --- a/spec/API_specification/indexing.md +++ b/spec/API_specification/indexing.md @@ -134,7 +134,11 @@ Multi-dimensional arrays must extend the concept of single-axis indexing to mult - Each axis may be independently indexed via single-axis indexing by providing a comma-separated sequence ("selection tuple") of single-axis indexing expressions (e.g., `A[:, 2:10, :, 5]`). ```{note} - In Python, `x[(exp1, exp2, ..., expN)]` is equivalent to `x[exp1, exp2, ..., expN]`; the latter is syntactic sugar for the former. + In Python, `A[(exp1, exp2, ..., expN)]` is equivalent to `A[exp1, exp2, ..., expN]`; the latter is syntactic sugar for the former. + + Accordingly, if `A` has rank `1`, then `A[(2:10,)]` must be equivalent to `A[2:10]`. If `A` has rank `2`, then `A[(2:10, :)]` must be equivalent to `A[2:10, :]`. And so on and so forth. + + To access the value in a zero-dimensional array, one must provide an empty tuple; e.g., `A[()]`. ``` - Providing a single nonnegative integer `i` as a single-axis index must index the same elements as the slice `i:i+1`. From 08b3dd6c22a4e7fef1ee778bdcca48746e0846e7 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 7 Oct 2021 02:33:17 -0700 Subject: [PATCH 2/9] Remove sentence --- spec/API_specification/indexing.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/API_specification/indexing.md b/spec/API_specification/indexing.md index c58afcee8..f60a15743 100644 --- a/spec/API_specification/indexing.md +++ b/spec/API_specification/indexing.md @@ -137,8 +137,6 @@ Multi-dimensional arrays must extend the concept of single-axis indexing to mult In Python, `A[(exp1, exp2, ..., expN)]` is equivalent to `A[exp1, exp2, ..., expN]`; the latter is syntactic sugar for the former. Accordingly, if `A` has rank `1`, then `A[(2:10,)]` must be equivalent to `A[2:10]`. If `A` has rank `2`, then `A[(2:10, :)]` must be equivalent to `A[2:10, :]`. And so on and so forth. - - To access the value in a zero-dimensional array, one must provide an empty tuple; e.g., `A[()]`. ``` - Providing a single nonnegative integer `i` as a single-axis index must index the same elements as the slice `i:i+1`. From 1c95ed7016de326e352cd0df81e5f468ab21d947 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 7 Oct 2021 02:45:27 -0700 Subject: [PATCH 3/9] Add note --- spec/API_specification/indexing.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/API_specification/indexing.md b/spec/API_specification/indexing.md index f60a15743..4de738618 100644 --- a/spec/API_specification/indexing.md +++ b/spec/API_specification/indexing.md @@ -60,7 +60,6 @@ A[i:j:k] ``` ```{note} - Slice syntax can be equivalently achieved using the Python built-in [`slice()`](https://docs.python.org/3/library/functions.html#slice) API. From the perspective of `A`, the behavior of `A[i:j:k]` and `A[slice(i, j, k)]` is indistinguishable (i.e., both retrieve the same set of items from `__getitem__`). ``` @@ -145,6 +144,10 @@ Multi-dimensional arrays must extend the concept of single-axis indexing to mult - Providing a single integer as a single-axis index must reduce the number of array dimensions by `1` (i.e., the array rank should decrease by one; if `A` has rank `2`, `rank(A)-1 == rank(A[0, :])`). In particular, a selection tuple with the `m`th element an integer (and all other entries `:`) indexes a sub-array with rank `N-1`. + ```{note} + When providing a single integer as a single-axis index to an array of rank `1`, the result should be an array of rank `0`, not a Python scalar. Note that this behavior differs from NumPy. + ``` + - Providing a slice must retain array dimensions (i.e., the array rank must remain the same; `rank(A) == rank(A[:])`). - Providing [ellipsis](https://docs.python.org/3/library/constants.html#Ellipsis) must apply `:` to each dimension necessary to index all dimensions (e.g., if `A` has rank `4`, `A[1:, ..., 2:5] == A[1:, :, :, 2:5]`). Only a single ellipsis must be allowed. An `IndexError` exception must be raised if more than one ellipsis is provided. From 58271c725c02f8d2513ada9eb399c53331367b37 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 7 Oct 2021 02:47:59 -0700 Subject: [PATCH 4/9] Add note regarding providing an empty tuple to a rank 0 array --- spec/API_specification/indexing.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/API_specification/indexing.md b/spec/API_specification/indexing.md index 4de738618..5ff5f692f 100644 --- a/spec/API_specification/indexing.md +++ b/spec/API_specification/indexing.md @@ -150,6 +150,8 @@ Multi-dimensional arrays must extend the concept of single-axis indexing to mult - Providing a slice must retain array dimensions (i.e., the array rank must remain the same; `rank(A) == rank(A[:])`). +- Providing an empty tuple to an array of rank `0` must result in an array of the same rank (i.e., if `A` has rank `0`, `A == A[()]`). + - Providing [ellipsis](https://docs.python.org/3/library/constants.html#Ellipsis) must apply `:` to each dimension necessary to index all dimensions (e.g., if `A` has rank `4`, `A[1:, ..., 2:5] == A[1:, :, :, 2:5]`). Only a single ellipsis must be allowed. An `IndexError` exception must be raised if more than one ellipsis is provided. - Except in the case of providing an ellipsis to index all trailing dimensions (e.g., `A[2:10, ...]`), the number of provided single-axis indexing expressions must equal `N`. For example, if `A` has rank `2`, a single-axis indexing expression must be explicitly provided for both axes (e.g., `A[2:10, :]`). An `IndexError` exception must be raised if the number of provided single-axis indexing expressions is less than `N`. From f42af51bd1f9f1b64217ba404944649e16d387e7 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 7 Oct 2021 02:50:30 -0700 Subject: [PATCH 5/9] Add note --- spec/API_specification/indexing.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spec/API_specification/indexing.md b/spec/API_specification/indexing.md index 5ff5f692f..c1aca930d 100644 --- a/spec/API_specification/indexing.md +++ b/spec/API_specification/indexing.md @@ -150,10 +150,14 @@ Multi-dimensional arrays must extend the concept of single-axis indexing to mult - Providing a slice must retain array dimensions (i.e., the array rank must remain the same; `rank(A) == rank(A[:])`). -- Providing an empty tuple to an array of rank `0` must result in an array of the same rank (i.e., if `A` has rank `0`, `A == A[()]`). - - Providing [ellipsis](https://docs.python.org/3/library/constants.html#Ellipsis) must apply `:` to each dimension necessary to index all dimensions (e.g., if `A` has rank `4`, `A[1:, ..., 2:5] == A[1:, :, :, 2:5]`). Only a single ellipsis must be allowed. An `IndexError` exception must be raised if more than one ellipsis is provided. +- Providing an empty tuple or an ellipsis to an array of rank `0` must result in an array of the same rank (i.e., if `A` has rank `0`, `A == A[()]` and `A == A[...]`). + + ```{note} + This behavior differs from NumPy where providing an empty tuple to a rank `0` array returns a Python scalar. + ``` + - Except in the case of providing an ellipsis to index all trailing dimensions (e.g., `A[2:10, ...]`), the number of provided single-axis indexing expressions must equal `N`. For example, if `A` has rank `2`, a single-axis indexing expression must be explicitly provided for both axes (e.g., `A[2:10, :]`). An `IndexError` exception must be raised if the number of provided single-axis indexing expressions is less than `N`. ```{note} From 9251d2b40896ccef4e3396aed0fe1a1757823129 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 7 Oct 2021 02:51:25 -0700 Subject: [PATCH 6/9] Update note --- spec/API_specification/indexing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/API_specification/indexing.md b/spec/API_specification/indexing.md index c1aca930d..a5f180261 100644 --- a/spec/API_specification/indexing.md +++ b/spec/API_specification/indexing.md @@ -155,7 +155,7 @@ Multi-dimensional arrays must extend the concept of single-axis indexing to mult - Providing an empty tuple or an ellipsis to an array of rank `0` must result in an array of the same rank (i.e., if `A` has rank `0`, `A == A[()]` and `A == A[...]`). ```{note} - This behavior differs from NumPy where providing an empty tuple to a rank `0` array returns a Python scalar. + This behavior differs from NumPy where providing an empty tuple to an array of rank `0` returns a Python scalar. ``` - Except in the case of providing an ellipsis to index all trailing dimensions (e.g., `A[2:10, ...]`), the number of provided single-axis indexing expressions must equal `N`. For example, if `A` has rank `2`, a single-axis indexing expression must be explicitly provided for both axes (e.g., `A[2:10, :]`). An `IndexError` exception must be raised if the number of provided single-axis indexing expressions is less than `N`. From ff9692641aada23787ab60d4c668da20f23ee02c Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 1 Nov 2021 11:04:26 -0700 Subject: [PATCH 7/9] Remove empty lines --- spec/API_specification/indexing.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/spec/API_specification/indexing.md b/spec/API_specification/indexing.md index 29c295d9e..0026cf75e 100644 --- a/spec/API_specification/indexing.md +++ b/spec/API_specification/indexing.md @@ -17,21 +17,18 @@ To index a single array axis, an array must support standard Python indexing rul - **Valid** nonnegative indices must reside on the half-open interval `[0, n)`. ```{note} - This specification does not require bounds checking. The behavior for out-of-bounds integer indices is left unspecified. ``` - Negative indices must count backward from the last array index, starting from `-1` (i.e., negative-one-based indexing, where `-1` refers to the last array index). ```{note} - A negative index `j` is equivalent to `n-j`; the former is syntactic sugar for the latter, providing a shorthand for indexing elements that would otherwise need to be specified in terms of the axis (dimension) size. ``` - **Valid** negative indices must reside on the closed interval `[-n, -1]`. ```{note} - This specification does not require bounds checking. The behavior for out-of-bounds integer indices is left unspecified. ``` From 1a3b89efba67d3931e72eb584674b51df3462570 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 1 Nov 2021 11:13:24 -0700 Subject: [PATCH 8/9] Fix note --- spec/API_specification/indexing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/API_specification/indexing.md b/spec/API_specification/indexing.md index 0026cf75e..38fa20df6 100644 --- a/spec/API_specification/indexing.md +++ b/spec/API_specification/indexing.md @@ -142,7 +142,7 @@ Multi-dimensional arrays must extend the concept of single-axis indexing to mult - Providing a single integer as a single-axis index must reduce the number of array dimensions by `1` (i.e., the array rank should decrease by one; if `A` has rank `2`, `rank(A)-1 == rank(A[0, :])`). In particular, a selection tuple with the `m`th element an integer (and all other entries `:`) indexes a sub-array with rank `N-1`. ```{note} - When providing a single integer as a single-axis index to an array of rank `1`, the result should be an array of rank `0`, not a Python scalar. Note that this behavior differs from NumPy. + When providing a single integer as a single-axis index to an array of rank `1`, the result should be an array of rank `0`, not a NumPy scalar. Note that this behavior differs from NumPy. ``` - Providing a slice must retain array dimensions (i.e., the array rank must remain the same; `rank(A) == rank(A[:])`). From 2b8030b69419e35899f834ce7c2ed0e820e4ec95 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 1 Nov 2021 11:22:48 -0700 Subject: [PATCH 9/9] Add note --- spec/API_specification/indexing.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/API_specification/indexing.md b/spec/API_specification/indexing.md index 38fa20df6..f06cae9d3 100644 --- a/spec/API_specification/indexing.md +++ b/spec/API_specification/indexing.md @@ -36,6 +36,10 @@ To index a single array axis, an array must support standard Python indexing rul - Colons `:` must be used for [slices](https://docs.python.org/3/library/functions.html#slice): `start:stop:step`, where `start` is inclusive and `stop` is exclusive. +```{note} +The specification does not support returning scalar (i.e., non-array) values from operations, including indexing. In contrast to standard Python indexing rules, for any index, or combination of indices, which select a single value, the result must be a zero-dimensional array containing the selected value. +``` + ### Slice Syntax The basic slice syntax is `i:j:k` where `i` is the starting index, `j` is the stopping index, and `k` is the step (`k != 0`). A slice may contain either one or two colons, with either an integer value or nothing on either side of each colon. The following are valid slices.