From 7bf2aa4054b8378a76dff63acdccbcdad91f68e6 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sat, 7 Aug 2021 20:41:31 -0400 Subject: BREAKING: Don't allow First of empty or reshaping empty to non-empty --- docs/spec/primitive.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/spec') diff --git a/docs/spec/primitive.html b/docs/spec/primitive.html index fc60460d..b2e127c6 100644 --- a/docs/spec/primitive.html +++ b/docs/spec/primitive.html @@ -122,13 +122,13 @@

Enclose (<) forms a unit array that contains its argument.

Merge (>) combines the outer axes of an array of arrays with inner axes: it requires that all elements of its argument have the same shape, and creates an array such that (iโˆพj)โŠ‘>๐•ฉ is iโŠ‘jโŠ‘๐•ฉ. It also accepts atom elements of ๐•ฉ, converting them to unit arrays, or an atom argument, which is returned unchanged. Solo and Couple (โ‰) turn one or two arguments into major cells of the result and can be defined easily in terms of Merge.

Join To (โˆพ) combines its two arguments along an existing initial axis, unless both arguments are units, in which case it creates an axis and is identical to Couple (โ‰). The arguments must differ in rank by at most 1, and the result rank is equal to the maximum of 1 and the higher argument rank. Each argument with rank less than the result, and each major cell of an argument with rank equal to it, becomes a major cell of the result, with cells from the left argument placed before those from the right. Join (โˆพ) generalizes the equal-rank subset of this behavior to an array of values instead of just two. The argument must be an array (unlike Merge), and its elements must all the same rank, which is at least the argument rank. Atom elements are treated as unit arrays. Then "outer" argument axes are matched up with leading "inner" element axes, and elements are joined along these axes. In order to allow this, the length of an element along a particular axis must depend only on the position along the corresponding axis in the argument. An empty argument to Join is return unchanged, as though the element rank is equal to the argument rank.

-

Deshape (โฅŠ) differs from the provided function (which returns the element list of an array) only in that it accepts an atom, returning a one-element list containing it. Reshape (โฅŠ) is extended in numerous ways. It accepts any list of natural numbers (including as a unit array or atom) for the left argument and any right argument; ๐•ฉ is deshaped first so that it is treated as a list of elements. These elements are repeated cyclically to fill the result array in ravel order. If ๐•ฉ is empty but the result is not, then the result consists of fill elements for ๐•ฉ. Furthermore, at most one element of ๐•จ can be a "length code": one of the primitives โˆ˜โŒŠโŒฝโ†‘. In this case, a target length is computed from the number of elements in ๐•ฉ divided by the product of the other elements of ๐•จ (which must not be zero). If the target length is an integer then it is used directly for the length code. Otherwise, an error is given if the length code is โˆ˜, and the target length is rounded down if the code is โŒŠ and up if it's โŒฝ or โ†‘. With code โŒฝ, elements are repeated cyclically as usual, but with code โ†‘, the extra elements after each argument element is used are fill values for ๐•ฉ.

+

Deshape (โฅŠ) differs from the provided function (which returns the element list of an array) only in that it accepts an atom, returning a one-element list containing it. Reshape (โฅŠ) is extended in numerous ways. It accepts any list of natural numbers (including as a unit array or atom) for the left argument and any right argument; ๐•ฉ is deshaped first so that it is treated as a list of elements. These elements are repeated cyclically to fill the result array in ravel order. If ๐•ฉ is empty then a non-empty requested result shape causes an error. Furthermore, at most one element of ๐•จ can be a "length code": one of the primitives โˆ˜โŒŠโŒฝโ†‘. In this case, a target length is computed from the number of elements in ๐•ฉ divided by the product of the other elements of ๐•จ (which must not be zero). If the target length is an integer then it is used directly for the length code. Otherwise, an error is given if the length code is โˆ˜, and the target length is rounded down if the code is โŒŠ and up if it's โŒฝ or โ†‘. With code โŒฝ, elements are repeated cyclically as usual, but with code โ†‘, the extra elements after each argument element is used are fill values for ๐•ฉ.

Transpose (โ‰) reorders axes of its argument to place the first axis last; if the argument has one or fewer axes then it's enclosed if it's an atom and otherwise returned unchanged. Reorder Axes (โ‰) requires the left argument to be a list or unit of natural numbers, with length at most the rank of the right argument. This list is extended to match the right argument rank exactly by repeatedly appending the least unused natural number (for example, given 1โ€ฟ3โ€ฟ0โ€ฟ0, 2 is appended). After extension, it specifies a result axis for each axis of the right argument. There must be no gaps in the list: that is, with the result rank equal to one plus the greatest value present, every result axis must appear at least once. Now each argument axis is "sent to" the specified result axis: in terms of indices, iโŠ‘๐•จโ‰๐•ฉ is (๐•จโŠi)โŠ‘๐•ฉ if ๐•จ is complete. If multiple argument axes correspond to the same result axis, then a diagonal is taken, and it's as long as the shortest of those argument axes. Like Transpose, Reorder Axes encloses ๐•ฉ if it's an atom, so that its result is always an array.

Indices and selection

Each element in an array sโฅŠe is associated with an index, which is a list of natural numbers i such that โˆงยดi<s. The list of all indices, which corresponds to the element list e, contains all such lists i in lexicographic order. That is, index i comes before j exactly when the two indices are not the same, and i has the smaller value at the first position where they are unequal. The index of an element along a particular axis a is the value aโŠ‘i.

Range (โ†•) is extended to apply to a list of natural numbers, in addition to the provided case of a single natural number (an enclosed natural number ๐•ฉ should still result in an error). For a list ๐•ฉ, the result is an array of shape ๐•ฉ in which the value at a given index is that index, as a list of natural numbers. That is, iโ‰กiโŠ‘โ†•๐•ฉ for any list of natural numbers i with โˆงยดi<๐•ฉ.

Pick (โŠ‘) is extended to array left arguments. In this case, it requires every depth-1 array in the nested structure of ๐•จ to be a valid index list for ๐•ฉ, and every atom to be contained in one of these lists. The result is ๐•จ with each index list replaced by the element of ๐•ฉ at that index. In the simple case where ๐•จ itself is an index list, the result is the element of ๐•ฉ at index ๐•จ.

-

First (โŠ‘) simply takes the first element of its argument in index order, or the fill element if ๐•ฉ is empty.

+

First (โŠ‘) simply takes the first element of its argument in index order, with an error if ๐•ฉ is empty.

For Select (โŠ), ๐•จ is an array of natural numbers, or a list of such arrays; if it's an empty list, it's interpreted as the former. The given arrays are matched with leading axes of ๐•ฉ and used to select from those axes. Their shape is retained, so that the final shape is the combined shapes of each array of natural numbers in ๐•จ in order, followed by the trailing (unmatched) shape of ๐•ฉ. This means that a single axis in ๐•ฉ can correspond to any number of axes in ๐•จโŠ๐•ฉ, depending on the rank of that portion of ๐•จ. More precisely, the value of the result at an index j is obtained by splitting j into one index into each array of ๐•จ followed by a partial index into ๐•ฉ. An index i for ๐•ฉ comes from selecting from each array of ๐•จ and appending the results to the partial index from j, and the value iโŠ‘๐•ฉ is jโŠ‘๐•จโŠ๐•ฉ.

First Cell (โŠ) selects the initial major cell of ๐•ฉ, giving an error if ๐•ฉ has rank 0 or length 0.

Group (โŠ”) performs an opposite operation to Select, so that ๐•จ specifies not the argument index that result values come from, but the result index that argument values go to. The general case is that ๐•จ is a list of arrays of numbers; if it has depth less than 2 it's converted to this form by first enclosing it if it's an atom, then placing it in a length-1 list. After this transformation, the result rank is โ‰ ๐•จ, and each result element has rank (โ‰ ๐•จ)+(=๐•ฉ)-+ยด=ยจ๐•จ, with the initial โ‰ ๐•จ axes corresponding to elements of ๐•จ and the remainder to trailing axes of ๐•ฉ. Each atom in ๐•จ can be either a natural number or ยฏ1 (which indicates the corresponding position in ๐•ฉ will be omitted). If ยฏ1 doesn't appear, the result has the property that each cell of ๐•ฉ appears in the corresponding element of ๐•จโŠ๐•จโŠ”๐•ฉ. More concretely, the length of the result along axis a is the maximum value in aโŠ‘๐•จ plus one, or zero if aโŠ‘๐•จ is empty. Axis a corresponds to =aโŠ‘๐•จ axes in ๐•ฉ, and an element of the result at position i along this axis contains all positions in ๐•ฉ where i=aโŠ‘๐•จ. There may be multiple such positions, and they're arranged along axis a of that result element according to their index order in ๐•ฉ. The shapes of components of ๐•จ must match the corresponding axes of ๐•ฉ, except for rank-1 components of ๐•จ, which can match or have an extra element. This element, which like the others is either a natural number or ยฏ1, gives the minimum length of the result axis corresponding to the component of ๐•จ in question, but otherwise does not affect the result. Group Indices treats its argument ๐•ฉ as a left argument for Group and uses a right argument made up of indices, which is โ†•โ‰ ๐•ฉ if ๐•ฉ has depth 1 and โ†•โˆพโ‰ขยจ๐•ฉ if it has depth 2. Because the depth-1 case uses atomic indices, ๐•ฉ is required to be a list (and it can't be an atom). Much like Range, the result has depth one higher than the argument.

-- cgit v1.2.3