`gauche.array`

- Arrays ¶- Module:
**gauche.array**¶ -
This module provides multi-dimensional array data type and operations. The primitive API follows SRFI-25. Besides a generic SRFI-25 array that can store any Scheme objects, this module also provides array classes that stores numeric objects efficiently, backed up by homogeneous numeric vectors (see Uniform vectors). An external representation of arrays, using SRFI-10 mechanism, is also provided.

Each element of an

`N`-dimensional array can be accessed by`N`integer indices,`[`

. An array has associated`i_0``i_1`…`i_N-1`]`shape`that knows lower-bound`s_k`and upper-bound`e_k`of index of each dimension, where`s_k`<=`e_k`, and the index`i_k`must satisfy`s_k`<=`i_k`<`e_k`. (Note: it is allowed to have`s_k`==`e_k`, but such array can’t store any data. It is also allowed to have zero-dimensional array, that can store a single data.). The shape itself is a [`D`x 2 ] array, where`D`is the dimension of the array which the shape represents.You can pass index(es) to array access primitives in a few ways; each index can be passed as individual argument, or can be ’packed’ in a vector or one-dimensional array. In the latter case, such a vector or an array is called an "index object". Using a vector is efficient in Gauche when you iterate over the elements by changing the vector elements, for it won’t involve memory allocation.

Arrays can be compared by the

`equal?`

procedure.`Equal?`

returns`#t`

if two arrays have the same shape and their corresponding elements are the same in the sense of`equal?`

.Internally, an array consists of a backing storage and a mapping procedure. A backing storage is an object of aggregate type that can be accessed by an integer index. A mapping procedure takes multi-dimensional indices (or index object) and returns a scalar index into the backing storage.

- Class:
**<array-base>**¶ -
{

`gauche.array`

} An abstract base class of array types, that implements generic operations on the array. To create an array instance, you should use one of the following concrete array classes.

- Class:
**<array>**¶ - Class:
**<u8array>**¶ - Class:
**<s8array>**¶ - Class:
**<u16array>**¶ - Class:
**<s16array>**¶ - Class:
**<u32array>**¶ - Class:
**<s32array>**¶ - Class:
**<u64array>**¶ - Class:
**<s64array>**¶ - Class:
**<f16array>**¶ - Class:
**<f32array>**¶ - Class:
**<f64array>**¶ -
{

`gauche.array`

} Concrete array classes. The`<array>`

class implements SRFI-25 compatible array, i.e. an array that can store any Scheme objects. The`<u8array>`

class through`<f64array>`

classes uses a`<u8vector>`

through`<f64vector>`

as a backing storage, and can only store a limited range of integers or inexact real numbers, but they are space efficient.

- Reader Syntax:
¶`#,(<array>`

`shape``obj`…) An array is written out in this format. (Substitute

`<array>`

for`<u8array>`

if the array is`<u8array>`

, etc.)`shape`is a list of even number of integers, and each 2`n`-th integer and 2`n`+1-th integer specifies the inclusive lower-bound and exclusive upper-bound of`n`-th dimension, respectively. The following`obj`… are the values in the array listed in row-major order.When read back, this syntax is read as an array with the same shape and content, so it is

`equal?`

to the original array.; an array such that: ; 8 3 4 ; 1 5 9 ; 6 7 2 #,(<array> (0 3 0 3) 8 3 4 1 5 9 6 7 2) ; a 4x4 identity matrix #,(<array> (0 4 0 4) 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1)

- Function:
**array?**`obj`¶ [SRFI-25]{

`gauche.array`

} Returns`#t`

if`obj`is an array,`#f`

otherwise. It is equivalent to`(is-a? obj <array-base>)`

.

- Function:
**make-array**`shape :optional init`¶ [SRFI-25]{

`gauche.array`

} Creates an array of shape`shape`.`Shape`must be a [`D`x 2 ] array, and for each`k`(0 <=`k`<`D`), the [`k`0 ] element must be less than or equal to the [`k`1] element. If`init`is given, all the elements are initialized by it. Otherwise, the initial value of the elements are undefined.(make-array (shape 0 2 0 2 0 2) 5) ⇒ #,(<array> (0 2 0 2 0 2) 5 5 5 5 5 5 5 5)

- Function:
**make-f32array**`shape :optional init`¶ - Function:
**make-f64array**`shape :optional init`¶ {

`gauche.array`

} Like`make-array`

, but creates and returns an uniform numeric array.

- Function:
**array-copy**`array`¶ {

`gauche.array`

} Returns a copy of`array`, with the same class, shape and content.

- Function:
**shape**`bound …`¶ [SRFI-25]{

`gauche.array`

} Takes even number of exact integer arguments, and returns a two-dimensional array that is suitable for representing the shape of an array.(shape 0 2 1 3 3 5) ⇒ #,(<array> (0 3 0 2) 0 2 1 3 3 5) (shape) ⇒ #,(<array> (0 0 0 2))

- Function:
**array**`shape init …`¶ [SRFI-25]{

`gauche.array`

} Creates an array of shape`shape`, initializing its elements by`init`….(array (shape 0 2 1 3) 'a 'b 'c 'd) ⇒ #,(<array> (0 2 1 3) a b c d)

- Function:
**f32array**`shape init …`¶ - Function:
**f64array**`shape init …`¶ {

`gauche.array`

} Like`array`

, but creates and returns an uniform numeric array initialized by`init`….(u8array (shape 0 2 0 2) 1 2 3 4) ⇒ #,(<u8array> (0 2 0 2) 1 2 3 4)

- Function:
**array-rank**`array`¶ [SRFI-25]{

`gauche.array`

} Returns the number of dimensions of an array`array`.(array-rank (make-array (shape 0 2 0 2 0 2))) ⇒ 3 (array-rank (make-array (shape))) ⇒ 0

- Function:
**array-shape**`array`¶ {

`gauche.array`

} Returns a shape array of`array`.

- Function:
**array-start**`array dim`¶ - Function:
**array-end**`array dim`¶ - Function:
**array-length**`array dim`¶ [SRFI-25+]{

`gauche.array`

}`Array-start`

returns the inclusive lower bound of index of`dim`-th dimension of an array`array`.`Array-end`

returns the exclusive upper bound. And`array-length`

returns the difference between two.`Array-start`

and`array-end`

are defined in SRFI-25.(define a (make-array (shape 1 5 0 2))) (array-start a 0) ⇒ 1 (array-end a 0) ⇒ 5 (array-length a 0) ⇒ 4 (array-start a 1) ⇒ 0 (array-end a 1) ⇒ 2 (array-length a 1) ⇒ 2

- Function:
**array-size**`array`¶ {

`gauche.array`

} Returns the total number of elements in the array`array`.(array-size (make-array (shape 5 9 1 3))) ⇒ 8 (array-size (make-array (shape))) ⇒ 1 (array-size (make-array (shape 0 0 0 2))) ⇒ 0

- Function:
**array-ref**`array k …`¶ - Function:
**array-ref**`array index`¶ [SRFI-25]{

`gauche.array`

} Gets the element of array`array`

. In the first form, the element is specified by indices`k`…. In the second form, the element is specified by an index object`index`, which must be a vector or an one-dimensional array.

- Function:
**array-set!**`array k … value`¶ - Function:
**array-set!**`array index value`¶ [SRFI-25]{

`gauche.array`

} Sets the element of array`array`to`value`. In the first form, the element is specified by indices`k`…. In the second form, the element is specified by an index object`index`, which must be a vector or an one-dimensional array.

[SRFI-25]{

`gauche.array`

} Creates and returns a new array of shape`shape`, that shares the backing storage with the given array`array`. The procedure`proc`maps the indices of the new array to the indices to the original array, i.e.`proc`must be a`n`-ary procedure that returns`m`values, where`n`is the dimension of the new array and`m`is the one of the original array. Furthermore,`proc`must be an affine function; each mapping has to be a linear combination of input arguments plus optional constant. (`Share-array`

optimizes the mapping function based on the affinity assumption, so`proc`won’t be called every time the new array is accessed).

- Function:
**array-for-each-index**`array proc :optional index`¶ {

`gauche.array`

} Calls`proc`with every index of`array`. If no`index`argument is provided,`proc`is called as`(`

, in which (`proc``i``j``k`…)`i`,`j`,`k`,…) walks over the index. It begins from the least index value of each dimension, and latter dimension is incremented faster.gosh> (define a (array (shape 0 2 0 2) 1 2 3 4)) a gosh> a #,(<array> (0 2 0 2) 1 2 3 4) gosh> (array-for-each-index a (^(i j) (print i","j))) 0,0 0,1 1,0 1,1

This form of passing indexes is simple but not very efficient, though. For better performance, you can pass an index object to an optional argument

`index`, which is modified for each index and passed to`proc`. The index object must be mutable, and either a vector, an one-dimensional array, an s8vector, an s16vector or an s32vector. The length of the index object must match the rank of the array. Using index object is efficient since the loop won’t allocate. Don’t forget that the index object is destructively modified within the loop.gosh> (array-for-each-index a (cut format #t "~s\n" <>) (vector 0 0)) #(0 0) #(0 1) #(1 0) #(1 1) gosh> (array-for-each-index a (cut format #t "~s\n" <>) (s8vector 0 0)) #s8(0 0) #s8(0 1) #s8(1 0) #s8(1 1)

The procedure returns an unspecified value.

- Function:
**shape-for-each**`shape proc :optional index`¶ {

`gauche.array`

} Calls`proc`with all possible indexes represented by the shape`shape`. The optional`index`argument works the same way as`array-for-each-index`

. Returns an unspecified value.gosh> (shape-for-each (shape 0 2 0 2) (^(i j) (print i","j))) 0,0 0,1 1,0 1,1

- Function:
**tabulate-array**`shape proc :optional index`¶ {

`gauche.array`

} Calls`proc`over each index represented by the shape`shape`, and creates an array from the result of`proc`. The optional index object can be used in the same way as`array-for-each-index`

. The following example creates an identity matrix of the given shape:(tabulate-array (shape 0 3 0 3) (^(i j) (if (= i j) 1 0))) ⇒ #,(<array> (0 3 0 3) 1 0 0 0 1 0 0 0 1)

- Function:
**array-retabulate!**`array proc :optional index`¶ - Function:
**array-retabulate!**`array shape proc :optional index`¶ {

`gauche.array`

} Calls`proc`over each index of the given`array`, and modifies the array’s element by the returned value of`proc`. The optional index object can be used in the same way as`array-for-each-index`

. The second form takes a shape; it must match the`array`’s shape. It is redundant, but may allow some optimization in future in case`shape`is a literal. Returns an unspecified value.

- Function:
**array-map**`proc array0 array1 …`¶ - Function:
**array-map**`shape proc array0 array1 …`¶ {

`gauche.array`

} The arguments`array0`,`array1`, … must be arrays with the same shape. For each set of corresponding elements of the input arrays,`proc`is called, and a new array of the same shape is created by the returned values. The second form takes a shape argument, which must match the shape of input array(s). It is redundant, but may allow some optimization in future in case`shape`is a literal.(array-map - (array (shape 0 2 0 2) 1 2 3 4)) ⇒ #,(<array> (0 2 0 2) -1 -2 -3 -4)

- Function:
**array-map!**`array proc array0 array1 …`¶ - Function:
**array-map!**`array shape proc array0 array1 …`¶ {

`gauche.array`

} Like`array-map`

, but the results of`proc`are stored by the given`array`, whose shape must match the shape of input array(s). Returns unspecified value.

- Function:
**array->vector**`array`¶ - Function:
**array->list**`array`¶ {

`gauche.array`

} Returns a fresh vector or a fresh list of all elements in`array`.(array->vector (tabulate-array (shape 1 3 1 4) (^(i j) (+ (* 10 i) j)))) ⇒ #(11 12 13 21 22 23)

- Function:
**array-concatenate**`a b :optional dimension`¶ {

`gauche.array`

} Concatenates arrays at the specified dimension. The sizes of the specified dimension of two arrays must match, although the shapes can be different. Arrays can be of any ranks, but two ranks must match.;; [a b] [a b] ;; [c d] (+) => [c d] ;; [e f] [e f] (array-concatenate (array (shape 0 2 0 2) 'a 'b 'c 'd) (array (shape 0 1 0 2) 'e 'f)) ⇒ #,(<array> (0 3 0 2) a b c d e f) ;; [a b] [e] [a b e] ;; [c d] (+) [f] => [c d f] (array-concatenate (array (shape 0 2 0 2) 'a 'b 'c 'd) (array (shape 0 2 0 1) 'e 'f) 1) ⇒ #,(<array> (0 2 0 3) a b e c d f) ;; The index range can differ, as far as the sizes match (array-concatenate (array (shape 0 2 0 2) 'a 'b 'c 'd) (array (shape 1 3 0 1) 'e 'f) 1) ⇒ #,(<array> (0 2 0 3) a b e c d f)

- Function:
**array-transpose**`array :optional dim1 dim2`¶ {

`gauche.array`

} The given array must have a rank greater than or equal to 2. Transpose the array’s`dim1`-th dimension and`dim2`-th dimension. The default is 0 and 1.

- Function:
**array-rotate-90**`array :optional dim1 dim2`¶ {

`gauche.array`

} The given array must have a rank greater than or equal to 2. We regard the array as a matrix with`dim1`-th dimension as rows and`dim2`-th dimension as columns, and returns a fresh array whose content is filled by*rotating*`array`90 degree clockwise. The defaults of`dim1`and`dim2`are 0 and 1, respectively.;; [1 2 3] [4 1] ;; [4 5 6] => [5 2] ;; [6 3] (array-rotate-90 (array (shape 0 2 0 3) 1 2 3 4 5 6)) ⇒ #,(<array> (0 3 0 2) 4 1 5 2 6 3)

If

`array`has a rank greater than 2, the array is treated as a matrix of subarrays.

- Function:
**array-flip**`array :optional dimension`¶ - Function:
**array-flip!**`array :optional dimension`¶ {

`gauche.array`

} Flips the content of the array across the`dimension`-th dimension. (default is 0).`array-flip!`

modifies the content of`array`and return it.`array-flip`

doesn’t modify`array`but creates a fresh array with the flipped content and returns it.;; [1 2 3] => [4 5 6] ;; [4 5 6] [1 2 3] (array-flip (array (shape 0 2 0 3) 1 2 3 4 5 6)) ⇒ #,(<array> (0 2 0 3) 4 5 6 1 2 3) ;; [1 2 3] => [3 2 1] ;; [4 5 6] [6 5 4] (array-flip (array (shape 0 2 0 3) 1 2 3 4 5 6) 1) ⇒ #,(<array> (0 2 0 3) 3 2 1 6 5 4)

- Function:
**identity-array**`dimension :optional class`¶ {

`gauche.array`

} Returns a fresh identity array of rank 2, with the given dimension. You can pass one of array classes to`class`to make the result the instance of the class; the default class is`<array>`

.(identity-array 3) ⇒ #,(<array> (0 3 0 3) 1 0 0 0 1 0 0 0 1) (identity-array 3 <f32array>) ⇒ #,(<f32array> (0 3 0 3) 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0)

- Function:
**array-inverse**`array`¶ {

`gauche.array`

} Regards the`array`as a matrix, and returns its inverse matrix;`array`must be 2-dimensional, and must have square shape. If`array`doesn’t satisfy these conditions, an error is thrown.If

`array`isn’t a regular matrix,`#f`

is returned.

- Function:
**determinant**`array`¶ - Function:
**determinant!**`array`¶ {

`gauche.array`

} Regards the`array`as a matrix, and calculates its determinant;`array`must be 2-dimensional, and must have square shape. If`array`doesn’t satisfy these conditions, an error is thrown.`determinant!`

destructively modifies the given array during calculation. It is faster than`determinant`

, which copies`array`before calculation to preserve it.

- Function:
**array-mul**`a b`¶ {

`gauche.array`

} Arrays`a`and`b`must be rank 2. Regarding them as matrices, multiply them together. The number of rows of`a`and the number of columns of`b`must match.;; [6 5] ;; [1 2 3] x [4 3] => [20 14] ;; [4 5 6] [2 1] [56 41] (array-mul (array (shape 0 2 0 3) 1 2 3 4 5 6) (array (shape 0 3 0 2) 6 5 4 3 2 1)) ⇒ #,(<array> (0 2 0 2) 20 14 56 41)

- Function:
**array-expt**`array pow`¶ {

`gauche.array`

} Raises`array`to the power of`pow`;`array`must be a square matrix, and`pow`must be a nonnegative exact integer.

- Function:
**array-div-left**`a b`¶ - Function:
**array-div-right**`a b`¶ {

`gauche.array`

} Inverse of`array-mul`

;`array-div-left`

returns a matrix`M`

such that`(array-mul B M)`

equals to`A`

, and`array-div-right`

returns a matrix`M`

such that`(array-mul M B)`

equals to`A`

.`A`and`B`must be a 2-dimensional square matrix. If`B`

isn’t regular, an error is thrown.

- Function:
**array-add-elements**`array array-or-scalar …`¶ - Function:
**array-add-elements!**`array array-or-scalar …`¶ - Function:
**array-sub-elements**`array array-or-scalar …`¶ - Function:
**array-sub-elements!**`array array-or-scalar …`¶ - Function:
**array-mul-elements**`array array-or-scalar …`¶ - Function:
**array-mul-elements!**`array array-or-scalar …`¶ - Function:
**array-div-elements**`array array-or-scalar …`¶ - Function:
**array-div-elements!**`array array-or-scalar …`¶ {

`gauche.array`

} Element-wise arithmetics. The second argument and after must be an array of the same shape of the first argument, or a number; if it is a number, it is interpreted as an array of the same shape of the first argument, and each element of which is the given number.Returns an array of the same shape of the first argument, where each element is the result of addition, subtraction, multiplication or division of the corresponding elements of the arguments.

The linear-update version (procedures whose name ends with

`!`

) may reuse the storage of the first array to calculate the result. The first array must be mutable. The caller must still use the returned value instead of counting on the side effects.(array-add-elements (array (shape 0 2 0 2) 1 2 3 4) (array (shape 0 2 0 2) 5 6 7 8) 10) ⇒ #,(<array> (0 2 0 2) 16 18 20 22) (array-div-elements (array (shape 0 2 0 2) 1 3 5 7) 100 (array (shape 0 2 0 2) 2 4 6 8)) ⇒ #,(<array> (0 2 0 2) 1/200 3/400 1/120 7/800)

If only one argument is passed, these procedures returns the argument itself.

You can mix different types of arrays as long as their shapes are the same. The result is the same type as the first argument.

(array-mul-elements (make-u8array (shape 0 2 0 2) 3) (array (shape 0 2 0 2) 1 3 5 7)) ⇒ #,(<u8array> (0 2 0 2) 3 9 15 21)

- Function:
**array-negate-elements**`array`¶ - Function:
**array-negate-elements!**`array`¶ Returns an array with the same type of the shape of

`array`, but each element is a negation of the corresponding elements in the original array.(array-negate-elements (array (shape 0 2 0 2) 1 2 3 4)) ⇒ #,(<array> (0 2 0 2) -1 -2 -3 -4)

- Function:
**array-reciprocate-elements**`array`¶ - Function:
**array-reciprocate-elements!**`array`¶ Returns an array with the same type of the shape of

`array`, but each element is a reciprocal of the corresponding elements in the original array.(array-reciprocate-elements (array (shape 0 2 0 2) 1 2 3 4)) ⇒ #,(<array> (0 2 0 2) 1 1/2 1/3 1/4)

DRAFT