No matching definitions.

tur/simd

stdlib/simd.tur

16-byte vector types and their lanewise operations.

GENERATED by tools/gen-simd.py -- edit the template there, not this file.

Phase S1 of docs/upcoming/simd-and-vectorization-plan.md, graduated 2026-10-30: (load "stdlib/simd.tur") is all a program needs.

| Type | Lanes | Lane | Loads from | |-------|-------|----------|------------| | F64x2 | 2 | float | F64Vec | | F32x4 | 4 | float32| F32Vec | | I64x2 | 2 | int | I64Vec | | I32x4 | 4 | int32 | I32Vec | | U16x8 | 8 | uint16 | (widen a U8x16) | | U8x16 | 16 | uint8 | U8Vec |

Each type is a ^copy struct with one field per lane (l0, l1, ...), so a vector is an ordinary value: a local, a parameter, a result, a struct field. (F64x2 7.1 3.25) builds one, (.l1 v) reads a lane. Every type has P-splat, P-lane, P-add, P-sub, P-mul, P-div, P-neg, P-min, P-max and P-hsum, and a Num instance, so {a + b} is the lanewise sum; the floats add P-sqrt and P-abs; all but U16x8 load from and store to their typed numeric array (P-load, P-store!, one bounds check per call); u8x16-widen-lo / -hi, u16x8-narrow and u16x8-shr move bytes through sixteen-bit lanes, where a product fits.

Comparisons (P-eq, P-lt, P-le, P-gt, P-ge) return a mask of the same lane width -- M64x2, M32x4, M16x8 or M8x16, -1 where the comparison held and 0 where not -- and P-select picks each lane from one of two vectors by a mask, without a branch; the masks combine with M-and, M-or, M-not and reduce with M-any / M-all. P-shuffle permutes lanes by an index vector (one instruction when the indices are constants). i32x4->f32x4, f32x4->i32x4 (truncating, saturating), f32x4-widen-lo / -hi and f64x2-narrow convert between lane types; every lane of every conversion is defined.

Compiled with gcc or clang, an operation is one vector instruction (a GNU vector extension over the struct's bytes); under tur jit the same operation is a loop over the lanes. Both compute each lane exactly as the scalar operator would -- integer lanes wrap, float operations are never fused -- so every engine gives the same bits. The types are 16 bytes on purpose: a 32-byte vector lives in memory on gcc without AVX (the plan's S0 findings).

Generic code takes a vector by value: a generic function (constrained or not) and a generic ADT such as (Option F64x2) are specialized per type. A Vec element is the exception -- each is boxed on the heap, as every multi-word element is -- so keep bulk lane data in the numeric arrays and load from them.

Since: S1 (simd-and-vectorization-plan)

defstruct

F64x2

(defstruct ^copy F64x2 [l0 : float l1 : float])

a 16-byte vector of 2 float lanes.

Lanes l0 .. l1; (F64x2 7.1 7.1) builds one.

Since: S1

defstruct

F32x4

(defstruct ^copy F32x4 [l0 : float32 l1 : float32 l2 : float32 l3 : float32])

a 16-byte vector of 4 float32 lanes.

Lanes l0 .. l3; (F32x4 (as float32 7.1) (as float32 7.1) (as float32 7.1) (as float32 7.1)) builds one.

Since: S1

defstruct

I64x2

(defstruct ^copy I64x2 [l0 : int l1 : int])

a 16-byte vector of 2 int lanes.

Lanes l0 .. l1; (I64x2 7 7) builds one.

Since: S1

defstruct

I32x4

(defstruct ^copy I32x4 [l0 : int32 l1 : int32 l2 : int32 l3 : int32])

a 16-byte vector of 4 int32 lanes.

Lanes l0 .. l3; (I32x4 (as int32 7) (as int32 7) (as int32 7) (as int32 7)) builds one.

Since: S1

defstruct

U16x8

(defstruct ^copy U16x8 [])

a 16-byte vector of 8 uint16 lanes.

Lanes l0 .. l7; (U16x8 (as uint16 7) (as uint16 7) (as uint16 7) (as uint16 7) (as uint16 7) (as uint16 7) (as uint16 7) (as uint16 7)) builds one.

Since: S1

defstruct

U8x16

(defstruct ^copy U8x16 [])

a 16-byte vector of 16 uint8 lanes.

Lanes l0 .. l15; (U8x16 (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7) (as uint8 7)) builds one.

Since: S1

defstruct

M64x2

(defstruct ^copy M64x2 [l0 : int l1 : int])

a 16-byte mask of 2 int lanes, for the 2-lane vectors.

A comparison sets a lane to -1 where it held and 0 where it did not; -select and the mask operations take any nonzero lane as set. (M64x2 -1 -1) builds one with every lane set.

Since: S1

defstruct

M32x4

(defstruct ^copy M32x4 [l0 : int32 l1 : int32 l2 : int32 l3 : int32])

a 16-byte mask of 4 int32 lanes, for the 4-lane vectors.

A comparison sets a lane to -1 where it held and 0 where it did not; -select and the mask operations take any nonzero lane as set. (M32x4 (as int32 -1) (as int32 -1) (as int32 -1) (as int32 -1)) builds one with every lane set.

Since: S1

defstruct

M16x8

(defstruct ^copy M16x8 [])

a 16-byte mask of 8 int16 lanes, for the 8-lane vectors.

A comparison sets a lane to -1 where it held and 0 where it did not; -select and the mask operations take any nonzero lane as set. (M16x8 (as int16 -1) (as int16 -1) (as int16 -1) (as int16 -1) (as int16 -1) (as int16 -1) (as int16 -1) (as int16 -1)) builds one with every lane set.

Since: S1

defstruct

M8x16

(defstruct ^copy M8x16 [])

a 16-byte mask of 16 int8 lanes, for the 16-lane vectors.

A comparison sets a lane to -1 where it held and 0 where it did not; -select and the mask operations take any nonzero lane as set. (M8x16 (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1) (as int8 -1)) builds one with every lane set.

Since: S1

defn

f64x2-splat

(f64x2-splat [x : float])

every lane x.

xthe value

A F64x2.

(f64x2-splat 7.1)

Since: S1

defn

f64x2-lane

(f64x2-lane [v : F64x2 k : int])

lane k of v (0 is the lowest; out of range panics).

vthe vector
kthe lane, 0 to 1

A float.

(f64x2-lane (f64x2-splat 7.1) 0)   ; => 7.1

Since: S1

defn

f64x2-load

(f64x2-load [^borrow arr : F64Vec i : int])

lanes from arr[i] .. arr[i + 1] (out of bounds panics, once).

The array's element type is the vector's lane type.

arrthe array (borrowed)
ithe first element

A F64x2.

(let [a (f64vec-new 8 7.1)] (f64x2-load a 0))

Since: S1

defn

f64x2-store!

(f64x2-store! [^borrow arr : F64Vec i : int v : F64x2])

write v's lanes to arr[i] .. arr[i + 1] (out of bounds panics, once).

arrthe array written (borrowed)
ithe first element
vthe vector
(f64x2-store! a 0 (f64x2-splat 3.25))

Since: S1

defn

f64x2-load-unchecked

(f64x2-load-unchecked [^borrow arr : F64Vec i : int])

lanes from arr[i] .. arr[i + 1], NOT bounds-checked.

#fx{Unsafe}: for a loop that has checked its bounds once. It can not panic, so a call to it carries no panic check and no call site: in a tight loop the checked -load costs up to 3x (clang). The interpreter checks the index anyway.

arrthe array (borrowed)
ithe first element; the caller proves 0 <= i and i + 2 <= len

A F64x2.

(unsafe (f64x2-load-unchecked a 0))

Since: S1

defn

f64x2-store-unchecked!

(f64x2-store-unchecked! [^borrow arr : F64Vec i : int v : F64x2])

write v's lanes to arr[i] .. arr[i + 1], NOT bounds-checked.

#fx{Unsafe}, as -load-unchecked. Stores numbers: no TUR_REGION_NOTE.

arrthe array written (borrowed)
ithe first element; the caller proves 0 <= i and i + 2 <= len
vthe vector
(unsafe (f64x2-store-unchecked! a 0 (f64x2-splat 3.25)))

Since: S1

defn

f64x2-add

(f64x2-add [a : F64x2 b : F64x2])

lanewise a + b.

Integer lanes wrap. Floats: one IEEE add per lane, as the scalar +.

aa vector
ba vector

A F64x2.

(f64x2-add (f64x2-splat 7.1) (f64x2-splat 3.25))

Since: S1

defn

f64x2-sub

(f64x2-sub [a : F64x2 b : F64x2])

lanewise a - b.

Integer lanes wrap.

aa vector
ba vector

A F64x2.

(f64x2-sub (f64x2-splat 7.1) (f64x2-splat 3.25))

Since: S1

defn

f64x2-mul

(f64x2-mul [a : F64x2 b : F64x2])

lanewise a * b.

Integer lanes wrap: a U8x16 product is taken modulo 256, lane by lane -- widen first (u8x16-widen-lo / -hi) for the full product.

aa vector
ba vector

A F64x2.

(f64x2-mul (f64x2-splat 7.1) (f64x2-splat 3.25))

Since: S1

defn

f64x2-div

(f64x2-div [a : F64x2 b : F64x2])

lanewise a / b.

An integer lane divided by zero panics; MIN / -1 wraps to MIN.

aa vector
ba vector

A F64x2.

(f64x2-div (f64x2-splat 7.1) (f64x2-splat 3.25))

Since: S1

defn

f64x2-neg

(f64x2-neg [a : F64x2])

lanewise -a.

Integer lanes wrap.

aa vector

A F64x2.

(f64x2-neg (f64x2-splat 7.1))

Since: S1

defn

f64x2-min

(f64x2-min [a : F64x2 b : F64x2])

lanewise minimum: lane k is b[k] < a[k] ? b[k] : a[k].

aa vector
ba vector

A F64x2.

(f64x2-min (f64x2-splat 7.1) (f64x2-splat 3.25))

Since: S1

defn

f64x2-max

(f64x2-max [a : F64x2 b : F64x2])

lanewise maximum: lane k is b[k] > a[k] ? b[k] : a[k].

aa vector
ba vector

A F64x2.

(f64x2-max (f64x2-splat 7.1) (f64x2-splat 3.25))

Since: S1

defn

f64x2-sqrt

(f64x2-sqrt [a : F64x2])

lanewise square root.

aa vector

A F64x2.

(f64x2-sqrt (f64x2-splat 7.1))

Since: S1

defn

f64x2-abs

(f64x2-abs [a : F64x2])

lanewise absolute value.

aa vector

A F64x2.

(f64x2-abs (f64x2-splat -1.5))

Since: S1

defn

f64x2-hsum

(f64x2-hsum [a : F64x2])

the sum of the lanes.

Floats add in one fixed tree -- (0 + 1) for two lanes, ((0 + 1) + (2 + 3)) for four -- the same on every engine. Integer lanes are widened to int and the sum wraps modulo 2^64.

aa vector

A float.

(f64x2-hsum (f64x2-splat 3.25))

Since: S1

defn

f64x2-eq

(f64x2-eq [a : F64x2 b : F64x2])

lanewise a == b: -1 where it holds, 0 where not.

Floats compare as IEEE: a NaN lane is unequal to everything and never less or greater.

aa vector
ba vector

A M64x2.

(f64x2-eq (f64x2-splat 3.25) (f64x2-splat 7.1))

Since: S1

defn

f64x2-lt

(f64x2-lt [a : F64x2 b : F64x2])

lanewise a < b: -1 where it holds, 0 where not.

aa vector
ba vector

A M64x2.

(f64x2-lt (f64x2-splat 3.25) (f64x2-splat 7.1))

Since: S1

defn

f64x2-le

(f64x2-le [a : F64x2 b : F64x2])

lanewise a <= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M64x2.

(f64x2-le (f64x2-splat 3.25) (f64x2-splat 7.1))

Since: S1

defn

f64x2-gt

(f64x2-gt [a : F64x2 b : F64x2])

lanewise a > b: -1 where it holds, 0 where not.

aa vector
ba vector

A M64x2.

(f64x2-gt (f64x2-splat 3.25) (f64x2-splat 7.1))

Since: S1

defn

f64x2-ge

(f64x2-ge [a : F64x2 b : F64x2])

lanewise a >= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M64x2.

(f64x2-ge (f64x2-splat 3.25) (f64x2-splat 7.1))

Since: S1

defn

f64x2-select

(f64x2-select [m : M64x2 a : F64x2 b : F64x2])

lane k is a[k] where m's lane k is set (nonzero), else b[k].

Branch-free: both a and b are computed. Lanewise min of a and b is (P-select (P-lt a b) a b), as P-min is.

mthe mask, from a comparison
athe lanes taken where m is set
bthe lanes taken where it is not

A F64x2.

(f64x2-select (f64x2-lt (f64x2-splat 3.25) (f64x2-splat 7.1)) (f64x2-splat 3.25) (f64x2-splat 7.1))

Since: S1

defn

f64x2-shuffle

(f64x2-shuffle [v : F64x2 idx : I64x2])

lane k is v's lane idx[k] mod 2.

Constant indices compile to one shuffle instruction (gcc and clang); an index outside 0 to 1 wraps, so there is no out-of-range case.

vthe vector
idxwhich lane of v each result lane takes

A F64x2.

(f64x2-shuffle (f64x2-splat 7.1) (I64x2 1 0))   ; lanes reversed

Since: S1

defn

f64x2-narrow

(f64x2-narrow [lo : F64x2 hi : F64x2])

lo's lanes then hi's, each rounded to float32.

Rounds to nearest; a lane beyond float32's range becomes an infinity.

lolanes 0-1 of the result
hilanes 2-3

A F32x4.

(f64x2-narrow (f64x2-splat 7.1) (f64x2-splat 3.25))

Since: S1

definstance

Num[F64x2]

(definstance Num [F64x2])

lanewise arithmetic, so {a + b} works.

defn

f32x4-splat

(f32x4-splat [x : float32])

every lane x.

xthe value

A F32x4.

(f32x4-splat (as float32 7.1))

Since: S1

defn

f32x4-lane

(f32x4-lane [v : F32x4 k : int])

lane k of v (0 is the lowest; out of range panics).

vthe vector
kthe lane, 0 to 3

A float32.

(f32x4-lane (f32x4-splat (as float32 7.1)) 0)   ; => (as float32 7.1)

Since: S1

defn

f32x4-load

(f32x4-load [^borrow arr : F32Vec i : int])

lanes from arr[i] .. arr[i + 3] (out of bounds panics, once).

The array's element type is the vector's lane type.

arrthe array (borrowed)
ithe first element

A F32x4.

(let [a (f32vec-new 8 (as float32 7.1))] (f32x4-load a 0))

Since: S1

defn

f32x4-store!

(f32x4-store! [^borrow arr : F32Vec i : int v : F32x4])

write v's lanes to arr[i] .. arr[i + 3] (out of bounds panics, once).

arrthe array written (borrowed)
ithe first element
vthe vector
(f32x4-store! a 0 (f32x4-splat (as float32 3.25)))

Since: S1

defn

f32x4-load-unchecked

(f32x4-load-unchecked [^borrow arr : F32Vec i : int])

lanes from arr[i] .. arr[i + 3], NOT bounds-checked.

#fx{Unsafe}: for a loop that has checked its bounds once. It can not panic, so a call to it carries no panic check and no call site: in a tight loop the checked -load costs up to 3x (clang). The interpreter checks the index anyway.

arrthe array (borrowed)
ithe first element; the caller proves 0 <= i and i + 4 <= len

A F32x4.

(unsafe (f32x4-load-unchecked a 0))

Since: S1

defn

f32x4-store-unchecked!

(f32x4-store-unchecked! [^borrow arr : F32Vec i : int v : F32x4])

write v's lanes to arr[i] .. arr[i + 3], NOT bounds-checked.

#fx{Unsafe}, as -load-unchecked. Stores numbers: no TUR_REGION_NOTE.

arrthe array written (borrowed)
ithe first element; the caller proves 0 <= i and i + 4 <= len
vthe vector
(unsafe (f32x4-store-unchecked! a 0 (f32x4-splat (as float32 3.25))))

Since: S1

defn

f32x4-add

(f32x4-add [a : F32x4 b : F32x4])

lanewise a + b.

Integer lanes wrap. Floats: one IEEE add per lane, as the scalar +.

aa vector
ba vector

A F32x4.

(f32x4-add (f32x4-splat (as float32 7.1)) (f32x4-splat (as float32 3.25)))

Since: S1

defn

f32x4-sub

(f32x4-sub [a : F32x4 b : F32x4])

lanewise a - b.

Integer lanes wrap.

aa vector
ba vector

A F32x4.

(f32x4-sub (f32x4-splat (as float32 7.1)) (f32x4-splat (as float32 3.25)))

Since: S1

defn

f32x4-mul

(f32x4-mul [a : F32x4 b : F32x4])

lanewise a * b.

Integer lanes wrap: a U8x16 product is taken modulo 256, lane by lane -- widen first (u8x16-widen-lo / -hi) for the full product.

aa vector
ba vector

A F32x4.

(f32x4-mul (f32x4-splat (as float32 7.1)) (f32x4-splat (as float32 3.25)))

Since: S1

defn

f32x4-div

(f32x4-div [a : F32x4 b : F32x4])

lanewise a / b.

An integer lane divided by zero panics; MIN / -1 wraps to MIN.

aa vector
ba vector

A F32x4.

(f32x4-div (f32x4-splat (as float32 7.1)) (f32x4-splat (as float32 3.25)))

Since: S1

defn

f32x4-neg

(f32x4-neg [a : F32x4])

lanewise -a.

Integer lanes wrap.

aa vector

A F32x4.

(f32x4-neg (f32x4-splat (as float32 7.1)))

Since: S1

defn

f32x4-min

(f32x4-min [a : F32x4 b : F32x4])

lanewise minimum: lane k is b[k] < a[k] ? b[k] : a[k].

aa vector
ba vector

A F32x4.

(f32x4-min (f32x4-splat (as float32 7.1)) (f32x4-splat (as float32 3.25)))

Since: S1

defn

f32x4-max

(f32x4-max [a : F32x4 b : F32x4])

lanewise maximum: lane k is b[k] > a[k] ? b[k] : a[k].

aa vector
ba vector

A F32x4.

(f32x4-max (f32x4-splat (as float32 7.1)) (f32x4-splat (as float32 3.25)))

Since: S1

defn

f32x4-sqrt

(f32x4-sqrt [a : F32x4])

lanewise square root.

aa vector

A F32x4.

(f32x4-sqrt (f32x4-splat (as float32 7.1)))

Since: S1

defn

f32x4-abs

(f32x4-abs [a : F32x4])

lanewise absolute value.

aa vector

A F32x4.

(f32x4-abs (f32x4-splat (as float32 -1.5)))

Since: S1

defn

f32x4-hsum

(f32x4-hsum [a : F32x4])

the sum of the lanes.

Floats add in one fixed tree -- (0 + 1) for two lanes, ((0 + 1) + (2 + 3)) for four -- the same on every engine. Integer lanes are widened to int and the sum wraps modulo 2^64.

aa vector

A float32.

(f32x4-hsum (f32x4-splat (as float32 3.25)))

Since: S1

defn

f32x4-eq

(f32x4-eq [a : F32x4 b : F32x4])

lanewise a == b: -1 where it holds, 0 where not.

Floats compare as IEEE: a NaN lane is unequal to everything and never less or greater.

aa vector
ba vector

A M32x4.

(f32x4-eq (f32x4-splat (as float32 3.25)) (f32x4-splat (as float32 7.1)))

Since: S1

defn

f32x4-lt

(f32x4-lt [a : F32x4 b : F32x4])

lanewise a < b: -1 where it holds, 0 where not.

aa vector
ba vector

A M32x4.

(f32x4-lt (f32x4-splat (as float32 3.25)) (f32x4-splat (as float32 7.1)))

Since: S1

defn

f32x4-le

(f32x4-le [a : F32x4 b : F32x4])

lanewise a <= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M32x4.

(f32x4-le (f32x4-splat (as float32 3.25)) (f32x4-splat (as float32 7.1)))

Since: S1

defn

f32x4-gt

(f32x4-gt [a : F32x4 b : F32x4])

lanewise a > b: -1 where it holds, 0 where not.

aa vector
ba vector

A M32x4.

(f32x4-gt (f32x4-splat (as float32 3.25)) (f32x4-splat (as float32 7.1)))

Since: S1

defn

f32x4-ge

(f32x4-ge [a : F32x4 b : F32x4])

lanewise a >= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M32x4.

(f32x4-ge (f32x4-splat (as float32 3.25)) (f32x4-splat (as float32 7.1)))

Since: S1

defn

f32x4-select

(f32x4-select [m : M32x4 a : F32x4 b : F32x4])

lane k is a[k] where m's lane k is set (nonzero), else b[k].

Branch-free: both a and b are computed. Lanewise min of a and b is (P-select (P-lt a b) a b), as P-min is.

mthe mask, from a comparison
athe lanes taken where m is set
bthe lanes taken where it is not

A F32x4.

(f32x4-select (f32x4-lt (f32x4-splat (as float32 3.25)) (f32x4-splat (as float32 7.1))) (f32x4-splat (as float32 3.25)) (f32x4-splat (as float32 7.1)))

Since: S1

defn

f32x4-shuffle

(f32x4-shuffle [v : F32x4 idx : I32x4])

lane k is v's lane idx[k] mod 4.

Constant indices compile to one shuffle instruction (gcc and clang); an index outside 0 to 3 wraps, so there is no out-of-range case.

vthe vector
idxwhich lane of v each result lane takes

A F32x4.

(f32x4-shuffle (f32x4-splat (as float32 7.1)) (I32x4 (as int32 3) (as int32 2) (as int32 1) (as int32 0)))   ; lanes reversed

Since: S1

defn

f32x4->i32x4

(f32x4->i32x4 [a : F32x4])

each lane truncated toward zero to int32, saturating.

Every lane is defined: NaN gives 0, a lane at or above 2^31 gives 2147483647, one below -2^31 gives -2147483648. (A C cast is undefined there, and cvttps2dq alone gives -2147483648 for all three.)

athe vector

A I32x4.

(f32x4->i32x4 (f32x4-splat (as float32 7.1)))   ; => lanes of 7

Since: S1

defn

f32x4-widen-lo

(f32x4-widen-lo [a : F32x4])

lanes 0 and 1 converted to float (exact).

athe vector

A F64x2.

(f32x4-widen-lo (f32x4-splat (as float32 7.1)))

Since: S1

defn

f32x4-widen-hi

(f32x4-widen-hi [a : F32x4])

lanes 2 and 3 converted to float (exact).

athe vector

A F64x2.

(f32x4-widen-hi (f32x4-splat (as float32 7.1)))

Since: S1

definstance

Num[F32x4]

(definstance Num [F32x4])

lanewise arithmetic, so {a + b} works.

defn

i64x2-splat

(i64x2-splat [x : int])

every lane x.

xthe value

A I64x2.

(i64x2-splat 7)

Since: S1

defn

i64x2-lane

(i64x2-lane [v : I64x2 k : int])

lane k of v (0 is the lowest; out of range panics).

vthe vector
kthe lane, 0 to 1

A int.

(i64x2-lane (i64x2-splat 7) 0)   ; => 7

Since: S1

defn

i64x2-load

(i64x2-load [^borrow arr : I64Vec i : int])

lanes from arr[i] .. arr[i + 1] (out of bounds panics, once).

The array's element type is the vector's lane type.

arrthe array (borrowed)
ithe first element

A I64x2.

(let [a (i64vec-new 8 7)] (i64x2-load a 0))

Since: S1

defn

i64x2-store!

(i64x2-store! [^borrow arr : I64Vec i : int v : I64x2])

write v's lanes to arr[i] .. arr[i + 1] (out of bounds panics, once).

arrthe array written (borrowed)
ithe first element
vthe vector
(i64x2-store! a 0 (i64x2-splat 3))

Since: S1

defn

i64x2-load-unchecked

(i64x2-load-unchecked [^borrow arr : I64Vec i : int])

lanes from arr[i] .. arr[i + 1], NOT bounds-checked.

#fx{Unsafe}: for a loop that has checked its bounds once. It can not panic, so a call to it carries no panic check and no call site: in a tight loop the checked -load costs up to 3x (clang). The interpreter checks the index anyway.

arrthe array (borrowed)
ithe first element; the caller proves 0 <= i and i + 2 <= len

A I64x2.

(unsafe (i64x2-load-unchecked a 0))

Since: S1

defn

i64x2-store-unchecked!

(i64x2-store-unchecked! [^borrow arr : I64Vec i : int v : I64x2])

write v's lanes to arr[i] .. arr[i + 1], NOT bounds-checked.

#fx{Unsafe}, as -load-unchecked. Stores numbers: no TUR_REGION_NOTE.

arrthe array written (borrowed)
ithe first element; the caller proves 0 <= i and i + 2 <= len
vthe vector
(unsafe (i64x2-store-unchecked! a 0 (i64x2-splat 3)))

Since: S1

defn

i64x2-add

(i64x2-add [a : I64x2 b : I64x2])

lanewise a + b.

Integer lanes wrap. Floats: one IEEE add per lane, as the scalar +.

aa vector
ba vector

A I64x2.

(i64x2-add (i64x2-splat 7) (i64x2-splat 3))

Since: S1

defn

i64x2-sub

(i64x2-sub [a : I64x2 b : I64x2])

lanewise a - b.

Integer lanes wrap.

aa vector
ba vector

A I64x2.

(i64x2-sub (i64x2-splat 7) (i64x2-splat 3))

Since: S1

defn

i64x2-mul

(i64x2-mul [a : I64x2 b : I64x2])

lanewise a * b.

Integer lanes wrap: a U8x16 product is taken modulo 256, lane by lane -- widen first (u8x16-widen-lo / -hi) for the full product.

aa vector
ba vector

A I64x2.

(i64x2-mul (i64x2-splat 7) (i64x2-splat 3))

Since: S1

defn

i64x2-div

(i64x2-div [a : I64x2 b : I64x2])

lanewise a / b.

An integer lane divided by zero panics; MIN / -1 wraps to MIN.

aa vector
ba vector

A I64x2.

(i64x2-div (i64x2-splat 7) (i64x2-splat 3))

Since: S1

defn

i64x2-neg

(i64x2-neg [a : I64x2])

lanewise -a.

Integer lanes wrap.

aa vector

A I64x2.

(i64x2-neg (i64x2-splat 7))

Since: S1

defn

i64x2-min

(i64x2-min [a : I64x2 b : I64x2])

lanewise minimum: lane k is b[k] < a[k] ? b[k] : a[k].

aa vector
ba vector

A I64x2.

(i64x2-min (i64x2-splat 7) (i64x2-splat 3))

Since: S1

defn

i64x2-max

(i64x2-max [a : I64x2 b : I64x2])

lanewise maximum: lane k is b[k] > a[k] ? b[k] : a[k].

aa vector
ba vector

A I64x2.

(i64x2-max (i64x2-splat 7) (i64x2-splat 3))

Since: S1

defn

i64x2-hsum

(i64x2-hsum [a : I64x2])

the sum of the lanes.

Floats add in one fixed tree -- (0 + 1) for two lanes, ((0 + 1) + (2 + 3)) for four -- the same on every engine. Integer lanes are widened to int and the sum wraps modulo 2^64.

aa vector

A int.

(i64x2-hsum (i64x2-splat 3))

Since: S1

defn

i64x2-eq

(i64x2-eq [a : I64x2 b : I64x2])

lanewise a == b: -1 where it holds, 0 where not.

Floats compare as IEEE: a NaN lane is unequal to everything and never less or greater.

aa vector
ba vector

A M64x2.

(i64x2-eq (i64x2-splat 3) (i64x2-splat 7))

Since: S1

defn

i64x2-lt

(i64x2-lt [a : I64x2 b : I64x2])

lanewise a < b: -1 where it holds, 0 where not.

aa vector
ba vector

A M64x2.

(i64x2-lt (i64x2-splat 3) (i64x2-splat 7))

Since: S1

defn

i64x2-le

(i64x2-le [a : I64x2 b : I64x2])

lanewise a <= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M64x2.

(i64x2-le (i64x2-splat 3) (i64x2-splat 7))

Since: S1

defn

i64x2-gt

(i64x2-gt [a : I64x2 b : I64x2])

lanewise a > b: -1 where it holds, 0 where not.

aa vector
ba vector

A M64x2.

(i64x2-gt (i64x2-splat 3) (i64x2-splat 7))

Since: S1

defn

i64x2-ge

(i64x2-ge [a : I64x2 b : I64x2])

lanewise a >= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M64x2.

(i64x2-ge (i64x2-splat 3) (i64x2-splat 7))

Since: S1

defn

i64x2-select

(i64x2-select [m : M64x2 a : I64x2 b : I64x2])

lane k is a[k] where m's lane k is set (nonzero), else b[k].

Branch-free: both a and b are computed. Lanewise min of a and b is (P-select (P-lt a b) a b), as P-min is.

mthe mask, from a comparison
athe lanes taken where m is set
bthe lanes taken where it is not

A I64x2.

(i64x2-select (i64x2-lt (i64x2-splat 3) (i64x2-splat 7)) (i64x2-splat 3) (i64x2-splat 7))

Since: S1

defn

i64x2-shuffle

(i64x2-shuffle [v : I64x2 idx : I64x2])

lane k is v's lane idx[k] mod 2.

Constant indices compile to one shuffle instruction (gcc and clang); an index outside 0 to 1 wraps, so there is no out-of-range case.

vthe vector
idxwhich lane of v each result lane takes

A I64x2.

(i64x2-shuffle (i64x2-splat 7) (I64x2 1 0))   ; lanes reversed

Since: S1

definstance

Num[I64x2]

(definstance Num [I64x2])

lanewise arithmetic, so {a + b} works.

defn

i32x4-splat

(i32x4-splat [x : int32])

every lane x.

xthe value

A I32x4.

(i32x4-splat (as int32 7))

Since: S1

defn

i32x4-lane

(i32x4-lane [v : I32x4 k : int])

lane k of v (0 is the lowest; out of range panics).

vthe vector
kthe lane, 0 to 3

A int32.

(i32x4-lane (i32x4-splat (as int32 7)) 0)   ; => (as int32 7)

Since: S1

defn

i32x4-load

(i32x4-load [^borrow arr : I32Vec i : int])

lanes from arr[i] .. arr[i + 3] (out of bounds panics, once).

The array's element type is the vector's lane type.

arrthe array (borrowed)
ithe first element

A I32x4.

(let [a (i32vec-new 8 (as int32 7))] (i32x4-load a 0))

Since: S1

defn

i32x4-store!

(i32x4-store! [^borrow arr : I32Vec i : int v : I32x4])

write v's lanes to arr[i] .. arr[i + 3] (out of bounds panics, once).

arrthe array written (borrowed)
ithe first element
vthe vector
(i32x4-store! a 0 (i32x4-splat (as int32 3)))

Since: S1

defn

i32x4-load-unchecked

(i32x4-load-unchecked [^borrow arr : I32Vec i : int])

lanes from arr[i] .. arr[i + 3], NOT bounds-checked.

#fx{Unsafe}: for a loop that has checked its bounds once. It can not panic, so a call to it carries no panic check and no call site: in a tight loop the checked -load costs up to 3x (clang). The interpreter checks the index anyway.

arrthe array (borrowed)
ithe first element; the caller proves 0 <= i and i + 4 <= len

A I32x4.

(unsafe (i32x4-load-unchecked a 0))

Since: S1

defn

i32x4-store-unchecked!

(i32x4-store-unchecked! [^borrow arr : I32Vec i : int v : I32x4])

write v's lanes to arr[i] .. arr[i + 3], NOT bounds-checked.

#fx{Unsafe}, as -load-unchecked. Stores numbers: no TUR_REGION_NOTE.

arrthe array written (borrowed)
ithe first element; the caller proves 0 <= i and i + 4 <= len
vthe vector
(unsafe (i32x4-store-unchecked! a 0 (i32x4-splat (as int32 3))))

Since: S1

defn

i32x4-add

(i32x4-add [a : I32x4 b : I32x4])

lanewise a + b.

Integer lanes wrap. Floats: one IEEE add per lane, as the scalar +.

aa vector
ba vector

A I32x4.

(i32x4-add (i32x4-splat (as int32 7)) (i32x4-splat (as int32 3)))

Since: S1

defn

i32x4-sub

(i32x4-sub [a : I32x4 b : I32x4])

lanewise a - b.

Integer lanes wrap.

aa vector
ba vector

A I32x4.

(i32x4-sub (i32x4-splat (as int32 7)) (i32x4-splat (as int32 3)))

Since: S1

defn

i32x4-mul

(i32x4-mul [a : I32x4 b : I32x4])

lanewise a * b.

Integer lanes wrap: a U8x16 product is taken modulo 256, lane by lane -- widen first (u8x16-widen-lo / -hi) for the full product.

aa vector
ba vector

A I32x4.

(i32x4-mul (i32x4-splat (as int32 7)) (i32x4-splat (as int32 3)))

Since: S1

defn

i32x4-div

(i32x4-div [a : I32x4 b : I32x4])

lanewise a / b.

An integer lane divided by zero panics; MIN / -1 wraps to MIN.

aa vector
ba vector

A I32x4.

(i32x4-div (i32x4-splat (as int32 7)) (i32x4-splat (as int32 3)))

Since: S1

defn

i32x4-neg

(i32x4-neg [a : I32x4])

lanewise -a.

Integer lanes wrap.

aa vector

A I32x4.

(i32x4-neg (i32x4-splat (as int32 7)))

Since: S1

defn

i32x4-min

(i32x4-min [a : I32x4 b : I32x4])

lanewise minimum: lane k is b[k] < a[k] ? b[k] : a[k].

aa vector
ba vector

A I32x4.

(i32x4-min (i32x4-splat (as int32 7)) (i32x4-splat (as int32 3)))

Since: S1

defn

i32x4-max

(i32x4-max [a : I32x4 b : I32x4])

lanewise maximum: lane k is b[k] > a[k] ? b[k] : a[k].

aa vector
ba vector

A I32x4.

(i32x4-max (i32x4-splat (as int32 7)) (i32x4-splat (as int32 3)))

Since: S1

defn

i32x4-hsum

(i32x4-hsum [a : I32x4])

the sum of the lanes.

Floats add in one fixed tree -- (0 + 1) for two lanes, ((0 + 1) + (2 + 3)) for four -- the same on every engine. Integer lanes are widened to int and the sum wraps modulo 2^64.

aa vector

A int.

(i32x4-hsum (i32x4-splat (as int32 3)))

Since: S1

defn

i32x4-eq

(i32x4-eq [a : I32x4 b : I32x4])

lanewise a == b: -1 where it holds, 0 where not.

Floats compare as IEEE: a NaN lane is unequal to everything and never less or greater.

aa vector
ba vector

A M32x4.

(i32x4-eq (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7)))

Since: S1

defn

i32x4-lt

(i32x4-lt [a : I32x4 b : I32x4])

lanewise a < b: -1 where it holds, 0 where not.

aa vector
ba vector

A M32x4.

(i32x4-lt (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7)))

Since: S1

defn

i32x4-le

(i32x4-le [a : I32x4 b : I32x4])

lanewise a <= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M32x4.

(i32x4-le (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7)))

Since: S1

defn

i32x4-gt

(i32x4-gt [a : I32x4 b : I32x4])

lanewise a > b: -1 where it holds, 0 where not.

aa vector
ba vector

A M32x4.

(i32x4-gt (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7)))

Since: S1

defn

i32x4-ge

(i32x4-ge [a : I32x4 b : I32x4])

lanewise a >= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M32x4.

(i32x4-ge (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7)))

Since: S1

defn

i32x4-select

(i32x4-select [m : M32x4 a : I32x4 b : I32x4])

lane k is a[k] where m's lane k is set (nonzero), else b[k].

Branch-free: both a and b are computed. Lanewise min of a and b is (P-select (P-lt a b) a b), as P-min is.

mthe mask, from a comparison
athe lanes taken where m is set
bthe lanes taken where it is not

A I32x4.

(i32x4-select (i32x4-lt (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7))) (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7)))

Since: S1

defn

i32x4-shuffle

(i32x4-shuffle [v : I32x4 idx : I32x4])

lane k is v's lane idx[k] mod 4.

Constant indices compile to one shuffle instruction (gcc and clang); an index outside 0 to 3 wraps, so there is no out-of-range case.

vthe vector
idxwhich lane of v each result lane takes

A I32x4.

(i32x4-shuffle (i32x4-splat (as int32 7)) (I32x4 (as int32 3) (as int32 2) (as int32 1) (as int32 0)))   ; lanes reversed

Since: S1

defn

i32x4->f32x4

(i32x4->f32x4 [a : I32x4])

each lane converted to float32, rounding to nearest (cvtdq2ps).

athe vector

A F32x4.

(i32x4->f32x4 (i32x4-splat (as int32 7)))

Since: S1

definstance

Num[I32x4]

(definstance Num [I32x4])

lanewise arithmetic, so {a + b} works.

defn

u16x8-splat

(u16x8-splat [x : uint16])

every lane x.

xthe value

A U16x8.

(u16x8-splat (as uint16 7))

Since: S1

defn

u16x8-lane

(u16x8-lane [v : U16x8 k : int])

lane k of v (0 is the lowest; out of range panics).

vthe vector
kthe lane, 0 to 7

A uint16.

(u16x8-lane (u16x8-splat (as uint16 7)) 0)   ; => (as uint16 7)

Since: S1

defn

u16x8-add

(u16x8-add [a : U16x8 b : U16x8])

lanewise a + b.

Integer lanes wrap. Floats: one IEEE add per lane, as the scalar +.

aa vector
ba vector

A U16x8.

(u16x8-add (u16x8-splat (as uint16 7)) (u16x8-splat (as uint16 3)))

Since: S1

defn

u16x8-sub

(u16x8-sub [a : U16x8 b : U16x8])

lanewise a - b.

Integer lanes wrap.

aa vector
ba vector

A U16x8.

(u16x8-sub (u16x8-splat (as uint16 7)) (u16x8-splat (as uint16 3)))

Since: S1

defn

u16x8-mul

(u16x8-mul [a : U16x8 b : U16x8])

lanewise a * b.

Integer lanes wrap: a U8x16 product is taken modulo 256, lane by lane -- widen first (u8x16-widen-lo / -hi) for the full product.

aa vector
ba vector

A U16x8.

(u16x8-mul (u16x8-splat (as uint16 7)) (u16x8-splat (as uint16 3)))

Since: S1

defn

u16x8-div

(u16x8-div [a : U16x8 b : U16x8])

lanewise a / b.

An integer lane divided by zero panics; MIN / -1 wraps to MIN.

aa vector
ba vector

A U16x8.

(u16x8-div (u16x8-splat (as uint16 7)) (u16x8-splat (as uint16 3)))

Since: S1

defn

u16x8-neg

(u16x8-neg [a : U16x8])

lanewise -a.

Integer lanes wrap.

aa vector

A U16x8.

(u16x8-neg (u16x8-splat (as uint16 7)))

Since: S1

defn

u16x8-min

(u16x8-min [a : U16x8 b : U16x8])

lanewise minimum: lane k is b[k] < a[k] ? b[k] : a[k].

aa vector
ba vector

A U16x8.

(u16x8-min (u16x8-splat (as uint16 7)) (u16x8-splat (as uint16 3)))

Since: S1

defn

u16x8-max

(u16x8-max [a : U16x8 b : U16x8])

lanewise maximum: lane k is b[k] > a[k] ? b[k] : a[k].

aa vector
ba vector

A U16x8.

(u16x8-max (u16x8-splat (as uint16 7)) (u16x8-splat (as uint16 3)))

Since: S1

defn

u16x8-hsum

(u16x8-hsum [a : U16x8])

the sum of the lanes.

Floats add in one fixed tree -- (0 + 1) for two lanes, ((0 + 1) + (2 + 3)) for four -- the same on every engine. Integer lanes are widened to int and the sum wraps modulo 2^64.

aa vector

A int.

(u16x8-hsum (u16x8-splat (as uint16 3)))

Since: S1

defn

u16x8-narrow

(u16x8-narrow [lo : U16x8 hi : U16x8])

lo's lanes then hi's, each truncated to eight bits.

lolanes 0-7 of the result
hilanes 8-15

A U8x16.

(u16x8-narrow (u16x8-splat (as uint16 7)) (u16x8-splat (as uint16 3)))

Since: S1

defn

u16x8-shr

(u16x8-shr [v : U16x8 n : int])

every lane shifted right n bits, zero-filled (n outside 0 to 15 gives zero lanes).

vthe vector
nthe shift count

A U16x8.

(u16x8-shr (u16x8-splat (as uint16 65535)) 8)

Since: S1

defn

u16x8-eq

(u16x8-eq [a : U16x8 b : U16x8])

lanewise a == b: -1 where it holds, 0 where not.

Floats compare as IEEE: a NaN lane is unequal to everything and never less or greater.

aa vector
ba vector

A M16x8.

(u16x8-eq (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7)))

Since: S1

defn

u16x8-lt

(u16x8-lt [a : U16x8 b : U16x8])

lanewise a < b: -1 where it holds, 0 where not.

aa vector
ba vector

A M16x8.

(u16x8-lt (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7)))

Since: S1

defn

u16x8-le

(u16x8-le [a : U16x8 b : U16x8])

lanewise a <= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M16x8.

(u16x8-le (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7)))

Since: S1

defn

u16x8-gt

(u16x8-gt [a : U16x8 b : U16x8])

lanewise a > b: -1 where it holds, 0 where not.

aa vector
ba vector

A M16x8.

(u16x8-gt (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7)))

Since: S1

defn

u16x8-ge

(u16x8-ge [a : U16x8 b : U16x8])

lanewise a >= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M16x8.

(u16x8-ge (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7)))

Since: S1

defn

u16x8-select

(u16x8-select [m : M16x8 a : U16x8 b : U16x8])

lane k is a[k] where m's lane k is set (nonzero), else b[k].

Branch-free: both a and b are computed. Lanewise min of a and b is (P-select (P-lt a b) a b), as P-min is.

mthe mask, from a comparison
athe lanes taken where m is set
bthe lanes taken where it is not

A U16x8.

(u16x8-select (u16x8-lt (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7))) (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7)))

Since: S1

defn

u16x8-shuffle

(u16x8-shuffle [v : U16x8 idx : U16x8])

lane k is v's lane idx[k] mod 8.

Constant indices compile to one shuffle instruction (gcc and clang); an index outside 0 to 7 wraps, so there is no out-of-range case.

vthe vector
idxwhich lane of v each result lane takes

A U16x8.

(u16x8-shuffle (u16x8-splat (as uint16 7)) (U16x8 (as uint16 7) (as uint16 6) (as uint16 5) (as uint16 4) (as uint16 3) (as uint16 2) (as uint16 1) (as uint16 0)))   ; lanes reversed

Since: S1

definstance

Num[U16x8]

(definstance Num [U16x8])

lanewise arithmetic, so {a + b} works.

defn

u8x16-splat

(u8x16-splat [x : uint8])

every lane x.

xthe value

A U8x16.

(u8x16-splat (as uint8 7))

Since: S1

defn

u8x16-lane

(u8x16-lane [v : U8x16 k : int])

lane k of v (0 is the lowest; out of range panics).

vthe vector
kthe lane, 0 to 15

A uint8.

(u8x16-lane (u8x16-splat (as uint8 7)) 0)   ; => (as uint8 7)

Since: S1

defn

u8x16-load

(u8x16-load [^borrow arr : U8Vec i : int])

lanes from arr[i] .. arr[i + 15] (out of bounds panics, once).

The array's element type is the vector's lane type.

arrthe array (borrowed)
ithe first element

A U8x16.

(let [a (u8vec-new 8 (as uint8 7))] (u8x16-load a 0))

Since: S1

defn

u8x16-store!

(u8x16-store! [^borrow arr : U8Vec i : int v : U8x16])

write v's lanes to arr[i] .. arr[i + 15] (out of bounds panics, once).

arrthe array written (borrowed)
ithe first element
vthe vector
(u8x16-store! a 0 (u8x16-splat (as uint8 3)))

Since: S1

defn

u8x16-load-unchecked

(u8x16-load-unchecked [^borrow arr : U8Vec i : int])

lanes from arr[i] .. arr[i + 15], NOT bounds-checked.

#fx{Unsafe}: for a loop that has checked its bounds once. It can not panic, so a call to it carries no panic check and no call site: in a tight loop the checked -load costs up to 3x (clang). The interpreter checks the index anyway.

arrthe array (borrowed)
ithe first element; the caller proves 0 <= i and i + 16 <= len

A U8x16.

(unsafe (u8x16-load-unchecked a 0))

Since: S1

defn

u8x16-store-unchecked!

(u8x16-store-unchecked! [^borrow arr : U8Vec i : int v : U8x16])

write v's lanes to arr[i] .. arr[i + 15], NOT bounds-checked.

#fx{Unsafe}, as -load-unchecked. Stores numbers: no TUR_REGION_NOTE.

arrthe array written (borrowed)
ithe first element; the caller proves 0 <= i and i + 16 <= len
vthe vector
(unsafe (u8x16-store-unchecked! a 0 (u8x16-splat (as uint8 3))))

Since: S1

defn

u8x16-add

(u8x16-add [a : U8x16 b : U8x16])

lanewise a + b.

Integer lanes wrap. Floats: one IEEE add per lane, as the scalar +.

aa vector
ba vector

A U8x16.

(u8x16-add (u8x16-splat (as uint8 7)) (u8x16-splat (as uint8 3)))

Since: S1

defn

u8x16-sub

(u8x16-sub [a : U8x16 b : U8x16])

lanewise a - b.

Integer lanes wrap.

aa vector
ba vector

A U8x16.

(u8x16-sub (u8x16-splat (as uint8 7)) (u8x16-splat (as uint8 3)))

Since: S1

defn

u8x16-mul

(u8x16-mul [a : U8x16 b : U8x16])

lanewise a * b.

Integer lanes wrap: a U8x16 product is taken modulo 256, lane by lane -- widen first (u8x16-widen-lo / -hi) for the full product.

aa vector
ba vector

A U8x16.

(u8x16-mul (u8x16-splat (as uint8 7)) (u8x16-splat (as uint8 3)))

Since: S1

defn

u8x16-div

(u8x16-div [a : U8x16 b : U8x16])

lanewise a / b.

An integer lane divided by zero panics; MIN / -1 wraps to MIN.

aa vector
ba vector

A U8x16.

(u8x16-div (u8x16-splat (as uint8 7)) (u8x16-splat (as uint8 3)))

Since: S1

defn

u8x16-neg

(u8x16-neg [a : U8x16])

lanewise -a.

Integer lanes wrap.

aa vector

A U8x16.

(u8x16-neg (u8x16-splat (as uint8 7)))

Since: S1

defn

u8x16-min

(u8x16-min [a : U8x16 b : U8x16])

lanewise minimum: lane k is b[k] < a[k] ? b[k] : a[k].

aa vector
ba vector

A U8x16.

(u8x16-min (u8x16-splat (as uint8 7)) (u8x16-splat (as uint8 3)))

Since: S1

defn

u8x16-max

(u8x16-max [a : U8x16 b : U8x16])

lanewise maximum: lane k is b[k] > a[k] ? b[k] : a[k].

aa vector
ba vector

A U8x16.

(u8x16-max (u8x16-splat (as uint8 7)) (u8x16-splat (as uint8 3)))

Since: S1

defn

u8x16-hsum

(u8x16-hsum [a : U8x16])

the sum of the lanes.

Floats add in one fixed tree -- (0 + 1) for two lanes, ((0 + 1) + (2 + 3)) for four -- the same on every engine. Integer lanes are widened to int and the sum wraps modulo 2^64.

aa vector

A int.

(u8x16-hsum (u8x16-splat (as uint8 3)))

Since: S1

defn

u8x16-widen-lo

(u8x16-widen-lo [a : U8x16])

lanes 0-7 widened to sixteen bits.

aa byte vector

A U16x8.

(u8x16-widen-lo (u8x16-splat (as uint8 255)))

Since: S1

defn

u8x16-widen-hi

(u8x16-widen-hi [a : U8x16])

lanes 8-15 widened to sixteen bits.

aa byte vector

A U16x8.

(u8x16-widen-hi (u8x16-splat (as uint8 255)))

Since: S1

defn

u8x16-eq

(u8x16-eq [a : U8x16 b : U8x16])

lanewise a == b: -1 where it holds, 0 where not.

Floats compare as IEEE: a NaN lane is unequal to everything and never less or greater.

aa vector
ba vector

A M8x16.

(u8x16-eq (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7)))

Since: S1

defn

u8x16-lt

(u8x16-lt [a : U8x16 b : U8x16])

lanewise a < b: -1 where it holds, 0 where not.

aa vector
ba vector

A M8x16.

(u8x16-lt (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7)))

Since: S1

defn

u8x16-le

(u8x16-le [a : U8x16 b : U8x16])

lanewise a <= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M8x16.

(u8x16-le (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7)))

Since: S1

defn

u8x16-gt

(u8x16-gt [a : U8x16 b : U8x16])

lanewise a > b: -1 where it holds, 0 where not.

aa vector
ba vector

A M8x16.

(u8x16-gt (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7)))

Since: S1

defn

u8x16-ge

(u8x16-ge [a : U8x16 b : U8x16])

lanewise a >= b: -1 where it holds, 0 where not.

aa vector
ba vector

A M8x16.

(u8x16-ge (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7)))

Since: S1

defn

u8x16-select

(u8x16-select [m : M8x16 a : U8x16 b : U8x16])

lane k is a[k] where m's lane k is set (nonzero), else b[k].

Branch-free: both a and b are computed. Lanewise min of a and b is (P-select (P-lt a b) a b), as P-min is.

mthe mask, from a comparison
athe lanes taken where m is set
bthe lanes taken where it is not

A U8x16.

(u8x16-select (u8x16-lt (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7))) (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7)))

Since: S1

defn

u8x16-shuffle

(u8x16-shuffle [v : U8x16 idx : U8x16])

lane k is v's lane idx[k] mod 16.

Constant indices compile to one shuffle instruction (gcc and clang); an index outside 0 to 15 wraps, so there is no out-of-range case.

vthe vector
idxwhich lane of v each result lane takes

A U8x16.

(u8x16-shuffle (u8x16-splat (as uint8 7)) (U8x16 (as uint8 15) (as uint8 14) (as uint8 13) (as uint8 12) (as uint8 11) (as uint8 10) (as uint8 9) (as uint8 8) (as uint8 7) (as uint8 6) (as uint8 5) (as uint8 4) (as uint8 3) (as uint8 2) (as uint8 1) (as uint8 0)))   ; lanes reversed

Since: S1

definstance

Num[U8x16]

(definstance Num [U8x16])

lanewise arithmetic, so {a + b} works.

defn

m64x2-and

(m64x2-and [a : M64x2 b : M64x2])

lane k is set where both a's and b's are.

aa mask
ba mask

A M64x2.

(m64x2-and (f64x2-lt (f64x2-splat 3.25) (f64x2-splat 7.1)) (f64x2-lt (f64x2-splat 3.25) (f64x2-splat 7.1)))

Since: S1

defn

m64x2-or

(m64x2-or [a : M64x2 b : M64x2])

lane k is set where a's or b's is.

aa mask
ba mask

A M64x2.

(m64x2-or (f64x2-lt (f64x2-splat 3.25) (f64x2-splat 7.1)) (f64x2-lt (f64x2-splat 3.25) (f64x2-splat 7.1)))

Since: S1

defn

m64x2-not

(m64x2-not [a : M64x2])

lane k is set where a's is not.

aa mask

A M64x2.

(m64x2-not (f64x2-lt (f64x2-splat 3.25) (f64x2-splat 7.1)))

Since: S1

defn

m64x2-any

(m64x2-any [a : M64x2])

true when some lane of a is set.

aa mask

A bool.

(m64x2-any (f64x2-lt (f64x2-splat 3.25) (f64x2-splat 7.1)))   ; => true

Since: S1

defn

m64x2-all

(m64x2-all [a : M64x2])

true when every lane of a is set.

aa mask

A bool.

(m64x2-all (f64x2-lt (f64x2-splat 3.25) (f64x2-splat 7.1)))   ; => true

Since: S1

defn

m32x4-and

(m32x4-and [a : M32x4 b : M32x4])

lane k is set where both a's and b's are.

aa mask
ba mask

A M32x4.

(m32x4-and (i32x4-lt (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7))) (i32x4-lt (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7))))

Since: S1

defn

m32x4-or

(m32x4-or [a : M32x4 b : M32x4])

lane k is set where a's or b's is.

aa mask
ba mask

A M32x4.

(m32x4-or (i32x4-lt (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7))) (i32x4-lt (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7))))

Since: S1

defn

m32x4-not

(m32x4-not [a : M32x4])

lane k is set where a's is not.

aa mask

A M32x4.

(m32x4-not (i32x4-lt (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7))))

Since: S1

defn

m32x4-any

(m32x4-any [a : M32x4])

true when some lane of a is set.

aa mask

A bool.

(m32x4-any (i32x4-lt (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7))))   ; => true

Since: S1

defn

m32x4-all

(m32x4-all [a : M32x4])

true when every lane of a is set.

aa mask

A bool.

(m32x4-all (i32x4-lt (i32x4-splat (as int32 3)) (i32x4-splat (as int32 7))))   ; => true

Since: S1

defn

m16x8-and

(m16x8-and [a : M16x8 b : M16x8])

lane k is set where both a's and b's are.

aa mask
ba mask

A M16x8.

(m16x8-and (u16x8-lt (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7))) (u16x8-lt (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7))))

Since: S1

defn

m16x8-or

(m16x8-or [a : M16x8 b : M16x8])

lane k is set where a's or b's is.

aa mask
ba mask

A M16x8.

(m16x8-or (u16x8-lt (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7))) (u16x8-lt (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7))))

Since: S1

defn

m16x8-not

(m16x8-not [a : M16x8])

lane k is set where a's is not.

aa mask

A M16x8.

(m16x8-not (u16x8-lt (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7))))

Since: S1

defn

m16x8-any

(m16x8-any [a : M16x8])

true when some lane of a is set.

aa mask

A bool.

(m16x8-any (u16x8-lt (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7))))   ; => true

Since: S1

defn

m16x8-all

(m16x8-all [a : M16x8])

true when every lane of a is set.

aa mask

A bool.

(m16x8-all (u16x8-lt (u16x8-splat (as uint16 3)) (u16x8-splat (as uint16 7))))   ; => true

Since: S1

defn

m8x16-and

(m8x16-and [a : M8x16 b : M8x16])

lane k is set where both a's and b's are.

aa mask
ba mask

A M8x16.

(m8x16-and (u8x16-lt (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7))) (u8x16-lt (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7))))

Since: S1

defn

m8x16-or

(m8x16-or [a : M8x16 b : M8x16])

lane k is set where a's or b's is.

aa mask
ba mask

A M8x16.

(m8x16-or (u8x16-lt (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7))) (u8x16-lt (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7))))

Since: S1

defn

m8x16-not

(m8x16-not [a : M8x16])

lane k is set where a's is not.

aa mask

A M8x16.

(m8x16-not (u8x16-lt (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7))))

Since: S1

defn

m8x16-any

(m8x16-any [a : M8x16])

true when some lane of a is set.

aa mask

A bool.

(m8x16-any (u8x16-lt (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7))))   ; => true

Since: S1

defn

m8x16-all

(m8x16-all [a : M8x16])

true when every lane of a is set.

aa mask

A bool.

(m8x16-all (u8x16-lt (u8x16-splat (as uint8 3)) (u8x16-splat (as uint8 7))))   ; => true

Since: S1