March Docs

NativeArray

NativeArray — flat numeric arrays for high-performance numeric loops.

Unlike Array (which uses a 32-way persistent trie), NativeArray is backed by a flat OCaml array that maps directly to sequential memory. This makes it cache-friendly for sequential scan patterns and enables tight inner loops for sum, map, and fold operations.

Compiled (--compile) vectorization, in practice:

  • sum_int / sum_float: both auto-vectorize under clang -O2 (NEON on
  arm64, SSE4.2+ on x86-64) — sum_float needed a scoped
  `#pragma clang fp reassociate(on)` in the runtime C loop, since
  strict IEEE 754 float semantics otherwise block the reduction from
  vectorizing at all.
- map_int with a non-capturing or single-capture lambda: the compiler
  inlines the callback directly into the loop instead of dispatching
  through a closure pointer, which lets clang's own inliner and
  vectorizer see through it — arithmetic-heavy bodies (`fn x -> x*x+1`,
  `fn x -> x + captured`) compile to real SIMD instructions. A closure
  reused elsewhere, or one with more than one captured variable, still
  works correctly but falls back to the slower closure-dispatch path.
- map_float: correct and (for capturing/non-capturing alike) gets the
  same closure-inlining treatment as map_int. Float crossing a
  closure-call boundary is normally heap-boxed (march_alloc_float),
  which blocks vectorization — but when the callback's signature is
  concretely all-Float (no generic type variable), the compiler clones
  the inlined callback under natural double params/return with zero
  boxing, and the loop DOES vectorize (real NEON/SSE, confirmed via
  -emit-llvm). A callback whose signature is still generic at this
  point falls back to the boxed (correct, non-vectorized) path. See
  specs/optimizations.md P10 "Float-boxing Stage 4, Option B" and
  specs/plans/2026-07-13-float-boxing-design.md.
- fold_int / fold_float / fold_f32 / fold_i32 / fold_u8 all have compiled
  implementations: the accumulator crosses the closure boundary in the
  erased/boxed representation (see march_typed_array_fold's RC
  discipline, which native_*_arr_fold mirrors), so no per-width
  vectorization applies — this is a correctness-first scalar loop.
- map2_int / map2_float (two-array zip-with, e.g. for column-column
  arithmetic) get the identical closure-inlining/vectorization treatment
  map_int/map_float do above — same eligibility bar, same unboxed clone
  for a concrete-Float callback. Verified ~47x faster than the pre-fix
  boxed closure-call path on a 5M-element benchmark; see
  docs/simd-benchmarks.md's "Fix history: map2".

Sharing and sending (Part C of specs/plans/2026-09-25-send-data-race-freedom-plan.md): A native array is a VALUE with copy-on-write semantics. set_ and sort_ "return a new array"; the compiled runtime writes in place only when the caller held the sole reference (march_rc_is_unique, an acquire load of the reference count) and copies otherwise, and the interpreter always copies. No program can tell the two apart, so an array may be sent in an actor message, captured by a Task or Parallel closure, or stored in a record like any other value; each holder sees only its own writes. Cost model:

  • a write to an array nobody else holds is in place: O(1) for set,
  O(n log n) for sort, no allocation;
- the first write to a SHARED array copies it, O(n), one allocation;
  later writes to the copy are in place again;
- sending, capturing in a closure or storing in a record shares the
  array. A loop `let arr = NativeArray.set_int(arr, i, v)` that threads
  the array through never shares it and never copies.
Audited 2026-10-06 (runtime/march_runtime.c): set and sort at all five
widths including the sort fast paths, and the SIMD vector store, are
gated on sole ownership; map/map2 (C and the inlined fast path),
filter_mask, the width conversions and from_list allocate fresh. Nothing
writes an array it does not solely own.

Five opaque element types are supported: NativeIntArr — wraps int array (i64) NativeFloatArr — wraps float array (f64) NativeF32Arr — narrow float array (f32); stores round to nearest-even NativeI32Arr — narrow int array (i32); stores truncate mod 2^32 NativeU8Arr — narrow int array (u8); stores truncate mod 2^8 Narrow-width stores never trap; loads widen exactly (u8 zero-extends, i32 sign-extends). See docs/simd-vectorization.md's "Narrow element widths" section for the full boundary rule and benchmarks.

Usage: let arr = NativeArray.make_float(1000, 0.0) let arr2 = NativeArray.map_float(arr, fn x -> x *. 2.0) let s = NativeArray.sum_float(arr2)

Functions

fnf32_to_float_arrf32_to_float_arr(arr)#

Widen a NativeF32Arr to NativeFloatArr (exact). O(n).

Examples

march> NativeArray.to_list_float(NativeArray.f32_to_float_arr(NativeArray.from_list_f32([0.5, 2.25])))
[0.5, 2.25]
fnfloat_to_f32_arrfloat_to_f32_arr(arr)#

Narrow a NativeFloatArr to a NativeF32Arr, rounding each element to binary32 (nearest-even). O(n).

Examples

march> NativeArray.to_list_f32(NativeArray.float_to_f32_arr(NativeArray.from_list_float([1.5, -0.25])))
[1.5, -0.25]
march> NativeArray.get_f32(NativeArray.float_to_f32_arr(NativeArray.from_list_float([0.1])), 0) == 0.1
false
fnfold_f32fold_f32(arr, acc, f)#

Left fold over all elements (each widened to Float). Argument order: collection first, init second, callback last (uncurried-collection convention). Callback f(acc, elem) = new_acc. O(n).

Examples

march> NativeArray.fold_f32(NativeArray.from_list_f32([0.5, 0.25]), 1.5, fn (acc, x) -> acc +. x)
2.25
fnfold_floatfold_float(arr, acc, f)#

Left fold over all elements. Argument order: collection first, init second, callback last (uncurried-collection convention). Callback f(acc, elem) = new_acc. O(n).

Examples

march> NativeArray.fold_float(NativeArray.from_list_float([1.5, 2.25]), 0.5, fn (acc, x) -> acc +. x)
4.25
fnfold_i32fold_i32(arr, acc, f)#

Left fold over all elements (each sign-extended to Int). Argument order: collection first, init second, callback last (uncurried-collection convention). Callback f(acc, elem) = new_acc. O(n).

Examples

march> NativeArray.fold_i32(NativeArray.from_list_i32([-1, 2]), 10, fn (acc, x) -> acc - x)
9
fnfold_intfold_int(arr, acc, f)#

Left fold over all elements. Argument order: collection first, init second, callback last (uncurried-collection convention). Callback f(acc, elem) = new_acc. O(n).

Examples

march> NativeArray.fold_int(NativeArray.from_list_int([1, 2, 3]), 0, fn (acc, x) -> acc * 10 + x)
123
march> NativeArray.fold_int(NativeArray.from_list_int([]), 5, fn (acc, x) -> acc + x)
5
fnfold_u8fold_u8(arr, acc, f)#

Left fold over all elements (each zero-extended to Int). Argument order: collection first, init second, callback last (uncurried-collection convention). Callback f(acc, elem) = new_acc. O(n).

Examples

march> NativeArray.fold_u8(NativeArray.from_list_u8([1, 2, 3]), 0, fn (acc, x) -> acc * 10 + x)
123
fnfrom_list_f32from_list_f32(lst)#

Build a NativeF32Arr from a List(Float), rounding each element to binary32. O(n).

Examples

march> NativeArray.length_f32(NativeArray.from_list_f32([0.5, 1.5, 2.5]))
3
march> NativeArray.get_f32(NativeArray.from_list_f32([0.1]), 0) == 0.1
false
fnfrom_list_floatfrom_list_float(lst)#

Build a NativeFloatArr from a List(Float), preserving order. O(n).

Examples

march> NativeArray.length_float(NativeArray.from_list_float([0.5, 1.5]))
2
fnfrom_list_i32from_list_i32(lst)#

Build a NativeI32Arr from a List(Int), wrapping each element to i32. O(n).

Examples

march> NativeArray.to_list_i32(NativeArray.from_list_i32([-5, 2147483647]))
[-5, 2147483647]
fnfrom_list_intfrom_list_int(lst)#

Build a NativeIntArr from a List(Int), preserving order. O(n).

Examples

march> NativeArray.get_int(NativeArray.from_list_int([5, 6, 7]), 0)
5
fnfrom_list_u8from_list_u8(lst)#

Build a NativeU8Arr from a List(Int), wrapping each element mod 256. O(n).

Examples

march> NativeArray.to_list_u8(NativeArray.from_list_u8([256, -1, 300]))
[0, 255, 44]
fnget_f32get_f32(arr, i : Int)#

Return the element at index i (0-based), widened (exactly) to Float. O(1). Panics if i is negative or >= length_f32(arr).

Examples

march> NativeArray.get_f32(NativeArray.from_list_f32([0.5, 0.75]), 1)
0.75
march> NativeArray.get_f32(NativeArray.from_list_f32([16777217.0]), 0) == 16777216.0
true
fnget_floatget_float(arr, i : Int)#

Return the element at index i (0-based). O(1). Panics if i is negative or >= length_float(arr).

Examples

march> NativeArray.get_float(NativeArray.from_list_float([9.5, 8.5]), 1)
8.5
fnget_i32get_i32(arr, i : Int)#

Return the element at index i (0-based), sign-extended to Int. O(1). Panics if i is negative or >= length_i32(arr).

Examples

march> NativeArray.get_i32(NativeArray.from_list_i32([9, -8]), 1)
-8
fnget_intget_int(arr, i : Int)#

Return the element at index i (0-based). O(1). Panics if i is negative or >= length_int(arr).

Examples

march> NativeArray.get_int(NativeArray.from_list_int([10, 20, 30]), 2)
30
fnget_u8get_u8(arr, i : Int)#

Return the element at index i (0-based), zero-extended to Int (0..255). O(1). Panics if i is negative or >= length_u8(arr).

Examples

march> NativeArray.get_u8(NativeArray.from_list_u8([9, 255]), 1)
255
fni32_to_f32_arri32_to_f32_arr(arr)#

Convert a NativeI32Arr to NativeF32Arr, rounding each element to binary32 (nearest-even; exact for magnitudes up to 2^24). O(n).

Examples

march> NativeArray.to_list_f32(NativeArray.i32_to_f32_arr(NativeArray.from_list_i32([3, -4]))) == [3.0, -4.0]
true
fni32_to_int_arri32_to_int_arr(arr)#

Widen a NativeI32Arr to NativeIntArr (exact sign-extend). O(n).

Examples

march> NativeArray.to_list_int(NativeArray.i32_to_int_arr(NativeArray.from_list_i32([-7, 8])))
[-7, 8]
fnint_to_i32_arrint_to_i32_arr(arr)#

Narrow a NativeIntArr to NativeI32Arr, wrapping each element mod 2^32 two's-complement. O(n).

Examples

march> NativeArray.to_list_i32(NativeArray.int_to_i32_arr(NativeArray.from_list_int([1, -1])))
[1, -1]
fnint_to_u8_arrint_to_u8_arr(arr)#

Narrow a NativeIntArr to NativeU8Arr, wrapping each element mod 256. O(n).

Examples

march> NativeArray.to_list_u8(NativeArray.int_to_u8_arr(NativeArray.from_list_int([255, 256, -1])))
[255, 0, 255]
fnlength_f32length_f32(arr)#

Return the number of elements in arr. O(1).

Examples

march> NativeArray.length_f32(NativeArray.make_f32(4, 1.5))
4
fnlength_floatlength_float(arr)#

Return the number of elements in arr. O(1).

Examples

march> NativeArray.length_float(NativeArray.make_float(4, 1.5))
4
fnlength_i32length_i32(arr)#

Return the number of elements in arr. O(1).

Examples

march> NativeArray.length_i32(NativeArray.make_i32(4, 1))
4
fnlength_intlength_int(arr)#

Return the number of elements in arr. O(1).

Examples

march> NativeArray.length_int(NativeArray.from_list_int([4, 5, 6]))
3
fnlength_u8length_u8(arr)#

Return the number of elements in arr. O(1).

Examples

march> NativeArray.length_u8(NativeArray.make_u8(4, 1))
4
fnmake_f32make_f32(n : {Int | _ >= 0}, fill : Float)#

Create a new f32 array of n elements, each initialised to fill rounded to binary32. O(n). n must be non-negative (a refinement precondition).

Examples

march> NativeArray.to_list_f32(NativeArray.make_f32(2, 0.25))
[0.25, 0.25]
march> NativeArray.get_f32(NativeArray.make_f32(1, 0.1), 0) == 0.1
false
fnmake_floatmake_float(n : {Int | _ >= 0}, fill : Float)#

Create a new float array of n elements, each initialised to fill. O(n). n must be non-negative (a refinement precondition; a negative size is a runtime error).

Examples

march> NativeArray.to_list_float(NativeArray.make_float(2, 0.5))
[0.5, 0.5]
fnmake_i32make_i32(n : {Int | _ >= 0}, fill : Int)#

Create a new i32 array of n elements, each initialised to fill wrapped to i32. O(n). n must be non-negative (a refinement precondition).

Examples

march> NativeArray.to_list_i32(NativeArray.make_i32(2, -3))
[-3, -3]
fnmake_intmake_int(n : {Int | _ >= 0}, fill : Int)#

Create a new integer array of n elements, each initialised to fill. O(n). n must be non-negative (a refinement precondition; a negative size is a runtime error).

Examples

march> NativeArray.to_list_int(NativeArray.make_int(3, 7))
[7, 7, 7]
march> NativeArray.length_int(NativeArray.make_int(0, 7))
0
fnmake_u8make_u8(n : {Int | _ >= 0}, fill : Int)#

Create a new u8 array of n elements, each initialised to fill wrapped mod 256. O(n). n must be non-negative (a refinement precondition).

Examples

march> NativeArray.to_list_u8(NativeArray.make_u8(2, 7))
[7, 7]
march> NativeArray.to_list_u8(NativeArray.make_u8(2, 257))
[1, 1]
fnmap2_f32map2_f32(arr1, arr2, f)#

Apply f elementwise to two same-length arrays, returning a new NativeF32Arr. f(a_elem, b_elem) = out_elem, rounded to binary32. Panics if the arrays differ in length. O(n).

Examples

march> NativeArray.to_list_f32(NativeArray.map2_f32(NativeArray.from_list_f32([1.5, 2.5]), NativeArray.from_list_f32([0.5, 0.5]), fn (a, b) -> a *. b))
[0.75, 1.25]
fnmap2_floatmap2_float(arr1, arr2, f)#

Apply f elementwise to two same-length arrays, returning a new NativeFloatArr. f(a_elem, b_elem) = out_elem. Panics if the arrays differ in length. O(n).

Examples

march> NativeArray.to_list_float(NativeArray.map2_float(NativeArray.from_list_float([1.5, 2.5]), NativeArray.from_list_float([0.25, 0.25]), fn (a, b) -> a +. b))
[1.75, 2.75]
fnmap2_i32map2_i32(arr1, arr2, f)#

Apply f elementwise to two same-length arrays, returning a new NativeI32Arr. f(a_elem, b_elem) = out_elem, wrapped to i32. Panics if the arrays differ in length. O(n).

Examples

march> NativeArray.to_list_i32(NativeArray.map2_i32(NativeArray.from_list_i32([1, 2]), NativeArray.from_list_i32([3, -4]), fn (a, b) -> a * b))
[3, -8]
fnmap2_intmap2_int(arr1, arr2, f)#

Apply f elementwise to two same-length arrays, returning a new NativeIntArr. f(a_elem, b_elem) = out_elem. Panics if the arrays differ in length. O(n).

Examples

march> NativeArray.to_list_int(NativeArray.map2_int(NativeArray.from_list_int([1, 2]), NativeArray.from_list_int([10, 20]), fn (a, b) -> a + b))
[11, 22]
fnmap2_u8map2_u8(arr1, arr2, f)#

Apply f elementwise to two same-length arrays, returning a new NativeU8Arr. f(a_elem, b_elem) = out_elem, wrapped mod 256. Panics if the arrays differ in length. O(n).

Examples

march> NativeArray.to_list_u8(NativeArray.map2_u8(NativeArray.from_list_u8([200, 1]), NativeArray.from_list_u8([100, 2]), fn (a, b) -> a + b))
[44, 3]
fnmap_f32map_f32(arr, f)#

Apply f to every element (widened Float in, rounded to binary32 out), returning a new NativeF32Arr. O(n).

Examples

march> NativeArray.to_list_f32(NativeArray.map_f32(NativeArray.from_list_f32([1.5, 2.25]), fn x -> x +. 1.0))
[2.5, 3.25]
fnmap_floatmap_float(arr, f)#

Apply f to every element, returning a new NativeFloatArr. O(n).

Examples

march> NativeArray.to_list_float(NativeArray.map_float(NativeArray.from_list_float([1.5, 2.5]), fn x -> x *. 0.5))
[0.75, 1.25]
fnmap_i32map_i32(arr, f)#

Apply f to every element (sign-extended Int in, wrapped to i32 out), returning a new NativeI32Arr. O(n).

Examples

march> NativeArray.to_list_i32(NativeArray.map_i32(NativeArray.from_list_i32([1, -2]), fn x -> x * 3))
[3, -6]
fnmap_intmap_int(arr, f)#

Apply f to every element, returning a new NativeIntArr. O(n).

Examples

march> NativeArray.to_list_int(NativeArray.map_int(NativeArray.from_list_int([1, 2, 3]), fn x -> x * x))
[1, 4, 9]
fnmap_u8map_u8(arr, f)#

Apply f to every element (zero-extended Int in, wrapped mod 256 out), returning a new NativeU8Arr. O(n).

Examples

march> NativeArray.to_list_u8(NativeArray.map_u8(NativeArray.from_list_u8([100, 200]), fn x -> x * 2))
[200, 144]
fnset_f32set_f32(arr, i : Int, v : Float)#

Return an array with element i set to v rounded to binary32 (nearest-even); the value conversion never traps. Same value semantics and cost as set_int. Panics if i is negative or >= length_f32(arr).

Examples

march> NativeArray.to_list_f32(NativeArray.set_f32(NativeArray.make_f32(2, 0.25), 0, 0.5))
[0.5, 0.25]
fnset_floatset_float(arr, i : Int, v : Float)#

Return an array with element i replaced by v. Same value semantics and cost as set_int: in place when solely owned (compiled), otherwise an O(n) copy. Panics if i is negative or >= length_float(arr).

Examples

march> NativeArray.to_list_float(NativeArray.set_float(NativeArray.make_float(2, 0.5), 1, 2.5))
[0.5, 2.5]
fnset_i32set_i32(arr, i : Int, v : Int)#

Return an array with element i set to v wrapped mod 2^32 two's-complement; the value conversion never traps. Same value semantics and cost as set_int. Panics if i is negative or >= length_i32(arr).

Examples

march> NativeArray.to_list_i32(NativeArray.set_i32(NativeArray.make_i32(2, 0), 0, -9))
[-9, 0]
fnset_intset_int(arr, i : Int, v : Int)#

Return an array with element i replaced by v. Value semantics: the original is unchanged as far as any other holder can tell. O(1) in place when the compiled program holds the only reference, otherwise an O(n) copy (the interpreter always copies). Panics if i is negative or >= length_int(arr).

Examples

march> NativeArray.to_list_int(NativeArray.set_int(NativeArray.from_list_int([1, 2, 3]), 0, 9))
[9, 2, 3]
march> let orig = NativeArray.from_list_int([1, 2, 3])
march> let changed = NativeArray.set_int(orig, 0, 100)
march> (NativeArray.to_list_int(orig), NativeArray.to_list_int(changed))
([1, 2, 3], [100, 2, 3])
fnset_u8set_u8(arr, i : Int, v : Int)#

Return an array with element i set to v wrapped mod 256; the value conversion never traps. Same value semantics and cost as set_int. Panics if i is negative or >= length_u8(arr).

Examples

march> NativeArray.to_list_u8(NativeArray.set_u8(NativeArray.make_u8(2, 0), 1, 511))
[0, 255]
fnsort_f32sort_f32(arr)#

Sort ascending by IEEE 754 totalOrder on binary32. Same algorithm, ownership and NaN / -0.0 placement as sort_float, on 32-bit keys: the elements are not widened to f64 to sort. Unstable, in place when the array is uniquely owned, so a threaded let a = NativeArray.sort_f32(a) allocates nothing.

-NaN < -Inf < ... < -0.0 < +0.0 < ... < +Inf < +NaN, so -0.0 sorts strictly before +0.0 although -0.0 == 0.0 is true.

march> NativeArray.get_f32(NativeArray.sort_f32(NativeArray.from_list_f32([2.5, -1.5, 0.5])), 0)
-1.5
fnsort_floatsort_float(arr)#

Sort ascending by IEEE 754 totalOrder. Same algorithm and ownership as sort_int: unstable, in place when the array is uniquely owned, so a threaded let a = NativeArray.sort_float(a) allocates nothing.

totalOrder is a total order on every bit pattern, NaN included: -NaN < -Inf < ... < -0.0 < +0.0 < ... < +Inf < +NaN. Two consequences that differ from the rest of the language:

  • -0.0 sorts strictly before +0.0, although -0.0 == 0.0 is true
and `compare(-0.0, 0.0)` is `0`.
  • A NaN goes to the end, or to the front if its sign bit is set. <
is false for every NaN comparison and `compare` does not order NaN
consistently, so a sort built on either has no defined NaN placement.

  march> NativeArray.get_float(NativeArray.sort_float(NativeArray.from_list_float([2.5, -1.5, 0.5])), 0)
  -1.5
fnsort_i32sort_i32(arr)#

Sort ascending (signed 32-bit order). The same ipnsort-style algorithm and ownership as sort_int, on 4-byte elements: unstable, in place when the array is uniquely owned, O(n) on sorted or reversed input, O(n log n) worst case.

march> NativeArray.to_list_i32(NativeArray.sort_i32(NativeArray.from_list_i32([3, -1, 2])))
[-1, 2, 3]
fnsort_intsort_int(arr)#

Sort ascending. Unstable and in place when the array is uniquely owned, so a threaded let a = NativeArray.sort_int(a) allocates nothing.

ipnsort-style: a full-run scan makes already-sorted and reversed input O(n), an equal-partition makes low-cardinality input near-linear, and a heapsort fallback bounds the worst case at O(n log n). Measured 5-30x faster than libc qsort at 5M elements; see specs/progress/2026-09-25-native-array-sort-narrow-widths.md.

Unstable is unobservable here: i64 elements carry no payload to reorder.

march> NativeArray.to_list_int(NativeArray.sort_int(NativeArray.from_list_int([3, 1, 2])))
[1, 2, 3]
fnsort_u8sort_u8(arr)#

Sort ascending. A counting sort over the 256 possible values: O(n + 256), no comparisons. Same ownership as sort_int: in place when the array is uniquely owned, so a threaded let a = NativeArray.sort_u8(a) allocates nothing.

march> NativeArray.to_list_u8(NativeArray.sort_u8(NativeArray.from_list_u8([200, 7, 255, 0])))
[0, 7, 200, 255]
fnsum_f32sum_f32(arr) : Float#

Sum all elements as a double (Float) accumulation over the already-rounded binary32 elements. O(n) tight loop.

Examples

march> NativeArray.sum_f32(NativeArray.from_list_f32([0.5, 0.25, 1.5]))
2.25
fnsum_floatsum_float(arr) : Float#

Sum all elements (0.0 for an empty array). O(n) tight loop. Compiled code may reassociate the additions to vectorize, so results on inputs that are not exactly representable can differ in the last bits from a left-to-right sum.

Examples

march> NativeArray.sum_float(NativeArray.from_list_float([0.5, 1.5, 2.25]))
4.25
fnsum_i32sum_i32(arr) : Int#

Sum all elements, accumulated in Int (i64), so the sum does not wrap at 32 bits. O(n) tight loop.

Examples

march> NativeArray.sum_i32(NativeArray.from_list_i32([-5, 7, 10]))
12
fnsum_intsum_int(arr) : Int#

Sum all elements (0 for an empty array). O(n) tight loop.

Examples

march> NativeArray.sum_int(NativeArray.from_list_int([1, 2, 3, 4]))
10
march> NativeArray.sum_int(NativeArray.from_list_int([]))
0
fnsum_u8sum_u8(arr) : Int#

Sum all elements, accumulated in Int (i64), so the sum does not wrap at 255. O(n) tight loop.

Examples

march> NativeArray.sum_u8(NativeArray.from_list_u8([255, 255]))
510
fnto_float_arrto_float_arr(arr)#

Widen every element to Float, returning a new NativeFloatArr. O(n).

Examples

march> NativeArray.to_list_float(NativeArray.to_float_arr(NativeArray.from_list_int([3, -2]))) == [3.0, -2.0]
true
fnto_list_f32to_list_f32(arr)#

Convert a NativeF32Arr to a List(Float) (exact widen), in index order. O(n).

Examples

march> NativeArray.to_list_f32(NativeArray.from_list_f32([0.5, -0.25]))
[0.5, -0.25]
fnto_list_floatto_list_float(arr)#

Convert a NativeFloatArr to a List(Float), in index order. O(n).

Examples

march> NativeArray.to_list_float(NativeArray.from_list_float([0.5, -1.5]))
[0.5, -1.5]
fnto_list_i32to_list_i32(arr)#

Convert a NativeI32Arr to a List(Int) (exact widen), in index order. O(n).

Examples

march> NativeArray.to_list_i32(NativeArray.from_list_i32([3, -1]))
[3, -1]
fnto_list_intto_list_int(arr)#

Convert a NativeIntArr to a List(Int), in index order. O(n).

Examples

march> NativeArray.to_list_int(NativeArray.from_list_int([5, 6, 7]))
[5, 6, 7]
fnto_list_u8to_list_u8(arr)#

Convert a NativeU8Arr to a List(Int) (exact zero-extend), in index order. O(n).

Examples

march> NativeArray.to_list_u8(NativeArray.from_list_u8([0, 128, 255]))
[0, 128, 255]
fnu8_to_f32_arru8_to_f32_arr(arr)#

Convert a NativeU8Arr to NativeF32Arr (every u8 value is exact in binary32). O(n).

Examples

march> NativeArray.to_list_f32(NativeArray.u8_to_f32_arr(NativeArray.from_list_u8([0, 255]))) == [0.0, 255.0]
true
fnu8_to_int_arru8_to_int_arr(arr)#

Widen a NativeU8Arr to NativeIntArr (exact zero-extend). O(n).

Examples

march> NativeArray.to_list_int(NativeArray.u8_to_int_arr(NativeArray.from_list_u8([255, 7])))
[255, 7]