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 X[⌊a]
X[⌈a]
1|a
. For higher-rank 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 array-oriented principles and/or obscure Dyalog behavior.
Should other index-related functions be changed as well? Of course. 3 7 4⍳5
should return either ⎕io+÷2
or ⎕io+5÷3
(or maybe both?).
Edit 2023-09-22: 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.