3.9. Matrices, Vectors, Tensors, Indexes and IDX


Lush has a powerful mechanism for manipulating tabular data such as
scalars, vectors, matrices, and tensors from 0 to 8 dimensions.
The basic Lush type for tabular data is called an INDEX or an IDX. The
IDX is merely an access structure, the actual data is stored in a
STORAGE associated with the IDX.
The data contained in a storage, and accessed with an IDX, can be of
type double, float, int, short, byte, ubyte, gptr (generic pointer),
atom (lisp object), and packed (onebyte fixed point number).
There are many IDXrelated functions in Lush. Some are described in this
section, but the vast majority is described in the Standard Libraries
section.
creating a tensor of float is done
simply with:
? (setq m (floatmatrix 10 8 4)) ; create 3D matrix
= ::INDEX3:<10x8x4>
? (m 3 4 2 45.6) ; set value of element (3,4,2) to 45.6
= ::INDEX3:<10x8x4>
? (m 3 4 2) ; get value of element (3,4,2).
= 45.6
Tensors of various basic types can be created with the functions listed
below. Each function has two versions, the regular version initializes
all the elements to zero, while the version with
nc at the end do not (no clear) and are a bit faster. All of
these functions take 0 to 8 integer arguments that are the sizes in each
dimension:
 doublematrix,
doublematrixnc, realmatrix, realmatrixnc : doubles
 floatmatrix, floatmatrixnc, fltmatrix,
fltmatrixnc : floats
 intmatrix, intmatrixnc :
32bit ints
 shortmatrix, shortmatrixnc :
16bit shorts
 bytematrix, bytematrixnc :
8bit bytes
 ubytematrix, ubytematrixnc :
8bit unsigned bytes
 gptrmatrix, gptrmatrixnc :
generic pointers (void*)
Tables of lisp objects (atoms) are created with the
array function.
An IDX is a structure that contains a pointer to the STORAGE where the
data resides, and offset indicating where the IDX data starts in the
storage, a number of dimensions (between 0 and 8), a size for each
dimension, and a modulo for each dimension. The modulo determines by how
much a pointer would have to be incremented to go from one element of
the IDX to the next element in the given dimension.
Multiple IDXs can point to the same STORAGE and provide access to the
same data in multiple ways.
an IDX with 0 dimension is called a scalar, and can be seen as a pointer
to a number.
3.9.1. IDX Creation and Allocation


Tensors of various basic types can be created with the functions listed
below. Each function has two versions, the regular version initializes
all the elements to zero, while the version with
nc at the end do not (no clear) and are a bit faster. All of
these functions take 0 to 8 integer arguments that are the sizes in each
dimension:
3.9.1.0. (doublematrix s1...sn)

[DX] 
create an n dimensional tensor of
double . The arguments are the sizes in each dimension. The
elements are initialized to 0.
3.9.1.1. (doublematrixnc s1...sn)

[DX] 
create an n dimensional tensor of
double . The arguments are the sizes in each dimension. The
elements are not initialized and may contain nonsensical values.
3.9.1.2. (floatmatrix s1...sn)

[DX] 
create an n dimensional tensor of
float . The arguments are the sizes in each dimension. The
elements are initialized to 0.
3.9.1.3. (floatmatrixnc s1...sn)

[DX] 
create an n dimensional tensor of
float . The arguments are the sizes in each dimension. The
elements are not initialized and may contain nonsensical values.
3.9.1.4. (intmatrix s1...sn)

[DX] 
create an n dimensional tensor of
32bit int . The arguments are the
sizes in each dimension. The elements are initialized to 0.
3.9.1.5. (intmatrixnc> s1...sn)


create an n dimensional tensor of
32bit int . The arguments are the
sizes in each dimension. The elements are not initialized
3.9.1.6. (shortmatrix s1...sn)

[DX] 
create an n dimensional tensor of
16bit short . The arguments are the
sizes in each dimension. The elements are initialized to 0.
3.9.1.7. (shortmatrixnc> s1...sn)


create an n dimensional tensor of
16bit short . The arguments are the
sizes in each dimension. The elements are not initialized
3.9.1.8. (bytematrix s1...sn)

[DX] 
create an n dimensional tensor of
signed byte . The arguments are the
sizes in each dimension. The elements are initialized to 0.
3.9.1.9. (bytematrixnc> s1...sn)


create an n dimensional tensor of
signed byte . The arguments are the
sizes in each dimension. The elements are not initialized
3.9.1.10. (ubytematrix s1...sn)

[DX] 
create an n dimensional tensor of
unsigned byte . The arguments are the
sizes in each dimension. The elements are initialized to 0.
3.9.1.11. (ubytematrixnc> s1...sn)


create an n dimensional tensor of
unsigned byte . The arguments are the
sizes in each dimension. The elements are not initialized
3.9.1.12. (gptrmatrix s1...sn)

[DX] 
create an n dimensional tensor of
generic pointers (void *). The arguments are the sizes in each
dimension. The elements are initialized to NULL.
3.9.1.13. (gptrmatrixnc> s1...sn)


create an n dimensional tensor of
generic pointers (void *). The arguments are the sizes in each
dimension. The elements are not initialized and may cause memory faults
if dereferenced carelessly.
3.9.1.14. (array m s1...sn)

[DX] 
create an n dimensional tensor lisp
objects. The arguments are the sizes in each dimension. The elements are
initialy nil.
3.9.1.15. (newindex srg slist)

[DX] 
Creates a new IDX pointing to the storage srg
. slist is a list of integers that
specifies the size in each of the dimensions. The
srg is allocated and resized if necessary.
The IDX literal syntax can be used to create an IDX and fill it up with
values in one fell swoop. Here is how to create a vector of doubles:
(setq m [3 4 5])
A twodimensional matrix of doubles can be created as follows:
(setq m [[1 2 3] [3 4 5]])
Vectors and matrices of other types than doubles can be created by
specifying the type with a single character right after the first open
bracket. Similarly, IDX of double, floats, int, short, bytes, ubytes,
and atoms (lisp objects) can be created by placing one the following
characters right after the opening bracket d, f,
i, s, b, u, a respectively. Here are a few examples:
(setq m [d 1 2 3]) ; doubles
(setq m [f 1 2 3]) ; floats
(setq m [i 1 2 3]) ; ints
(setq m [s 1 2 3]) ; shorts
(setq m [b 1 2 3]) ; bytes
(setq m [u 1 2 3]) ; ubytes
(setq m [a "choucroute" "garnie"]) ; lisp objects
Another syntax is provided for IDX of atoms (lisp objects):
(setq m #["choucroute" "garnie" #])
Scalars literals (i.e. idx0) can be entered by placing an @ sign after
the type indicator. Here is an examples:
(idxdotm0 vector [f@ 34] output)
Here are examples for each of the IDX types:
(setq s [d@ 42])
(setq s [f@ 42])
(setq s [i@ 42])
(setq s [s@ 42])
(setq s [b@ 42])
(setq s [u@ 42])
(setq s [a@ "choucroute"])
(setq s #[@ "choucroute" #])
The last two lines are equivalent.
3.9.2.1. IDX Literals as Local Variables in Functions


A very important fact about array literals created as local variables
within functions is that they are "static" variables (a bit like
closures in lexicallybound Lisps). Here is an example:
? (de foo () (let ((v [0 1])) (v 0 (+ (v 0) 1)) v))
= foo
? (foo)
= [ 1.00 1.00 ]
? (foo)
= [ 2.00 1.00 ]
The values in the IDX are retained from one call to the next. This is
true in interpreted mode and in compiled mode. Preventing this behavior
can be done by copying the literal each time the function is called:
(de foo () (let ((v (idxcopy [0 1]))) (v 0 (+ (v 0) 1)) v))
3.9.2.2. Array Literals as Closures


Being dynamically bound, Lush has no lexical closure mechanism. However,
array literals provide a way to emulate the behavior of lexical closures
(i.e. bundling "static" variables within a function):
? (de newcounter () (lambda () (let ((v [@ 0])) (v (1+ (v))) (v))))
= newcounter
? (setq c (newcounter))
= ::DE:8805898
? (c)
= 1
? (c)
= 2
3.9.3. IDX Copying and Cloning


3.9.3.0. (idxcopy m1 [m2])

[DX] 
Copy m1 into m2
. If m1 and m2
are of different numerical types, appropriate conversion will be
performed. m1 and
m2 must have the same dimensions. If
m2 is not present, a fresh copy of m1
is returned (the data is copied).
3.9.3.1. (copymatrix m1 [m2])

[DX] 
Copy m1 into m2
. Unlike idxcopy , this function does
not require that m1 and
m2 have the same structure as long as they have the same
number of elements. In other words, m1
can be a 4 by 5 matrix, and m2 a
20dimensional vector.
3.9.3.2. (idxclone m)

[DX] 
Return a clone of IDX m . The returned
IDX is identical to m and points to
the same storage at the same place. This does not actually copy any
data.
3.9.3.3. (copyanymatrix m1 [m2])

[DX] 
obsolete function. Works like copymatrix (sort of). If
m2 is omitted return a new copy of m1
(a new storage is created and m1 is
copied in it). If m2 is present, the
storage of m1 is copied into the
storage of m2 . Return
m2 .
3.9.4.0. (idxbloop ((symb1 idx1) [ (symb2 idx2) [...(symbn idxn) ]]) body)

[DY] 
make each symbi be an idx that loops
over the first dimension of its corresponding
idxi . Execute body for
each value.
More precisely, each si will be an idx
with one less dimension than the corresponding
idxi , and will simulataneously loop over the successive
"slices" of idxi for each possible
value of the first index. In other words, applying function
myfunc to each element of a vector v1
and putting the result in the corresponding element in
v2 can be done with:
(idxbloop ((x1 v1) (x2 v2)) (x2 (myfunc (x1))))
x1 and x2
are scalars (i.e. zerodimensional tensors). The above function work
just as well is v1 and
v2 are n dimensional
tensors and myfunc accepts
n1 th dimensional tensors as arguments.
3.9.4.1. (idxpbloop ((symb1 idx1) [ (symb2> idx2) [...(symbn idxn) ]]) body)

[DY] 
Works just like idxbloop, but the multiple evaluations of the body may
be executed in parallel on some implementations of Lush.
3.9.4.2. (idxeloop ((symb1 idx1) [ (symb2> idx2) [...(symbn idxn) ]]) body)

[DY] 
Make each symbi be an idx that loops
over the last dimension of its corresponding idxi
. Execute body for each value.
This is like idxbloop, but it loops on the last dimension, instead of
the first. For example, the matrix product operation
C = A*B can be written as follows:
(de idxm2timesm2 (A B C)
(idxeloop ((Bj B)(Cj C)) (idxm2dotm1 A Bj Cj)))
where idxm2dotm1 is the usual
matrixvector product. The idxeloop
construct simultaneously iterates over all columns of
B and C .
3.9.4.3. (idxpeloop ((symb1 idx1) [ (symb2> idx2) [...(symbn idxn) ]]) body)

[DY] 
Works just like idxpbloop, but the multiple evaluations of the body may
be executed in parallel on some implementations of Lush.
3.9.4.4. (cidxbloop (i_1 [i_2...i_n] (c_1 l_1) [(c_1 l_1)...(c_m l_m)) p_1 [p_2...])

[DF] 
This iterator is desinged to facilitate the implementation of inner
loops of tensor functions in C, while leaving all the bookkeeping to the
Lisp.
A call to cidxbloop as shown in the
synopsis is somewhat equivalent to n
nested idxbloop s, which will loop
over the first n dimensions of idxs
l_1 to l_m simultaneously.
The arguments i_1 to
i_n are strings containing names of C local variables that
will be created and set to the loop index in each of the
n dimensions. At each iteration, the C variables provided in
strings c_1 to
c_m will point to the appropriate values in the idxs
l_1 to l_m . For example,
the following function will fill matrix a
with cos(i+j).
(de foo (a)
((idx2 (flt)) a)
(cidxbloop ("i" "j" ("a" a)) #{ *a = cos(i+j); #}) a)
The return value is (like in idxbloop) the last IDX specified in the
declaration (in the example above, the return value is superfluous).
3.9.4.5. (idxgloop (p1...[pn]) body)

[DM] 
an enhanced version of bloop which allows to "bloop" through a pointer
table, and to have access to the current index value of the loop. Each
pi is a list with 1, 2, or 3 elements. if it has 2 elements
the meaning is like a in reguler bloop. if it has 1 element, which must
be a symbol, it will be used as a local variable which contains the
current index of the loop. if it has 3 elements. It must be of the form
( symbol p
m ), where p is a 1D index
and m an index of at least one
dimension. symbol will take the values
(idxselect m 0 (p i)) for all possible values of i.
Return true if m is an IDX.
3.9.5.1. (matrixp m)

[DX] 
Return true if m is an IDX whose
storage is of a numerical or generic pointer type, as opposed to lisp
objects.
return true if m is an IDX over a
storage of lisp objects (as opposed to numerical types). For historical
reasons, this kind of IDX is also known as an array.
3.9.5.3. (idxstorage m)

[DX] 
return the storage on which IDX m
points.
3.9.5.4. (idxsize m)

[DX] 
return the memory size occupied by the elements of
m in bytes.
3.9.5.5. (idxnelements m)

[DX] 
return the number of elements of IDX m
. This function is not compilable (no reason, we just forgot to write
the macros).
3.9.5.6. (idxndim m)

[DX] 
return the number of dimensions of IDX m
.
3.9.5.7. (idxoffset m)

[DX] 
return the offset of the first element of IDX m
in its storage. The offset is in number of elements, not bytes.
3.9.5.8. (idxdim m [n])

[DX] 
With two arguments, return the size of IDX m
in its n th dimension (starting at
zero). With one argument, return the size of IDX
m in each dimension in the form of a list of integers.
Example:
? (idxdim [[2 3 4][5 6 7]])
= (2 3)
3.9.5.9. (idxbound m)

[DX] 
Return the largest index in each dimension in the form of a list. This
function is mostly here for historical reasons.
3.9.5.10. (idxmodulo m [n])

[DX] 
With two arguments: return the number of elements that separate two
elements that have successive indices in the n
th dimension (starting at zero). With one argument, return a list of
all the modulos in all the dimensions.
3.9.5.11. (contiguousp m)

[DE] 
returns true if the elements of m are
contiguous in memory. IDX resulting from
idxtransclone or narrow
are generally noncontiguous.
3.9.5.12. (idxptr m)

[DX] 
return a gptr that points to the first
element of m . This must be used with
caution because the data pointed to by the pointer may be garbage
collected (when m is destroyed), or
even displaced (when m is resized).
idxptr is primarily used when calling C function that
require a pointer to numerical data.
3.9.6.0. Cloning Manipulations


These functions take an IDX as argument and return a modified clone of
this IDX pointing to the same data (or a subset of it).
3.9.6.0.0. (select m n s)

[DM] 
Return a clone of IDX m (on the same
storage), with the n th dimension
removed, and which is the s th
"slice" of m , in the
n th dimension.
? (setq m [[0 1 2 3 4][10 11 12 13 14]])
= [[ 0.00 1.00 2.00 3.00 4.00 ]
[10.00 11.00 12.00 13.00 14.00 ]]
? (select m 1 2)
= [ 2.00 12.00 ]
3.9.6.0.1. (narrow m n s [o])

[DM] 
Make a clone of IDX m , and reduce its
size in the n th dimension to
s elements, offset by o .
? (setq m [[0 1 2 3 4][10 11 12 13 14]])
= [[ 0.00 1.00 2.00 3.00 4.00 ]
[10.00 11.00 12.00 13.00 14.00 ]]
? (narrow m 1 3 2)
= [[ 2.00 3.00 4.00 ]
[12.00 13.00 14.00 ]]
3.9.6.0.2. (unfold m n ksize step)

[DM] 
Return an idx on the same storage as m
(pointing to the same data) with an added dimension at the end obtained
by "unfolding" the n th dimension.
The size of the new dimension is ksize
. This essentially manipulates the modulos to make convolutions look
like matrixvector multiplies. For example, a onedimensional
convolution between vector v and
kernel k can be done as follows:
? (setq v [0 1 2 3 4 5 6])
= [ 0.00 1.00 2.00 3.00 4.00 5.00 6.00 ]
? (setq k [1 2 1])
= [ 1.00 2.00 1.00 ]
? (setq uv (unfold v 0 3 1))
= [[ 0.00 1.00 2.00 ]
[ 1.00 2.00 3.00 ]
[ 2.00 3.00 4.00 ]
[ 3.00 4.00 5.00 ]
[ 4.00 5.00 6.00 ]]
? (setq r (matrix 5))
= [ 0.00 0.00 0.00 0.00 0.00 ]
? (idxm2dotm1 uv k r)
= [ 4.00 8.00 12.00 16.00 20.00 ]
A subsampled convolution (where the kernel is stepped by more than one
element) can be performed by setting the step
parameter to a value other than 1:
? (setq uv (unfold v 0 3 2))
= [[ 0.00 1.00 2.00 ]
[ 2.00 3.00 4.00 ]
[ 4.00 5.00 6.00 ]]
? (setq r (matrix 3))
= [ 0.00 0.00 0.00 ]
? (idxm2dotm1 uv k r)
= [ 4.00 12.00 20.00 ]
Here are other amusing examples:
? (unfold [3 4 5 6 7] 0 5 1)
= [[ 3.00 4.00 5.00 6.00 7.00 ]]
? (unfold [3 4] 0 1 1)
= [[ 3.00 ]
[ 4.00 ]]
Naturally, there is no real need for most programmers to use the
unfold construct directly because the standard library
contains efficient predefined 1D and 2D convolutions.
3.9.6.0.3. (idxtransclone m dimlist)

[DX] 
return a clone of idx m where the
dimensions have been permuted according to the list of dimension indices
dimlist . For example:
(idxtransclone m '(0 2 1))
permutes the second and third dimensions.
3.9.6.0.4. (transpose m)

[DE] 
Simple transpose function for 1D vectors and 2D matrices. This does not
copy any data, but simply returns a new IDX on the same data with the
appropriate structure.
3.9.6.0.5. (diagonal m d)

[DM] 
return a clone of m where the modulos
and dimensions have been hacked so as to grab the diagonal of the last
d dimensions. Those dimensions must all have the same size.
The result has d1 less dimensions
than the original IDX.
? (setq m [[[111 112 113][121 122 123][131 132 133]]
[[211 212 213][221 222 223][231 232 233]]])
= [[[111.00 112.00 113.00 ]
[121.00 122.00 123.00 ]
[131.00 132.00 133.00 ]]
[[211.00 212.00 213.00 ]
[221.00 222.00 223.00 ]
[231.00 232.00 233.00 ]]]
? (diagonal m 2)
= [[111.00 122.00 133.00 ]
[211.00 222.00 233.00 ]]
3.9.6.1. Compilable Direct IDX Manipulations


3.9.6.1.0. (idxchangedim m n v)

[DX] 
change the size of the n th dimension
of m to v
. This generates an error if the resulting IDX overflows its storage.
? (setq m (matrix 3 4))
= [[ 0.00 0.00 0.00 0.00 ]
[ 0.00 0.00 0.00 0.00 ]
[ 0.00 0.00 0.00 0.00 ]]
? (m () () (range 0 11))
= [[ 0.00 1.00 2.00 3.00 ]
[ 4.00 5.00 6.00 7.00 ]
[ 8.00 9.00 10.00 11.00 ]]
? (idxchangedim m 1 3)
= ()
? m
= [[ 0.00 1.00 2.00 ]
[ 4.00 5.00 6.00 ]
[ 8.00 9.00 10.00 ]]
3.9.6.1.1. (idxchangemod m n v)

[DX] 
change modulo of n th dimension of
m to v .
3.9.6.1.2. (idxchangeoffset m n)

[DX] 
change offset of m in its storage to
n
3.9.6.2. Noncompilable Direct IDX manipulations


These functions directly hack into the IDX passed as argument. Because
of those bad side effects, they cannot be called in compiled code.
3.9.6.2.0. (idxredim m dimlist)

[DX] 
Redimensions IDX m to the list of
dimensions passed as argument.
3.9.6.2.1. (idxundim m)

[DX] 
Turn m into an undimensioned IDX.
3.9.6.2.2. (idxunfold m n ksize step)

[DX] 
same as unfold , but hacks
m directly instead of cloning it.
3.9.6.2.3. (idxdiagonal m d)

[DX] 
same as diagonal , but hacks
m directly instead of cloning it.
3.9.6.2.4. (idxnarrow m n s [o])>


Works like narrow, but hack m "in
place" instead of returning a hacked clone.
3.9.6.2.5. (idxselect m n s)

[DX] 
same as select , but hacks
m directly instead of cloning it.
3.9.6.2.6. (idxtranspose m permlist)

[DX] 
Permute the dimensions of idx using
the list of int's permlist as a
permutation matrix.
3.9.6.2.7. (idxtranspose2 idx d1 d2)

[DX] 
permute dimesnions d1 and
d2 if IDX idx .
3.9.7. Loading and Saving


There are two ways to load and save matrices and tensors in Lush which
deal with two incompatible formats. The functions listed below use the
socalled "classic" format, but cannot be used in compiled code. The
other set of functions, described in the standard library section uses a
different format (socalled IDX format) and are based on the C stdio
library. This discrepancy exists largely for historical reasons and will
be fixed eventually.
3.9.7.0. Loading, Saving, and Mapping Matrices


There are two types of "classic" matrix files: ASCII files and binary
files. Binary files are a more accurate, more compact, and more
efficient way of saving matrix data. ASCII matrix files should be used
only reserved to
3.9.7.0.0. (savematrix mat file)

[DX] 
Stores the matrix mat into the binary
file file . Argument
file may be a filename string or a file descriptor created
with openwrite or
openappend . When file is
a file name, a suffix ".mat" is added
when needed. Binary Matrix File Format.
3.9.7.0.1. (saveasciimatrix mat file)

[DX] 
Stores the matrix mat into the text
file file . Argument
file may be a filename string or a file descriptor created
with openwrite or
openappend . When file is
a file name, a suffix ".mat" is added
when needed. Ascii Matrix File Format.
3.9.7.0.2. (loadmatrix [mat] file)

[DX] 
Loads a matrix from file file and
returns it. This function senses the file format and performs the
adequate actions. If a symbol mat is
specified, it stores the new matrix in symbol mat
.
Argument file may be a filename string
or a file descriptor created with openread
. When file is a file name, a suffix
".mat" is added when needed. Binary Matrix File
Format. Ascii Matrix File Format.
3.9.7.0.3. (mapmatrix [mat] filename)

[DX] 
This function is available on certain systems only. It loads a binary
matrix file by mapping the file to certain memory addresses using the
virtual memory facilities provided by the operating system. This
function is especially handy for handling very large matrices. Mapped
matrices however are always readonly.
3.9.7.1. Native Matrix File Formats


This section describes the "classic" or "native" file formats used for
Lush matrices. The IDX format (used by compilable matrix I/O functions)
is not described here.
3.9.7.1.0. Ascii Matrix File Format


ASCII matrix files are generated with function
saveasciimatrix . These machine independent files are handy
for transferring data between different computers. They tend however to
eat a lot of disk space.
The first line of the file is a matrix header. It is composed of the
letters ``.MAT'', the number of dimensions and the size of each
dimension. The array elements are written then, separated by spaces and
newlines characters.
The following lines display the content of a valid ascii matrix file.
.MAT 2 3 4
1 1 1 2 1 1 3
1 1
4 0 0
The same matrix could have been written in the following, more natural
way.
.MAT 2 3 4
1 1 1
2 1 1
3 1 1
4 0 0
3.9.7.1.1. Binary Matrix File Format


Binary matrix files are generated with function
savematrix . Binary matrix files begin with a header which
describes the type and the size of the matrix. Then comes a binary image
of the matrix.
The core header is a C structure defined as follows :
struct header {
int magic;
int ndim;
int dim[3];
};
It can be followed by further int when
the matrix has more than 3 dimensions.
The first member, magic , of this
structure is a ``magic'' number, which encodes the type of the matrix.
This number must be:
 0x1E3D4C51
for a single precision matrix
 0x1E3D4C53 for a double precision
matrix
 0x1E3D4C54 for an integer matrix
 0x1E3D4C56 for a short matrix
 0x1E3D4C55 for a byte matrix
 0x1E3D4C52 for a packed matrix
The second member of this structure, ndim
, is the number of dimensions of the matrix. Then come the dimensions
themselves in the array dim . If there
are more than three dimensions, the array dim
is extended to accomodate the extra dimensions.
When the number of dimensions (specified in ndim
) is greater than 3, the header is completed by
ndim  3 further integers.
This header is followed by a binary image of the matrix. Elements are
stored with the last index changing faster, i.e.
(0,0,0) (0,0,1) (0,0,2) ... (0,1,0) (0,1,2) etc...
 as float numbers for single precision matrix
 as double numbers for double precision matrix
 as int numbers for integer matrix
 as short numbers for short matrix
 as unsigned char numbers for byte matrix
 and as char for packed matrix.
In this latter case, each byte represents a fixed point number between
8 and +8 (+8 not included), the first 4 bits (most significant nybble)
contain the integral part and the remaining 4 bits contain the
fractional part. It uses a two's complement format. Here are two C
functions which convert a ``compacted fixed point'' number into a
floating point number and back.
/* Converts a packed number to a float */
float unpack(b)
int b;
{
if (b & 0x80)
b = ~0x7f;
else
b &= 0x7f;
return (float)b / 16.0;
}
/* Converts a float into a single byte packed number */
unsigned char pack(x)
float x;
{
if (x > 8.01.0/16.0)
return 0x7f;
else if (x < 8.0)
return 0x80;
else
return x*16;
}
3.9.7.2. Foreign Matrix Files


The following functions are for reading and writing information stored
in files created by other programs than Lush. These functions make it
easy to read binary or text files into a Lush matrix.
3.9.7.2.0. Foreign Binary Matrices


3.9.7.2.0.0. (importrawmatrix mat file [offset])

[DX] 
This function just reads the contents of file
file into matrix mat .
Accessing the matrix then access this data as single precision numbers
(float), double precision numbers (double), integers (int), short
integers (short), bytes (unsigned char) or packed numbers according to
the type of matrix mat .
Argument mat must be a matrix freshly
created with functions matrix ,
dmatrix , imatrix ,
smatrix , bmatrix or
pmatrix . Submatrices are usually rejected. Argument
file might be a file name or a file descriptor created with
openread . When argument offset
is specified, a header of offset bytes is skipped.
After executing this function, the file descriptor
file points to the first byte following the matrix data.
3.9.7.2.0.1. (exportrawmatrix mat file)

[DX] 
Stores the data of the matrix mat into
the binary file file . Argument
file may be a filename string or a file descriptor created
with openwrite or
openappend . No header is written.
3.9.7.2.1. Foreign Ascii Matrices


3.9.7.2.1.0. (importtextmatrix mat file)

[DX] 
This function reads numbers in the text file file
and stores them in matrix mat .
Argument mat must be a freshly created
matrix (submatrices are not accepted). Argument
file might be or a file descriptor created with
openread .
After executing this function, the file descriptor
file points to the first non blank character following the
matrix data.
3.9.7.2.1.1. (exporttextmatrix mat file)

[DX] 
Stores the data of the matrix mat into
the text file file . Argument
file may be a filename string or a file descriptor created
with openwrite or
openappend . No header is stored.
3.9.8. Componentwise Unary Operations


All of these functions apply a unary function to each element and either
write the result in the elements of the second argument if it is
present, or return a new tensor with the result if the second argument
is not present (except for idxclear). The two argument must have the
same dimensions. If their numerical types are different, appropriate
conversions are performed.
3.9.8.0. (idxclear src)

[DX] 
Set elements of src to 0.
3.9.8.1. (idxminus src [dst])

[DX] 
negate all elements of src .
3.9.8.2. (idxabs src [dst])

[DX] 
absolute value of elements of src .
3.9.8.3. (idxsqrt src [dst])

[DX] 
square root of elements of src .
3.9.8.4. (idxinv src [dst])

[DX] 
inverse of elements of src .
3.9.8.5. (idxsin src [dst])

[DX] 
apply sine to elements of src .
3.9.8.6. (idxcos src [dst])

[DX] 
apply cosine to elements of src .
3.9.8.7. (idxatan src [dst])

[DX] 
apply arctangent to elements of src .
3.9.8.8. (idxlog src [dst])

[DX] 
apply log to elements of src .
3.9.8.9. (idxexp src [dst])

[DX] 
apply exp to elements of src .
3.9.8.10. (idxqtanh src [dst])

[DX] 
apply rational approximation to hyperbolic tangent to elements of
src .
3.9.8.11. (idxqdtanh src [dst])

[DX] 
apply derivative of the rational approximation to hyperbolic tangent to
elements of src .
3.9.8.12. (idxstdsigmoid src [dst])

[DX] 
apply the "standard" neuralnet sigmoid function to elements of
src .
3.9.8.13. (idxdstdsigmoid src [dst])

[DX] 
apply derivative of the "standard" neuralnet sigmoid function to
elements of src .
3.9.8.14. (idxexpmx src [dst])

[DX] 
apply a rational approximation of (exp x) to elements of
src .
3.9.8.15. (idxdexpmx src [dst])

[DX] 
apply derivative of expmx to elements
of src .
3.9.9. Componentwise Dyadic Operations


All of these functions apply a dyadic function to each pair of
corresponding elements in the first two arguments. They either write the
result in the elements of the third argument if it is present, or return
a new tensor with the result if the third argument is not present All
the arguments must have the same dimensions. If their numerical types
are different, appropriate conversions are performed.
3.9.9.0. (idxadd m1 m2 [r])

[DX] 
componentwise addition of m1 and
m2 . Result in r if
present, or returned if not present.
3.9.9.1. (idxsub m1 m2 [r])

[DX] 
componentwise subtraction of m1 and
m2 . Result in r if
present, or returned if not present.
3.9.9.2. (idxmul m1 m2 [r])

[DX] 
componentwise multiplication of m1
and m2 . Result in
r if present, or returned if not present.
3.9.9.3. (idxdiv m1 m2 [r])

[DX] 
componentwise division of m1 and
m2 . Result in r if
present, or returned if not present.
3.9.10. Contracting Operations with Scalar Result


The following functions include dot products, distances, sums of terms,
min, max, etc and return scalars. These operations "contract" all the
dimensions. The dyadic ones can be seen as generalized dot product of
two tensors (e.g. the sum of all the products of corresponding terms in
the two tensors). These function have a base form and an accumulating
form (which accumulates the result in idx0 past as last argument). If
the last (and optional) idx0 argument is present, the result is written
in it. If it is not present, a number (not an idx0) is returned.
3.9.10.0. (idxsum m [r])

[DX] 
sum of all terms of m .
3.9.10.1. (idxsup m [r])

[DX] 
max of all terms of m .
3.9.10.2. (idxinf m [r])

[DX] 
min of all terms of m .
3.9.10.3. (idxsumsqr m [r])

[DX] 
sum of squares of all terms of m .
3.9.10.4. (idxdot m1 m2 [r])

[DX] 
generalized dot product of m1 and
m2 , i.e. the sum of all products of corresponding terms in
m1 and m2 .
3.9.10.5. (idxsqrdist m1 m2 [r])

[DX] 
generalized Uclidean distance between m1
and m2 , i.e. the sum of squares of
all the differences between corresponding terms of
m1 and m2 .
3.9.10.6. (idxsumacc m r)

[DX] 
sum of terms of m . Result accumulated
in idx0 r .
3.9.10.7. (idxsupacc m r)

[DX] 
max of terms of m . Result accumulated
in idx0 r .
3.9.10.8. (idxinfacc m r)

[DX] 
min of terms of m . Result accumulated
in idx0 r .
3.9.10.9. (idxsumsqracc m r)

[DX] 
sum square of terms of m . Result
accumulated in idx0 r .
3.9.10.10. (idxdotacc m1 m2 r)

[DX] 
generalized dot product of m1 and
m2 , i.e. the sum of all products of corresponding terms in
m1 and m2 . Result
accumulated in idx0 r .
3.9.10.11. (idxsqrdistacc m1 m2 r)

[DX] 
generalized Uclidean distance between m1
and m2 , i.e. the sum of squares of
all the differences between corresponding terms of
m1 and m2 . Result
accumulated in idx0 r .
3.9.11. Operations between Tensors and Scalars


3.9.11.0. (idxdotm0 m s [r])

[DX] 
multiply all terms of m by scalar
s (an idx0).
3.9.11.1. (idxaddm0 m s [r])

[DX] 
add scalar s (an idx0) to all terms of
m .
3.9.11.2. (idxdotm0acc m s r)

[DX] 
multiply all terms of m by scalar
s (an idx0). Result accumulated in r
.
3.9.11.3. (idxaddm0acc m s r)

[DX] 
add scalar s (an idx0) to all terms of
m . Result accumulated in r
.
3.9.12. Matrix/Vector and 4Tensor/Matrix Products


3.9.12.0. (idxm2dotm1 m1 m2 [r])

[DX] 
matrixvector multiply.
3.9.12.1. (idxm4dotm2 m1 m2 [r])

[DX] 
4tensor by 2matrix multiplication: R_ij = sum_kl M1_ijkl * M2_kl
3.9.12.2. (idxm2dotm1acc m1 m2 r)

[DX] 
matrixvector multiply. Result accumulated in r
.
3.9.12.3. (idxm4dotm2acc m1 m2 r)

[DX] 
4tensor by 2matrix multiplication with accumulation: R_ij += sum_kl
M1_ijkl M2_kl
3.9.13.0. (idxm1extm1 m1 m2 [r])

[DX] 
outer product between vectors: R_ij = M1_i * M_j
3.9.13.1. (idxm2extm2 m1 m2 [r])

[DX] 
outer product between matrices. Gives a 4tensor: R_ijkl = M1_ij * M2_kl
3.9.13.2. (idxm1extm1acc m1 m2 r]


outer product between vectors with accumulation: R_ij + = M1_i * M_j
3.9.13.3. (idxm2extm2acc m1 m2 [r])

[DX] 
outer product between matrices with accumulation. Gives a 4tensor:
R_ijkl += M1_ij * M2_kl
3.9.14. Backward Compatibility Functions


These functions are here for historical reasons.
3.9.14.0. (matrix [n0...np])

[DX] 
same as (doublematrix [ n0 ...
np ]): allocate a matrix of doubles.
3.9.14.1. (submatrix m '(low0 hi0) '(low1 hi1)...)

[DX] 
This is superseded by narrow. Return a new index that points to a subset
of the elements of m . The lists
passed as arguments contain lower and upper index of the selected
elements in each dimension.
Return a list of upper bound for the index in each dimension.
3.9.14.3. (nrvectorp m)

[DX] 
Obsolete function.
3.9.14.4. (nrmatrixp m)

[DX] 
Obsolete function.
3.9.14.5. (dotproduct a b)

[DM] 
return the dot product of a and
b
3.9.14.6. (m*m a b [c])

[DE] 
obsolete and noncompilable matrix product function.
3.9.14.7. (m+m a b [c])

[DE] 
obsolete and noncompilable matrix addition function.
3.9.14.8. (mxm a b [c])

[DE] 
obsolete and noncompilable componentwise matrix multiply function.
3.9.14.9. (mm a b [c])

[DE] 
obsolete and noncompilable matrix subtraction function.
3.9.14.10. (m*c a b [c])

[DE] 
obsolete and noncompilable multiplication of a matrix by a scalar.
3.9.14.11. (m+c a b [c])

[DE] 
obsolete and noncompilable addition of a scalar to the elements of a
matrix.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;