We all know 3 7 4[1]
is 3
and 3 7 4[2]
is 7
, but what about 3 7 4[1.5]
?
This article proposes an extension to indices in the APL family of languages, known as float indexing, which allows indexing an array X
in its n
th dimension with any value in the (closed) interval ⎕io
to ⎕io+n⌷⍴X
, not just integers.
If X
is a vector, the extension is quite trivial: define X[a]
to be $\mathrm{lerp}($X[⌊a]
$,$X[⌈a]
$, t=$1a
$)$. For higherrank arrays, this requires some more thought.
Consider X
to be the matrix 2 2⍴3 9 4 1
, and a
the vector 1.5 1.5
. Let's draw a picture:
3 9
\ /
a
/ \
4 1
It really looks like X[a]
should be an average of 3
, 9
, 4
and 1
, that is, 4.25
. In general, X[a]
will be some function of the subarray delimited by the entries X[⌊a]
and X[⌈a]
. We can calculate the coefficients for one particular value by looking at how close the value is to the desired index.
I wrote the following (intentionally ugly) function for float indexing:
∆I←{
bitstrings←(⊂⍴∘2)(,⊤)¨⎕io⍨∘⍳2∘*
X←⍵
coefficients←×⌿{1∘@(⍸⍵)⊢1,⍺}
index←{X⌷⍨⌊@(⍸⍵)⌈@(⍸~⍵)⊢,⍺}
+⌿⍺∘(index×coefficients)¨bitstrings≢⍺
}
Surely someone will contact me^{(1)} and propose a four glyphs long reimplementation that actually makes use of arrayoriented principles and/or obscure Dyalog behavior.
Should other indexrelated functions be changed as well? Of course. 3 7 4⍳5
should return either ⎕io+÷2
or ⎕io+5÷3
(or maybe both?).
Edit 20230922: I came up with ⊣(1⊥,⍤⊢×(×⌿¨⍤1∘⍤⊂⍤⊣¨~⍤,⍤⍳⍤⍴⍤⊢))(2↑⌊⍤⊣↓⊢)
which I think is equivalent if ⎕io←0
. You tell me which is better :)
Footnotes

If you actually want to contact me, ping @RubenVerg at The APL Orchard.