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.
Simd: what every element type has. Arithmetic, min and max, comparisons,simd-select, sums, and one lane.SimdBitwise: and, or, xor, not and and-not, for vectors and for masks.SimdMask: reading a mask.SimdFloat: what only float lanes have. Division, square root, rounding, NaN and fused multiply-add.SimdInt: what only integer lanes have. Shifts, saturating arithmetic, and shuffles.SimdLookup: 16-byte table lookups, a vector of bytes at a time.SimdBits: the same bits read as another element type.SimdWiden,SimdNarrow,SimdIntToFloatandSimdFloatToInt: conversions to another element type.
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
ByteLaneFloat32x4Float32x8Float64x2Float64x4FloatLaneInt16x16Int16x8Int32x4Int32x8Int64x2Int64x4Int8x16Int8x32IntLaneLaneMask128Mask256SimdSimd128Simd256SimdBitsSimdBitwiseSimdFloatSimdFloatToIntSimdIntSimdIntToFloatSimdLookupSimdMaskSimdNarrowSimdSourceSimdWidenUInt16x16UInt16x8UInt32x4UInt32x8UInt64x2UInt64x4UInt8x16UInt8x32
simd-abssimd-addsimd-add-saturatingsimd-all?simd-andsimd-and-notsimd-any?simd-bits->float32simd-bits->float64simd-bits->int16simd-bits->int32simd-bits->int64simd-bits->int8simd-bits->uint16simd-bits->uint32simd-bits->uint64simd-bits->uint8simd-ceilingsimd-count-truesimd-divsimd-dotsimd-eqsimd-first-truesimd-floorsimd-gesimd-gtsimd-lanessimd-lesimd-lookupsimd-ltsimd-mask->lanessimd-mask-bitssimd-maxsimd-minsimd-mulsimd-mul-addsimd-nan?simd-nesimd-negsimd-notsimd-orsimd-refsimd-roundsimd-scalesimd-selectsimd-shift-leftsimd-shift-rightsimd-shift-right-logicalsimd-shufflesimd-source-lengthsimd-sqrtsimd-store!simd-subsimd-sub-saturatingsimd-sumsimd-truncatesimd-withsimd-xorsimd128-float->int-truncatingsimd128-float->uint-truncatingsimd128-int->floatsimd128-lanessimd128-loadsimd128-narrow-saturatingsimd128-narrow-wrappingsimd128-splatsimd128-wholesimd128-widen-lowersimd128-widen-uppersimd128-zerosimd256-float->int-truncatingsimd256-float->uint-truncatingsimd256-int->floatsimd256-lanessimd256-loadsimd256-narrow-saturatingsimd256-narrow-wrappingsimd256-splatsimd256-wholesimd256-widen-lowersimd256-widen-uppersimd256-zero
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.
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.
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
FloatLaneelements, such asFloat64x4.
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
IntLaneelements, such asInt32x8.
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:
UInt8x16orUInt8x32.
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,longorulong.
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.Singleordouble.
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
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-rightdoes.
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
UInt8x16orUInt8x32. - 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
aand notb.
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
Int8x16orInt8x32.
simd-bits->uint8
function ↑ Functions
(: simd-bits->uint8 (-> %v %uint8))
The same bits, as lanes of byte.
v- The vector.
- returns
- A
UInt8x16orUInt8x32.
simd-bits->int16
function ↑ Functions
(: simd-bits->int16 (-> %v %int16))
The same bits, as lanes of short.
v- The vector.
- returns
- An
Int16x8orInt16x16.
simd-bits->uint16
function ↑ Functions
(: simd-bits->uint16 (-> %v %uint16))
The same bits, as lanes of ushort.
v- The vector.
- returns
- A
UInt16x8orUInt16x16.
simd-bits->int32
function ↑ Functions
(: simd-bits->int32 (-> %v %int32))
The same bits, as lanes of int.
v- The vector.
- returns
- An
Int32x4orInt32x8.
simd-bits->uint32
function ↑ Functions
(: simd-bits->uint32 (-> %v %uint32))
The same bits, as lanes of uint.
v- The vector.
- returns
- A
UInt32x4orUInt32x8.
simd-bits->int64
function ↑ Functions
(: simd-bits->int64 (-> %v %int64))
The same bits, as lanes of long.
v- The vector.
- returns
- An
Int64x2orInt64x4.
(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
UInt64x2orUInt64x4.
simd-bits->float32
function ↑ Functions
(: simd-bits->float32 (-> %v %float32))
The same bits, as lanes of System.Single.
v- The vector.
- returns
- A
Float32x4orFloat32x8.
simd-bits->float64
function ↑ Functions
(: simd-bits->float64 (-> %v %float64))
The same bits, as lanes of double.
v- The vector.
- returns
- A
Float64x2orFloat64x4.
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:
UInt8x16givesUInt16x8.
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:
UInt8x32givesUInt16x16.
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
int300 becomes theshort300, 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
int70000 becomes theshort32767.
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