| // Copyright 2026 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| //go:build goexperiment.simd | |
| /* | |
| Package simd implements portable and vector-size-agnostic SIMD types, | |
| and functions and methods for working with these types. SIMD types | |
| are either implemented in hardware (for example, arm64 "Neon" or | |
| amd64 "AVX/AVX2/AVX512") using the corresponding types in the | |
| [simd/archsimd] package, or emulated in pure Go. In all cases, the | |
| vector length is at least 128 bits, and within a given program | |
| execution, all vectors have the same length. | |
| # SIMD Types | |
| There is a simd type corresponding to each primitive numeric type, | |
| except for complex64 and complex128. Each of these is the type name, | |
| capitalized, with an "s" suffix, for example [Int8s], [Uint16s], | |
| or [Float64s]. | |
| There are also simd "mask" types that abstract the mask registers | |
| present in some architectures, otherwise these will be implemented | |
| as bit masks. | |
| # Obtaining SIMD values | |
| The zero value of a SIMD vector type is valid and represents a zero vector. | |
| For each SIMD type, "Load<Types>(s []<type>) <Types>" | |
| loads a full vector of the type from a long-enough slice. | |
| For slices that are not long enough, "Load<Types>Part(s []<type>) (<Types>, int)" | |
| will load as many elements as are available from the slice, fill the remainder | |
| with zero, and also return the number that were loaded. | |
| For each SIMD type, "Broadcast<Types>(x type) <Types>" | |
| returns a vector whose elements are all initialized to x. | |
| Examples: | |
| - [LoadInt8s] | |
| - [LoadUint16sPart] | |
| - [BroadcastFloat32s] | |
| # Operations | |
| SIMD types provide methods for unary ([Float32s.Abs], [Int16s.Not]), binary | |
| ([Float64s.Add], [Uint32s.GreaterEqual]), and ternary operations ([Int64s.IfElse], [Float32s.MulAdd]). | |
| Relational operations produce masks. | |
| SIMD types also support conversions between types, both those that are | |
| mostly value-preserving ([Int32s.ConvertToFloat32], [Float32s.ConvertToInt32]) and | |
| those that change types without altering the underlying vector bit | |
| pattern. | |
| Signed integer types convert to mask types ([Int16s.ToMask]), but this is a | |
| comparison against zero, not a simple bitwise conversion. Mask types | |
| convert to signed integers in an operation ([Mask32s.ToInt32s]) that may be a | |
| zero-cost bitwise conversion, or not, depending on the underlying hardware. | |
| # Storing | |
| SIMD vector types have two methods, one for storing the entire vector into a slice | |
| "Store([]<type>)" and a second for storing part of a vector into a slice "StorePart([]<type>) int". | |
| StorePart returns the number of elements actually stored. | |
| # String conversion | |
| Vectors and masks provide a String method for conversion to strings. | |
| # Conversion to and from simd/archsimd types. | |
| Each SIMD vector type has a "ToArch() any" method that returns the type | |
| supported by the current hardware as an "any". Code using | |
| these methods must be build-tagged to the relevant architecture(s) | |
| and type-assert the returned value to the appropriate type. | |
| The simd package also includes generic functions for converting an | |
| architecture-dependent simd/archsimd value (e.g. [archsimd.Float32x4]) | |
| into the corresponding simd type. This function will panic if the | |
| correspondence is incorrect. | |
| For an example of converting between [simd] and [simd/archsimd] types, | |
| see the test file sum_amd64_test.go. | |
| */ | |
| package simd | |
| // BUG(reflection): Calls won't work, and there may be other bugs. | |
| // BUG(global initialization): SIMD-dependent var initializers don't work. | |
| // BUG(modified names): Modified names may appear in stack traces and debugging. |