::core::

Primitive array

Expand

Fixed size arrays, written [T; N]

Implementations

impl<T, #uint N> [T; N]
fn all(self, f: impl Fn(T) -> bool) -> bool

Returns whether the provided predicate is true for all array elements.

Note that an empty array has no elements, so the result will always be true regardless of the predicate.

Examples

assert [].any(fn |x| x == 0u8) == false;
assert [7u8, 10u8, 13u8].all(fn |x| x > 5) == true;
assert [7u8, 10u8, 13u8].all(fn |x| x > 12) == false;
assert [7u8, 10u8, 13u8].all(fn |x| x > 20) == false;
fn any(self, f: impl Fn(T) -> bool) -> bool

Returns whether the provided predicate is true for at least one array element.

Note that an empty array has no elements, so the result will always be false regardless of the predicate.

Examples

assert [].any(fn |x| x == 0u8) == false;
assert [7u8, 10u8, 13u8].any(fn |x| x > 5) == true;
assert [7u8, 10u8, 13u8].any(fn |x| x > 12) == true;
assert [7u8, 10u8, 13u8].any(fn |x| x > 20) == false;
fn chunks<#uint ChunkSize>(self) -> [[T; ChunkSize]; { N / ChunkSize }]
where
N == N / ChunkSize * ChunkSize else "The size of the input array must be a multiple of the chunk size",

Splits the array into equally-sized chunks.

The chunk size is provided at compile time as a type parameter. This means that it cannot depend on a runtime value. However, it also means that it can be inferred.

Examples

let array = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8];

let two_item_chunks = array.chunks::<2>();
assert two_item_chunks[0] == [1u8, 2u8];
assert two_item_chunks[1] == [3u8, 4u8];
assert two_item_chunks[2] == [5u8, 6u8];

let three_item_chunks = array.chunks::<3>();
assert three_item_chunks[0] == [1u8, 2u8, 3u8];
assert three_item_chunks[1] == [4u8, 5u8, 6u8];
pub fn concat<#uint M>(self, other: [T; M]) -> [T; { M + N }]

Creates an array by concatenating the elements of two existing ones.

The result is an array whose lower elements correspond to the first input array, and its higher elements correspond to the second one. In other words, given two arrays [l0, l1, ...] and [r0, r1, ...], the result is [l0, l1, ..., r0, r1, ...].

Examples

let empty: [uint<8>; 0] = [];
assert [].concat([]) == empty;
assert [1u8].concat([2u8, 3u8]) == [1u8, 2u8, 3u8];
fn reversed(self) -> Self

Reverses the elements of an array.

Examples

let empty: [uint<8>; 0] = [];
assert [].reversed() == empty;
assert [1u8, 2u8, 3u8].reversed() == [3u8, 2u8, 1u8];
fn fold<B>(self, init: B, f: impl Fn(B, T) -> B) -> B

Folds an array into a single value using a function to assimilate elements.

Given an input array [a0, a1, a2, ...] and a function f, the output would be f(init f(a0, f(a1, f(a2, ...)))).

As opposed to reduce, this function requires an initial value for the accumulator. This allows the accumulator and the array elements to have a different type, and the method to operate on empty arrays.

See also [T; N]::fold.

Examples

assert [1u8, 2u8, 3u8, 4u8].fold(0, fn |acc, val| acc +. val) == 10u8;
assert [1u8, 2u8, 3u8, 4u8].fold(true, fn |acc, val| acc && val != 4) == false;
fn interleave(self, other: Self) -> [T; { 2 * N }]

Interleaves the elements of two arrays.

An array containing elements from both input arrays is built, with even positions occupied by elements from the first array and odd positions occupied by those from the second array. In other words, given two arrays [l0, l1, l2, ...] and [r0, r1, r2, ...], the output would be [l0, r0, l1, r1, l2, r2, ...].

Examples

let l = [10u8, 11u8, 12u8];
let r = [20u8, 21u8, 22u8];
assert l.interleave(r) == [10u8, 20u8, 11u8, 21u8, 12u8, 22u8];
let empty: [uint<8>; 0] = [];
assert [].interleave([]) == empty;
fn map<O>(self, f: impl Fn(T) -> O) -> [O; N]

Builds an array by applying a function to each element of the input array.

Examples

let array = [1u8, 2u8, 3u8, 4u8];
assert array.map(fn |x| x < 4) == [true, true, true, false];
pub fn push_back(self, item: T) -> [T; { N + 1 }]

Creates a new array with item added at the end of the original array

Examples

let a = [];
let b = a.push_back(1u8);
let c = b.push_back(2u8);
let d = c.push_back(3u8);
assert b == [1u8];
assert c == [1u8, 2u8];
assert d == [1u8, 2u8, 3u8];
pub fn push_front(self, item: T) -> [T; { N + 1 }]

Adds an element at the start of the array.

Examples

let a = [];
let b = a.push_front(1u8);
let c = b.push_front(2u8);
let d = c.push_front(3u8);
assert b == [1u8];
assert c == [2u8, 1u8];
assert d == [3u8, 2u8, 1u8];
fn sliding_window<#uint M>(self) -> [[T; M]; { N - M + 1 }]
where
M <= N else "Window size is larger than array size",

Generates an array with the intermediate values of an sliding window over the input array.

The window size is provided at compile time as a type parameter. This means that it cannot depend on a runtime value. However, it also means that it can be inferred.

Examples

let array = [1u8, 2u8, 3u8, 4u8, 5u8];

let two_item_windows = array.sliding_window::<2>();
assert two_item_windows[0] == [1u8, 2u8];
assert two_item_windows[1] == [2u8, 3u8];
assert two_item_windows[2] == [3u8, 4u8];
assert two_item_windows[3] == [4u8, 5u8];

let three_item_windows = array.sliding_window::<3>();
assert three_item_windows[0] == [1u8, 2u8, 3u8];
assert three_item_windows[1] == [2u8, 3u8, 4u8];
assert three_item_windows[2] == [3u8, 4u8, 5u8];
fn split_at<#uint K>(self) -> ([T; K], [T; { N - K }])
where
K <= N else "Split point is outside array bounds",

Splits an array into two parts.

The split point is provided at compile time as a type parameter. This means that it cannot depend on a runtime value. However, it also means that it can be inferred.

Examples

let empty: [uint<8>; 0] = [];
assert empty.split_at::<0>() == ([], []);
assert [1u8, 2u8, 3u8].split_at::<0>() == ([], [1u8, 2u8, 3u8]);
assert [1u8, 2u8, 3u8].split_at::<1>() == ([1u8], [2u8, 3u8]);
assert [1u8, 2u8, 3u8].split_at::<2>() == ([1u8, 2u8], [3u8]);
assert [1u8, 2u8, 3u8].split_at::<3>() == ([1u8, 2u8, 3u8], []);
assert [1u8, 2u8, 3u8].split_at() == ([1u8, 2u8], [3u8]);
assert [1u8, 2u8, 3u8].split_at() == ([1u8, 2u8, 3u8], []);
fn zip<O>(self, other: [O; N]) -> [(T, O); N]

Pairs elements of two arrays together into a single array of tuples.

An array is produced with the same length as both inputs provided. For each array position, the elements from both arrays are paired as a tuple and stored in the result array. In other words, given two arrays [l0, l1, l2, ...] and [r0, r1, r2, ...], the output would be [(l0, r0), (l1, r1), (l2, r2), ...].

Examples

let l = [10u8, 11u8, 12u8];
let r = [20u8, 21u8, 22u8];
assert l.zip(r) == [(10u8, 20u8), (11u8, 21u8), (12u8, 22u8)];
let empty: [(uint<8>, uint<8>); 0] = [];
assert [].zip([]) == empty;
fn len(self) -> uint<{ }>

Returns the length of the array.

Since arrays are static, this simply returns a constant value.

let empty: [uint<8>; 0] = [];
assert empty.len() == 0;
assert [true].len() == 1;
assert [true, false].len() == 2;
impl<T, #uint N> [T; N]
where
N > 0,
pub fn first(self) -> T

Retrieves the first element of the array.

Examples

assert [true].first() == true;
assert [true, false].first() == true;
pub fn last(self) -> T

Retrieves the last element of the array.

Examples

assert [true].last() == true;
assert [true, false].last() == false;
fn reduce(self, f: impl Fn(T, T) -> T) -> T

Reduces an array to a single value using a function to assimilate elements.

Given an input array [a0, a1, a2, ...] and a function f, the output would be f(a0, f(a1, f(a2, ...))).

As opposed to fold, this function operates without an initial value for the accumulator by taking the first element of the array instead. This requires the accumulator and the array elements to have the same type, and the array to not be empty.

See also [T; N]::fold.

Examples

assert [1u8, 2u8, 3u8, 4u8].reduce(fn |a, b| a +. b) == 10u8;
pub fn shift_back(self, item: T) -> Self

Shifts an element into the end of the array, dropping the first one.

Examples

let a = [1u8, 2u8, 3u8];
let b = a.shift_back(4u8);
let c = b.shift_back(5u8);
let d = c.shift_back(6u8);
assert b == [2u8, 3u8, 4u8];
assert c == [3u8, 4u8, 5u8];
assert d == [4u8, 5u8, 6u8];
pub fn shift_front(self, item: T) -> Self

Shifts an element into the start of the array, dropping the last one.

Examples

let a = [3u8, 2u8, 1u8];
let b = a.shift_front(4u8);
let c = b.shift_front(5u8);
let d = c.shift_front(6u8);
assert b == [4u8, 3u8, 2u8];
assert c == [5u8, 4u8, 3u8];
assert d == [6u8, 5u8, 4u8];
impl<S, T, #uint N> [(S, T); N]
fn unzip(self) -> ([S; N], [T; N])

Splits an array of pairs into a pair of arrays.

Both arrays produced have the same length as the input array. The first element of the left array is the first element of the first tuple, the second element the first element of the second tuple, and so on. In other words, the array [(l0, r0), (l1, r1), (l2, r2), ...] is split into [l0, l1, l2, ...] and [r0, r1, r2, ...].

Examples

let (l, r) = [(10u8, 20u8), (11u8, 21u8), (12u8, 22u8)].unzip();
assert l == [10u8, 11u8, 12u8];
assert r == [20u8, 21u8, 22u8];
let empty: [(uint<8>, uint<8>); 0] = [];
assert empty.unzip() == ([], []);
impl<T, #uint N> [inv T; N]
fn transpose(self) -> inv [T; N]

Transposes an array of inv values into an inv array.

This transformation preserves the low level signals behind the value, but presents them in a new format that is easier to set.

Examples

let x = port;
let y = port;
let array_of_invs: [inv bool; 2] = [x.1, y.1];
let inv_array: inv [bool; 2] = array_of_invs.transpose();
set inv_array = [true, false];
assert x.0 == true;
assert y.0 == false;
impl<T, #uint N, #uint M> [[T; M]; N]
fn flatten(self) -> [T; { N * M }]

Turns an array of arrays into a single array containing the same elements in the same order.

This operation only flattens one level of nesting, requiring multiple calls to flatten a deeply-nested array value.

Examples

let empty: [[uint<8>; 0]; 0] = [];
assert empty.flatten() == [];
assert [[1u8], [2u8], [3u8], [4u8]].flatten() == [1u8, 2u8, 3u8, 4u8];
assert [[[1u8], [2u8]], [[3u8], [4u8]]].flatten() == [[1u8], [2u8], [3u8], [4u8]];
impl<#uint N> [bool; N]
where
N > 0,
fn reduce_and(self) -> bool

Reduces an array of bool into a single value by performing AND on all elements.

Examples

assert [true, true, true].reduce_and() == true;
assert [false, false, false].reduce_and() == false;
assert [false, true, true].reduce_and() == false;

This operation is equivalent to the Verilog AND reduction operator &.

fn reduce_or(self) -> bool

Reduces an array of bool into a single value by performing OR on all elements.

Examples

assert [true, true, true].reduce_or() == true;
assert [false, false, false].reduce_or() == false;
assert [false, true, true].reduce_or() == true;

This operation is equivalent to the Verilog OR reduction operator |.

fn reduce_xor(self) -> bool

Reduces an array of bool into a single value by performing XOR on all elements.

Examples

assert [true, true, true].reduce_xor() == true ^^ true ^^ true;
assert [false, false, false].reduce_xor() == false ^^ false ^^ false;
assert [false, true, true].reduce_xor() == false ^^ true ^^ true;

This operation is equivalent to the Verilog OR reduction operator ^.

impl<#uint N> [bool; N]
pub fn as_int(self) -> int<N>

Casts a an array of bool to a signed integer by reinterpreting its bits.

Bits are laid out from LSB to MSB, so the first element of the array corresponds to the LSB of the input number and the last element corresponds to its MSB.

Note that bits in the literal binary representation of the number are written right-to-left, while items in the literal representation of the array are written left-to-right.

Examples

assert [true, true, true, false].as_int() == 0b0111i4;
assert [true, true, true, true].as_int() == -0b0001i4;
pub fn as_uint(self) -> uint<N>

Casts an array of bool to an unsigned integer by reinterpreting its bits.

Bits are laid out from LSB to MSB, so the first element of the array corresponds to the LSB of the input number and the last element corresponds to its MSB.

Note that bits in the literal binary representation of the number are written right-to-left, while items in the literal representation of the array are written left-to-right.

Examples

assert [true, false, true, true].as_uint() == 0b1101u4;
pub fn to_int(self) -> int<N>

Casts a an array of bool to a signed integer by reinterpreting its bits.

Bits are laid out from LSB to MSB, so the first element of the array corresponds to the LSB of the input number and the last element corresponds to its MSB.

Note that bits in the literal binary representation of the number are written right-to-left, while items in the literal representation of the array are written left-to-right.

Examples

assert [true, true, true, false].to_int() == 0b0111i4;
assert [true, true, true, true].to_int() == -0b0001i4;
pub fn to_uint(self) -> uint<N>

Casts an array of bool to an unsigned integer by reinterpreting its bits.

Bits are laid out from LSB to MSB, so the first element of the array corresponds to the LSB of the input number and the last element corresponds to its MSB.

Note that bits in the literal binary representation of the number are written right-to-left, while items in the literal representation of the array are written left-to-right.

Examples

assert empty.to_uint() == 0u0;
assert [true, false, true, true].to_uint() == 0b1101u4;

Trait Implementations

impl<T: Data, #uint N> Data for [T; N]
impl<#uint N, T: PartialEq> PartialEq for [T; N]
fn eq(self, rhs: Self) -> bool
fn ne(self, rhs: Self) -> bool
impl<#uint N> BitNot for [bool; N]
fn bit_not(self) -> Self
impl<#uint N> BitAnd for [bool; N]
fn bit_and(self, rhs: Self) -> Self
impl<#uint N> BitOr for [bool; N]
fn bit_or(self, rhs: Self) -> Self
impl<#uint N> BitXor for [bool; N]
fn bit_xor(self, rhs: Self) -> Self