(std simd)

Reference

Overview

Vectors of numbers, 128 or 256 bits wide, with one CPU instruction per operation.

(import (std simd))

;; The dot product of two double arrays, four lanes at a time.
(: dot (-> (Array double) (Array double) double))
(defun (dot a b)
  (def w (simd256-lanes a))
  (def whole (simd256-whole a))
  (def acc
    (loop (:for i (up-from 0 #:to whole #:by w))
          (:acc v (folding (simd256-zero)
                           (simd-add v (simd-mul (simd256-load a i) (simd256-load b i)))))
          => v))
  ;; The elements after the last whole vector, one at a time.
  (+ (simd-sum acc)
     (loop (:for i (up-from whole #:to (array-length a)))
           (:acc s (folding 0.0 (+ s (* (array-ref a i) (array-ref b i)))))
           => s)))

A lane type is a .NET Vector128<T> or Vector256<T>: a value that holds 128 or 256 bits of numbers of one type, in lanes. The names say the element and the number of lanes: Float64x4 is four doubles, Int8x32 is 32 signed bytes. (Simd256 double) is the same type as Float64x4.

Operations. The operations are the methods of a few traits, which both widths implement, so simd-add adds two Float64x2 values or two Int32x8 values. At a known type, each call compiles to the .NET intrinsic, which the JIT compiles to one instruction. Arithmetic on integer lanes wraps.

Making a vector. The functions that make a vector say their width in the name, because there is no vector argument to take it from: simd256-load, simd128-splat, simd256-zero, (simd128-of 1 2 3 4). The element type comes from the argument, or from where the vector is used. A conversion makes a vector of another type, and says its width too.

Sources. simd128-load and simd256-load read from any SimdSource: an array or a MutableVec.

Masks. A comparison such as simd-lt gives a mask, a (Mask128 %a) or (Mask256 %a): every bit of a lane is set where the comparison holds and none where it does not. A mask is a type of its own, so it can not be added up or multiplied by mistake. simd-and, simd-or and simd-not combine masks. simd-select, simd-any?, simd-all?, simd-count-true and simd-first-true read one. simd-mask-bits gives an int with one bit per lane, which trailing-zeros from (std maths) walks: that is how a search finds every match in a vector, not only the first. simd-mask->lanes gives the lanes themselves, -1 where set and 0 where not for integer lanes, for code that counts matches by subtracting them.

Floats and integers. SimdFloat and SimdInt are implemented only for float and only for integer lanes, so a shift of a Float64x4 or the square root of an Int32x8 is refused when the program is compiled. Integer division is not offered: there is no instruction for it, and a zero divisor would raise.

Conversions. Each name says what happens to a value that does not fit. simd128-widen-lower and -upper widen half the lanes to twice the bits, sign-extending a signed lane and zero-extending an unsigned one. simd128-narrow-wrapping and -saturating make one vector of half the bits from two. simd128-int->float rounds to the nearest float. simd128-float->int-truncating goes toward zero, saturates past the range, and gives 0 for NaN. simd-bits->int64 and its family keep the bits and read them as another type.

Moving lanes. Every other operation works lane by lane: simd-shuffle is how a value reaches another lane, as in reversing or reordering. simd-lookup uses the bytes of a vector as indices into a table of 16: sixteen or thirty-two lookups in one instruction, which is how fast text code classifies and converts bytes. Neighbouring elements are compared by loading again one element on, at (+ i 1): an unaligned load is as fast as an aligned one.

Element types. A vector holds one of the primitive numbers that the trait Lane lists. A vector of anything else, such as (Simd128 char), can be named as a type, but nothing makes or takes one: the checker refuses it.

Design. The library follows OxCaml’s SIMD library where that fits a language with traits and unsigned types: masks of their own type, operations only for the element types they mean something for, and conversions named for what they do. Unlike OxCaml’s, it has unsigned lane types, so a comparison or a widening of bytes is unsigned by the type, not by the name of the operation.

The tail. An array whose length is not a multiple of the lanes has elements after the last whole vector. simd256-whole is the index where they start; handle them one at a time, as in the example. simd256-load raises ArgumentOutOfRangeException when a whole vector does not fit. simd256-whole takes any source.

Which width. A 128-bit vector is accelerated on every x86-64 and ARM64 CPU. A 256-bit vector needs AVX2; elsewhere .NET emulates it, which is much slower than scalar code. simd256-accelerated? says which. A Native AOT build targets a CPU without AVX2 unless the manifest says (aot-cpu "native") or a level such as "x86-64-v3".

Speed. Use more than one accumulator for a sum: an addition waits for the one before it to finish. On 4 million doubles with AVX2, a dot product with four Float64x4 accumulators took 1.4 ms, and a scalar loop 9.9 ms. For the common reductions, (std array) has array-sum and array-dot, which do this already.

See also: Simd, SimdBitwise, SimdMask, SimdFloat, SimdInt, SimdBits, SimdWiden, SimdNarrow, SimdSource, Mask256, simd256-load, simd256-whole, simd-mask-bits, simd256-accelerated?, Float64x4, Int32x4

Reference

Types

Functions

Values

Macros

Types

Simd128

type alias ↑ Types

A 128-bit vector of numbers of type %a: .NET’s Vector128<T>.

%a
The element type: a primitive number, one of Lane.

See also: Simd, simd128-load, simd128-splat

Simd256

type alias ↑ Types

A 256-bit vector of numbers of type %a: .NET’s Vector256<T>.

%a
The element type: a primitive number, one of Lane.

See also: Simd, simd256-load, simd256-splat

Lane

trait ↑ Types

The element types a vector holds: the primitive numbers.

%a
The element type.

double, System.Single, long, int, short, System.SByte, ulong, uint, ushort and byte. It has no methods: it only says which types these are, so that a vector of another type, which .NET refuses at run time, is refused when the program is compiled. Every operation and every way to make a vector requires it.

See also: IntLane, Simd

IntLane

trait ↑ Types

The integer element types, for the operations only integer lanes have.

%a
The element type.

The eight integer types of Lane. SimdInt requires it.

See also: Lane, FloatLane, SimdInt

FloatLane

trait ↑ Types

The float element types, double and System.Single.

%a
The element type.

See also: Lane, IntLane, SimdFloat

Mask128

record ↑ Types

The answer of a comparison of two 128-bit vectors of %a: which lanes it holds for.

%a
The element type of the vectors compared.

It holds a (Simd128 %a) with every bit of a lane set where the comparison holds, and none where it does not. Only (std simd) makes one. simd-mask->lanes gives the vector.

See also: SimdMask, SimdBitwise, simd-select, Mask256

Mask256

record ↑ Types

The answer of a comparison of two 256-bit vectors of %a: which lanes it holds for.

%a
The element type of the vectors compared.

See also: SimdMask, SimdBitwise, simd-select, Mask128

SimdBitwise

trait ↑ Types

The bitwise operations, of vectors and of masks.

%v
A vector or a mask type.

See also: simd-and, simd-or, simd-xor, simd-not, simd-and-not

SimdMask

trait ↑ Types

Reading a mask: which lanes are set.

%m
A mask type, (Mask128 %a) or (Mask256 %a).

See also: simd-any?, simd-all?, simd-count-true, simd-first-true, simd-mask-bits, simd-mask->lanes

SimdFloat

trait ↑ Types

The operations only float lanes have.

%v
A vector of FloatLane elements, such as Float64x4.

See also: simd-div, simd-sqrt, simd-floor, simd-ceiling, simd-round, simd-truncate, simd-nan?, simd-mul-add

SimdInt

trait ↑ Types

The operations only integer lanes have.

%v
A vector of IntLane elements, such as Int32x8.

See also: simd-shift-left, simd-shift-right, simd-shift-right-logical, simd-add-saturating, simd-sub-saturating, simd-shuffle, IntLane

SimdLookup

trait ↑ Types

Table lookups: each byte of a vector picks one of 16 bytes.

%v
The vector of indices: UInt8x16 or UInt8x32.

See also: simd-lookup, ByteLane

ByteLane

trait ↑ Types

The element type of simd-lookup’s indices: byte.

%a
The element type.

See also: SimdLookup

SimdBits

trait ↑ Types

The same bits, read as lanes of another type.

%v
The vector type.

See also: simd-bits->int64, simd-bits->float64, simd-bits->uint8

SimdWiden

trait ↑ Types

Widening, by the element type: half the lanes, each to twice the bits.

%a
The element type of the vector widened.

System.SByte to short, byte to ushort, short to int, ushort to uint, int to long, uint to ulong, and System.Single to double. Every value fits: a signed lane is sign-extended and an unsigned one zero-extended.

See also: simd128-widen-lower, simd128-widen-upper, simd256-widen-lower, simd256-widen-upper, SimdNarrow

SimdNarrow

trait ↑ Types

Narrowing, by the element type: two vectors into one of half the bits a lane.

%a
The element type of the vectors narrowed.

short to System.SByte, ushort to byte, int to short, uint to ushort, long to int and ulong to uint.

See also: simd128-narrow-wrapping, simd128-narrow-saturating, SimdWiden

SimdIntToFloat

trait ↑ Types

Integer lanes to float lanes of the same bits.

%a
The element type converted: int, uint, long or ulong.

See also: simd128-int->float, simd256-int->float, SimdFloatToInt

SimdFloatToInt

trait ↑ Types

Float lanes to integer lanes of the same bits, toward zero.

%a
The element type converted: System.Single or double.

See also: simd128-float->int-truncating, simd128-float->uint-truncating, SimdIntToFloat

Simd

trait ↑ Types

What every vector has, implemented by Simd128 and Simd256 at every Lane type.

%v
The vector type, such as Float64x4.

See also: simd-add, simd-lt, simd-select, simd-sum, SimdBitwise, SimdFloat, SimdInt

Float64x2

type alias ↑ Types

2 lanes of double: (Simd128 double).

Float32x4

type alias ↑ Types

4 lanes of System.Single: (Simd128 System.Single).

Int64x2

type alias ↑ Types

2 lanes of long: (Simd128 long).

Int32x4

type alias ↑ Types

4 lanes of int: (Simd128 int).

Int16x8

type alias ↑ Types

8 lanes of short: (Simd128 short).

Int8x16

type alias ↑ Types

16 lanes of System.SByte: (Simd128 System.SByte).

UInt64x2

type alias ↑ Types

2 lanes of ulong: (Simd128 ulong).

UInt32x4

type alias ↑ Types

4 lanes of uint: (Simd128 uint).

UInt16x8

type alias ↑ Types

8 lanes of ushort: (Simd128 ushort).

UInt8x16

type alias ↑ Types

16 lanes of byte: (Simd128 byte).

Float64x4

type alias ↑ Types

4 lanes of double: (Simd256 double).

Float32x8

type alias ↑ Types

8 lanes of System.Single: (Simd256 System.Single).

Int64x4

type alias ↑ Types

4 lanes of long: (Simd256 long).

Int32x8

type alias ↑ Types

8 lanes of int: (Simd256 int).

Int16x16

type alias ↑ Types

16 lanes of short: (Simd256 short).

Int8x32

type alias ↑ Types

32 lanes of System.SByte: (Simd256 System.SByte).

UInt64x4

type alias ↑ Types

4 lanes of ulong: (Simd256 ulong).

UInt32x8

type alias ↑ Types

8 lanes of uint: (Simd256 uint).

UInt16x16

type alias ↑ Types

16 lanes of ushort: (Simd256 ushort).

UInt8x32

type alias ↑ Types

32 lanes of byte: (Simd256 byte).

SimdSource

trait ↑ Types

What vectors are loaded from: elements of one type, one after the other in memory.

%s
The source: (Array %a) or (MutableVec %a).

A string is not a source. Its positions are cursors, and a lane of its bytes would be a byte index. For a byte search, string->bytes gives an array.

See also: simd128-load, simd256-load, simd256-whole, simd-source-length

Functions

simd-source-length

function ↑ Functions

(: simd-source-length (-> %s int))

How many elements a source has: the length of the array or the MutableVec.

s
The source.
returns
The number of elements.

simd-mask-bits

function ↑ Functions

(: simd-mask-bits (-> %m int))

A mask as an int: bit i is set where lane i of the mask is.

mask
The mask.
returns
The bits. A 32-lane mask with its last lane set is a negative int.
(import (std maths))

;; The index of every comma in the 32 bytes of the array a from i.
(defun (commas a i)
  (def bits (simd-mask-bits (simd-eq (simd256-load a i) (simd256-splat 44uy))))
  (loop (:with b bits (bitwise-and b (- b 1)))
        (:while (not (= b 0)))
        (:acc out (listing (+ i (trailing-zeros b))))
        => out))

The CPU’s move-mask instruction: one instruction for a whole vector. Each lane gives its top bit, which is every bit of a mask’s lane.

See also: simd-first-true, simd-count-true

simd-shift-left

function ↑ Functions

(: simd-shift-left (-> %v int %v))

Shifts every lane left by the same number of bits.

v
The vector, of integer lanes.
n
The number of bits.
returns
The shifted lanes. Bits shifted out are lost, and zeros come in.

The count is taken modulo the lane’s width in bits, as the scalar shifts take it: shifting an Int32x4 by 33 shifts it by 1.

See also: simd-shift-right, simd-shift-right-logical

simd-shift-right

function ↑ Functions

(: simd-shift-right (-> %v int %v))

Shifts every lane right: arithmetic for signed lanes, logical for unsigned ones.

v
The vector, of integer lanes.
n
The number of bits.
returns
The shifted lanes. A signed lane keeps its sign, as shift-right does.

See also: simd-shift-right-logical, simd-shift-left

simd-shift-right-logical

function ↑ Functions

(: simd-shift-right-logical (-> %v int %v))

Shifts every lane right, with zeros coming in, for any integer lane type.

v
The vector, of integer lanes.
n
The number of bits.
returns
The shifted lanes.

See also: simd-shift-right, simd-shift-left

simd-add

function ↑ Functions

(: simd-add (-> %v %v %v))

Adds the lanes of two vectors.

a
The first vector.
b
The second vector.
returns
The lane-wise sums.

simd-sub

function ↑ Functions

(: simd-sub (-> %v %v %v))

Subtracts the lanes of b from the lanes of a.

a
The vector to subtract from.
b
The vector to subtract.
returns
The lane-wise differences.

simd-mul

function ↑ Functions

(: simd-mul (-> %v %v %v))

Multiplies the lanes of two vectors.

a
The first vector.
b
The second vector.
returns
The lane-wise products.

simd-div

function ↑ Functions

(: simd-div (-> %v %v %v))

Divides the float lanes of a by those of b. A lane divided by 0 is an infinity, or NaN for 0 by 0.

a
The dividends.
b
The divisors.
returns
The lane-wise quotients.

simd-scale

function ↑ Functions

(: simd-scale (-> %v %elem %v))

Multiplies every lane by one number.

v
The vector.
k
The factor.
returns
Each lane times k.

simd-neg

function ↑ Functions

(: simd-neg (-> %v %v))

Negates every lane.

v
The vector.
returns
The negated lanes.

simd-abs

function ↑ Functions

(: simd-abs (-> %v %v))

The absolute value of every lane.

v
The vector.
returns
The absolute values.

simd-min

function ↑ Functions

(: simd-min (-> %v %v %v))

The lesser of each pair of lanes.

a
The first vector.
b
The second vector.
returns
The lane-wise minimums.

simd-max

function ↑ Functions

(: simd-max (-> %v %v %v))

The greater of each pair of lanes.

a
The first vector.
b
The second vector.
returns
The lane-wise maximums.

simd-sqrt

function ↑ Functions

(: simd-sqrt (-> %v %v))

The square root of every float lane. A negative lane gives NaN.

v
The vector.
returns
The square roots.

simd-floor

function ↑ Functions

(: simd-floor (-> %v %v))

Every float lane rounded down, toward negative infinity.

v
The vector.
returns
The rounded lanes, still floats.

simd-ceiling

function ↑ Functions

(: simd-ceiling (-> %v %v))

Every float lane rounded up, toward positive infinity.

v
The vector.
returns
The rounded lanes, still floats.

simd-round

function ↑ Functions

(: simd-round (-> %v %v))

Every float lane rounded to the nearest integer, and from halfway to the even one.

v
The vector.
returns
The rounded lanes, still floats: 0.5 and 1.5 give 0 and 2.

See also: simd128-float->int-truncating

simd-truncate

function ↑ Functions

(: simd-truncate (-> %v %v))

Every float lane rounded toward zero.

v
The vector.
returns
The rounded lanes, still floats.

simd-nan?

function ↑ Functions

(: simd-nan? (-> %v %mask))

A mask of the float lanes that are NaN.

v
The vector.
returns
A mask.

simd-mul-add

function ↑ Functions

(: simd-mul-add (-> %v %v %v %v))

a * b + c in every float lane, rounded once.

a
The first factors.
b
The second factors.
c
What is added to the products.
returns
The lanes of a * b + c.

One fused instruction where the CPU has one (FMA3 on x86-64, every ARM64). Rounded once, so it can differ in the last bit from (simd-add (simd-mul a b) c), which rounds twice.

simd-shuffle

function ↑ Functions

(: simd-shuffle (-> %v %v %v))

The lanes of v, in the order idx says: lane i of the result is lane (simd-ref idx i) of v.

v
The vector, of integer lanes.
idx
The lane to take for each lane, of the same type. An index past the last lane gives 0.
returns
The rearranged lanes.
(simd-shuffle (simd128-of 10 20 30 40) (simd128-of 3 2 1 0))   ; 40 30 20 10
(simd-shuffle v (simd128-of 0 0 0 0))                          ; lane 0 in every lane

;; Float lanes, through their bits.
(simd-bits->float64 (simd-shuffle (simd-bits->int64 xs) (simd128-of 1L 0L)))

One instruction where the indices are known and the CPU has it: SSSE3 or AVX2 on x86-64, tbl on ARM64. Indices that are not constant cost a little more. At 256 bits, AVX2 moves bytes and shorts only within each half of 16 bytes, so a shuffle that takes a lane from the other half is a few instructions.

See also: simd-lookup, simd-bits->int64

simd-lookup

function ↑ Functions

(: simd-lookup (-> (Simd128 byte) %v %v))

Each byte of idx looked up in a table of 16 bytes. An index of 16 or more gives 0.

table
The table: a UInt8x16, entry i at lane i.
idx
The indices, a UInt8x16 or UInt8x32.
returns
The entries, a vector of the type of idx.
;; Which bytes are ASCII digits, by their two halves. A byte's high
;; half picks a set of low halves from one table, its low half a bit
;; from the other: bit 0 is "a digit's low half", and only high half 3
;; allows it.
(def low-table  (simd128-of 1uy 1uy 1uy 1uy 1uy 1uy 1uy 1uy 1uy 1uy))   ; 0-9
(def high-table (simd128-of 0uy 0uy 0uy 1uy))                         ; 0x30-0x3F
(: digits (-> UInt8x32 (Mask256 byte)))
(defun (digits bytes)
  (def lo (simd-lookup low-table (simd-and bytes (simd256-splat 15uy))))
  (def hi (simd-lookup high-table (simd-shift-right bytes 4)))
  (simd-ne (simd-and lo hi) (simd256-zero)))

The instruction is pshufb on x86-64 and tbl on ARM64: 16 lookups for a UInt8x16 and 32 for a UInt8x32, in one instruction. A UInt8x32 looks up its two halves in the same table. With a table for each half of a byte, as in the example, a vector of bytes is classified into up to eight sets at once: digits, spaces, the characters a JSON or CSV parser stops at. With a table of characters, it converts: "0123456789abcdef" gives hex digits.

See also: simd-shuffle, simd-shift-right-logical

simd-add-saturating

function ↑ Functions

(: simd-add-saturating (-> %v %v %v))

Adds the integer lanes, and gives the type’s greatest or least value where the sum does not fit.

a
The first vector.
b
The second vector.
returns
The lane-wise sums, saturated: 250uy plus 10uy is 255uy.

simd-sub-saturating

function ↑ Functions

(: simd-sub-saturating (-> %v %v %v))

Subtracts the integer lanes, and gives the type’s greatest or least value where the difference does not fit.

a
The vector to subtract from.
b
The vector to subtract.
returns
The lane-wise differences, saturated: 5uy minus 10uy is 0uy.

simd-and-not

function ↑ Functions

(: simd-and-not (-> %v %v %v))

The bits of a that are not set in b. Of two masks, the lanes set in the first only.

a
The first vector or mask.
b
The second, whose bits are taken away.
returns
The bits of a and not b.

simd-and

function ↑ Functions

(: simd-and (-> %v %v %v))

The bitwise and of two vectors. Combines two masks into the lanes set in both.

a
The first vector.
b
The second vector.
returns
The bitwise and.

simd-or

function ↑ Functions

(: simd-or (-> %v %v %v))

The bitwise or of two vectors. Combines two masks into the lanes set in either.

a
The first vector.
b
The second vector.
returns
The bitwise or.

simd-xor

function ↑ Functions

(: simd-xor (-> %v %v %v))

The bitwise exclusive or of two vectors.

a
The first vector.
b
The second vector.
returns
The bitwise exclusive or.

simd-not

function ↑ Functions

(: simd-not (-> %v %v))

Inverts every bit. Turns a mask into the lanes it does not set.

v
The vector.
returns
The inverted bits.

simd-eq

function ↑ Functions

(: simd-eq (-> %v %v %mask))

A mask of the lanes where a equals b. NaN equals nothing.

a
The first vector.
b
The second vector.
returns
A mask.

simd-ne

function ↑ Functions

(: simd-ne (-> %v %v %mask))

A mask of the lanes where a does not equal b. NaN differs from everything.

a
The first vector.
b
The second vector.
returns
A mask.
(simd-ne v (simd256-zero))   ; the lanes that are not 0: a mask from -1/0 lanes kept in memory

simd-lt

function ↑ Functions

(: simd-lt (-> %v %v %mask))

A mask of the lanes where a is less than b.

a
The first vector.
b
The second vector.
returns
A mask.

simd-le

function ↑ Functions

(: simd-le (-> %v %v %mask))

A mask of the lanes where a is less than or equal to b.

a
The first vector.
b
The second vector.
returns
A mask.

simd-gt

function ↑ Functions

(: simd-gt (-> %v %v %mask))

A mask of the lanes where a is greater than b.

a
The first vector.
b
The second vector.
returns
A mask.

simd-ge

function ↑ Functions

(: simd-ge (-> %v %v %mask))

A mask of the lanes where a is greater than or equal to b.

a
The first vector.
b
The second vector.
returns
A mask.

simd-select

function ↑ Functions

(: simd-select (-> %mask %v %v %v))

Each lane from a where mask is set, and from b where it is not. The mask is a comparison’s of vectors of the same type.

mask
Which lanes to take from a.
a
The lanes where the mask is set.
b
The lanes where the mask is not set.
returns
The selected lanes.

simd-any?

function ↑ Functions

(: simd-any? (-> %m bool))

Whether any lane of a mask is set.

mask
The mask.
returns
#t when at least one lane is set.

simd-all?

function ↑ Functions

(: simd-all? (-> %m bool))

Whether every lane of a mask is set.

mask
The mask.
returns
#t when every lane is set.

simd-count-true

function ↑ Functions

(: simd-count-true (-> %m int))

How many lanes of a mask are set.

mask
The mask.
returns
The number of lanes that are set.

simd-first-true

function ↑ Functions

(: simd-first-true (-> %m int))

The index of the first lane of a mask that is set, or -1.

mask
The mask.
returns
The lowest index of a set lane, or -1.

simd-sum

function ↑ Functions

(: simd-sum (-> %v %elem))

The sum of the lanes.

v
The vector.
returns
The sum.

simd-dot

function ↑ Functions

(: simd-dot (-> %v %v %elem))

The sum of the products of the lanes.

a
The first vector.
b
The second vector.
returns
The dot product.

simd-ref

function ↑ Functions

(: simd-ref (-> %v int %elem))

The lane at an index. Raises ArgumentOutOfRangeException outside the lanes.

v
The vector.
i
The lane, from 0.
returns
The number in the lane.

simd-with

function ↑ Functions

(: simd-with (-> %v int %elem %v))

The vector with one lane replaced. Raises ArgumentOutOfRangeException outside the lanes.

v
The vector.
i
The lane, from 0.
x
The new number.
returns
A vector of the same lanes but the one at i.

See also: simd128-of, simd-ref

simd-mask->lanes

function ↑ Functions

(: simd-mask->lanes (-> %m %vec))

The vector a mask holds: every bit of a lane set where the mask is, and none where it is not.

mask
The mask.
returns
For integer lanes, -1 where set and 0 where not. For float lanes, the same bits, which are NaN.
;; Matches counted lane by lane: subtracting -1 adds one.
(simd-sub counts (simd-mask->lanes (simd-eq bytes needle)))

simd-bits->int8

function ↑ Functions

(: simd-bits->int8 (-> %v %int8))

The same bits, as lanes of System.SByte.

v
The vector.
returns
An Int8x16 or Int8x32.

simd-bits->uint8

function ↑ Functions

(: simd-bits->uint8 (-> %v %uint8))

The same bits, as lanes of byte.

v
The vector.
returns
A UInt8x16 or UInt8x32.

simd-bits->int16

function ↑ Functions

(: simd-bits->int16 (-> %v %int16))

The same bits, as lanes of short.

v
The vector.
returns
An Int16x8 or Int16x16.

simd-bits->uint16

function ↑ Functions

(: simd-bits->uint16 (-> %v %uint16))

The same bits, as lanes of ushort.

v
The vector.
returns
A UInt16x8 or UInt16x16.

simd-bits->int32

function ↑ Functions

(: simd-bits->int32 (-> %v %int32))

The same bits, as lanes of int.

v
The vector.
returns
An Int32x4 or Int32x8.

simd-bits->uint32

function ↑ Functions

(: simd-bits->uint32 (-> %v %uint32))

The same bits, as lanes of uint.

v
The vector.
returns
A UInt32x4 or UInt32x8.

simd-bits->int64

function ↑ Functions

(: simd-bits->int64 (-> %v %int64))

The same bits, as lanes of long.

v
The vector.
returns
An Int64x2 or Int64x4.
(simd-bits->int64 (simd-mask->lanes (simd-lt xs ys)))   ; -1 and 0, from doubles

simd-bits->uint64

function ↑ Functions

(: simd-bits->uint64 (-> %v %uint64))

The same bits, as lanes of ulong.

v
The vector.
returns
A UInt64x2 or UInt64x4.

simd-bits->float32

function ↑ Functions

(: simd-bits->float32 (-> %v %float32))

The same bits, as lanes of System.Single.

v
The vector.
returns
A Float32x4 or Float32x8.

simd-bits->float64

function ↑ Functions

(: simd-bits->float64 (-> %v %float64))

The same bits, as lanes of double.

v
The vector.
returns
A Float64x2 or Float64x4.

simd128-widen-lower

function ↑ Functions

(: simd128-widen-lower (-> (Simd128 %a) (Simd128 %wide)))

The lower half of the lanes, each widened to twice the bits.

v
The vector.
returns
A vector of the wider type: UInt8x16 gives UInt16x8.

See also: simd128-widen-upper, SimdWiden

simd128-widen-upper

function ↑ Functions

(: simd128-widen-upper (-> (Simd128 %a) (Simd128 %wide)))

The upper half of the lanes, each widened to twice the bits.

v
The vector.
returns
A vector of the wider type.

See also: simd128-widen-lower, SimdWiden

simd256-widen-lower

function ↑ Functions

(: simd256-widen-lower (-> (Simd256 %a) (Simd256 %wide)))

The lower half of the lanes, each widened to twice the bits.

v
The vector.
returns
A vector of the wider type: UInt8x32 gives UInt16x16.

See also: simd256-widen-upper, SimdWiden

simd256-widen-upper

function ↑ Functions

(: simd256-widen-upper (-> (Simd256 %a) (Simd256 %wide)))

The upper half of the lanes, each widened to twice the bits.

v
The vector.
returns
A vector of the wider type.

See also: simd256-widen-lower, SimdWiden

simd128-narrow-wrapping

function ↑ Functions

(: simd128-narrow-wrapping (-> (Simd128 %a) (Simd128 %a) (Simd128 %narrow)))

Two vectors into one of half the bits a lane, keeping the low bits of each.

lower
The vector whose lanes become the lower half.
upper
The vector whose lanes become the upper half.
returns
The narrowed lanes: an int 300 becomes the short 300, and 70000 becomes 4464.

See also: simd128-narrow-saturating, SimdNarrow

simd128-narrow-saturating

function ↑ Functions

(: simd128-narrow-saturating (-> (Simd128 %a) (Simd128 %a) (Simd128 %narrow)))

Two vectors into one of half the bits a lane, giving the nearest value that fits.

lower
The vector whose lanes become the lower half.
upper
The vector whose lanes become the upper half.
returns
The narrowed lanes: an int 70000 becomes the short 32767.

See also: simd128-narrow-wrapping, SimdNarrow

simd256-narrow-wrapping

function ↑ Functions

(: simd256-narrow-wrapping (-> (Simd256 %a) (Simd256 %a) (Simd256 %narrow)))

Two vectors into one of half the bits a lane, keeping the low bits of each.

lower
The vector whose lanes become the lower half.
upper
The vector whose lanes become the upper half.
returns
The narrowed lanes.

See also: simd256-narrow-saturating, SimdNarrow

simd256-narrow-saturating

function ↑ Functions

(: simd256-narrow-saturating (-> (Simd256 %a) (Simd256 %a) (Simd256 %narrow)))

Two vectors into one of half the bits a lane, giving the nearest value that fits.

lower
The vector whose lanes become the lower half.
upper
The vector whose lanes become the upper half.
returns
The narrowed lanes.

See also: simd256-narrow-wrapping, SimdNarrow

simd128-int->float

function ↑ Functions

(: simd128-int->float (-> (Simd128 %a) (Simd128 %float)))

Integer lanes as float lanes of the same bits: int to System.Single, long to double.

v
The vector.
returns
The floats, each the nearest to its integer.

See also: simd128-float->int-truncating, SimdIntToFloat

simd256-int->float

function ↑ Functions

(: simd256-int->float (-> (Simd256 %a) (Simd256 %float)))

Integer lanes as float lanes of the same bits.

v
The vector.
returns
The floats, each the nearest to its integer.

See also: simd256-float->int-truncating, SimdIntToFloat

simd128-float->int-truncating

function ↑ Functions

(: simd128-float->int-truncating (-> (Simd128 %a) (Simd128 %int)))

Float lanes as signed integer lanes of the same bits, rounded toward zero.

v
The vector.
returns
The integers. Past the range, the type's least or greatest value; NaN gives 0.
(simd128-float->int-truncating (simd-round v))   ; to the nearest, then exact

See also: simd-round, simd128-float->uint-truncating, SimdFloatToInt

simd256-float->int-truncating

function ↑ Functions

(: simd256-float->int-truncating (-> (Simd256 %a) (Simd256 %int)))

Float lanes as signed integer lanes of the same bits, rounded toward zero.

v
The vector.
returns
The integers. Past the range, the type's least or greatest value; NaN gives 0.

See also: simd256-float->uint-truncating, SimdFloatToInt

simd128-float->uint-truncating

function ↑ Functions

(: simd128-float->uint-truncating (-> (Simd128 %a) (Simd128 %uint)))

Float lanes as unsigned integer lanes of the same bits, rounded toward zero.

v
The vector.
returns
The integers. A negative lane gives 0, past the range the greatest value, and NaN 0.

See also: simd128-float->int-truncating, SimdFloatToInt

simd256-float->uint-truncating

function ↑ Functions

(: simd256-float->uint-truncating (-> (Simd256 %a) (Simd256 %uint)))

Float lanes as unsigned integer lanes of the same bits, rounded toward zero.

v
The vector.
returns
The integers. A negative lane gives 0, past the range the greatest value, and NaN 0.

See also: simd256-float->int-truncating, SimdFloatToInt

simd-store!

function ↑ Functions

(: simd-store! (-> %v (Array %elem) int void))

Writes the lanes into an array, from an index. Raises when they do not fit.

v
The vector.
a
The array to write.
i
The index of the first lane in the array.

simd-lanes

function ↑ Functions

(: simd-lanes (-> %v int))

How many lanes the vector has.

v
The vector. Only its type is read.
returns
The number of lanes.

simd128-splat

function ↑ Functions

(: simd128-splat (-> %a (Simd128 %a)))
(simd128-splat x)

A 128-bit vector with the number in every lane.

x
The number.
returns
The vector.

simd128-zero

function ↑ Functions

(: simd128-zero (-> (Simd128 %a)))
(simd128-zero)

A 128-bit vector of zeros. Its element type comes from where it is used.

returns
The vector.

simd128-load

function ↑ Functions

(: simd128-load (-> %s int (Simd128 %elem)))

The 128-bit vector of the elements of a source from an index.

s
The array or MutableVec.
i
The index of the first lane.
returns
The vector.

Raises ArgumentOutOfRangeException when fewer than a vector’s lanes of elements are left from i.

simd128-lanes

function ↑ Functions

(: simd128-lanes (-> %s int))

How many elements of the source one 128-bit vector holds.

s
The source. Only its type is read.
returns
The number of lanes.

simd128-whole

function ↑ Functions

(: simd128-whole (-> %s int))
(simd128-whole s)

The length of the source, rounded down to whole 128-bit vectors.

s
The array or MutableVec.
returns
The index of the first element after the last whole vector.

simd256-splat

function ↑ Functions

(: simd256-splat (-> %a (Simd256 %a)))
(simd256-splat x)

A 256-bit vector with the number in every lane.

x
The number.
returns
The vector.

simd256-zero

function ↑ Functions

(: simd256-zero (-> (Simd256 %a)))
(simd256-zero)

A 256-bit vector of zeros. Its element type comes from where it is used.

returns
The vector.

simd256-load

function ↑ Functions

(: simd256-load (-> %s int (Simd256 %elem)))

The 256-bit vector of the elements of a source from an index.

s
The array or MutableVec.
i
The index of the first lane.
returns
The vector.

Raises ArgumentOutOfRangeException when fewer than a vector’s lanes of elements are left from i.

simd256-lanes

function ↑ Functions

(: simd256-lanes (-> %s int))

How many elements of the source one 256-bit vector holds.

s
The source. Only its type is read.
returns
The number of lanes.

simd256-whole

function ↑ Functions

(: simd256-whole (-> %s int))
(simd256-whole s)

The length of the source, rounded down to whole 256-bit vectors.

s
The array or MutableVec.
returns
The index of the first element after the last whole vector.

Values

simd128-accelerated?

value ↑ Values

Whether the CPU runs 128-bit vector operations as instructions, not emulated.

simd256-accelerated?

value ↑ Values

Whether the CPU runs 256-bit vector operations as instructions, not emulated.

Macros

simd128-of

macro ↑ Macros

(simd128-of x more ...)

A 128-bit vector of the given lanes, from lane 0.

x
Lane 0.
more ...
The lanes after it.
(simd128-of 1 2 3 4)          ; an Int32x4
(simd128-of 1.5 2.5)          ; a Float64x2

Each value is written into a vector of zeros with simd-with, so a lane not given is 0, and a value past the last lane raises ArgumentOutOfRangeException. The element type is the values’.

See also: simd-with, simd128-splat

simd256-of

macro ↑ Macros

(simd256-of x more ...)

A 256-bit vector of the given lanes, from lane 0.

x
Lane 0.
more ...
The lanes after it.
(simd256-of 1.0 2.0 3.0 4.0)  ; a Float64x4

Each value is written into a vector of zeros with simd-with, so a lane not given is 0, and a value past the last lane raises ArgumentOutOfRangeException. The element type is the values’.

See also: simd-with, simd256-splat