From 666ad23844be33141f7c986de3b83f035db4b95a Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 15 Feb 2021 17:51:17 -0500 Subject: Reference implementation and commentary for Group length extension --- docs/spec/primitive.html | 2 +- spec/primitive.md | 2 +- spec/reference.bqn | 13 +++++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/spec/primitive.html b/docs/spec/primitive.html index ab65ef6c..d0eb9b2f 100644 --- a/docs/spec/primitive.html +++ b/docs/spec/primitive.html @@ -127,7 +127,7 @@

First (βŠ‘) simply takes the first element of its argument in index order, or the fill element 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 𝕩. Group Indices treats its argument 𝕩 as a left argument for Group and uses a right argument made up of indices, with the definition βŠ”βŸœ(β†•β‰ βš‡1).

+

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, with the definition βŠ”βŸœ(β†•β‰ βš‡1).

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<𝕩.

Indices (/) applies to a list of natural numbers, and returns a list of natural numbers. The result contains iβŠ‘π•© copies of each natural number index i for 𝕩, in increasing order.

Structural manipulation

diff --git a/spec/primitive.md b/spec/primitive.md index fca283d5..2662f8c4 100644 --- a/spec/primitive.md +++ b/spec/primitive.md @@ -161,7 +161,7 @@ For **Select** (`⊏`), `𝕨` is an array of natural numbers, or a list of such **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 `𝕩`. **Group Indices** treats its argument `𝕩` as a left argument for Group and uses a right argument made up of indices, with the definition `βŠ”βŸœ(β†•β‰ βš‡1)`. +**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, with the definition `βŠ”βŸœ(β†•β‰ βš‡1)`. **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<𝕩`. diff --git a/spec/reference.bqn b/spec/reference.bqn index 288fdc39..988bfb51 100644 --- a/spec/reference.bqn +++ b/spec/reference.bqn @@ -383,11 +383,16 @@ Group←{ 𝕨↩Pair∘ToArray⍟(2>≑)𝕨 ! 1==𝕨 {!∧´Int¨𝕩⋄!∧´¯1≀𝕩}∘β₯ŠΒ¨π•¨ - n←+Β΄=¨𝕨 + n←+Β΄r←=¨𝕨 ! n≀=𝕩 - ! (βˆΎβ‰’βŒœπ•¨)≑n↑≒𝕩 - 𝕨↩β₯ŠΒ¨π•¨ β‹„ 𝕩↩((≠¨𝕨)∾n↓≒𝕩)β₯Šπ•© - (π•¨βŠΈ=/𝕩˙)¨↕1+Β―1βŒˆΒ΄Β¨π•¨ + ld←(βˆΎβ‰’βŒœπ•¨)-n↑≒𝕩 + ! ∧´(0βŠΈβ‰€βˆ§β‰€βŸœ(r/1=r))ld + dr←r⌊(0Β»+`r)⊏ld∾⟨0⟩ + s←drβŠ£β—ΆβŸ¨0,Β―1βŠΈβŠ‘βŸ©Β¨π•¨ + 𝕨↩dr(β₯ŠΒ―1βŠΈβ†“βŸβŠ£)¨𝕨 + sβŒˆβ†©1+Β―1βŒˆΒ΄Β¨π•¨ + 𝕩↩((≠¨𝕨)∾n↓≒𝕩)β₯Šπ•© + (π•¨βŠΈ=/𝕩˙)¨↕s } GroupInds←{ ! 1==𝕩 -- cgit v1.2.3