# 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 of `N` bit unsigned integers.

• `array::int``N`, N = 8, 16, 32 or 64. Arrays of `N` bit signed integers.

• `array::float``N`, N = 32 or 64. Arrays of `N` bit floating point real numbers.

• `array::complex``N`, N = 32 or 64. Arrays of `2 * 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>>
C: <<vector::any>>
```

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>>
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.