new array indexing in lush2

Ralf Juengling <[email protected]> Sat, 18 Oct 2008 14:41:38 -0700 (PDT)
Newsgroups gmane.lisp.lush.devel
Message-ID <[email protected]>
Good afternoon,

We briefly talked about the need for more powerful
ways of indexing Lush arrays in the past. I finally
took the time to implement some ideas in Lush2 (rev 93).

I added two new indexing modes and left the old
one in place, so this extension is backwards compatible.
Let me demonstrate briefly how it works.

? m  ;; a matrix
= [d[d   1.0000   2.0000   3.0000   4.0000   5.0000]
     [d   6.0000   7.0000   8.0000   9.0000  10.0000]
     [d  11.0000  12.0000  13.0000  14.0000  15.0000]
     [d  16.0000  17.0000  18.0000  19.0000  20.0000]]

? img  ;; an RGB image
= ::INDEX:<512x512x3>

The old-style indexing uses numbers as subscripts--
as many numbers as dimensions--and gives the indexed
element as a number or the updated array as result.

? ; element (1,2) of m
? (m 1 2)
= 8
? ; updating element (1,2) of m
? (m 1 2 -8)
= [d[d   1.0000   2.0000   3.0000   4.0000   5.0000]
     [d   6.0000   7.0000  -8.0000   9.0000  10.0000]
     [d  11.0000  12.0000  13.0000  14.0000  15.0000]
     [d  16.0000  17.0000  18.0000  19.0000  20.0000]]

Both new indexing modes use arrays as subscripts and
give an array of indexed elements or the updated array
as result.

In the first mode, the subscript is a vector, and its
contents are used to do a (partial) select:

? ; element (1,2) of m
? (m [1 2])
= [d@ -8]

? ; row 1 of m
? (m [1])
= [d   6.0000   7.0000  -8.0000   9.0000  10.0000]

? ; all of m
? (m [])
= [d[d   1.0000   2.0000   3.0000   4.0000   5.0000]
     [d   6.0000   7.0000  -8.0000   9.0000  10.0000]
     [d  11.0000  12.0000  13.0000  14.0000  15.0000]
     [d  16.0000  17.0000  18.0000  19.0000  20.0000]]

? ; updating all of m
? (m [] 0)
= [d[d   0.0000   0.0000   0.0000   0.0000   0.0000]
     [d   0.0000   0.0000   0.0000   0.0000   0.0000]
     [d   0.0000   0.0000   0.0000   0.0000   0.0000]
     [d   0.0000   0.0000   0.0000   0.0000   0.0000]]

? ; updating row 1 of m
? (m [1] 1)
= [d[d   0.0000   0.0000   0.0000   0.0000   0.0000]
     [d   1.0000   1.0000   1.0000   1.0000   1.0000]
     [d   0.0000   0.0000   0.0000   0.0000   0.0000]
     [d   0.0000   0.0000   0.0000   0.0000   0.0000]]

? ; pixel (100, 100) of img
? (img [100 100])
= [u   182    74    87]

In the second mode, the subscript argument is an array
of subscript vectors, that is, the extent in the
last dimension equals the rank of the array to be
indexed.

? ; subscripts of diagonal elements of m
? (setq ss [[0 0] [1 1] [2 2] [3 3]])
= [d[d   0.0000   0.0000]
     [d   1.0000   1.0000]
     [d   2.0000   2.0000]
     [d   3.0000   3.0000]]
? (m ss)
= [d   0.0000   1.0000   0.0000   0.0000]

? ; updating diagonal elements of m
? (m ss [10 20 30 40])
= [d[d  10.0000   0.0000   0.0000   0.0000   0.0000]
     [d   1.0000  20.0000   1.0000   1.0000   1.0000]
     [d   0.0000   0.0000  30.0000   0.0000   0.0000]
     [d   0.0000   0.0000   0.0000  40.0000   0.0000]]

? ; updating diagonal elements of m
? (m ss (/ (m ss) 10))
= [d[d   1.0000   0.0000   0.0000   0.0000   0.0000]
     [d   1.0000   2.0000   1.0000   1.0000   1.0000]
     [d   0.0000   0.0000   3.0000   0.0000   0.0000]
     [d   0.0000   0.0000   0.0000   4.0000   0.0000]]

This second mode is in particular handy in combination
with 'where', which gives you the indices of all nonzero
entries in an array (the function that used to be
called 'where' in lush is called 'btrace' in lush2):

? (where m)
= [i[i     0     0]
     [i     1     0]
     [i     1     1]
     [i     1     2]
     [i     1     3]
     [i     1     4]
     [i     2     2]
     [i     3     3]]

? ; start with a fresh m
? (setq m (reshape (arange 20) '(4 5)))
= [d[d   1.0000   2.0000   3.0000   4.0000   5.0000]
     [d   6.0000   7.0000   8.0000   9.0000  10.0000]
     [d  11.0000  12.0000  13.0000  14.0000  15.0000]
     [d  16.0000  17.0000  18.0000  19.0000  20.0000]]

? ; change all odd entries
? (mod m 2)
= [d[d   1.0000   0.0000   1.0000   0.0000   1.0000]
     [d   0.0000   1.0000   0.0000   1.0000   0.0000]
     [d   1.0000   0.0000   1.0000   0.0000   1.0000]
     [d   0.0000   1.0000   0.0000   1.0000   0.0000]]

? (let ((ss (where (mod m 2))))
     (m ss (* (m ss) 10)) )
= [d[d  10.0000   2.0000  30.0000   4.0000  50.0000]
     [d   6.0000  70.0000   8.0000  90.0000  10.0000]
     [d 110.0000  12.0000 130.0000  14.0000 150.0000]
     [d  16.0000 170.0000  18.0000 190.0000  20.0000]]


The indexing stuff if very new and the compiler does
not support the new indexing modes yet. But before I
put more work into it, I thought you should take a
look at this.

Cheers,
Ralf

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/