Arrays¶
Minilang can optionally be built with support for multidimensional arrays. There are several different types of array, each capable of storing different types of values:
array::uint
N
, N = 8, 16, 32 or 64. Arrays ofN
bit unsigned integers.array::int
N
, N = 8, 16, 32 or 64. Arrays ofN
bit signed integers.array::float
N
, N = 32 or 64. Arrays ofN
bit floating point real numbers.array::complex
N
, N = 32 or 64. Arrays of2 * N
bit floating point complex numbers. Only available if Minilang was built with support for complex numbers.array::any
. Arrays of any Minilang value. Not all operations are available for these arrays.
Each array type (except array::any
) also has other parent types denoting their properties:
Integer array types are subtypes of
array::integer
.Real array types (including integer array types) are subtypes of
array::real
.Complex array types (including real and integer array types) are subtypes of
array::complex
.
If an array has exactly 1 or 2 dimensions, it will have type vector::
type
or matrix::
type
respectively. Each vector and matrix type is also a subtype of one or more of vector::integer
, vector::real
, ..., matrix::integer
, ... etc.
Constructing Arrays¶
Arrays can be created by calling the corresponding type with a list of dimension sizes. All the entries of new array will be initialized to 0 and can be assigned later.
1let A := array::int32([2, 2])
2print('A = {A}')
3A[1, 1] := 11
4A[1, 2] := 12
5A[2, 1] := 21
6A[2, 2] := 22
7print('A = {A}')
A = <<0 0> <0 0>>
A = <<11 12> <21 22>>
Instead of assigning each value later, a function can be passed to the array constructor to populate the values. The function will be called with the indices of each entry and the returned value will be assigned to the entry in the new array.
1let A := array::int32([2, 2], fun(I, J) I * 10 + J)
2:> or
3let A := array::int32([2, 2]; I, J) I * 10 + J
A = <<11 12> <21 22>>
Arrays can also be constructed directly from nested lists using array
. In this case, the array type and shape is inferred from the list values and structure.
1let A := array([[1, 2], [3, 4]])
2print('A: {type(A)}{A:shape}\n')
3let B := array([1.0, 2.0, 3.0])
4print('B: {type(B)}{B:shape}\n')
5let C := array(["A", "B", "C"])
6print('C: {type(C)}{C:shape}\n')
A: <<matrix::int64>>[2, 2]
B: <<vector::float64>>[3]
C: <<vector::any>>[3]
For convenience, the prefix operators $
and ^
can be used with lists to construct arrays more easily. $List
is equivalent to array(List)
. ^List
adds an extra dimension of size 1 and then transposes the resulting array. It is mainly used for constructing column vectors without requiring each value being wrapped in its own list.
1let A := $[[1, 2], [3, 4]]
2print('A: {type(A)}{A:shape}\n')
3let B := $[1.0, 2.0, 3.0]
4print('B: {type(B)}{B:shape}\n')
5let C := ^["A", "B", "C"]
6print('C: {type(C)}{C:shape}\n')
A: <<matrix::int64>>[2, 2]
B: <<vector::float64>>[3]
C: <<vector::any>>[3, 1]
Array Operations¶
The standard numeric infix operations (+
, -
, *
, /
and ^
) are all available for arrays and operate element-wise. When used with 2 arrays with different dimension counts, the smaller array is used repeatedly for each of the additional dimensions in the bigger array. This is often called broadcasting in other array libraries.