api/go1.27.txt | 3 +++ src/cmd/compile/internal/arm64/simdssa.go | 4 ++-- src/cmd/compile/internal/dwarfgen/dwarf.go | 12 ++++++++---- src/cmd/compile/internal/escape/assign.go | 2 ++ src/cmd/compile/internal/escape/call.go | 2 ++ src/cmd/compile/internal/escape/expr.go | 2 ++ src/cmd/compile/internal/inline/inl.go | 8 ++++---- src/cmd/compile/internal/noder/reader.go | 8 +++----- src/cmd/compile/internal/noder/unified.go | 8 ++++---- src/cmd/compile/internal/pkginit/init.go | 5 ++++- src/cmd/compile/internal/ssa/_gen/AMD64.rules | 70 +++++++++++++++++++++++++++--------------------------- src/cmd/compile/internal/ssa/_gen/generic.rules | 72 +++++++++++++++++++++++++++--------------------------- src/cmd/compile/internal/ssa/_gen/simdARM64.rules | 6 +++--- src/cmd/compile/internal/ssa/rewriteAMD64.go | 168 +++++++++++++++++++++++++++--------------------------- src/cmd/compile/internal/ssa/rewriteARM64.go | 4 ++-- src/cmd/compile/internal/ssa/rewritegeneric.go | 252 +++++++++++++++++++++++------------------------------ src/cmd/compile/internal/ssagen/simdWasmintrinsics.go | 4 ++-- src/cmd/compile/internal/staticinit/sched.go | 52 ---------------------------------------------------- src/cmd/compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/stdlib_test.go | 1 + src/cmd/compile/internal/types2/typestring.go | 6 +++++- src/cmd/compile/internal/walk/assign.go | 15 +++++++-------- src/cmd/compile/internal/walk/expr.go | 45 +++++++++++---------------------------------- src/cmd/compile/internal/walk/walk.go | 3 ++- src/cmd/internal/objfile/elf.go | 6 +++++- src/cmd/internal/objfile/pe.go | 25 +++++++++++++++++++++++++ src/cmd/internal/script/scripttest/setup.go | 4 +++- src/cmd/link/internal/ld/ld_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++ src/cmd/link/internal/ld/pe.go | 2 +- src/cmd/nm/nm_test.go | 2 ++ src/cmd/nm/script_test.go | 35 +++++++++++++++++++++++++++++++++++ src/cmd/nm/testdata/script/README | 286 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/nm/testdata/script/issue77301.txt | 20 ++++++++++++++++++++ src/crypto/internal/cryptotest/fetchmodule.go | 12 +++++++++--- src/crypto/internal/cryptotest/x509limbo/_schema/go.mod | 14 ++++++++++++++ src/crypto/internal/cryptotest/x509limbo/_schema/go.sum | 25 +++++++++++++++++++++++++ src/crypto/internal/cryptotest/x509limbo/_schema/schema_gen.go | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/crypto/internal/cryptotest/x509limbo/schema.go | 591 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/crypto/internal/cryptotest/x509limbo/schemaversion.go | 14 ++++++++++++++ src/crypto/tls/conn.go | 6 ++++++ src/crypto/tls/handshake_messages.go | 4 +++- src/crypto/tls/handshake_messages_test.go | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++--- src/crypto/tls/tls_test.go | 1 + src/crypto/x509/bettertls_test.go | 225 ----------------------------------------------------- src/crypto/x509/x509limbo_test.go | 339 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/encoding/json/v2/arshal.go | 8 ++++++-- src/encoding/json/v2/arshal_default.go | 10 ++++++++-- src/encoding/json/v2/arshal_funcs.go | 2 ++ src/encoding/json/v2/arshal_test.go | 36 ++++++++++++++++++++++-------------- src/encoding/json/v2/doc.go | 3 ++- src/encoding/json/v2/errors.go | 8 ++++++-- src/encoding/json/v2/options.go | 18 +++++++++++++++--- src/encoding/json/v2_options.go | 5 +++++ src/fmt/doc.go | 2 +- src/go/build/deps_test.go | 3 +++ src/go/types/instantiate.go | 2 +- src/go/types/stdlib_test.go | 1 + src/go/types/typestring.go | 6 +++++- src/internal/nettest/conn_test.go | 1 + src/internal/runtime/maps/map.go | 19 +++++++++++++++++++ src/internal/types/testdata/fixedbugs/issue79883.go | 9 +++++++++ src/log/slog/handler.go | 1 - src/math/big/floatconv_test.go | 25 ++++++++++++++++++++++--- src/math/big/ftoa.go | 16 +++++++++++----- src/math/rand/v2/rand.go | 3 +++ src/net/http/http2.go | 3 ++- src/net/http/httputil/reverseproxy.go | 30 ------------------------------ src/net/http/httputil/reverseproxy_test.go | 38 -------------------------------------- src/net/http/internal/http2/api.go | 1 + src/net/http/internal/http2/frame.go | 18 ++++++++++++++++++ src/net/http/internal/http2/server.go | 4 ++++ src/net/http/request.go | 16 +++++++++++++++- src/net/http/serve_test.go | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++-- src/net/http/server.go | 104 +++++++++++++++++++++++++++++++++++++++++++++-------- src/net/lookup_test.go | 4 ++-- src/net/textproto/reader.go | 13 ++++++++++--- src/os/dir_darwin.go | 7 +++++++ src/os/read_test.go | 15 +++++++++++++++ src/os/root_windows.go | 4 ++++ src/os/root_windows_test.go | 25 +++++++++++++++++++++++++ src/os/signal/signal_windows_test.go | 37 ++++++++++++++++++++++++++++--------- src/os/statat_unix.go | 6 +++++- src/runtime/lockrank_off.go | 7 +++++-- src/runtime/lockrank_on.go | 12 ++++++++---- src/runtime/malloc_generated.go | 264 +++++++++++++++++++++++++++++++---------------------- src/runtime/malloc_stubs.go | 91 ++++++++++++++++++++++++++++++++++------------------- src/runtime/mem_sbrk.go | 4 ++++ src/runtime/softfloat64.go | 9 +++++++-- src/runtime/softfloat64_test.go | 10 ++++++---- src/simd/archsimd/_gen/midway/intersect_simd_ops.go | 7 ++++++- src/simd/archsimd/_gen/simdgen/ops/Moves/categories.yaml | 4 ++-- src/simd/archsimd/_gen/simdgen/ops/Moves/go_arm64.yaml | 14 +++++++------- src/simd/archsimd/_gen/tmplgen/main.go | 213 ++++++++++++++++++----------------------------------- src/simd/archsimd/_gen/wasmgen/main.go | 4 ++-- src/simd/archsimd/internal/simd_test/arm64_binary_helpers_test.go | 164 ----------------------------------------------------- src/simd/archsimd/internal/simd_test/arm64_binary_test.go | 336 ----------------------------------------------------- src/simd/archsimd/internal/simd_test/arm64_bitwise_test.go | 84 ----------------------------------------------------- src/simd/archsimd/internal/simd_test/arm64_compare_helpers_test.go | 164 ----------------------------------------------------- src/simd/archsimd/internal/simd_test/arm64_compare_test.go | 192 ----------------------------------------------------- src/simd/archsimd/internal/simd_test/arm64_convert_test.go | 39 --------------------------------------- src/simd/archsimd/internal/simd_test/arm64_shift_helpers_test.go | 382 ----------------------------------------------------- src/simd/archsimd/internal/simd_test/arm64_shift_test.go | 169 ----------------------------------------------------- src/simd/archsimd/internal/simd_test/arm64_simd_test.go | 130 ----------------------------------------------------- src/simd/archsimd/internal/simd_test/arm64_unary_helpers_test.go | 1554 ----------------------------------------------------- src/simd/archsimd/internal/simd_test/arm64_unary_test.go | 37 ------------------------------------- src/simd/archsimd/internal/simd_test/binary_128_test.go | 223 ++++++++++++++++++++++++++++++++++++++++++++++++----- src/simd/archsimd/internal/simd_test/binary_arm64_test.go | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/binary_helpers_128_test.go | 2 +- src/simd/archsimd/internal/simd_test/binary_test.go => src/simd/archsimd/internal/simd_test/binary_amd64_test.go | 196 ++++++++--------------------------------------------- src/simd/archsimd/internal/simd_test/binary_wasm_test.go | 27 +++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/compare_128_test.go | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/simd/archsimd/internal/simd_test/compare_helpers_128_test.go | 2 +- src/simd/archsimd/internal/simd_test/compare_test.go => src/simd/archsimd/internal/simd_test/compare_amd64_test.go | 106 +++-------------------------------------------------- src/simd/archsimd/internal/simd_test/convert_arm64_test.go | 39 +++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/convert_helpers_128_test.go | 1942 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/convert_helpers_test.go => src/simd/archsimd/internal/simd_test/convert_helpers_wider_test.go | 3270 ++++++++++++++++++++++------------------------------- src/simd/archsimd/internal/simd_test/helpers_test.go | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/reduce_arm64_helpers_test.go => src/simd/archsimd/internal/simd_test/reduce_helpers_arm64_test.go | 0 src/simd/archsimd/internal/simd_test/shift_128_test.go | 22 +++++++++++++++++++++- src/simd/archsimd/internal/simd_test/shift_arm64_test.go | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/shift_helpers_128_test.go | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/shift_helpers_arm64_test.go | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/shift_helpers_wider_test.go | 318 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/shift_test.go => src/simd/archsimd/internal/simd_test/shift_amd64_test.go | 61 +++++++++++++++++++++++++++++++++++++++++------------ src/simd/archsimd/internal/simd_test/shift_wasm_test.go | 19 +++++++++++++++++++ src/simd/archsimd/internal/simd_test/simd_amd64_test.go | 1567 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/simd_arm64_test.go | 39 +++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/simd_test.go | 1576 +++++------------------------------------------------ src/simd/archsimd/internal/simd_test/slicepart_128_test.go | 13 +++++++++++++ src/simd/archsimd/internal/simd_test/slicepart_wider_test.go | 28 ++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/ternary_arm64_helpers_test.go | 344 ----------------------------------------------------- src/simd/archsimd/internal/simd_test/ternary_helpers_128_test.go | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/ternary_helpers_test.go => src/simd/archsimd/internal/simd_test/ternary_helpers_wider_test.go | 205 ++++++++--------------------------------------------- src/simd/archsimd/internal/simd_test/unary_128_test.go | 36 +++++++++++++++++++++--------------- src/simd/archsimd/internal/simd_test/unary_helpers_128_test.go | 2 +- src/simd/archsimd/internal/simd_test/unary_test.go => src/simd/archsimd/internal/simd_test/unary_amd64_test.go | 126 ++++++++++++++++++++++++++++++----------------------- src/simd/archsimd/internal/simd_test/unary_wasm_test.go | 21 +++++++++++++++++++++ src/simd/archsimd/ops_internal_arm64.go | 8 ++++---- src/simd/archsimd/slice_gen_amd64.go | 96 ++++++++++++++++++++++++++++++----------------------- src/simd/internal/bridge/decls_amd64.go | 80 +++++++++++++++++++++++++++--------------------------- src/simd/internal/bridge/decls_arm64.go | 8 ++++---- src/simd/internal/bridge/decls_wasm.go | 8 ++++---- src/simd/internal/bridge/simd_emulated.go | 157 +++++++++++++++++++---------------------------------- src/simd/internal/bridge/simd_types_emulated.go | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/simd_emulated.go | 76 ++++++++++++++++++++++++++++++++++++++++++----------- src/simd/simd_test.go | 11 +++++++++++ src/simd/testdata/tostring_test.go | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/testdata_test.go | 20 +++++++++++++++++++- test/codegen/simd_arm64.go | 6 +++--- test/fixedbugs/issue80096.go | 18 ++++++++++++++++++ test/fixedbugs/issue80097.go | 23 +++++++++++++++++++++++ diff --git a/api/go1.27.txt b/api/go1.27.txt index 2520fba32f543734397a294a279bb0db581f4d5d..04b797d9f9a7c17bb545d2caf60f89b0a869c9df 100644 --- a/api/go1.27.txt +++ b/api/go1.27.txt @@ -278,6 +278,9 @@ pkg math/big, const Trunc RoundingMode #76821 pkg math/big, method (*Int) Divide(*Int, *Int, *Int, RoundingMode) (*Int, *Int) #76821 pkg math/rand/v2, method (*Rand) N[$0 intType]($0) $0 #77853 pkg net/http, type Server struct, DisableClientPriority bool #75500 +pkg net/http, const DefaultMaxHeaderValueCount = 500 #79936 +pkg net/http, const DefaultMaxHeaderValueCount ideal-int #79936 +pkg net/http, type Server struct, MaxHeaderValueCount int #79936 pkg net/http/httptest, func NewTestServer(testing.TB, http.Handler) *Server #76608 pkg net/url, method (*URL) Clone() *URL #73450 pkg net/url, method (Values) Clone() Values #73450 diff --git a/src/cmd/compile/internal/arm64/simdssa.go b/src/cmd/compile/internal/arm64/simdssa.go index dd89daf4f77665c3c357fc5e2ce45f2418abf52c..41ae2925425494c2aaae411c4a949631591faacb 100644 --- a/src/cmd/compile/internal/arm64/simdssa.go +++ b/src/cmd/compile/internal/arm64/simdssa.go @@ -272,8 +272,8 @@ case ssa.OpARM64VEXT16B: p = simdV21Imm(s, v, arm64.ARNG_16B) case ssa.OpARM64VMLA16B, - ssa.OpARM64VBIT16B, - ssa.OpARM64VBIF16B: + ssa.OpARM64VBIF16B, + ssa.OpARM64VBIT16B: p = simdV31ResultInArg0(s, v, arm64.ARNG_16B) case ssa.OpARM64VFMLA2D: diff --git a/src/cmd/compile/internal/dwarfgen/dwarf.go b/src/cmd/compile/internal/dwarfgen/dwarf.go index 79bf550cb1ec6872f309695dbcecffc4674eae08..3f654fabee7e97561d2c2565d2d3828f9ca6d12d 100644 --- a/src/cmd/compile/internal/dwarfgen/dwarf.go +++ b/src/cmd/compile/internal/dwarfgen/dwarf.go @@ -360,10 +360,14 @@ ChildIndex: -1, DictIndex: n.DictIndex, ClosureOffset: closureOffset(n, closureVars), } - if n.Esc() == ir.EscHeap { - if n.Heapaddr == nil { - base.Fatalf("invalid heap allocated var without Heapaddr") - } + if n.Esc() == ir.EscHeap && n.Heapaddr != nil { + // The variable was promoted to the heap and has a known heap + // address, so describe its location by dereferencing the pointer + // stored at its stack offset. A heap-escaped variable may have no + // Heapaddr if it was declared in unreachable code: escape analysis + // marks it as heap-allocated, but SSA generation skips the dead + // declaration and never allocates the address. In that case fall + // through and emit a conservative variable with no location list. debug := fn.DebugInfo.(*ssa.FuncDebug) list := createHeapDerefLocationList(n, debug.EntryID) dvar.PutLocationList = func(listSym, startPC dwarf.Sym) { diff --git a/src/cmd/compile/internal/escape/assign.go b/src/cmd/compile/internal/escape/assign.go index 6af53886831a1ebaebe3a14ad79f2601e3b00d95..27f13ca5aa2d39f312e3c17337cb0cb256f26ff2 100644 --- a/src/cmd/compile/internal/escape/assign.go +++ b/src/cmd/compile/internal/escape/assign.go @@ -50,6 +50,8 @@ e.mutate(n.X) case ir.OINDEXMAP: n := n.(*ir.IndexExpr) e.discard(n.X) + // Keys used in map assignments must escape. + // See "Hashing Pointers" doc in internal/runtime/maps/map.go. e.assignHeap(n.Index, "key of map put", n) } diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 56ec6641ac0c756b967aa18a7c0c2f2df8934735..8619e6010b0baa2ec8a6bfa112ea0a1592ae86b8 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -204,6 +204,8 @@ for _, arg := range call.Args { e.discard(arg) } e.discard(call.RType) + // Note: keys used in map deletes do not need to escape. + // See "Hashing Pointers" doc in internal/runtime/maps/map.go. case ir.OMIN, ir.OMAX: call := call.(*ir.CallExpr) diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index 1521c2edd176054253b8ea7dcaf0256b25feb5ef..468c4713f5b925a6153e11daf2859e63ee74919e 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -90,6 +90,8 @@ e.discard(n.Index) case ir.OINDEXMAP: n := n.(*ir.IndexExpr) e.discard(n.X) + // Keys used in map lookups do not need to escape. + // See "Hashing Pointers" doc in internal/runtime/maps/map.go. e.discard(n.Index) case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR: n := n.(*ir.SliceExpr) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 4ee30e6562c692508252cdcb3ebf9577b4591b2d..bd8c3c1a23f482d1a1cf56ec3d162ccfeb0989f0 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -912,7 +912,7 @@ return nil } if fn := inlCallee(callerfn, call.Fun, profile, false); fn != nil && typecheck.HaveInlineBody(fn) { - return mkinlcall(callerfn, call, fn, bigCaller, closureCalledOnce) + return mkinlcall(callerfn, call, fn, bigCaller, closureCalledOnce, profile) } return nil } @@ -960,7 +960,7 @@ var SSADumpInline = func(*ir.Func) {} // InlineCall allows the inliner implementation to be overridden. // If it returns nil, the function will not be inlined. -var InlineCall = func(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr { +var InlineCall = func(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int, profile *pgoir.Profile) *ir.InlinedCallExpr { base.Fatalf("inline.InlineCall not overridden") panic("unreachable") } @@ -1155,7 +1155,7 @@ // // The result of mkinlcall MUST be assigned back to n, e.g. // // n.Left = mkinlcall(n.Left, fn, isddd) -func mkinlcall(callerfn *ir.Func, n *ir.CallExpr, fn *ir.Func, bigCaller, closureCalledOnce bool) *ir.InlinedCallExpr { +func mkinlcall(callerfn *ir.Func, n *ir.CallExpr, fn *ir.Func, bigCaller, closureCalledOnce bool, profile *pgoir.Profile) *ir.InlinedCallExpr { ok, score, hot := canInlineCallExpr(callerfn, n, fn, bigCaller, closureCalledOnce, true) if !ok { return nil @@ -1236,7 +1236,7 @@ if base.Flag.LowerM > 2 { fmt.Printf("%v: Before inlining: %+v\n", ir.Line(n), n) } - res := InlineCall(callerfn, n, fn, inlIndex) + res := InlineCall(callerfn, n, fn, inlIndex, profile) if res == nil { base.FatalfAt(n.Pos(), "inlining call to %v failed", fn.Nname.DiagName()) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index a833ff73c799707c2c4ba2df779f0b37773d48f9..fab311e7e7a48d58c84aa8bc0be880c4c1087c30 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -19,6 +19,7 @@ "cmd/compile/internal/inline" "cmd/compile/internal/inline/interleaved" "cmd/compile/internal/ir" "cmd/compile/internal/objw" + "cmd/compile/internal/pgoir" "cmd/compile/internal/reflectdata" "cmd/compile/internal/staticinit" "cmd/compile/internal/typecheck" @@ -3572,9 +3573,6 @@ // Outline (if legal/profitable) global map inits. staticinit.OutlineMapInits(fn) - // Split large init function. - staticinit.SplitLargeInit(fn) - target.Inits = append(target.Inits, fn) } @@ -3682,7 +3680,7 @@ var inlgen = 0 // unifiedInlineCall implements inline.NewInline by re-reading the function // body from its Unified IR export data. -func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr { +func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int, profile *pgoir.Profile) *ir.InlinedCallExpr { pri, ok := bodyReaderFor(fn) if !ok { base.FatalfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn) @@ -3796,7 +3794,7 @@ // read in new function/method declarations, which could // potentially be recursively inlined themselves; but we shouldn't // need to read in the non-inlined bodies for the declarations // themselves. But currently it's an easy fix to #50552. - readBodies(typecheck.Target, true) + readBodies(typecheck.Target, true, profile) // Replace any "return" statements within the function body. var edit func(ir.Node) ir.Node diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 320fb3c75ac9adfea2ac035792716d6f64829ab7..9ec2e40e4883f57ca081c7b985b673b66468b6e3 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -80,7 +80,7 @@ // after a series of calls to LookupFunc, specifically invoking // readBodies to post-process any funcs on the "todoBodies" list // that were added as a result of the lookup operations. func PostLookupCleanup() { - readBodies(typecheck.Target, false) + readBodies(typecheck.Target, false, nil) } func lookupFunction(pkg *types.Pkg, symName string) (*ir.Func, error) { @@ -205,7 +205,7 @@ r := localPkgReader.newReader(pkgbits.SectionMeta, pkgbits.PrivateRootIdx, pkgbits.SyncPrivate) r.pkgInit(types.LocalPkg, target) - readBodies(target, false) + readBodies(target, false, nil) // Check that nothing snuck past typechecking. for _, fn := range target.Funcs { @@ -239,7 +239,7 @@ // // If duringInlining is true, then the inline.InlineDecls is called as // necessary on instantiations of imported generic functions, so their // inlining costs can be computed. -func readBodies(target *ir.Package, duringInlining bool) { +func readBodies(target *ir.Package, duringInlining bool, profile *pgoir.Profile) { var inlDecls []*ir.Func // Don't use range--bodyIdx can add closures to todoBodies. @@ -306,7 +306,7 @@ // it's pointless repeating them here. oldLowerM := base.Flag.LowerM base.Flag.LowerM = 0 - inline.CanInlineFuncs(inlDecls, nil) + inline.CanInlineFuncs(inlDecls, profile) base.Flag.LowerM = oldLowerM for _, fn := range inlDecls { diff --git a/src/cmd/compile/internal/pkginit/init.go b/src/cmd/compile/internal/pkginit/init.go index 9be15860a664da2fb12ab557854f161b8110e9e4..04f6a5d3509f85fee8d9c453ab51a3b8bee2fb63 100644 --- a/src/cmd/compile/internal/pkginit/init.go +++ b/src/cmd/compile/internal/pkginit/init.go @@ -87,7 +87,10 @@ } // Record user init functions. for _, fn := range typecheck.Target.Inits { - if staticinit.CanOptimize(fn) { + if fn.Sym().Name == "init" { + // Synthetic init function for initialization of package-scope + // variables. We can use staticinit to optimize away static + // assignments. s := staticinit.Schedule{ Plans: make(map[ir.Node]*staticinit.Plan), Temps: make(map[ir.Node]*ir.Name), diff --git a/src/cmd/compile/internal/ssa/_gen/AMD64.rules b/src/cmd/compile/internal/ssa/_gen/AMD64.rules index a58f5acb0d337f2184258edd712939eafa7a5c49..36c1e3354d6f06c36f62647af89470d8848f9c23 100644 --- a/src/cmd/compile/internal/ssa/_gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/_gen/AMD64.rules @@ -1745,61 +1745,61 @@ (VPORD512 (VPMOVMToVec64x8 (VCMPPD512 [3] x x)) (VPMOVMToVec64x8 (VCMPPD512 [3] y y))) => (VPMOVMToVec64x8 (VCMPPD512 [3] x y)) // Include these rules because you never know about rewrite order -(KANDQ (VCMPPD512 [3] x x) (VCMPPD512 [3] y y)) => (VCMPPD512 [3] x x) -(KANDD (VCMPPS512 [3] x x) (VCMPPS512 [3] y y)) => (VCMPPS512 [3] x y) +(KANDB (VCMPPD512 [3] x x) (VCMPPD512 [3] y y)) => (VCMPPD512 [3] x x) // 512 = 64x8 -> KANDB +(KANDW (VCMPPS512 [3] x x) (VCMPPS512 [3] y y)) => (VCMPPS512 [3] x y) // 512 = 32x16 -> KANDW // These larger simplifying rules must come before the smaller simplifying rules that might break them). // Rewrite rules for binary logical mask operations that apply to 8-bit elements (B, for bytes) of 128, 256, and 512-bit vectors -(VPAND128 (VPMOVMToVec8x16 x) (VPMOVMToVec8x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x16 (KANDB x y)) -(VPAND256 (VPMOVMToVec8x32 x) (VPMOVMToVec8x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x32 (KANDB x y)) -(VPANDD512 (VPMOVMToVec8x64 x) (VPMOVMToVec8x64 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x64 (KANDB x y)) +(VPAND128 (VPMOVMToVec8x16 x) (VPMOVMToVec8x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x16 (KANDW x y)) +(VPAND256 (VPMOVMToVec8x32 x) (VPMOVMToVec8x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x32 (KANDD x y)) +(VPANDD512 (VPMOVMToVec8x64 x) (VPMOVMToVec8x64 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x64 (KANDQ x y)) -(VPOR128 (VPMOVMToVec8x16 x) (VPMOVMToVec8x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x16 (KORB x y)) -(VPOR256 (VPMOVMToVec8x32 x) (VPMOVMToVec8x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x32 (KORB x y)) -(VPORD512 (VPMOVMToVec8x64 x) (VPMOVMToVec8x64 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x64 (KORB x y)) +(VPOR128 (VPMOVMToVec8x16 x) (VPMOVMToVec8x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x16 (KORW x y)) +(VPOR256 (VPMOVMToVec8x32 x) (VPMOVMToVec8x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x32 (KORD x y)) +(VPORD512 (VPMOVMToVec8x64 x) (VPMOVMToVec8x64 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x64 (KORQ x y)) -(VPXOR128 (VPMOVMToVec8x16 x) (VPMOVMToVec8x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x16 (KXORB x y)) -(VPXOR256 (VPMOVMToVec8x32 x) (VPMOVMToVec8x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x32 (KXORB x y)) -(VPXORD512 (VPMOVMToVec8x64 x) (VPMOVMToVec8x64 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x64 (KXORB x y)) +(VPXOR128 (VPMOVMToVec8x16 x) (VPMOVMToVec8x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x16 (KXORW x y)) +(VPXOR256 (VPMOVMToVec8x32 x) (VPMOVMToVec8x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x32 (KXORD x y)) +(VPXORD512 (VPMOVMToVec8x64 x) (VPMOVMToVec8x64 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec8x64 (KXORQ x y)) // Rewrite rules for binary logical mask operations that apply to 16-bit elements (W, for words) of 128, 256, and 512-bit vectors -(VPAND128 (VPMOVMToVec16x8 x) (VPMOVMToVec16x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x8 (KANDW x y)) +(VPAND128 (VPMOVMToVec16x8 x) (VPMOVMToVec16x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x8 (KANDB x y)) (VPAND256 (VPMOVMToVec16x16 x) (VPMOVMToVec16x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x16 (KANDW x y)) -(VPANDD512 (VPMOVMToVec16x32 x) (VPMOVMToVec16x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x32 (KANDW x y)) +(VPANDD512 (VPMOVMToVec16x32 x) (VPMOVMToVec16x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x32 (KANDD x y)) -(VPOR128 (VPMOVMToVec16x8 x) (VPMOVMToVec16x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x8 (KORW x y)) +(VPOR128 (VPMOVMToVec16x8 x) (VPMOVMToVec16x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x8 (KORB x y)) (VPOR256 (VPMOVMToVec16x16 x) (VPMOVMToVec16x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x16 (KORW x y)) -(VPORD512 (VPMOVMToVec16x32 x) (VPMOVMToVec16x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x32 (KORW x y)) +(VPORD512 (VPMOVMToVec16x32 x) (VPMOVMToVec16x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x32 (KORD x y)) -(VPXOR128 (VPMOVMToVec16x8 x) (VPMOVMToVec16x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x8 (KXORW x y)) +(VPXOR128 (VPMOVMToVec16x8 x) (VPMOVMToVec16x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x8 (KXORB x y)) (VPXOR256 (VPMOVMToVec16x16 x) (VPMOVMToVec16x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x16 (KXORW x y)) -(VPXORD512 (VPMOVMToVec16x32 x) (VPMOVMToVec16x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x32 (KXORW x y)) +(VPXORD512 (VPMOVMToVec16x32 x) (VPMOVMToVec16x32 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec16x32 (KXORD x y)) // Rewrite rules for binary logical mask operations that apply to 32-bit elements (D, for doublewords) of 128, 256, and 512-bit vectors -(VPAND128 (VPMOVMToVec32x4 x) (VPMOVMToVec32x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x4 (KANDD x y)) -(VPAND256 (VPMOVMToVec32x8 x) (VPMOVMToVec32x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x8 (KANDD x y)) -(VPANDD512 (VPMOVMToVec32x16 x) (VPMOVMToVec32x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x16 (KANDD x y)) +(VPAND128 (VPMOVMToVec32x4 x) (VPMOVMToVec32x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x4 (KANDB x y)) +(VPAND256 (VPMOVMToVec32x8 x) (VPMOVMToVec32x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x8 (KANDB x y)) +(VPANDD512 (VPMOVMToVec32x16 x) (VPMOVMToVec32x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x16 (KANDW x y)) -(VPOR128 (VPMOVMToVec32x4 x) (VPMOVMToVec32x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x4 (KORD x y)) -(VPOR256 (VPMOVMToVec32x8 x) (VPMOVMToVec32x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x8 (KORD x y)) -(VPORD512 (VPMOVMToVec32x16 x) (VPMOVMToVec32x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x16 (KORD x y)) +(VPOR128 (VPMOVMToVec32x4 x) (VPMOVMToVec32x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x4 (KORB x y)) +(VPOR256 (VPMOVMToVec32x8 x) (VPMOVMToVec32x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x8 (KORB x y)) +(VPORD512 (VPMOVMToVec32x16 x) (VPMOVMToVec32x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x16 (KORW x y)) -(VPXOR128 (VPMOVMToVec32x4 x) (VPMOVMToVec32x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x4 (KXORD x y)) -(VPXOR256 (VPMOVMToVec32x8 x) (VPMOVMToVec32x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x8 (KXORD x y)) -(VPXORD512 (VPMOVMToVec32x16 x) (VPMOVMToVec32x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x16 (KXORD x y)) +(VPXOR128 (VPMOVMToVec32x4 x) (VPMOVMToVec32x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x4 (KXORB x y)) +(VPXOR256 (VPMOVMToVec32x8 x) (VPMOVMToVec32x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x8 (KXORB x y)) +(VPXORD512 (VPMOVMToVec32x16 x) (VPMOVMToVec32x16 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec32x16 (KXORW x y)) // Rewrite rules for binary logical mask operations that apply to 64-bit elements (Q, for quadwords) of 128, 256, and 512-bit vectors -(VPAND128 (VPMOVMToVec64x2 x) (VPMOVMToVec64x2 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x2 (KANDQ x y)) -(VPAND256 (VPMOVMToVec64x4 x) (VPMOVMToVec64x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x4 (KANDQ x y)) -(VPANDD512 (VPMOVMToVec64x8 x) (VPMOVMToVec64x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x8 (KANDQ x y)) +(VPAND128 (VPMOVMToVec64x2 x) (VPMOVMToVec64x2 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x2 (KANDB x y)) +(VPAND256 (VPMOVMToVec64x4 x) (VPMOVMToVec64x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x4 (KANDB x y)) +(VPANDD512 (VPMOVMToVec64x8 x) (VPMOVMToVec64x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x8 (KANDB x y)) -(VPOR128 (VPMOVMToVec64x2 x) (VPMOVMToVec64x2 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x2 (KORQ x y)) -(VPOR256 (VPMOVMToVec64x4 x) (VPMOVMToVec64x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x4 (KORQ x y)) -(VPORD512 (VPMOVMToVec64x8 x) (VPMOVMToVec64x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x8 (KORQ x y)) +(VPOR128 (VPMOVMToVec64x2 x) (VPMOVMToVec64x2 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x2 (KORB x y)) +(VPOR256 (VPMOVMToVec64x4 x) (VPMOVMToVec64x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x4 (KORB x y)) +(VPORD512 (VPMOVMToVec64x8 x) (VPMOVMToVec64x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x8 (KORB x y)) -(VPXOR128 (VPMOVMToVec64x2 x) (VPMOVMToVec64x2 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x2 (KXORQ x y)) -(VPXOR256 (VPMOVMToVec64x4 x) (VPMOVMToVec64x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x4 (KXORQ x y)) -(VPXORD512 (VPMOVMToVec64x8 x) (VPMOVMToVec64x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x8 (KXORQ x y)) +(VPXOR128 (VPMOVMToVec64x2 x) (VPMOVMToVec64x2 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x2 (KXORB x y)) +(VPXOR256 (VPMOVMToVec64x4 x) (VPMOVMToVec64x4 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x4 (KXORB x y)) +(VPXORD512 (VPMOVMToVec64x8 x) (VPMOVMToVec64x8 y)) && v.Block.CPUfeatures.hasFeature(CPUavx512) => (VPMOVMToVec64x8 (KXORB x y)) (VPMOVVec8x16ToM (VPMOVMToVec8x16 x)) => x (VPMOVVec8x32ToM (VPMOVMToVec8x32 x)) => x diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index 84cf50a964152cfd7fe9d8e3e78c58c2829a0931..80e7c8e9b6ead32260bd3f0cbe368ac4a9d5aa0a 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -428,45 +428,45 @@ (Add(64|32|16|8) x x) => (Lsh(64|32|16|8)x64 x (Const64 [1])) // rewrite shifts of 8/16/32 bit consts into 64 bit consts to reduce // the number of the other rewrite rules for const shifts -(Lsh64x32 x (Const32 [c])) => (Lsh64x64 x (Const64 [int64(uint32(c))])) -(Lsh64x16 x (Const16 [c])) => (Lsh64x64 x (Const64 [int64(uint16(c))])) -(Lsh64x8 x (Const8 [c])) => (Lsh64x64 x (Const64 [int64(uint8(c))])) -(Rsh64x32 x (Const32 [c])) => (Rsh64x64 x (Const64 [int64(uint32(c))])) -(Rsh64x16 x (Const16 [c])) => (Rsh64x64 x (Const64 [int64(uint16(c))])) -(Rsh64x8 x (Const8 [c])) => (Rsh64x64 x (Const64 [int64(uint8(c))])) -(Rsh64Ux32 x (Const32 [c])) => (Rsh64Ux64 x (Const64 [int64(uint32(c))])) -(Rsh64Ux16 x (Const16 [c])) => (Rsh64Ux64 x (Const64 [int64(uint16(c))])) -(Rsh64Ux8 x (Const8 [c])) => (Rsh64Ux64 x (Const64 [int64(uint8(c))])) +(Lsh64x32 x (Const32 [c])) => (Lsh64x64 x (Const64 [int64(uint32(c))])) +(Lsh64x16 x (Const16 [c])) => (Lsh64x64 x (Const64 [int64(uint16(c))])) +(Lsh64x8 x (Const8 [c])) => (Lsh64x64 x (Const64 [int64(uint8(c))])) +(Rsh64x32 x (Const32 [c])) => (Rsh64x64 x (Const64 [int64(uint32(c))])) +(Rsh64x16 x (Const16 [c])) => (Rsh64x64 x (Const64 [int64(uint16(c))])) +(Rsh64x8 x (Const8 [c])) => (Rsh64x64 x (Const64 [int64(uint8(c))])) +(Rsh64Ux32 x (Const32 [c])) => (Rsh64Ux64 x (Const64 [int64(uint32(c))])) +(Rsh64Ux16 x (Const16 [c])) => (Rsh64Ux64 x (Const64 [int64(uint16(c))])) +(Rsh64Ux8 x (Const8 [c])) => (Rsh64Ux64 x (Const64 [int64(uint8(c))])) -(Lsh32x32 x (Const32 [c])) => (Lsh32x64 x (Const64 [int64(uint32(c))])) -(Lsh32x16 x (Const16 [c])) => (Lsh32x64 x (Const64 [int64(uint16(c))])) -(Lsh32x8 x (Const8 [c])) => (Lsh32x64 x (Const64 [int64(uint8(c))])) -(Rsh32x32 x (Const32 [c])) => (Rsh32x64 x (Const64 [int64(uint32(c))])) -(Rsh32x16 x (Const16 [c])) => (Rsh32x64 x (Const64 [int64(uint16(c))])) -(Rsh32x8 x (Const8 [c])) => (Rsh32x64 x (Const64 [int64(uint8(c))])) -(Rsh32Ux32 x (Const32 [c])) => (Rsh32Ux64 x (Const64 [int64(uint32(c))])) -(Rsh32Ux16 x (Const16 [c])) => (Rsh32Ux64 x (Const64 [int64(uint16(c))])) -(Rsh32Ux8 x (Const8 [c])) => (Rsh32Ux64 x (Const64 [int64(uint8(c))])) +(Lsh32x32 x (Const32 [c])) => (Lsh32x64 x (Const64 [int64(uint32(c))])) +(Lsh32x16 x (Const16 [c])) => (Lsh32x64 x (Const64 [int64(uint16(c))])) +(Lsh32x8 x (Const8 [c])) => (Lsh32x64 x (Const64 [int64(uint8(c))])) +(Rsh32x32 x (Const32 [c])) => (Rsh32x64 x (Const64 [int64(uint32(c))])) +(Rsh32x16 x (Const16 [c])) => (Rsh32x64 x (Const64 [int64(uint16(c))])) +(Rsh32x8 x (Const8 [c])) => (Rsh32x64 x (Const64 [int64(uint8(c))])) +(Rsh32Ux32 x (Const32 [c])) => (Rsh32Ux64 x (Const64 [int64(uint32(c))])) +(Rsh32Ux16 x (Const16 [c])) => (Rsh32Ux64 x (Const64 [int64(uint16(c))])) +(Rsh32Ux8 x (Const8 [c])) => (Rsh32Ux64 x (Const64 [int64(uint8(c))])) -(Lsh16x32 x (Const32 [c])) => (Lsh16x64 x (Const64 [int64(uint32(c))])) -(Lsh16x16 x (Const16 [c])) => (Lsh16x64 x (Const64 [int64(uint16(c))])) -(Lsh16x8 x (Const8 [c])) => (Lsh16x64 x (Const64 [int64(uint8(c))])) -(Rsh16x32 x (Const32 [c])) => (Rsh16x64 x (Const64 [int64(uint32(c))])) -(Rsh16x16 x (Const16 [c])) => (Rsh16x64 x (Const64 [int64(uint16(c))])) -(Rsh16x8 x (Const8 [c])) => (Rsh16x64 x (Const64 [int64(uint8(c))])) -(Rsh16Ux32 x (Const32 [c])) => (Rsh16Ux64 x (Const64 [int64(uint32(c))])) -(Rsh16Ux16 x (Const16 [c])) => (Rsh16Ux64 x (Const64 [int64(uint16(c))])) -(Rsh16Ux8 x (Const8 [c])) => (Rsh16Ux64 x (Const64 [int64(uint8(c))])) +(Lsh16x32 x (Const32 [c])) => (Lsh16x64 x (Const64 [int64(uint32(c))])) +(Lsh16x16 x (Const16 [c])) => (Lsh16x64 x (Const64 [int64(uint16(c))])) +(Lsh16x8 x (Const8 [c])) => (Lsh16x64 x (Const64 [int64(uint8(c))])) +(Rsh16x32 x (Const32 [c])) => (Rsh16x64 x (Const64 [int64(uint32(c))])) +(Rsh16x16 x (Const16 [c])) => (Rsh16x64 x (Const64 [int64(uint16(c))])) +(Rsh16x8 x (Const8 [c])) => (Rsh16x64 x (Const64 [int64(uint8(c))])) +(Rsh16Ux32 x (Const32 [c])) => (Rsh16Ux64 x (Const64 [int64(uint32(c))])) +(Rsh16Ux16 x (Const16 [c])) => (Rsh16Ux64 x (Const64 [int64(uint16(c))])) +(Rsh16Ux8 x (Const8 [c])) => (Rsh16Ux64 x (Const64 [int64(uint8(c))])) -(Lsh8x32 x (Const32 [c])) => (Lsh8x64 x (Const64 [int64(uint32(c))])) -(Lsh8x16 x (Const16 [c])) => (Lsh8x64 x (Const64 [int64(uint16(c))])) -(Lsh8x8 x (Const8 [c])) => (Lsh8x64 x (Const64 [int64(uint8(c))])) -(Rsh8x32 x (Const32 [c])) => (Rsh8x64 x (Const64 [int64(uint32(c))])) -(Rsh8x16 x (Const16 [c])) => (Rsh8x64 x (Const64 [int64(uint16(c))])) -(Rsh8x8 x (Const8 [c])) => (Rsh8x64 x (Const64 [int64(uint8(c))])) -(Rsh8Ux32 x (Const32 [c])) => (Rsh8Ux64 x (Const64 [int64(uint32(c))])) -(Rsh8Ux16 x (Const16 [c])) => (Rsh8Ux64 x (Const64 [int64(uint16(c))])) -(Rsh8Ux8 x (Const8 [c])) => (Rsh8Ux64 x (Const64 [int64(uint8(c))])) +(Lsh8x32 x (Const32 [c])) => (Lsh8x64 x (Const64 [int64(uint32(c))])) +(Lsh8x16 x (Const16 [c])) => (Lsh8x64 x (Const64 [int64(uint16(c))])) +(Lsh8x8 x (Const8 [c])) => (Lsh8x64 x (Const64 [int64(uint8(c))])) +(Rsh8x32 x (Const32 [c])) => (Rsh8x64 x (Const64 [int64(uint32(c))])) +(Rsh8x16 x (Const16 [c])) => (Rsh8x64 x (Const64 [int64(uint16(c))])) +(Rsh8x8 x (Const8 [c])) => (Rsh8x64 x (Const64 [int64(uint8(c))])) +(Rsh8Ux32 x (Const32 [c])) => (Rsh8Ux64 x (Const64 [int64(uint32(c))])) +(Rsh8Ux16 x (Const16 [c])) => (Rsh8Ux64 x (Const64 [int64(uint16(c))])) +(Rsh8Ux8 x (Const8 [c])) => (Rsh8Ux64 x (Const64 [int64(uint8(c))])) // shifts by zero (Lsh(64|32|16|8)x64 x (Const64 [0])) => x diff --git a/src/cmd/compile/internal/ssa/_gen/simdARM64.rules b/src/cmd/compile/internal/ssa/_gen/simdARM64.rules index fb85f663a411c00d928f518662ffc00b37d97600..131ab8eff5da23803e1528389d5dd58fa52e1db9 100644 --- a/src/cmd/compile/internal/ssa/_gen/simdARM64.rules +++ b/src/cmd/compile/internal/ssa/_gen/simdARM64.rules @@ -376,10 +376,10 @@ (XorUint8x16 ...) => (VEOR16B ...) // pureVreg (XorUint16x8 ...) => (VEOR16B ...) // pureVreg (XorUint32x4 ...) => (VEOR16B ...) // pureVreg (XorUint64x2 ...) => (VEOR16B ...) // pureVreg -(bitSelectInt8x16 ...) => (VBIT16B ...) // pureVreg -(VBIT16B x y (VNOT16B mask)) => (VBIF16B x y mask) // specialLower -(bitSelectNotInt8x16 ...) => (VBIF16B ...) // pureVreg +(bitSelectInt8x16 ...) => (VBIF16B ...) // pureVreg (VBIF16B x y (VNOT16B mask)) => (VBIT16B x y mask) // specialLower +(bitSelectNotInt8x16 ...) => (VBIT16B ...) // pureVreg +(VBIT16B x y (VNOT16B mask)) => (VBIF16B x y mask) // specialLower (broadcast1To2Float64x2 x) => (VDUPDbcast [0] x) // pureVreg (broadcast1To2Int64x2 x) => (VDUPDbcast [0] x) // pureVreg (broadcast1To2Uint64x2 x) => (VDUPDbcast [0] x) // pureVreg diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index ce7b6b003b7f99303fd851cd7ca1407f7b70d9ef..e37459035b8b0d5fc74abacbfc6e8b06d3b80e9c 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -240,10 +240,10 @@ case OpAMD64HMULQ: return rewriteValueAMD64_OpAMD64HMULQ(v) case OpAMD64HMULQU: return rewriteValueAMD64_OpAMD64HMULQU(v) - case OpAMD64KANDD: - return rewriteValueAMD64_OpAMD64KANDD(v) - case OpAMD64KANDQ: - return rewriteValueAMD64_OpAMD64KANDQ(v) + case OpAMD64KANDB: + return rewriteValueAMD64_OpAMD64KANDB(v) + case OpAMD64KANDW: + return rewriteValueAMD64_OpAMD64KANDW(v) case OpAMD64KMOVBk: return rewriteValueAMD64_OpAMD64KMOVBk(v) case OpAMD64KMOVDk: @@ -23758,50 +23758,50 @@ return true } return false } -func rewriteValueAMD64_OpAMD64KANDD(v *Value) bool { +func rewriteValueAMD64_OpAMD64KANDB(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] - // match: (KANDD (VCMPPS512 [3] x x) (VCMPPS512 [3] y y)) - // result: (VCMPPS512 [3] x y) + // match: (KANDB (VCMPPD512 [3] x x) (VCMPPD512 [3] y y)) + // result: (VCMPPD512 [3] x x) for { - if v_0.Op != OpAMD64VCMPPS512 || auxIntToUint8(v_0.AuxInt) != 3 { + if v_0.Op != OpAMD64VCMPPD512 || auxIntToUint8(v_0.AuxInt) != 3 { break } x := v_0.Args[1] - if x != v_0.Args[0] || v_1.Op != OpAMD64VCMPPS512 || auxIntToUint8(v_1.AuxInt) != 3 { + if x != v_0.Args[0] || v_1.Op != OpAMD64VCMPPD512 || auxIntToUint8(v_1.AuxInt) != 3 { break } y := v_1.Args[1] if y != v_1.Args[0] { break } - v.reset(OpAMD64VCMPPS512) + v.reset(OpAMD64VCMPPD512) v.AuxInt = uint8ToAuxInt(3) - v.AddArg2(x, y) + v.AddArg2(x, x) return true } return false } -func rewriteValueAMD64_OpAMD64KANDQ(v *Value) bool { +func rewriteValueAMD64_OpAMD64KANDW(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] - // match: (KANDQ (VCMPPD512 [3] x x) (VCMPPD512 [3] y y)) - // result: (VCMPPD512 [3] x x) + // match: (KANDW (VCMPPS512 [3] x x) (VCMPPS512 [3] y y)) + // result: (VCMPPS512 [3] x y) for { - if v_0.Op != OpAMD64VCMPPD512 || auxIntToUint8(v_0.AuxInt) != 3 { + if v_0.Op != OpAMD64VCMPPS512 || auxIntToUint8(v_0.AuxInt) != 3 { break } x := v_0.Args[1] - if x != v_0.Args[0] || v_1.Op != OpAMD64VCMPPD512 || auxIntToUint8(v_1.AuxInt) != 3 { + if x != v_0.Args[0] || v_1.Op != OpAMD64VCMPPS512 || auxIntToUint8(v_1.AuxInt) != 3 { break } y := v_1.Args[1] if y != v_1.Args[0] { break } - v.reset(OpAMD64VCMPPD512) + v.reset(OpAMD64VCMPPS512) v.AuxInt = uint8ToAuxInt(3) - v.AddArg2(x, x) + v.AddArg2(x, y) return true } return false @@ -58610,7 +58610,7 @@ b := v.Block typ := &b.Func.Config.Types // match: (VPAND128 (VPMOVMToVec8x16 x) (VPMOVMToVec8x16 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec8x16 (KANDB x y)) + // result: (VPMOVMToVec8x16 (KANDW x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec8x16 { @@ -58625,7 +58625,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec8x16) - v0 := b.NewValue0(v.Pos, OpAMD64KANDB, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDW, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -58634,7 +58634,7 @@ break } // match: (VPAND128 (VPMOVMToVec16x8 x) (VPMOVMToVec16x8 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec16x8 (KANDW x y)) + // result: (VPMOVMToVec16x8 (KANDB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec16x8 { @@ -58649,7 +58649,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec16x8) - v0 := b.NewValue0(v.Pos, OpAMD64KANDW, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -58658,7 +58658,7 @@ break } // match: (VPAND128 (VPMOVMToVec32x4 x) (VPMOVMToVec32x4 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec32x4 (KANDD x y)) + // result: (VPMOVMToVec32x4 (KANDB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec32x4 { @@ -58673,7 +58673,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec32x4) - v0 := b.NewValue0(v.Pos, OpAMD64KANDD, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -58682,7 +58682,7 @@ break } // match: (VPAND128 (VPMOVMToVec64x2 x) (VPMOVMToVec64x2 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec64x2 (KANDQ x y)) + // result: (VPMOVMToVec64x2 (KANDB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec64x2 { @@ -58697,7 +58697,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec64x2) - v0 := b.NewValue0(v.Pos, OpAMD64KANDQ, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -58814,7 +58814,7 @@ b := v.Block typ := &b.Func.Config.Types // match: (VPAND256 (VPMOVMToVec8x32 x) (VPMOVMToVec8x32 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec8x32 (KANDB x y)) + // result: (VPMOVMToVec8x32 (KANDD x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec8x32 { @@ -58829,7 +58829,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec8x32) - v0 := b.NewValue0(v.Pos, OpAMD64KANDB, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDD, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -58862,7 +58862,7 @@ break } // match: (VPAND256 (VPMOVMToVec32x8 x) (VPMOVMToVec32x8 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec32x8 (KANDD x y)) + // result: (VPMOVMToVec32x8 (KANDB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec32x8 { @@ -58877,7 +58877,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec32x8) - v0 := b.NewValue0(v.Pos, OpAMD64KANDD, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -58886,7 +58886,7 @@ break } // match: (VPAND256 (VPMOVMToVec64x4 x) (VPMOVMToVec64x4 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec64x4 (KANDQ x y)) + // result: (VPMOVMToVec64x4 (KANDB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec64x4 { @@ -58901,7 +58901,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec64x4) - v0 := b.NewValue0(v.Pos, OpAMD64KANDQ, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -59018,7 +59018,7 @@ b := v.Block typ := &b.Func.Config.Types // match: (VPANDD512 (VPMOVMToVec8x64 x) (VPMOVMToVec8x64 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec8x64 (KANDB x y)) + // result: (VPMOVMToVec8x64 (KANDQ x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec8x64 { @@ -59033,7 +59033,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec8x64) - v0 := b.NewValue0(v.Pos, OpAMD64KANDB, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDQ, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -59042,7 +59042,7 @@ break } // match: (VPANDD512 (VPMOVMToVec16x32 x) (VPMOVMToVec16x32 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec16x32 (KANDW x y)) + // result: (VPMOVMToVec16x32 (KANDD x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec16x32 { @@ -59057,7 +59057,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec16x32) - v0 := b.NewValue0(v.Pos, OpAMD64KANDW, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDD, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -59066,7 +59066,7 @@ break } // match: (VPANDD512 (VPMOVMToVec32x16 x) (VPMOVMToVec32x16 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec32x16 (KANDD x y)) + // result: (VPMOVMToVec32x16 (KANDW x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec32x16 { @@ -59081,7 +59081,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec32x16) - v0 := b.NewValue0(v.Pos, OpAMD64KANDD, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDW, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -59090,7 +59090,7 @@ break } // match: (VPANDD512 (VPMOVMToVec64x8 x) (VPMOVMToVec64x8 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec64x8 (KANDQ x y)) + // result: (VPMOVMToVec64x8 (KANDB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec64x8 { @@ -59105,7 +59105,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec64x8) - v0 := b.NewValue0(v.Pos, OpAMD64KANDQ, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KANDB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79414,7 +79414,7 @@ break } // match: (VPOR128 (VPMOVMToVec8x16 x) (VPMOVMToVec8x16 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec8x16 (KORB x y)) + // result: (VPMOVMToVec8x16 (KORW x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec8x16 { @@ -79429,7 +79429,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec8x16) - v0 := b.NewValue0(v.Pos, OpAMD64KORB, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORW, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79438,7 +79438,7 @@ break } // match: (VPOR128 (VPMOVMToVec16x8 x) (VPMOVMToVec16x8 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec16x8 (KORW x y)) + // result: (VPMOVMToVec16x8 (KORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec16x8 { @@ -79453,7 +79453,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec16x8) - v0 := b.NewValue0(v.Pos, OpAMD64KORW, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79462,7 +79462,7 @@ break } // match: (VPOR128 (VPMOVMToVec32x4 x) (VPMOVMToVec32x4 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec32x4 (KORD x y)) + // result: (VPMOVMToVec32x4 (KORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec32x4 { @@ -79477,7 +79477,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec32x4) - v0 := b.NewValue0(v.Pos, OpAMD64KORD, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79486,7 +79486,7 @@ break } // match: (VPOR128 (VPMOVMToVec64x2 x) (VPMOVMToVec64x2 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec64x2 (KORQ x y)) + // result: (VPMOVMToVec64x2 (KORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec64x2 { @@ -79501,7 +79501,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec64x2) - v0 := b.NewValue0(v.Pos, OpAMD64KORQ, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79586,7 +79586,7 @@ break } // match: (VPOR256 (VPMOVMToVec8x32 x) (VPMOVMToVec8x32 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec8x32 (KORB x y)) + // result: (VPMOVMToVec8x32 (KORD x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec8x32 { @@ -79601,7 +79601,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec8x32) - v0 := b.NewValue0(v.Pos, OpAMD64KORB, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORD, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79634,7 +79634,7 @@ break } // match: (VPOR256 (VPMOVMToVec32x8 x) (VPMOVMToVec32x8 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec32x8 (KORD x y)) + // result: (VPMOVMToVec32x8 (KORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec32x8 { @@ -79649,7 +79649,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec32x8) - v0 := b.NewValue0(v.Pos, OpAMD64KORD, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79658,7 +79658,7 @@ break } // match: (VPOR256 (VPMOVMToVec64x4 x) (VPMOVMToVec64x4 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec64x4 (KORQ x y)) + // result: (VPMOVMToVec64x4 (KORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec64x4 { @@ -79673,7 +79673,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec64x4) - v0 := b.NewValue0(v.Pos, OpAMD64KORQ, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79778,7 +79778,7 @@ break } // match: (VPORD512 (VPMOVMToVec8x64 x) (VPMOVMToVec8x64 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec8x64 (KORB x y)) + // result: (VPMOVMToVec8x64 (KORQ x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec8x64 { @@ -79793,7 +79793,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec8x64) - v0 := b.NewValue0(v.Pos, OpAMD64KORB, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORQ, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79802,7 +79802,7 @@ break } // match: (VPORD512 (VPMOVMToVec16x32 x) (VPMOVMToVec16x32 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec16x32 (KORW x y)) + // result: (VPMOVMToVec16x32 (KORD x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec16x32 { @@ -79817,7 +79817,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec16x32) - v0 := b.NewValue0(v.Pos, OpAMD64KORW, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORD, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79826,7 +79826,7 @@ break } // match: (VPORD512 (VPMOVMToVec32x16 x) (VPMOVMToVec32x16 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec32x16 (KORD x y)) + // result: (VPMOVMToVec32x16 (KORW x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec32x16 { @@ -79841,7 +79841,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec32x16) - v0 := b.NewValue0(v.Pos, OpAMD64KORD, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORW, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -79850,7 +79850,7 @@ break } // match: (VPORD512 (VPMOVMToVec64x8 x) (VPMOVMToVec64x8 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec64x8 (KORQ x y)) + // result: (VPMOVMToVec64x8 (KORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec64x8 { @@ -79865,7 +79865,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec64x8) - v0 := b.NewValue0(v.Pos, OpAMD64KORQ, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89648,7 +89648,7 @@ b := v.Block typ := &b.Func.Config.Types // match: (VPXOR128 (VPMOVMToVec8x16 x) (VPMOVMToVec8x16 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec8x16 (KXORB x y)) + // result: (VPMOVMToVec8x16 (KXORW x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec8x16 { @@ -89663,7 +89663,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec8x16) - v0 := b.NewValue0(v.Pos, OpAMD64KXORB, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORW, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89672,7 +89672,7 @@ break } // match: (VPXOR128 (VPMOVMToVec16x8 x) (VPMOVMToVec16x8 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec16x8 (KXORW x y)) + // result: (VPMOVMToVec16x8 (KXORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec16x8 { @@ -89687,7 +89687,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec16x8) - v0 := b.NewValue0(v.Pos, OpAMD64KXORW, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89696,7 +89696,7 @@ break } // match: (VPXOR128 (VPMOVMToVec32x4 x) (VPMOVMToVec32x4 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec32x4 (KXORD x y)) + // result: (VPMOVMToVec32x4 (KXORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec32x4 { @@ -89711,7 +89711,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec32x4) - v0 := b.NewValue0(v.Pos, OpAMD64KXORD, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89720,7 +89720,7 @@ break } // match: (VPXOR128 (VPMOVMToVec64x2 x) (VPMOVMToVec64x2 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec64x2 (KXORQ x y)) + // result: (VPMOVMToVec64x2 (KXORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec64x2 { @@ -89735,7 +89735,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec64x2) - v0 := b.NewValue0(v.Pos, OpAMD64KXORQ, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89776,7 +89776,7 @@ b := v.Block typ := &b.Func.Config.Types // match: (VPXOR256 (VPMOVMToVec8x32 x) (VPMOVMToVec8x32 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec8x32 (KXORB x y)) + // result: (VPMOVMToVec8x32 (KXORD x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec8x32 { @@ -89791,7 +89791,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec8x32) - v0 := b.NewValue0(v.Pos, OpAMD64KXORB, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORD, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89824,7 +89824,7 @@ break } // match: (VPXOR256 (VPMOVMToVec32x8 x) (VPMOVMToVec32x8 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec32x8 (KXORD x y)) + // result: (VPMOVMToVec32x8 (KXORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec32x8 { @@ -89839,7 +89839,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec32x8) - v0 := b.NewValue0(v.Pos, OpAMD64KXORD, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89848,7 +89848,7 @@ break } // match: (VPXOR256 (VPMOVMToVec64x4 x) (VPMOVMToVec64x4 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec64x4 (KXORQ x y)) + // result: (VPMOVMToVec64x4 (KXORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec64x4 { @@ -89863,7 +89863,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec64x4) - v0 := b.NewValue0(v.Pos, OpAMD64KXORQ, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89904,7 +89904,7 @@ b := v.Block typ := &b.Func.Config.Types // match: (VPXORD512 (VPMOVMToVec8x64 x) (VPMOVMToVec8x64 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec8x64 (KXORB x y)) + // result: (VPMOVMToVec8x64 (KXORQ x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec8x64 { @@ -89919,7 +89919,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec8x64) - v0 := b.NewValue0(v.Pos, OpAMD64KXORB, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORQ, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89928,7 +89928,7 @@ break } // match: (VPXORD512 (VPMOVMToVec16x32 x) (VPMOVMToVec16x32 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec16x32 (KXORW x y)) + // result: (VPMOVMToVec16x32 (KXORD x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec16x32 { @@ -89943,7 +89943,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec16x32) - v0 := b.NewValue0(v.Pos, OpAMD64KXORW, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORD, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89952,7 +89952,7 @@ break } // match: (VPXORD512 (VPMOVMToVec32x16 x) (VPMOVMToVec32x16 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec32x16 (KXORD x y)) + // result: (VPMOVMToVec32x16 (KXORW x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec32x16 { @@ -89967,7 +89967,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec32x16) - v0 := b.NewValue0(v.Pos, OpAMD64KXORD, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORW, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true @@ -89976,7 +89976,7 @@ break } // match: (VPXORD512 (VPMOVMToVec64x8 x) (VPMOVMToVec64x8 y)) // cond: v.Block.CPUfeatures.hasFeature(CPUavx512) - // result: (VPMOVMToVec64x8 (KXORQ x y)) + // result: (VPMOVMToVec64x8 (KXORB x y)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpAMD64VPMOVMToVec64x8 { @@ -89991,7 +89991,7 @@ if !(v.Block.CPUfeatures.hasFeature(CPUavx512)) { continue } v.reset(OpAMD64VPMOVMToVec64x8) - v0 := b.NewValue0(v.Pos, OpAMD64KXORQ, typ.Mask) + v0 := b.NewValue0(v.Pos, OpAMD64KXORB, typ.Mask) v0.AddArg2(x, y) v.AddArg(v0) return true diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index d93a2042124e4cc8bc00a039d1c2a59f0dac0fb4..26d94b9ebf83fdeea856bb38d4ffacc154c10a94 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -2276,10 +2276,10 @@ return true case OpZeroSIMD: return rewriteValueARM64_OpZeroSIMD(v) case OpbitSelectInt8x16: - v.Op = OpARM64VBIT16B + v.Op = OpARM64VBIF16B return true case OpbitSelectNotInt8x16: - v.Op = OpARM64VBIF16B + v.Op = OpARM64VBIT16B return true case Opbroadcast1To16Int8x16: return rewriteValueARM64_Opbroadcast1To16Int8x16(v) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index e39e08d7aed5e536533cf463358e6a1bd4a761b3..a5e0478a40acb75071ced29fe9d6237f240664ef 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -14845,17 +14845,16 @@ func rewriteValuegeneric_OpLsh16x16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh16x16 x (Const16 [c])) - // result: (Lsh16x64 x (Const64 [int64(uint16(c))])) + // match: (Lsh16x16 x (Const16 [c])) + // result: (Lsh16x64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpLsh16x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -14897,17 +14896,16 @@ func rewriteValuegeneric_OpLsh16x32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh16x32 x (Const32 [c])) - // result: (Lsh16x64 x (Const64 [int64(uint32(c))])) + // match: (Lsh16x32 x (Const32 [c])) + // result: (Lsh16x64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpLsh16x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -15324,17 +15322,16 @@ func rewriteValuegeneric_OpLsh16x8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh16x8 x (Const8 [c])) - // result: (Lsh16x64 x (Const64 [int64(uint8(c))])) + // match: (Lsh16x8 x (Const8 [c])) + // result: (Lsh16x64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpLsh16x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -15376,17 +15373,16 @@ func rewriteValuegeneric_OpLsh32x16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh32x16 x (Const16 [c])) - // result: (Lsh32x64 x (Const64 [int64(uint16(c))])) + // match: (Lsh32x16 x (Const16 [c])) + // result: (Lsh32x64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpLsh32x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -15428,17 +15424,16 @@ func rewriteValuegeneric_OpLsh32x32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh32x32 x (Const32 [c])) - // result: (Lsh32x64 x (Const64 [int64(uint32(c))])) + // match: (Lsh32x32 x (Const32 [c])) + // result: (Lsh32x64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpLsh32x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -15855,17 +15850,16 @@ func rewriteValuegeneric_OpLsh32x8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh32x8 x (Const8 [c])) - // result: (Lsh32x64 x (Const64 [int64(uint8(c))])) + // match: (Lsh32x8 x (Const8 [c])) + // result: (Lsh32x64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpLsh32x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -15907,17 +15901,16 @@ func rewriteValuegeneric_OpLsh64x16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh64x16 x (Const16 [c])) - // result: (Lsh64x64 x (Const64 [int64(uint16(c))])) + // match: (Lsh64x16 x (Const16 [c])) + // result: (Lsh64x64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpLsh64x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -15959,17 +15952,16 @@ func rewriteValuegeneric_OpLsh64x32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh64x32 x (Const32 [c])) - // result: (Lsh64x64 x (Const64 [int64(uint32(c))])) + // match: (Lsh64x32 x (Const32 [c])) + // result: (Lsh64x64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpLsh64x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -16386,17 +16378,16 @@ func rewriteValuegeneric_OpLsh64x8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh64x8 x (Const8 [c])) - // result: (Lsh64x64 x (Const64 [int64(uint8(c))])) + // match: (Lsh64x8 x (Const8 [c])) + // result: (Lsh64x64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpLsh64x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -16438,17 +16429,16 @@ func rewriteValuegeneric_OpLsh8x16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh8x16 x (Const16 [c])) - // result: (Lsh8x64 x (Const64 [int64(uint16(c))])) + // match: (Lsh8x16 x (Const16 [c])) + // result: (Lsh8x64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpLsh8x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -16490,17 +16480,16 @@ func rewriteValuegeneric_OpLsh8x32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh8x32 x (Const32 [c])) - // result: (Lsh8x64 x (Const64 [int64(uint32(c))])) + // match: (Lsh8x32 x (Const32 [c])) + // result: (Lsh8x64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpLsh8x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -16917,17 +16906,16 @@ func rewriteValuegeneric_OpLsh8x8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Lsh8x8 x (Const8 [c])) - // result: (Lsh8x64 x (Const64 [int64(uint8(c))])) + // match: (Lsh8x8 x (Const8 [c])) + // result: (Lsh8x64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpLsh8x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -30221,17 +30209,16 @@ func rewriteValuegeneric_OpRsh16Ux16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh16Ux16 x (Const16 [c])) - // result: (Rsh16Ux64 x (Const64 [int64(uint16(c))])) + // match: (Rsh16Ux16 x (Const16 [c])) + // result: (Rsh16Ux64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpRsh16Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -30273,17 +30260,16 @@ func rewriteValuegeneric_OpRsh16Ux32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh16Ux32 x (Const32 [c])) - // result: (Rsh16Ux64 x (Const64 [int64(uint32(c))])) + // match: (Rsh16Ux32 x (Const32 [c])) + // result: (Rsh16Ux64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpRsh16Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -30530,17 +30516,16 @@ func rewriteValuegeneric_OpRsh16Ux8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh16Ux8 x (Const8 [c])) - // result: (Rsh16Ux64 x (Const64 [int64(uint8(c))])) + // match: (Rsh16Ux8 x (Const8 [c])) + // result: (Rsh16Ux64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpRsh16Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -30582,17 +30567,16 @@ func rewriteValuegeneric_OpRsh16x16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh16x16 x (Const16 [c])) - // result: (Rsh16x64 x (Const64 [int64(uint16(c))])) + // match: (Rsh16x16 x (Const16 [c])) + // result: (Rsh16x64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpRsh16x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -30634,17 +30618,16 @@ func rewriteValuegeneric_OpRsh16x32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh16x32 x (Const32 [c])) - // result: (Rsh16x64 x (Const64 [int64(uint32(c))])) + // match: (Rsh16x32 x (Const32 [c])) + // result: (Rsh16x64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpRsh16x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -30795,17 +30778,16 @@ func rewriteValuegeneric_OpRsh16x8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh16x8 x (Const8 [c])) - // result: (Rsh16x64 x (Const64 [int64(uint8(c))])) + // match: (Rsh16x8 x (Const8 [c])) + // result: (Rsh16x64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpRsh16x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -30847,17 +30829,16 @@ func rewriteValuegeneric_OpRsh32Ux16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh32Ux16 x (Const16 [c])) - // result: (Rsh32Ux64 x (Const64 [int64(uint16(c))])) + // match: (Rsh32Ux16 x (Const16 [c])) + // result: (Rsh32Ux64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpRsh32Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -30899,17 +30880,16 @@ func rewriteValuegeneric_OpRsh32Ux32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh32Ux32 x (Const32 [c])) - // result: (Rsh32Ux64 x (Const64 [int64(uint32(c))])) + // match: (Rsh32Ux32 x (Const32 [c])) + // result: (Rsh32Ux64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpRsh32Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -31174,17 +31154,16 @@ func rewriteValuegeneric_OpRsh32Ux8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh32Ux8 x (Const8 [c])) - // result: (Rsh32Ux64 x (Const64 [int64(uint8(c))])) + // match: (Rsh32Ux8 x (Const8 [c])) + // result: (Rsh32Ux64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpRsh32Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -31226,17 +31205,16 @@ func rewriteValuegeneric_OpRsh32x16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh32x16 x (Const16 [c])) - // result: (Rsh32x64 x (Const64 [int64(uint16(c))])) + // match: (Rsh32x16 x (Const16 [c])) + // result: (Rsh32x64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpRsh32x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -31278,17 +31256,16 @@ func rewriteValuegeneric_OpRsh32x32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh32x32 x (Const32 [c])) - // result: (Rsh32x64 x (Const64 [int64(uint32(c))])) + // match: (Rsh32x32 x (Const32 [c])) + // result: (Rsh32x64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpRsh32x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -31457,17 +31434,16 @@ func rewriteValuegeneric_OpRsh32x8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh32x8 x (Const8 [c])) - // result: (Rsh32x64 x (Const64 [int64(uint8(c))])) + // match: (Rsh32x8 x (Const8 [c])) + // result: (Rsh32x64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpRsh32x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -31509,17 +31485,16 @@ func rewriteValuegeneric_OpRsh64Ux16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh64Ux16 x (Const16 [c])) - // result: (Rsh64Ux64 x (Const64 [int64(uint16(c))])) + // match: (Rsh64Ux16 x (Const16 [c])) + // result: (Rsh64Ux64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpRsh64Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -31561,17 +31536,16 @@ func rewriteValuegeneric_OpRsh64Ux32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh64Ux32 x (Const32 [c])) - // result: (Rsh64Ux64 x (Const64 [int64(uint32(c))])) + // match: (Rsh64Ux32 x (Const32 [c])) + // result: (Rsh64Ux64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpRsh64Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -31854,17 +31828,16 @@ func rewriteValuegeneric_OpRsh64Ux8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh64Ux8 x (Const8 [c])) - // result: (Rsh64Ux64 x (Const64 [int64(uint8(c))])) + // match: (Rsh64Ux8 x (Const8 [c])) + // result: (Rsh64Ux64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpRsh64Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -31906,17 +31879,16 @@ func rewriteValuegeneric_OpRsh64x16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh64x16 x (Const16 [c])) - // result: (Rsh64x64 x (Const64 [int64(uint16(c))])) + // match: (Rsh64x16 x (Const16 [c])) + // result: (Rsh64x64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpRsh64x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -31958,17 +31930,16 @@ func rewriteValuegeneric_OpRsh64x32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh64x32 x (Const32 [c])) - // result: (Rsh64x64 x (Const64 [int64(uint32(c))])) + // match: (Rsh64x32 x (Const32 [c])) + // result: (Rsh64x64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpRsh64x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -32155,17 +32126,16 @@ func rewriteValuegeneric_OpRsh64x8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh64x8 x (Const8 [c])) - // result: (Rsh64x64 x (Const64 [int64(uint8(c))])) + // match: (Rsh64x8 x (Const8 [c])) + // result: (Rsh64x64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpRsh64x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -32207,17 +32177,16 @@ func rewriteValuegeneric_OpRsh8Ux16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh8Ux16 x (Const16 [c])) - // result: (Rsh8Ux64 x (Const64 [int64(uint16(c))])) + // match: (Rsh8Ux16 x (Const16 [c])) + // result: (Rsh8Ux64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpRsh8Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -32259,17 +32228,16 @@ func rewriteValuegeneric_OpRsh8Ux32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh8Ux32 x (Const32 [c])) - // result: (Rsh8Ux64 x (Const64 [int64(uint32(c))])) + // match: (Rsh8Ux32 x (Const32 [c])) + // result: (Rsh8Ux64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpRsh8Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -32498,17 +32466,16 @@ func rewriteValuegeneric_OpRsh8Ux8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh8Ux8 x (Const8 [c])) - // result: (Rsh8Ux64 x (Const64 [int64(uint8(c))])) + // match: (Rsh8Ux8 x (Const8 [c])) + // result: (Rsh8Ux64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpRsh8Ux64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true @@ -32550,17 +32517,16 @@ func rewriteValuegeneric_OpRsh8x16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh8x16 x (Const16 [c])) - // result: (Rsh8x64 x (Const64 [int64(uint16(c))])) + // match: (Rsh8x16 x (Const16 [c])) + // result: (Rsh8x64 x (Const64 [int64(uint16(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst16 { break } c := auxIntToInt16(v_1.AuxInt) v.reset(OpRsh8x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint16(c))) v.AddArg2(x, v0) return true @@ -32602,17 +32568,16 @@ func rewriteValuegeneric_OpRsh8x32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh8x32 x (Const32 [c])) - // result: (Rsh8x64 x (Const64 [int64(uint32(c))])) + // match: (Rsh8x32 x (Const32 [c])) + // result: (Rsh8x64 x (Const64 [int64(uint32(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst32 { break } c := auxIntToInt32(v_1.AuxInt) v.reset(OpRsh8x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint32(c))) v.AddArg2(x, v0) return true @@ -32744,17 +32709,16 @@ func rewriteValuegeneric_OpRsh8x8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (Rsh8x8 x (Const8 [c])) - // result: (Rsh8x64 x (Const64 [int64(uint8(c))])) + // match: (Rsh8x8 x (Const8 [c])) + // result: (Rsh8x64 x (Const64 [int64(uint8(c))])) for { - t := v.Type x := v_0 if v_1.Op != OpConst8 { break } c := auxIntToInt8(v_1.AuxInt) v.reset(OpRsh8x64) - v0 := b.NewValue0(v.Pos, OpConst64, t) + v0 := b.NewValue0(v.Pos, OpConst64, types.Types[types.TUINT64]) v0.AuxInt = int64ToAuxInt(int64(uint8(c))) v.AddArg2(x, v0) return true diff --git a/src/cmd/compile/internal/ssagen/simdWasmintrinsics.go b/src/cmd/compile/internal/ssagen/simdWasmintrinsics.go index f50d94717823451a353445e0a8d652e4dc33f9da..9a92cf8eedbe830ea6d2406ed1c4a797b5e75beb 100644 --- a/src/cmd/compile/internal/ssagen/simdWasmintrinsics.go +++ b/src/cmd/compile/internal/ssagen/simdWasmintrinsics.go @@ -43,7 +43,7 @@ makeSimdOp1Imm8 := func(op ssa.Op, immLimit uint64) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { t := n.Type() - if args[1].Op == ssa.OpConst8 { + if args[1].Op == ssa.OpConst8 && uint64(args[1].AuxInt) < immLimit { return s.newValue1I(op, t, args[1].AuxInt, args[0]) } return immJumpTableN(s, args[1], n, immLimit, func(sNew *state, idx int) { @@ -56,7 +56,7 @@ makeSimdOp2Imm8 := func(op ssa.Op, immLimit uint64) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { t := types.TypeVec128 - if args[1].Op == ssa.OpConst8 { + if args[1].Op == ssa.OpConst8 && uint64(args[1].AuxInt) < immLimit { return s.newValue2I(op, t, args[1].AuxInt, args[0], args[2]) } return immJumpTableN(s, args[1], n, immLimit, func(sNew *state, idx int) { diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go index 42a2276414177e8a4aad87e5641679322f1fcc56..c9546313bb50aa98e5ef6fe099faca5e61afeff4 100644 --- a/src/cmd/compile/internal/staticinit/sched.go +++ b/src/cmd/compile/internal/staticinit/sched.go @@ -9,7 +9,6 @@ "fmt" "go/constant" "go/token" "os" - "slices" "strings" "cmd/compile/internal/base" @@ -1248,54 +1247,3 @@ if base.Debug.WrapGlobalMapDbg > 1 { fmt.Fprintf(os.Stderr, "=-= outlined %v map initializations\n", outlined) } } - -const maxInitStatements = 1000 - -// SplitLargeInit breaks up a large "init" function into smaller chunks to avoid slow compilation. -func SplitLargeInit(fn *ir.Func) { - if !fn.IsPackageInit() || len(fn.Body) <= maxInitStatements { - return - } - var calls []ir.Node - for chunk := range slices.Chunk(fn.Body, maxInitStatements) { - varInitFn := generateVarInitFunc(chunk) - ir.WithFunc(fn, func() { - calls = append(calls, typecheck.Call(varInitFn.Pos(), varInitFn.Nname, nil, false)) - }) - } - fn.Body = calls -} - -// CanOptimize reports whether the given fn can be optimized for static assignments. -func CanOptimize(fn *ir.Func) bool { - name := fn.Sym().Name - return name == "init" || strings.HasPrefix(name, varInitFuncPrefix) -} - -// varInitGen is a counter used to uniquify compiler-generated functions for initializing variables. -var varInitGen int - -const varInitFuncPrefix = "init.var." - -// Create a new function that will (eventually) have this form: -// -// func init.var.%d() { -// ... -// } -func generateVarInitFunc(body []ir.Node) *ir.Func { - pos := base.AutogeneratedPos - base.Pos = pos - - sym := typecheck.LookupNum(varInitFuncPrefix, varInitGen) - varInitGen++ - - fn := ir.NewFunc(pos, pos, sym, types.NewSignature(nil, nil, nil)) - fn.SetInlinabilityChecked(true) // suppress inlining; otherwise, we end up with giant init eventually. - fn.SetWrapper(true) // less disruptive on backtraces. - typecheck.DeclFunc(fn) - - fn.Body = body - typecheck.FinishFuncBody() - - return fn -} diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index daa6b506eb43eb4520c9cf5e68f1f2dbc763ee16..4dbd47299936133639688e6ea649f443d03d7871 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -257,7 +257,7 @@ if Ti == nil { if cause != nil { var detail string if isInterfacePtr(Tu) { - detail = check.sprintf("type %s is pointer to interface, not interface", T) + detail = check.interfacePtrError(T) } else { detail = check.sprintf("%s is not an interface", T) } diff --git a/src/cmd/compile/internal/types2/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go index 06e2827782534d83aa6096d16fa84f306a4c5582..94d31ba4ee3dd542de477f2253537b41d955f269 100644 --- a/src/cmd/compile/internal/types2/stdlib_test.go +++ b/src/cmd/compile/internal/types2/stdlib_test.go @@ -356,6 +356,7 @@ var excluded = map[string]bool{ "builtin": true, "cmd/compile/internal/ssa/_gen": true, "crypto/internal/cryptotest/wycheproof/_schema": true, + "crypto/internal/cryptotest/x509limbo/_schema": true, "runtime/_mkmalloc": true, "simd/archsimd/_gen/midway": true, "simd/archsimd/_gen/sgutil": true, diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index e635b3852735d4f0834bb9c8f6be3a7066e2d863..fa220fc277ea18e00cdf5f8fca3af75c493258d7 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -336,7 +336,11 @@ w.tParamList(t.TypeParams().list()) } if w.ctxt != nil { // TODO(gri) do we need to print the alias type name, too? - w.typ(Unalias(t.obj.typ)) + typ := Unalias(t.obj.typ) + if typ == nil { + panic("known implementation limitation: encountered an incomplete alias (see go.dev/issue/78296)") + } + w.typ(typ) } default: diff --git a/src/cmd/compile/internal/walk/assign.go b/src/cmd/compile/internal/walk/assign.go index d7ce684e00eb7435b5c5c2074ac5835b87551d2a..6c4c13ef824b826b018a635eef27f6d958f0548a 100644 --- a/src/cmd/compile/internal/walk/assign.go +++ b/src/cmd/compile/internal/walk/assign.go @@ -167,11 +167,9 @@ walkExprListSafe(n.Lhs, init) r.X = walkExpr(r.X, init) r.Index = walkExpr(r.Index, init) - map_ := r.X t := r.X.Type() fast := mapfast(t) key := mapKeyArg(fast, r, r.Index, false) - args := []ir.Node{reflectdata.IndexMapRType(base.Pos, r), map_, key} // from: // a,b = m[i] @@ -180,14 +178,15 @@ // var,b = mapaccess2*(t, m, i) // a = *var a := n.Lhs[0] - var mapFn ir.Node - if t.Elem().Size() > abi.ZeroValSize { - args = append(args, reflectdata.ZeroAddr(t.Elem().Size())) - mapFn = mapfn("mapaccess2_fat", t, true) + var call *ir.CallExpr + if w := t.Elem().Size(); w <= abi.ZeroValSize { + fn := mapfn(mapaccess2[fast], t, false) + call = mkcall1(fn, fn.Type().ResultsTuple(), init, reflectdata.IndexMapRType(base.Pos, r), r.X, key) } else { - mapFn = mapfn(mapaccess[fast], t, false) + fn := mapfn("mapaccess2_fat", t, true) + z := reflectdata.ZeroAddr(w) + call = mkcall1(fn, fn.Type().ResultsTuple(), init, reflectdata.IndexMapRType(base.Pos, r), r.X, key, z) } - call := mkcall1(mapFn, mapFn.Type().ResultsTuple(), init, args...) // mapaccess2* returns a typed bool, but due to spec changes, // the boolean result of i.(T) is now untyped so we make it the diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 8d3f96df94cb91ee2f224a9f224689b73f94ceab..296d43f1d92da4461a9527cf53b7810276095afd 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -914,43 +914,20 @@ fast := mapfast(t) key := mapKeyArg(fast, n, n.Index, n.Assigned) args := []ir.Node{reflectdata.IndexMapRType(base.Pos, n), map_, key} - if n.Assigned { - mapFn := mapfn(mapassign[fast], t, false) - call := mkcall1(mapFn, nil, init, args...) - call.SetType(types.NewPtr(t.Elem())) - call.MarkNonNil() // mapassign always return non-nil pointers. - star := ir.NewStarExpr(base.Pos, call) - star.SetType(t.Elem()) - star.SetTypecheck(1) - return star - } - - // from: - // m[i] - // to: - // var, _ = mapaccess2*(t, m, i) - // *var var mapFn ir.Node - if t.Elem().Size() > abi.ZeroValSize { + switch { + case n.Assigned: + mapFn = mapfn(mapassign[fast], t, false) + case t.Elem().Size() > abi.ZeroValSize: args = append(args, reflectdata.ZeroAddr(t.Elem().Size())) - mapFn = mapfn("mapaccess2_fat", t, true) - } else { - mapFn = mapfn(mapaccess[fast], t, false) + mapFn = mapfn("mapaccess1_fat", t, true) + default: + mapFn = mapfn(mapaccess1[fast], t, false) } - call := mkcall1(mapFn, mapFn.Type().ResultsTuple(), init, args...) - - var_ := typecheck.TempAt(base.Pos, ir.CurFunc, types.NewPtr(t.Elem())) - var_.SetTypecheck(1) - var_.MarkNonNil() // mapaccess always returns a non-nill pointer - - bool_ := typecheck.TempAt(base.Pos, ir.CurFunc, types.Types[types.TBOOL]) - bool_.SetTypecheck(1) - - r := ir.NewAssignListStmt(base.Pos, ir.OAS2FUNC, []ir.Node{var_, bool_}, []ir.Node{call}) - r.SetTypecheck(1) - init.Append(walkExpr(r, init)) - - star := ir.NewStarExpr(base.Pos, var_) + call := mkcall1(mapFn, nil, init, args...) + call.SetType(types.NewPtr(t.Elem())) + call.MarkNonNil() // mapaccess1* and mapassign always return non-nil pointers. + star := ir.NewStarExpr(base.Pos, call) star.SetType(t.Elem()) star.SetTypecheck(1) return star diff --git a/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go index 6f59d5802cb476c42a0a9cca547188405d0e989a..259649019a414bc8588a93f4ce8b291c0e94e10f 100644 --- a/src/cmd/compile/internal/walk/walk.go +++ b/src/cmd/compile/internal/walk/walk.go @@ -184,7 +184,8 @@ func mkmapnames(base string, ptr string) mapnames { return mapnames{base, base + "_fast32", base + "_fast32" + ptr, base + "_fast64", base + "_fast64" + ptr, base + "_faststr"} } -var mapaccess = mkmapnames("mapaccess2", "") +var mapaccess1 = mkmapnames("mapaccess1", "") +var mapaccess2 = mkmapnames("mapaccess2", "") var mapassign = mkmapnames("mapassign", "ptr") var mapdelete = mkmapnames("mapdelete", "") diff --git a/src/cmd/internal/objfile/elf.go b/src/cmd/internal/objfile/elf.go index 6988cea9362d19435ac48407440b1bda9bbb0049..6da31906b5f9a4e10d90a6aee2ce960fdc4587a9 100644 --- a/src/cmd/internal/objfile/elf.go +++ b/src/cmd/internal/objfile/elf.go @@ -52,7 +52,11 @@ sym.Code = 'T' case elf.SHF_ALLOC: sym.Code = 'R' case elf.SHF_ALLOC | elf.SHF_WRITE: - sym.Code = 'D' + if sect.Type == elf.SHT_NOBITS { + sym.Code = 'B' + } else { + sym.Code = 'D' + } } } if elf.ST_BIND(s.Info) == elf.STB_LOCAL { diff --git a/src/cmd/internal/objfile/pe.go b/src/cmd/internal/objfile/pe.go index e94821298f1ba744e2b7ad179df2b130dbad239d..7bbfaa54d1c4aa166aa754514ce76cca0b7f1031 100644 --- a/src/cmd/internal/objfile/pe.go +++ b/src/cmd/internal/objfile/pe.go @@ -34,6 +34,25 @@ var addrs []uint64 imageBase, _ := f.imageBase() + // When using internal linking we currently put BSS into the + // .data section. In order to set the B code correctly, + // we find the address of runtime.bss. Anything in a data section + // past runtime.bss is a BSS symbol. + // + // Just checking the section size in insufficient, + // as it will be rounded up to the page size. + // That is, there can be BSS symbols at the end of the page + // that holds the last data symbols. + var bssAddr uint32 + var bssSectionNumber int16 + for _, s := range f.pe.Symbols { + if s.Name == "runtime.bss" { + bssAddr = s.Value + bssSectionNumber = s.SectionNumber + break + } + } + var syms []Sym for _, s := range f.pe.Symbols { const ( @@ -67,6 +86,12 @@ sym.Code = 'T' case ch&data != 0: if ch&permW == 0 { sym.Code = 'R' + } else if bssSectionNumber == s.SectionNumber && bssAddr > 0 && s.Value >= bssAddr { + // Past runtime.bss is BSS. + sym.Code = 'B' + } else if s.Value >= sect.Size { + // Past section size is BSS. + sym.Code = 'B' } else { sym.Code = 'D' } diff --git a/src/cmd/internal/script/scripttest/setup.go b/src/cmd/internal/script/scripttest/setup.go index f9d650af1c48fc52753cee55fba697e71e14853c..07cf8ea2f914af5018191a9c71112aaf2fef3341 100644 --- a/src/cmd/internal/script/scripttest/setup.go +++ b/src/cmd/internal/script/scripttest/setup.go @@ -6,8 +6,10 @@ // Package scripttest adapts the script engine for use in tests. package scripttest import ( + "errors" "internal/testenv" "io" + "io/fs" "os" "path/filepath" "runtime" @@ -83,7 +85,7 @@ if runtime.GOOS == "windows" { exename += ".exe" } toolpath := filepath.Join(testgoroot, toolsub, exename) - if err := os.Remove(toolpath); err != nil { + if err := os.Remove(toolpath); err != nil && !errors.Is(err, fs.ErrNotExist) { t.Fatalf("removing %s: %v", toolpath, err) } linkOrCopy(t, newtoolpath, toolpath) diff --git a/src/cmd/link/internal/ld/ld_test.go b/src/cmd/link/internal/ld/ld_test.go index a2a3d18fd674c38196859cbcf28b5641450e2767..3cddcf797fc95825a587e074bc09469cc4865c8b 100644 --- a/src/cmd/link/internal/ld/ld_test.go +++ b/src/cmd/link/internal/ld/ld_test.go @@ -199,6 +199,49 @@ testWindowsBuildmodeCSharedASLR(t, false) }) } +func TestWindowsBuildmodeCSharedTrailingDotOutput(t *testing.T) { + if runtime.GOOS != "windows" { + t.Skip("skipping windows only test") + } + + t.Parallel() + testenv.MustHaveGoBuild(t) + testenv.MustHaveCGO(t) + testenv.MustHaveBuildMode(t, "c-shared") + + dir := t.TempDir() + srcfile := filepath.Join(dir, "test.go") + objfile := filepath.Join(dir, "mypackage.") + linktmp := filepath.Join(dir, "linktmp") + if err := os.Mkdir(linktmp, 0777); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(srcfile, []byte(`package main +import "C" + +//export Hello +func Hello() {} + +func main() {} +`), 0666); err != nil { + t.Fatal(err) + } + + argv := []string{"build", "-buildmode=c-shared", "-o", objfile, "-ldflags", "-tmpdir=" + linktmp, srcfile} + out, err := testenv.Command(t, testenv.GoToolPath(t), argv...).CombinedOutput() + if err != nil { + t.Fatalf("build failure: %s\n%s\n", err, string(out)) + } + + def, err := os.ReadFile(filepath.Join(linktmp, "export_file.def")) + if err != nil { + t.Fatal(err) + } + if want := []byte("LIBRARY \"mypackage.\"\n"); !bytes.HasPrefix(def, want) { + t.Fatalf("export_file.def begins with %q, want %q", def, want) + } +} + func testWindowsBuildmodeCSharedASLR(t *testing.T, useASLR bool) { t.Parallel() testenv.MustHaveGoBuild(t) diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 8a01d1f2df3fc5320104e505f7adb9af953706d4..8376ddefe56bb7090bdd91aae552d2761fdf8a5d 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -1920,7 +1920,7 @@ fname = filepath.Join(*flagTmpdir, "export_file.def") var buf bytes.Buffer if ctxt.BuildMode == BuildModeCShared { - fmt.Fprintf(&buf, "LIBRARY %s\n", libName) + fmt.Fprintf(&buf, "LIBRARY %q\n", libName) } buf.WriteString("EXPORTS\n") diff --git a/src/cmd/nm/nm_test.go b/src/cmd/nm/nm_test.go index 424ac72e228db81ba583df66ee023aaf34af240c..ce1bd7cd5747d7a28c85ff84046d3a25a94b2a82 100644 --- a/src/cmd/nm/nm_test.go +++ b/src/cmd/nm/nm_test.go @@ -116,6 +116,8 @@ "runtime.rodata": "R", "runtime.erodata": "R", "runtime.epclntab": "R", "runtime.noptrdata": "D", + "runtime.bss": "B", + "runtime.noptrbss": "B", } out, err = testenv.Command(t, testenv.Executable(t), exe).CombinedOutput() diff --git a/src/cmd/nm/script_test.go b/src/cmd/nm/script_test.go new file mode 100644 index 0000000000000000000000000000000000000000..025817d652556e51be8571830e32cd93d405e61a --- /dev/null +++ b/src/cmd/nm/script_test.go @@ -0,0 +1,35 @@ +// 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. + +package main + +import ( + "cmd/internal/script/scripttest" + "flag" + "internal/testenv" + "os" + "testing" +) + +//go:generate go test cmd/nm -v -run=TestScript/README --fixreadme + +var fixReadme = flag.Bool("fixreadme", false, "if true, update README for script tests") + +func TestScript(t *testing.T) { + testenv.MustHaveGoBuild(t) + + testExe, testExeErr := os.Executable() + + repls := []scripttest.ToolReplacement{} + if testExeErr == nil { + repls = []scripttest.ToolReplacement{ + scripttest.ToolReplacement{ + ToolName: "nm", + ReplacementPath: testExe, + EnvVar: "GO_NMTEST_IS_NM=1", + }, + } + } + scripttest.RunToolScriptTest(t, repls, "testdata/script", *fixReadme) +} diff --git a/src/cmd/nm/testdata/script/README b/src/cmd/nm/testdata/script/README new file mode 100644 index 0000000000000000000000000000000000000000..9ec997a138f0f27be42882b819a1531f63600394 --- /dev/null +++ b/src/cmd/nm/testdata/script/README @@ -0,0 +1,286 @@ +This file is generated by 'go generate'. DO NOT EDIT. + +This directory holds test scripts *.txt run during 'go test cmd/'. +To run a specific script foo.txt + + go test cmd/ -run=Script/^foo$ + +In general script files should have short names: a few words, + not whole sentences. +The first word should be the general category of behavior being tested, +often the name of a go subcommand (build, link, compile, ...) or concept (vendor, pattern). + +Each script is a text archive (go doc internal/txtar). +The script begins with an actual command script to run +followed by the content of zero or more supporting files to +create in the script's temporary file system before it starts executing. + +As an example, run_hello.txt says: + + # hello world + go run hello.go + stderr 'hello world' + ! stdout . + + -- hello.go -- + package main + func main() { println("hello world") } + +Each script runs in a fresh temporary work directory tree, available to scripts as $WORK. +Scripts also have access to other environment variables, including: + + GOARCH= + GOOS= + TMPDIR=$WORK/tmp + devnull= + goversion= + +On Plan 9, the variables $path and $home are set instead of $PATH and $HOME. +On Windows, the variables $USERPROFILE and $TMP are set instead of +$HOME and $TMPDIR. + +The lines at the top of the script are a sequence of commands to be executed by +a small script engine configured in .../cmd/internal/script/scripttest/run.go (not the system shell). + +Each line of a script is parsed into a sequence of space-separated command +words, with environment variable expansion within each word and # marking +an end-of-line comment. Additional variables named ':' and '/' are expanded +within script arguments (expanding to the value of os.PathListSeparator and +os.PathSeparator respectively) but are not inherited in subprocess environments. + +Adding single quotes around text keeps spaces in that text from being treated +as word separators and also disables environment variable expansion. Inside a +single-quoted block of text, a repeated single quote indicates a literal single +quote, as in: + + 'Don''t communicate by sharing memory.' + +A line beginning with # is a comment and conventionally explains what is being +done or tested at the start of a new section of the script. + +Commands are executed one at a time, and errors are checked for each command; +if any command fails unexpectedly, no subsequent commands in the script are +executed. The command prefix ! indicates that the command on the rest of the +line (typically go or a matching predicate) must fail instead of succeeding. +The command prefix ? indicates that the command may or may not succeed, but the +script should continue regardless. + +The command prefix [cond] indicates that the command on the rest of the line +should only run when the condition is satisfied. + +A condition can be negated: [!root] means to run the rest of the line only if +the user is not root. Multiple conditions may be given for a single command, +for example, '[linux] [amd64] skip'. The command will run if all conditions are +satisfied. + +When TestScript runs a script and the script fails, by default TestScript shows +the execution of the most recent phase of the script (since the last # comment) +and only shows the # comments for earlier phases. + +Note also that in reported output, the actual name of the per-script temporary directory +has been consistently replaced with the literal string $WORK. + +The available commands are: +cat files... + concatenate files and print to the script's stdout buffer + + +cc args... + run the platform C compiler + + +cd dir + change the working directory + + +chmod perm paths... + change file mode bits + + Changes the permissions of the named files or directories to + be equal to perm. + Only numerical permissions are supported. + +cmp [-q] file1 file2 + compare files for differences + + By convention, file1 is the actual data and file2 is the + expected data. + The command succeeds if the file contents are identical. + File1 can be 'stdout' or 'stderr' to compare the stdout or + stderr buffer from the most recent command. + +cmpenv [-q] file1 file2 + compare files for differences, with environment expansion + + By convention, file1 is the actual data and file2 is the + expected data. + The command succeeds if the file contents are identical + after substituting variables from the script environment. + File1 can be 'stdout' or 'stderr' to compare the script's + stdout or stderr buffer. + +cp src... dst + copy files to a target file or directory + + src can include 'stdout' or 'stderr' to copy from the + script's stdout or stderr buffer. + +echo string... + display a line of text + + +env [key[=value]...] + set or log the values of environment variables + + With no arguments, print the script environment to the log. + Otherwise, add the listed key=value pairs to the environment + or print the listed keys. + +exec program [args...] [&] + run an executable program with arguments + + Note that 'exec' does not terminate the script (unlike Unix + shells). + +exists [-readonly] [-exec] file... + check that files exist + + +go [args...] [&] + run the 'go' program provided by the script host + + +grep [-count=N] [-q] 'pattern' file + find lines in a file that match a pattern + + The command succeeds if at least one match (or the exact + count, if given) is found. + The -q flag suppresses printing of matches. + +help [-v] name... + log help text for commands and conditions + + To display help for a specific condition, enclose it in + brackets: 'help [amd64]'. + To display complete documentation when listing all commands, + pass the -v flag. + +mkdir path... + create directories, if they do not already exist + + Unlike Unix mkdir, parent directories are always created if + needed. + +mv old new + rename a file or directory to a new path + + OS-specific restrictions may apply when old and new are in + different directories. + +replace [old new]... file + replace strings in a file + + The 'old' and 'new' arguments are unquoted as if in quoted + Go strings. + +rm path... + remove a file or directory + + If the path is a directory, its contents are removed + recursively. + +skip [msg] + skip the current test + + +sleep duration [&] + sleep for a specified duration + + The duration must be given as a Go time.Duration string. + +stderr [-count=N] [-q] 'pattern' file + find lines in the stderr buffer that match a pattern + + The command succeeds if at least one match (or the exact + count, if given) is found. + The -q flag suppresses printing of matches. + +stdout [-count=N] [-q] 'pattern' file + find lines in the stdout buffer that match a pattern + + The command succeeds if at least one match (or the exact + count, if given) is found. + The -q flag suppresses printing of matches. + +stop [msg] + stop execution of the script + + The message is written to the script log, but no error is + reported from the script engine. + +symlink path -> target + create a symlink + + Creates path as a symlink to target. + The '->' token (like in 'ls -l' output on Unix) is required. + +wait + wait for completion of background commands + + Waits for all background commands to complete. + The output (and any error) from each command is printed to + the log in the order in which the commands were started. + After the call to 'wait', the script's stdout and stderr + buffers contain the concatenation of the background + commands' outputs. + + + +The available conditions are: +[GOARCH:*] + runtime.GOARCH == +[GODEBUG:*] + GODEBUG contains +[GOEXPERIMENT:*] + GOEXPERIMENT is enabled +[GOOS:*] + runtime.GOOS == +[asan] + GOOS/GOARCH supports -asan +[buildmode:*] + go supports -buildmode= +[cgo] + host CGO_ENABLED +[cgolinkext] + platform requires external linking for cgo +[compiler:*] + runtime.Compiler == +[cross] + cmd/go GOOS/GOARCH != GOHOSTOS/GOHOSTARCH +[exec:*] + names an executable in the test binary's PATH +[fuzz] + GOOS/GOARCH supports -fuzz +[fuzz-instrumented] + GOOS/GOARCH supports -fuzz with instrumentation +[go-builder] + GO_BUILDER_NAME is non-empty +[link] + testenv.HasLink() +[msan] + GOOS/GOARCH supports -msan +[mustlinkext] + platform always requires external linking +[pielinkext] + platform requires external linking for PIE +[race] + GOOS/GOARCH supports -race +[root] + os.Geteuid() == 0 +[short] + testing.Short() +[symlink] + testenv.HasSymlink() +[verbose] + testing.Verbose() + diff --git a/src/cmd/nm/testdata/script/issue77301.txt b/src/cmd/nm/testdata/script/issue77301.txt new file mode 100644 index 0000000000000000000000000000000000000000..aa0c9c60db81c0a6d82762d2276417e7e5463911 --- /dev/null +++ b/src/cmd/nm/testdata/script/issue77301.txt @@ -0,0 +1,20 @@ +# Tests the correct symbol placement for initialized vs uninitialized +# globals in the respective sections: https://go.dev/issues/77301 +go build -o main +exec go tool nm main +stdout 'B main.globalUninitialized' +stdout 'D main.globalInitialized' + +-- go.mod -- +module nm_bss_symbol_check + +-- main.go -- +package main + +var globalUninitialized int64 +var globalInitialized int64 = 42 + +func main() { + println(globalUninitialized) + println(globalInitialized) +} diff --git a/src/crypto/internal/cryptotest/fetchmodule.go b/src/crypto/internal/cryptotest/fetchmodule.go index 5df340a697531e63a71c6a8000fcfa27bdba21ab..738c638a778e50ccc8b49914f85055b7b8bab234 100644 --- a/src/crypto/internal/cryptotest/fetchmodule.go +++ b/src/crypto/internal/cryptotest/fetchmodule.go @@ -43,15 +43,21 @@ } t.Logf("fetching %s@%s\n", module, version) - output, err := testenv.Command(t, testenv.GoToolPath(t), "mod", "download", "-json", module+"@"+version).CombinedOutput() + cmd := testenv.Command(t, testenv.GoToolPath(t), "mod", "download", "-json", module+"@"+version) + var stderr bytes.Buffer + cmd.Stderr = &stderr + output, err := cmd.Output() if err != nil { - t.Fatalf("failed to download %s@%s: %s\n%s\n", module, version, err, output) + t.Fatalf("failed to download %s@%s: %s\nstdout:\n%s\nstderr:\n%s\n", module, version, err, output, stderr.Bytes()) + } + if stderr.Len() > 0 { + t.Logf("go mod download stderr:\n%s", stderr.Bytes()) } var j struct { Dir string } if err := json.Unmarshal(output, &j); err != nil { - t.Fatalf("failed to parse 'go mod download': %s\n%s\n", err, output) + t.Fatalf("failed to parse 'go mod download': %s\nstdout:\n%s\nstderr:\n%s\n", err, output, stderr.Bytes()) } return j.Dir diff --git a/src/crypto/internal/cryptotest/x509limbo/_schema/go.mod b/src/crypto/internal/cryptotest/x509limbo/_schema/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..bfb3d5ce6bca92b1dd67d81376a3e43919d39c3a --- /dev/null +++ b/src/crypto/internal/cryptotest/x509limbo/_schema/go.mod @@ -0,0 +1,14 @@ +module crypto/internal/cryptotest/x509limbo/_schema + +go 1.26 + +require github.com/atombender/go-jsonschema v0.23.1 + +require ( + dario.cat/mergo v1.0.2 // indirect + github.com/goccy/go-yaml v1.19.2 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/sanity-io/litter v1.5.8 // indirect + github.com/sosodev/duration v1.4.0 // indirect +) diff --git a/src/crypto/internal/cryptotest/x509limbo/_schema/go.sum b/src/crypto/internal/cryptotest/x509limbo/_schema/go.sum new file mode 100644 index 0000000000000000000000000000000000000000..fef1f2b29fb0b3f6a1d0c5522977922b4d71630c --- /dev/null +++ b/src/crypto/internal/cryptotest/x509limbo/_schema/go.sum @@ -0,0 +1,25 @@ +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= +github.com/atombender/go-jsonschema v0.23.1 h1:hpj94ehS+gpVvd1NJSTE0BMtWIpab06ObCz57rwo37c= +github.com/atombender/go-jsonschema v0.23.1/go.mod h1:4SrgNrwGKijxhewvpPQ8HKEbin5Q2N4Tk+pFKW77HEk= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sanity-io/litter v1.5.8 h1:uM/2lKrWdGbRXDrIq08Lh9XtVYoeGtcQxk9rtQ7+rYg= +github.com/sanity-io/litter v1.5.8/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/sosodev/duration v1.4.0 h1:35ed0KiVFriGHHzZZJaZLgmTEEICIyt8Sx0RQfj9IjE= +github.com/sosodev/duration v1.4.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= +github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/src/crypto/internal/cryptotest/x509limbo/_schema/schema_gen.go b/src/crypto/internal/cryptotest/x509limbo/_schema/schema_gen.go new file mode 100644 index 0000000000000000000000000000000000000000..8911228c5ab2bdf945a3f7ebe0b12f0dedb7aee6 --- /dev/null +++ b/src/crypto/internal/cryptotest/x509limbo/_schema/schema_gen.go @@ -0,0 +1,125 @@ +// 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. + +// A stand-alone Go module that generates ../schema.go using the upstream +// x509-limbo JSON schema document. +// +// We maintain this in a separate Go module and vendor the resulting generated +// .go code to avoid the standard library taking a direct dependency on the +// C2SP/x509-limbo or atombender/go-jsonschema modules. + +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + + "github.com/atombender/go-jsonschema/pkg/generator" +) + +// x509LimboVersion is the github.com/C2SP/x509-limbo module version used to +// generate ../schema.go. Update this to retarget a different upstream revision. +// +// x509-limbo publishes no Go packages, so we can't pin the version via a +// `require` directive (any `go mod tidy` would drop it) or a `tool` directive +// (no main package). Instead we fetch the module on demand via `go mod +// download` below, and propagate this constant to ../schemaversion.go so the +// runtime test fetches a matching revision. +const x509LimboVersion = "v0.0.0-20260522003327-feb7caccc1af" + +const x509LimboModule = "github.com/C2SP/x509-limbo" + +func main() { + limboDir, err := downloadModuleDir(x509LimboModule, x509LimboVersion) + if err != nil { + log.Fatalf("failed to fetch %s@%s: %v", x509LimboModule, x509LimboVersion, err) + } + + outputName := "schema.go" + gen, err := generator.New(generator.Config{ + DefaultPackageName: "x509limbo", + DefaultOutputName: outputName, + Tags: []string{"json"}, + Warner: func(message string) { + log.Printf("go-jsonschema: %s", message) + }, + }) + if err != nil { + log.Fatal(err) + } + + schemaFile := filepath.Join(limboDir, "limbo-schema.json") + if err := gen.DoFile(schemaFile); err != nil { + log.Fatalf("error processing limbo-schema.json: %v\n", err) + } + + sources, err := gen.Sources() + if err != nil { + log.Fatalf("error generating sources: %v\n", err) + } + if sourceCount := len(sources); sourceCount != 1 { + log.Fatalf("expected to generate 1 source file, got %d\n", sourceCount) + } + content, ok := sources[outputName] + if !ok { + log.Fatalf("missing generated %q output file source", outputName) + } + outFile := filepath.Join("../", outputName) + if err := os.WriteFile(outFile, content, 0644); err != nil { + log.Fatalf("error writing file %s: %v\n", outFile, err) + } + + // Write a sibling file recording the x509-limbo module version that the + // generated schema.go was produced against. The x509limbo package uses + // this constant to fetch matching test vectors at runtime. We avoid reading + // go.sum at test time because it might not be available (e.g. if the test + // binary was copied to a remote machine). + const versionFile = "../schemaversion.go" + versionSrc := fmt.Sprintf(`// 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. + +// Code generated by _schema/schema_gen.go, DO NOT EDIT. + +package x509limbo + +// X509LimboModule is the module path of the upstream x509-limbo project. +const X509LimboModule = %q + +// X509LimboVersion is the X509LimboModule version that schema.go was +// generated against. +const X509LimboVersion = %q +`, x509LimboModule, x509LimboVersion) + if err := os.WriteFile(versionFile, []byte(versionSrc), 0644); err != nil { + log.Fatalf("writing %s: %v", versionFile, err) + } +} + +// downloadModuleDir runs `go mod download` to ensure module@version is present +// in the module cache and returns the directory containing its source tree. +func downloadModuleDir(module, version string) (string, error) { + cmd := exec.Command("go", "mod", "download", "-json", module+"@"+version) + var stderr bytes.Buffer + cmd.Stderr = &stderr + out, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("%w\n%s", err, stderr.String()) + } + var info struct { + Dir string + Error string + } + if err := json.Unmarshal(out, &info); err != nil { + return "", fmt.Errorf("parsing go mod download output: %w", err) + } + if info.Error != "" { + return "", fmt.Errorf("%s", info.Error) + } + return info.Dir, nil +} diff --git a/src/crypto/internal/cryptotest/x509limbo/schema.go b/src/crypto/internal/cryptotest/x509limbo/schema.go new file mode 100644 index 0000000000000000000000000000000000000000..769a07525ebf10ebdfc76a8469ccaf8de27bdcce --- /dev/null +++ b/src/crypto/internal/cryptotest/x509limbo/schema.go @@ -0,0 +1,591 @@ +// Code generated by github.com/atombender/go-jsonschema, DO NOT EDIT. + +package x509limbo + +import "encoding/json" +import "errors" +import "fmt" +import "reflect" +import "regexp" +import "time" + +type ExpectedResult string + +const ExpectedResultFAILURE ExpectedResult = "FAILURE" +const ExpectedResultSUCCESS ExpectedResult = "SUCCESS" + +var enumValues_ExpectedResult = []interface{}{ + "SUCCESS", + "FAILURE", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ExpectedResult) UnmarshalJSON(value []byte) error { + var v string + if err := json.Unmarshal(value, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_ExpectedResult { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ExpectedResult, v) + } + *j = ExpectedResult(v) + return nil +} + +type Feature string + +const FeatureDenialOfService Feature = "denial-of-service" +const FeatureHasCertPolicies Feature = "has-cert-policies" +const FeatureHasCrl Feature = "has-crl" +const FeatureHasPolicyConstraints Feature = "has-policy-constraints" +const FeatureMaxChainDepth Feature = "max-chain-depth" +const FeatureNameConstraintDn Feature = "name-constraint-dn" +const FeatureNoCertPolicies Feature = "no-cert-policies" +const FeaturePedanticPublicSuffixWildcard Feature = "pedantic-public-suffix-wildcard" +const FeaturePedanticRfc5280 Feature = "pedantic-rfc5280" +const FeaturePedanticSerialNumber Feature = "pedantic-serial-number" +const FeaturePedanticWebpkiEku Feature = "pedantic-webpki-eku" +const FeaturePedanticWebpkiSubscriberKey Feature = "pedantic-webpki-subscriber-key" +const FeatureRfc5280IncompatibleWithWebpki Feature = "rfc5280-incompatible-with-webpki" + +var enumValues_Feature = []interface{}{ + "has-policy-constraints", + "has-cert-policies", + "no-cert-policies", + "pedantic-public-suffix-wildcard", + "name-constraint-dn", + "pedantic-webpki-subscriber-key", + "pedantic-webpki-eku", + "pedantic-serial-number", + "max-chain-depth", + "pedantic-rfc5280", + "rfc5280-incompatible-with-webpki", + "denial-of-service", + "has-crl", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Feature) UnmarshalJSON(value []byte) error { + var v string + if err := json.Unmarshal(value, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_Feature { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_Feature, v) + } + *j = Feature(v) + return nil +} + +type Importance string + +const ImportanceCritical Importance = "critical" +const ImportanceHigh Importance = "high" +const ImportanceLow Importance = "low" +const ImportanceMedium Importance = "medium" +const ImportanceUndetermined Importance = "undetermined" + +var enumValues_Importance = []interface{}{ + "undetermined", + "low", + "medium", + "high", + "critical", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Importance) UnmarshalJSON(value []byte) error { + var v string + if err := json.Unmarshal(value, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_Importance { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_Importance, v) + } + *j = Importance(v) + return nil +} + +type KeyUsage string + +const KeyUsageCRLSign KeyUsage = "cRLSign" +const KeyUsageContentCommitment KeyUsage = "contentCommitment" +const KeyUsageDataEncipherment KeyUsage = "dataEncipherment" +const KeyUsageDecipherOnly KeyUsage = "decipherOnly" +const KeyUsageDigitalSignature KeyUsage = "digitalSignature" +const KeyUsageEncipherOnly KeyUsage = "encipherOnly" +const KeyUsageKeyAgreement KeyUsage = "keyAgreement" +const KeyUsageKeyCertSign KeyUsage = "keyCertSign" +const KeyUsageKeyEncipherment KeyUsage = "keyEncipherment" + +var enumValues_KeyUsage = []interface{}{ + "digitalSignature", + "contentCommitment", + "keyEncipherment", + "dataEncipherment", + "keyAgreement", + "keyCertSign", + "cRLSign", + "encipherOnly", + "decipherOnly", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *KeyUsage) UnmarshalJSON(value []byte) error { + var v string + if err := json.Unmarshal(value, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_KeyUsage { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_KeyUsage, v) + } + *j = KeyUsage(v) + return nil +} + +type KnownEKUs string + +const KnownEKUsAnyExtendedKeyUsage KnownEKUs = "anyExtendedKeyUsage" +const KnownEKUsClientAuth KnownEKUs = "clientAuth" +const KnownEKUsCodeSigning KnownEKUs = "codeSigning" +const KnownEKUsEmailProtection KnownEKUs = "emailProtection" +const KnownEKUsOCSPSigning KnownEKUs = "OCSPSigning" +const KnownEKUsServerAuth KnownEKUs = "serverAuth" +const KnownEKUsTimeStamping KnownEKUs = "timeStamping" + +var enumValues_KnownEKUs = []interface{}{ + "anyExtendedKeyUsage", + "serverAuth", + "clientAuth", + "codeSigning", + "emailProtection", + "timeStamping", + "OCSPSigning", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *KnownEKUs) UnmarshalJSON(value []byte) error { + var v string + if err := json.Unmarshal(value, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_KnownEKUs { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_KnownEKUs, v) + } + *j = KnownEKUs(v) + return nil +} + +// The top-level testcase container. +type Limbo struct { + // One or more testcases in this testsuite + Testcases []Testcase `json:"testcases"` + + // The limbo schema version; this must currently always be 1 + Version int `json:"version"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Limbo) UnmarshalJSON(value []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(value, &raw); err != nil { + return err + } + if _, ok := raw["testcases"]; raw != nil && !ok { + return fmt.Errorf("field testcases in Limbo: required") + } + if _, ok := raw["version"]; raw != nil && !ok { + return fmt.Errorf("field version in Limbo: required") + } + type Plain Limbo + var plain Plain + if err := json.Unmarshal(value, &plain); err != nil { + return err + } + if plain.Version != 1 { + return fmt.Errorf("field %s: must be equal to %v", "version", 1) + } + *j = Limbo(plain) + return nil +} + +type PeerKind string + +const PeerKindDNS PeerKind = "DNS" +const PeerKindIP PeerKind = "IP" +const PeerKindRFC822 PeerKind = "RFC822" + +var enumValues_PeerKind = []interface{}{ + "RFC822", + "DNS", + "IP", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *PeerKind) UnmarshalJSON(value []byte) error { + var v string + if err := json.Unmarshal(value, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_PeerKind { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_PeerKind, v) + } + *j = PeerKind(v) + return nil +} + +// Represents a peer (i.e., end entity) certificate's name (Subject or SAN). +type PeerName struct { + // The kind of peer name + Kind PeerKind `json:"kind"` + + // The peer's name + Value string `json:"value"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *PeerName) UnmarshalJSON(value []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(value, &raw); err != nil { + return err + } + if _, ok := raw["kind"]; raw != nil && !ok { + return fmt.Errorf("field kind in PeerName: required") + } + if _, ok := raw["value"]; raw != nil && !ok { + return fmt.Errorf("field value in PeerName: required") + } + type Plain PeerName + var plain Plain + if err := json.Unmarshal(value, &plain); err != nil { + return err + } + *j = PeerName(plain) + return nil +} + +type SignatureAlgorithm string + +const SignatureAlgorithmDSAWITHSHA1 SignatureAlgorithm = "DSA_WITH_SHA1" +const SignatureAlgorithmDSAWITHSHA224 SignatureAlgorithm = "DSA_WITH_SHA224" +const SignatureAlgorithmDSAWITHSHA256 SignatureAlgorithm = "DSA_WITH_SHA256" +const SignatureAlgorithmDSAWITHSHA384 SignatureAlgorithm = "DSA_WITH_SHA384" +const SignatureAlgorithmDSAWITHSHA512 SignatureAlgorithm = "DSA_WITH_SHA512" +const SignatureAlgorithmECDSAWITHSHA1 SignatureAlgorithm = "ECDSA_WITH_SHA1" +const SignatureAlgorithmECDSAWITHSHA224 SignatureAlgorithm = "ECDSA_WITH_SHA224" +const SignatureAlgorithmECDSAWITHSHA256 SignatureAlgorithm = "ECDSA_WITH_SHA256" +const SignatureAlgorithmECDSAWITHSHA3224 SignatureAlgorithm = "ECDSA_WITH_SHA3_224" +const SignatureAlgorithmECDSAWITHSHA3256 SignatureAlgorithm = "ECDSA_WITH_SHA3_256" +const SignatureAlgorithmECDSAWITHSHA3384 SignatureAlgorithm = "ECDSA_WITH_SHA3_384" +const SignatureAlgorithmECDSAWITHSHA3512 SignatureAlgorithm = "ECDSA_WITH_SHA3_512" +const SignatureAlgorithmECDSAWITHSHA384 SignatureAlgorithm = "ECDSA_WITH_SHA384" +const SignatureAlgorithmECDSAWITHSHA512 SignatureAlgorithm = "ECDSA_WITH_SHA512" +const SignatureAlgorithmED25519 SignatureAlgorithm = "ED25519" +const SignatureAlgorithmED448 SignatureAlgorithm = "ED448" +const SignatureAlgorithmGOSTR34102012WITH34112012256 SignatureAlgorithm = "GOSTR3410_2012_WITH_3411_2012_256" +const SignatureAlgorithmGOSTR34102012WITH34112012512 SignatureAlgorithm = "GOSTR3410_2012_WITH_3411_2012_512" +const SignatureAlgorithmGOSTR341194WITH34102001 SignatureAlgorithm = "GOSTR3411_94_WITH_3410_2001" +const SignatureAlgorithmRSASSAPSS SignatureAlgorithm = "RSASSA_PSS" +const SignatureAlgorithmRSAWITHMD5 SignatureAlgorithm = "RSA_WITH_MD5" +const SignatureAlgorithmRSAWITHSHA1 SignatureAlgorithm = "RSA_WITH_SHA1" +const SignatureAlgorithmRSAWITHSHA224 SignatureAlgorithm = "RSA_WITH_SHA224" +const SignatureAlgorithmRSAWITHSHA256 SignatureAlgorithm = "RSA_WITH_SHA256" +const SignatureAlgorithmRSAWITHSHA3224 SignatureAlgorithm = "RSA_WITH_SHA3_224" +const SignatureAlgorithmRSAWITHSHA3256 SignatureAlgorithm = "RSA_WITH_SHA3_256" +const SignatureAlgorithmRSAWITHSHA3384 SignatureAlgorithm = "RSA_WITH_SHA3_384" +const SignatureAlgorithmRSAWITHSHA3512 SignatureAlgorithm = "RSA_WITH_SHA3_512" +const SignatureAlgorithmRSAWITHSHA384 SignatureAlgorithm = "RSA_WITH_SHA384" +const SignatureAlgorithmRSAWITHSHA512 SignatureAlgorithm = "RSA_WITH_SHA512" + +var enumValues_SignatureAlgorithm = []interface{}{ + "RSA_WITH_MD5", + "RSA_WITH_SHA1", + "RSA_WITH_SHA224", + "RSA_WITH_SHA256", + "RSA_WITH_SHA384", + "RSA_WITH_SHA512", + "RSA_WITH_SHA3_224", + "RSA_WITH_SHA3_256", + "RSA_WITH_SHA3_384", + "RSA_WITH_SHA3_512", + "RSASSA_PSS", + "ECDSA_WITH_SHA1", + "ECDSA_WITH_SHA224", + "ECDSA_WITH_SHA256", + "ECDSA_WITH_SHA384", + "ECDSA_WITH_SHA512", + "ECDSA_WITH_SHA3_224", + "ECDSA_WITH_SHA3_256", + "ECDSA_WITH_SHA3_384", + "ECDSA_WITH_SHA3_512", + "DSA_WITH_SHA1", + "DSA_WITH_SHA224", + "DSA_WITH_SHA256", + "DSA_WITH_SHA384", + "DSA_WITH_SHA512", + "ED25519", + "ED448", + "GOSTR3411_94_WITH_3410_2001", + "GOSTR3410_2012_WITH_3411_2012_256", + "GOSTR3410_2012_WITH_3411_2012_512", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *SignatureAlgorithm) UnmarshalJSON(value []byte) error { + var v string + if err := json.Unmarshal(value, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_SignatureAlgorithm { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_SignatureAlgorithm, v) + } + *j = SignatureAlgorithm(v) + return nil +} + +// Represents an individual Limbo testcase. +type Testcase struct { + // A list of testcase IDs that this testcase is mutually incompatible with + ConflictsWith []string `json:"conflicts_with,omitempty,omitzero"` + + // A list of PEM-encoded Certificate Revocation Lists (CRLs) + Crls []string `json:"crls,omitempty,omitzero"` + + // A short, Markdown-formatted description + Description string `json:"description"` + + // For server (i.e. client-side) validation: the expected peer name, if any + ExpectedPeerName *TestcaseExpectedPeerName `json:"expected_peer_name,omitempty,omitzero"` + + // For client (i.e. server-side) validation: the expected peer names + ExpectedPeerNames []PeerName `json:"expected_peer_names"` + + // The expected validation result + ExpectedResult ExpectedResult `json:"expected_result"` + + // A constraining list of extended key usages, either in well-known form or as + // OIDs + ExtendedKeyUsage []KnownEKUs `json:"extended_key_usage"` + + // Zero or more human-readable tags that describe OPTIONAL functionality described + // by this testcase. Implementers should use this to specify testcases for + // non-mandatory X.509 behavior (like certificate policy validation) or for + // 'pedantic' cases. Consumers that don't understand a given feature should skip + // tests that are marked with it. + Features []Feature `json:"features,omitempty,omitzero"` + + // A short, unique identifier for this testcase + Id string `json:"id"` + + // The testcase's importance + Importance Importance `json:"importance,omitempty,omitzero"` + + // A constraining list of key usages + KeyUsage []KeyUsage `json:"key_usage"` + + // The maximum chain-building depth + MaxChainDepth interface{} `json:"max_chain_depth,omitempty,omitzero"` + + // The PEM-encoded peer (EE) certificate + PeerCertificate string `json:"peer_certificate"` + + // The PEM-encoded private key for the peer certificate, if present + PeerCertificateKey interface{} `json:"peer_certificate_key,omitempty,omitzero"` + + // A list of acceptable signature algorithms to constrain against + SignatureAlgorithms []SignatureAlgorithm `json:"signature_algorithms"` + + // A list of PEM-encoded CA certificates to consider trusted + TrustedCerts []string `json:"trusted_certs"` + + // A list of PEM-encoded untrusted intermediates to use during path building + UntrustedIntermediates []string `json:"untrusted_intermediates"` + + // The kind of validation to perform + ValidationKind ValidationKind `json:"validation_kind"` + + // The time at which to perform the validation + ValidationTime interface{} `json:"validation_time,omitempty,omitzero"` +} + +// For server (i.e. client-side) validation: the expected peer name, if any +type TestcaseExpectedPeerName struct { + // The kind of peer name + Kind PeerKind `json:"kind"` + + // The peer's name + Value string `json:"value"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *TestcaseExpectedPeerName) UnmarshalJSON(value []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(value, &raw); err != nil { + return err + } + var testcaseExpectedPeerName_0 TestcaseExpectedPeerName_0 + var errs []error + if err := testcaseExpectedPeerName_0.UnmarshalJSON(value); err != nil { + errs = append(errs, err) + } + if len(errs) == 1 { + return fmt.Errorf("all validators failed: %s", errors.Join(errs...)) + } + type Plain TestcaseExpectedPeerName + var plain Plain + if err := json.Unmarshal(value, &plain); err != nil { + return err + } + *j = TestcaseExpectedPeerName(plain) + return nil +} + +type TestcaseMaxChainDepth_0 *int + +type TestcasePeerCertificateKey_0 *string + +type TestcaseValidationTime_0 *time.Time + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Testcase) UnmarshalJSON(value []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(value, &raw); err != nil { + return err + } + if _, ok := raw["description"]; raw != nil && !ok { + return fmt.Errorf("field description in Testcase: required") + } + if _, ok := raw["expected_peer_names"]; raw != nil && !ok { + return fmt.Errorf("field expected_peer_names in Testcase: required") + } + if _, ok := raw["expected_result"]; raw != nil && !ok { + return fmt.Errorf("field expected_result in Testcase: required") + } + if _, ok := raw["extended_key_usage"]; raw != nil && !ok { + return fmt.Errorf("field extended_key_usage in Testcase: required") + } + if _, ok := raw["id"]; raw != nil && !ok { + return fmt.Errorf("field id in Testcase: required") + } + if _, ok := raw["key_usage"]; raw != nil && !ok { + return fmt.Errorf("field key_usage in Testcase: required") + } + if _, ok := raw["peer_certificate"]; raw != nil && !ok { + return fmt.Errorf("field peer_certificate in Testcase: required") + } + if _, ok := raw["signature_algorithms"]; raw != nil && !ok { + return fmt.Errorf("field signature_algorithms in Testcase: required") + } + if _, ok := raw["trusted_certs"]; raw != nil && !ok { + return fmt.Errorf("field trusted_certs in Testcase: required") + } + if _, ok := raw["untrusted_intermediates"]; raw != nil && !ok { + return fmt.Errorf("field untrusted_intermediates in Testcase: required") + } + if _, ok := raw["validation_kind"]; raw != nil && !ok { + return fmt.Errorf("field validation_kind in Testcase: required") + } + type Plain Testcase + var plain Plain + if err := json.Unmarshal(value, &plain); err != nil { + return err + } + if v, ok := raw["conflicts_with"]; !ok || v == nil { + plain.ConflictsWith = []string{} + } + if v, ok := raw["crls"]; !ok || v == nil { + plain.Crls = []string{} + } + if v, ok := raw["features"]; !ok || v == nil { + plain.Features = []Feature{} + } + if matched, _ := regexp.MatchString(`^([A-Za-z][A-Za-z0-9-.]+::)*([A-Za-z][A-Za-z0-9-.]+)$`, string(plain.Id)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "Id", `^([A-Za-z][A-Za-z0-9-.]+::)*([A-Za-z][A-Za-z0-9-.]+)$`) + } + if v, ok := raw["importance"]; !ok || v == nil { + plain.Importance = "undetermined" + } + *j = Testcase(plain) + return nil +} + +type ValidationKind string + +const ValidationKindCLIENT ValidationKind = "CLIENT" +const ValidationKindSERVER ValidationKind = "SERVER" + +var enumValues_ValidationKind = []interface{}{ + "CLIENT", + "SERVER", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ValidationKind) UnmarshalJSON(value []byte) error { + var v string + if err := json.Unmarshal(value, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_ValidationKind { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ValidationKind, v) + } + *j = ValidationKind(v) + return nil +} + +type TestcaseExpectedPeerName_0 = PeerName diff --git a/src/crypto/internal/cryptotest/x509limbo/schemaversion.go b/src/crypto/internal/cryptotest/x509limbo/schemaversion.go new file mode 100644 index 0000000000000000000000000000000000000000..b79a112e0d09d657d7f538947400547bb05064a9 --- /dev/null +++ b/src/crypto/internal/cryptotest/x509limbo/schemaversion.go @@ -0,0 +1,14 @@ +// 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. + +// Code generated by _schema/schema_gen.go, DO NOT EDIT. + +package x509limbo + +// X509LimboModule is the module path of the upstream x509-limbo project. +const X509LimboModule = "github.com/C2SP/x509-limbo" + +// X509LimboVersion is the X509LimboModule version that schema.go was +// generated against. +const X509LimboVersion = "v0.0.0-20260522003327-feb7caccc1af" diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index fb1e9f00e240eabeb0c15ecf16dd41df47f054c6..e8102787fe5f3995801e352dab36a2878588f700 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -1604,6 +1604,12 @@ return c.handshakeErr } // ConnectionState returns basic TLS details about the connection. +// +// The returned [ConnectionState] is only meaningful after the handshake has +// completed, as reported by [ConnectionState.HandshakeComplete]; before then +// its fields are not populated. The handshake is run automatically by the +// first [Conn.Read] or [Conn.Write], or it can be triggered explicitly with +// [Conn.Handshake]. func (c *Conn) ConnectionState() ConnectionState { c.handshakeMutex.Lock() defer c.handshakeMutex.Unlock() diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go index aa0b7db75dd493eed6b21460999bbd24289dfb00..511e073df57d724da7c9f31e15f3d4ff610a323b 100644 --- a/src/crypto/tls/handshake_messages.go +++ b/src/crypto/tls/handshake_messages.go @@ -5,6 +5,7 @@ package tls import ( + "bytes" "errors" "fmt" "slices" @@ -317,7 +318,8 @@ } }) }) } - if len(m.pskIdentities) > 0 { // pre_shared_key must be the last extension + // pre_shared_key must be the last extension + if len(m.pskIdentities) > 0 && (echInner || len(m.encryptedClientHello) == 0 || bytes.Equal(m.encryptedClientHello, []byte{byte(innerECHExt)})) { // RFC 8446, Section 4.2.11 exts.AddUint16(extensionPreSharedKey) exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { diff --git a/src/crypto/tls/handshake_messages_test.go b/src/crypto/tls/handshake_messages_test.go index aa4659ac3aec38ad88fdbfe1cde7cc95b4c06d4f..d025ce85ca4a9df7793eb475c10500adbe6f9bf0 100644 --- a/src/crypto/tls/handshake_messages_test.go +++ b/src/crypto/tls/handshake_messages_test.go @@ -215,7 +215,16 @@ m.pskModes = []uint8{pskModeDHE} case 2: m.pskModes = []uint8{pskModeDHE, pskModePlain} } - for i := 0; i < rand.Intn(5); i++ { + // clientHelloMsg.marshal uses echInner == false. If m.encryptedClientHello > 0 and + // does not equal []byte{innerECHExt}, then the psk extension will be omitted, + // so either only emit empty encryptedClientHello and psk, encryptedClientHello with + // []byte{innerECHExt} and psk, or random encryptedClientHello and no psk. + if rand.Intn(10) > 5 { + m.encryptedClientHello = randomBytes(rand.Intn(50)+1, rand) + } else { + if rand.Intn(10) > 5 { + m.encryptedClientHello = []byte{byte(innerECHExt)} + } var psk pskIdentity psk.obfuscatedTicketAge = uint32(rand.Intn(500000)) psk.label = randomBytes(rand.Intn(500)+1, rand) @@ -227,9 +236,6 @@ m.quicTransportParameters = randomBytes(rand.Intn(500), rand) } if rand.Intn(10) > 5 { m.earlyData = true - } - if rand.Intn(10) > 5 { - m.encryptedClientHello = randomBytes(rand.Intn(50)+1, rand) } return reflect.ValueOf(m) @@ -579,3 +585,88 @@ if serverHelloCopy.unmarshal(serverHelloBytes) { t.Fatal("Unmarshaled ServerHello with duplicate extensions") } } + +func TestECHRemoveOuterPSK(t *testing.T) { + r := rand.New(rand.NewSource(0)) + + for _, tc := range []struct { + name string + echInner bool + echExt []byte + expectRemoved bool + }{ + { + name: "echInner true", + echInner: true, + expectRemoved: false, + }, + { + name: "echInner true, no ech ext", + echInner: true, + expectRemoved: false, + }, + { + name: "echInner true, ech ext present", + echInner: true, + echExt: []byte{254}, + expectRemoved: false, + }, + { + name: "echInner true, ech ext present, inner ech sentinel", + echInner: true, + echExt: []byte{byte(innerECHExt)}, + expectRemoved: false, + }, + { + name: "echInner false, no ech ext", + echInner: false, + expectRemoved: false, + }, + { + name: "echInner false, ech ext present", + echInner: false, + echExt: []byte{254}, + expectRemoved: true, + }, + { + name: "echInner false, ech ext present, inner ech sentinel", + echInner: false, + echExt: []byte{byte(innerECHExt)}, + expectRemoved: false, + }, + } { + t.Run(tc.name, func(t *testing.T) { + ch := (&clientHelloMsg{}).Generate(r, 0).Interface().(*clientHelloMsg) + + ch.pskBinders = [][]byte{[]byte("test")} + ch.pskIdentities = []pskIdentity{{label: []byte("test")}} + ch.encryptedClientHello = tc.echExt + + b, err := ch.marshalMsg(tc.echInner) + if err != nil { + t.Fatal(err) + } + var rch clientHelloMsg + if !rch.unmarshal(b) { + t.Fatal("Failed to unmarshal ClientHello") + } + + if tc.expectRemoved { + if rch.pskIdentities != nil { + t.Error("expected PSK identities to be removed") + } + if rch.pskBinders != nil { + t.Error("expected PSK binders to be removed") + } + } else { + if rch.pskIdentities == nil { + t.Error("expected PSK identities to be present") + } + if rch.pskBinders == nil { + t.Error("expected PSK binders to be present") + } + } + }) + } + +} diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go index d1f229b0c77127ee821ed1a8d2881805f41d8624..6fe44907358095b791e8f5218211b5e65e6f8738 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -2678,6 +2678,7 @@ clientConfig.RootCAs = x509.NewCertPool() clientConfig.RootCAs.AddCert(secretCert) clientConfig.RootCAs.AddCert(publicCert) clientConfig.EncryptedClientHelloConfigList = echConfigList + clientConfig.ClientSessionCache = NewLRUClientSessionCache(2) serverConfig.InsecureSkipVerify = false serverConfig.Time = nil serverConfig.MinVersion = VersionTLS13 diff --git a/src/crypto/x509/bettertls_test.go b/src/crypto/x509/bettertls_test.go deleted file mode 100644 index 3ef67b05a91753ed2b1ea52e3c7486a5b69fac05..0000000000000000000000000000000000000000 --- a/src/crypto/x509/bettertls_test.go +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2025 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. - -// This test uses Netflix's BetterTLS test suite to test the crypto/x509 -// path building and name constraint validation. -// -// The test data in JSON form is around 31MB, so we fetch the BetterTLS -// go module and use it to generate the JSON data on-the-fly in a tmp dir. -// -// For more information, see: -// https://github.com/netflix/bettertls -// https://netflixtechblog.com/bettertls-c9915cd255c0 - -package x509 - -import ( - "crypto/internal/cryptotest" - "encoding/base64" - "encoding/json" - "internal/testenv" - "os" - "path/filepath" - "testing" -) - -// TestBetterTLS runs the "pathbuilding" and "nameconstraints" suites of -// BetterTLS. -// -// The test cases in the pathbuilding suite are designed to test edge-cases -// for path building and validation. In particular, the ["chain of pain"][0] -// scenario where a validator treats path building as an operation with -// a single possible outcome, instead of many. -// -// The test cases in the nameconstraints suite are designed to test edge-cases -// for name constraint parsing and validation. -// -// [0]: https://medium.com/@sleevi_/path-building-vs-path-verifying-the-chain-of-pain-9fbab861d7d6 -func TestBetterTLS(t *testing.T) { - testenv.SkipIfShortAndSlow(t) - - data, roots := betterTLSTestData(t) - - for _, suite := range []string{"pathbuilding", "nameconstraints"} { - t.Run(suite, func(t *testing.T) { - runTestSuite(t, suite, &data, roots) - }) - } -} - -func runTestSuite(t *testing.T, suiteName string, data *betterTLS, roots *CertPool) { - suite, exists := data.Suites[suiteName] - if !exists { - t.Fatalf("missing %s suite", suiteName) - } - - t.Logf( - "running %s test suite with %d test cases", - suiteName, len(suite.TestCases)) - - for _, tc := range suite.TestCases { - t.Logf("testing %s test case %d", suiteName, tc.ID) - - certsDER, err := tc.Certs() - if err != nil { - t.Fatalf( - "failed to decode certificates for test case %d: %v", - tc.ID, err) - } - - if len(certsDER) == 0 { - t.Fatalf("test case %d has no certificates", tc.ID) - } - - eeCert, err := ParseCertificate(certsDER[0]) - if err != nil { - // Several constraint test cases contain invalid end-entity - // certificate extensions that we reject ahead of verification - // time. We consider this a pass and skip further processing. - // - // For example, a SAN with a uniformResourceIdentifier general name - // containing the value `"http://foo.bar, DNS:test.localhost"`, or - // an iPAddress general name of the wrong length. - if suiteName == "nameconstraints" && tc.Expected == expectedReject { - t.Logf( - "skipping expected reject test case %d "+ - "- end entity certificate parse error: %v", - tc.ID, err) - continue - } - t.Fatalf( - "failed to parse end entity certificate for test case %d: %v", - tc.ID, err) - } - - intermediates := NewCertPool() - for i, certDER := range certsDER[1:] { - cert, err := ParseCertificate(certDER) - if err != nil { - t.Fatalf( - "failed to parse intermediate certificate %d for test case %d: %v", - i+1, tc.ID, err) - } - intermediates.AddCert(cert) - } - - _, err = eeCert.Verify(VerifyOptions{ - Roots: roots, - Intermediates: intermediates, - DNSName: tc.Hostname, - KeyUsages: []ExtKeyUsage{ExtKeyUsageServerAuth}, - }) - - switch tc.Expected { - case expectedAccept: - if err != nil { - t.Errorf( - "test case %d failed: expected success, got error: %v", - tc.ID, err) - } - case expectedReject: - if err == nil { - t.Errorf( - "test case %d failed: expected failure, but verification succeeded", - tc.ID) - } - default: - t.Fatalf( - "test case %d failed: unknown expected result: %s", - tc.ID, tc.Expected) - } - } -} - -func betterTLSTestData(t *testing.T) (betterTLS, *CertPool) { - const ( - bettertlsModule = "github.com/Netflix/bettertls" - bettertlsVersion = "v0.0.0-20250909192348-e1e99e353074" - ) - - bettertlsDir := cryptotest.FetchModule(t, bettertlsModule, bettertlsVersion) - - tempDir := t.TempDir() - testsJSONPath := filepath.Join(tempDir, "tests.json") - - cmd := testenv.Command(t, testenv.GoToolPath(t), - "run", "./test-suites/cmd/bettertls", - "export-tests", - "--out", testsJSONPath) - cmd.Dir = bettertlsDir - t.Log("running bettertls export-tests command") - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("failed to run bettertls export-tests: %v\n%s", err, out) - } - - jsonData, err := os.ReadFile(testsJSONPath) - if err != nil { - t.Fatalf("failed to read exported tests.json: %v", err) - } - - t.Logf("successfully loaded tests.json at %s", testsJSONPath) - - var data betterTLS - if err := json.Unmarshal(jsonData, &data); err != nil { - t.Fatalf("failed to unmarshal JSON data: %v", err) - } - - t.Logf("testing betterTLS revision: %s", data.Revision) - t.Logf("number of test suites: %d", len(data.Suites)) - - rootDER, err := data.RootCert() - if err != nil { - t.Fatalf("failed to decode trust root: %v", err) - } - - rootCert, err := ParseCertificate(rootDER) - if err != nil { - t.Fatalf("failed to parse trust root certificate: %v", err) - } - - roots := NewCertPool() - roots.AddCert(rootCert) - - return data, roots -} - -type betterTLS struct { - Revision string `json:"betterTlsRevision"` - Root string `json:"trustRoot"` - Suites map[string]betterTLSSuite `json:"suites"` -} - -func (b *betterTLS) RootCert() ([]byte, error) { - return base64.StdEncoding.DecodeString(b.Root) -} - -type betterTLSSuite struct { - TestCases []betterTLSTest `json:"testCases"` -} - -type betterTLSTest struct { - ID uint32 `json:"id"` - Certificates []string `json:"certificates"` - Hostname string `json:"hostname"` - Expected expectedResult `json:"expected"` -} - -func (test *betterTLSTest) Certs() ([][]byte, error) { - certs := make([][]byte, len(test.Certificates)) - for i, cert := range test.Certificates { - decoded, err := base64.StdEncoding.DecodeString(cert) - if err != nil { - return nil, err - } - certs[i] = decoded - } - return certs, nil -} - -type expectedResult string - -const ( - expectedAccept expectedResult = "ACCEPT" - expectedReject expectedResult = "REJECT" -) diff --git a/src/crypto/x509/x509limbo_test.go b/src/crypto/x509/x509limbo_test.go new file mode 100644 index 0000000000000000000000000000000000000000..1567601a2a221cb0a6a1cd9274dd039e462744b9 --- /dev/null +++ b/src/crypto/x509/x509limbo_test.go @@ -0,0 +1,339 @@ +// 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. + +package x509 + +import ( + "crypto/internal/cryptotest" + "crypto/internal/cryptotest/x509limbo" + "encoding/json" + "encoding/pem" + "flag" + "fmt" + "internal/testenv" + "os" + "path/filepath" + "slices" + "strings" + "testing" + "time" +) + +var limboCases = flag.String("limbo_cases", "", "comma-separated limbo case ids to run; if empty, all cases run") + +// Instances where we do **not** produce an error, but the test corpus says +// we should have. The map value justifies each allow. +var allowedUnexpectedVerifications = map[string]string{ + // These are instances where we should consider updating the implementation. + "rfc5280::san::noncritical-with-empty-subject": "TODO(#79741)", + "webpki::san::san-critical-with-nonempty-subject": "TODO(#79741)", + "rfc5280::nc::not-allowed-in-ee-noncritical": "TODO(#79742)", + "rfc5280::nc::not-allowed-in-ee-critical": "TODO(#79742)", + "rfc5280::eku::ee-eku-empty": "TODO(#79743)", + "rfc5280::ca-empty-subject": "TODO(#79744)", + + // Underscores and other invalid characters are presently allowed after + // tightening up the validation caused issues with real world certificates. + "rfc5280::san::underscore-dns": "TODO(#75835)", + + // Go does not apply CABF key-strength policies. + "webpki::forbidden-dsa-leaf": "Go doesn't enforce CABF key strength policies", + "webpki::forbidden-weak-rsa-key-in-root": "Go doesn't enforce CABF key strength policies", + "webpki::forbidden-weak-rsa-in-leaf": "Go doesn't enforce CABF key strength policies", + "webpki::forbidden-rsa-not-divisable-by-8-in-root": "Go doesn't enforce CABF key strength policies", + "webpki::forbidden-rsa-key-not-divisable-by-8-in-leaf": "Go doesn't enforce CABF key strength policies", + + // We don't want to take a public suffix data dependency, other heuristics + // are incomplete and will interact badly with private PKIs. + "webpki::san::public-suffix-wildcard-san": "Go doesn't include the PSL in its stdlib", + + // Trust anchors are implicitly considered issuers regardless of basic + // constraints extension. + "rfc5280::root-non-critical-basic-constraints": "Go only considers BC on intermediates", + // Similarly, KeyUsage status flags are ignored by design. See Certificate.isValid + // comment in body of implementation. + "rfc5280::root-inconsistent-ca-extensions": "Go ignores KU, only considers BC on intermediates", + "rfc5280::leaf-ku-keycertsign": "Go ignores KU, only considers BC on intermediates", + + // Enforcing ee-basicconstraints-ca/ca-as-leaf may additionally break the + // somewhat common practice of using a self-signed issuer as the sole leaf + // certificate in a chain. + "webpki::ee-basicconstraints-ca": "Go ignores KU", + "webpki::ca-as-leaf": "Go ignores KU", + + // Certificate.Verify documents that we allow a leading period for DNS + // name constraints, similar to emails/URIs. + "rfc5280::nc::invalid-dnsname-leading-period": "Go accepts leading period", + + // AKI is not load-bearing for validation. We only use it as a + // parent-ordering hint in CertPool.findPotentialParents. + "rfc5280::aki::cross-signed-root-missing-aki": "Go only uses AKI for ordering hint, not a verification requirement", + "rfc5280::aki::leaf-missing-aki": "Go only uses AKI for ordering hint, not a verification requirement", + "webpki::aki::root-with-aki-missing-keyidentifier": "Go does not enforce CABF requirement that root AKI contain a keyIdentifier field", + "webpki::aki::root-with-aki-authoritycertissuer": "Go does not enforce CABF prohibition on authorityCertIssuer in root AKI", + "webpki::aki::root-with-aki-authoritycertserialnumber": "Go does not enforce CABF prohibition on authorityCertSerialNumber in root AKI", + "webpki::aki::root-with-aki-all-fields": "Go does not enforce CABF restrictions on AKI field composition in roots", + "webpki::aki::root-with-aki-ski-mismatch": "Go does not enforce CABF requirement that a self-signed root's AKI keyIdentifier match its SKI", + + // Enforcing criticality is of dubious value in these cases and likely bumps + // into incorrect real world certificates. Additionally, no other verifiers + // tested by x509-limbo upstream treat these as a failure condition. + "webpki::eku::ee-critical-eku": "Go doesn't reject this extension when marked critical", + "rfc5280::nc::permitted-dns-match-noncritical": "Go doesn't require this extension to be critical", + "rfc5280::pc::ica-noncritical-pc": "Go doesn't require this extension to be critical", + + // Serial parsing enforces no negatives, but doesn't enforce max length or + // non-zero. Important roots have a serial of zero, and enforcing serial + // length broke enough private PKIs that the enforcement change was reverted. + "rfc5280::serial::too-long": "Causes significant breakage of real-world private PKIs", + "rfc5280::serial::zero": "RFC 5280 says certificate users SHOULD gracefully handle zero", + + // These are skipped based on CT analysis of affected certificates. + // See https://github.com/golang/go/issues/65085#issuecomment-1932886623 + "rfc5280::ski::root-missing-ski": "would break various trusted Verisign roots", + "rfc5280::ski::intermediate-missing-ski": "would break various trusted intermediates", + "rfc5280::aki::intermediate-missing-aki": "would break real world certificates", + + // Go enforces EKU as an application-level capability filter, not according + // to CABF webpki policy where (for e.g.) anyExtendedKeyUsage is forbidden + // on leaves. + "webpki::eku::ee-anyeku": "Go treats anyExtendedKeyUsage as overriding any other key usage.", + "webpki::eku::ee-without-eku": "Go skips certs with no EKU when checking chain usage.", + "webpki::eku::root-has-eku": "Go allows a root to have an EKU as a downward constraint", + + // Our implementation handles these degenerate name constraint tests + // without error. They are described as standards compliant but are + // marked expected-reject upstream because quadratic implementations + // hit a fixed DoS prevention limit. nc-dos-3 is not listed: it matches + // the expected failure result, but due to the use of a subject CN + // without SAN, not because of quadratic NC checking. + "pathological::nc-dos-1": "standards compliant; upstream rejects due to quadratic DoS limit", + "pathological::nc-dos-2": "standards compliant; upstream rejects due to quadratic DoS limit", + + // These webpki::cn::* cases test CABF BR 7.1.4.3 constraints on the + // CN field. Go's x509 package intentionally ignores the legacy Common Name + // (CN) field for hostname matching (see Certificate.VerifyHostname), so + // verification succeeds via the well-formed SAN even when the CN is + // non-conformant. + "webpki::cn::case-mismatch": "Go ignores legacy CN", + "webpki::cn::ipv4-hex-mismatch": "Go ignores legacy CN", + "webpki::cn::ipv4-leading-zeros-mismatch": "Go ignores legacy CN", + "webpki::cn::ipv6-non-rfc5952-mismatch": "Go ignores legacy CN", + "webpki::cn::ipv6-uncompressed-mismatch": "Go ignores legacy CN", + "webpki::cn::ipv6-uppercase-mismatch": "Go ignores legacy CN", + "webpki::cn::not-in-san": "Go ignores legacy CN", + "webpki::cn::punycode-not-in-san": "Go ignores legacy CN", + "webpki::cn::utf8-vs-punycode-mismatch": "Go ignores legacy CN", +} + +// Instances where we produce an error, but the test corpus says we +// shouldn't have. The map value justifies each allow. +var allowedUnexpectedFailures = map[string]string{ + // This looks like a small oversight in our implementation, and should be + // fixed. + "rfc5280::nc::permitted-self-issued": "TODO(#79746)", + + // The spec-conformant behavior weakens the security value of pathlen, and + // has limited real-world impact on webpki certificates. Other + // implementations like mozilla::pkix have reached a similar conclusion. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=926265 and + // https://github.com/golang/go/issues/79745#issuecomment-4578179884 + "pathlen::self-issued-certs-pathlen": "Go prefers a stricter pathen implementation", + + // Limbo argues there are no OtherName GeneralName's in the chain being + // validated, and so it should pass. We take a more conservative stance + // backed by 5280 §4.2 that we have a critical extension we can't process, + // and don't make a determination based on usage in verification. + "rfc5280::nc::nc-forbids-othername-noop": "Go rejects critical NC with GeneralName types it doesn't implement", + + // Per the test's description there is "no clear 'winning' interpretation" + // between second-granularity checks vs instantaneous. Changing our + // behavior in this case seems low-priority. + "rfc5280::validity::notafter-fractional": "Go uses instantaneous time comparisons", +} + +var extKeyUsagesMap = map[x509limbo.KnownEKUs]ExtKeyUsage{ + x509limbo.KnownEKUsAnyExtendedKeyUsage: ExtKeyUsageAny, + x509limbo.KnownEKUsClientAuth: ExtKeyUsageClientAuth, + x509limbo.KnownEKUsCodeSigning: ExtKeyUsageCodeSigning, + x509limbo.KnownEKUsEmailProtection: ExtKeyUsageEmailProtection, + x509limbo.KnownEKUsOCSPSigning: ExtKeyUsageOCSPSigning, + x509limbo.KnownEKUsServerAuth: ExtKeyUsageServerAuth, + x509limbo.KnownEKUsTimeStamping: ExtKeyUsageTimeStamping, +} + +// Tests the x509 package using the test vectors from https://x509-limbo.com/ +func TestX509Limbo(t *testing.T) { + testenv.SkipIfShortAndSlow(t) + + limboDir := cryptotest.FetchModule(t, x509limbo.X509LimboModule, x509limbo.X509LimboVersion) + + limboJson, err := os.ReadFile(filepath.Join(limboDir, "limbo.json")) + if err != nil { + t.Fatalf("error reading limbo.json: %v", err) + } + + var limbo x509limbo.Limbo + if err := json.Unmarshal(limboJson, &limbo); err != nil { + t.Fatalf("failed to unmarshal limbo.json: %v", err) + } + + for _, tc := range limbo.Testcases { + t.Run(tc.Id, func(t *testing.T) { + t.Parallel() + + if *limboCases != "" && !slices.Contains(strings.Split(*limboCases, ","), tc.Id) { + t.Skip("filtered out by -limbo_cases") + } + + if slices.Contains(tc.Features, x509limbo.FeatureHasCrl) { + t.Skipf("CRL revocation checking not supported") + } + + if slices.Contains(tc.Features, x509limbo.FeatureMaxChainDepth) { + t.Skipf("customizable max chain depth not supported") + } + + if slices.Contains(tc.Features, x509limbo.FeatureNameConstraintDn) { + t.Skipf("name constraints for DirectoryNames are not supported") + } + + if len(tc.SignatureAlgorithms) != 0 { + // Note: there are no limbo.json test cases that specify signature + // algorithms at this time, so this skip is largely a no-op. + t.Skipf("signature algorithms are not customizable through the x509 interface") + } + + if len(tc.KeyUsage) != 0 && + !slices.Contains(tc.KeyUsage, x509limbo.KeyUsageDigitalSignature) { + // Note: there are no limbo.json test cases that specify key usages other + // than digitalSignature at this time, so this skip is largely a no-op. + t.Skipf("key usage checks other than Digital Signature are not supported") + } + + // In the server validation context we may be given a single expected + // peer name to use for our verify options. + var verifyDnsName string + if tc.ExpectedPeerName != nil && tc.ValidationKind == x509limbo.ValidationKindSERVER { + switch tc.ExpectedPeerName.Kind { + case x509limbo.PeerKindDNS: + verifyDnsName = tc.ExpectedPeerName.Value + case x509limbo.PeerKindIP: + verifyDnsName = fmt.Sprintf("[%s]", tc.ExpectedPeerName.Value) + default: + t.Skipf("unsupported peer name kind: %v", tc.ExpectedPeerName.Kind) + } + } + + roots, intermediates := NewCertPool(), NewCertPool() + for _, rootPem := range tc.TrustedCerts { + roots.AppendCertsFromPEM([]byte(rootPem)) + } + for _, intermediatePem := range tc.UntrustedIntermediates { + intermediates.AppendCertsFromPEM([]byte(intermediatePem)) + } + + block, rest := pem.Decode([]byte(tc.PeerCertificate)) + if block == nil { + t.Fatalf("unable to PEM decode peer certificate") + } else if block.Type != "CERTIFICATE" { + t.Fatalf("unexpected data, expected cert: %+#v", *block) + } else if len(rest) > 0 { + t.Fatalf("peer certificate has %d trailing bytes", len(rest)) + } + + peer, parseErr := ParseCertificate(block.Bytes) + if parseErr != nil { + if tc.ExpectedResult == x509limbo.ExpectedResultFAILURE { + // The test expects failure and we detect an error at parse + // time instead of verification time. Considered a pass. + return + } + printChainDetails(t, tc, parseErr) + t.Errorf("expected success, parsing peer certificate failed: %v", parseErr) + return + } + + validationTime := time.Now() + if tc.ValidationTime != nil { + vtStr, ok := tc.ValidationTime.(string) + if !ok { + t.Fatalf("validation time is not a string: %T %v", tc.ValidationTime, tc.ValidationTime) + } + parsed, err := time.Parse(time.RFC3339, vtStr) + if err != nil { + t.Fatalf("invalid validation time %q: %v", vtStr, err) + } + validationTime = parsed + } + + var ekus []ExtKeyUsage + for _, elem := range tc.ExtendedKeyUsage { + eku, ok := extKeyUsagesMap[elem] + if !ok { + t.Skipf("unsupported extended key usage: %v", elem) + } + ekus = append(ekus, eku) + } + + _, err := peer.Verify(VerifyOptions{ + DNSName: verifyDnsName, + Intermediates: intermediates, + Roots: roots, + CurrentTime: validationTime, + KeyUsages: ekus, + }) + if err == nil && tc.ExpectedResult == x509limbo.ExpectedResultFAILURE { + if _, allowed := allowedUnexpectedVerifications[tc.Id]; !allowed { + printChainDetails(t, tc, nil) + t.Errorf("expected failure, built chain without error") + } + } else if err != nil && tc.ExpectedResult == x509limbo.ExpectedResultSUCCESS { + if _, allowed := allowedUnexpectedFailures[tc.Id]; !allowed { + printChainDetails(t, tc, err) + t.Errorf("expected success, built chain with error: %v", err) + } + } + + // In the client validation context we may be given multiple expected + // peer names so we check these explicitly after path building. + // The DNSName in our VerifyOpts will have been empty. + if tc.ValidationKind == x509limbo.ValidationKindCLIENT { + for _, name := range tc.ExpectedPeerNames { + if name.Kind != x509limbo.PeerKindIP && name.Kind != x509limbo.PeerKindDNS { + // We don't support verifying RFC8222 peer names. + t.Skipf("unsupported peer name kind: %v", name.Kind) + } + err = peer.VerifyHostname(name.Value) + // We don't check allowedUnexpectedVerifications or allowedUnexpectedFailures + // here because there aren't any that apply to ValidationKindCLIENT + // at this time. + if err == nil && tc.ExpectedResult == x509limbo.ExpectedResultFAILURE { + printChainDetails(t, tc, nil) + t.Errorf("expected failure, built chain without error") + } else if err != nil && tc.ExpectedResult == x509limbo.ExpectedResultSUCCESS { + printChainDetails(t, tc, err) + t.Errorf("expected success, built chain with error: %v", err) + } + } + } + }) + } +} + +func printChainDetails(t *testing.T, tc x509limbo.Testcase, actualResult error) { + t.Log("----") + t.Logf("testcase: %q expected result: %v actual result: %v", tc.Id, tc.ExpectedResult, actualResult) + t.Log("trust anchor PEM:") + for _, root := range tc.TrustedCerts { + t.Log(root) + } + t.Log("intermediates PEM:") + for _, intermediate := range tc.UntrustedIntermediates { + t.Log(intermediate) + } + t.Log("end entity PEM:") + t.Log(tc.PeerCertificate) + t.Log("----") +} diff --git a/src/encoding/json/v2/arshal.go b/src/encoding/json/v2/arshal.go index 10b5706968eb127b216b5a2c291c487c8bcbb08e..5b60cc5a78f0455f6f3c0429fc2bc6a3231e0fc3 100644 --- a/src/encoding/json/v2/arshal.go +++ b/src/encoding/json/v2/arshal.go @@ -73,7 +73,7 @@ // over the default representation of a value. // Functions or methods that operate on *T are only called when encoding // a value of type T (by taking its address) or a non-nil value of *T. // Marshal ensures that a value is always addressable -// (by boxing it on the heap if necessary) so that +// (by copying the value if necessary) so that // these functions and methods can be consistently called. For performance, // it is recommended that Marshal be passed a non-nil pointer to the value. // @@ -265,8 +265,12 @@ // over the default representation of a value. // Functions or methods that operate on *T are only called when decoding // a value of type T (by taking its address) or a non-nil value of *T. // Unmarshal ensures that a value is always addressable -// (by boxing it on the heap if necessary) so that +// (by copying the value if necessary) so that // these functions and methods can be consistently called. +// If a value must be shallow copied to call a pointer-receiver +// [Unmarshaler], [UnmarshalerFrom], or [encoding.TextUnmarshaler] method, +// then any mutations performed by the method are shallow copied back +// into the destination value. // // The input is decoded into the output according to the following rules: // diff --git a/src/encoding/json/v2/arshal_default.go b/src/encoding/json/v2/arshal_default.go index 5760ae7b6890a8f794baa88064729bee01e30616..4799eaf9301a04c7c346807664a4053f5c4cdad7 100644 --- a/src/encoding/json/v2/arshal_default.go +++ b/src/encoding/json/v2/arshal_default.go @@ -1324,11 +1324,17 @@ } name := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim()) f := fields.byActualName[string(name)] if f == nil { + var numMatch int for _, f2 := range fields.lookupByFoldedName(name) { if f2.matchFoldedName(name, &uo.Flags) { - f = f2 - break + if f == nil { + f = f2 // use first seen name by breadth-first order + } + numMatch++ } + } + if numMatch > 1 && !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { + return newUnmarshalErrorAfter(dec, t, errAmbiguousName) } if f == nil { if uo.Flags.Get(jsonflags.RejectUnknownMembers) && fields.embeddedFallback == nil { diff --git a/src/encoding/json/v2/arshal_funcs.go b/src/encoding/json/v2/arshal_funcs.go index 860ff0b0f2cf7cb92776f813321c582904d69067..d63f2ee17ed45795b2150c185c33ac57fb0eab81 100644 --- a/src/encoding/json/v2/arshal_funcs.go +++ b/src/encoding/json/v2/arshal_funcs.go @@ -164,6 +164,8 @@ // if T is an interface or pointer type. // // The function must marshal exactly one JSON value. // The value of T must not be retained outside the function call. +// It is recommended that fn return a []byte buffer that is safe +// for the caller to retain and potentially mutate. // It may not return [errors.ErrUnsupported]. func MarshalFunc[T any](fn func(T) ([]byte, error)) *Marshalers { t := reflect.TypeFor[T]() diff --git a/src/encoding/json/v2/arshal_test.go b/src/encoding/json/v2/arshal_test.go index 6fd6a8b7d52b8dd90d3e55c2047e0d3f01483d19..554ee6547863631848596b376ef860b4ace5328c 100644 --- a/src/encoding/json/v2/arshal_test.go +++ b/src/encoding/json/v2/arshal_test.go @@ -7220,10 +7220,17 @@ inBuf: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`, inVal: new(structNoCase), want: addr(structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"}), }, { - name: jsontest.Name("Structs/NoCase/CaseInsensitiveDefault"), + name: jsontest.Name("Structs/NoCase/CaseInsensitiveDefault/Ambiguous"), + opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1}, inBuf: `{"aa_a":"aa_a"}`, inVal: new(structNoCase), want: addr(structNoCase{AaA: "aa_a"}), + }, { + name: jsontest.Name("Structs/NoCase/CaseInsensitiveDefault/Ambiguous"), + inBuf: `{"aa_a":"aa_a"}`, + inVal: new(structNoCase), + want: addr(structNoCase{}), + wantErr: EU(errAmbiguousName).withPos(`{`, "/aa_a").withType('"', T[structNoCase]()), }, { name: jsontest.Name("Structs/NoCase/MatchCaseSensitiveDelimiter"), opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1}, @@ -7238,17 +7245,24 @@ inVal: new(structNoCase), want: addr(structNoCase{AA_A: "aa_a"}), }, { name: jsontest.Name("Structs/NoCase/Merge/AllowDuplicateNames"), - opts: []Options{jsontext.AllowDuplicateNames(true)}, + opts: []Options{jsontext.AllowDuplicateNames(true), jsonflags.ReportErrorsWithLegacySemantics | 1}, inBuf: `{"AaA":"AaA","aaa":"aaa","aAa":"aAa"}`, inVal: new(structNoCase), want: addr(structNoCase{AaA: "aAa"}), }, { - name: jsontest.Name("Structs/NoCase/Merge/RejectDuplicateNames"), + name: jsontest.Name("Structs/NoCase/Merge/AllowDuplicateNames/Ambiguous"), + opts: []Options{jsontext.AllowDuplicateNames(true)}, + inBuf: `{"AaA":"AaA","aaa":"aaa","aAa":"aAa"}`, + inVal: new(structNoCase), + want: addr(structNoCase{AaA: "AaA"}), + wantErr: EU(errAmbiguousName).withPos(`{"AaA":"AaA",`, "/aaa").withType('"', T[structNoCase]()), + }, { + name: jsontest.Name("Structs/NoCase/Merge/RejectDuplicateNames/Ambiguous"), opts: []Options{jsontext.AllowDuplicateNames(false)}, inBuf: `{"AaA":"AaA","aaa":"aaa"}`, inVal: new(structNoCase), want: addr(structNoCase{AaA: "AaA"}), - wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AaA":"AaA",`)), + wantErr: EU(errAmbiguousName).withPos(`{"AaA":"AaA",`, "/aaa").withType('"', T[structNoCase]()), }, { name: jsontest.Name("Structs/CaseSensitive"), inBuf: `{"BOOL": true, "STRING": "hello", "BYTES": "AQID", "INT": -64, "UINT": 64, "FLOAT": 3.14159}`, @@ -7271,17 +7285,11 @@ inBuf: `{"AAA":"after"}`, inVal: addr(structNoCaseEmbedTextValue{AAA: "before"}), want: addr(structNoCaseEmbedTextValue{AAA: "after"}), }, { - name: jsontest.Name("Structs/DuplicateName/NoCase/NoCaseConflict"), - inBuf: `{"aaa":"aaa","aaA":"aaA"}`, - inVal: addr(structNoCaseEmbedTextValue{}), - want: addr(structNoCaseEmbedTextValue{AaA: "aaa"}), - wantErr: newDuplicateNameError("", []byte(`"aaA"`), len64(`{"aaa":"aaa",`)), - }, { - name: jsontest.Name("Structs/DuplicateName/NoCase/OverwriteNoCase"), - inBuf: `{"aaa":"aaa","aaA":"aaA"}`, + name: jsontest.Name("Structs/AmbiguousName/NoCase"), + inBuf: `{"aaa":"aaa"}`, inVal: addr(structNoCaseEmbedTextValue{}), - want: addr(structNoCaseEmbedTextValue{AaA: "aaa"}), - wantErr: newDuplicateNameError("", []byte(`"aaA"`), len64(`{"aaa":"aaa",`)), + want: addr(structNoCaseEmbedTextValue{}), + wantErr: EU(errAmbiguousName).withPos(`{`, "/aaa").withType('"', T[structNoCaseEmbedTextValue]()), }, { name: jsontest.Name("Structs/DuplicateName/Embed/Unknown"), inBuf: `{"unknown":""}`, diff --git a/src/encoding/json/v2/doc.go b/src/encoding/json/v2/doc.go index b6c8448d46c520ccd040a8cab1d414ddee9b0a73..21262e2a079bc5815b99544570a81e5844787dab 100644 --- a/src/encoding/json/v2/doc.go +++ b/src/encoding/json/v2/doc.go @@ -97,7 +97,8 @@ // The option is a key-value pair specified as "case:value" where // the value must either be 'ignore' or 'strict'. // The 'ignore' value specifies that matching is case-insensitive // where dashes and underscores are also ignored. If multiple fields match, -// the first declared field in breadth-first order takes precedence. +// then the field with an exact name match is selected, otherwise an error +// is reported due to an ambiguous set of candidate fields to unmarshal into. // The 'strict' value specifies that matching is case-sensitive. // This takes precedence over the [MatchCaseInsensitiveNames] option. // diff --git a/src/encoding/json/v2/errors.go b/src/encoding/json/v2/errors.go index fd9431dadc3d0cfeea8227bfdc5773f96b1c0818..cbaf95c00ab649cceabca212543ddd4dcebe50af 100644 --- a/src/encoding/json/v2/errors.go +++ b/src/encoding/json/v2/errors.go @@ -39,6 +39,10 @@ // // This error is only returned if [RejectUnknownMembers] is true. var ErrUnknownName = errors.New("unknown object member name") +// errAmbiguousName indicates a JSON object member could be unmarshal +// into multiple candidate Go struct fields. +var errAmbiguousName = errors.New("ambiguous object member name") + const errorPrefix = "json: " func isSemanticError(err error) bool { @@ -396,9 +400,9 @@ sb.WriteString(typeString) } // Special handling for unknown names. - if e.Err == ErrUnknownName { + if e.Err == ErrUnknownName || e.Err == errAmbiguousName { sb.WriteString(": ") - sb.WriteString(ErrUnknownName.Error()) + sb.WriteString(e.Err.Error()) sb.WriteString(" ") sb.WriteString(strconv.Quote(e.JSONPointer.LastToken())) if parent := e.JSONPointer.Parent(); parent != "" { diff --git a/src/encoding/json/v2/options.go b/src/encoding/json/v2/options.go index f6d132a9ce9747442fa9333d096529aa10ac00ea..ebb311cfa8c90177b8bedb0323e9cea5c70ab1ea 100644 --- a/src/encoding/json/v2/options.go +++ b/src/encoding/json/v2/options.go @@ -82,6 +82,7 @@ } // GetOption returns the value stored in opts with the provided setter, // reporting whether the value is present. +// If not present, the returned value is the zero value for type T. // // Example usage: // @@ -188,14 +189,25 @@ } // MatchCaseInsensitiveNames specifies that JSON object members are matched // against Go struct fields using a case-insensitive match of the name. +// If a name matches multiple fields, it chooses the field with an exact +// match of the name, otherwise it reports an error. // Go struct fields explicitly marked with `case:strict` or `case:ignore` // always use case-sensitive (or case-insensitive) name matching, // regardless of the value of this option. // // This affects either marshaling or unmarshaling. -// For marshaling, this option may alter the detection of duplicate names -// (assuming [jsontext.AllowDuplicateNames] is false) from embedded fields -// if it matches one of the declared fields in the Go struct. +// +// By matching names in a case-insensitive manner, it also affects the detection +// of duplicate names (assuming [jsontext.AllowDuplicateNames] is false) since +// variations of the same name may match the same Go struct field. +// For example, when unmarshaling, the names "foo" and "Foo" may both +// match the same Go struct field and therefore be considered a duplicate name. +// When marshaling, normally it is impossible for any two Go struct fields to +// serialize in a way where they unmarshal into the same Go struct field +// since they all have unique exact names. +// However, with the use of an embedded fallback, it is possible for the +// embedded fallback to contain a name that also matches the name for +// a Go struct field, resulting in a duplicate name error. func MatchCaseInsensitiveNames(v bool) Options { if v { return jsonflags.MatchCaseInsensitiveNames | 1 diff --git a/src/encoding/json/v2_options.go b/src/encoding/json/v2_options.go index a4de2e638e9c85316da886c4e62996621b328bc1..0ce601a0234cd48944efdef0713eb470a7fbf013 100644 --- a/src/encoding/json/v2_options.go +++ b/src/encoding/json/v2_options.go @@ -460,6 +460,11 @@ // (e.g., conflicting names or malformed field tags), then such errors // are ignored and the Go struct uses a best-effort representation. // In contrast, the v2 semantic is to report a runtime error. // +// - When unmarshaling with [jsonv2.MatchCaseInsensitiveNames], if a JSON +// object name has a non-exact match with multiple Go struct fields, then +// an error is not reported and instead the first declared field is used. +// In contrast, the v2 semantic is to report a runtime error. +// // - When unmarshaling, the syntactic structure of the JSON input // is fully validated before performing the semantic unmarshaling // of the JSON data into the Go value. Practically speaking, diff --git a/src/fmt/doc.go b/src/fmt/doc.go index 49365eedf72640d9729a94f97b252cf06942abac..a6724e6a336f53cba240990a1fcfed00058cdde5 100644 --- a/src/fmt/doc.go +++ b/src/fmt/doc.go @@ -43,7 +43,7 @@ %c the character represented by the corresponding Unicode code point %d base 10 %o base 8 %O base 8 with 0o prefix - %q a single-quoted character literal safely escaped with Go syntax. + %q a single-quoted rune literal safely escaped with Go syntax. %x base 16, with lower-case letters for a-f %X base 16, with upper-case letters for A-F %U Unicode format: U+1234; same as "U+%04X" diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index f65e709a72f6af725a35e03df12ebb21ff05243b..4959a42189299650ecbf542ddaf740460be187db 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -781,6 +781,9 @@ crypto/internal/cryptotest, encoding/hex < crypto/internal/cryptotest/wycheproof; + FMT, encoding/json, time, regexp + < crypto/internal/cryptotest/x509limbo; + CGO, FMT < crypto/internal/sysrand/internal/seccomp; diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 018998485d6459dfb8b1ae9fc96bec6b472227cd..6b48982eba3a2cd19a441d598fa59a24571e0f2a 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -260,7 +260,7 @@ if Ti == nil { if cause != nil { var detail string if isInterfacePtr(Tu) { - detail = check.sprintf("type %s is pointer to interface, not interface", T) + detail = check.interfacePtrError(T) } else { detail = check.sprintf("%s is not an interface", T) } diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index 9b49b0dc3b03134fea54be53908e0332c19fd2c5..d4ff0aff80c9305feeea85863cec617319a968a3 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -358,6 +358,7 @@ var excluded = map[string]bool{ "builtin": true, "cmd/compile/internal/ssa/_gen": true, "crypto/internal/cryptotest/wycheproof/_schema": true, + "crypto/internal/cryptotest/x509limbo/_schema": true, "runtime/_mkmalloc": true, "simd/archsimd/_gen/midway": true, "simd/archsimd/_gen/sgutil": true, diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 5a106c7919fc7b5a2f48bd355918735441805f03..b29bf2ff017daa83855e4515cedf4ea3a73a0450 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -339,7 +339,11 @@ w.tParamList(t.TypeParams().list()) } if w.ctxt != nil { // TODO(gri) do we need to print the alias type name, too? - w.typ(Unalias(t.obj.typ)) + typ := Unalias(t.obj.typ) + if typ == nil { + panic("known implementation limitation: encountered an incomplete alias (see go.dev/issue/78296)") + } + w.typ(typ) } default: diff --git a/src/internal/nettest/conn_test.go b/src/internal/nettest/conn_test.go index afd98ea611b8af395c5b3def71aca28322070756..d7c6830e0a4e882e8f6112a92c462be1e1acb75b 100644 --- a/src/internal/nettest/conn_test.go +++ b/src/internal/nettest/conn_test.go @@ -88,6 +88,7 @@ } if want := data[:readSize]; !bytes.Equal(got, want) { t.Errorf("read %q, want %q", got, want) } + synctest.Wait() rconn.Close() }() n, err := wconn.Write(data) diff --git a/src/internal/runtime/maps/map.go b/src/internal/runtime/maps/map.go index 0a0dd359d161fe71fee7290739c4f7c61c7ae2c9..0ee5e09bf05bc5c655bc2fde3b642a26d15bc2bb 100644 --- a/src/internal/runtime/maps/map.go +++ b/src/internal/runtime/maps/map.go @@ -177,6 +177,25 @@ // // For (b), we must adjust the current directory index when the directory // grows. This is more straightforward, as the directory orders remains the // same after grow, so we just double the index if the directory size doubles. +// +// Hashing Pointers +// +// Keys in Go maps can be pointers, or contain pointers. The hash of +// a pointer is a somewhat tricky concept, as pointers to stack +// objects can change during a stack copy. Because we hash a pointer +// by just hashing its uintptr-converted value, the hash of a key can +// potentially become stale across any stack copy. +// +// For keys that are stored into maps, we must avoid this. All key +// arguments to map assignments must have their pointer targets marked +// as escaping so that the hash of the key in the map is stable. This +// is true even when the map itself does not escape and can live on +// the stack. +// +// For keys that are used for lookup (or delete), it turns out that +// escaping is not required. If we are looking up a pointer which +// points to the stack, the hash value is ~irrelevant, as the key is +// guaranteed to not be in the map (due to the previous paragraph). // Extracts the H1 portion of a hash: the 57 upper bits. // TODO(prattmic): what about 32-bit systems? diff --git a/src/internal/types/testdata/fixedbugs/issue79883.go b/src/internal/types/testdata/fixedbugs/issue79883.go new file mode 100644 index 0000000000000000000000000000000000000000..504f625155d81b7a6f4aaf54b6c0095b1043cb6e --- /dev/null +++ b/src/internal/types/testdata/fixedbugs/issue79883.go @@ -0,0 +1,9 @@ +// 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. + +package p + +func _[P []byte](p string) { + _ = (*P)(p /* ERROR "pointer to type parameter" */) +} diff --git a/src/log/slog/handler.go b/src/log/slog/handler.go index 26eb4b82fc8b5742933808d9677ebd75a58bfd39..691a0807d751861524a3bcd8bded51ff559a88a0 100644 --- a/src/log/slog/handler.go +++ b/src/log/slog/handler.go @@ -204,7 +204,6 @@ w io.Writer } func (h *commonHandler) clone() *commonHandler { - // We can't use assignment because we can't copy the mutex. return &commonHandler{ json: h.json, opts: h.opts, diff --git a/src/math/big/floatconv_test.go b/src/math/big/floatconv_test.go index a1cc38a4596c5b3f8d67b9506c4a6329eeb848d6..fbf234f5d983502db788f4b90014d82216de0795 100644 --- a/src/math/big/floatconv_test.go +++ b/src/math/big/floatconv_test.go @@ -384,6 +384,25 @@ } return 53 } +func TestRoundShortestNormal(t *testing.T) { + // See go.dev/issue/80206. + text := func(x float64) string { + return new(Float).SetPrec(53).SetFloat64(x).Text('g', -1) + } + for _, x := range []float64{ + 4.3749999999999917e+17, + 4.9999999999999917e+17, + 4.7619047619047597e+17, + 3.7499999999999917e+17, + 1.9047619047619039e+18, + 1.1138394197049199e+18, // m='9' at trimmed position; guard must reject round-up + } { + if got, want := text(x), strconv.FormatFloat(x, 'g', -1, 64); got != want { + t.Errorf("got %s, want %s", got, want) + } + } +} + func TestFloatText(t *testing.T) { const defaultRound = ^RoundingMode(0) @@ -710,7 +729,7 @@ } } func BenchmarkParseFloatSmallExp(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { for _, s := range []string{ "1e0", "1e-1", @@ -740,7 +759,7 @@ } } func BenchmarkParseFloatLargeExp(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { for _, s := range []string{ "1e0", "1e-10", @@ -774,7 +793,7 @@ } } func TestFloatScan(t *testing.T) { - var floatScanTests = []struct { + floatScanTests := []struct { input string format string output string diff --git a/src/math/big/ftoa.go b/src/math/big/ftoa.go index c94fbeee440189b3516ec7509ae6d29a79d763bb..d9c0ced381fbab081e3057192eaa00c9685acf32 100644 --- a/src/math/big/ftoa.go +++ b/src/math/big/ftoa.go @@ -4,7 +4,7 @@ // license that can be found in the LICENSE file. // This file implements Float-to-string conversion functions. // It is closely following the corresponding implementation -// in strconv/ftoa.go, but modified and simplified for Float. +// in internal/strconv/ftoa.go, but modified and simplified for Float. package big @@ -44,6 +44,10 @@ // For 'g' and 'G' it is the total number of digits. A negative precision selects // the smallest number of decimal digits necessary to identify the value x uniquely // using x.Prec() mantissa bits. // The prec value is ignored for the 'b' and 'p' formats. +// +// Note that Text may return a different result than strconv.FormatFloat for +// corresponding arguments if the matching float32 or float64 number provided +// to strconv.FormatFloat is a denormalized number. func (x *Float) Text(format byte, prec int) string { cap := 10 // TODO(gri) determine a good/better value here if prec > 0 { @@ -177,9 +181,6 @@ // (possibly exclusive) round to x for the given precision of x. // Compute the lower and upper bound in decimal form and find the // shortest decimal number d such that lower <= d <= upper. - // TODO(gri) strconv/ftoa.do describes a shortcut in some cases. - // See if we can use it (in adjusted form) here as well. - // 1) Compute normalized mantissa mant and exponent exp for x such // that the lsb of mant corresponds to 1/2 ulp for the precision of // x (i.e., for mant we want x.prec + 1 bits). @@ -222,7 +223,12 @@ okdown := l != m || inclusive && i+1 == len(lower.mant) // Okay to round up if upper has a different digit and either upper // is inclusive or upper is bigger than the result of rounding up. - okup := m != u && (inclusive || m+1 < u || i+1 < len(upper.mant)) + // The last clause handles digits past upper's trimmed mantissa: + // upper.at(i) returns '0' there, but the true upper bound was + // determined by earlier digits, so rounding up is valid unless + // m == '9' (which would carry onto the exclusive upper bound). + // See also go.dev/issue/80206. + okup := m != u && (inclusive || m+1 < u || i+1 < len(upper.mant) || i >= len(upper.mant) && m < '9') // If it's okay to do either, then round to the nearest one. // If it's okay to do only one, do it. diff --git a/src/math/rand/v2/rand.go b/src/math/rand/v2/rand.go index 662e84fd70f5f0f313299e4389490f4fed18f8ea..991c184e819ae426e7b4ec7a0c9384d4a8579994 100644 --- a/src/math/rand/v2/rand.go +++ b/src/math/rand/v2/rand.go @@ -12,6 +12,9 @@ // // Top-level functions, such as [Float64] and [Int], // are safe for concurrent use by multiple goroutines. // +// The [ChaCha8] source is a general-purpose source resistant to prediction. +// The [PCG] source is faster but unfit for security-relevant purposes. +// // This package's outputs might be easily predictable regardless of how it's // seeded. For random numbers suitable for security-sensitive work, see the // [crypto/rand] package. diff --git a/src/net/http/http2.go b/src/net/http/http2.go index bb752a68943b855073432cc7280e986738c8b26e..301aff7a6f27af3f0a57063853ece303d9955867 100644 --- a/src/net/http/http2.go +++ b/src/net/http/http2.go @@ -186,7 +186,8 @@ type http2ServerConfig struct { s *Server } -func (s http2ServerConfig) MaxHeaderBytes() int { return s.s.MaxHeaderBytes } +func (s http2ServerConfig) MaxHeaderBytes() int { return s.s.MaxHeaderBytes } +func (s http2ServerConfig) MaxHeaderValueCount() int { return s.s.maxHeaderValueCount() } func (s http2ServerConfig) ConnState(c net.Conn, st http2.ConnState) { if s.s.ConnState != nil { s.s.ConnState(c, ConnState(st)) diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go index 8c994827255cc9067b0da7c62e8f3a5ea2353b25..ba9b507cd1587c0ee772d5f5d0b1f9510d394936 100644 --- a/src/net/http/httputil/reverseproxy.go +++ b/src/net/http/httputil/reverseproxy.go @@ -22,7 +22,6 @@ "net/textproto" "net/url" "strings" "sync" - "sync/atomic" "time" "golang.org/x/net/http/httpguts" @@ -437,18 +436,6 @@ if req.ContentLength == 0 { outreq.Body = nil // Issue 16036: nil Body for http.Transport retries } if outreq.Body != nil { - // Wrap the body in a reader where Close does nothing. This is done - // because p.Transport.RoundTrip would close the reverse proxy's - // outbound request body if it fails to connect to upstream. If we do - // not wrap the body, when we close the reverse proxy's outbound - // request, it will also close the reverse proxy's inbound request body - // (i.e. the client's outbound request body). This is because - // http.(*Request).Clone creates a shallow copy of the body. This can - // cause an infinite hang in cases where the body is not yet received - // from the client (e.g. 100-continue requests): Close, which - // internally tries to consume the body content, would be called too - // early and would hang. - outreq.Body = &noopCloseReader{readCloser: outreq.Body} // Reading from the request body after returning from a handler is not // allowed, and the RoundTrip goroutine that reads the Body can outlive // this handler. This can lead to a crash if the handler panics (see @@ -968,20 +955,3 @@ return true } return false } - -type noopCloseReader struct { - readCloser io.ReadCloser - closed atomic.Bool -} - -func (ncr *noopCloseReader) Close() error { - ncr.closed.Store(true) - return nil -} - -func (ncr *noopCloseReader) Read(p []byte) (int, error) { - if ncr.closed.Load() { - return 0, errors.New("ReverseProxy does an invalid Read on closed Body") - } - return ncr.readCloser.Read(p) -} diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go index ef78ba4b0f69213b261bc02ec61d5e222b94308a..aa26d900cee8f2cbecf66c15ba845395dbf9f0a0 100644 --- a/src/net/http/httputil/reverseproxy_test.go +++ b/src/net/http/httputil/reverseproxy_test.go @@ -2155,44 +2155,6 @@ req.Header.Set("Upgrade", "someproto") proxyHandler.ServeHTTP(rw, req) } -// https://go.dev/issue/75933. -func TestReverseProxyInvalidUpstream100ContinueDoNotHang(t *testing.T) { - proxy := ReverseProxy{ - Transport: &http.Transport{DisableKeepAlives: true, ExpectContinueTimeout: time.Second * 60}, - Director: func(request *http.Request) { - request.URL.Scheme = "http" - request.URL.Host = "doesnotexist:12345" // non-existent upstream - }, - } - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - proxy.ServeHTTP(w, r) - }) - upstreamServer := httptest.NewServer(handler) - defer upstreamServer.Close() - - conn, err := net.Dial("tcp", upstreamServer.Listener.Addr().String()) - if err != nil { - t.Fatal(err) - } - defer conn.Close() - - requestBody := `{"test": "data"}` - initialRequest := fmt.Sprintf("POST %s/test-expect HTTP/1.1\r\n"+ - "Host: %s\r\n"+ - "Content-Type: application/json\r\n"+ - "Content-Length: %d\r\n"+ - "Expect: 100-continue\r\n"+ - "\r\n", upstreamServer.URL, upstreamServer.Listener.Addr().String(), len(requestBody)) - - if _, err := conn.Write([]byte(initialRequest)); err != nil { - log.Fatal(err) - } - buff := make([]byte, 1024) - if _, err := conn.Read(buff); err != nil { - log.Fatal(err) - } -} - type testResponseWriter struct { h http.Header writeHeader func(int) diff --git a/src/net/http/internal/http2/api.go b/src/net/http/internal/http2/api.go index f208d525de82640b5c0bdc52ef77ca2a052b8fa7..1728bc32b14ef90cc77b5de507c668a5533223a7 100644 --- a/src/net/http/internal/http2/api.go +++ b/src/net/http/internal/http2/api.go @@ -107,6 +107,7 @@ // ServerConfig is configuration from an http.Server. type ServerConfig interface { MaxHeaderBytes() int + MaxHeaderValueCount() int ConnState(net.Conn, ConnState) DoKeepAlives() bool WriteTimeout() time.Duration diff --git a/src/net/http/internal/http2/frame.go b/src/net/http/internal/http2/frame.go index a2de8c271904f04313b7c63a775c8cbb55e800d3..e3b371acec42a3b7364abafac6205c2a23bdb09f 100644 --- a/src/net/http/internal/http2/frame.go +++ b/src/net/http/internal/http2/frame.go @@ -333,6 +333,12 @@ // (currently 16MB) // If the limit is hit, MetaHeadersFrame.Truncated is set true. MaxHeaderListSize uint32 + // MaxHeaderValueCount is the maximum permitted number of + // header values. + // It's used only if ReadMetaHeaders is set; 0 means no limit. + // If the limit is hit, MetaHeadersFrame.Truncated is set true. + MaxHeaderValueCount int + // TODO: track which type of frame & with which flags was sent // last. Then return an error (unless AllowIllegalWrites) if // we're in the middle of a header block and a @@ -354,6 +360,10 @@ if fr.MaxHeaderListSize == 0 { return 16 << 20 // sane default, per docs } return fr.MaxHeaderListSize +} + +func (fr *Framer) maxHeaderValueCount() int { + return fr.MaxHeaderValueCount } func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) { @@ -1715,6 +1725,7 @@ HeadersFrame: hf, } var remainSize = fr.maxHeaderListSize() var sawRegular bool + var headerCount int var invalid error // pseudo header field errors hdec := fr.ReadMetaHeaders @@ -1723,6 +1734,13 @@ hdec.SetMaxStringLength(fr.maxHeaderStringLen()) hdec.SetEmitFunc(func(hf hpack.HeaderField) { if VerboseLogs && fr.logReads { fr.debugReadLoggerf("http2: decoded hpack field %+v", hf) + } + headerCount++ + if limit := fr.maxHeaderValueCount(); limit > 0 && headerCount > limit { + hdec.SetEmitEnabled(false) + mh.Truncated = true + remainSize = 0 + return } if !httpguts.ValidHeaderFieldValue(hf.Value) { // Don't include the value in the error, because it may be sensitive. diff --git a/src/net/http/internal/http2/server.go b/src/net/http/internal/http2/server.go index 49abd85ea3fe18aab7e9b3a887232c2211cd5ecb..aed43b255a8fc9bca19a895d0f5e6bbfdf56a341 100644 --- a/src/net/http/internal/http2/server.go +++ b/src/net/http/internal/http2/server.go @@ -321,6 +321,7 @@ fr.countError = conf.CountError } fr.ReadMetaHeaders = hpack.NewDecoder(uint32(conf.MaxDecoderHeaderTableSize), nil) fr.MaxHeaderListSize = sc.maxHeaderListSize() + fr.MaxHeaderValueCount = sc.hs.MaxHeaderValueCount() fr.SetMaxReadFrameSize(uint32(conf.MaxReadFrameSize)) sc.framer = fr @@ -2029,6 +2030,9 @@ } if len(f.PseudoFields()) > 0 { return sc.countError("trailers_pseudo", streamError(st.id, ErrCodeProtocol)) + } + if f.Truncated { + return sc.countError("trailers_too_large", streamError(st.id, ErrCodeProtocol)) } if st.trailer != nil { for _, hf := range f.RegularFields() { diff --git a/src/net/http/request.go b/src/net/http/request.go index a95e9916813667fe390892d12dd89cd81dfa7463..e07088fae53b4a3f6d2e6626abb3a23d2d46a0c0 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -16,6 +16,7 @@ "errors" "fmt" "io" "maps" + "math" "mime" "mime/multipart" "net/http/httptrace" @@ -1074,6 +1075,11 @@ delete(req.Header, "Host") return req, nil } +// readMIMEHeader is defined in package [net/textproto]. +// +//go:linkname readMIMEHeader net/textproto.readMIMEHeader +func readMIMEHeader(r *textproto.Reader, maxMemory, maxHeaders int64) (textproto.MIMEHeader, error) + // readRequest should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: @@ -1086,6 +1092,10 @@ // See go.dev/issue/67401. // //go:linkname readRequest func readRequest(b *bufio.Reader) (req *Request, err error) { + return readRequestLimit(b, math.MaxInt64) +} + +func readRequestLimit(b *bufio.Reader, maxHeaders int64) (req *Request, err error) { tp := newTextprotoReader(b) defer putTextprotoReader(tp) @@ -1139,8 +1149,12 @@ req.URL.Scheme = "" } // Subsequent lines: Key: value. - mimeHeader, err := tp.ReadMIMEHeader() + mimeHeader, err := readMIMEHeader(tp, math.MaxInt64, maxHeaders) if err != nil { + // TODO: Add a distinguishable error to net/textproto. + if err.Error() == "message too large" { + return nil, errTooLarge + } return nil, err } req.Header = Header(mimeHeader) diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 7e8398485ab4df0108174bb00c7aebc6f56fb3c2..08fbf356766f6948b804efab27f1923220a88f1b 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -308,6 +308,7 @@ {"/search", serve(201)}, {"codesearch.google.com/search", serve(202)}, {"codesearch.google.com/", serve(203)}, {"example.com/", HandlerFunc(checkQueryStringHandler)}, + {"/pkg/bar/extra%2fpath", serve(200)}, } // serve returns a handler that sends a response with the given code. @@ -427,6 +428,9 @@ }{ {"GET", "google.com", "/", 404, false}, {"GET", "example.com", "/test/?example.com/test/", 200, false}, {"GET", "example.com", "test/?example.com/test/", 200, true}, + {"GET", "google.com", "/pkg/bar//extra%2fpath", 200, true}, + {"GET", "google.com", "/dir/b%2fc/..", 200, true}, + {"GET", "google.com", "/doesnotexist/b%2fc/..", 404, true}, } // TestServeMuxHandlerRedirects tests that automatic redirects generated by @@ -601,6 +605,7 @@ mux.Handle("example.com/pkg/bar/", stringHandler("example.com/pkg/bar/")) mux.Handle("example.com:3000/pkg/connect/", stringHandler("example.com:3000/pkg/connect/")) mux.Handle("example.com:9000/", stringHandler("example.com:9000/")) mux.Handle("/pkg/baz/", stringHandler("/pkg/baz/")) + mux.Handle("example.com/a%2fb/", stringHandler("example.com/a%2fb/")) tests := []struct { method string @@ -622,6 +627,7 @@ {"CONNECT", "http://example.com/pkg/foo", 307, "/pkg/foo/", ""}, {"CONNECT", "http://example.com:3000/pkg/foo", 404, "", ""}, {"CONNECT", "http://example.com:3000/pkg/baz", 307, "/pkg/baz/", ""}, {"CONNECT", "http://example.com:3000/pkg/connect", 307, "/pkg/connect/", ""}, + {"GET", "http://example.com/a%2fb", 307, "/a%2fb/", ""}, } for i, tt := range tests { @@ -633,7 +639,7 @@ if got, want := w.Code, tt.code; got != want { t.Errorf("#%d: Status = %d; want = %d", i, got, want) } - if tt.code == 301 { + if tt.code == 307 { if got, want := w.HeaderMap.Get("Location"), tt.loc; got != want { t.Errorf("#%d: Location = %q; want = %q", i, got, want) } @@ -3292,12 +3298,16 @@ } func TestRequestLimit(t *testing.T) { run(t, testRequestLimit, http3SkippedMode) } func testRequestLimit(t *testing.T, mode testMode) { + bytesPerHeader := len("header12345: val12345\r\n") + numHeaders := ((DefaultMaxHeaderBytes + 4096) / bytesPerHeader) + 1 + cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { t.Fatalf("didn't expect to get request in Handler") - }), optQuietLog) + }), func(s *Server) { + s.MaxHeaderValueCount = numHeaders + }, optQuietLog) req, _ := NewRequest("GET", cst.ts.URL, nil) - var bytesPerHeader = len("header12345: val12345\r\n") - for i := 0; i < ((DefaultMaxHeaderBytes+4096)/bytesPerHeader)+1; i++ { + for i := range numHeaders { req.Header.Set(fmt.Sprintf("header%05d", i), fmt.Sprintf("val%05d", i)) } res, err := cst.c.Do(req) @@ -3323,6 +3333,164 @@ } if res.StatusCode != 431 { t.Fatalf("expected 431 response status; got: %d %s", res.StatusCode, res.Status) } + } +} + +func TestRequestHeaderValueCountLimit(t *testing.T) { + run(t, testRequestHeaderValueCountLimit, http3SkippedMode) +} +func testRequestHeaderValueCountLimit(t *testing.T, mode testMode) { + tests := []struct { + name string + limit int + setup func(req *Request) + wantStatus int + }{ + { + name: "below limit", + limit: 15, + setup: func(req *Request) { + // Send considerably below the limit, to account for the client + // automatically adding pseudo-headers and headers that it can + // infer. + for i := range 5 { + req.Header.Add(fmt.Sprintf("X-Header-%d", i), "val") + } + }, + wantStatus: 200, + }, + { + name: "above limit", + limit: 15, + setup: func(req *Request) { + for i := range 16 { + req.Header.Add(fmt.Sprintf("X-Header-%d", i), "val") + } + }, + wantStatus: 431, + }, + { + name: "comma separated values count as one", + limit: 15, + setup: func(req *Request) { + vals := make([]string, 16) + for i := range vals { + vals[i] = "val" + } + req.Header.Add("X-Comma", strings.Join(vals, ", ")) + }, + wantStatus: 200, + }, + { + name: "multiple values count as multiple", + limit: 15, + setup: func(req *Request) { + for range 16 { + req.Header.Add("X-Repeated", "val") + } + }, + wantStatus: 431, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { + w.WriteHeader(StatusOK) + }), func(s *Server) { + s.MaxHeaderValueCount = tt.limit + }, optQuietLog) + + req, _ := NewRequest("GET", cst.ts.URL, nil) + tt.setup(req) + + res, err := cst.c.Do(req) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + if res.StatusCode != tt.wantStatus { + t.Errorf("got status %d, want %d", res.StatusCode, tt.wantStatus) + } + }) + } +} + +func TestRequestTrailerHeaderValueCountLimit(t *testing.T) { + // HTTP/1 has a static limit for trailer headers that are not affected by + // settings such as MaxHeaderBytes and MaxHeaderValueCount. + run(t, testRequestTrailerHeaderValueCountLimit, []testMode{http2Mode}) +} +func testRequestTrailerHeaderValueCountLimit(t *testing.T, mode testMode) { + tests := []struct { + name string + limit int + setup func(req *Request) + wantErr bool + }{ + { + name: "below limit", + limit: 15, + setup: func(req *Request) { + req.Trailer = make(Header) + for i := range 14 { + req.Trailer.Add(fmt.Sprintf("X-Trailer-%d", i), "val") + } + }, + }, + { + name: "above limit", + limit: 15, + setup: func(req *Request) { + req.Trailer = make(Header) + for i := range 16 { + req.Trailer.Add(fmt.Sprintf("X-Trailer-%d", i), "val") + } + }, + wantErr: true, + }, + { + name: "comma separated values count as one", + limit: 15, + setup: func(req *Request) { + req.Trailer = make(Header) + vals := make([]string, 16) + for i := range vals { + vals[i] = "val" + } + req.Trailer.Add("X-Comma-Trailer", strings.Join(vals, ", ")) + }, + }, + { + name: "multiple values count as multiple", + limit: 15, + setup: func(req *Request) { + req.Trailer = make(Header) + for range 16 { + req.Trailer.Add("X-Repeated-Trailer", "val") + } + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { + io.Copy(io.Discard, r.Body) + }), func(s *Server) { + s.MaxHeaderValueCount = tt.limit + }, optQuietLog) + + req, _ := NewRequest("GET", cst.ts.URL, strings.NewReader("some body")) + tt.setup(req) + + res, err := cst.c.Do(req) + if (err != nil) != tt.wantErr { + t.Fatalf("got error %v, want %v", err, tt.wantErr) + } + if err == nil { + res.Body.Close() + } + }) } } @@ -7547,6 +7715,36 @@ res.Body.Close() } readyc <- struct{}{} // server starts reading from the request body readyc <- struct{}{} // server finishes reading from the request body +} + +// Issue 75933. +func TestServerExpect100ContinueUnreadBody(t *testing.T) { + run(t, testServerExpect100ContinueUnreadBody) +} +func testServerExpect100ContinueUnreadBody(t *testing.T, mode testMode) { + cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { + w.WriteHeader(StatusOK) + // Make sure that Read after not sending status 100 does not hang. + // TODO: Read in this situation should return an error. + io.ReadAll(r.Body) + })) + + req, _ := NewRequest("POST", cst.ts.URL, strings.NewReader("some body")) + req.Header.Set("Expect", "100-continue") + + // Set a short timeout on the client to catch the hang quickly. + cst.c.Timeout = 2 * time.Second + cst.tr.ExpectContinueTimeout = 10 * time.Second + + resp, err := cst.c.Do(req) + if err != nil { + t.Fatalf("Request failed: %v (likely due to hang)", err) + } + defer resp.Body.Close() + + if resp.StatusCode != StatusOK { + t.Errorf("expected 200 OK, got %v", resp.Status) + } } func TestInvalidChunkedBodies(t *testing.T) { diff --git a/src/net/http/server.go b/src/net/http/server.go index 933dcc95f26a08c6ef498e405a29788d712cf3f1..d193dcd45c37772ba2d27596aab0f2876ba202a9 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -570,11 +570,30 @@ w.Header().Set("Connection", "close") } } -// disableWriteContinue stops Request.Body.Read from sending an automatic 100-Continue. -// If a 100-Continue is being written, it waits for it to complete before continuing. -func (w *response) disableWriteContinue() { +// disableWriteContinue stops Request.Body.Read from sending an automatic +// 100 Continue. As the name implies, it is only useful when the request +// expects a 100 Continue and the body is wrapped in an expectContinueReader; +// otherwise, it is a no-op. +// If a 100-Continue is being written, it waits for it to complete before +// continuing. If skipDrain is true, it also prevents the server from draining +// the request body and flags the connection to be closed after the reply, as +// the client will never send the body. +func (w *response) disableWriteContinue(skipDrain bool) { + ecr, ok := w.reqBody.(*expectContinueReader) + if !ok { + return + } w.writeContinueMu.Lock() - w.canWriteContinue.Store(false) + if w.canWriteContinue.Load() { + w.canWriteContinue.Store(false) + if skipDrain { + // Make sure that the connection will not be reused by sending + // "Connection: close" header in the response. + w.closeAfterReply = true + // Ensure that the body will not be drained in Close. + ecr.closed.Store(true) + } + } w.writeContinueMu.Unlock() } @@ -919,6 +938,11 @@ // in an HTTP request. // This can be overridden by setting [Server.MaxHeaderBytes]. const DefaultMaxHeaderBytes = 1 << 20 // 1 MB +// DefaultMaxHeaderValueCount is the maximum permitted number of +// header values in an HTTP request. +// This can be overridden by setting [Server.MaxHeaderValueCount]. +const DefaultMaxHeaderValueCount = 500 + func (s *Server) maxHeaderBytes() int { if s.MaxHeaderBytes > 0 { return s.MaxHeaderBytes @@ -926,6 +950,13 @@ } return DefaultMaxHeaderBytes } +func (s *Server) maxHeaderValueCount() int { + if s.MaxHeaderValueCount > 0 { + return s.MaxHeaderValueCount + } + return DefaultMaxHeaderValueCount +} + func (s *Server) initialReadLimitSize() int64 { return int64(s.maxHeaderBytes()) + 4096 // bufio slop } @@ -983,7 +1014,12 @@ return } func (ecr *expectContinueReader) Close() error { - ecr.closed.Store(true) + if ecr.resp.canWriteContinue.Load() { + ecr.resp.disableWriteContinue(true) + } + if ecr.closed.Swap(true) { + return nil + } return ecr.readCloser.Close() } @@ -1027,7 +1063,7 @@ // RFC 7230 section 3 tolerance for old buggy clients. peek, _ := c.bufr.Peek(4) // ReadRequest will get err below c.bufr.Discard(numLeadingCRorLF(peek)) } - req, err := readRequest(c.bufr) + req, err := readRequestLimit(c.bufr, int64(c.server.maxHeaderValueCount())) if err != nil { if c.r.hitReadLimit() { return nil, errTooLarge @@ -1185,10 +1221,12 @@ return } checkWriteHeaderCode(code) - if code < 101 || code > 199 { - // Sending a 100 Continue or any non-1xx header disables the - // automatically-sent 100 Continue from Request.Body.Read. - w.disableWriteContinue() + // Sending a 100 Continue or any non-1XX header disables the + // automatically-sent 100 Continue from Request.Body.Read. If it is a final + // response (200 or higher), we skip draining the request body, which the + // client will never send. + if code == 100 || code >= 200 { + w.disableWriteContinue(code >= 200) } // Handle informational headers. @@ -1663,7 +1701,7 @@ } if w.canWriteContinue.Load() { // Body reader wants to write 100 Continue but hasn't yet. Tell it not to. - w.disableWriteContinue() + w.disableWriteContinue(true) } if !w.wroteHeader { @@ -1700,6 +1738,10 @@ w.cw.close() w.conn.bufw.Flush() w.conn.r.abortPendingRead() + + if w.canWriteContinue.Load() { + w.disableWriteContinue(true) + } // Close the body (regardless of w.closeAfterReply) so we can // re-use its bufio.Reader later safely. @@ -1931,7 +1973,7 @@ c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf) } if inFlightResponse != nil { inFlightResponse.cancelCtx() - inFlightResponse.disableWriteContinue() + inFlightResponse.disableWriteContinue(true) } if !c.hijacked() { if inFlightResponse != nil { @@ -2094,6 +2136,7 @@ if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 { // Wrap the Body reader with one that replies on the connection req.Body = &expectContinueReader{readCloser: req.Body, resp: w} w.canWriteContinue.Store(true) + w.reqBody = req.Body } } else if req.Header.get("Expect") != "" { w.sendExpectationFailed() @@ -2257,7 +2300,7 @@ func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) { if w.handlerDone.Load() { panic("net/http: Hijack called after ServeHTTP finished") } - w.disableWriteContinue() + w.disableWriteContinue(false) if w.wroteHeader { w.cw.flush() } @@ -2747,7 +2790,7 @@ patStr := "" if n != nil { patStr = n.pattern.String() } - u := &url.URL{Path: path, RawQuery: r.URL.RawQuery} + u := urlFromEscaped(path, r.URL.RawQuery) return RedirectHandler(u.String(), StatusTemporaryRedirect), patStr, nil, nil } } @@ -2792,12 +2835,35 @@ // It is safe to return n2 here: it is used only in the second RedirectHandler case // of findHandler, and that method returns before it does the "n == nil" check where // the first return value matters. We return it here only to make the pattern available // to findHandler. - return n2, nil, &url.URL{Path: cleanPath(u.Path) + "/", RawQuery: u.RawQuery} + return n2, nil, urlFromEscaped(path, u.RawQuery) } } return n, matches, nil } +// urlFromEscaped returns a url.URL constructed from an escaped path and a raw +// query. +// +// It ensures that the Path and RawPath fields are in sync by unescaping the +// escaped path. Populating only the Path field and leaving RawPath empty (or +// failing to keep them in sync) can cause url.URL.String to produce a URL with +// either unexpected escaping (e.g., double-escaping "%" into "%25" in an +// already escaped path) or a lack thereof (e.g., losing the escaping of "%2f" +// and turning it into a literal path separator "/"). +func urlFromEscaped(escaped, rawQuery string) *url.URL { + unescaped, err := url.PathUnescape(escaped) + // Should be impossible, since ServeMux will reject unparsable URLs way + // earlier. + if err != nil { + unescaped = escaped + } + return &url.URL{ + Path: unescaped, + RawPath: escaped, + RawQuery: rawQuery, + } +} + // exactMatch reports whether the node's pattern exactly matches the path. // As a special case, if the node is nil, exactMatch return false. // @@ -3076,6 +3142,14 @@ // values, including the request line. It does not limit the // size of the request body. // If zero, DefaultMaxHeaderBytes is used. MaxHeaderBytes int + + // MaxHeaderValueCount controls the maximum number of header + // values that the server is willing to parse from a request. + // If zero, DefaultMaxHeaderValueCount is used. + // Note that comma-separated values in a single header line are + // counted once, while values sent as multiple header lines are + // counted multiple times. + MaxHeaderValueCount int // TLSNextProto optionally specifies a function to take over // ownership of the provided TLS connection when an ALPN diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go index 42211ed099ed1e7fe9d96c4da7328465dfd89e58..afa7e4c14aaf1feaa4b8c92deae2fc4f2980e072 100644 --- a/src/net/lookup_test.go +++ b/src/net/lookup_test.go @@ -335,8 +335,8 @@ var lookupCNAMETests = []struct { name, cname string }{ - {"www.iana.org", "icann.org."}, - {"www.iana.org.", "icann.org."}, + {"www.golang.org", "golang.org."}, + {"www.golang.org.", "golang.org."}, {"www.google.com", "google.com."}, {"google.com", "google.com."}, {"cname-to-txt.go4.org", "test-txt-record.go4.org."}, diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go index 997e42aff15a13b904d08d73f8237e901e3a5218..b9ec4654db5883e0efb89b7f20c1a64d8cfae363 100644 --- a/src/net/textproto/reader.go +++ b/src/net/textproto/reader.go @@ -18,7 +18,7 @@ _ "unsafe" // for linkname ) // TODO: This should be a distinguishable error (ErrMessageTooLarge) -// to allow mime/multipart to detect it. +// to allow mime/multipart and net/http to detect it. var errMessageTooLarge = errors.New("message too large") // A Reader implements convenience methods for reading requests @@ -508,11 +508,18 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) { return readMIMEHeader(r, math.MaxInt64, math.MaxInt64) } -// readMIMEHeader is accessed from mime/multipart. +// readMIMEHeader should be an internal detail, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/qtgolang/SunnyNet +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// //go:linkname readMIMEHeader // readMIMEHeader is a version of ReadMIMEHeader which takes a limit on the header size. -// It is called by the mime/multipart package. +// It is called by the mime/multipart and net/http package. func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) { // Avoid lots of small slice allocations later by allocating one // large one ahead of time which we'll cut up into smaller diff --git a/src/os/dir_darwin.go b/src/os/dir_darwin.go index b6ebca7e9e837fef3a537613a72a9151c9e3042c..c82428d5d20e4b13122ac6d7208515cd286b70c2 100644 --- a/src/os/dir_darwin.go +++ b/src/os/dir_darwin.go @@ -5,6 +5,7 @@ package os import ( + "errors" "io" "runtime" "syscall" @@ -92,6 +93,12 @@ de, err := newUnixDirent(f, string(name), dtToType(dirent.Type)) if IsNotExist(err) { // File disappeared between readdir and stat. // Treat as if it didn't exist. + continue + } + if errors.Is(err, syscall.EBADF) { + // Work around go.dev/issue/80143 during + // os.ReadDir("/dev/fd") by skipping kqueue fds. + // Exercised by TestReadDirFD. continue } if err != nil { diff --git a/src/os/read_test.go b/src/os/read_test.go index e5fd941d0fc1f67e1c6de5d6276e17eb0ef6de5c..50f0788b236efc635f0a4cde32dfae2118555848 100644 --- a/src/os/read_test.go +++ b/src/os/read_test.go @@ -142,3 +142,18 @@ if !foundSubDir { t.Fatalf("ReadDir %s: exec directory not found", dirname) } } + +func TestReadDirFD(t *testing.T) { + dir := "/dev/fd" + if runtime.GOOS == "plan9" { + dir = "#f" + } + if _, err := Stat(dir); err != nil { + t.Skipf("skipping on %s: %v", runtime.GOOS, err) + } + + _, err := ReadDir(dir) + if err != nil { + t.Fatal(err) + } +} diff --git a/src/os/root_windows.go b/src/os/root_windows.go index ca3bea8fc397764f4122a86880bd3acf8b1c2dd0..362963daa7ce02f2f2bdf1ccf8c76bc8a2422288 100644 --- a/src/os/root_windows.go +++ b/src/os/root_windows.go @@ -242,6 +242,10 @@ if oldname == "" { return syscall.EINVAL } + // Windows treats / and \ as equivalent almost everywhere, but not in symlink targets. + // Match os.Symlink behavior and convert / to \. + oldname = filepathlite.FromSlash(oldname) + // CreateSymbolicLinkW converts volume-relative paths into absolute ones. // Do the same. if filepathlite.VolumeNameLen(oldname) > 0 && !filepathlite.IsAbs(oldname) { diff --git a/src/os/root_windows_test.go b/src/os/root_windows_test.go index f393ad47a4205c2f32b7ca197b62db3d612234c8..ea604d18b195904a04ac6f979d9a224150953e45 100644 --- a/src/os/root_windows_test.go +++ b/src/os/root_windows_test.go @@ -235,6 +235,31 @@ }) } } +func TestRootSymlinkNormalization(t *testing.T) { + if !testenv.HasSymlink() { + t.Skip("skipping test; no symlink support") + } + const content = "dir/target" // same as file name + dir := makefs(t, []string{ + "dir/target", + }) + root, err := os.OpenRoot(dir) + if err != nil { + t.Fatal(err) + } + defer root.Close() + if err := root.Symlink("dir/target", "link"); err != nil { + t.Fatal(err) + } + got, err := os.ReadFile(dir + "/link") + if err != nil { + t.Fatal(err) + } + if string(got) != content { + t.Fatalf("read link contents %q, want %q", got, content) + } +} + func TestRootOpenFileTruncateNamedPipe(t *testing.T) { t.Parallel() name := pipeName() diff --git a/src/os/signal/signal_windows_test.go b/src/os/signal/signal_windows_test.go index 145a805c50b34d8b065e620d439958b5db10832f..d39f6c1d4200970282ad6c1c4106fe2bf3e55452 100644 --- a/src/os/signal/signal_windows_test.go +++ b/src/os/signal/signal_windows_test.go @@ -5,28 +5,30 @@ package signal import ( + "bufio" + "fmt" "internal/testenv" "os" "path/filepath" "strings" "syscall" "testing" - "time" ) -func sendCtrlBreak(t *testing.T, pid int) { +func sendCtrlBreak(pid int) error { d, e := syscall.LoadDLL("kernel32.dll") if e != nil { - t.Fatalf("LoadDLL: %v\n", e) + return fmt.Errorf("LoadDLL: %v\n", e) } p, e := d.FindProc("GenerateConsoleCtrlEvent") if e != nil { - t.Fatalf("FindProc: %v\n", e) + return fmt.Errorf("FindProc: %v\n", e) } r, _, e := p.Call(syscall.CTRL_BREAK_EVENT, uintptr(pid)) if r == 0 { - t.Fatalf("GenerateConsoleCtrlEvent: %v\n", e) + return fmt.Errorf("GenerateConsoleCtrlEvent: %v\n", e) } + return nil } func TestCtrlBreak(t *testing.T) { @@ -35,6 +37,7 @@ const source = ` package main import ( + "fmt" "log" "os" "os/signal" @@ -45,6 +48,7 @@ func main() { c := make(chan os.Signal, 10) signal.Notify(c) + fmt.Println("ready") select { case s := <-c: if s != os.Interrupt { @@ -58,7 +62,7 @@ ` tmp := t.TempDir() // write ctrlbreak.go - name := filepath.Join(tmp, "ctlbreak") + name := filepath.Join(tmp, "ctrlbreak") src := name + ".go" f, err := os.Create(src) if err != nil { @@ -78,8 +82,11 @@ // run it cmd := testenv.Command(t, exe) var buf strings.Builder - cmd.Stdout = &buf cmd.Stderr = &buf + stdout, err := cmd.StdoutPipe() + if err != nil { + t.Fatalf("StdoutPipe failed: %v", err) + } cmd.SysProcAttr = &syscall.SysProcAttr{ CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP, } @@ -87,10 +94,22 @@ err = cmd.Start() if err != nil { t.Fatalf("Start failed: %v", err) } + + outReader := bufio.NewReader(stdout) + errCh := make(chan error, 1) go func() { - time.Sleep(1 * time.Second) - sendCtrlBreak(t, cmd.Process.Pid) + if line, err := outReader.ReadString('\n'); err != nil { + errCh <- fmt.Errorf("could not read stdout: %v", err) + } else if strings.TrimSpace(line) != "ready" { + errCh <- fmt.Errorf("unexpected message: %v", line) + } else { + errCh <- sendCtrlBreak(cmd.Process.Pid) + } }() + + if err := <-errCh; err != nil { + t.Fatal(err) + } err = cmd.Wait() if err != nil { t.Fatalf("Program exited with error: %v\n%v", err, buf.String()) diff --git a/src/os/statat_unix.go b/src/os/statat_unix.go index 80f89f95c41129d71856ac8d52faa3ef41cc8900..8552e49065a8893a7aaa79df987f57d27a289a55 100644 --- a/src/os/statat_unix.go +++ b/src/os/statat_unix.go @@ -13,7 +13,11 @@ func (f *File) lstatatNolog(name string) (FileInfo, error) { var fs fileStat if err := f.pfd.Fstatat(name, &fs.sys, unix.AT_SYMLINK_NOFOLLOW); err != nil { - return nil, f.wrapErr("fstatat", err) + err = f.wrapErr("fstatat", err) + if pe, ok := err.(*PathError); ok { + pe.Path = pe.Path + string(PathSeparator) + name + } + return nil, err } fillFileStatFromSys(&fs, name) return &fs, nil diff --git a/src/runtime/lockrank_off.go b/src/runtime/lockrank_off.go index 18aef6bd2b3f438f161624328370f89709486925..571e24e6932e552bcb6c30f2e9c7331c7fb459a6 100644 --- a/src/runtime/lockrank_off.go +++ b/src/runtime/lockrank_off.go @@ -28,7 +28,8 @@ // This function may be called in nosplit context and thus must be nosplit. // //go:nosplit func acquireLockRankAndM(rank lockRank) { - acquirem() + mp := acquirem() + mp.locks += mutexMLocksDelta // not safe to profile right now } func unlockWithRank(l *mutex) { @@ -39,7 +40,9 @@ // This function may be called in nosplit context and thus must be nosplit. // //go:nosplit func releaseLockRankAndM(rank lockRank) { - releasem(getg().m) + mp := getg().m + mp.locks -= mutexMLocksDelta + releasem(mp) } // This function may be called in nosplit context and thus must be nosplit. diff --git a/src/runtime/lockrank_on.go b/src/runtime/lockrank_on.go index da9fb924bc5e6be145fd2638ac0e919d61d13536..6dd0ee87567769af499cdca526c60050504aa958 100644 --- a/src/runtime/lockrank_on.go +++ b/src/runtime/lockrank_on.go @@ -102,14 +102,16 @@ } } // acquireLockRankAndM acquires a rank which is not associated with a mutex -// lock. To maintain the invariant that an M with m.locks==0 does not hold any -// lock-like resources, it also acquires the M. +// lock. To maintain the invariant that an M which holds lock-like resources +// will have m.locks/mutexMLocksDelta > 0, it also acquires the M and adjusts +// m.locks by mutexMLocksDelta. // // This function may be called in nosplit context and thus must be nosplit. // //go:nosplit func acquireLockRankAndM(rank lockRank) { - acquirem() + mp := acquirem() + mp.locks += mutexMLocksDelta // not safe to profile right now gp := getg() // Log the new class. See comment on lockWithRank. @@ -215,7 +217,9 @@ throw("lockRank release without matching lockRank acquire") } }) - releasem(getg().m) + mp := getg().m + mp.locks -= mutexMLocksDelta + releasem(mp) } // nosplit because it may be called from nosplit contexts. diff --git a/src/runtime/malloc_generated.go b/src/runtime/malloc_generated.go index c694aad99127cd18eef988e6de75950c90edae56..95000726fbd1e5836810f6e375c27cb873df5077 100644 --- a/src/runtime/malloc_generated.go +++ b/src/runtime/malloc_generated.go @@ -11,10 +11,20 @@ "unsafe" ) func mallocgcSmallScanNoHeaderSC1(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(1<<1) | spanClass(0) const elemsize = uintptr(8) @@ -22,18 +32,11 @@ return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 1 const elemsize = 8 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallScanNoHeader(size, typ, mp) @@ -161,21 +164,25 @@ return x } func mallocgcSmallScanNoHeaderSC2(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(2<<1) | spanClass(0) const elemsize = uintptr(16) return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) - } - - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } } lockRankMayQueueFinalizer() @@ -183,7 +190,6 @@ const sizeclass = 2 const elemsize = 16 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallScanNoHeader(size, typ, mp) @@ -311,21 +317,25 @@ return x } func mallocgcSmallScanNoHeaderSC3(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(3<<1) | spanClass(0) const elemsize = uintptr(24) return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) - } - - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } } lockRankMayQueueFinalizer() @@ -333,7 +343,6 @@ const sizeclass = 3 const elemsize = 24 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallScanNoHeader(size, typ, mp) @@ -461,10 +470,20 @@ return x } func mallocgcSmallScanNoHeaderSC4(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(4<<1) | spanClass(0) const elemsize = uintptr(32) @@ -472,18 +491,11 @@ return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 4 const elemsize = 32 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallScanNoHeader(size, typ, mp) @@ -611,10 +623,20 @@ return x } func mallocgcSmallScanNoHeaderSC5(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(5<<1) | spanClass(0) const elemsize = uintptr(48) @@ -622,18 +644,11 @@ return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 5 const elemsize = 48 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallScanNoHeader(size, typ, mp) @@ -761,10 +776,20 @@ return x } func mallocgcSmallScanNoHeaderSC6(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(6<<1) | spanClass(0) const elemsize = uintptr(64) @@ -772,18 +797,11 @@ return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 6 const elemsize = 64 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallScanNoHeader(size, typ, mp) @@ -911,10 +929,20 @@ return x } func mallocgcSmallScanNoHeaderSC7(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(7<<1) | spanClass(0) const elemsize = uintptr(80) @@ -922,18 +950,11 @@ return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 7 const elemsize = 80 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallScanNoHeader(size, typ, mp) @@ -1061,26 +1082,29 @@ return x } func mallocgcTinySC2(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) return mallocgcTinySlowPath(size, typ, needzero) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const elemsize = 16 - mp := acquirem() if doubleCheckMalloc { doubleCheckTiny(size, typ, mp) } @@ -1165,10 +1189,20 @@ return x } func mallocgcSmallNoScanSC2(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(2<<1) | spanClass(1) const elemsize = uintptr(16) @@ -1176,18 +1210,11 @@ return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 2 const elemsize = 16 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallNoScan(typ, mp) @@ -1261,10 +1288,20 @@ return x } func mallocgcSmallNoScanSC3(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(3<<1) | spanClass(1) const elemsize = uintptr(24) @@ -1272,18 +1309,11 @@ return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 3 const elemsize = 24 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallNoScan(typ, mp) @@ -1357,10 +1387,20 @@ return x } func mallocgcSmallNoScanSC4(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(4<<1) | spanClass(1) const elemsize = uintptr(32) @@ -1368,18 +1408,11 @@ return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 4 const elemsize = 32 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallNoScan(typ, mp) @@ -1453,10 +1486,20 @@ return x } func mallocgcSmallNoScanSC5(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(5<<1) | spanClass(1) const elemsize = uintptr(48) @@ -1464,18 +1507,11 @@ return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 5 const elemsize = 48 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallNoScan(typ, mp) @@ -1549,10 +1585,20 @@ return x } func mallocgcSmallNoScanSC6(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(6<<1) | spanClass(1) const elemsize = uintptr(64) @@ -1560,18 +1606,11 @@ return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 6 const elemsize = 64 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallNoScan(typ, mp) @@ -1645,10 +1684,20 @@ return x } func mallocgcSmallNoScanSC7(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m + + mp = acquirem() forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) const spc = spanClass(7<<1) | spanClass(1) const elemsize = uintptr(80) @@ -1656,18 +1705,11 @@ return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() const sizeclass = 7 const elemsize = 80 - mp := acquirem() if doubleCheckMalloc { doubleCheckSmallNoScan(typ, mp) @@ -1741,18 +1783,19 @@ return x } func mallocgcTinySlowPath(size uintptr, typ *_type, needzero bool) unsafe.Pointer { + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") + } + } + + var mp *m gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { return mallocgcSmallNoScanSC2(size, typ, needzero) } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") - } - } - lockRankMayQueueFinalizer() if debug.malloc { @@ -1773,9 +1816,10 @@ gcAssistAlloc(assistG) } } + mp = acquirem() + const elemsize = 16 - mp := acquirem() if doubleCheckMalloc { doubleCheckTiny(size, typ, mp) } @@ -1890,6 +1934,8 @@ if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") } } + + var mp *m lockRankMayQueueFinalizer() @@ -1911,7 +1957,8 @@ gcAssistAlloc(assistG) } } - mp := acquirem() + mp = acquirem() + if doubleCheckMalloc { doubleCheckSmallScanNoHeader(size, typ, mp) @@ -2065,6 +2112,8 @@ throw("mallocgc called with gcphase == _GCmarktermination") } } + var mp *m + lockRankMayQueueFinalizer() if debug.malloc { @@ -2085,7 +2134,8 @@ gcAssistAlloc(assistG) } } - mp := acquirem() + mp = acquirem() + if doubleCheckMalloc { doubleCheckSmallNoScan(typ, mp) diff --git a/src/runtime/malloc_stubs.go b/src/runtime/malloc_stubs.go index 177d69487e51c2977446f65cabe0d286aed742d5..337055c25d166fc29f56a7abd645d0a079001645 100644 --- a/src/runtime/malloc_stubs.go +++ b/src/runtime/malloc_stubs.go @@ -63,22 +63,26 @@ // WARNING: mallocStub does not do any work for sanitizers so callers need // to steer out of this codepath early if sanitizers are enabled. func mallocStub(size uintptr, typ *_type, needzero bool) unsafe.Pointer { - if isSlowPath_ && isTiny_ { - // secret code, need to avoid the tiny allocator since it might keep - // co-located values alive longer and prevent timely zero-ing - // - // Call directly into the NoScan allocator. - // See go.dev/issue/76356 - gp := getg() - if goexperiment.RuntimeSecret && gp.secret > 0 { - return mallocgcSmallNoScanSC2(size, typ, needzero) + if doubleCheckMalloc { + if gcphase == _GCmarktermination { + throw("mallocgc called with gcphase == _GCmarktermination") } } + var mp *m if !isSlowPath_ { + // Fast path. + + // The fast path assumes that GC marking is not running. We + // must acquirem to ensure the GC does not start after we + // check. + mp = acquirem() + + // Do we need to fall back to slow path? forceSlowPath := debug.malloc || gcBlackenEnabled != 0 || (goexperiment.RuntimeSecret && getg().secret > 0) if forceSlowPath { + releasem(mp) // Slow path will reacquire. if isTiny_ { return mallocgcTinySlowPath(size, typ, needzero) } else { @@ -87,34 +91,50 @@ const elemsize = uintptr(elemsize_) return mallocgcSlowPathStub(size, typ, needzero, spc, elemsize) } } - } - if doubleCheckMalloc { - if gcphase == _GCmarktermination { - throw("mallocgc called with gcphase == _GCmarktermination") + // It's possible for any malloc to trigger sweeping, which may + // in turn queue finalizers. Record this dynamic lock edge. + // N.B. Compiled away if lockrank experiment is not enabled. + lockRankMayQueueFinalizer() + } else { + // Slow path. + if isTiny_ { + // secret code, need to avoid the tiny allocator since + // it might keep co-located values alive longer and + // prevent timely zero-ing. + // + // Call directly into the NoScan allocator. + // See go.dev/issue/76356 + gp := getg() + if goexperiment.RuntimeSecret && gp.secret > 0 { + return mallocgcSmallNoScanSC2(size, typ, needzero) + } } - } + + // It's possible for any malloc to trigger sweeping, which may + // in turn queue finalizers. Record this dynamic lock edge. + // N.B. Compiled away if lockrank experiment is not enabled. + lockRankMayQueueFinalizer() - // It's possible for any malloc to trigger sweeping, which may in - // turn queue finalizers. Record this dynamic lock edge. - // N.B. Compiled away if lockrank experiment is not enabled. - lockRankMayQueueFinalizer() + // Pre-malloc debug hooks. + if debug.malloc { + if x := preMallocgcDebug(size, typ); x != nil { + return x + } + } - // Pre-malloc debug hooks. - if isSlowPath_ && debug.malloc { - if x := preMallocgcDebug(size, typ); x != nil { - return x + // Assist the GC if needed. (On the reuse path, we currently + // compensate for this; changes here might require changes + // there.) + if gcBlackenEnabled != 0 { + deductAssistCredit(size) } - } - // Assist the GC if needed. (On the reuse path, we currently compensate for this; - // changes here might require changes there.) - if isSlowPath_ && gcBlackenEnabled != 0 { - deductAssistCredit(size) + mp = acquirem() } // Actually do the allocation. - return inlinedMalloc(size, typ, needzero) + return inlinedMalloc(mp, size, typ, needzero) } func postMallocgc(x unsafe.Pointer, typ *_type, size uintptr, elemsize uintptr) { @@ -163,7 +183,10 @@ // to generate a size-specialized malloc function. The call to inlinedMalloc in mallocStub // will be replaced with the inlined body of smallStub or tinyStub when generating the // size-specialized malloc function. See the comment at the top of this file for more // information. -func inlinedMalloc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +// +// The caller must acquirem prior to calling inlinedMalloc, which will releasem +// before returning. +func inlinedMalloc(mp *m, size uintptr, typ *_type, needzero bool) unsafe.Pointer { return unsafe.Pointer(uintptr(0)) } @@ -182,12 +205,13 @@ throw("heap bits in not in span for non-header-only path") } } -func smallStub(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +// The caller must acquirem prior to calling smallStub, which will releasem +// before returning. +func smallStub(mp *m, size uintptr, typ *_type, needzero bool) unsafe.Pointer { const sizeclass = sizeclass_ const elemsize = elemsize_ // Set mp.mallocing to keep from being preempted by GC. - mp := acquirem() if doubleCheckMalloc { if isNoScan_ { doubleCheckSmallNoScan(typ, mp) @@ -331,11 +355,12 @@ throw("expected noscan for tiny alloc") } } -func tinyStub(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +// The caller must acquirem prior to calling tinyStub, which will releasem +// before returning. +func tinyStub(mp *m, size uintptr, typ *_type, needzero bool) unsafe.Pointer { const elemsize = elemsize_ // Set mp.mallocing to keep from being preempted by GC. - mp := acquirem() if doubleCheckMalloc { doubleCheckTiny(size, typ, mp) } diff --git a/src/runtime/mem_sbrk.go b/src/runtime/mem_sbrk.go index 9e752df2c338b469fbef6907e2227e29f1b12ee8..b8a2a7522d5f5bd11460286e64d4cf33a91ba113 100644 --- a/src/runtime/mem_sbrk.go +++ b/src/runtime/mem_sbrk.go @@ -206,6 +206,10 @@ return unsafe.Pointer(p) } func sysFreeOS(v unsafe.Pointer, n uintptr) { + if v == nil { + // A failed sysReserveOS returns nil, so freeing it is a no-op. + return + } systemstack(func() { lock(&memlock) if uintptr(v)+n == bloc { diff --git a/src/runtime/softfloat64.go b/src/runtime/softfloat64.go index 42ef0092970b3e2525b65fa1c4cf5559d51b44d7..c230c6418e50fe9d217f3baf80c3133b4215305a 100644 --- a/src/runtime/softfloat64.go +++ b/src/runtime/softfloat64.go @@ -91,7 +91,6 @@ return } func fpack64(sign, mant uint64, exp int, trunc uint64) uint64 { - mant0, exp0, trunc0 := mant, exp, trunc if mant == 0 { return sign } @@ -99,6 +98,11 @@ for mant < 1<= 4<>= 1 @@ -142,7 +146,6 @@ return sign | uint64(exp-bias64)<= 4<>= 1 diff --git a/src/runtime/softfloat64_test.go b/src/runtime/softfloat64_test.go index 3f53e8bc55810cfb9cbd67961cbd958d9a7b2067..1a0a502b4da4b2cde2378a92b64b9200a0900d7c 100644 --- a/src/runtime/softfloat64_test.go +++ b/src/runtime/softfloat64_test.go @@ -36,10 +36,12 @@ math.Inf(+1), math.Inf(-1), 0.1, 1.5, - 1.9999999999999998, // all 1s mantissa - 1.3333333333333333, // 1.010101010101... - 1.1428571428571428, // 1.001001001001... - 1.112536929253601e-308, // first normal + 1.9999999999999998, // all 1s mantissa + 1.3333333333333333, // 1.010101010101... + 1.1428571428571428, // 1.001001001001... + 1.112536929253601e-308, // first normal + -2.662107816930723e-301, // #79964: two near-equal opposite-sign + 2.662107858822336e-301, // normals cancelling to a subnormal 2, 4, 8, diff --git a/src/simd/archsimd/_gen/midway/intersect_simd_ops.go b/src/simd/archsimd/_gen/midway/intersect_simd_ops.go index e91c52763c45b1a4dc4f33ea7525e7ada44b3012..141ccc24923173413d389368b158fbe42e99a233 100644 --- a/src/simd/archsimd/_gen/midway/intersect_simd_ops.go +++ b/src/simd/archsimd/_gen/midway/intersect_simd_ops.go @@ -669,7 +669,12 @@ fd := methodsByType[combine(arch, t)][m] if fd == nil { continue } - pf("func (x %s) %s(", t, fd.Name.Name) + bridgeName := fd.Name.Name + if strings.HasPrefix(t, "Mask") && strings.HasPrefix(bridgeName, "ToInt") { + x := strings.Index(bridgeName, "x") + bridgeName = bridgeName[:x] + "s" + } + pf("func (x %s) %s(", t, bridgeName) var args []string if fd.Type.Params != nil { paramCount := 0 diff --git a/src/simd/archsimd/_gen/simdgen/ops/Moves/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/Moves/categories.yaml index 68dc1ab9844ce4db9ea75d2cf67e49849fef2c56..872628ef0d9c8e9b587d655d83cd6d6eba6b7543 100644 --- a/src/simd/archsimd/_gen/simdgen/ops/Moves/categories.yaml +++ b/src/simd/archsimd/_gen/simdgen/ops/Moves/categories.yaml @@ -85,11 +85,11 @@ // the first or the second based on whether the third is false or true - go: bitSelect commutative: false documentation: !string |- - // NAME selects bits from y where mask is 1, keeps bits from x where mask is 0. + // NAME returns the bitwise selection if mask[i] then x[i] else y[i]. - go: bitSelectNot commutative: false documentation: !string |- - // NAME selects bits from y where mask is 0, keeps bits from x where mask is 1. + // NAME returns the bitwise selection if mask[i] then y[i] else x[i]. - go: move commutative: false noTypes: "true" diff --git a/src/simd/archsimd/_gen/simdgen/ops/Moves/go_arm64.yaml b/src/simd/archsimd/_gen/simdgen/ops/Moves/go_arm64.yaml index e81879a6c6b668d4a0d34a25a8f139cc9b516692..1f6ed73daef5ebb1fec0c83a94cc205c37b38b46 100644 --- a/src/simd/archsimd/_gen/simdgen/ops/Moves/go_arm64.yaml +++ b/src/simd/archsimd/_gen/simdgen/ops/Moves/go_arm64.yaml @@ -122,12 +122,12 @@ elemBits: 64 out: - *bcast64 -# bitSelect — VBIT (bit insert if true, internal) -# Only Int8x16 is needed since VBIT operates on the full 128-bit register. +# bitSelect — VBIF (bit insert if false, internal) +# Only Int8x16 is needed since VBIF operates on the full 128-bit register. # Other types cast to Int8x16 before calling bitSelect. - go: bitSelect - asm: "VBIT" - specialLower: !string "match (%h x y (VNOT16B mask)) => (VBIF16B x y mask)" + asm: "VBIF" + specialLower: !string "match (%h x y (VNOT16B mask)) => (VBIT16B x y mask)" in: - &v8 go: $t @@ -142,10 +142,10 @@ name: mask out: - *v8 -# bitSelectNot — VBIF (bit insert if false, internal) +# bitSelectNot — VBIT (bit insert if true, internal) - go: bitSelectNot - asm: "VBIF" - specialLower: !string "match (%h x y (VNOT16B mask)) => (VBIT16B x y mask)" + asm: "VBIT" + specialLower: !string "match (%h x y (VNOT16B mask)) => (VBIF16B x y mask)" in: - *v8 - *v8 diff --git a/src/simd/archsimd/_gen/tmplgen/main.go b/src/simd/archsimd/_gen/tmplgen/main.go index 772b58ef7ba653ddeaae36cea9034fcdc896da73..de7352a085247fa63529ad0c6776f1f4f6cfac6d 100644 --- a/src/simd/archsimd/_gen/tmplgen/main.go +++ b/src/simd/archsimd/_gen/tmplgen/main.go @@ -45,38 +45,15 @@ } return x } -// smallSAT filters a shapeAndTemplate to keep only those -// for vector lengths <= 128 (effectively, for those == 128). -// 128 is the available-everywhere SIMD size, so many SIMD -// things across architectures can be lumped together as "128" -func smallSAT(sat shapeAndTemplate) shapeAndTemplate { - r := sat - s := *r.s - s.vecs = []int{} - for _, v := range r.s.vecs { - if v <= 128 { - s.vecs = append(s.vecs, v) - } - } - r.s = &s - return r -} +// shapeFilter specifies how helper templates are filtered based on their size. +// It applies to both input and output vector shapes. +type shapeFilter int -// largeSAT filters a shapeAndTemplate to keep only those -// for vector lengths > 128. These tend to be less share-able -// than length 128 -func largeSAT(sat shapeAndTemplate) shapeAndTemplate { - r := sat - s := *r.s - s.vecs = []int{} - for _, v := range r.s.vecs { - if v > 128 { - s.vecs = append(s.vecs, v) - } - } - r.s = &s - return r -} +const ( + filterAll shapeFilter = iota + filterSmallOnly // both input and output vectors are <= 128 bits + filterLarge // either input or output vector is > 128 bits +) func (sat shapeAndTemplate) target(outType string, width int) shapeAndTemplate { newSat := sat @@ -254,7 +231,7 @@ } var ternaryFlaky = &shapes{ // for tests that support flaky equality vecs: []int{128, 256, 512}, - floats: []int{32}, + floats: []int{32, 64}, } var avx2SignedComparisons = &shapes{ @@ -310,7 +287,7 @@ func (t templateData) As128BitVec() string { return fmt.Sprintf("%s%dx%d", t.Base, t.EWidth, 128/t.EWidth) } -func oneTemplate(t *template.Template, baseType string, width, count int, out io.Writer, rtf resultTypeFunc) { +func oneTemplate(t *template.Template, baseType string, width, count int, out io.Writer, rtf resultTypeFunc, filter shapeFilter) { b := width * count if b < 128 || b > 512 { return @@ -326,7 +303,24 @@ // TODO someday we will support conversions to 16-bit floats if ot == "float" && ow < 32 { return } + if ot == baseType && ow == width && oc == count && strings.Contains(t.Name(), "convert_helpers") { + return + } } + + ob := ow * oc + isSmall := (b <= 128) && (ob <= 128) + switch filter { + case filterSmallOnly: + if !isSmall { + return + } + case filterLarge: + if isSmall { + return + } + } + ovType := fmt.Sprintf("%s%dx%d", strings.ToUpper(ot[:1])+ot[1:], ow, oc) oeType := fmt.Sprintf("%s%d", ot, ow) oEType := fmt.Sprintf("%s%d", strings.ToUpper(ot[:1])+ot[1:], ow) @@ -365,7 +359,7 @@ } // forTemplates expands the template sat.t for each shape // in sat.s, writing to out. -func (sat shapeAndTemplate) forTemplates(out io.Writer) { +func (sat shapeAndTemplate) forTemplates(out io.Writer, filter shapeFilter) { t, s := sat.t, sat.s vecs := s.vecs ints := s.ints @@ -374,15 +368,15 @@ floats := s.floats for _, v := range vecs { for _, w := range ints { c := v / w - oneTemplate(t, "int", w, c, out, sat.s.output) + oneTemplate(t, "int", w, c, out, sat.s.output, filter) } for _, w := range uints { c := v / w - oneTemplate(t, "uint", w, c, out, sat.s.output) + oneTemplate(t, "uint", w, c, out, sat.s.output, filter) } for _, w := range floats { c := v / w - oneTemplate(t, "float", w, c, out, sat.s.output) + oneTemplate(t, "float", w, c, out, sat.s.output, filter) } } } @@ -543,7 +537,7 @@ unaryToFloat32 = convertTemplate.target("float", 32) unaryToFloat64 = convertTemplate.target("float", 64) ) -var convertLoTemplate = shapedTemplateOf(integerShapes, "convert_lo_helpers", ` +var convertLoTemplate = shapedTemplateOf(allShapes, "convert_lo_helpers", ` // test{{.VType}}ConvertLoTo{{.OVType}} tests the simd conversion method f against the expected behavior generated by want. // This converts only the low {{.OCount}} elements. func test{{.VType}}ConvertLoTo{{.OVType}}(t *testing.T, f func(x archsimd.{{.VType}}) archsimd.{{.OVType}}, want func(x []{{.Etype}}) []{{.OEtype}}) { @@ -566,16 +560,18 @@ // The output is fixed to 128- or 256-bits (no 512-bit, as the // regular convertTemplate covers that). // TODO: this includes shapes where in and out have the same element // type or length, which are not needed. - unaryToInt64x2 = convertLoTemplate.targetFixed("int", 64, 2) - unaryToInt64x4 = convertLoTemplate.targetFixed("int", 64, 4) - unaryToUint64x2 = convertLoTemplate.targetFixed("uint", 64, 2) - unaryToUint64x4 = convertLoTemplate.targetFixed("uint", 64, 4) - unaryToInt32x4 = convertLoTemplate.targetFixed("int", 32, 4) - unaryToInt32x8 = convertLoTemplate.targetFixed("int", 32, 8) - unaryToUint32x4 = convertLoTemplate.targetFixed("uint", 32, 4) - unaryToUint32x8 = convertLoTemplate.targetFixed("uint", 32, 8) - unaryToInt16x8 = convertLoTemplate.targetFixed("int", 16, 8) - unaryToUint16x8 = convertLoTemplate.targetFixed("uint", 16, 8) + unaryToInt64x2 = convertLoTemplate.targetFixed("int", 64, 2) + unaryToInt64x4 = convertLoTemplate.targetFixed("int", 64, 4) + unaryToUint64x2 = convertLoTemplate.targetFixed("uint", 64, 2) + unaryToUint64x4 = convertLoTemplate.targetFixed("uint", 64, 4) + unaryToInt32x4 = convertLoTemplate.targetFixed("int", 32, 4) + unaryToInt32x8 = convertLoTemplate.targetFixed("int", 32, 8) + unaryToUint32x4 = convertLoTemplate.targetFixed("uint", 32, 4) + unaryToUint32x8 = convertLoTemplate.targetFixed("uint", 32, 8) + unaryToInt16x8 = convertLoTemplate.targetFixed("int", 16, 8) + unaryToUint16x8 = convertLoTemplate.targetFixed("uint", 16, 8) + unaryToFloat64x2 = convertLoTemplate.targetFixed("float", 64, 2) + unaryToFloat64x4 = convertLoTemplate.targetFixed("float", 64, 4) ) const binaryTestTemplate = ` @@ -600,28 +596,7 @@ var binaryTemplateArm64 = shapedTemplateOf(arm64Shapes, "arm64_binary_helpers", binaryTestTemplate) // ARM64 shift test helper templates -var shiftConstTestTemplateArm64 = shapedTemplateOf(arm64IntegerShapes, "arm64_shift_const_helpers", ` -// test{{.VType}}ShiftConst tests a const-shift method (unary + immediate). -func test{{.VType}}ShiftConst(t *testing.T, f func(_ archsimd.{{.VType}}, _ uint64) archsimd.{{.VType}}, want func(_ []{{.Etype}}, _ uint64) []{{.Etype}}) { - n := {{.Count}} - t.Helper() - forSlice(t, {{.Etype}}s, n, func(x []{{.Etype}}) bool { - t.Helper() - for _, amt := range []uint64{0, 1, 3, {{.EWidth}}-1} { - a := archsimd.Load{{.VType}}(x) - g := make([]{{.Etype}}, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} -`) - -var shiftAllTestTemplateArm64 = shapedTemplateOf(arm64IntegerShapes, "arm64_shift_all_helpers", ` +var shiftAllTestTemplate = shapedTemplateOf(integerShapes, "shift_all_helpers", ` // test{{.VType}}ShiftAll tests a shift-all method (unary + scalar uint64). func test{{.VType}}ShiftAll(t *testing.T, f func(_ archsimd.{{.VType}}, _ uint64) archsimd.{{.VType}}, want func(_ []{{.Etype}}, _ uint64) []{{.Etype}}) { n := {{.Count}} @@ -660,35 +635,6 @@ }) } `) -var convertTemplateArm64 = shapedTemplateOf(arm64Shapes, "arm64_convert_helpers", ` -// test{{.VType}}ConvertTo{{.OVType}} tests the simd conversion method f against the expected behavior generated by want. -func test{{.VType}}ConvertTo{{.OVType}}(t *testing.T, f func(x archsimd.{{.VType}}) archsimd.{{.OVType}}, want func(x []{{.Etype}}) []{{.OEtype}}) { - n := {{.Count}} - t.Helper() - forSlice(t, {{.Etype}}s, n, func(x []{{.Etype}}) bool { - t.Helper() - a := archsimd.Load{{.VType}}(x) - g := make([]{{.OEtype}}, {{.OCount}}) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x)}) - }) -} -`) - -var ( - arm64ToInt8 = convertTemplateArm64.arm64Target("int", 8) - arm64ToUint8 = convertTemplateArm64.arm64Target("uint", 8) - arm64ToInt16 = convertTemplateArm64.arm64Target("int", 16) - arm64ToUint16 = convertTemplateArm64.arm64Target("uint", 16) - arm64ToInt32 = convertTemplateArm64.arm64Target("int", 32) - arm64ToUint32 = convertTemplateArm64.arm64Target("uint", 32) - arm64ToInt64 = convertTemplateArm64.arm64Target("int", 64) - arm64ToUint64 = convertTemplateArm64.arm64Target("uint", 64) - arm64ToFloat32 = convertTemplateArm64.arm64Target("float", 32) - arm64ToFloat64 = convertTemplateArm64.arm64Target("float", 64) -) - const ternaryTestTemplateText = ` // test{{.VType}}Ternary tests the simd ternary method f against the expected behavior generated by want func test{{.VType}}Ternary(t *testing.T, f func(_, _, _ archsimd.{{.VType}}) archsimd.{{.VType}}, want func(_, _, _ []{{.Etype}}) []{{.Etype}}) { @@ -728,8 +674,6 @@ ` var ternaryTemplate = templateOf("ternary_helpers", ternaryTestTemplateText) var ternaryFlakyTemplate = shapedTemplateOf(ternaryFlaky, "ternary_helpers", ternaryFlakyTestTemplateText) -var ternaryTemplateArm64 = shapedTemplateOf(arm64Shapes, "ternary_arm64_helpers", ternaryTestTemplateText) -var ternaryFlakyTemplateArm64 = shapedTemplateOf(arm64Shapes, "ternary_arm64_helpers", ternaryFlakyTestTemplateText) const reduceTestTemplateText = ` func test{{.VType}}Reduce(t *testing.T, f func(_ archsimd.{{.VType}}) {{.Etype}}, want func(_ []{{.Etype}}) {{.Etype}}) { @@ -892,17 +836,18 @@ // StorePart stores the {{.Count}} elements of x into the slice s. // It stores as many elements as will fit in s. // If s has {{.Count}} or more elements, the method is equivalent to x.Store. -func (x {{.VType}}) StorePart(s []{{.Etype}}) { +func (x {{.VType}}) StorePart(s []{{.Etype}}) int { l := len(s) if l >= {{.Count}} { x.Store(s) - return + return {{.Count}} } if l == 0 { - return + return 0 } mask := vecMask{{.EWidth}}[len(vecMask{{.EWidth}})/2-l:] x.StoreArrayMasked(pa{{.VType}}(s), LoadInt{{.WxC}}(mask).asMask()) + return l } `) @@ -924,12 +869,12 @@ // StorePart stores the {{.Count}} elements of x into the slice s. // It stores as many elements as will fit in s. // If s has {{.Count}} or more elements, the method is equivalent to x.Store. -func (x {{.VType}}) StorePart(s []{{.Etype}}) { +func (x {{.VType}}) StorePart(s []{{.Etype}}) int { if len(s) == 0 { - return + return 0 } t := unsafe.Slice((*int{{.EWidth}})(unsafe.Pointer(&s[0])), len(s)) - x.AsInt{{.WxC}}().StorePart(t) + return x.AsInt{{.WxC}}().StorePart(t) } `) @@ -1443,21 +1388,18 @@ op := flag.String("op", SIMD+"other_gen_amd64.go", "file name for other operations") ush := flag.String("ush", SIMD+"unsafe_helpers.go", "file name for unsafe helpers") bh := flag.String("bh", TD+"binary_helpers_%W_test.go", "file name for binary test helpers") uh := flag.String("uh", TD+"unary_helpers_%W_test.go", "file name for unary test helpers") - cvh := flag.String("cvh", TD+"convert_helpers_test.go", "file name for conversion test helpers") - th := flag.String("th", TD+"ternary_helpers_test.go", "file name for ternary test helpers") + cvh := flag.String("cvh", TD+"convert_helpers_%W_test.go", "file name for conversion test helpers") + th := flag.String("th", TD+"ternary_helpers_%W_test.go", "file name for ternary test helpers") ch := flag.String("ch", TD+"compare_helpers_%W_test.go", "file name for compare test helpers") cmh := flag.String("cmh", TD+"comparemasked_helpers_test.go", "file name for compare-masked test helpers") + sh := flag.String("sh", TD+"shift_helpers_%W_test.go", "file name for shift test helpers") // ARM64-specific - bhArm64 := flag.String("bhArm64", TD+"arm64_binary_helpers_test.go", "file name for ARM64 binary test helpers") slArm64 := flag.String("slArm64", SIMD+"slice_gen_arm64.go", "file name for ARM64 slice operations") opArm64 := flag.String("opArm64", SIMD+"other_gen_arm64.go", "file name for ARM64 other operations") - shArm64 := flag.String("shArm64", TD+"arm64_shift_helpers_test.go", "file name for ARM64 shift test helpers") - uhArm64 := flag.String("uhArm64", TD+"arm64_unary_helpers_test.go", "file name for ARM64 unary test helpers") + shArm64 := flag.String("shArm64", TD+"shift_helpers_arm64_test.go", "file name for ARM64 shift test helpers") cmArm64 := flag.String("cmArm64", SIMD+"compare_gen_arm64.go", "file name for ARM64 comparison operations") mmArm64 := flag.String("mmArm64", SIMD+"maskmerge_gen_arm64.go", "file name for ARM64 mask/merge operations") - chArm64 := flag.String("chArm64", TD+"arm64_compare_helpers_test.go", "file name for ARM64 compare test helpers") - thArm64 := flag.String("thArm64", TD+"ternary_arm64_helpers_test.go", "file name for ARM64 ternary test helpers") - rhArm64 := flag.String("rhArm64", TD+"reduce_arm64_helpers_test.go", "file name for ARM64 reduce test helpers") + rhArm64 := flag.String("rhArm64", TD+"reduce_helpers_arm64_test.go", "file name for ARM64 reduce test helpers") flag.Parse() if *sl != "" { @@ -1508,6 +1450,7 @@ unaryToUint64x2, unaryToUint64x4, unaryToInt32x4, unaryToInt32x8, unaryToUint32x4, unaryToUint32x8, unaryToInt16x8, unaryToUint16x8, + unaryToFloat64x2, unaryToFloat64x4, unaryFlakyTemplate, ) } @@ -1523,13 +1466,15 @@ } if *cmh != "" { one(*cmh, curryTestPrologue("simd methods that compare two operands under a mask"), compareMaskedTemplate) } + if *sh != "" { + one(*sh, curryTestPrologue("shift simd methods"), + shiftAllTestTemplate, + ) + } // ARM64-specific generation if *slArm64 != "" { one(*slArm64, prologue, sliceTemplateArm64) - } - if *bhArm64 != "" { - oneArch(*bhArm64, "arm64", curryTestPrologue("binary simd methods"), binaryTemplateArm64) } if *opArm64 != "" { one(*opArm64, prologue, @@ -1543,22 +1488,10 @@ reduceSumTemplateArm64, reduceMinMaxTemplateArm64) } if *shArm64 != "" { - oneArch(*shArm64, "arm64", curryTestPrologue("shift simd methods"), - shiftConstTestTemplateArm64, - shiftAllTestTemplateArm64, + oneArch(*shArm64, "arm64", curryTestPrologue("shift simd methods"), filterAll, shiftMixedTestTemplateArm64, ) } - if *uhArm64 != "" { - oneArch(*uhArm64, "arm64", curryTestPrologue("unary simd methods"), - arm64ToInt8, arm64ToUint8, - arm64ToInt16, arm64ToUint16, - arm64ToInt32, arm64ToUint32, - arm64ToInt64, arm64ToUint64, - arm64ToFloat32, arm64ToFloat64, - unaryTemplateArm64, - ) - } if *cmArm64 != "" { one(*cmArm64, prologue, arm64LessTemplate, @@ -1572,14 +1505,8 @@ arm64MaskedMergeTemplate, arm64MaskToString, ) } - if *chArm64 != "" { - oneArch(*chArm64, "arm64", curryTestPrologue("simd methods that compare two operands"), compareTemplateArm64) - } - if *thArm64 != "" { - oneArch(*thArm64, "arm64", curryTestPrologue("ternary simd methods"), ternaryTemplateArm64, ternaryFlakyTemplateArm64) - } if *rhArm64 != "" { - oneArch(*rhArm64, "arm64", reduceTestPrologue, reduceTestTemplateArm64) + oneArch(*rhArm64, "arm64", reduceTestPrologue, filterAll, reduceTestTemplateArm64) } nonTemplateRewrites(SSA+"tern_helpers.go", ssaPrologue, classifyBooleanSIMD, ternOpForLogical) @@ -1749,14 +1676,14 @@ if strings.Contains(filename, "%W") { smallFile := strings.ReplaceAll(filename, "%W", "128") largeFile := strings.ReplaceAll(filename, "%W", "wider") - oneArch(smallFile, "(amd64 || wasm)", prologue, Map(smallSAT, sats)...) - oneArch(largeFile, "amd64", prologue, Map(largeSAT, sats)...) + oneArch(smallFile, "(amd64 || wasm || arm64)", prologue, filterSmallOnly, sats...) + oneArch(largeFile, "amd64", prologue, filterLarge, sats...) return } - oneArch(filename, "amd64", prologue, sats...) + oneArch(filename, "amd64", prologue, filterAll, sats...) } -func oneArch(filename, buildArch string, prologue func(s, buildArch string, out io.Writer), sats ...shapeAndTemplate) { +func oneArch(filename, buildArch string, prologue func(s, buildArch string, out io.Writer), filter shapeFilter, sats ...shapeAndTemplate) { ofile := os.Stdout @@ -1773,7 +1700,7 @@ out := new(bytes.Buffer) prologue("tmplgen", buildArch, out) for _, sat := range sats { - sat.forTemplates(out) + sat.forTemplates(out, filter) } b, err := format.Source(out.Bytes()) diff --git a/src/simd/archsimd/_gen/wasmgen/main.go b/src/simd/archsimd/_gen/wasmgen/main.go index 90c783cc86475855442f01721499387f65c31679..b73cff8071154a4ef47a1d453f5e29b030d5bdd0 100644 --- a/src/simd/archsimd/_gen/wasmgen/main.go +++ b/src/simd/archsimd/_gen/wasmgen/main.go @@ -1947,7 +1947,7 @@ makeSimdOp1Imm8 := func(op ssa.Op, immLimit uint64) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { t := n.Type() - if args[1].Op == ssa.OpConst8 { + if args[1].Op == ssa.OpConst8 && uint64(args[1].AuxInt) < immLimit { return s.newValue1I(op, t, args[1].AuxInt, args[0]) } return immJumpTableN(s, args[1], n, immLimit, func(sNew *state, idx int) { @@ -1960,7 +1960,7 @@ makeSimdOp2Imm8 := func(op ssa.Op, immLimit uint64) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { t := types.TypeVec128 - if args[1].Op == ssa.OpConst8 { + if args[1].Op == ssa.OpConst8 && uint64(args[1].AuxInt) < immLimit { return s.newValue2I(op, t, args[1].AuxInt, args[0], args[2]) } return immJumpTableN(s, args[1], n, immLimit, func(sNew *state, idx int) { diff --git a/src/simd/archsimd/internal/simd_test/arm64_binary_helpers_test.go b/src/simd/archsimd/internal/simd_test/arm64_binary_helpers_test.go deleted file mode 100644 index 6f537c29ffe6a594ca6dbcad8ed3eeb7c3c517ae..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_binary_helpers_test.go +++ /dev/null @@ -1,164 +0,0 @@ -// Code generated by 'tmplgen'; DO NOT EDIT. - -//go:build goexperiment.simd && arm64 - -// This file contains functions testing binary simd methods. -// Each function in this file is specialized for a -// particular simd type x. - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -// testInt8x16Binary tests the simd binary method f against the expected behavior generated by want -func testInt8x16Binary(t *testing.T, f func(_, _ archsimd.Int8x16) archsimd.Int8x16, want func(_, _ []int8) []int8) { - n := 16 - t.Helper() - forSlicePair(t, int8s, n, func(x, y []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - b := archsimd.LoadInt8x16(y) - g := make([]int8, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testInt16x8Binary tests the simd binary method f against the expected behavior generated by want -func testInt16x8Binary(t *testing.T, f func(_, _ archsimd.Int16x8) archsimd.Int16x8, want func(_, _ []int16) []int16) { - n := 8 - t.Helper() - forSlicePair(t, int16s, n, func(x, y []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - b := archsimd.LoadInt16x8(y) - g := make([]int16, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testInt32x4Binary tests the simd binary method f against the expected behavior generated by want -func testInt32x4Binary(t *testing.T, f func(_, _ archsimd.Int32x4) archsimd.Int32x4, want func(_, _ []int32) []int32) { - n := 4 - t.Helper() - forSlicePair(t, int32s, n, func(x, y []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - b := archsimd.LoadInt32x4(y) - g := make([]int32, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testInt64x2Binary tests the simd binary method f against the expected behavior generated by want -func testInt64x2Binary(t *testing.T, f func(_, _ archsimd.Int64x2) archsimd.Int64x2, want func(_, _ []int64) []int64) { - n := 2 - t.Helper() - forSlicePair(t, int64s, n, func(x, y []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - b := archsimd.LoadInt64x2(y) - g := make([]int64, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint8x16Binary tests the simd binary method f against the expected behavior generated by want -func testUint8x16Binary(t *testing.T, f func(_, _ archsimd.Uint8x16) archsimd.Uint8x16, want func(_, _ []uint8) []uint8) { - n := 16 - t.Helper() - forSlicePair(t, uint8s, n, func(x, y []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - b := archsimd.LoadUint8x16(y) - g := make([]uint8, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint16x8Binary tests the simd binary method f against the expected behavior generated by want -func testUint16x8Binary(t *testing.T, f func(_, _ archsimd.Uint16x8) archsimd.Uint16x8, want func(_, _ []uint16) []uint16) { - n := 8 - t.Helper() - forSlicePair(t, uint16s, n, func(x, y []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - b := archsimd.LoadUint16x8(y) - g := make([]uint16, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint32x4Binary tests the simd binary method f against the expected behavior generated by want -func testUint32x4Binary(t *testing.T, f func(_, _ archsimd.Uint32x4) archsimd.Uint32x4, want func(_, _ []uint32) []uint32) { - n := 4 - t.Helper() - forSlicePair(t, uint32s, n, func(x, y []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - b := archsimd.LoadUint32x4(y) - g := make([]uint32, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint64x2Binary tests the simd binary method f against the expected behavior generated by want -func testUint64x2Binary(t *testing.T, f func(_, _ archsimd.Uint64x2) archsimd.Uint64x2, want func(_, _ []uint64) []uint64) { - n := 2 - t.Helper() - forSlicePair(t, uint64s, n, func(x, y []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - b := archsimd.LoadUint64x2(y) - g := make([]uint64, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testFloat32x4Binary tests the simd binary method f against the expected behavior generated by want -func testFloat32x4Binary(t *testing.T, f func(_, _ archsimd.Float32x4) archsimd.Float32x4, want func(_, _ []float32) []float32) { - n := 4 - t.Helper() - forSlicePair(t, float32s, n, func(x, y []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - b := archsimd.LoadFloat32x4(y) - g := make([]float32, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testFloat64x2Binary tests the simd binary method f against the expected behavior generated by want -func testFloat64x2Binary(t *testing.T, f func(_, _ archsimd.Float64x2) archsimd.Float64x2, want func(_, _ []float64) []float64) { - n := 2 - t.Helper() - forSlicePair(t, float64s, n, func(x, y []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - b := archsimd.LoadFloat64x2(y) - g := make([]float64, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} diff --git a/src/simd/archsimd/internal/simd_test/arm64_binary_test.go b/src/simd/archsimd/internal/simd_test/arm64_binary_test.go deleted file mode 100644 index a1d2c555cb66b695a128fcc32cc6a5a487ab15f6..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_binary_test.go +++ /dev/null @@ -1,336 +0,0 @@ -// 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 && arm64 - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -func TestAdd(t *testing.T) { - testFloat32x4Binary(t, archsimd.Float32x4.Add, addSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.Add, addSlice[float64]) - - testInt8x16Binary(t, archsimd.Int8x16.Add, addSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.Add, addSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Add, addSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.Add, addSlice[int64]) - - testUint8x16Binary(t, archsimd.Uint8x16.Add, addSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.Add, addSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Add, addSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.Add, addSlice[uint64]) -} - -func TestMul(t *testing.T) { - testFloat32x4Binary(t, archsimd.Float32x4.Mul, mulSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.Mul, mulSlice[float64]) - - testInt8x16Binary(t, archsimd.Int8x16.Mul, mulSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.Mul, mulSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Mul, mulSlice[int32]) - - testUint8x16Binary(t, archsimd.Uint8x16.Mul, mulSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.Mul, mulSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Mul, mulSlice[uint32]) -} - -func TestSub(t *testing.T) { - testFloat32x4Binary(t, archsimd.Float32x4.Sub, subSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.Sub, subSlice[float64]) - - testInt8x16Binary(t, archsimd.Int8x16.Sub, subSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.Sub, subSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Sub, subSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.Sub, subSlice[int64]) - - testUint8x16Binary(t, archsimd.Uint8x16.Sub, subSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.Sub, subSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Sub, subSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.Sub, subSlice[uint64]) -} - -func TestDiv(t *testing.T) { - testFloat32x4Binary(t, archsimd.Float32x4.Div, divSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.Div, divSlice[float64]) -} - -func TestMax(t *testing.T) { - testFloat32x4Binary(t, archsimd.Float32x4.Max, maxSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.Max, maxSlice[float64]) - - testInt8x16Binary(t, archsimd.Int8x16.Max, maxSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.Max, maxSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Max, maxSlice[int32]) - testUint8x16Binary(t, archsimd.Uint8x16.Max, maxSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.Max, maxSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Max, maxSlice[uint32]) -} - -func TestMin(t *testing.T) { - testFloat32x4Binary(t, archsimd.Float32x4.Min, minSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.Min, minSlice[float64]) - - testInt8x16Binary(t, archsimd.Int8x16.Min, minSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.Min, minSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Min, minSlice[int32]) - testUint8x16Binary(t, archsimd.Uint8x16.Min, minSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.Min, minSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Min, minSlice[uint32]) -} - -func TestConcatEven(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.ConcatEven, deinterleaveSlice[int8](128, false)) - testInt16x8Binary(t, archsimd.Int16x8.ConcatEven, deinterleaveSlice[int16](128, false)) - testInt32x4Binary(t, archsimd.Int32x4.ConcatEven, deinterleaveSlice[int32](128, false)) - testInt64x2Binary(t, archsimd.Int64x2.ConcatEven, deinterleaveSlice[int64](128, false)) - testUint8x16Binary(t, archsimd.Uint8x16.ConcatEven, deinterleaveSlice[uint8](128, false)) - testUint16x8Binary(t, archsimd.Uint16x8.ConcatEven, deinterleaveSlice[uint16](128, false)) - testUint32x4Binary(t, archsimd.Uint32x4.ConcatEven, deinterleaveSlice[uint32](128, false)) - testUint64x2Binary(t, archsimd.Uint64x2.ConcatEven, deinterleaveSlice[uint64](128, false)) -} - -func TestConcatOdd(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.ConcatOdd, deinterleaveSlice[int8](128, true)) - testInt16x8Binary(t, archsimd.Int16x8.ConcatOdd, deinterleaveSlice[int16](128, true)) - testInt32x4Binary(t, archsimd.Int32x4.ConcatOdd, deinterleaveSlice[int32](128, true)) - testInt64x2Binary(t, archsimd.Int64x2.ConcatOdd, deinterleaveSlice[int64](128, true)) - testUint8x16Binary(t, archsimd.Uint8x16.ConcatOdd, deinterleaveSlice[uint8](128, true)) - testUint16x8Binary(t, archsimd.Uint16x8.ConcatOdd, deinterleaveSlice[uint16](128, true)) - testUint32x4Binary(t, archsimd.Uint32x4.ConcatOdd, deinterleaveSlice[uint32](128, true)) - testUint64x2Binary(t, archsimd.Uint64x2.ConcatOdd, deinterleaveSlice[uint64](128, true)) -} - -func TestInterleaveEven(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.InterleaveEven, transposeSlice[int8](128, false)) - testInt16x8Binary(t, archsimd.Int16x8.InterleaveEven, transposeSlice[int16](128, false)) - testInt32x4Binary(t, archsimd.Int32x4.InterleaveEven, transposeSlice[int32](128, false)) - testInt64x2Binary(t, archsimd.Int64x2.InterleaveEven, transposeSlice[int64](128, false)) - testUint8x16Binary(t, archsimd.Uint8x16.InterleaveEven, transposeSlice[uint8](128, false)) - testUint16x8Binary(t, archsimd.Uint16x8.InterleaveEven, transposeSlice[uint16](128, false)) - testUint32x4Binary(t, archsimd.Uint32x4.InterleaveEven, transposeSlice[uint32](128, false)) - testUint64x2Binary(t, archsimd.Uint64x2.InterleaveEven, transposeSlice[uint64](128, false)) -} - -func TestInterleaveOdd(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.InterleaveOdd, transposeSlice[int8](128, true)) - testInt16x8Binary(t, archsimd.Int16x8.InterleaveOdd, transposeSlice[int16](128, true)) - testInt32x4Binary(t, archsimd.Int32x4.InterleaveOdd, transposeSlice[int32](128, true)) - testInt64x2Binary(t, archsimd.Int64x2.InterleaveOdd, transposeSlice[int64](128, true)) - testUint8x16Binary(t, archsimd.Uint8x16.InterleaveOdd, transposeSlice[uint8](128, true)) - testUint16x8Binary(t, archsimd.Uint16x8.InterleaveOdd, transposeSlice[uint16](128, true)) - testUint32x4Binary(t, archsimd.Uint32x4.InterleaveOdd, transposeSlice[uint32](128, true)) - testUint64x2Binary(t, archsimd.Uint64x2.InterleaveOdd, transposeSlice[uint64](128, true)) -} - -func TestInterleaveLoARM64(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.InterleaveLo, interleaveSlice[int8](128, false)) - testInt16x8Binary(t, archsimd.Int16x8.InterleaveLo, interleaveSlice[int16](128, false)) - testInt32x4Binary(t, archsimd.Int32x4.InterleaveLo, interleaveSlice[int32](128, false)) - testInt64x2Binary(t, archsimd.Int64x2.InterleaveLo, interleaveSlice[int64](128, false)) - testUint8x16Binary(t, archsimd.Uint8x16.InterleaveLo, interleaveSlice[uint8](128, false)) - testUint16x8Binary(t, archsimd.Uint16x8.InterleaveLo, interleaveSlice[uint16](128, false)) - testUint32x4Binary(t, archsimd.Uint32x4.InterleaveLo, interleaveSlice[uint32](128, false)) - testUint64x2Binary(t, archsimd.Uint64x2.InterleaveLo, interleaveSlice[uint64](128, false)) -} - -func TestInterleaveHiARM64(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.InterleaveHi, interleaveSlice[int8](128, true)) - testInt16x8Binary(t, archsimd.Int16x8.InterleaveHi, interleaveSlice[int16](128, true)) - testInt32x4Binary(t, archsimd.Int32x4.InterleaveHi, interleaveSlice[int32](128, true)) - testInt64x2Binary(t, archsimd.Int64x2.InterleaveHi, interleaveSlice[int64](128, true)) - testUint8x16Binary(t, archsimd.Uint8x16.InterleaveHi, interleaveSlice[uint8](128, true)) - testUint16x8Binary(t, archsimd.Uint16x8.InterleaveHi, interleaveSlice[uint16](128, true)) - testUint32x4Binary(t, archsimd.Uint32x4.InterleaveHi, interleaveSlice[uint32](128, true)) - testUint64x2Binary(t, archsimd.Uint64x2.InterleaveHi, interleaveSlice[uint64](128, true)) -} - -func TestGetElem(t *testing.T) { - // Int8x16 - { - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - v := archsimd.LoadInt8x16(a) - if e := v.GetElem(2); e != a[2] { - t.Errorf("Int8x16.GetElem(2) = %d, want %d", e, a[2]) - } - } - // Int16x8 - { - a := []int16{10, 20, 30, 40, 50, 60, 70, 80} - v := archsimd.LoadInt16x8(a) - if e := v.GetElem(3); e != a[3] { - t.Errorf("Int16x8.GetElem(3) = %d, want %d", e, a[3]) - } - } - // Int32x4 - { - a := []int32{100, 200, 300, 400} - v := archsimd.LoadInt32x4(a) - if e := v.GetElem(1); e != a[1] { - t.Errorf("Int32x4.GetElem(1) = %d, want %d", e, a[1]) - } - } - // Int64x2 - { - a := []int64{1000, 2000} - v := archsimd.LoadInt64x2(a) - if e := v.GetElem(0); e != a[0] { - t.Errorf("Int64x2.GetElem(0) = %d, want %d", e, a[0]) - } - } - // Uint8x16 - { - a := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - v := archsimd.LoadUint8x16(a) - if e := v.GetElem(5); e != a[5] { - t.Errorf("Uint8x16.GetElem(5) = %d, want %d", e, a[5]) - } - } - // Uint16x8 - { - a := []uint16{100, 200, 300, 400, 500, 600, 700, 800} - v := archsimd.LoadUint16x8(a) - if e := v.GetElem(7); e != a[7] { - t.Errorf("Uint16x8.GetElem(7) = %d, want %d", e, a[7]) - } - } - // Uint32x4 - { - a := []uint32{1000, 2000, 3000, 4000} - v := archsimd.LoadUint32x4(a) - if e := v.GetElem(2); e != a[2] { - t.Errorf("Uint32x4.GetElem(2) = %d, want %d", e, a[2]) - } - } - // Uint64x2 - { - a := []uint64{10000, 20000} - v := archsimd.LoadUint64x2(a) - if e := v.GetElem(1); e != a[1] { - t.Errorf("Uint64x2.GetElem(1) = %d, want %d", e, a[1]) - } - } - // Float32x4 - { - a := []float32{1.0, 2.0, 3.0, 4.0} - v := archsimd.LoadFloat32x4(a) - if e := v.GetElem(3); e != a[3] { - t.Errorf("Float32x4.GetElem(3) = %f, want %f", e, a[3]) - } - } - // Float64x2 - { - a := []float64{10.5, 20.5} - v := archsimd.LoadFloat64x2(a) - if e := v.GetElem(0); e != a[0] { - t.Errorf("Float64x2.GetElem(0) = %f, want %f", e, a[0]) - } - } -} - -func TestSetElem(t *testing.T) { - // Int8x16 - { - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - v := archsimd.LoadInt8x16(a) - v = v.SetElem(3, int8(99)) - a[3] = 99 - b := make([]int8, 16) - v.Store(b) - checkSlices(t, b, a) - } - // Int16x8 - { - a := []int16{10, 20, 30, 40, 50, 60, 70, 80} - v := archsimd.LoadInt16x8(a) - v = v.SetElem(5, int16(123)) - a[5] = 123 - b := make([]int16, 8) - v.Store(b) - checkSlices(t, b, a) - } - // Int32x4 - { - a := []int32{100, 200, 300, 400} - v := archsimd.LoadInt32x4(a) - v = v.SetElem(2, int32(999)) - a[2] = 999 - b := make([]int32, 4) - v.Store(b) - checkSlices(t, b, a) - } - // Int64x2 - { - a := []int64{1000, 2000} - v := archsimd.LoadInt64x2(a) - v = v.SetElem(1, int64(5555)) - a[1] = 5555 - b := make([]int64, 2) - v.Store(b) - checkSlices(t, b, a) - } - // Uint8x16 - { - a := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - v := archsimd.LoadUint8x16(a) - v = v.SetElem(7, uint8(200)) - a[7] = 200 - b := make([]uint8, 16) - v.Store(b) - checkSlices(t, b, a) - } - // Uint16x8 - { - a := []uint16{100, 200, 300, 400, 500, 600, 700, 800} - v := archsimd.LoadUint16x8(a) - v = v.SetElem(0, uint16(1111)) - a[0] = 1111 - b := make([]uint16, 8) - v.Store(b) - checkSlices(t, b, a) - } - // Uint32x4 - { - a := []uint32{1000, 2000, 3000, 4000} - v := archsimd.LoadUint32x4(a) - v = v.SetElem(3, uint32(9999)) - a[3] = 9999 - b := make([]uint32, 4) - v.Store(b) - checkSlices(t, b, a) - } - // Uint64x2 - { - a := []uint64{10000, 20000} - v := archsimd.LoadUint64x2(a) - v = v.SetElem(0, uint64(55555)) - a[0] = 55555 - b := make([]uint64, 2) - v.Store(b) - checkSlices(t, b, a) - } - // Float32x4 - { - a := []float32{1.0, 2.0, 3.0, 4.0} - v := archsimd.LoadFloat32x4(a) - v = v.SetElem(1, float32(42.5)) - a[1] = 42.5 - b := make([]float32, 4) - v.Store(b) - checkSlices(t, b, a) - } - // Float64x2 - { - a := []float64{10.5, 20.5} - v := archsimd.LoadFloat64x2(a) - v = v.SetElem(0, float64(99.9)) - a[0] = 99.9 - b := make([]float64, 2) - v.Store(b) - checkSlices(t, b, a) - } -} diff --git a/src/simd/archsimd/internal/simd_test/arm64_bitwise_test.go b/src/simd/archsimd/internal/simd_test/arm64_bitwise_test.go deleted file mode 100644 index c0b5522be4f1da7ccd1eabedba4ee4b7f8cbd421..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_bitwise_test.go +++ /dev/null @@ -1,84 +0,0 @@ -// 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 && arm64 - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -func TestAnd(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.And, andSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.And, andSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.And, andSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.And, andSlice[int64]) - - testUint8x16Binary(t, archsimd.Uint8x16.And, andSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.And, andSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.And, andSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.And, andSlice[uint64]) -} - -func TestOr(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.Or, orSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.Or, orSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Or, orSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.Or, orSlice[int64]) - - testUint8x16Binary(t, archsimd.Uint8x16.Or, orSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.Or, orSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Or, orSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.Or, orSlice[uint64]) -} - -func TestXor(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.Xor, xorSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.Xor, xorSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Xor, xorSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.Xor, xorSlice[int64]) - - testUint8x16Binary(t, archsimd.Uint8x16.Xor, xorSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.Xor, xorSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Xor, xorSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.Xor, xorSlice[uint64]) -} - -func TestAndNot(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.AndNot, andNotSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.AndNot, andNotSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.AndNot, andNotSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.AndNot, andNotSlice[int64]) - - testUint8x16Binary(t, archsimd.Uint8x16.AndNot, andNotSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.AndNot, andNotSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.AndNot, andNotSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.AndNot, andNotSlice[uint64]) -} - -func TestOrNot(t *testing.T) { - testInt8x16Binary(t, archsimd.Int8x16.OrNot, orNotSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.OrNot, orNotSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.OrNot, orNotSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.OrNot, orNotSlice[int64]) - - testUint8x16Binary(t, archsimd.Uint8x16.OrNot, orNotSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.OrNot, orNotSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.OrNot, orNotSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.OrNot, orNotSlice[uint64]) -} - -func TestNot(t *testing.T) { - testInt8x16Unary(t, archsimd.Int8x16.Not, notSlice[int8]) - testInt16x8Unary(t, archsimd.Int16x8.Not, notSlice[int16]) - testInt32x4Unary(t, archsimd.Int32x4.Not, notSlice[int32]) - testInt64x2Unary(t, archsimd.Int64x2.Not, notSlice[int64]) - - testUint8x16Unary(t, archsimd.Uint8x16.Not, notSlice[uint8]) - testUint16x8Unary(t, archsimd.Uint16x8.Not, notSlice[uint16]) - testUint32x4Unary(t, archsimd.Uint32x4.Not, notSlice[uint32]) - testUint64x2Unary(t, archsimd.Uint64x2.Not, notSlice[uint64]) -} diff --git a/src/simd/archsimd/internal/simd_test/arm64_compare_helpers_test.go b/src/simd/archsimd/internal/simd_test/arm64_compare_helpers_test.go deleted file mode 100644 index a7a90b71e07663c50f2a04a590dd46c0f7b6b2aa..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_compare_helpers_test.go +++ /dev/null @@ -1,164 +0,0 @@ -// Code generated by 'tmplgen'; DO NOT EDIT. - -//go:build goexperiment.simd && arm64 - -// This file contains functions testing simd methods that compare two operands. -// Each function in this file is specialized for a -// particular simd type x. - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -// testInt8x16Compare tests the simd comparison method f against the expected behavior generated by want -func testInt8x16Compare(t *testing.T, f func(_, _ archsimd.Int8x16) archsimd.Mask8x16, want func(_, _ []int8) []int64) { - n := 16 - t.Helper() - forSlicePair(t, int8s, n, func(x, y []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - b := archsimd.LoadInt8x16(y) - g := make([]int8, n) - f(a, b).ToInt8x16().Store(g) - w := want(x, y) - return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testInt16x8Compare tests the simd comparison method f against the expected behavior generated by want -func testInt16x8Compare(t *testing.T, f func(_, _ archsimd.Int16x8) archsimd.Mask16x8, want func(_, _ []int16) []int64) { - n := 8 - t.Helper() - forSlicePair(t, int16s, n, func(x, y []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - b := archsimd.LoadInt16x8(y) - g := make([]int16, n) - f(a, b).ToInt16x8().Store(g) - w := want(x, y) - return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testInt32x4Compare tests the simd comparison method f against the expected behavior generated by want -func testInt32x4Compare(t *testing.T, f func(_, _ archsimd.Int32x4) archsimd.Mask32x4, want func(_, _ []int32) []int64) { - n := 4 - t.Helper() - forSlicePair(t, int32s, n, func(x, y []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - b := archsimd.LoadInt32x4(y) - g := make([]int32, n) - f(a, b).ToInt32x4().Store(g) - w := want(x, y) - return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testInt64x2Compare tests the simd comparison method f against the expected behavior generated by want -func testInt64x2Compare(t *testing.T, f func(_, _ archsimd.Int64x2) archsimd.Mask64x2, want func(_, _ []int64) []int64) { - n := 2 - t.Helper() - forSlicePair(t, int64s, n, func(x, y []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - b := archsimd.LoadInt64x2(y) - g := make([]int64, n) - f(a, b).ToInt64x2().Store(g) - w := want(x, y) - return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint8x16Compare tests the simd comparison method f against the expected behavior generated by want -func testUint8x16Compare(t *testing.T, f func(_, _ archsimd.Uint8x16) archsimd.Mask8x16, want func(_, _ []uint8) []int64) { - n := 16 - t.Helper() - forSlicePair(t, uint8s, n, func(x, y []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - b := archsimd.LoadUint8x16(y) - g := make([]int8, n) - f(a, b).ToInt8x16().Store(g) - w := want(x, y) - return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint16x8Compare tests the simd comparison method f against the expected behavior generated by want -func testUint16x8Compare(t *testing.T, f func(_, _ archsimd.Uint16x8) archsimd.Mask16x8, want func(_, _ []uint16) []int64) { - n := 8 - t.Helper() - forSlicePair(t, uint16s, n, func(x, y []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - b := archsimd.LoadUint16x8(y) - g := make([]int16, n) - f(a, b).ToInt16x8().Store(g) - w := want(x, y) - return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint32x4Compare tests the simd comparison method f against the expected behavior generated by want -func testUint32x4Compare(t *testing.T, f func(_, _ archsimd.Uint32x4) archsimd.Mask32x4, want func(_, _ []uint32) []int64) { - n := 4 - t.Helper() - forSlicePair(t, uint32s, n, func(x, y []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - b := archsimd.LoadUint32x4(y) - g := make([]int32, n) - f(a, b).ToInt32x4().Store(g) - w := want(x, y) - return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint64x2Compare tests the simd comparison method f against the expected behavior generated by want -func testUint64x2Compare(t *testing.T, f func(_, _ archsimd.Uint64x2) archsimd.Mask64x2, want func(_, _ []uint64) []int64) { - n := 2 - t.Helper() - forSlicePair(t, uint64s, n, func(x, y []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - b := archsimd.LoadUint64x2(y) - g := make([]int64, n) - f(a, b).ToInt64x2().Store(g) - w := want(x, y) - return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testFloat32x4Compare tests the simd comparison method f against the expected behavior generated by want -func testFloat32x4Compare(t *testing.T, f func(_, _ archsimd.Float32x4) archsimd.Mask32x4, want func(_, _ []float32) []int64) { - n := 4 - t.Helper() - forSlicePair(t, float32s, n, func(x, y []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - b := archsimd.LoadFloat32x4(y) - g := make([]int32, n) - f(a, b).ToInt32x4().Store(g) - w := want(x, y) - return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testFloat64x2Compare tests the simd comparison method f against the expected behavior generated by want -func testFloat64x2Compare(t *testing.T, f func(_, _ archsimd.Float64x2) archsimd.Mask64x2, want func(_, _ []float64) []int64) { - n := 2 - t.Helper() - forSlicePair(t, float64s, n, func(x, y []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - b := archsimd.LoadFloat64x2(y) - g := make([]int64, n) - f(a, b).ToInt64x2().Store(g) - w := want(x, y) - return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} diff --git a/src/simd/archsimd/internal/simd_test/arm64_compare_test.go b/src/simd/archsimd/internal/simd_test/arm64_compare_test.go deleted file mode 100644 index e9a9eff3bbfd9c656c9a42d0d070c8d39c3e820f..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_compare_test.go +++ /dev/null @@ -1,192 +0,0 @@ -// 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 && arm64 - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -// --- Equal (hardware: CMEQ / FCMEQ) --- - -func TestEqual(t *testing.T) { - testInt8x16Compare(t, archsimd.Int8x16.Equal, equalSlice[int8]) - testInt16x8Compare(t, archsimd.Int16x8.Equal, equalSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.Equal, equalSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.Equal, equalSlice[int64]) - - testUint8x16Compare(t, archsimd.Uint8x16.Equal, equalSlice[uint8]) - testUint16x8Compare(t, archsimd.Uint16x8.Equal, equalSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.Equal, equalSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.Equal, equalSlice[uint64]) - - testFloat32x4Compare(t, archsimd.Float32x4.Equal, equalSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.Equal, equalSlice[float64]) -} - -// --- Greater (hardware: CMGT/CMHI for signed/unsigned, FCMGT for float) --- - -func TestGreater(t *testing.T) { - testInt8x16Compare(t, archsimd.Int8x16.Greater, greaterSlice[int8]) - testInt16x8Compare(t, archsimd.Int16x8.Greater, greaterSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.Greater, greaterSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.Greater, greaterSlice[int64]) - - testUint8x16Compare(t, archsimd.Uint8x16.Greater, greaterSlice[uint8]) - testUint16x8Compare(t, archsimd.Uint16x8.Greater, greaterSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.Greater, greaterSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.Greater, greaterSlice[uint64]) - - testFloat32x4Compare(t, archsimd.Float32x4.Greater, greaterSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.Greater, greaterSlice[float64]) -} - -// --- GreaterEqual (hardware: CMGE/CMHS for signed/unsigned, FCMGE for float) --- - -func TestGreaterEqual(t *testing.T) { - testInt8x16Compare(t, archsimd.Int8x16.GreaterEqual, greaterEqualSlice[int8]) - testInt16x8Compare(t, archsimd.Int16x8.GreaterEqual, greaterEqualSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.GreaterEqual, greaterEqualSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.GreaterEqual, greaterEqualSlice[int64]) - - testUint8x16Compare(t, archsimd.Uint8x16.GreaterEqual, greaterEqualSlice[uint8]) - testUint16x8Compare(t, archsimd.Uint16x8.GreaterEqual, greaterEqualSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.GreaterEqual, greaterEqualSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.GreaterEqual, greaterEqualSlice[uint64]) - - testFloat32x4Compare(t, archsimd.Float32x4.GreaterEqual, greaterEqualSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.GreaterEqual, greaterEqualSlice[float64]) -} - -// --- Less (derived: y.Greater(x)) --- - -func TestLess(t *testing.T) { - testInt8x16Compare(t, archsimd.Int8x16.Less, lessSlice[int8]) - testInt16x8Compare(t, archsimd.Int16x8.Less, lessSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.Less, lessSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.Less, lessSlice[int64]) - - testUint8x16Compare(t, archsimd.Uint8x16.Less, lessSlice[uint8]) - testUint16x8Compare(t, archsimd.Uint16x8.Less, lessSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.Less, lessSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.Less, lessSlice[uint64]) - - testFloat32x4Compare(t, archsimd.Float32x4.Less, lessSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.Less, lessSlice[float64]) -} - -// --- LessEqual (derived: y.GreaterEqual(x)) --- - -func TestLessEqual(t *testing.T) { - testInt8x16Compare(t, archsimd.Int8x16.LessEqual, lessEqualSlice[int8]) - testInt16x8Compare(t, archsimd.Int16x8.LessEqual, lessEqualSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.LessEqual, lessEqualSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.LessEqual, lessEqualSlice[int64]) - - testUint8x16Compare(t, archsimd.Uint8x16.LessEqual, lessEqualSlice[uint8]) - testUint16x8Compare(t, archsimd.Uint16x8.LessEqual, lessEqualSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.LessEqual, lessEqualSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.LessEqual, lessEqualSlice[uint64]) - - testFloat32x4Compare(t, archsimd.Float32x4.LessEqual, lessEqualSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.LessEqual, lessEqualSlice[float64]) -} - -// --- NotEqual (derived: Equal().Not()) --- - -func TestNotEqual(t *testing.T) { - testInt8x16Compare(t, archsimd.Int8x16.NotEqual, notEqualSlice[int8]) - testInt16x8Compare(t, archsimd.Int16x8.NotEqual, notEqualSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.NotEqual, notEqualSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.NotEqual, notEqualSlice[int64]) - - testUint8x16Compare(t, archsimd.Uint8x16.NotEqual, notEqualSlice[uint8]) - testUint16x8Compare(t, archsimd.Uint16x8.NotEqual, notEqualSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.NotEqual, notEqualSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.NotEqual, notEqualSlice[uint64]) - - testFloat32x4Compare(t, archsimd.Float32x4.NotEqual, notEqualSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.NotEqual, notEqualSlice[float64]) -} - -// --- Masked: zero elements where mask is false --- - -func TestMasked(t *testing.T) { - // Test Masked for Int8x16 - forSlicePair(t, int8s, 16, func(x, y []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - mask := archsimd.LoadInt8x16(y).Greater(archsimd.Int8x16{}) // mask: y > 0 - g := make([]int8, 16) - a.Masked(mask).Store(g) - w := make([]int8, 16) - for i := range w { - if y[i] > 0 { - w[i] = x[i] - } - } - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, y=%v", x, y) }) - }) - - // Test Masked for Float64x2 - forSlicePair(t, float64s, 2, func(x, y []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - mask := archsimd.LoadFloat64x2(y).Greater(archsimd.Float64x2{}) // mask: y > 0 - g := make([]float64, 2) - a.Masked(mask).Store(g) - w := make([]float64, 2) - for i := range w { - if y[i] > 0 { - w[i] = x[i] - } - } - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, y=%v", x, y) }) - }) -} - -// --- IfElse: set elements to y where mask is true, keep x where true --- - -func TestIfElse(t *testing.T) { - // Test Merge for Int8x16 - forSliceTriple(t, int8s, 16, func(x, y, m []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - b := archsimd.LoadInt8x16(y) - mask := archsimd.LoadInt8x16(m).Greater(archsimd.Int8x16{}) // mask: m > 0 - g := make([]int8, 16) - a.IfElse(mask, b).Store(g) - w := make([]int8, 16) - for i := range w { - if m[i] > 0 { - w[i] = y[i] - } else { - w[i] = x[i] - } - } - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, y=%v, m=%v", x, y, m) }) - }) - - // Test Merge for Float32x4 - forSliceTriple(t, float32s, 4, func(x, y, m []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - b := archsimd.LoadFloat32x4(y) - mask := archsimd.LoadFloat32x4(m).Greater(archsimd.Float32x4{}) // mask: m > 0 - g := make([]float32, 4) - a.IfElse(mask, b).Store(g) - w := make([]float32, 4) - for i := range w { - if m[i] > 0 { - w[i] = y[i] - } else { - w[i] = x[i] - } - } - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, y=%v, m=%v", x, y, m) }) - }) -} diff --git a/src/simd/archsimd/internal/simd_test/arm64_convert_test.go b/src/simd/archsimd/internal/simd_test/arm64_convert_test.go deleted file mode 100644 index ac737777f591094e4bb83b8697ea041ccc18d929..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_convert_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// 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 && arm64 - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -func TestConvertArm64(t *testing.T) { - testFloat64x2ConvertToFloat32x4(t, archsimd.Float64x2.ConvertToFloat32, map1[float64](toFloat32)) - testFloat32x4ConvertToFloat64x2(t, archsimd.Float32x4.ConvertLo2ToFloat64, map1n[float32](toFloat64, 2)) - - testFloat32x4ConvertToInt32x4(t, archsimd.Float32x4.ConvertToInt32, map1[float32](floatToInt32_arm64)) - testFloat64x2ConvertToInt64x2(t, archsimd.Float64x2.ConvertToInt64, map1[float64](floatToInt64_arm64)) - - testFloat32x4ConvertToUint32x4(t, archsimd.Float32x4.ConvertToUint32, map1[float32](floatToUint32_arm64)) - testFloat64x2ConvertToUint64x2(t, archsimd.Float64x2.ConvertToUint64, map1[float64](floatToUint64_arm64)) - - testInt32x4ConvertToFloat32x4(t, archsimd.Int32x4.ConvertToFloat32, map1[int32](toFloat32)) - testInt64x2ConvertToFloat64x2(t, archsimd.Int64x2.ConvertToFloat64, map1[int64](toFloat64)) - - testUint32x4ConvertToFloat32x4(t, archsimd.Uint32x4.ConvertToFloat32, map1[uint32](toFloat32)) - testUint64x2ConvertToFloat64x2(t, archsimd.Uint64x2.ConvertToFloat64, map1[uint64](toFloat64)) -} - -func TestTruncateArm64(t *testing.T) { - testInt16x8ConvertToInt8x16(t, archsimd.Int16x8.TruncToInt8, map1[int16](toInt8)) - testInt32x4ConvertToInt16x8(t, archsimd.Int32x4.TruncToInt16, map1[int32](toInt16)) - testInt64x2ConvertToInt32x4(t, archsimd.Int64x2.TruncToInt32, map1[int64](toInt32)) - - testUint16x8ConvertToUint8x16(t, archsimd.Uint16x8.TruncToUint8, map1[uint16](toUint8)) - testUint32x4ConvertToUint16x8(t, archsimd.Uint32x4.TruncToUint16, map1[uint32](toUint16)) - testUint64x2ConvertToUint32x4(t, archsimd.Uint64x2.TruncToUint32, map1[uint64](toUint32)) -} diff --git a/src/simd/archsimd/internal/simd_test/arm64_shift_helpers_test.go b/src/simd/archsimd/internal/simd_test/arm64_shift_helpers_test.go deleted file mode 100644 index d9fbaca88da746f2776e297b0e3146041f492a76..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_shift_helpers_test.go +++ /dev/null @@ -1,382 +0,0 @@ -// Code generated by 'tmplgen'; DO NOT EDIT. - -//go:build goexperiment.simd && arm64 - -// This file contains functions testing shift simd methods. -// Each function in this file is specialized for a -// particular simd type x. - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -// testInt8x16ShiftConst tests a const-shift method (unary + immediate). -func testInt8x16ShiftConst(t *testing.T, f func(_ archsimd.Int8x16, _ uint64) archsimd.Int8x16, want func(_ []int8, _ uint64) []int8) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - for _, amt := range []uint64{0, 1, 3, 8 - 1} { - a := archsimd.LoadInt8x16(x) - g := make([]int8, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testInt16x8ShiftConst tests a const-shift method (unary + immediate). -func testInt16x8ShiftConst(t *testing.T, f func(_ archsimd.Int16x8, _ uint64) archsimd.Int16x8, want func(_ []int16, _ uint64) []int16) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - for _, amt := range []uint64{0, 1, 3, 16 - 1} { - a := archsimd.LoadInt16x8(x) - g := make([]int16, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testInt32x4ShiftConst tests a const-shift method (unary + immediate). -func testInt32x4ShiftConst(t *testing.T, f func(_ archsimd.Int32x4, _ uint64) archsimd.Int32x4, want func(_ []int32, _ uint64) []int32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - for _, amt := range []uint64{0, 1, 3, 32 - 1} { - a := archsimd.LoadInt32x4(x) - g := make([]int32, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testInt64x2ShiftConst tests a const-shift method (unary + immediate). -func testInt64x2ShiftConst(t *testing.T, f func(_ archsimd.Int64x2, _ uint64) archsimd.Int64x2, want func(_ []int64, _ uint64) []int64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - for _, amt := range []uint64{0, 1, 3, 64 - 1} { - a := archsimd.LoadInt64x2(x) - g := make([]int64, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testUint8x16ShiftConst tests a const-shift method (unary + immediate). -func testUint8x16ShiftConst(t *testing.T, f func(_ archsimd.Uint8x16, _ uint64) archsimd.Uint8x16, want func(_ []uint8, _ uint64) []uint8) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - for _, amt := range []uint64{0, 1, 3, 8 - 1} { - a := archsimd.LoadUint8x16(x) - g := make([]uint8, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testUint16x8ShiftConst tests a const-shift method (unary + immediate). -func testUint16x8ShiftConst(t *testing.T, f func(_ archsimd.Uint16x8, _ uint64) archsimd.Uint16x8, want func(_ []uint16, _ uint64) []uint16) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - for _, amt := range []uint64{0, 1, 3, 16 - 1} { - a := archsimd.LoadUint16x8(x) - g := make([]uint16, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testUint32x4ShiftConst tests a const-shift method (unary + immediate). -func testUint32x4ShiftConst(t *testing.T, f func(_ archsimd.Uint32x4, _ uint64) archsimd.Uint32x4, want func(_ []uint32, _ uint64) []uint32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - for _, amt := range []uint64{0, 1, 3, 32 - 1} { - a := archsimd.LoadUint32x4(x) - g := make([]uint32, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testUint64x2ShiftConst tests a const-shift method (unary + immediate). -func testUint64x2ShiftConst(t *testing.T, f func(_ archsimd.Uint64x2, _ uint64) archsimd.Uint64x2, want func(_ []uint64, _ uint64) []uint64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - for _, amt := range []uint64{0, 1, 3, 64 - 1} { - a := archsimd.LoadUint64x2(x) - g := make([]uint64, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testInt8x16ShiftAll tests a shift-all method (unary + scalar uint64). -func testInt8x16ShiftAll(t *testing.T, f func(_ archsimd.Int8x16, _ uint64) archsimd.Int8x16, want func(_ []int8, _ uint64) []int8) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - for _, amt := range testShiftAllAmts { - a := archsimd.LoadInt8x16(x) - g := make([]int8, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testInt16x8ShiftAll tests a shift-all method (unary + scalar uint64). -func testInt16x8ShiftAll(t *testing.T, f func(_ archsimd.Int16x8, _ uint64) archsimd.Int16x8, want func(_ []int16, _ uint64) []int16) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - for _, amt := range testShiftAllAmts { - a := archsimd.LoadInt16x8(x) - g := make([]int16, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testInt32x4ShiftAll tests a shift-all method (unary + scalar uint64). -func testInt32x4ShiftAll(t *testing.T, f func(_ archsimd.Int32x4, _ uint64) archsimd.Int32x4, want func(_ []int32, _ uint64) []int32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - for _, amt := range testShiftAllAmts { - a := archsimd.LoadInt32x4(x) - g := make([]int32, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testInt64x2ShiftAll tests a shift-all method (unary + scalar uint64). -func testInt64x2ShiftAll(t *testing.T, f func(_ archsimd.Int64x2, _ uint64) archsimd.Int64x2, want func(_ []int64, _ uint64) []int64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - for _, amt := range testShiftAllAmts { - a := archsimd.LoadInt64x2(x) - g := make([]int64, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testUint8x16ShiftAll tests a shift-all method (unary + scalar uint64). -func testUint8x16ShiftAll(t *testing.T, f func(_ archsimd.Uint8x16, _ uint64) archsimd.Uint8x16, want func(_ []uint8, _ uint64) []uint8) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - for _, amt := range testShiftAllAmts { - a := archsimd.LoadUint8x16(x) - g := make([]uint8, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testUint16x8ShiftAll tests a shift-all method (unary + scalar uint64). -func testUint16x8ShiftAll(t *testing.T, f func(_ archsimd.Uint16x8, _ uint64) archsimd.Uint16x8, want func(_ []uint16, _ uint64) []uint16) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - for _, amt := range testShiftAllAmts { - a := archsimd.LoadUint16x8(x) - g := make([]uint16, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testUint32x4ShiftAll tests a shift-all method (unary + scalar uint64). -func testUint32x4ShiftAll(t *testing.T, f func(_ archsimd.Uint32x4, _ uint64) archsimd.Uint32x4, want func(_ []uint32, _ uint64) []uint32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - for _, amt := range testShiftAllAmts { - a := archsimd.LoadUint32x4(x) - g := make([]uint32, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testUint64x2ShiftAll tests a shift-all method (unary + scalar uint64). -func testUint64x2ShiftAll(t *testing.T, f func(_ archsimd.Uint64x2, _ uint64) archsimd.Uint64x2, want func(_ []uint64, _ uint64) []uint64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - for _, amt := range testShiftAllAmts { - a := archsimd.LoadUint64x2(x) - g := make([]uint64, n) - f(a, amt).Store(g) - w := want(x, amt) - if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { - return false - } - } - return true - }) -} - -// testUint8x16Shift tests a shift-like method where the first operand is Uint8x16 -// and the second operand is Int8x16 (mixed-type shift). -func testUint8x16Shift(t *testing.T, f func(_ archsimd.Uint8x16, _ archsimd.Int8x16) archsimd.Uint8x16, want func(_ []uint8, _ []int8) []uint8) { - n := 16 - t.Helper() - forSliceMixed(t, uint8s, int8s, n, func(x []uint8, y []int8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - b := archsimd.LoadInt8x16(y) - g := make([]uint8, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint16x8Shift tests a shift-like method where the first operand is Uint16x8 -// and the second operand is Int16x8 (mixed-type shift). -func testUint16x8Shift(t *testing.T, f func(_ archsimd.Uint16x8, _ archsimd.Int16x8) archsimd.Uint16x8, want func(_ []uint16, _ []int16) []uint16) { - n := 8 - t.Helper() - forSliceMixed(t, uint16s, int16s, n, func(x []uint16, y []int16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - b := archsimd.LoadInt16x8(y) - g := make([]uint16, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint32x4Shift tests a shift-like method where the first operand is Uint32x4 -// and the second operand is Int32x4 (mixed-type shift). -func testUint32x4Shift(t *testing.T, f func(_ archsimd.Uint32x4, _ archsimd.Int32x4) archsimd.Uint32x4, want func(_ []uint32, _ []int32) []uint32) { - n := 4 - t.Helper() - forSliceMixed(t, uint32s, int32s, n, func(x []uint32, y []int32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - b := archsimd.LoadInt32x4(y) - g := make([]uint32, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} - -// testUint64x2Shift tests a shift-like method where the first operand is Uint64x2 -// and the second operand is Int64x2 (mixed-type shift). -func testUint64x2Shift(t *testing.T, f func(_ archsimd.Uint64x2, _ archsimd.Int64x2) archsimd.Uint64x2, want func(_ []uint64, _ []int64) []uint64) { - n := 2 - t.Helper() - forSliceMixed(t, uint64s, int64s, n, func(x []uint64, y []int64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - b := archsimd.LoadInt64x2(y) - g := make([]uint64, n) - f(a, b).Store(g) - w := want(x, y) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) - }) -} diff --git a/src/simd/archsimd/internal/simd_test/arm64_shift_test.go b/src/simd/archsimd/internal/simd_test/arm64_shift_test.go deleted file mode 100644 index 76206e991d885b5d3ee7846dcb3f69b2c26f1829..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_shift_test.go +++ /dev/null @@ -1,169 +0,0 @@ -// 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 && arm64 - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -func TestShift(t *testing.T) { - // Signed — reuse binary helpers, same-type operand pairs - testInt8x16Binary(t, archsimd.Int8x16.Shift, shiftSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.Shift, shiftSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Shift, shiftSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.Shift, shiftSlice[int64]) - - // Unsigned — mixed-type operand pairs - testUint8x16Shift(t, archsimd.Uint8x16.Shift, shiftMixedSlice[uint8, int8]) - testUint16x8Shift(t, archsimd.Uint16x8.Shift, shiftMixedSlice[uint16, int16]) - testUint32x4Shift(t, archsimd.Uint32x4.Shift, shiftMixedSlice[uint32, int32]) - testUint64x2Shift(t, archsimd.Uint64x2.Shift, shiftMixedSlice[uint64, int64]) -} - -func TestShiftSaturated(t *testing.T) { - // Signed — reuse binary helpers - testInt8x16Binary(t, archsimd.Int8x16.ShiftSaturated, shiftSaturatingSignedSlice[int8]) - testInt16x8Binary(t, archsimd.Int16x8.ShiftSaturated, shiftSaturatingSignedSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.ShiftSaturated, shiftSaturatingSignedSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.ShiftSaturated, shiftSaturatingSignedSlice[int64]) - - // Unsigned — mixed-type - testUint8x16Shift(t, archsimd.Uint8x16.ShiftSaturated, shiftSaturatingUnsignedSlice[uint8, int8]) - testUint16x8Shift(t, archsimd.Uint16x8.ShiftSaturated, shiftSaturatingUnsignedSlice[uint16, int16]) - testUint32x4Shift(t, archsimd.Uint32x4.ShiftSaturated, shiftSaturatingUnsignedSlice[uint32, int32]) - testUint64x2Shift(t, archsimd.Uint64x2.ShiftSaturated, shiftSaturatingUnsignedSlice[uint64, int64]) -} - -var testShiftConstAmt uint64 = 3 - -func TestShiftLeftConst(t *testing.T) { - // Signed - testInt8x16ShiftConst(t, archsimd.Int8x16.ShiftAllLeft, shiftLeftByConstSlice[int8]) - testInt16x8ShiftConst(t, archsimd.Int16x8.ShiftAllLeft, shiftLeftByConstSlice[int16]) - testInt32x4ShiftConst(t, archsimd.Int32x4.ShiftAllLeft, shiftLeftByConstSlice[int32]) - testInt64x2ShiftConst(t, archsimd.Int64x2.ShiftAllLeft, shiftLeftByConstSlice[int64]) - // Unsigned - testUint8x16ShiftConst(t, archsimd.Uint8x16.ShiftAllLeft, shiftLeftByConstSlice[uint8]) - testUint16x8ShiftConst(t, archsimd.Uint16x8.ShiftAllLeft, shiftLeftByConstSlice[uint16]) - testUint32x4ShiftConst(t, archsimd.Uint32x4.ShiftAllLeft, shiftLeftByConstSlice[uint32]) - testUint64x2ShiftConst(t, archsimd.Uint64x2.ShiftAllLeft, shiftLeftByConstSlice[uint64]) - - // Variable shift amount to prevent constant folding - forSlice(t, int32s, 4, func(x []int32) bool { - a := archsimd.LoadInt32x4(x) - g := make([]int32, 4) - a.ShiftAllLeft(testShiftConstAmt).Store(g) - w := shiftLeftByConstSlice(x, testShiftConstAmt) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, testShiftConstAmt) }) - }) -} - -func TestShiftRightConst(t *testing.T) { - // Signed (arithmetic right shift) - testInt8x16ShiftConst(t, archsimd.Int8x16.ShiftAllRight, shiftRightByConstSlice[int8]) - testInt16x8ShiftConst(t, archsimd.Int16x8.ShiftAllRight, shiftRightByConstSlice[int16]) - testInt32x4ShiftConst(t, archsimd.Int32x4.ShiftAllRight, shiftRightByConstSlice[int32]) - testInt64x2ShiftConst(t, archsimd.Int64x2.ShiftAllRight, shiftRightByConstSlice[int64]) - // Unsigned (logical right shift) - testUint8x16ShiftConst(t, archsimd.Uint8x16.ShiftAllRight, shiftRightByConstSlice[uint8]) - testUint16x8ShiftConst(t, archsimd.Uint16x8.ShiftAllRight, shiftRightByConstSlice[uint16]) - testUint32x4ShiftConst(t, archsimd.Uint32x4.ShiftAllRight, shiftRightByConstSlice[uint32]) - testUint64x2ShiftConst(t, archsimd.Uint64x2.ShiftAllRight, shiftRightByConstSlice[uint64]) - - // Variable shift amount to prevent constant folding - forSlice(t, int32s, 4, func(x []int32) bool { - a := archsimd.LoadInt32x4(x) - g := make([]int32, 4) - a.ShiftAllRight(testShiftConstAmt).Store(g) - w := shiftRightByConstSlice(x, testShiftConstAmt) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, testShiftConstAmt) }) - }) -} - -// testShiftAllAmts contains shift amounts for ShiftAll tests, including -// in-range amounts for all element sizes and out-of-range amounts to -// verify CSEL/CMPconst clamping logic in the lowering rules. -var testShiftAllAmts = []uint64{0, 1, 3, 7, 15, 31, 63, 128, 1024} - -// testShiftAllVarAmt is a non-constant shift amount to prevent constant folding. -var testShiftAllVarAmt uint64 = 3 - -func TestShiftAllLeft(t *testing.T) { - // Signed - testInt8x16ShiftAll(t, archsimd.Int8x16.ShiftAllLeft, shiftAllLeftSlice[int8]) - testInt16x8ShiftAll(t, archsimd.Int16x8.ShiftAllLeft, shiftAllLeftSlice[int16]) - testInt32x4ShiftAll(t, archsimd.Int32x4.ShiftAllLeft, shiftAllLeftSlice[int32]) - testInt64x2ShiftAll(t, archsimd.Int64x2.ShiftAllLeft, shiftAllLeftSlice[int64]) - // Unsigned - testUint8x16ShiftAll(t, archsimd.Uint8x16.ShiftAllLeft, shiftAllLeftSlice[uint8]) - testUint16x8ShiftAll(t, archsimd.Uint16x8.ShiftAllLeft, shiftAllLeftSlice[uint16]) - testUint32x4ShiftAll(t, archsimd.Uint32x4.ShiftAllLeft, shiftAllLeftSlice[uint32]) - testUint64x2ShiftAll(t, archsimd.Uint64x2.ShiftAllLeft, shiftAllLeftSlice[uint64]) - - // Variable shift amount to prevent constant folding - forSlice(t, int32s, 4, func(x []int32) bool { - a := archsimd.LoadInt32x4(x) - g := make([]int32, 4) - a.ShiftAllLeft(testShiftAllVarAmt).Store(g) - w := shiftAllLeftSlice(x, testShiftAllVarAmt) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, testShiftAllVarAmt) }) - }) -} - -func TestShiftAllRight(t *testing.T) { - // Signed (arithmetic right shift) - testInt8x16ShiftAll(t, archsimd.Int8x16.ShiftAllRight, shiftAllRightSlice[int8]) - testInt16x8ShiftAll(t, archsimd.Int16x8.ShiftAllRight, shiftAllRightSlice[int16]) - testInt32x4ShiftAll(t, archsimd.Int32x4.ShiftAllRight, shiftAllRightSlice[int32]) - testInt64x2ShiftAll(t, archsimd.Int64x2.ShiftAllRight, shiftAllRightSlice[int64]) - // Unsigned (logical right shift) - testUint8x16ShiftAll(t, archsimd.Uint8x16.ShiftAllRight, shiftAllRightSlice[uint8]) - testUint16x8ShiftAll(t, archsimd.Uint16x8.ShiftAllRight, shiftAllRightSlice[uint16]) - testUint32x4ShiftAll(t, archsimd.Uint32x4.ShiftAllRight, shiftAllRightSlice[uint32]) - testUint64x2ShiftAll(t, archsimd.Uint64x2.ShiftAllRight, shiftAllRightSlice[uint64]) - - // Variable shift amount to prevent constant folding - forSlice(t, int32s, 4, func(x []int32) bool { - a := archsimd.LoadInt32x4(x) - g := make([]int32, 4) - a.ShiftAllRight(testShiftAllVarAmt).Store(g) - w := shiftAllRightSlice(x, testShiftAllVarAmt) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, testShiftAllVarAmt) }) - }) -} - -func TestConcatShiftBytesRight(t *testing.T) { - hide := hideConst[uint64] - - csbr := func(shift uint64) func(x, y []uint8) []uint8 { - return func(x, y []uint8) []uint8 { - z := make([]uint8, len(x)) - for i := range z { - target := i + int(shift) - if target < 16 { - z[i] = y[target] - } else if target < 32 { - z[i] = x[(target - 16)] - } - } - return z - } - } - - t.Run("Uint8x16", func(t *testing.T) { - for _, shift := range []uint64{0, 2, 8, 15} { - t.Log("shift", shift) - testUint8x16Binary(t, - func(x, y archsimd.Uint8x16) archsimd.Uint8x16 { return x.ConcatShiftBytesRight(y, shift) }, - csbr(shift)) - testUint8x16Binary(t, - func(x, y archsimd.Uint8x16) archsimd.Uint8x16 { return x.ConcatShiftBytesRight(y, hide(shift)) }, - csbr(hide(shift))) - } - }) -} diff --git a/src/simd/archsimd/internal/simd_test/arm64_simd_test.go b/src/simd/archsimd/internal/simd_test/arm64_simd_test.go deleted file mode 100644 index 3237ba936a8cf92b3620fa074b71dbdd766fafea..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_simd_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// 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 && arm64 - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -func TestBroadcastUint32x4(t *testing.T) { - s := make([]uint32, 4, 4) - archsimd.BroadcastUint32x4(123456789).Store(s) - checkSlices(t, s, []uint32{123456789, 123456789, 123456789, 123456789}) -} - -func TestBroadcastFloat32x4(t *testing.T) { - s := make([]float32, 4, 4) - archsimd.BroadcastFloat32x4(3.14).Store(s) - checkSlices(t, s, []float32{3.14, 3.14, 3.14, 3.14}) -} - -func TestBroadcastFloat64x2(t *testing.T) { - s := make([]float64, 2, 2) - archsimd.BroadcastFloat64x2(3.14).Store(s) - checkSlices(t, s, []float64{3.14, 3.14}) -} - -func TestBroadcastUint64x2(t *testing.T) { - s := make([]uint64, 2, 2) - archsimd.BroadcastUint64x2(123456789012345).Store(s) - checkSlices(t, s, []uint64{123456789012345, 123456789012345}) -} - -func TestString(t *testing.T) { - x := archsimd.LoadUint32x4([]uint32{0, 1, 2, 3}) - y := archsimd.LoadInt64x2([]int64{-44, -5}) - z := archsimd.LoadFloat32x4([]float32{0.5, 1.5, -2.5, 3.5e9}) - w := archsimd.LoadFloat64x2([]float64{-2.5, 3.5e9}) - - sx := "{0,1,2,3}" - sy := "{-44,-5}" - sz := "{0.5,1.5,-2.5,3.5e+09}" - sw := "{-2.5,3.5e+09}" - - if x.String() != sx { - t.Errorf("x=%s wanted %s", x, sx) - } - if y.String() != sy { - t.Errorf("y=%s wanted %s", y, sy) - } - if z.String() != sz { - t.Errorf("z=%s wanted %s", z, sz) - } - if w.String() != sw { - t.Errorf("w=%s wanted %s", w, sw) - } - t.Logf("w=%s", w) - t.Logf("x=%s", x) - t.Logf("y=%s", y) - t.Logf("z=%s", z) -} - -func TestBroadcastUint16x8(t *testing.T) { - s := make([]uint16, 8, 8) - archsimd.BroadcastUint16x8(12345).Store(s) - checkSlices(t, s, []uint16{12345, 12345, 12345, 12345, 12345, 12345, 12345, 12345}) -} - -func TestBroadcastInt8x16(t *testing.T) { - s := make([]int8, 16, 16) - archsimd.BroadcastInt8x16(-123).Store(s) - checkSlices(t, s, []int8{-123, -123, -123, -123, -123, -123, -123, -123, - -123, -123, -123, -123, -123, -123, -123, -123}) -} - -func TestBroadcastUint8x16(t *testing.T) { - s := make([]uint8, 16, 16) - archsimd.BroadcastUint8x16(200).Store(s) - checkSlices(t, s, []uint8{200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200}) -} - -func TestBroadcastInt16x8(t *testing.T) { - s := make([]int16, 8, 8) - archsimd.BroadcastInt16x8(-12345).Store(s) - checkSlices(t, s, []int16{-12345, -12345, -12345, -12345, -12345, -12345, -12345, -12345}) -} - -func TestBroadcastInt32x4(t *testing.T) { - s := make([]int32, 4, 4) - archsimd.BroadcastInt32x4(-123456789).Store(s) - checkSlices(t, s, []int32{-123456789, -123456789, -123456789, -123456789}) -} - -func TestBroadcastInt64x2(t *testing.T) { - s := make([]int64, 2, 2) - archsimd.BroadcastInt64x2(-123456789).Store(s) - checkSlices(t, s, []int64{-123456789, -123456789}) -} - -func TestLookupOrZero(t *testing.T) { - // Out-of-range indices produce zero lane value. - x := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - indices := []uint8{7, 6, 5, 4, 3, 2, 1, 0, 0xff, 8, 16, 9, 128, 10, 20, 11} - want := []uint8{8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 0, 10, 0, 11, 0, 12} - got := make([]uint8, len(x)) - archsimd.LoadUint8x16(x).LookupOrZero(archsimd.LoadUint8x16(indices)).Store(got) - checkSlices(t, got, want) -} - -func TestClMul(t *testing.T) { - var x = archsimd.LoadUint64x2([]uint64{1, 5}) - var y = archsimd.LoadUint64x2([]uint64{3, 9}) - - foo := func(v archsimd.Uint64x2, s []uint64) { - r := make([]uint64, 2, 2) - v.Store(r) - checkSlices[uint64](t, r, s) - } - - foo(x.CarrylessMultiplyEven(y), []uint64{3, 0}) - foo(x.CarrylessMultiplyEvenOdd(y), []uint64{9, 0}) - foo(x.CarrylessMultiplyOddEven(y), []uint64{15, 0}) - foo(x.CarrylessMultiplyOdd(y), []uint64{45, 0}) - foo(y.CarrylessMultiplyEven(y), []uint64{5, 0}) -} diff --git a/src/simd/archsimd/internal/simd_test/arm64_unary_helpers_test.go b/src/simd/archsimd/internal/simd_test/arm64_unary_helpers_test.go deleted file mode 100644 index 78d1db9cc51e689dab466e1e5a3d82c8ae491ae9..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_unary_helpers_test.go +++ /dev/null @@ -1,1554 +0,0 @@ -// Code generated by 'tmplgen'; DO NOT EDIT. - -//go:build goexperiment.simd && arm64 - -// This file contains functions testing unary simd methods. -// Each function in this file is specialized for a -// particular simd type x. - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -// testInt8x16ConvertToInt8x16 tests the simd conversion method f against the expected behavior generated by want. -func testInt8x16ConvertToInt8x16(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int8x16, want func(x []int8) []int8) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToInt8x16 tests the simd conversion method f against the expected behavior generated by want. -func testInt16x8ConvertToInt8x16(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int8x16, want func(x []int16) []int8) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToInt8x16 tests the simd conversion method f against the expected behavior generated by want. -func testInt32x4ConvertToInt8x16(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int8x16, want func(x []int32) []int8) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToInt8x16 tests the simd conversion method f against the expected behavior generated by want. -func testInt64x2ConvertToInt8x16(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int8x16, want func(x []int64) []int8) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToInt8x16 tests the simd conversion method f against the expected behavior generated by want. -func testUint8x16ConvertToInt8x16(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int8x16, want func(x []uint8) []int8) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToInt8x16 tests the simd conversion method f against the expected behavior generated by want. -func testUint16x8ConvertToInt8x16(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int8x16, want func(x []uint16) []int8) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToInt8x16 tests the simd conversion method f against the expected behavior generated by want. -func testUint32x4ConvertToInt8x16(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int8x16, want func(x []uint32) []int8) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToInt8x16 tests the simd conversion method f against the expected behavior generated by want. -func testUint64x2ConvertToInt8x16(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int8x16, want func(x []uint64) []int8) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToInt8x16 tests the simd conversion method f against the expected behavior generated by want. -func testFloat32x4ConvertToInt8x16(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int8x16, want func(x []float32) []int8) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToInt8x16 tests the simd conversion method f against the expected behavior generated by want. -func testFloat64x2ConvertToInt8x16(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int8x16, want func(x []float64) []int8) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16ConvertToUint8x16 tests the simd conversion method f against the expected behavior generated by want. -func testInt8x16ConvertToUint8x16(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint8x16, want func(x []int8) []uint8) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToUint8x16 tests the simd conversion method f against the expected behavior generated by want. -func testInt16x8ConvertToUint8x16(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint8x16, want func(x []int16) []uint8) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToUint8x16 tests the simd conversion method f against the expected behavior generated by want. -func testInt32x4ConvertToUint8x16(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint8x16, want func(x []int32) []uint8) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToUint8x16 tests the simd conversion method f against the expected behavior generated by want. -func testInt64x2ConvertToUint8x16(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint8x16, want func(x []int64) []uint8) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToUint8x16 tests the simd conversion method f against the expected behavior generated by want. -func testUint8x16ConvertToUint8x16(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint8x16, want func(x []uint8) []uint8) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToUint8x16 tests the simd conversion method f against the expected behavior generated by want. -func testUint16x8ConvertToUint8x16(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint8x16, want func(x []uint16) []uint8) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToUint8x16 tests the simd conversion method f against the expected behavior generated by want. -func testUint32x4ConvertToUint8x16(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint8x16, want func(x []uint32) []uint8) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToUint8x16 tests the simd conversion method f against the expected behavior generated by want. -func testUint64x2ConvertToUint8x16(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint8x16, want func(x []uint64) []uint8) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToUint8x16 tests the simd conversion method f against the expected behavior generated by want. -func testFloat32x4ConvertToUint8x16(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint8x16, want func(x []float32) []uint8) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToUint8x16 tests the simd conversion method f against the expected behavior generated by want. -func testFloat64x2ConvertToUint8x16(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint8x16, want func(x []float64) []uint8) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16ConvertToInt16x8 tests the simd conversion method f against the expected behavior generated by want. -func testInt8x16ConvertToInt16x8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int16x8, want func(x []int8) []int16) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToInt16x8 tests the simd conversion method f against the expected behavior generated by want. -func testInt16x8ConvertToInt16x8(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int16x8, want func(x []int16) []int16) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToInt16x8 tests the simd conversion method f against the expected behavior generated by want. -func testInt32x4ConvertToInt16x8(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int16x8, want func(x []int32) []int16) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToInt16x8 tests the simd conversion method f against the expected behavior generated by want. -func testInt64x2ConvertToInt16x8(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int16x8, want func(x []int64) []int16) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToInt16x8 tests the simd conversion method f against the expected behavior generated by want. -func testUint8x16ConvertToInt16x8(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int16x8, want func(x []uint8) []int16) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToInt16x8 tests the simd conversion method f against the expected behavior generated by want. -func testUint16x8ConvertToInt16x8(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int16x8, want func(x []uint16) []int16) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToInt16x8 tests the simd conversion method f against the expected behavior generated by want. -func testUint32x4ConvertToInt16x8(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int16x8, want func(x []uint32) []int16) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToInt16x8 tests the simd conversion method f against the expected behavior generated by want. -func testUint64x2ConvertToInt16x8(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int16x8, want func(x []uint64) []int16) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToInt16x8 tests the simd conversion method f against the expected behavior generated by want. -func testFloat32x4ConvertToInt16x8(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int16x8, want func(x []float32) []int16) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToInt16x8 tests the simd conversion method f against the expected behavior generated by want. -func testFloat64x2ConvertToInt16x8(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int16x8, want func(x []float64) []int16) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16ConvertToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -func testInt8x16ConvertToUint16x8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint16x8, want func(x []int8) []uint16) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -func testInt16x8ConvertToUint16x8(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint16x8, want func(x []int16) []uint16) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -func testInt32x4ConvertToUint16x8(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint16x8, want func(x []int32) []uint16) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -func testInt64x2ConvertToUint16x8(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint16x8, want func(x []int64) []uint16) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -func testUint8x16ConvertToUint16x8(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint16x8, want func(x []uint8) []uint16) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -func testUint16x8ConvertToUint16x8(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint16x8, want func(x []uint16) []uint16) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -func testUint32x4ConvertToUint16x8(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint16x8, want func(x []uint32) []uint16) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -func testUint64x2ConvertToUint16x8(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint16x8, want func(x []uint64) []uint16) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -func testFloat32x4ConvertToUint16x8(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint16x8, want func(x []float32) []uint16) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -func testFloat64x2ConvertToUint16x8(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint16x8, want func(x []float64) []uint16) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16ConvertToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt8x16ConvertToInt32x4(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int32x4, want func(x []int8) []int32) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt16x8ConvertToInt32x4(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int32x4, want func(x []int16) []int32) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt32x4ConvertToInt32x4(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int32x4, want func(x []int32) []int32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt64x2ConvertToInt32x4(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int32x4, want func(x []int64) []int32) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint8x16ConvertToInt32x4(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int32x4, want func(x []uint8) []int32) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint16x8ConvertToInt32x4(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int32x4, want func(x []uint16) []int32) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint32x4ConvertToInt32x4(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int32x4, want func(x []uint32) []int32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint64x2ConvertToInt32x4(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int32x4, want func(x []uint64) []int32) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -func testFloat32x4ConvertToInt32x4(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int32x4, want func(x []float32) []int32) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -func testFloat64x2ConvertToInt32x4(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int32x4, want func(x []float64) []int32) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16ConvertToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt8x16ConvertToUint32x4(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint32x4, want func(x []int8) []uint32) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt16x8ConvertToUint32x4(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint32x4, want func(x []int16) []uint32) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt32x4ConvertToUint32x4(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint32x4, want func(x []int32) []uint32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt64x2ConvertToUint32x4(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint32x4, want func(x []int64) []uint32) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint8x16ConvertToUint32x4(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint32x4, want func(x []uint8) []uint32) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint16x8ConvertToUint32x4(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint32x4, want func(x []uint16) []uint32) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint32x4ConvertToUint32x4(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint32x4, want func(x []uint32) []uint32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint64x2ConvertToUint32x4(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint32x4, want func(x []uint64) []uint32) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -func testFloat32x4ConvertToUint32x4(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint32x4, want func(x []float32) []uint32) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -func testFloat64x2ConvertToUint32x4(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint32x4, want func(x []float64) []uint32) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16ConvertToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt8x16ConvertToInt64x2(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int64x2, want func(x []int8) []int64) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt16x8ConvertToInt64x2(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int64x2, want func(x []int16) []int64) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt32x4ConvertToInt64x2(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int64x2, want func(x []int32) []int64) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt64x2ConvertToInt64x2(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int64x2, want func(x []int64) []int64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint8x16ConvertToInt64x2(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int64x2, want func(x []uint8) []int64) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint16x8ConvertToInt64x2(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int64x2, want func(x []uint16) []int64) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint32x4ConvertToInt64x2(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int64x2, want func(x []uint32) []int64) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint64x2ConvertToInt64x2(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int64x2, want func(x []uint64) []int64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -func testFloat32x4ConvertToInt64x2(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int64x2, want func(x []float32) []int64) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -func testFloat64x2ConvertToInt64x2(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int64x2, want func(x []float64) []int64) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16ConvertToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt8x16ConvertToUint64x2(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint64x2, want func(x []int8) []uint64) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt16x8ConvertToUint64x2(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint64x2, want func(x []int16) []uint64) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt32x4ConvertToUint64x2(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint64x2, want func(x []int32) []uint64) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt64x2ConvertToUint64x2(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint64x2, want func(x []int64) []uint64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint8x16ConvertToUint64x2(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint64x2, want func(x []uint8) []uint64) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint16x8ConvertToUint64x2(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint64x2, want func(x []uint16) []uint64) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint32x4ConvertToUint64x2(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint64x2, want func(x []uint32) []uint64) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint64x2ConvertToUint64x2(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint64x2, want func(x []uint64) []uint64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -func testFloat32x4ConvertToUint64x2(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint64x2, want func(x []float32) []uint64) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -func testFloat64x2ConvertToUint64x2(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint64x2, want func(x []float64) []uint64) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16ConvertToFloat32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt8x16ConvertToFloat32x4(t *testing.T, f func(x archsimd.Int8x16) archsimd.Float32x4, want func(x []int8) []float32) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToFloat32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt16x8ConvertToFloat32x4(t *testing.T, f func(x archsimd.Int16x8) archsimd.Float32x4, want func(x []int16) []float32) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToFloat32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt32x4ConvertToFloat32x4(t *testing.T, f func(x archsimd.Int32x4) archsimd.Float32x4, want func(x []int32) []float32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToFloat32x4 tests the simd conversion method f against the expected behavior generated by want. -func testInt64x2ConvertToFloat32x4(t *testing.T, f func(x archsimd.Int64x2) archsimd.Float32x4, want func(x []int64) []float32) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToFloat32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint8x16ConvertToFloat32x4(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Float32x4, want func(x []uint8) []float32) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToFloat32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint16x8ConvertToFloat32x4(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Float32x4, want func(x []uint16) []float32) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToFloat32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint32x4ConvertToFloat32x4(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Float32x4, want func(x []uint32) []float32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToFloat32x4 tests the simd conversion method f against the expected behavior generated by want. -func testUint64x2ConvertToFloat32x4(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Float32x4, want func(x []uint64) []float32) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToFloat32x4 tests the simd conversion method f against the expected behavior generated by want. -func testFloat32x4ConvertToFloat32x4(t *testing.T, f func(x archsimd.Float32x4) archsimd.Float32x4, want func(x []float32) []float32) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToFloat32x4 tests the simd conversion method f against the expected behavior generated by want. -func testFloat64x2ConvertToFloat32x4(t *testing.T, f func(x archsimd.Float64x2) archsimd.Float32x4, want func(x []float64) []float32) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16ConvertToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt8x16ConvertToFloat64x2(t *testing.T, f func(x archsimd.Int8x16) archsimd.Float64x2, want func(x []int8) []float64) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt16x8ConvertToFloat64x2(t *testing.T, f func(x archsimd.Int16x8) archsimd.Float64x2, want func(x []int16) []float64) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt32x4ConvertToFloat64x2(t *testing.T, f func(x archsimd.Int32x4) archsimd.Float64x2, want func(x []int32) []float64) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. -func testInt64x2ConvertToFloat64x2(t *testing.T, f func(x archsimd.Int64x2) archsimd.Float64x2, want func(x []int64) []float64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint8x16ConvertToFloat64x2(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Float64x2, want func(x []uint8) []float64) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint16x8ConvertToFloat64x2(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Float64x2, want func(x []uint16) []float64) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint32x4ConvertToFloat64x2(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Float64x2, want func(x []uint32) []float64) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. -func testUint64x2ConvertToFloat64x2(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Float64x2, want func(x []uint64) []float64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. -func testFloat32x4ConvertToFloat64x2(t *testing.T, f func(x archsimd.Float32x4) archsimd.Float64x2, want func(x []float32) []float64) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. -func testFloat64x2ConvertToFloat64x2(t *testing.T, f func(x archsimd.Float64x2) archsimd.Float64x2, want func(x []float64) []float64) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16Unary tests the simd unary method f against the expected behavior generated by want -func testInt8x16Unary(t *testing.T, f func(_ archsimd.Int8x16) archsimd.Int8x16, want func(_ []int8) []int8) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]int8, n) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8Unary tests the simd unary method f against the expected behavior generated by want -func testInt16x8Unary(t *testing.T, f func(_ archsimd.Int16x8) archsimd.Int16x8, want func(_ []int16) []int16) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]int16, n) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4Unary tests the simd unary method f against the expected behavior generated by want -func testInt32x4Unary(t *testing.T, f func(_ archsimd.Int32x4) archsimd.Int32x4, want func(_ []int32) []int32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]int32, n) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2Unary tests the simd unary method f against the expected behavior generated by want -func testInt64x2Unary(t *testing.T, f func(_ archsimd.Int64x2) archsimd.Int64x2, want func(_ []int64) []int64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int64, n) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16Unary tests the simd unary method f against the expected behavior generated by want -func testUint8x16Unary(t *testing.T, f func(_ archsimd.Uint8x16) archsimd.Uint8x16, want func(_ []uint8) []uint8) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]uint8, n) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8Unary tests the simd unary method f against the expected behavior generated by want -func testUint16x8Unary(t *testing.T, f func(_ archsimd.Uint16x8) archsimd.Uint16x8, want func(_ []uint16) []uint16) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]uint16, n) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4Unary tests the simd unary method f against the expected behavior generated by want -func testUint32x4Unary(t *testing.T, f func(_ archsimd.Uint32x4) archsimd.Uint32x4, want func(_ []uint32) []uint32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]uint32, n) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2Unary tests the simd unary method f against the expected behavior generated by want -func testUint64x2Unary(t *testing.T, f func(_ archsimd.Uint64x2) archsimd.Uint64x2, want func(_ []uint64) []uint64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint64, n) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4Unary tests the simd unary method f against the expected behavior generated by want -func testFloat32x4Unary(t *testing.T, f func(_ archsimd.Float32x4) archsimd.Float32x4, want func(_ []float32) []float32) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]float32, n) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2Unary tests the simd unary method f against the expected behavior generated by want -func testFloat64x2Unary(t *testing.T, f func(_ archsimd.Float64x2) archsimd.Float64x2, want func(_ []float64) []float64) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]float64, n) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} diff --git a/src/simd/archsimd/internal/simd_test/arm64_unary_test.go b/src/simd/archsimd/internal/simd_test/arm64_unary_test.go deleted file mode 100644 index ec1c80961fceb5763b7d0e62c5d8a13efd2cb154..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/arm64_unary_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// 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 && arm64 - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -func TestSqrt(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Sqrt, sqrtSlice[float32]) - testFloat64x2Unary(t, archsimd.Float64x2.Sqrt, sqrtSlice[float64]) -} - -func TestRound(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Round, roundSlice[float32]) - testFloat64x2Unary(t, archsimd.Float64x2.Round, roundSlice[float64]) -} - -func TestFloor(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Floor, floorSlice[float32]) - testFloat64x2Unary(t, archsimd.Float64x2.Floor, floorSlice[float64]) -} - -func TestCeil(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Ceil, ceilSlice[float32]) - testFloat64x2Unary(t, archsimd.Float64x2.Ceil, ceilSlice[float64]) -} - -func TestTrunc(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Trunc, truncSlice[float32]) - testFloat64x2Unary(t, archsimd.Float64x2.Trunc, truncSlice[float64]) -} diff --git a/src/simd/archsimd/internal/simd_test/binary_128_test.go b/src/simd/archsimd/internal/simd_test/binary_128_test.go index 79360e61aea74ae847fc3c908a996a5d2f6fb8b6..e5c4984cd3c27cfd4f8c5f8fbc14e043a047f513 100644 --- a/src/simd/archsimd/internal/simd_test/binary_128_test.go +++ b/src/simd/archsimd/internal/simd_test/binary_128_test.go @@ -2,11 +2,12 @@ // Copyright 2025 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 && wasm +//go:build goexperiment.simd && (amd64 || wasm || arm64) package simd_test import ( + "runtime" "simd/archsimd" "testing" ) @@ -42,35 +43,33 @@ testUint8x16Binary(t, archsimd.Uint8x16.Sub, subSlice[uint8]) } func TestMax(t *testing.T) { + if runtime.GOARCH != "amd64" { + // skip in AMD64 as NaN behavior is different + testFloat32x4Binary(t, archsimd.Float32x4.Max, maxSlice[float32]) + testFloat64x2Binary(t, archsimd.Float64x2.Max, maxSlice[float64]) + } + testInt8x16Binary(t, archsimd.Int8x16.Max, maxSlice[int8]) testInt16x8Binary(t, archsimd.Int16x8.Max, maxSlice[int16]) testInt32x4Binary(t, archsimd.Int32x4.Max, maxSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.Max, maxSlice[int64]) - - testInt8x16Binary(t, archsimd.Int8x16.Max, maxSlice[int8]) - + testUint8x16Binary(t, archsimd.Uint8x16.Max, maxSlice[uint8]) testUint16x8Binary(t, archsimd.Uint16x8.Max, maxSlice[uint16]) testUint32x4Binary(t, archsimd.Uint32x4.Max, maxSlice[uint32]) - - testUint64x2Binary(t, archsimd.Uint64x2.Max, maxSlice[uint64]) - - testUint8x16Binary(t, archsimd.Uint8x16.Max, maxSlice[uint8]) } func TestMin(t *testing.T) { + if runtime.GOARCH != "amd64" { + // skip in AMD64 as NaN behavior is different + testFloat32x4Binary(t, archsimd.Float32x4.Min, minSlice[float32]) + testFloat64x2Binary(t, archsimd.Float64x2.Min, minSlice[float64]) + } + testInt8x16Binary(t, archsimd.Int8x16.Min, minSlice[int8]) testInt16x8Binary(t, archsimd.Int16x8.Min, minSlice[int16]) testInt32x4Binary(t, archsimd.Int32x4.Min, minSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.Min, minSlice[int64]) - - testInt8x16Binary(t, archsimd.Int8x16.Min, minSlice[int8]) - + testUint8x16Binary(t, archsimd.Uint8x16.Min, minSlice[uint8]) testUint16x8Binary(t, archsimd.Uint16x8.Min, minSlice[uint16]) testUint32x4Binary(t, archsimd.Uint32x4.Min, minSlice[uint32]) - - testUint64x2Binary(t, archsimd.Uint64x2.Min, minSlice[uint64]) - - testUint8x16Binary(t, archsimd.Uint8x16.Min, minSlice[uint8]) } func TestAnd(t *testing.T) { @@ -129,13 +128,195 @@ testInt8x16Binary(t, archsimd.Int8x16.Mul, mulSlice[int8]) testUint8x16Binary(t, archsimd.Uint8x16.Mul, mulSlice[uint8]) testInt16x8Binary(t, archsimd.Int16x8.Mul, mulSlice[int16]) testInt32x4Binary(t, archsimd.Int32x4.Mul, mulSlice[int32]) - - if archsimd.X86.AVX512() { - testInt64x2Binary(t, archsimd.Int64x2.Mul, mulSlice[int64]) - } } func TestDiv(t *testing.T) { testFloat32x4Binary(t, archsimd.Float32x4.Div, divSlice[float32]) testFloat64x2Binary(t, archsimd.Float64x2.Div, divSlice[float64]) } + +func TestGetElem(t *testing.T) { + // Int8x16 + { + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + v := archsimd.LoadInt8x16(a) + if e := v.GetElem(2); e != a[2] { + t.Errorf("Int8x16.GetElem(2) = %d, want %d", e, a[2]) + } + } + // Int16x8 + { + a := []int16{10, 20, 30, 40, 50, 60, 70, 80} + v := archsimd.LoadInt16x8(a) + if e := v.GetElem(3); e != a[3] { + t.Errorf("Int16x8.GetElem(3) = %d, want %d", e, a[3]) + } + } + // Int32x4 + { + a := []int32{100, 200, 300, 400} + v := archsimd.LoadInt32x4(a) + if e := v.GetElem(1); e != a[1] { + t.Errorf("Int32x4.GetElem(1) = %d, want %d", e, a[1]) + } + } + // Int64x2 + { + a := []int64{1000, 2000} + v := archsimd.LoadInt64x2(a) + if e := v.GetElem(0); e != a[0] { + t.Errorf("Int64x2.GetElem(0) = %d, want %d", e, a[0]) + } + } + // Uint8x16 + { + a := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + v := archsimd.LoadUint8x16(a) + if e := v.GetElem(5); e != a[5] { + t.Errorf("Uint8x16.GetElem(5) = %d, want %d", e, a[5]) + } + } + // Uint16x8 + { + a := []uint16{100, 200, 300, 400, 500, 600, 700, 800} + v := archsimd.LoadUint16x8(a) + if e := v.GetElem(7); e != a[7] { + t.Errorf("Uint16x8.GetElem(7) = %d, want %d", e, a[7]) + } + } + // Uint32x4 + { + a := []uint32{1000, 2000, 3000, 4000} + v := archsimd.LoadUint32x4(a) + if e := v.GetElem(2); e != a[2] { + t.Errorf("Uint32x4.GetElem(2) = %d, want %d", e, a[2]) + } + } + // Uint64x2 + { + a := []uint64{10000, 20000} + v := archsimd.LoadUint64x2(a) + if e := v.GetElem(1); e != a[1] { + t.Errorf("Uint64x2.GetElem(1) = %d, want %d", e, a[1]) + } + } + // Float32x4 + { + a := []float32{1.0, 2.0, 3.0, 4.0} + v := archsimd.LoadFloat32x4(a) + if e := v.GetElem(3); e != a[3] { + t.Errorf("Float32x4.GetElem(3) = %f, want %f", e, a[3]) + } + } + // Float64x2 + { + a := []float64{10.5, 20.5} + v := archsimd.LoadFloat64x2(a) + if e := v.GetElem(0); e != a[0] { + t.Errorf("Float64x2.GetElem(0) = %f, want %f", e, a[0]) + } + } +} + +func TestSetElem(t *testing.T) { + // Int8x16 + { + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + v := archsimd.LoadInt8x16(a) + v = v.SetElem(3, int8(99)) + a[3] = 99 + b := make([]int8, 16) + v.Store(b) + checkSlices(t, b, a) + } + // Int16x8 + { + a := []int16{10, 20, 30, 40, 50, 60, 70, 80} + v := archsimd.LoadInt16x8(a) + v = v.SetElem(5, int16(123)) + a[5] = 123 + b := make([]int16, 8) + v.Store(b) + checkSlices(t, b, a) + } + // Int32x4 + { + a := []int32{100, 200, 300, 400} + v := archsimd.LoadInt32x4(a) + v = v.SetElem(2, int32(999)) + a[2] = 999 + b := make([]int32, 4) + v.Store(b) + checkSlices(t, b, a) + } + // Int64x2 + { + a := []int64{1000, 2000} + v := archsimd.LoadInt64x2(a) + v = v.SetElem(1, int64(5555)) + a[1] = 5555 + b := make([]int64, 2) + v.Store(b) + checkSlices(t, b, a) + } + // Uint8x16 + { + a := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + v := archsimd.LoadUint8x16(a) + v = v.SetElem(7, uint8(200)) + a[7] = 200 + b := make([]uint8, 16) + v.Store(b) + checkSlices(t, b, a) + } + // Uint16x8 + { + a := []uint16{100, 200, 300, 400, 500, 600, 700, 800} + v := archsimd.LoadUint16x8(a) + v = v.SetElem(0, uint16(1111)) + a[0] = 1111 + b := make([]uint16, 8) + v.Store(b) + checkSlices(t, b, a) + } + // Uint32x4 + { + a := []uint32{1000, 2000, 3000, 4000} + v := archsimd.LoadUint32x4(a) + v = v.SetElem(3, uint32(9999)) + a[3] = 9999 + b := make([]uint32, 4) + v.Store(b) + checkSlices(t, b, a) + } + // Uint64x2 + { + a := []uint64{10000, 20000} + v := archsimd.LoadUint64x2(a) + v = v.SetElem(0, uint64(55555)) + a[0] = 55555 + b := make([]uint64, 2) + v.Store(b) + checkSlices(t, b, a) + } + // Float32x4 + { + a := []float32{1.0, 2.0, 3.0, 4.0} + v := archsimd.LoadFloat32x4(a) + v = v.SetElem(1, float32(42.5)) + a[1] = 42.5 + b := make([]float32, 4) + v.Store(b) + checkSlices(t, b, a) + } + // Float64x2 + { + a := []float64{10.5, 20.5} + v := archsimd.LoadFloat64x2(a) + v = v.SetElem(0, float64(99.9)) + a[0] = 99.9 + b := make([]float64, 2) + v.Store(b) + checkSlices(t, b, a) + } +} diff --git a/src/simd/archsimd/internal/simd_test/binary_arm64_test.go b/src/simd/archsimd/internal/simd_test/binary_arm64_test.go new file mode 100644 index 0000000000000000000000000000000000000000..0476b222a7ab9e67ecc022702694ef3b3ba59346 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/binary_arm64_test.go @@ -0,0 +1,90 @@ +// 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 && arm64 + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +func TestConcatEven(t *testing.T) { + testInt8x16Binary(t, archsimd.Int8x16.ConcatEven, deinterleaveSlice[int8](128, false)) + testInt16x8Binary(t, archsimd.Int16x8.ConcatEven, deinterleaveSlice[int16](128, false)) + testInt32x4Binary(t, archsimd.Int32x4.ConcatEven, deinterleaveSlice[int32](128, false)) + testInt64x2Binary(t, archsimd.Int64x2.ConcatEven, deinterleaveSlice[int64](128, false)) + testUint8x16Binary(t, archsimd.Uint8x16.ConcatEven, deinterleaveSlice[uint8](128, false)) + testUint16x8Binary(t, archsimd.Uint16x8.ConcatEven, deinterleaveSlice[uint16](128, false)) + testUint32x4Binary(t, archsimd.Uint32x4.ConcatEven, deinterleaveSlice[uint32](128, false)) + testUint64x2Binary(t, archsimd.Uint64x2.ConcatEven, deinterleaveSlice[uint64](128, false)) +} + +func TestConcatOdd(t *testing.T) { + testInt8x16Binary(t, archsimd.Int8x16.ConcatOdd, deinterleaveSlice[int8](128, true)) + testInt16x8Binary(t, archsimd.Int16x8.ConcatOdd, deinterleaveSlice[int16](128, true)) + testInt32x4Binary(t, archsimd.Int32x4.ConcatOdd, deinterleaveSlice[int32](128, true)) + testInt64x2Binary(t, archsimd.Int64x2.ConcatOdd, deinterleaveSlice[int64](128, true)) + testUint8x16Binary(t, archsimd.Uint8x16.ConcatOdd, deinterleaveSlice[uint8](128, true)) + testUint16x8Binary(t, archsimd.Uint16x8.ConcatOdd, deinterleaveSlice[uint16](128, true)) + testUint32x4Binary(t, archsimd.Uint32x4.ConcatOdd, deinterleaveSlice[uint32](128, true)) + testUint64x2Binary(t, archsimd.Uint64x2.ConcatOdd, deinterleaveSlice[uint64](128, true)) +} + +func TestInterleaveEven(t *testing.T) { + testInt8x16Binary(t, archsimd.Int8x16.InterleaveEven, transposeSlice[int8](128, false)) + testInt16x8Binary(t, archsimd.Int16x8.InterleaveEven, transposeSlice[int16](128, false)) + testInt32x4Binary(t, archsimd.Int32x4.InterleaveEven, transposeSlice[int32](128, false)) + testInt64x2Binary(t, archsimd.Int64x2.InterleaveEven, transposeSlice[int64](128, false)) + testUint8x16Binary(t, archsimd.Uint8x16.InterleaveEven, transposeSlice[uint8](128, false)) + testUint16x8Binary(t, archsimd.Uint16x8.InterleaveEven, transposeSlice[uint16](128, false)) + testUint32x4Binary(t, archsimd.Uint32x4.InterleaveEven, transposeSlice[uint32](128, false)) + testUint64x2Binary(t, archsimd.Uint64x2.InterleaveEven, transposeSlice[uint64](128, false)) +} + +func TestInterleaveOdd(t *testing.T) { + testInt8x16Binary(t, archsimd.Int8x16.InterleaveOdd, transposeSlice[int8](128, true)) + testInt16x8Binary(t, archsimd.Int16x8.InterleaveOdd, transposeSlice[int16](128, true)) + testInt32x4Binary(t, archsimd.Int32x4.InterleaveOdd, transposeSlice[int32](128, true)) + testInt64x2Binary(t, archsimd.Int64x2.InterleaveOdd, transposeSlice[int64](128, true)) + testUint8x16Binary(t, archsimd.Uint8x16.InterleaveOdd, transposeSlice[uint8](128, true)) + testUint16x8Binary(t, archsimd.Uint16x8.InterleaveOdd, transposeSlice[uint16](128, true)) + testUint32x4Binary(t, archsimd.Uint32x4.InterleaveOdd, transposeSlice[uint32](128, true)) + testUint64x2Binary(t, archsimd.Uint64x2.InterleaveOdd, transposeSlice[uint64](128, true)) +} + +func TestInterleaveLoARM64(t *testing.T) { + testInt8x16Binary(t, archsimd.Int8x16.InterleaveLo, interleaveSlice[int8](128, false)) + testInt16x8Binary(t, archsimd.Int16x8.InterleaveLo, interleaveSlice[int16](128, false)) + testInt32x4Binary(t, archsimd.Int32x4.InterleaveLo, interleaveSlice[int32](128, false)) + testInt64x2Binary(t, archsimd.Int64x2.InterleaveLo, interleaveSlice[int64](128, false)) + testUint8x16Binary(t, archsimd.Uint8x16.InterleaveLo, interleaveSlice[uint8](128, false)) + testUint16x8Binary(t, archsimd.Uint16x8.InterleaveLo, interleaveSlice[uint16](128, false)) + testUint32x4Binary(t, archsimd.Uint32x4.InterleaveLo, interleaveSlice[uint32](128, false)) + testUint64x2Binary(t, archsimd.Uint64x2.InterleaveLo, interleaveSlice[uint64](128, false)) +} + +func TestInterleaveHiARM64(t *testing.T) { + testInt8x16Binary(t, archsimd.Int8x16.InterleaveHi, interleaveSlice[int8](128, true)) + testInt16x8Binary(t, archsimd.Int16x8.InterleaveHi, interleaveSlice[int16](128, true)) + testInt32x4Binary(t, archsimd.Int32x4.InterleaveHi, interleaveSlice[int32](128, true)) + testInt64x2Binary(t, archsimd.Int64x2.InterleaveHi, interleaveSlice[int64](128, true)) + testUint8x16Binary(t, archsimd.Uint8x16.InterleaveHi, interleaveSlice[uint8](128, true)) + testUint16x8Binary(t, archsimd.Uint16x8.InterleaveHi, interleaveSlice[uint16](128, true)) + testUint32x4Binary(t, archsimd.Uint32x4.InterleaveHi, interleaveSlice[uint32](128, true)) + testUint64x2Binary(t, archsimd.Uint64x2.InterleaveHi, interleaveSlice[uint64](128, true)) +} + +func TestOrNot(t *testing.T) { + testInt8x16Binary(t, archsimd.Int8x16.OrNot, orNotSlice[int8]) + testInt16x8Binary(t, archsimd.Int16x8.OrNot, orNotSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.OrNot, orNotSlice[int32]) + testInt64x2Binary(t, archsimd.Int64x2.OrNot, orNotSlice[int64]) + + testUint8x16Binary(t, archsimd.Uint8x16.OrNot, orNotSlice[uint8]) + testUint16x8Binary(t, archsimd.Uint16x8.OrNot, orNotSlice[uint16]) + testUint32x4Binary(t, archsimd.Uint32x4.OrNot, orNotSlice[uint32]) + testUint64x2Binary(t, archsimd.Uint64x2.OrNot, orNotSlice[uint64]) +} diff --git a/src/simd/archsimd/internal/simd_test/binary_helpers_128_test.go b/src/simd/archsimd/internal/simd_test/binary_helpers_128_test.go index be1aee90abc0341f941b2e5ef74c8f8b2a547fc9..f3bf87e415a424a599e7a7220c56d7052e6aa5b0 100644 --- a/src/simd/archsimd/internal/simd_test/binary_helpers_128_test.go +++ b/src/simd/archsimd/internal/simd_test/binary_helpers_128_test.go @@ -1,6 +1,6 @@ // Code generated by 'tmplgen'; DO NOT EDIT. -//go:build goexperiment.simd && (amd64 || wasm) +//go:build goexperiment.simd && (amd64 || wasm || arm64) // This file contains functions testing binary simd methods. // Each function in this file is specialized for a diff --git a/src/simd/archsimd/internal/simd_test/binary_test.go b/src/simd/archsimd/internal/simd_test/binary_amd64_test.go rename from src/simd/archsimd/internal/simd_test/binary_test.go rename to src/simd/archsimd/internal/simd_test/binary_amd64_test.go index 797a7af8e6d89ae58e14fb076e2a86202b36b225..412f7a356234440ab100b63a8afda16f44ae5e30 100644 --- a/src/simd/archsimd/internal/simd_test/binary_test.go +++ b/src/simd/archsimd/internal/simd_test/binary_amd64_test.go @@ -11,22 +11,10 @@ "simd/archsimd" "testing" ) -func TestAdd(t *testing.T) { - testFloat32x4Binary(t, archsimd.Float32x4.Add, addSlice[float32]) +func TestAddAMD64(t *testing.T) { testFloat32x8Binary(t, archsimd.Float32x8.Add, addSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.Add, addSlice[float64]) testFloat64x4Binary(t, archsimd.Float64x4.Add, addSlice[float64]) - testInt16x8Binary(t, archsimd.Int16x8.Add, addSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Add, addSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.Add, addSlice[int64]) - testInt8x16Binary(t, archsimd.Int8x16.Add, addSlice[int8]) - - testUint32x4Binary(t, archsimd.Uint32x4.Add, addSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.Add, addSlice[uint64]) - testUint16x8Binary(t, archsimd.Uint16x8.Add, addSlice[uint16]) - testUint8x16Binary(t, archsimd.Uint8x16.Add, addSlice[uint8]) - if archsimd.X86.AVX2() { testUint16x16Binary(t, archsimd.Uint16x16.Add, addSlice[uint16]) testUint32x8Binary(t, archsimd.Uint32x8.Add, addSlice[uint32]) @@ -55,17 +43,10 @@ testUint64x8Binary(t, archsimd.Uint64x8.Add, addSlice[uint64]) } } -func TestSub(t *testing.T) { - testFloat32x4Binary(t, archsimd.Float32x4.Sub, subSlice[float32]) +func TestSubAMD64(t *testing.T) { testFloat32x8Binary(t, archsimd.Float32x8.Sub, subSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.Sub, subSlice[float64]) testFloat64x4Binary(t, archsimd.Float64x4.Sub, subSlice[float64]) - testInt32x4Binary(t, archsimd.Int32x4.Sub, subSlice[int32]) - testInt16x8Binary(t, archsimd.Int16x8.Sub, subSlice[int16]) - testInt64x2Binary(t, archsimd.Int64x2.Sub, subSlice[int64]) - testInt8x16Binary(t, archsimd.Int8x16.Sub, subSlice[int8]) - if archsimd.X86.AVX2() { testInt16x16Binary(t, archsimd.Int16x16.Sub, subSlice[int16]) testInt32x8Binary(t, archsimd.Int32x8.Sub, subSlice[int32]) @@ -73,11 +54,6 @@ testInt64x4Binary(t, archsimd.Int64x4.Sub, subSlice[int64]) testInt8x32Binary(t, archsimd.Int8x32.Sub, subSlice[int8]) } - testUint32x4Binary(t, archsimd.Uint32x4.Sub, subSlice[uint32]) - testUint16x8Binary(t, archsimd.Uint16x8.Sub, subSlice[uint16]) - testUint64x2Binary(t, archsimd.Uint64x2.Sub, subSlice[uint64]) - testUint8x16Binary(t, archsimd.Uint8x16.Sub, subSlice[uint8]) - if archsimd.X86.AVX2() { testUint16x16Binary(t, archsimd.Uint16x16.Sub, subSlice[uint16]) testUint32x8Binary(t, archsimd.Uint32x8.Sub, subSlice[uint32]) @@ -99,53 +75,26 @@ testUint64x8Binary(t, archsimd.Uint64x8.Sub, subSlice[uint64]) } } -func TestMax(t *testing.T) { - // testFloat32x4Binary(t, archsimd.Float32x4.Max, maxSlice[float32]) // nan is wrong +func TestMaxAMD64(t *testing.T) { // testFloat32x8Binary(t, archsimd.Float32x8.Max, maxSlice[float32]) // nan is wrong - // testFloat64x2Binary(t, archsimd.Float64x2.Max, maxSlice[float64]) // nan is wrong // testFloat64x4Binary(t, archsimd.Float64x4.Max, maxSlice[float64]) // nan is wrong - testInt16x8Binary(t, archsimd.Int16x8.Max, maxSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Max, maxSlice[int32]) - if archsimd.X86.AVX2() { testInt16x16Binary(t, archsimd.Int16x16.Max, maxSlice[int16]) testInt32x8Binary(t, archsimd.Int32x8.Max, maxSlice[int32]) - } - - if archsimd.X86.AVX512() { - testInt64x2Binary(t, archsimd.Int64x2.Max, maxSlice[int64]) - testInt64x4Binary(t, archsimd.Int64x4.Max, maxSlice[int64]) - } - - testInt8x16Binary(t, archsimd.Int8x16.Max, maxSlice[int8]) - - if archsimd.X86.AVX2() { testInt8x32Binary(t, archsimd.Int8x32.Max, maxSlice[int8]) - } - - testUint16x8Binary(t, archsimd.Uint16x8.Max, maxSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Max, maxSlice[uint32]) - - if archsimd.X86.AVX2() { testUint16x16Binary(t, archsimd.Uint16x16.Max, maxSlice[uint16]) testUint32x8Binary(t, archsimd.Uint32x8.Max, maxSlice[uint32]) - } - - if archsimd.X86.AVX512() { - testUint64x2Binary(t, archsimd.Uint64x2.Max, maxSlice[uint64]) - testUint64x4Binary(t, archsimd.Uint64x4.Max, maxSlice[uint64]) - } - - testUint8x16Binary(t, archsimd.Uint8x16.Max, maxSlice[uint8]) - - if archsimd.X86.AVX2() { testUint8x32Binary(t, archsimd.Uint8x32.Max, maxSlice[uint8]) } if archsimd.X86.AVX512() { // testFloat32x16Binary(t, archsimd.Float32x16.Max, maxSlice[float32]) // nan is wrong // testFloat64x8Binary(t, archsimd.Float64x8.Max, maxSlice[float64]) // nan is wrong + testInt64x2Binary(t, archsimd.Int64x2.Max, maxSlice[int64]) + testInt64x4Binary(t, archsimd.Int64x4.Max, maxSlice[int64]) + testUint64x2Binary(t, archsimd.Uint64x2.Max, maxSlice[uint64]) + testUint64x4Binary(t, archsimd.Uint64x4.Max, maxSlice[uint64]) testInt8x64Binary(t, archsimd.Int8x64.Max, maxSlice[int8]) testInt16x32Binary(t, archsimd.Int16x32.Max, maxSlice[int16]) testInt32x16Binary(t, archsimd.Int32x16.Max, maxSlice[int32]) @@ -157,53 +106,26 @@ testUint64x8Binary(t, archsimd.Uint64x8.Max, maxSlice[uint64]) } } -func TestMin(t *testing.T) { - // testFloat32x4Binary(t, archsimd.Float32x4.Min, minSlice[float32]) // nan is wrong +func TestMinAMD64(t *testing.T) { // testFloat32x8Binary(t, archsimd.Float32x8.Min, minSlice[float32]) // nan is wrong - // testFloat64x2Binary(t, archsimd.Float64x2.Min, minSlice[float64]) // nan is wrong // testFloat64x4Binary(t, archsimd.Float64x4.Min, minSlice[float64]) // nan is wrong - testInt16x8Binary(t, archsimd.Int16x8.Min, minSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Min, minSlice[int32]) - if archsimd.X86.AVX2() { testInt16x16Binary(t, archsimd.Int16x16.Min, minSlice[int16]) testInt32x8Binary(t, archsimd.Int32x8.Min, minSlice[int32]) - } - - if archsimd.X86.AVX512() { - testInt64x2Binary(t, archsimd.Int64x2.Min, minSlice[int64]) - testInt64x4Binary(t, archsimd.Int64x4.Min, minSlice[int64]) - } - - testInt8x16Binary(t, archsimd.Int8x16.Min, minSlice[int8]) - - if archsimd.X86.AVX2() { testInt8x32Binary(t, archsimd.Int8x32.Min, minSlice[int8]) - } - - testUint16x8Binary(t, archsimd.Uint16x8.Min, minSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Min, minSlice[uint32]) - - if archsimd.X86.AVX2() { testUint16x16Binary(t, archsimd.Uint16x16.Min, minSlice[uint16]) testUint32x8Binary(t, archsimd.Uint32x8.Min, minSlice[uint32]) - } - - if archsimd.X86.AVX512() { - testUint64x2Binary(t, archsimd.Uint64x2.Min, minSlice[uint64]) - testUint64x4Binary(t, archsimd.Uint64x4.Min, minSlice[uint64]) - } - - testUint8x16Binary(t, archsimd.Uint8x16.Min, minSlice[uint8]) - - if archsimd.X86.AVX2() { testUint8x32Binary(t, archsimd.Uint8x32.Min, minSlice[uint8]) } if archsimd.X86.AVX512() { // testFloat32x16Binary(t, archsimd.Float32x16.Min, minSlice[float32]) // nan is wrong // testFloat64x8Binary(t, archsimd.Float64x8.Min, minSlice[float64]) // nan is wrong + testInt64x2Binary(t, archsimd.Int64x2.Min, minSlice[int64]) + testInt64x4Binary(t, archsimd.Int64x4.Min, minSlice[int64]) + testUint64x2Binary(t, archsimd.Uint64x2.Min, minSlice[uint64]) + testUint64x4Binary(t, archsimd.Uint64x4.Min, minSlice[uint64]) testInt8x64Binary(t, archsimd.Int8x64.Min, minSlice[int8]) testInt16x32Binary(t, archsimd.Int16x32.Min, minSlice[int16]) testInt32x16Binary(t, archsimd.Int32x16.Min, minSlice[int32]) @@ -215,25 +137,13 @@ testUint64x8Binary(t, archsimd.Uint64x8.Min, minSlice[uint64]) } } -func TestAnd(t *testing.T) { - testInt16x8Binary(t, archsimd.Int16x8.And, andSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.And, andSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.And, andSlice[int64]) - testInt8x16Binary(t, archsimd.Int8x16.And, andSlice[int8]) - +func TestAndAMD64(t *testing.T) { if archsimd.X86.AVX2() { testInt16x16Binary(t, archsimd.Int16x16.And, andSlice[int16]) testInt32x8Binary(t, archsimd.Int32x8.And, andSlice[int32]) testInt64x4Binary(t, archsimd.Int64x4.And, andSlice[int64]) testInt8x32Binary(t, archsimd.Int8x32.And, andSlice[int8]) - } - testUint16x8Binary(t, archsimd.Uint16x8.And, andSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.And, andSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.And, andSlice[uint64]) - testUint8x16Binary(t, archsimd.Uint8x16.And, andSlice[uint8]) - - if archsimd.X86.AVX2() { testUint16x16Binary(t, archsimd.Uint16x16.And, andSlice[uint16]) testUint32x8Binary(t, archsimd.Uint32x8.And, andSlice[uint32]) testUint64x4Binary(t, archsimd.Uint64x4.And, andSlice[uint64]) @@ -241,36 +151,24 @@ testUint8x32Binary(t, archsimd.Uint8x32.And, andSlice[uint8]) } if archsimd.X86.AVX512() { - // testInt8x64Binary(t, archsimd.Int8x64.And, andISlice[int8]) // missing - // testInt16x32Binary(t, archsimd.Int16x32.And, andISlice[int16]) // missing + testInt8x64Binary(t, archsimd.Int8x64.And, andSlice[int8]) + testInt16x32Binary(t, archsimd.Int16x32.And, andSlice[int16]) testInt32x16Binary(t, archsimd.Int32x16.And, andSlice[int32]) testInt64x8Binary(t, archsimd.Int64x8.And, andSlice[int64]) - // testUint8x64Binary(t, archsimd.Uint8x64.And, andISlice[uint8]) // missing - // testUint16x32Binary(t, archsimd.Uint16x32.And, andISlice[uint16]) // missing + testUint8x64Binary(t, archsimd.Uint8x64.And, andSlice[uint8]) + testUint16x32Binary(t, archsimd.Uint16x32.And, andSlice[uint16]) testUint32x16Binary(t, archsimd.Uint32x16.And, andSlice[uint32]) testUint64x8Binary(t, archsimd.Uint64x8.And, andSlice[uint64]) } } -func TestAndNot(t *testing.T) { - testInt16x8Binary(t, archsimd.Int16x8.AndNot, andNotSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.AndNot, andNotSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.AndNot, andNotSlice[int64]) - testInt8x16Binary(t, archsimd.Int8x16.AndNot, andNotSlice[int8]) - +func TestAndNotAMD64(t *testing.T) { if archsimd.X86.AVX2() { testInt16x16Binary(t, archsimd.Int16x16.AndNot, andNotSlice[int16]) testInt32x8Binary(t, archsimd.Int32x8.AndNot, andNotSlice[int32]) testInt64x4Binary(t, archsimd.Int64x4.AndNot, andNotSlice[int64]) testInt8x32Binary(t, archsimd.Int8x32.AndNot, andNotSlice[int8]) - } - testUint8x16Binary(t, archsimd.Uint8x16.AndNot, andNotSlice[uint8]) - testUint16x8Binary(t, archsimd.Uint16x8.AndNot, andNotSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.AndNot, andNotSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.AndNot, andNotSlice[uint64]) - - if archsimd.X86.AVX2() { testUint16x16Binary(t, archsimd.Uint16x16.AndNot, andNotSlice[uint16]) testUint32x8Binary(t, archsimd.Uint32x8.AndNot, andNotSlice[uint32]) testUint64x4Binary(t, archsimd.Uint64x4.AndNot, andNotSlice[uint64]) @@ -289,25 +187,13 @@ testUint64x8Binary(t, archsimd.Uint64x8.AndNot, andNotSlice[uint64]) } } -func TestXor(t *testing.T) { - testInt16x8Binary(t, archsimd.Int16x8.Xor, xorSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Xor, xorSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.Xor, xorSlice[int64]) - testInt8x16Binary(t, archsimd.Int8x16.Xor, xorSlice[int8]) - +func TestXorAMD64(t *testing.T) { if archsimd.X86.AVX2() { testInt16x16Binary(t, archsimd.Int16x16.Xor, xorSlice[int16]) testInt32x8Binary(t, archsimd.Int32x8.Xor, xorSlice[int32]) testInt64x4Binary(t, archsimd.Int64x4.Xor, xorSlice[int64]) testInt8x32Binary(t, archsimd.Int8x32.Xor, xorSlice[int8]) - } - testUint16x8Binary(t, archsimd.Uint16x8.Xor, xorSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Xor, xorSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.Xor, xorSlice[uint64]) - testUint8x16Binary(t, archsimd.Uint8x16.Xor, xorSlice[uint8]) - - if archsimd.X86.AVX2() { testUint16x16Binary(t, archsimd.Uint16x16.Xor, xorSlice[uint16]) testUint32x8Binary(t, archsimd.Uint32x8.Xor, xorSlice[uint32]) testUint64x4Binary(t, archsimd.Uint64x4.Xor, xorSlice[uint64]) @@ -315,36 +201,24 @@ testUint8x32Binary(t, archsimd.Uint8x32.Xor, xorSlice[uint8]) } if archsimd.X86.AVX512() { - // testInt8x64Binary(t, archsimd.Int8x64.Xor, andISlice[int8]) // missing - // testInt16x32Binary(t, archsimd.Int16x32.Xor, andISlice[int16]) // missing + testInt8x64Binary(t, archsimd.Int8x64.Xor, xorSlice[int8]) + testInt16x32Binary(t, archsimd.Int16x32.Xor, xorSlice[int16]) testInt32x16Binary(t, archsimd.Int32x16.Xor, xorSlice[int32]) testInt64x8Binary(t, archsimd.Int64x8.Xor, xorSlice[int64]) - // testUint8x64Binary(t, archsimd.Uint8x64.Xor, andISlice[uint8]) // missing - // testUint16x32Binary(t, archsimd.Uint16x32.Xor, andISlice[uint16]) // missing + testUint8x64Binary(t, archsimd.Uint8x64.Xor, xorSlice[uint8]) + testUint16x32Binary(t, archsimd.Uint16x32.Xor, xorSlice[uint16]) testUint32x16Binary(t, archsimd.Uint32x16.Xor, xorSlice[uint32]) testUint64x8Binary(t, archsimd.Uint64x8.Xor, xorSlice[uint64]) } } -func TestOr(t *testing.T) { - testInt16x8Binary(t, archsimd.Int16x8.Or, orSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Or, orSlice[int32]) - testInt64x2Binary(t, archsimd.Int64x2.Or, orSlice[int64]) - testInt8x16Binary(t, archsimd.Int8x16.Or, orSlice[int8]) - +func TestOrAMD64(t *testing.T) { if archsimd.X86.AVX2() { testInt16x16Binary(t, archsimd.Int16x16.Or, orSlice[int16]) testInt32x8Binary(t, archsimd.Int32x8.Or, orSlice[int32]) testInt64x4Binary(t, archsimd.Int64x4.Or, orSlice[int64]) testInt8x32Binary(t, archsimd.Int8x32.Or, orSlice[int8]) - } - testUint16x8Binary(t, archsimd.Uint16x8.Or, orSlice[uint16]) - testUint32x4Binary(t, archsimd.Uint32x4.Or, orSlice[uint32]) - testUint64x2Binary(t, archsimd.Uint64x2.Or, orSlice[uint64]) - testUint8x16Binary(t, archsimd.Uint8x16.Or, orSlice[uint8]) - - if archsimd.X86.AVX2() { testUint16x16Binary(t, archsimd.Uint16x16.Or, orSlice[uint16]) testUint32x8Binary(t, archsimd.Uint32x8.Or, orSlice[uint32]) testUint64x4Binary(t, archsimd.Uint64x4.Or, orSlice[uint64]) @@ -352,35 +226,27 @@ testUint8x32Binary(t, archsimd.Uint8x32.Or, orSlice[uint8]) } if archsimd.X86.AVX512() { - // testInt8x64Binary(t, archsimd.Int8x64.Or, andISlice[int8]) // missing - // testInt16x32Binary(t, archsimd.Int16x32.Or, andISlice[int16]) // missing + testInt8x64Binary(t, archsimd.Int8x64.Or, orSlice[int8]) + testInt16x32Binary(t, archsimd.Int16x32.Or, orSlice[int16]) testInt32x16Binary(t, archsimd.Int32x16.Or, orSlice[int32]) testInt64x8Binary(t, archsimd.Int64x8.Or, orSlice[int64]) - // testUint8x64Binary(t, archsimd.Uint8x64.Or, andISlice[uint8]) // missing - // testUint16x32Binary(t, archsimd.Uint16x32.Or, andISlice[uint16]) // missing + testUint8x64Binary(t, archsimd.Uint8x64.Or, orSlice[uint8]) + testUint16x32Binary(t, archsimd.Uint16x32.Or, orSlice[uint16]) testUint32x16Binary(t, archsimd.Uint32x16.Or, orSlice[uint32]) testUint64x8Binary(t, archsimd.Uint64x8.Or, orSlice[uint64]) } } -func TestMul(t *testing.T) { - testFloat32x4Binary(t, archsimd.Float32x4.Mul, mulSlice[float32]) +func TestMulAMD64(t *testing.T) { testFloat32x8Binary(t, archsimd.Float32x8.Mul, mulSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.Mul, mulSlice[float64]) testFloat64x4Binary(t, archsimd.Float64x4.Mul, mulSlice[float64]) - testInt16x8Binary(t, archsimd.Int16x8.Mul, mulSlice[int16]) - testInt32x4Binary(t, archsimd.Int32x4.Mul, mulSlice[int32]) - if archsimd.X86.AVX2() { testInt16x16Binary(t, archsimd.Int16x16.Mul, mulSlice[int16]) testInt32x8Binary(t, archsimd.Int32x8.Mul, mulSlice[int32]) testInt8x32Binary(t, archsimd.Int8x32.Mul, mulSlice[int8]) testUint8x32Binary(t, archsimd.Uint8x32.Mul, mulSlice[uint8]) } - - testInt8x16Binary(t, archsimd.Int8x16.Mul, mulSlice[int8]) - testUint8x16Binary(t, archsimd.Uint8x16.Mul, mulSlice[uint8]) // TODO we should be able to do these, there's no difference between signed/unsigned Mul // testUint16x16Binary(t, archsimd.Uint16x16.Mul, mulSlice[uint16]) @@ -413,10 +279,8 @@ // testUint64x8Binary(t, archsimd.Uint64x8.Mul, mulSlice[uint64]) } } -func TestDiv(t *testing.T) { - testFloat32x4Binary(t, archsimd.Float32x4.Div, divSlice[float32]) +func TestDivAMD64(t *testing.T) { testFloat32x8Binary(t, archsimd.Float32x8.Div, divSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.Div, divSlice[float64]) testFloat64x4Binary(t, archsimd.Float64x4.Div, divSlice[float64]) if archsimd.X86.AVX512() { diff --git a/src/simd/archsimd/internal/simd_test/binary_wasm_test.go b/src/simd/archsimd/internal/simd_test/binary_wasm_test.go new file mode 100644 index 0000000000000000000000000000000000000000..cbae26a154745d4042dc7d27d0d3f453b593b85a --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/binary_wasm_test.go @@ -0,0 +1,27 @@ +// 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 && wasm + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +func TestMaxWasm(t *testing.T) { + testInt64x2Binary(t, archsimd.Int64x2.Max, maxSlice[int64]) + testUint64x2Binary(t, archsimd.Uint64x2.Max, maxSlice[uint64]) +} + +func TestMinWasm(t *testing.T) { + testInt64x2Binary(t, archsimd.Int64x2.Min, minSlice[int64]) + testUint64x2Binary(t, archsimd.Uint64x2.Min, minSlice[uint64]) +} + +func TestMulWasm(t *testing.T) { + testInt64x2Binary(t, archsimd.Int64x2.Mul, mulSlice[int64]) + testUint64x2Binary(t, archsimd.Uint64x2.Mul, mulSlice[uint64]) +} diff --git a/src/simd/archsimd/internal/simd_test/compare_128_test.go b/src/simd/archsimd/internal/simd_test/compare_128_test.go index 2fa1dc8ea8b3a2e2ca40aa7c907f6eab0c516635..2d1b05aff7f10e851dfc37f139cd84b55bc6866f 100644 --- a/src/simd/archsimd/internal/simd_test/compare_128_test.go +++ b/src/simd/archsimd/internal/simd_test/compare_128_test.go @@ -2,7 +2,7 @@ // Copyright 2025 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 && wasm +//go:build goexperiment.simd && (amd64 || wasm || arm64) package simd_test @@ -118,3 +118,77 @@ // func(x, y archsimd.Float64x2) archsimd.Mask64x2 { // return x.IsNaN().Or(y.IsNaN()) // }, want64) // } + +func TestMasked(t *testing.T) { + // Test Masked for Int8x16 + forSlicePair(t, int8s, 16, func(x, y []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + mask := archsimd.LoadInt8x16(y).Greater(archsimd.Int8x16{}) // mask: y > 0 + g := make([]int8, 16) + a.Masked(mask).Store(g) + w := make([]int8, 16) + for i := range w { + if y[i] > 0 { + w[i] = x[i] + } + } + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, y=%v", x, y) }) + }) + + // Test Masked for Float64x2 + forSlicePair(t, float64s, 2, func(x, y []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + mask := archsimd.LoadFloat64x2(y).Greater(archsimd.Float64x2{}) // mask: y > 0 + g := make([]float64, 2) + a.Masked(mask).Store(g) + w := make([]float64, 2) + for i := range w { + if y[i] > 0 { + w[i] = x[i] + } + } + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, y=%v", x, y) }) + }) +} + +func TestIfElse(t *testing.T) { + // Test Merge for Int8x16 + forSliceTriple(t, int8s, 16, func(x, y, m []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + b := archsimd.LoadInt8x16(y) + mask := archsimd.LoadInt8x16(m).Greater(archsimd.Int8x16{}) // mask: m > 0 + g := make([]int8, 16) + a.IfElse(mask, b).Store(g) + w := make([]int8, 16) + for i := range w { + if m[i] > 0 { + w[i] = x[i] + } else { + w[i] = y[i] + } + } + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, y=%v, m=%v", x, y, m) }) + }) + + // Test Merge for Float32x4 + forSliceTriple(t, float32s, 4, func(x, y, m []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + b := archsimd.LoadFloat32x4(y) + mask := archsimd.LoadFloat32x4(m).Greater(archsimd.Float32x4{}) // mask: m > 0 + g := make([]float32, 4) + a.IfElse(mask, b).Store(g) + w := make([]float32, 4) + for i := range w { + if m[i] > 0 { + w[i] = x[i] + } else { + w[i] = y[i] + } + } + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, y=%v, m=%v", x, y, m) }) + }) +} diff --git a/src/simd/archsimd/internal/simd_test/compare_helpers_128_test.go b/src/simd/archsimd/internal/simd_test/compare_helpers_128_test.go index 44819baa2dd81dc5047600dd357195bd537da007..c2174400bce773cb9b1cf1808a22b6668fba763c 100644 --- a/src/simd/archsimd/internal/simd_test/compare_helpers_128_test.go +++ b/src/simd/archsimd/internal/simd_test/compare_helpers_128_test.go @@ -1,6 +1,6 @@ // Code generated by 'tmplgen'; DO NOT EDIT. -//go:build goexperiment.simd && (amd64 || wasm) +//go:build goexperiment.simd && (amd64 || wasm || arm64) // This file contains functions testing simd methods that compare two operands. // Each function in this file is specialized for a diff --git a/src/simd/archsimd/internal/simd_test/compare_test.go b/src/simd/archsimd/internal/simd_test/compare_amd64_test.go rename from src/simd/archsimd/internal/simd_test/compare_test.go rename to src/simd/archsimd/internal/simd_test/compare_amd64_test.go index 3ce0d548675b67c7205aea4cdec32f97f7953256..f264be89e1fbc7fba45bb350ac41ebe586c9464f 100644 --- a/src/simd/archsimd/internal/simd_test/compare_test.go +++ b/src/simd/archsimd/internal/simd_test/compare_amd64_test.go @@ -11,40 +11,16 @@ "simd/archsimd" "testing" ) -func TestLess(t *testing.T) { - testFloat32x4Compare(t, archsimd.Float32x4.Less, lessSlice[float32]) +func TestLessAMD64(t *testing.T) { testFloat32x8Compare(t, archsimd.Float32x8.Less, lessSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.Less, lessSlice[float64]) testFloat64x4Compare(t, archsimd.Float64x4.Less, lessSlice[float64]) - testInt16x8Compare(t, archsimd.Int16x8.Less, lessSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.Less, lessSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.Less, lessSlice[int64]) - testInt8x16Compare(t, archsimd.Int8x16.Less, lessSlice[int8]) - if archsimd.X86.AVX2() { testInt16x16Compare(t, archsimd.Int16x16.Less, lessSlice[int16]) testInt32x8Compare(t, archsimd.Int32x8.Less, lessSlice[int32]) testInt64x4Compare(t, archsimd.Int64x4.Less, lessSlice[int64]) testInt8x32Compare(t, archsimd.Int8x32.Less, lessSlice[int8]) - testInt16x16Compare(t, archsimd.Int16x16.Less, lessSlice[int16]) - testInt32x8Compare(t, archsimd.Int32x8.Less, lessSlice[int32]) - testInt64x4Compare(t, archsimd.Int64x4.Less, lessSlice[int64]) - testInt8x32Compare(t, archsimd.Int8x32.Less, lessSlice[int8]) - } - - testInt16x8Compare(t, archsimd.Int16x8.Less, lessSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.Less, lessSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.Less, lessSlice[int64]) - testInt8x16Compare(t, archsimd.Int8x16.Less, lessSlice[int8]) - - testUint16x8Compare(t, archsimd.Uint16x8.Less, lessSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.Less, lessSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.Less, lessSlice[uint64]) - testUint8x16Compare(t, archsimd.Uint8x16.Less, lessSlice[uint8]) - - if archsimd.X86.AVX2() { testUint16x16Compare(t, archsimd.Uint16x16.Less, lessSlice[uint16]) testUint32x8Compare(t, archsimd.Uint32x8.Less, lessSlice[uint32]) testUint64x4Compare(t, archsimd.Uint64x4.Less, lessSlice[uint64]) @@ -74,30 +50,16 @@ testUint64x8Compare(t, archsimd.Uint64x8.Less, lessSlice[uint64]) } } -func TestLessEqual(t *testing.T) { - testFloat32x4Compare(t, archsimd.Float32x4.LessEqual, lessEqualSlice[float32]) +func TestLessEqualAMD64(t *testing.T) { testFloat32x8Compare(t, archsimd.Float32x8.LessEqual, lessEqualSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.LessEqual, lessEqualSlice[float64]) testFloat64x4Compare(t, archsimd.Float64x4.LessEqual, lessEqualSlice[float64]) - testInt16x8Compare(t, archsimd.Int16x8.LessEqual, lessEqualSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.LessEqual, lessEqualSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.LessEqual, lessEqualSlice[int64]) - testInt8x16Compare(t, archsimd.Int8x16.LessEqual, lessEqualSlice[int8]) - if archsimd.X86.AVX2() { testInt16x16Compare(t, archsimd.Int16x16.LessEqual, lessEqualSlice[int16]) testInt32x8Compare(t, archsimd.Int32x8.LessEqual, lessEqualSlice[int32]) testInt64x4Compare(t, archsimd.Int64x4.LessEqual, lessEqualSlice[int64]) testInt8x32Compare(t, archsimd.Int8x32.LessEqual, lessEqualSlice[int8]) - } - testUint16x8Compare(t, archsimd.Uint16x8.LessEqual, lessEqualSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.LessEqual, lessEqualSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.LessEqual, lessEqualSlice[uint64]) - testUint8x16Compare(t, archsimd.Uint8x16.LessEqual, lessEqualSlice[uint8]) - - if archsimd.X86.AVX2() { testUint16x16Compare(t, archsimd.Uint16x16.LessEqual, lessEqualSlice[uint16]) testUint32x8Compare(t, archsimd.Uint32x8.LessEqual, lessEqualSlice[uint32]) testUint64x4Compare(t, archsimd.Uint64x4.LessEqual, lessEqualSlice[uint64]) @@ -118,30 +80,16 @@ testUint64x8Compare(t, archsimd.Uint64x8.LessEqual, lessEqualSlice[uint64]) } } -func TestGreater(t *testing.T) { - testFloat32x4Compare(t, archsimd.Float32x4.Greater, greaterSlice[float32]) +func TestGreaterAMD64(t *testing.T) { testFloat32x8Compare(t, archsimd.Float32x8.Greater, greaterSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.Greater, greaterSlice[float64]) testFloat64x4Compare(t, archsimd.Float64x4.Greater, greaterSlice[float64]) - testInt16x8Compare(t, archsimd.Int16x8.Greater, greaterSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.Greater, greaterSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.Greater, greaterSlice[int64]) - testInt8x16Compare(t, archsimd.Int8x16.Greater, greaterSlice[int8]) - if archsimd.X86.AVX2() { testInt16x16Compare(t, archsimd.Int16x16.Greater, greaterSlice[int16]) testInt32x8Compare(t, archsimd.Int32x8.Greater, greaterSlice[int32]) testInt64x4Compare(t, archsimd.Int64x4.Greater, greaterSlice[int64]) testInt8x32Compare(t, archsimd.Int8x32.Greater, greaterSlice[int8]) - } - testUint16x8Compare(t, archsimd.Uint16x8.Greater, greaterSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.Greater, greaterSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.Greater, greaterSlice[uint64]) - testUint8x16Compare(t, archsimd.Uint8x16.Greater, greaterSlice[uint8]) - - if archsimd.X86.AVX2() { testUint16x16Compare(t, archsimd.Uint16x16.Greater, greaterSlice[uint16]) testUint32x8Compare(t, archsimd.Uint32x8.Greater, greaterSlice[uint32]) testUint64x4Compare(t, archsimd.Uint64x4.Greater, greaterSlice[uint64]) @@ -163,30 +111,16 @@ testUint64x8Compare(t, archsimd.Uint64x8.Greater, greaterSlice[uint64]) } } -func TestGreaterEqual(t *testing.T) { - testFloat32x4Compare(t, archsimd.Float32x4.GreaterEqual, greaterEqualSlice[float32]) +func TestGreaterEqualAMD64(t *testing.T) { testFloat32x8Compare(t, archsimd.Float32x8.GreaterEqual, greaterEqualSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.GreaterEqual, greaterEqualSlice[float64]) testFloat64x4Compare(t, archsimd.Float64x4.GreaterEqual, greaterEqualSlice[float64]) - - testInt16x8Compare(t, archsimd.Int16x8.GreaterEqual, greaterEqualSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.GreaterEqual, greaterEqualSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.GreaterEqual, greaterEqualSlice[int64]) - testInt8x16Compare(t, archsimd.Int8x16.GreaterEqual, greaterEqualSlice[int8]) if archsimd.X86.AVX2() { testInt16x16Compare(t, archsimd.Int16x16.GreaterEqual, greaterEqualSlice[int16]) testInt32x8Compare(t, archsimd.Int32x8.GreaterEqual, greaterEqualSlice[int32]) testInt64x4Compare(t, archsimd.Int64x4.GreaterEqual, greaterEqualSlice[int64]) testInt8x32Compare(t, archsimd.Int8x32.GreaterEqual, greaterEqualSlice[int8]) - } - testUint16x8Compare(t, archsimd.Uint16x8.GreaterEqual, greaterEqualSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.GreaterEqual, greaterEqualSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.GreaterEqual, greaterEqualSlice[uint64]) - testUint8x16Compare(t, archsimd.Uint8x16.GreaterEqual, greaterEqualSlice[uint8]) - - if archsimd.X86.AVX2() { testUint16x16Compare(t, archsimd.Uint16x16.GreaterEqual, greaterEqualSlice[uint16]) testUint32x8Compare(t, archsimd.Uint32x8.GreaterEqual, greaterEqualSlice[uint32]) testUint64x4Compare(t, archsimd.Uint64x4.GreaterEqual, greaterEqualSlice[uint64]) @@ -207,30 +141,16 @@ testUint64x8Compare(t, archsimd.Uint64x8.GreaterEqual, greaterEqualSlice[uint64]) } } -func TestEqual(t *testing.T) { - testFloat32x4Compare(t, archsimd.Float32x4.Equal, equalSlice[float32]) +func TestEqualAMD64(t *testing.T) { testFloat32x8Compare(t, archsimd.Float32x8.Equal, equalSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.Equal, equalSlice[float64]) testFloat64x4Compare(t, archsimd.Float64x4.Equal, equalSlice[float64]) - testInt16x8Compare(t, archsimd.Int16x8.Equal, equalSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.Equal, equalSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.Equal, equalSlice[int64]) - testInt8x16Compare(t, archsimd.Int8x16.Equal, equalSlice[int8]) - if archsimd.X86.AVX2() { testInt16x16Compare(t, archsimd.Int16x16.Equal, equalSlice[int16]) testInt32x8Compare(t, archsimd.Int32x8.Equal, equalSlice[int32]) testInt64x4Compare(t, archsimd.Int64x4.Equal, equalSlice[int64]) testInt8x32Compare(t, archsimd.Int8x32.Equal, equalSlice[int8]) - } - testUint16x8Compare(t, archsimd.Uint16x8.Equal, equalSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.Equal, equalSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.Equal, equalSlice[uint64]) - testUint8x16Compare(t, archsimd.Uint8x16.Equal, equalSlice[uint8]) - - if archsimd.X86.AVX2() { testUint16x16Compare(t, archsimd.Uint16x16.Equal, equalSlice[uint16]) testUint32x8Compare(t, archsimd.Uint32x8.Equal, equalSlice[uint32]) testUint64x4Compare(t, archsimd.Uint64x4.Equal, equalSlice[uint64]) @@ -251,30 +171,16 @@ testUint64x8Compare(t, archsimd.Uint64x8.Equal, equalSlice[uint64]) } } -func TestNotEqual(t *testing.T) { - testFloat32x4Compare(t, archsimd.Float32x4.NotEqual, notEqualSlice[float32]) +func TestNotEqualAMD64(t *testing.T) { testFloat32x8Compare(t, archsimd.Float32x8.NotEqual, notEqualSlice[float32]) - testFloat64x2Compare(t, archsimd.Float64x2.NotEqual, notEqualSlice[float64]) testFloat64x4Compare(t, archsimd.Float64x4.NotEqual, notEqualSlice[float64]) - testInt16x8Compare(t, archsimd.Int16x8.NotEqual, notEqualSlice[int16]) - testInt32x4Compare(t, archsimd.Int32x4.NotEqual, notEqualSlice[int32]) - testInt64x2Compare(t, archsimd.Int64x2.NotEqual, notEqualSlice[int64]) - testInt8x16Compare(t, archsimd.Int8x16.NotEqual, notEqualSlice[int8]) - if archsimd.X86.AVX2() { testInt16x16Compare(t, archsimd.Int16x16.NotEqual, notEqualSlice[int16]) testInt32x8Compare(t, archsimd.Int32x8.NotEqual, notEqualSlice[int32]) testInt64x4Compare(t, archsimd.Int64x4.NotEqual, notEqualSlice[int64]) testInt8x32Compare(t, archsimd.Int8x32.NotEqual, notEqualSlice[int8]) - } - testUint16x8Compare(t, archsimd.Uint16x8.NotEqual, notEqualSlice[uint16]) - testUint32x4Compare(t, archsimd.Uint32x4.NotEqual, notEqualSlice[uint32]) - testUint64x2Compare(t, archsimd.Uint64x2.NotEqual, notEqualSlice[uint64]) - testUint8x16Compare(t, archsimd.Uint8x16.NotEqual, notEqualSlice[uint8]) - - if archsimd.X86.AVX2() { testUint16x16Compare(t, archsimd.Uint16x16.NotEqual, notEqualSlice[uint16]) testUint32x8Compare(t, archsimd.Uint32x8.NotEqual, notEqualSlice[uint32]) testUint64x4Compare(t, archsimd.Uint64x4.NotEqual, notEqualSlice[uint64]) diff --git a/src/simd/archsimd/internal/simd_test/convert_arm64_test.go b/src/simd/archsimd/internal/simd_test/convert_arm64_test.go new file mode 100644 index 0000000000000000000000000000000000000000..d5b8bcd8b28689c6350c2e006a15eb2fafeab84e --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/convert_arm64_test.go @@ -0,0 +1,39 @@ +// 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 && arm64 + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +func TestConvertARM64(t *testing.T) { + testFloat64x2ConvertToFloat32(t, archsimd.Float64x2.ConvertToFloat32, map1[float64](toFloat32)) + testFloat32x4ConvertLoToFloat64x2(t, archsimd.Float32x4.ConvertLo2ToFloat64, map1n[float32](toFloat64, 2)) + + testFloat32x4ConvertToInt32(t, archsimd.Float32x4.ConvertToInt32, map1[float32](floatToInt32_arm64)) + testFloat64x2ConvertToInt64(t, archsimd.Float64x2.ConvertToInt64, map1[float64](floatToInt64_arm64)) + + testFloat32x4ConvertToUint32(t, archsimd.Float32x4.ConvertToUint32, map1[float32](floatToUint32_arm64)) + testFloat64x2ConvertToUint64(t, archsimd.Float64x2.ConvertToUint64, map1[float64](floatToUint64_arm64)) + + testInt32x4ConvertToFloat32(t, archsimd.Int32x4.ConvertToFloat32, map1[int32](toFloat32)) + testInt64x2ConvertToFloat64(t, archsimd.Int64x2.ConvertToFloat64, map1[int64](toFloat64)) + + testUint32x4ConvertToFloat32(t, archsimd.Uint32x4.ConvertToFloat32, map1[uint32](toFloat32)) + testUint64x2ConvertToFloat64(t, archsimd.Uint64x2.ConvertToFloat64, map1[uint64](toFloat64)) +} + +func TestTruncateARM64(t *testing.T) { + testInt16x8ConvertToInt8(t, archsimd.Int16x8.TruncToInt8, map1[int16](toInt8)) + testInt32x4ConvertToInt16(t, archsimd.Int32x4.TruncToInt16, map1[int32](toInt16)) + testInt64x2ConvertToInt32(t, archsimd.Int64x2.TruncToInt32, map1[int64](toInt32)) + + testUint16x8ConvertToUint8(t, archsimd.Uint16x8.TruncToUint8, map1[uint16](toUint8)) + testUint32x4ConvertToUint16(t, archsimd.Uint32x4.TruncToUint16, map1[uint32](toUint16)) + testUint64x2ConvertToUint32(t, archsimd.Uint64x2.TruncToUint32, map1[uint64](toUint32)) +} diff --git a/src/simd/archsimd/internal/simd_test/convert_helpers_128_test.go b/src/simd/archsimd/internal/simd_test/convert_helpers_128_test.go new file mode 100644 index 0000000000000000000000000000000000000000..577afe3e45107660caae51dcdf9591764f6032aa --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/convert_helpers_128_test.go @@ -0,0 +1,1942 @@ +// Code generated by 'tmplgen'; DO NOT EDIT. + +//go:build goexperiment.simd && (amd64 || wasm || arm64) + +// This file contains functions testing conversion simd methods. +// Each function in this file is specialized for a +// particular simd type x. + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +// testInt16x8ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt16x8ConvertToInt8(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int8x16, want func(x []int16) []int8) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + g := make([]int8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt32x4ConvertToInt8(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int8x16, want func(x []int32) []int8) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]int8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt64x2ConvertToInt8(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int8x16, want func(x []int64) []int8) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]int8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x16ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint8x16ConvertToInt8(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int8x16, want func(x []uint8) []int8) { + n := 16 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x16(x) + g := make([]int8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x8ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint16x8ConvertToInt8(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int8x16, want func(x []uint16) []int8) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + g := make([]int8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint32x4ConvertToInt8(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int8x16, want func(x []uint32) []int8) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]int8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint64x2ConvertToInt8(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int8x16, want func(x []uint64) []int8) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]int8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat32x4ConvertToInt8(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int8x16, want func(x []float32) []int8) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]int8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat64x2ConvertToInt8(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int8x16, want func(x []float64) []int8) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]int8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x16ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt8x16ConvertToUint8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint8x16, want func(x []int8) []uint8) { + n := 16 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + g := make([]uint8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x8ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt16x8ConvertToUint8(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint8x16, want func(x []int16) []uint8) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + g := make([]uint8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt32x4ConvertToUint8(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint8x16, want func(x []int32) []uint8) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]uint8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt64x2ConvertToUint8(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint8x16, want func(x []int64) []uint8) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]uint8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x8ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint16x8ConvertToUint8(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint8x16, want func(x []uint16) []uint8) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + g := make([]uint8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint32x4ConvertToUint8(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint8x16, want func(x []uint32) []uint8) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]uint8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint64x2ConvertToUint8(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint8x16, want func(x []uint64) []uint8) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]uint8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat32x4ConvertToUint8(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint8x16, want func(x []float32) []uint8) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]uint8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat64x2ConvertToUint8(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint8x16, want func(x []float64) []uint8) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]uint8, 16) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt32x4ConvertToInt16(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int16x8, want func(x []int32) []int16) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt64x2ConvertToInt16(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int16x8, want func(x []int64) []int16) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x8ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint16x8ConvertToInt16(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int16x8, want func(x []uint16) []int16) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint32x4ConvertToInt16(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int16x8, want func(x []uint32) []int16) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint64x2ConvertToInt16(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int16x8, want func(x []uint64) []int16) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat32x4ConvertToInt16(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int16x8, want func(x []float32) []int16) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat64x2ConvertToInt16(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int16x8, want func(x []float64) []int16) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt16x8ConvertToUint16(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint16x8, want func(x []int16) []uint16) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt32x4ConvertToUint16(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint16x8, want func(x []int32) []uint16) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt64x2ConvertToUint16(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint16x8, want func(x []int64) []uint16) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint32x4ConvertToUint16(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint16x8, want func(x []uint32) []uint16) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint64x2ConvertToUint16(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint16x8, want func(x []uint64) []uint16) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat32x4ConvertToUint16(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint16x8, want func(x []float32) []uint16) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat64x2ConvertToUint16(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint16x8, want func(x []float64) []uint16) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt64x2ConvertToInt32(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int32x4, want func(x []int64) []int32) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint32x4ConvertToInt32(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int32x4, want func(x []uint32) []int32) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint64x2ConvertToInt32(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int32x4, want func(x []uint64) []int32) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat32x4ConvertToInt32(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int32x4, want func(x []float32) []int32) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat64x2ConvertToInt32(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int32x4, want func(x []float64) []int32) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt32x4ConvertToUint32(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint32x4, want func(x []int32) []uint32) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt64x2ConvertToUint32(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint32x4, want func(x []int64) []uint32) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint64x2ConvertToUint32(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint32x4, want func(x []uint64) []uint32) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat32x4ConvertToUint32(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint32x4, want func(x []float32) []uint32) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat64x2ConvertToUint32(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint32x4, want func(x []float64) []uint32) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint64x2ConvertToInt64(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int64x2, want func(x []uint64) []int64) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat64x2ConvertToInt64(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int64x2, want func(x []float64) []int64) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt64x2ConvertToUint64(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint64x2, want func(x []int64) []uint64) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat64x2ConvertToUint64(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint64x2, want func(x []float64) []uint64) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt32x4ConvertToFloat32(t *testing.T, f func(x archsimd.Int32x4) archsimd.Float32x4, want func(x []int32) []float32) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]float32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt64x2ConvertToFloat32(t *testing.T, f func(x archsimd.Int64x2) archsimd.Float32x4, want func(x []int64) []float32) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]float32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint32x4ConvertToFloat32(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Float32x4, want func(x []uint32) []float32) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]float32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint64x2ConvertToFloat32(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Float32x4, want func(x []uint64) []float32) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]float32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testFloat64x2ConvertToFloat32(t *testing.T, f func(x archsimd.Float64x2) archsimd.Float32x4, want func(x []float64) []float32) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]float32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertToFloat64 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testInt64x2ConvertToFloat64(t *testing.T, f func(x archsimd.Int64x2) archsimd.Float64x2, want func(x []int64) []float64) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertToFloat64 tests the simd conversion method f against the expected behavior generated by want. +// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, +// (extended to at least 128 bits, or truncated to at most 512 bits). +func testUint64x2ConvertToFloat64(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Float64x2, want func(x []uint64) []float64) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x16ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt8x16ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int64x2, want func(x []int8) []int64) { + n := 16 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x8ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt16x8ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int64x2, want func(x []int16) []int64) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt32x4ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int64x2, want func(x []int32) []int64) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt64x2ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int64x2, want func(x []int64) []int64) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x16ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint8x16ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int64x2, want func(x []uint8) []int64) { + n := 16 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x16(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x8ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint16x8ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int64x2, want func(x []uint16) []int64) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint32x4ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int64x2, want func(x []uint32) []int64) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint64x2ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int64x2, want func(x []uint64) []int64) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat32x4ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int64x2, want func(x []float32) []int64) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat64x2ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int64x2, want func(x []float64) []int64) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x16ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt8x16ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint64x2, want func(x []int8) []uint64) { + n := 16 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x8ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt16x8ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint64x2, want func(x []int16) []uint64) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt32x4ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint64x2, want func(x []int32) []uint64) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt64x2ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint64x2, want func(x []int64) []uint64) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x16ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint8x16ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint64x2, want func(x []uint8) []uint64) { + n := 16 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x16(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x8ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint16x8ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint64x2, want func(x []uint16) []uint64) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint32x4ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint64x2, want func(x []uint32) []uint64) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint64x2ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint64x2, want func(x []uint64) []uint64) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat32x4ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint64x2, want func(x []float32) []uint64) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat64x2ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint64x2, want func(x []float64) []uint64) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x16ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt8x16ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int32x4, want func(x []int8) []int32) { + n := 16 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x8ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt16x8ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int32x4, want func(x []int16) []int32) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt32x4ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int32x4, want func(x []int32) []int32) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt64x2ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int32x4, want func(x []int64) []int32) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x16ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint8x16ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int32x4, want func(x []uint8) []int32) { + n := 16 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x16(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x8ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint16x8ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int32x4, want func(x []uint16) []int32) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint32x4ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int32x4, want func(x []uint32) []int32) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint64x2ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int32x4, want func(x []uint64) []int32) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x4ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int32x4, want func(x []float32) []int32) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x2ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int32x4, want func(x []float64) []int32) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x16ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt8x16ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint32x4, want func(x []int8) []uint32) { + n := 16 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x8ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt16x8ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint32x4, want func(x []int16) []uint32) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt32x4ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint32x4, want func(x []int32) []uint32) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt64x2ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint32x4, want func(x []int64) []uint32) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x16ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint8x16ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint32x4, want func(x []uint8) []uint32) { + n := 16 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x16(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x8ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint16x8ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint32x4, want func(x []uint16) []uint32) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint32x4ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint32x4, want func(x []uint32) []uint32) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint64x2ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint32x4, want func(x []uint64) []uint32) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x4ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint32x4, want func(x []float32) []uint32) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x2ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint32x4, want func(x []float64) []uint32) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt8x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int16x8, want func(x []int8) []int16) { + n := 16 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt16x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int16x8, want func(x []int16) []int16) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt32x4ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int16x8, want func(x []int32) []int16) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt64x2ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int16x8, want func(x []int64) []int16) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint8x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int16x8, want func(x []uint8) []int16) { + n := 16 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x16(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint16x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int16x8, want func(x []uint16) []int16) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint32x4ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int16x8, want func(x []uint32) []int16) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint64x2ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int16x8, want func(x []uint64) []int16) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat32x4ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int16x8, want func(x []float32) []int16) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x2ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int16x8, want func(x []float64) []int16) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt8x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint16x8, want func(x []int8) []uint16) { + n := 16 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt16x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint16x8, want func(x []int16) []uint16) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt32x4ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint16x8, want func(x []int32) []uint16) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt64x2ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint16x8, want func(x []int64) []uint16) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint8x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint16x8, want func(x []uint8) []uint16) { + n := 16 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x16(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint16x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint16x8, want func(x []uint16) []uint16) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint32x4ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint16x8, want func(x []uint32) []uint16) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint64x2ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint16x8, want func(x []uint64) []uint16) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat32x4ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint16x8, want func(x []float32) []uint16) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x2ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint16x8, want func(x []float64) []uint16) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x16ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt8x16ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int8x16) archsimd.Float64x2, want func(x []int8) []float64) { + n := 16 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x8ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt16x8ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int16x8) archsimd.Float64x2, want func(x []int16) []float64) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x4ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt32x4ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int32x4) archsimd.Float64x2, want func(x []int32) []float64) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x2ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt64x2ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int64x2) archsimd.Float64x2, want func(x []int64) []float64) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x16ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint8x16ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Float64x2, want func(x []uint8) []float64) { + n := 16 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x16(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x8ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint16x8ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Float64x2, want func(x []uint16) []float64) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x4ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint32x4ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Float64x2, want func(x []uint32) []float64) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x2ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint64x2ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Float64x2, want func(x []uint64) []float64) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat32x4ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Float32x4) archsimd.Float64x2, want func(x []float32) []float64) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat64x2ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Float64x2) archsimd.Float64x2, want func(x []float64) []float64) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x4UnaryFlaky tests the simd unary method f against the expected behavior generated by want, +// but using a flakiness parameter because we haven't exactly figured out how simd floating point works +func testFloat32x4UnaryFlaky(t *testing.T, f func(x archsimd.Float32x4) archsimd.Float32x4, want func(x []float32) []float32, flakiness float64) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]float32, n) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2UnaryFlaky tests the simd unary method f against the expected behavior generated by want, +// but using a flakiness parameter because we haven't exactly figured out how simd floating point works +func testFloat64x2UnaryFlaky(t *testing.T, f func(x archsimd.Float64x2) archsimd.Float64x2, want func(x []float64) []float64, flakiness float64) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]float64, n) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} diff --git a/src/simd/archsimd/internal/simd_test/convert_helpers_test.go b/src/simd/archsimd/internal/simd_test/convert_helpers_wider_test.go rename from src/simd/archsimd/internal/simd_test/convert_helpers_test.go rename to src/simd/archsimd/internal/simd_test/convert_helpers_wider_test.go index 067e60a76feb8c2e607ab1433b422a86010d16bb..d3a823e9642f8d180ee69fd47748aea6f4b59417 100644 --- a/src/simd/archsimd/internal/simd_test/convert_helpers_test.go +++ b/src/simd/archsimd/internal/simd_test/convert_helpers_wider_test.go @@ -13,182 +13,6 @@ "simd/archsimd" "testing" ) -// testInt8x16ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt8x16ConvertToInt8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int8x16, want func(x []int8) []int8) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt16x8ConvertToInt8(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int8x16, want func(x []int16) []int8) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt32x4ConvertToInt8(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int8x16, want func(x []int32) []int8) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x2ConvertToInt8(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int8x16, want func(x []int64) []int8) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint8x16ConvertToInt8(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int8x16, want func(x []uint8) []int8) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint16x8ConvertToInt8(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int8x16, want func(x []uint16) []int8) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint32x4ConvertToInt8(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int8x16, want func(x []uint32) []int8) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x2ConvertToInt8(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int8x16, want func(x []uint64) []int8) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat32x4ConvertToInt8(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int8x16, want func(x []float32) []int8) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x2ConvertToInt8(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int8x16, want func(x []float64) []int8) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]int8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x32ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt8x32ConvertToInt8(t *testing.T, f func(x archsimd.Int8x32) archsimd.Int8x32, want func(x []int8) []int8) { - n := 32 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x32(x) - g := make([]int8, 32) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt16x16ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -333,22 +157,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x64ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt8x64ConvertToInt8(t *testing.T, f func(x archsimd.Int8x64) archsimd.Int8x64, want func(x []int8) []int8) { - n := 64 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x64(x) - g := make([]int8, 64) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt16x32ConvertToInt8 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -493,166 +301,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x16ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt8x16ConvertToUint8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint8x16, want func(x []int8) []uint8) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt16x8ConvertToUint8(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint8x16, want func(x []int16) []uint8) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt32x4ConvertToUint8(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint8x16, want func(x []int32) []uint8) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x2ConvertToUint8(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint8x16, want func(x []int64) []uint8) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint8x16ConvertToUint8(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint8x16, want func(x []uint8) []uint8) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint16x8ConvertToUint8(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint8x16, want func(x []uint16) []uint8) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint32x4ConvertToUint8(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint8x16, want func(x []uint32) []uint8) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x2ConvertToUint8(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint8x16, want func(x []uint64) []uint8) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat32x4ConvertToUint8(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint8x16, want func(x []float32) []uint8) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x2ConvertToUint8(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint8x16, want func(x []float64) []uint8) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt8x32ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -717,22 +365,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint8x32ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint8x32ConvertToUint8(t *testing.T, f func(x archsimd.Uint8x32) archsimd.Uint8x32, want func(x []uint8) []uint8) { - n := 32 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x32(x) - g := make([]uint8, 32) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint16x16ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -871,22 +503,6 @@ forSlice(t, int64s, n, func(x []int64) bool { t.Helper() a := archsimd.LoadInt64x8(x) g := make([]uint8, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x64ConvertToUint8 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint8x64ConvertToUint8(t *testing.T, f func(x archsimd.Uint8x64) archsimd.Uint8x64, want func(x []uint8) []uint8) { - n := 64 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x64(x) - g := make([]uint8, 64) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) @@ -989,54 +605,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x8ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt16x8ConvertToInt16(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int16x8, want func(x []int16) []int16) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt32x4ConvertToInt16(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int16x8, want func(x []int32) []int16) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x2ConvertToInt16(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int16x8, want func(x []int64) []int16) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint8x16ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -1047,86 +615,6 @@ forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() a := archsimd.LoadUint8x16(x) g := make([]int16, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint16x8ConvertToInt16(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int16x8, want func(x []uint16) []int16) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint32x4ConvertToInt16(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int16x8, want func(x []uint32) []int16) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x2ConvertToInt16(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int16x8, want func(x []uint64) []int16) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat32x4ConvertToInt16(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int16x8, want func(x []float32) []int16) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]int16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x2ConvertToInt16(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int16x8, want func(x []float64) []int16) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]int16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) @@ -1149,22 +637,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x16ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt16x16ConvertToInt16(t *testing.T, f func(x archsimd.Int16x16) archsimd.Int16x16, want func(x []int16) []int16) { - n := 16 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x16(x) - g := make([]int16, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt32x8ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -1309,22 +781,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x32ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt16x32ConvertToInt16(t *testing.T, f func(x archsimd.Int16x32) archsimd.Int16x32, want func(x []int16) []int16) { - n := 32 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x32(x) - g := make([]int16, 32) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt32x16ConvertToInt16 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -1469,54 +925,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt16x8ConvertToUint16(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint16x8, want func(x []int16) []uint16) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt32x4ConvertToUint16(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint16x8, want func(x []int32) []uint16) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x2ConvertToUint16(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint16x8, want func(x []int64) []uint16) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint8x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -1533,86 +941,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint16x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint16x8ConvertToUint16(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint16x8, want func(x []uint16) []uint16) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint32x4ConvertToUint16(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint16x8, want func(x []uint32) []uint16) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x2ConvertToUint16(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint16x8, want func(x []uint64) []uint16) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat32x4ConvertToUint16(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint16x8, want func(x []float32) []uint16) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x2ConvertToUint16(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint16x8, want func(x []float64) []uint16) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]uint16, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt8x32ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -1687,22 +1015,6 @@ forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() a := archsimd.LoadUint8x32(x) g := make([]uint16, 32) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint16x16ConvertToUint16(t *testing.T, f func(x archsimd.Uint16x16) archsimd.Uint16x16, want func(x []uint16) []uint16) { - n := 16 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x16(x) - g := make([]uint16, 16) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) @@ -1853,22 +1165,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint16x32ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint16x32ConvertToUint16(t *testing.T, f func(x archsimd.Uint16x32) archsimd.Uint16x32, want func(x []uint16) []uint16) { - n := 32 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x32(x) - g := make([]uint16, 32) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint32x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -1965,38 +1261,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt32x4ConvertToInt32(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int32x4, want func(x []int32) []int32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x2ConvertToInt32(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int32x4, want func(x []int64) []int32) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint8x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -2029,70 +1293,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint32x4ConvertToInt32(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int32x4, want func(x []uint32) []int32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x2ConvertToInt32(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int32x4, want func(x []uint64) []int32) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat32x4ConvertToInt32(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int32x4, want func(x []float32) []int32) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x2ConvertToInt32(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int32x4, want func(x []float64) []int32) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt8x32ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -2119,22 +1319,6 @@ forSlice(t, int16s, n, func(x []int16) bool { t.Helper() a := archsimd.LoadInt16x16(x) g := make([]int32, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt32x8ConvertToInt32(t *testing.T, f func(x archsimd.Int32x8) archsimd.Int32x8, want func(x []int32) []int32) { - n := 8 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x8(x) - g := make([]int32, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) @@ -2285,22 +1469,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt32x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt32x16ConvertToInt32(t *testing.T, f func(x archsimd.Int32x16) archsimd.Int32x16, want func(x []int32) []int32) { - n := 16 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x16(x) - g := make([]int32, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt64x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -2445,38 +1613,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt32x4ConvertToUint32(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint32x4, want func(x []int32) []uint32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x2ConvertToUint32(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint32x4, want func(x []int64) []uint32) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint8x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -2509,70 +1645,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint32x4ConvertToUint32(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint32x4, want func(x []uint32) []uint32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x2ConvertToUint32(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint32x4, want func(x []uint64) []uint32) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat32x4ConvertToUint32(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint32x4, want func(x []float32) []uint32) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x2ConvertToUint32(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint32x4, want func(x []float64) []uint32) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt8x32ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -2663,22 +1735,6 @@ forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() a := archsimd.LoadUint16x16(x) g := make([]uint32, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint32x8ConvertToUint32(t *testing.T, f func(x archsimd.Uint32x8) archsimd.Uint32x8, want func(x []uint32) []uint32) { - n := 8 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x8(x) - g := make([]uint32, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) @@ -2829,22 +1885,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint32x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint32x16ConvertToUint32(t *testing.T, f func(x archsimd.Uint32x16) archsimd.Uint32x16, want func(x []uint32) []uint32) { - n := 16 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x16(x) - g := make([]uint32, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint64x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -2941,22 +1981,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x2ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x2ConvertToInt64(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int64x2, want func(x []int64) []int64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint8x16ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3005,22 +2029,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x2ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x2ConvertToInt64(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int64x2, want func(x []uint64) []int64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testFloat32x4ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3037,22 +2045,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testFloat64x2ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x2ConvertToInt64(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int64x2, want func(x []float64) []int64) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt8x32ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3101,22 +2093,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x4ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x4ConvertToInt64(t *testing.T, f func(x archsimd.Int64x4) archsimd.Int64x4, want func(x []int64) []int64) { - n := 4 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x4(x) - g := make([]int64, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint8x32ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3261,22 +2237,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x8ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x8ConvertToInt64(t *testing.T, f func(x archsimd.Int64x8) archsimd.Int64x8, want func(x []int64) []int64) { - n := 8 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x8(x) - g := make([]int64, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint8x64ConvertToInt64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3421,22 +2381,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x2ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x2ConvertToUint64(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint64x2, want func(x []int64) []uint64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint8x16ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3485,22 +2429,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x2ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x2ConvertToUint64(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint64x2, want func(x []uint64) []uint64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testFloat32x4ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3517,22 +2445,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testFloat64x2ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x2ConvertToUint64(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint64x2, want func(x []float64) []uint64) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt8x32ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3645,22 +2557,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x4ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x4ConvertToUint64(t *testing.T, f func(x archsimd.Uint64x4) archsimd.Uint64x4, want func(x []uint64) []uint64) { - n := 4 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x4(x) - g := make([]uint64, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testFloat32x8ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3805,22 +2701,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x8ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x8ConvertToUint64(t *testing.T, f func(x archsimd.Uint64x8) archsimd.Uint64x8, want func(x []uint64) []uint64) { - n := 8 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x8(x) - g := make([]uint64, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testFloat32x16ConvertToUint64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3885,38 +2765,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt32x4ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt32x4ConvertToFloat32(t *testing.T, f func(x archsimd.Int32x4) archsimd.Float32x4, want func(x []int32) []float32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x2ConvertToFloat32(t *testing.T, f func(x archsimd.Int64x2) archsimd.Float32x4, want func(x []int64) []float32) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint8x16ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -3943,70 +2791,6 @@ forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() a := archsimd.LoadUint16x8(x) g := make([]float32, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint32x4ConvertToFloat32(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Float32x4, want func(x []uint32) []float32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x2ConvertToFloat32(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Float32x4, want func(x []uint64) []float32) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat32x4ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat32x4ConvertToFloat32(t *testing.T, f func(x archsimd.Float32x4) archsimd.Float32x4, want func(x []float32) []float32) { - n := 4 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]float32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x2ConvertToFloat32(t *testing.T, f func(x archsimd.Float64x2) archsimd.Float32x4, want func(x []float64) []float32) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]float32, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) @@ -4141,22 +2925,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testFloat32x8ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat32x8ConvertToFloat32(t *testing.T, f func(x archsimd.Float32x8) archsimd.Float32x8, want func(x []float32) []float32) { - n := 8 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x8(x) - g := make([]float32, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testFloat64x4ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -4301,22 +3069,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testFloat32x16ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat32x16ConvertToFloat32(t *testing.T, f func(x archsimd.Float32x16) archsimd.Float32x16, want func(x []float32) []float32) { - n := 16 - t.Helper() - forSlice(t, float32s, n, func(x []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x16(x) - g := make([]float32, 16) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testFloat64x8ConvertToFloat32 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -4381,22 +3133,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x2ConvertToFloat64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testInt64x2ConvertToFloat64(t *testing.T, f func(x archsimd.Int64x2) archsimd.Float64x2, want func(x []int64) []float64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testUint8x16ConvertToFloat64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -4445,22 +3181,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x2ConvertToFloat64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testUint64x2ConvertToFloat64(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Float64x2, want func(x []uint64) []float64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]float64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testFloat32x4ConvertToFloat64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -4471,22 +3191,6 @@ forSlice(t, float32s, n, func(x []float32) bool { t.Helper() a := archsimd.LoadFloat32x4(x) g := make([]float64, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testFloat64x2ConvertToFloat64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x2ConvertToFloat64(t *testing.T, f func(x archsimd.Float64x2) archsimd.Float64x2, want func(x []float64) []float64) { - n := 2 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]float64, 2) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) @@ -4637,22 +3341,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testFloat64x4ConvertToFloat64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x4ConvertToFloat64(t *testing.T, f func(x archsimd.Float64x4) archsimd.Float64x4, want func(x []float64) []float64) { - n := 4 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x4(x) - g := make([]float64, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt8x64ConvertToFloat64 tests the simd conversion method f against the expected behavior generated by want. // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, // (extended to at least 128 bits, or truncated to at most 512 bits). @@ -4797,142 +3485,6 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testFloat64x8ConvertToFloat64 tests the simd conversion method f against the expected behavior generated by want. -// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width, -// (extended to at least 128 bits, or truncated to at most 512 bits). -func testFloat64x8ConvertToFloat64(t *testing.T, f func(x archsimd.Float64x8) archsimd.Float64x8, want func(x []float64) []float64) { - n := 8 - t.Helper() - forSlice(t, float64s, n, func(x []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x8(x) - g := make([]float64, 8) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt8x16ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testInt8x16ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int64x2, want func(x []int8) []int64) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testInt16x8ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int64x2, want func(x []int16) []int64) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testInt32x4ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int64x2, want func(x []int32) []int64) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testInt64x2ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int64x2, want func(x []int64) []int64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testUint8x16ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int64x2, want func(x []uint8) []int64) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testUint16x8ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int64x2, want func(x []uint16) []int64) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testUint32x4ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int64x2, want func(x []uint32) []int64) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testUint64x2ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int64x2, want func(x []uint64) []int64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]int64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - // testInt8x32ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 2 elements. func testInt8x32ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Int8x32) archsimd.Int64x2, want func(x []int8) []int64) { @@ -5053,6 +3605,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x8ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat32x8ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Float32x8) archsimd.Int64x2, want func(x []float32) []int64) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x4ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat64x4ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Float64x4) archsimd.Int64x2, want func(x []float64) []int64) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x64ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 2 elements. func testInt8x64ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Int8x64) archsimd.Int64x2, want func(x []int8) []int64) { @@ -5173,6 +3755,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x16ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat32x16ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Float32x16) archsimd.Int64x2, want func(x []float32) []int64) { + n := 16 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x16(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x8ConvertLoToInt64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat64x8ConvertLoToInt64x2(t *testing.T, f func(x archsimd.Float64x8) archsimd.Int64x2, want func(x []float64) []int64) { + n := 8 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x8(x) + g := make([]int64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x16ConvertLoToInt64x4 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 4 elements. func testInt8x16ConvertLoToInt64x4(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int64x4, want func(x []int8) []int64) { @@ -5293,6 +3905,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x4ConvertLoToInt64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x4ConvertLoToInt64x4(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int64x4, want func(x []float32) []int64) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]int64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToInt64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x2ConvertLoToInt64x4(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int64x4, want func(x []float64) []int64) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]int64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x32ConvertLoToInt64x4 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 4 elements. func testInt8x32ConvertLoToInt64x4(t *testing.T, f func(x archsimd.Int8x32) archsimd.Int64x4, want func(x []int8) []int64) { @@ -5413,6 +4055,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x8ConvertLoToInt64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x8ConvertLoToInt64x4(t *testing.T, f func(x archsimd.Float32x8) archsimd.Int64x4, want func(x []float32) []int64) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]int64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x4ConvertLoToInt64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x4ConvertLoToInt64x4(t *testing.T, f func(x archsimd.Float64x4) archsimd.Int64x4, want func(x []float64) []int64) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]int64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x64ConvertLoToInt64x4 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 4 elements. func testInt8x64ConvertLoToInt64x4(t *testing.T, f func(x archsimd.Int8x64) archsimd.Int64x4, want func(x []int8) []int64) { @@ -5533,120 +4205,30 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x16ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testInt8x16ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint64x2, want func(x []int8) []uint64) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testInt16x8ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint64x2, want func(x []int16) []uint64) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testInt32x4ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint64x2, want func(x []int32) []uint64) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testInt64x2ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint64x2, want func(x []int64) []uint64) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testUint8x16ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint64x2, want func(x []uint8) []uint64) { +// testFloat32x16ConvertLoToInt64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x16ConvertLoToInt64x4(t *testing.T, f func(x archsimd.Float32x16) archsimd.Int64x4, want func(x []float32) []int64) { n := 16 t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { + forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]uint64, 2) + a := archsimd.LoadFloat32x16(x) + g := make([]int64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint16x8ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testUint16x8ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint64x2, want func(x []uint16) []uint64) { +// testFloat64x8ConvertLoToInt64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x8ConvertLoToInt64x4(t *testing.T, f func(x archsimd.Float64x8) archsimd.Int64x4, want func(x []float64) []int64) { n := 8 t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { + forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testUint32x4ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint64x2, want func(x []uint32) []uint64) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]uint64, 2) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 2 elements. -func testUint64x2ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint64x2, want func(x []uint64) []uint64) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint64, 2) + a := archsimd.LoadFloat64x8(x) + g := make([]int64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) @@ -5773,6 +4355,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x8ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat32x8ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Float32x8) archsimd.Uint64x2, want func(x []float32) []uint64) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x4ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat64x4ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Float64x4) archsimd.Uint64x2, want func(x []float64) []uint64) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x64ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 2 elements. func testInt8x64ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Int8x64) archsimd.Uint64x2, want func(x []int8) []uint64) { @@ -5893,6 +4505,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x16ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat32x16ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Float32x16) archsimd.Uint64x2, want func(x []float32) []uint64) { + n := 16 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x16(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x8ConvertLoToUint64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat64x8ConvertLoToUint64x2(t *testing.T, f func(x archsimd.Float64x8) archsimd.Uint64x2, want func(x []float64) []uint64) { + n := 8 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x8(x) + g := make([]uint64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x16ConvertLoToUint64x4 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 4 elements. func testInt8x16ConvertLoToUint64x4(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint64x4, want func(x []int8) []uint64) { @@ -6013,6 +4655,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x4ConvertLoToUint64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x4ConvertLoToUint64x4(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint64x4, want func(x []float32) []uint64) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]uint64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToUint64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x2ConvertLoToUint64x4(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint64x4, want func(x []float64) []uint64) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]uint64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x32ConvertLoToUint64x4 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 4 elements. func testInt8x32ConvertLoToUint64x4(t *testing.T, f func(x archsimd.Int8x32) archsimd.Uint64x4, want func(x []int8) []uint64) { @@ -6133,6 +4805,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x8ConvertLoToUint64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x8ConvertLoToUint64x4(t *testing.T, f func(x archsimd.Float32x8) archsimd.Uint64x4, want func(x []float32) []uint64) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]uint64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x4ConvertLoToUint64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x4ConvertLoToUint64x4(t *testing.T, f func(x archsimd.Float64x4) archsimd.Uint64x4, want func(x []float64) []uint64) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]uint64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x64ConvertLoToUint64x4 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 4 elements. func testInt8x64ConvertLoToUint64x4(t *testing.T, f func(x archsimd.Int8x64) archsimd.Uint64x4, want func(x []int8) []uint64) { @@ -6253,120 +4955,30 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x16ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// testFloat32x16ConvertLoToUint64x4 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 4 elements. -func testInt8x16ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int32x4, want func(x []int8) []int32) { +func testFloat32x16ConvertLoToUint64x4(t *testing.T, f func(x archsimd.Float32x16) archsimd.Uint64x4, want func(x []float32) []uint64) { n := 16 t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { + forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]int32, 4) + a := archsimd.LoadFloat32x16(x) + g := make([]uint64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x8ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// testFloat64x8ConvertLoToUint64x4 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 4 elements. -func testInt16x8ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int32x4, want func(x []int16) []int32) { +func testFloat64x8ConvertLoToUint64x4(t *testing.T, f func(x archsimd.Float64x8) archsimd.Uint64x4, want func(x []float64) []uint64) { n := 8 t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testInt32x4ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int32x4, want func(x []int32) []int32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { + forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testInt64x2ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int32x4, want func(x []int64) []int32) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testUint8x16ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int32x4, want func(x []uint8) []int32) { - n := 16 - t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint16x8ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testUint16x8ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int32x4, want func(x []uint16) []int32) { - n := 8 - t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testUint32x4ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int32x4, want func(x []uint32) []int32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]int32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testUint64x2ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int32x4, want func(x []uint64) []int32) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]int32, 4) + a := archsimd.LoadFloat64x8(x) + g := make([]uint64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) @@ -6486,6 +5098,36 @@ t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() a := archsimd.LoadUint64x4(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x8ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x8ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Float32x8) archsimd.Int32x4, want func(x []float32) []int32) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x4ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x4ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Float64x4) archsimd.Int32x4, want func(x []float64) []int32) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) g := make([]int32, 4) f(a).Store(g) w := want(x) @@ -6613,6 +5255,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x16ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x16ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Float32x16) archsimd.Int32x4, want func(x []float32) []int32) { + n := 16 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x16(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x8ConvertLoToInt32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x8ConvertLoToInt32x4(t *testing.T, f func(x archsimd.Float64x8) archsimd.Int32x4, want func(x []float64) []int32) { + n := 8 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x8(x) + g := make([]int32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x16ConvertLoToInt32x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. func testInt8x16ConvertLoToInt32x8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int32x8, want func(x []int8) []int32) { @@ -6733,6 +5405,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x4ConvertLoToInt32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat32x4ConvertLoToInt32x8(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int32x8, want func(x []float32) []int32) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]int32, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToInt32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x2ConvertLoToInt32x8(t *testing.T, f func(x archsimd.Float64x2) archsimd.Int32x8, want func(x []float64) []int32) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]int32, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x32ConvertLoToInt32x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. func testInt8x32ConvertLoToInt32x8(t *testing.T, f func(x archsimd.Int8x32) archsimd.Int32x8, want func(x []int8) []int32) { @@ -6853,6 +5555,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x8ConvertLoToInt32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat32x8ConvertLoToInt32x8(t *testing.T, f func(x archsimd.Float32x8) archsimd.Int32x8, want func(x []float32) []int32) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]int32, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x4ConvertLoToInt32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x4ConvertLoToInt32x8(t *testing.T, f func(x archsimd.Float64x4) archsimd.Int32x8, want func(x []float64) []int32) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]int32, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x64ConvertLoToInt32x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. func testInt8x64ConvertLoToInt32x8(t *testing.T, f func(x archsimd.Int8x64) archsimd.Int32x8, want func(x []int8) []int32) { @@ -6973,120 +5705,30 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x16ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testInt8x16ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint32x4, want func(x []int8) []uint32) { - n := 16 - t.Helper() - forSlice(t, int8s, n, func(x []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt16x8ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testInt16x8ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint32x4, want func(x []int16) []uint32) { - n := 8 - t.Helper() - forSlice(t, int16s, n, func(x []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt32x4ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testInt32x4ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint32x4, want func(x []int32) []uint32) { - n := 4 - t.Helper() - forSlice(t, int32s, n, func(x []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testInt64x2ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testInt64x2ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint32x4, want func(x []int64) []uint32) { - n := 2 - t.Helper() - forSlice(t, int64s, n, func(x []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint8x16ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testUint8x16ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint32x4, want func(x []uint8) []uint32) { +// testFloat32x16ConvertLoToInt32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat32x16ConvertLoToInt32x8(t *testing.T, f func(x archsimd.Float32x16) archsimd.Int32x8, want func(x []float32) []int32) { n := 16 t.Helper() - forSlice(t, uint8s, n, func(x []uint8) bool { + forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := archsimd.LoadUint8x16(x) - g := make([]uint32, 4) + a := archsimd.LoadFloat32x16(x) + g := make([]int32, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint16x8ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testUint16x8ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint32x4, want func(x []uint16) []uint32) { +// testFloat64x8ConvertLoToInt32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x8ConvertLoToInt32x8(t *testing.T, f func(x archsimd.Float64x8) archsimd.Int32x8, want func(x []float64) []int32) { n := 8 t.Helper() - forSlice(t, uint16s, n, func(x []uint16) bool { + forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := archsimd.LoadUint16x8(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint32x4ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testUint32x4ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint32x4, want func(x []uint32) []uint32) { - n := 4 - t.Helper() - forSlice(t, uint32s, n, func(x []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - g := make([]uint32, 4) - f(a).Store(g) - w := want(x) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) - }) -} - -// testUint64x2ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 4 elements. -func testUint64x2ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint32x4, want func(x []uint64) []uint32) { - n := 2 - t.Helper() - forSlice(t, uint64s, n, func(x []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - g := make([]uint32, 4) + a := archsimd.LoadFloat64x8(x) + g := make([]int32, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) @@ -7213,6 +5855,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x8ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x8ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Float32x8) archsimd.Uint32x4, want func(x []float32) []uint32) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x4ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x4ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Float64x4) archsimd.Uint32x4, want func(x []float64) []uint32) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x64ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 4 elements. func testInt8x64ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Int8x64) archsimd.Uint32x4, want func(x []int8) []uint32) { @@ -7333,6 +6005,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x16ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x16ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Float32x16) archsimd.Uint32x4, want func(x []float32) []uint32) { + n := 16 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x16(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x8ConvertLoToUint32x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x8ConvertLoToUint32x4(t *testing.T, f func(x archsimd.Float64x8) archsimd.Uint32x4, want func(x []float64) []uint32) { + n := 8 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x8(x) + g := make([]uint32, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x16ConvertLoToUint32x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. func testInt8x16ConvertLoToUint32x8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint32x8, want func(x []int8) []uint32) { @@ -7453,6 +6155,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x4ConvertLoToUint32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat32x4ConvertLoToUint32x8(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint32x8, want func(x []float32) []uint32) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]uint32, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToUint32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x2ConvertLoToUint32x8(t *testing.T, f func(x archsimd.Float64x2) archsimd.Uint32x8, want func(x []float64) []uint32) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]uint32, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x32ConvertLoToUint32x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. func testInt8x32ConvertLoToUint32x8(t *testing.T, f func(x archsimd.Int8x32) archsimd.Uint32x8, want func(x []int8) []uint32) { @@ -7573,6 +6305,36 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } +// testFloat32x8ConvertLoToUint32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat32x8ConvertLoToUint32x8(t *testing.T, f func(x archsimd.Float32x8) archsimd.Uint32x8, want func(x []float32) []uint32) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]uint32, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x4ConvertLoToUint32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x4ConvertLoToUint32x8(t *testing.T, f func(x archsimd.Float64x4) archsimd.Uint32x8, want func(x []float64) []uint32) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]uint32, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + // testInt8x64ConvertLoToUint32x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. func testInt8x64ConvertLoToUint32x8(t *testing.T, f func(x archsimd.Int8x64) archsimd.Uint32x8, want func(x []int8) []uint32) { @@ -7693,14 +6455,59 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testFloat32x16ConvertLoToUint32x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt8x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int16x8, want func(x []int8) []int16) { +func testFloat32x16ConvertLoToUint32x8(t *testing.T, f func(x archsimd.Float32x16) archsimd.Uint32x8, want func(x []float32) []uint32) { n := 16 t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x16(x) + g := make([]uint32, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x8ConvertLoToUint32x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x8ConvertLoToUint32x8(t *testing.T, f func(x archsimd.Float64x8) archsimd.Uint32x8, want func(x []float64) []uint32) { + n := 8 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x8(x) + g := make([]uint32, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x32ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt8x32ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int8x32) archsimd.Int16x8, want func(x []int8) []int16) { + n := 32 + t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() - a := archsimd.LoadInt8x16(x) + a := archsimd.LoadInt8x32(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt16x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int16x16) archsimd.Int16x8, want func(x []int16) []int16) { + n := 16 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x16(x) g := make([]int16, 8) f(a).Store(g) w := want(x) @@ -7708,14 +6515,149 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testInt32x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt16x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int16x8, want func(x []int16) []int16) { +func testInt32x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int32x8) archsimd.Int16x8, want func(x []int32) []int16) { n := 8 t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x8(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x4ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt64x4ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int64x4) archsimd.Int16x8, want func(x []int64) []int16) { + n := 4 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x4(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x32ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint8x32ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint8x32) archsimd.Int16x8, want func(x []uint8) []int16) { + n := 32 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x32(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint16x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint16x16) archsimd.Int16x8, want func(x []uint16) []int16) { + n := 16 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x16(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint32x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint32x8) archsimd.Int16x8, want func(x []uint32) []int16) { + n := 8 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x8(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x4ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testUint64x4ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint64x4) archsimd.Int16x8, want func(x []uint64) []int16) { + n := 4 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x4(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat32x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Float32x8) archsimd.Int16x8, want func(x []float32) []int16) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x4ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x4ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Float64x4) archsimd.Int16x8, want func(x []float64) []int16) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x64ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt8x64ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int8x64) archsimd.Int16x8, want func(x []int8) []int16) { + n := 64 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x64(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x32ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt16x32ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int16x32) archsimd.Int16x8, want func(x []int16) []int16) { + n := 32 + t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := archsimd.LoadInt16x8(x) + a := archsimd.LoadInt16x32(x) g := make([]int16, 8) f(a).Store(g) w := want(x) @@ -7723,14 +6665,14 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt32x4ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testInt32x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt32x4ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int16x8, want func(x []int32) []int16) { - n := 4 +func testInt32x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int32x16) archsimd.Int16x8, want func(x []int32) []int16) { + n := 16 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := archsimd.LoadInt32x4(x) + a := archsimd.LoadInt32x16(x) g := make([]int16, 8) f(a).Store(g) w := want(x) @@ -7738,14 +6680,14 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x2ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testInt64x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt64x2ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int64x2) archsimd.Int16x8, want func(x []int64) []int16) { - n := 2 +func testInt64x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int64x8) archsimd.Int16x8, want func(x []int64) []int16) { + n := 8 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() - a := archsimd.LoadInt64x2(x) + a := archsimd.LoadInt64x8(x) g := make([]int16, 8) f(a).Store(g) w := want(x) @@ -7753,14 +6695,14 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint8x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint8x64ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint8x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int16x8, want func(x []uint8) []int16) { - n := 16 +func testUint8x64ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint8x64) archsimd.Int16x8, want func(x []uint8) []int16) { + n := 64 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() - a := archsimd.LoadUint8x16(x) + a := archsimd.LoadUint8x64(x) g := make([]int16, 8) f(a).Store(g) w := want(x) @@ -7768,14 +6710,14 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint16x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint16x32ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint16x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int16x8, want func(x []uint16) []int16) { - n := 8 +func testUint16x32ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint16x32) archsimd.Int16x8, want func(x []uint16) []int16) { + n := 32 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := archsimd.LoadUint16x8(x) + a := archsimd.LoadUint16x32(x) g := make([]int16, 8) f(a).Store(g) w := want(x) @@ -7783,14 +6725,14 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint32x4ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint32x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint32x4ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int16x8, want func(x []uint32) []int16) { - n := 4 +func testUint32x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint32x16) archsimd.Int16x8, want func(x []uint32) []int16) { + n := 16 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := archsimd.LoadUint32x4(x) + a := archsimd.LoadUint32x16(x) g := make([]int16, 8) f(a).Store(g) w := want(x) @@ -7798,14 +6740,44 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x2ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint64x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint64x2ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Int16x8, want func(x []uint64) []int16) { - n := 2 +func testUint64x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint64x8) archsimd.Int16x8, want func(x []uint64) []int16) { + n := 8 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() - a := archsimd.LoadUint64x2(x) + a := archsimd.LoadUint64x8(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat32x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Float32x16) archsimd.Int16x8, want func(x []float32) []int16) { + n := 16 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x16(x) + g := make([]int16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Float64x8) archsimd.Int16x8, want func(x []float64) []int16) { + n := 8 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x8(x) g := make([]int16, 8) f(a).Store(g) w := want(x) @@ -7813,633 +6785,1053 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x32ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testInt8x32ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt8x32ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int8x32) archsimd.Int16x8, want func(x []int8) []int16) { +func testInt8x32ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int8x32) archsimd.Uint16x8, want func(x []int8) []uint16) { n := 32 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() a := archsimd.LoadInt8x32(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testInt16x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt16x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int16x16) archsimd.Int16x8, want func(x []int16) []int16) { +func testInt16x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int16x16) archsimd.Uint16x8, want func(x []int16) []uint16) { n := 16 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() a := archsimd.LoadInt16x16(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt32x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testInt32x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt32x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int32x8) archsimd.Int16x8, want func(x []int32) []int16) { +func testInt32x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int32x8) archsimd.Uint16x8, want func(x []int32) []uint16) { n := 8 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() a := archsimd.LoadInt32x8(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x4ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testInt64x4ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt64x4ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int64x4) archsimd.Int16x8, want func(x []int64) []int16) { +func testInt64x4ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int64x4) archsimd.Uint16x8, want func(x []int64) []uint16) { n := 4 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() a := archsimd.LoadInt64x4(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint8x32ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint8x32ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint8x32ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint8x32) archsimd.Int16x8, want func(x []uint8) []int16) { +func testUint8x32ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint8x32) archsimd.Uint16x8, want func(x []uint8) []uint16) { n := 32 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() a := archsimd.LoadUint8x32(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint16x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint16x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint16x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint16x16) archsimd.Int16x8, want func(x []uint16) []int16) { +func testUint16x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint16x16) archsimd.Uint16x8, want func(x []uint16) []uint16) { n := 16 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() a := archsimd.LoadUint16x16(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint32x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint32x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint32x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint32x8) archsimd.Int16x8, want func(x []uint32) []int16) { +func testUint32x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint32x8) archsimd.Uint16x8, want func(x []uint32) []uint16) { n := 8 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() a := archsimd.LoadUint32x8(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x4ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint64x4ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint64x4ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint64x4) archsimd.Int16x8, want func(x []uint64) []int16) { +func testUint64x4ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint64x4) archsimd.Uint16x8, want func(x []uint64) []uint16) { n := 4 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() a := archsimd.LoadUint64x4(x) - g := make([]int16, 8) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat32x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Float32x8) archsimd.Uint16x8, want func(x []float32) []uint16) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x64ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testFloat64x4ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt8x64ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int8x64) archsimd.Int16x8, want func(x []int8) []int16) { +func testFloat64x4ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Float64x4) archsimd.Uint16x8, want func(x []float64) []uint16) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x64ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testInt8x64ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int8x64) archsimd.Uint16x8, want func(x []int8) []uint16) { n := 64 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() a := archsimd.LoadInt8x64(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x32ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testInt16x32ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt16x32ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int16x32) archsimd.Int16x8, want func(x []int16) []int16) { +func testInt16x32ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int16x32) archsimd.Uint16x8, want func(x []int16) []uint16) { n := 32 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() a := archsimd.LoadInt16x32(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt32x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testInt32x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt32x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int32x16) archsimd.Int16x8, want func(x []int32) []int16) { +func testInt32x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int32x16) archsimd.Uint16x8, want func(x []int32) []uint16) { n := 16 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() a := archsimd.LoadInt32x16(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testInt64x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt64x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Int64x8) archsimd.Int16x8, want func(x []int64) []int16) { +func testInt64x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int64x8) archsimd.Uint16x8, want func(x []int64) []uint16) { n := 8 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() a := archsimd.LoadInt64x8(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint8x64ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint8x64ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint8x64ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint8x64) archsimd.Int16x8, want func(x []uint8) []int16) { +func testUint8x64ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint8x64) archsimd.Uint16x8, want func(x []uint8) []uint16) { n := 64 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() a := archsimd.LoadUint8x64(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint16x32ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint16x32ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint16x32ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint16x32) archsimd.Int16x8, want func(x []uint16) []int16) { +func testUint16x32ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint16x32) archsimd.Uint16x8, want func(x []uint16) []uint16) { n := 32 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() a := archsimd.LoadUint16x32(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint32x16ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint32x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint32x16ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint32x16) archsimd.Int16x8, want func(x []uint32) []int16) { +func testUint32x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint32x16) archsimd.Uint16x8, want func(x []uint32) []uint16) { n := 16 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() a := archsimd.LoadUint32x16(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x8ConvertLoToInt16x8 tests the simd conversion method f against the expected behavior generated by want. +// testUint64x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testUint64x8ConvertLoToInt16x8(t *testing.T, f func(x archsimd.Uint64x8) archsimd.Int16x8, want func(x []uint64) []int16) { +func testUint64x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint64x8) archsimd.Uint16x8, want func(x []uint64) []uint16) { n := 8 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() a := archsimd.LoadUint64x8(x) - g := make([]int16, 8) + g := make([]uint16, 8) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// testFloat32x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. // This converts only the low 8 elements. -func testInt8x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint16x8, want func(x []int8) []uint16) { +func testFloat32x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Float32x16) archsimd.Uint16x8, want func(x []float32) []uint16) { + n := 16 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x16(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 8 elements. +func testFloat64x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Float64x8) archsimd.Uint16x8, want func(x []float64) []uint16) { + n := 8 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x8(x) + g := make([]uint16, 8) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x32ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt8x32ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int8x32) archsimd.Float64x2, want func(x []int8) []float64) { + n := 32 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x32(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x16ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt16x16ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int16x16) archsimd.Float64x2, want func(x []int16) []float64) { + n := 16 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x16(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x8ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt32x8ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int32x8) archsimd.Float64x2, want func(x []int32) []float64) { + n := 8 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x8(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x4ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt64x4ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int64x4) archsimd.Float64x2, want func(x []int64) []float64) { + n := 4 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x4(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x32ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint8x32ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint8x32) archsimd.Float64x2, want func(x []uint8) []float64) { + n := 32 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x32(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x16ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint16x16ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint16x16) archsimd.Float64x2, want func(x []uint16) []float64) { + n := 16 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x16(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x8ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint32x8ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint32x8) archsimd.Float64x2, want func(x []uint32) []float64) { + n := 8 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x8(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x4ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint64x4ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint64x4) archsimd.Float64x2, want func(x []uint64) []float64) { + n := 4 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x4(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x8ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat32x8ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Float32x8) archsimd.Float64x2, want func(x []float32) []float64) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x4ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat64x4ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Float64x4) archsimd.Float64x2, want func(x []float64) []float64) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x64ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt8x64ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int8x64) archsimd.Float64x2, want func(x []int8) []float64) { + n := 64 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + a := archsimd.LoadInt8x64(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt16x32ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt16x32ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int16x32) archsimd.Float64x2, want func(x []int16) []float64) { + n := 32 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + a := archsimd.LoadInt16x32(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt32x16ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt32x16ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int32x16) archsimd.Float64x2, want func(x []int32) []float64) { + n := 16 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + a := archsimd.LoadInt32x16(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt64x8ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testInt64x8ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Int64x8) archsimd.Float64x2, want func(x []int64) []float64) { + n := 8 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + a := archsimd.LoadInt64x8(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint8x64ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint8x64ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint8x64) archsimd.Float64x2, want func(x []uint8) []float64) { + n := 64 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x64(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint16x32ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint16x32ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint16x32) archsimd.Float64x2, want func(x []uint16) []float64) { + n := 32 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x32(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint32x16ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint32x16ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint32x16) archsimd.Float64x2, want func(x []uint32) []float64) { + n := 16 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x16(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testUint64x8ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testUint64x8ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Uint64x8) archsimd.Float64x2, want func(x []uint64) []float64) { + n := 8 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x8(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x16ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat32x16ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Float32x16) archsimd.Float64x2, want func(x []float32) []float64) { + n := 16 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x16(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x8ConvertLoToFloat64x2 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 2 elements. +func testFloat64x8ConvertLoToFloat64x2(t *testing.T, f func(x archsimd.Float64x8) archsimd.Float64x2, want func(x []float64) []float64) { + n := 8 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x8(x) + g := make([]float64, 2) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x16ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt8x16ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int8x16) archsimd.Float64x4, want func(x []int8) []float64) { n := 16 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() a := archsimd.LoadInt8x16(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt16x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint16x8, want func(x []int16) []uint16) { +// testInt16x8ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt16x8ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int16x8) archsimd.Float64x4, want func(x []int16) []float64) { n := 8 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() a := archsimd.LoadInt16x8(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt32x4ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt32x4ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint16x8, want func(x []int32) []uint16) { +// testInt32x4ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt32x4ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int32x4) archsimd.Float64x4, want func(x []int32) []float64) { n := 4 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() a := archsimd.LoadInt32x4(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x2ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt64x2ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int64x2) archsimd.Uint16x8, want func(x []int64) []uint16) { +// testInt64x2ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt64x2ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int64x2) archsimd.Float64x4, want func(x []int64) []float64) { n := 2 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() a := archsimd.LoadInt64x2(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint8x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint8x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint16x8, want func(x []uint8) []uint16) { +// testUint8x16ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint8x16ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Float64x4, want func(x []uint8) []float64) { n := 16 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() a := archsimd.LoadUint8x16(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint16x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint16x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint16x8, want func(x []uint16) []uint16) { +// testUint16x8ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint16x8ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Float64x4, want func(x []uint16) []float64) { n := 8 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() a := archsimd.LoadUint16x8(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint32x4ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint32x4ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint16x8, want func(x []uint32) []uint16) { +// testUint32x4ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint32x4ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Float64x4, want func(x []uint32) []float64) { n := 4 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() a := archsimd.LoadUint32x4(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x2ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint64x2ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Uint16x8, want func(x []uint64) []uint16) { +// testUint64x2ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint64x2ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint64x2) archsimd.Float64x4, want func(x []uint64) []float64) { n := 2 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() a := archsimd.LoadUint64x2(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x32ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt8x32ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int8x32) archsimd.Uint16x8, want func(x []int8) []uint16) { +// testFloat32x4ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x4ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Float32x4) archsimd.Float64x4, want func(x []float32) []float64) { + n := 4 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + g := make([]float64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat64x2ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x2ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Float64x2) archsimd.Float64x4, want func(x []float64) []float64) { + n := 2 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + g := make([]float64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x32ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt8x32ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int8x32) archsimd.Float64x4, want func(x []int8) []float64) { n := 32 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() a := archsimd.LoadInt8x32(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt16x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int16x16) archsimd.Uint16x8, want func(x []int16) []uint16) { +// testInt16x16ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt16x16ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int16x16) archsimd.Float64x4, want func(x []int16) []float64) { n := 16 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() a := archsimd.LoadInt16x16(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt32x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt32x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int32x8) archsimd.Uint16x8, want func(x []int32) []uint16) { +// testInt32x8ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt32x8ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int32x8) archsimd.Float64x4, want func(x []int32) []float64) { n := 8 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() a := archsimd.LoadInt32x8(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x4ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt64x4ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int64x4) archsimd.Uint16x8, want func(x []int64) []uint16) { +// testInt64x4ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt64x4ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int64x4) archsimd.Float64x4, want func(x []int64) []float64) { n := 4 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() a := archsimd.LoadInt64x4(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint8x32ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint8x32ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint8x32) archsimd.Uint16x8, want func(x []uint8) []uint16) { +// testUint8x32ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint8x32ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint8x32) archsimd.Float64x4, want func(x []uint8) []float64) { n := 32 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() a := archsimd.LoadUint8x32(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint16x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint16x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint16x16) archsimd.Uint16x8, want func(x []uint16) []uint16) { +// testUint16x16ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint16x16ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint16x16) archsimd.Float64x4, want func(x []uint16) []float64) { n := 16 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() a := archsimd.LoadUint16x16(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint32x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint32x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint32x8) archsimd.Uint16x8, want func(x []uint32) []uint16) { +// testUint32x8ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint32x8ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint32x8) archsimd.Float64x4, want func(x []uint32) []float64) { n := 8 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() a := archsimd.LoadUint32x8(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x4ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint64x4ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint64x4) archsimd.Uint16x8, want func(x []uint64) []uint16) { +// testUint64x4ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint64x4ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint64x4) archsimd.Float64x4, want func(x []uint64) []float64) { n := 4 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() a := archsimd.LoadUint64x4(x) - g := make([]uint16, 8) + g := make([]float64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testFloat32x8ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x8ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Float32x8) archsimd.Float64x4, want func(x []float32) []float64) { + n := 8 + t.Helper() + forSlice(t, float32s, n, func(x []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x8(x) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt8x64ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt8x64ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int8x64) archsimd.Uint16x8, want func(x []int8) []uint16) { +// testFloat64x4ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x4ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Float64x4) archsimd.Float64x4, want func(x []float64) []float64) { + n := 4 + t.Helper() + forSlice(t, float64s, n, func(x []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x4(x) + g := make([]float64, 4) + f(a).Store(g) + w := want(x) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) + }) +} + +// testInt8x64ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt8x64ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int8x64) archsimd.Float64x4, want func(x []int8) []float64) { n := 64 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() a := archsimd.LoadInt8x64(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt16x32ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt16x32ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int16x32) archsimd.Uint16x8, want func(x []int16) []uint16) { +// testInt16x32ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt16x32ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int16x32) archsimd.Float64x4, want func(x []int16) []float64) { n := 32 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() a := archsimd.LoadInt16x32(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt32x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt32x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int32x16) archsimd.Uint16x8, want func(x []int32) []uint16) { +// testInt32x16ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt32x16ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int32x16) archsimd.Float64x4, want func(x []int32) []float64) { n := 16 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() a := archsimd.LoadInt32x16(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testInt64x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testInt64x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Int64x8) archsimd.Uint16x8, want func(x []int64) []uint16) { +// testInt64x8ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testInt64x8ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Int64x8) archsimd.Float64x4, want func(x []int64) []float64) { n := 8 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() a := archsimd.LoadInt64x8(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint8x64ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint8x64ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint8x64) archsimd.Uint16x8, want func(x []uint8) []uint16) { +// testUint8x64ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint8x64ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint8x64) archsimd.Float64x4, want func(x []uint8) []float64) { n := 64 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() a := archsimd.LoadUint8x64(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint16x32ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint16x32ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint16x32) archsimd.Uint16x8, want func(x []uint16) []uint16) { +// testUint16x32ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint16x32ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint16x32) archsimd.Float64x4, want func(x []uint16) []float64) { n := 32 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() a := archsimd.LoadUint16x32(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint32x16ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint32x16ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint32x16) archsimd.Uint16x8, want func(x []uint32) []uint16) { +// testUint32x16ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint32x16ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint32x16) archsimd.Float64x4, want func(x []uint32) []float64) { n := 16 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() a := archsimd.LoadUint32x16(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testUint64x8ConvertLoToUint16x8 tests the simd conversion method f against the expected behavior generated by want. -// This converts only the low 8 elements. -func testUint64x8ConvertLoToUint16x8(t *testing.T, f func(x archsimd.Uint64x8) archsimd.Uint16x8, want func(x []uint64) []uint16) { +// testUint64x8ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testUint64x8ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Uint64x8) archsimd.Float64x4, want func(x []uint64) []float64) { n := 8 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() a := archsimd.LoadUint64x8(x) - g := make([]uint16, 8) + g := make([]float64, 4) f(a).Store(g) w := want(x) return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testFloat32x4UnaryFlaky tests the simd unary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat32x4UnaryFlaky(t *testing.T, f func(x archsimd.Float32x4) archsimd.Float32x4, want func(x []float32) []float32, flakiness float64) { - n := 4 +// testFloat32x16ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat32x16ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Float32x16) archsimd.Float64x4, want func(x []float32) []float64) { + n := 16 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := archsimd.LoadFloat32x4(x) - g := make([]float32, n) + a := archsimd.LoadFloat32x16(x) + g := make([]float64, 4) f(a).Store(g) w := want(x) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) }) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } -// testFloat64x2UnaryFlaky tests the simd unary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat64x2UnaryFlaky(t *testing.T, f func(x archsimd.Float64x2) archsimd.Float64x2, want func(x []float64) []float64, flakiness float64) { - n := 2 +// testFloat64x8ConvertLoToFloat64x4 tests the simd conversion method f against the expected behavior generated by want. +// This converts only the low 4 elements. +func testFloat64x8ConvertLoToFloat64x4(t *testing.T, f func(x archsimd.Float64x8) archsimd.Float64x4, want func(x []float64) []float64) { + n := 8 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := archsimd.LoadFloat64x2(x) - g := make([]float64, n) + a := archsimd.LoadFloat64x8(x) + g := make([]float64, 4) f(a).Store(g) w := want(x) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) }) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) }) }) } diff --git a/src/simd/archsimd/internal/simd_test/helpers_test.go b/src/simd/archsimd/internal/simd_test/helpers_test.go index 061bb30249248ad0a1a9b9943369dfc3c5159736..c55555bf3c805751b890c47be77aa396be93cbb2 100644 --- a/src/simd/archsimd/internal/simd_test/helpers_test.go +++ b/src/simd/archsimd/internal/simd_test/helpers_test.go @@ -9,6 +9,7 @@ import ( "fmt" "math" + "reflect" "simd/archsimd/internal/test_helpers" "testing" "unsafe" @@ -292,3 +293,72 @@ //go:noinline func hideConst[T number](x T) T { return x } + +func testStorePartRV[T number, V any](t *testing.T, name string, n int, val V, storePart func(v V, s []T) int) { + t.Helper() + // empty slice + { + s := make([]T, 0) + rv := storePart(val, s) + if rv != 0 { + t.Errorf("%s: StorePart on empty slice returned %d, expected 0", name, rv) + } + } + + // single-element slice + { + s := make([]T, 1) + rv := storePart(val, s) + if rv != 1 { + t.Errorf("%s: StorePart on 1-element slice returned %d, expected 1", name, rv) + } + } + + // longer-than-vector slice + { + s := make([]T, n+5) + rv := storePart(val, s) + if rv != n { + t.Errorf("%s: StorePart on %d-element slice (longer than %d) returned %d, expected %d", name, n+5, n, rv, n) + } + } +} + +type HasLenAndStorePart[T number] interface { + StorePart(s []T) int + Len() int +} + +func testStorePartReturnValue[T number, V HasLenAndStorePart[T]](t *testing.T) { + t.Helper() + var v V + n := v.Len() + name := reflect.TypeOf(v).Name() + // empty slice + { + s := make([]T, 0) + rv := v.StorePart(s) + if rv != 0 { + t.Errorf("%s: StorePart on empty slice returned %d, expected 0", name, rv) + } + } + + // single-element slice + { + s := make([]T, 1) + rv := v.StorePart(s) + if rv != 1 { + t.Errorf("%s: StorePart on 1-element slice returned %d, expected 1", name, rv) + } + } + + // longer-than-vector slice + { + s := make([]T, n+5) + rv := v.StorePart(s) + if rv != n { + t.Errorf("%s: StorePart on %d-element slice (longer than %d) returned %d, expected %d", name, n+5, n, rv, n) + } + } + t.Logf("tested %s", name) +} diff --git a/src/simd/archsimd/internal/simd_test/reduce_arm64_helpers_test.go b/src/simd/archsimd/internal/simd_test/reduce_helpers_arm64_test.go rename from src/simd/archsimd/internal/simd_test/reduce_arm64_helpers_test.go rename to src/simd/archsimd/internal/simd_test/reduce_helpers_arm64_test.go diff --git a/src/simd/archsimd/internal/simd_test/shift_128_test.go b/src/simd/archsimd/internal/simd_test/shift_128_test.go index 7da9ad198884a18901b646f49067a309a402bd7f..1ece7d3988110278ffd0baccd78d7ce93c95a9d2 100644 --- a/src/simd/archsimd/internal/simd_test/shift_128_test.go +++ b/src/simd/archsimd/internal/simd_test/shift_128_test.go @@ -2,11 +2,12 @@ // 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 && wasm +//go:build goexperiment.simd && (amd64 || wasm || arm64) package simd_test import ( + "runtime" "simd/archsimd" "testing" ) @@ -75,6 +76,13 @@ testInt32x4Unary(t, func(x archsimd.Int32x4) archsimd.Int32x4 { return x.ShiftAllLeft(hide(0x1000)) }, map1(func(x int32) int32 { return x << hide(0x1000) })) + testInt16x8ShiftAll(t, archsimd.Int16x8.ShiftAllLeft, shiftAllLeftSlice[int16]) + testInt32x4ShiftAll(t, archsimd.Int32x4.ShiftAllLeft, shiftAllLeftSlice[int32]) + testInt64x2ShiftAll(t, archsimd.Int64x2.ShiftAllLeft, shiftAllLeftSlice[int64]) + testUint16x8ShiftAll(t, archsimd.Uint16x8.ShiftAllLeft, shiftAllLeftSlice[uint16]) + testUint32x4ShiftAll(t, archsimd.Uint32x4.ShiftAllLeft, shiftAllLeftSlice[uint32]) + testUint64x2ShiftAll(t, archsimd.Uint64x2.ShiftAllLeft, shiftAllLeftSlice[uint64]) + // Signed ShiftAllRight testInt32x4Unary(t, @@ -91,6 +99,12 @@ testInt32x4Unary(t, func(x archsimd.Int32x4) archsimd.Int32x4 { return x.ShiftAllRight(hide(0x1000)) }, map1(func(x int32) int32 { return x >> hide(0x1000) })) + testInt16x8ShiftAll(t, archsimd.Int16x8.ShiftAllRight, shiftAllRightSlice[int16]) + testInt32x4ShiftAll(t, archsimd.Int32x4.ShiftAllRight, shiftAllRightSlice[int32]) + if runtime.GOARCH != "amd64" || archsimd.X86.AVX512() { + testInt64x2ShiftAll(t, archsimd.Int64x2.ShiftAllRight, shiftAllRightSlice[int64]) + } + // Unsigned ShiftAllRight testUint32x4Unary(t, @@ -106,4 +120,10 @@ map1(func(x uint32) uint32 { return x >> hide(0x1000) })) testUint32x4Unary(t, func(x archsimd.Uint32x4) archsimd.Uint32x4 { return x.ShiftAllRight(hide(0x1000)) }, map1(func(x uint32) uint32 { return x >> hide(0x1000) })) + + testUint16x8ShiftAll(t, archsimd.Uint16x8.ShiftAllRight, shiftAllRightSlice[uint16]) + testUint32x4ShiftAll(t, archsimd.Uint32x4.ShiftAllRight, shiftAllRightSlice[uint32]) + testUint64x2ShiftAll(t, archsimd.Uint64x2.ShiftAllRight, shiftAllRightSlice[uint64]) } + +var testShiftAllAmts = []uint64{0, 1, 3, 7, 15, 31, 63, 128, 1024} diff --git a/src/simd/archsimd/internal/simd_test/shift_arm64_test.go b/src/simd/archsimd/internal/simd_test/shift_arm64_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e1f99e0d8c5feecf2c6a6742812a7a318a69dcb2 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/shift_arm64_test.go @@ -0,0 +1,78 @@ +// 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 && arm64 + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +func TestShift(t *testing.T) { + // Signed — reuse binary helpers, same-type operand pairs + testInt8x16Binary(t, archsimd.Int8x16.Shift, shiftSlice[int8]) + testInt16x8Binary(t, archsimd.Int16x8.Shift, shiftSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.Shift, shiftSlice[int32]) + testInt64x2Binary(t, archsimd.Int64x2.Shift, shiftSlice[int64]) + + // Unsigned — mixed-type operand pairs + testUint8x16Shift(t, archsimd.Uint8x16.Shift, shiftMixedSlice[uint8, int8]) + testUint16x8Shift(t, archsimd.Uint16x8.Shift, shiftMixedSlice[uint16, int16]) + testUint32x4Shift(t, archsimd.Uint32x4.Shift, shiftMixedSlice[uint32, int32]) + testUint64x2Shift(t, archsimd.Uint64x2.Shift, shiftMixedSlice[uint64, int64]) +} + +func TestShiftSaturated(t *testing.T) { + // Signed — reuse binary helpers + testInt8x16Binary(t, archsimd.Int8x16.ShiftSaturated, shiftSaturatingSignedSlice[int8]) + testInt16x8Binary(t, archsimd.Int16x8.ShiftSaturated, shiftSaturatingSignedSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.ShiftSaturated, shiftSaturatingSignedSlice[int32]) + testInt64x2Binary(t, archsimd.Int64x2.ShiftSaturated, shiftSaturatingSignedSlice[int64]) + + // Unsigned — mixed-type + testUint8x16Shift(t, archsimd.Uint8x16.ShiftSaturated, shiftSaturatingUnsignedSlice[uint8, int8]) + testUint16x8Shift(t, archsimd.Uint16x8.ShiftSaturated, shiftSaturatingUnsignedSlice[uint16, int16]) + testUint32x4Shift(t, archsimd.Uint32x4.ShiftSaturated, shiftSaturatingUnsignedSlice[uint32, int32]) + testUint64x2Shift(t, archsimd.Uint64x2.ShiftSaturated, shiftSaturatingUnsignedSlice[uint64, int64]) +} + +func TestConcatShiftBytesRight(t *testing.T) { + hide := hideConst[uint64] + + csbr := func(shift uint64) func(x, y []uint8) []uint8 { + return func(x, y []uint8) []uint8 { + z := make([]uint8, len(x)) + for i := range z { + target := i + int(shift) + if target < 16 { + z[i] = y[target] + } else if target < 32 { + z[i] = x[(target - 16)] + } + } + return z + } + } + + t.Run("Uint8x16", func(t *testing.T) { + for _, shift := range []uint64{0, 2, 8, 15} { + t.Log("shift", shift) + testUint8x16Binary(t, + func(x, y archsimd.Uint8x16) archsimd.Uint8x16 { return x.ConcatShiftBytesRight(y, shift) }, + csbr(shift)) + testUint8x16Binary(t, + func(x, y archsimd.Uint8x16) archsimd.Uint8x16 { return x.ConcatShiftBytesRight(y, hide(shift)) }, + csbr(hide(shift))) + } + }) +} + +func TestShiftAll8(t *testing.T) { + testInt8x16ShiftAll(t, archsimd.Int8x16.ShiftAllLeft, shiftAllLeftSlice[int8]) + testUint8x16ShiftAll(t, archsimd.Uint8x16.ShiftAllLeft, shiftAllLeftSlice[uint8]) + testInt8x16ShiftAll(t, archsimd.Int8x16.ShiftAllRight, shiftAllRightSlice[int8]) + testUint8x16ShiftAll(t, archsimd.Uint8x16.ShiftAllRight, shiftAllRightSlice[uint8]) +} diff --git a/src/simd/archsimd/internal/simd_test/shift_helpers_128_test.go b/src/simd/archsimd/internal/simd_test/shift_helpers_128_test.go new file mode 100644 index 0000000000000000000000000000000000000000..10081516abb2dc9e9c9971cb17495c180d60e213 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/shift_helpers_128_test.go @@ -0,0 +1,166 @@ +// Code generated by 'tmplgen'; DO NOT EDIT. + +//go:build goexperiment.simd && (amd64 || wasm || arm64) + +// This file contains functions testing shift simd methods. +// Each function in this file is specialized for a +// particular simd type x. + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +// testInt8x16ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt8x16ShiftAll(t *testing.T, f func(_ archsimd.Int8x16, _ uint64) archsimd.Int8x16, want func(_ []int8, _ uint64) []int8) { + n := 16 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt8x16(x) + g := make([]int8, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testInt16x8ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt16x8ShiftAll(t *testing.T, f func(_ archsimd.Int16x8, _ uint64) archsimd.Int16x8, want func(_ []int16, _ uint64) []int16) { + n := 8 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt16x8(x) + g := make([]int16, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testInt32x4ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt32x4ShiftAll(t *testing.T, f func(_ archsimd.Int32x4, _ uint64) archsimd.Int32x4, want func(_ []int32, _ uint64) []int32) { + n := 4 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt32x4(x) + g := make([]int32, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testInt64x2ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt64x2ShiftAll(t *testing.T, f func(_ archsimd.Int64x2, _ uint64) archsimd.Int64x2, want func(_ []int64, _ uint64) []int64) { + n := 2 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt64x2(x) + g := make([]int64, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint8x16ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint8x16ShiftAll(t *testing.T, f func(_ archsimd.Uint8x16, _ uint64) archsimd.Uint8x16, want func(_ []uint8, _ uint64) []uint8) { + n := 16 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint8x16(x) + g := make([]uint8, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint16x8ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint16x8ShiftAll(t *testing.T, f func(_ archsimd.Uint16x8, _ uint64) archsimd.Uint16x8, want func(_ []uint16, _ uint64) []uint16) { + n := 8 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint16x8(x) + g := make([]uint16, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint32x4ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint32x4ShiftAll(t *testing.T, f func(_ archsimd.Uint32x4, _ uint64) archsimd.Uint32x4, want func(_ []uint32, _ uint64) []uint32) { + n := 4 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint32x4(x) + g := make([]uint32, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint64x2ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint64x2ShiftAll(t *testing.T, f func(_ archsimd.Uint64x2, _ uint64) archsimd.Uint64x2, want func(_ []uint64, _ uint64) []uint64) { + n := 2 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint64x2(x) + g := make([]uint64, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} diff --git a/src/simd/archsimd/internal/simd_test/shift_helpers_arm64_test.go b/src/simd/archsimd/internal/simd_test/shift_helpers_arm64_test.go new file mode 100644 index 0000000000000000000000000000000000000000..65ddd317fb04196594f7a25b245d9189355ad0a9 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/shift_helpers_arm64_test.go @@ -0,0 +1,78 @@ +// Code generated by 'tmplgen'; DO NOT EDIT. + +//go:build goexperiment.simd && arm64 + +// This file contains functions testing shift simd methods. +// Each function in this file is specialized for a +// particular simd type x. + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +// testUint8x16Shift tests a shift-like method where the first operand is Uint8x16 +// and the second operand is Int8x16 (mixed-type shift). +func testUint8x16Shift(t *testing.T, f func(_ archsimd.Uint8x16, _ archsimd.Int8x16) archsimd.Uint8x16, want func(_ []uint8, _ []int8) []uint8) { + n := 16 + t.Helper() + forSliceMixed(t, uint8s, int8s, n, func(x []uint8, y []int8) bool { + t.Helper() + a := archsimd.LoadUint8x16(x) + b := archsimd.LoadInt8x16(y) + g := make([]uint8, n) + f(a, b).Store(g) + w := want(x, y) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) + }) +} + +// testUint16x8Shift tests a shift-like method where the first operand is Uint16x8 +// and the second operand is Int16x8 (mixed-type shift). +func testUint16x8Shift(t *testing.T, f func(_ archsimd.Uint16x8, _ archsimd.Int16x8) archsimd.Uint16x8, want func(_ []uint16, _ []int16) []uint16) { + n := 8 + t.Helper() + forSliceMixed(t, uint16s, int16s, n, func(x []uint16, y []int16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + b := archsimd.LoadInt16x8(y) + g := make([]uint16, n) + f(a, b).Store(g) + w := want(x, y) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) + }) +} + +// testUint32x4Shift tests a shift-like method where the first operand is Uint32x4 +// and the second operand is Int32x4 (mixed-type shift). +func testUint32x4Shift(t *testing.T, f func(_ archsimd.Uint32x4, _ archsimd.Int32x4) archsimd.Uint32x4, want func(_ []uint32, _ []int32) []uint32) { + n := 4 + t.Helper() + forSliceMixed(t, uint32s, int32s, n, func(x []uint32, y []int32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + b := archsimd.LoadInt32x4(y) + g := make([]uint32, n) + f(a, b).Store(g) + w := want(x, y) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) + }) +} + +// testUint64x2Shift tests a shift-like method where the first operand is Uint64x2 +// and the second operand is Int64x2 (mixed-type shift). +func testUint64x2Shift(t *testing.T, f func(_ archsimd.Uint64x2, _ archsimd.Int64x2) archsimd.Uint64x2, want func(_ []uint64, _ []int64) []uint64) { + n := 2 + t.Helper() + forSliceMixed(t, uint64s, int64s, n, func(x []uint64, y []int64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + b := archsimd.LoadInt64x2(y) + g := make([]uint64, n) + f(a, b).Store(g) + w := want(x, y) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) + }) +} diff --git a/src/simd/archsimd/internal/simd_test/shift_helpers_wider_test.go b/src/simd/archsimd/internal/simd_test/shift_helpers_wider_test.go new file mode 100644 index 0000000000000000000000000000000000000000..4efc276526f5643624beadd2f6fb29ed593788c4 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/shift_helpers_wider_test.go @@ -0,0 +1,318 @@ +// Code generated by 'tmplgen'; DO NOT EDIT. + +//go:build goexperiment.simd && amd64 + +// This file contains functions testing shift simd methods. +// Each function in this file is specialized for a +// particular simd type x. + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +// testInt8x32ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt8x32ShiftAll(t *testing.T, f func(_ archsimd.Int8x32, _ uint64) archsimd.Int8x32, want func(_ []int8, _ uint64) []int8) { + n := 32 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt8x32(x) + g := make([]int8, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testInt16x16ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt16x16ShiftAll(t *testing.T, f func(_ archsimd.Int16x16, _ uint64) archsimd.Int16x16, want func(_ []int16, _ uint64) []int16) { + n := 16 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt16x16(x) + g := make([]int16, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testInt32x8ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt32x8ShiftAll(t *testing.T, f func(_ archsimd.Int32x8, _ uint64) archsimd.Int32x8, want func(_ []int32, _ uint64) []int32) { + n := 8 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt32x8(x) + g := make([]int32, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testInt64x4ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt64x4ShiftAll(t *testing.T, f func(_ archsimd.Int64x4, _ uint64) archsimd.Int64x4, want func(_ []int64, _ uint64) []int64) { + n := 4 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt64x4(x) + g := make([]int64, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint8x32ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint8x32ShiftAll(t *testing.T, f func(_ archsimd.Uint8x32, _ uint64) archsimd.Uint8x32, want func(_ []uint8, _ uint64) []uint8) { + n := 32 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint8x32(x) + g := make([]uint8, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint16x16ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint16x16ShiftAll(t *testing.T, f func(_ archsimd.Uint16x16, _ uint64) archsimd.Uint16x16, want func(_ []uint16, _ uint64) []uint16) { + n := 16 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint16x16(x) + g := make([]uint16, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint32x8ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint32x8ShiftAll(t *testing.T, f func(_ archsimd.Uint32x8, _ uint64) archsimd.Uint32x8, want func(_ []uint32, _ uint64) []uint32) { + n := 8 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint32x8(x) + g := make([]uint32, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint64x4ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint64x4ShiftAll(t *testing.T, f func(_ archsimd.Uint64x4, _ uint64) archsimd.Uint64x4, want func(_ []uint64, _ uint64) []uint64) { + n := 4 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint64x4(x) + g := make([]uint64, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testInt8x64ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt8x64ShiftAll(t *testing.T, f func(_ archsimd.Int8x64, _ uint64) archsimd.Int8x64, want func(_ []int8, _ uint64) []int8) { + n := 64 + t.Helper() + forSlice(t, int8s, n, func(x []int8) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt8x64(x) + g := make([]int8, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testInt16x32ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt16x32ShiftAll(t *testing.T, f func(_ archsimd.Int16x32, _ uint64) archsimd.Int16x32, want func(_ []int16, _ uint64) []int16) { + n := 32 + t.Helper() + forSlice(t, int16s, n, func(x []int16) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt16x32(x) + g := make([]int16, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testInt32x16ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt32x16ShiftAll(t *testing.T, f func(_ archsimd.Int32x16, _ uint64) archsimd.Int32x16, want func(_ []int32, _ uint64) []int32) { + n := 16 + t.Helper() + forSlice(t, int32s, n, func(x []int32) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt32x16(x) + g := make([]int32, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testInt64x8ShiftAll tests a shift-all method (unary + scalar uint64). +func testInt64x8ShiftAll(t *testing.T, f func(_ archsimd.Int64x8, _ uint64) archsimd.Int64x8, want func(_ []int64, _ uint64) []int64) { + n := 8 + t.Helper() + forSlice(t, int64s, n, func(x []int64) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadInt64x8(x) + g := make([]int64, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint8x64ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint8x64ShiftAll(t *testing.T, f func(_ archsimd.Uint8x64, _ uint64) archsimd.Uint8x64, want func(_ []uint8, _ uint64) []uint8) { + n := 64 + t.Helper() + forSlice(t, uint8s, n, func(x []uint8) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint8x64(x) + g := make([]uint8, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint16x32ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint16x32ShiftAll(t *testing.T, f func(_ archsimd.Uint16x32, _ uint64) archsimd.Uint16x32, want func(_ []uint16, _ uint64) []uint16) { + n := 32 + t.Helper() + forSlice(t, uint16s, n, func(x []uint16) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint16x32(x) + g := make([]uint16, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint32x16ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint32x16ShiftAll(t *testing.T, f func(_ archsimd.Uint32x16, _ uint64) archsimd.Uint32x16, want func(_ []uint32, _ uint64) []uint32) { + n := 16 + t.Helper() + forSlice(t, uint32s, n, func(x []uint32) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint32x16(x) + g := make([]uint32, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} + +// testUint64x8ShiftAll tests a shift-all method (unary + scalar uint64). +func testUint64x8ShiftAll(t *testing.T, f func(_ archsimd.Uint64x8, _ uint64) archsimd.Uint64x8, want func(_ []uint64, _ uint64) []uint64) { + n := 8 + t.Helper() + forSlice(t, uint64s, n, func(x []uint64) bool { + t.Helper() + for _, amt := range testShiftAllAmts { + a := archsimd.LoadUint64x8(x) + g := make([]uint64, n) + f(a, amt).Store(g) + w := want(x, amt) + if !checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v, amt=%d", x, amt) }) { + return false + } + } + return true + }) +} diff --git a/src/simd/archsimd/internal/simd_test/shift_test.go b/src/simd/archsimd/internal/simd_test/shift_amd64_test.go rename from src/simd/archsimd/internal/simd_test/shift_test.go rename to src/simd/archsimd/internal/simd_test/shift_amd64_test.go index 18cc206f647d2b9b2b5d3e190a4ceb5b2cfa3aa2..036ea478730763fb5ca817854fb22095a2855098 100644 --- a/src/simd/archsimd/internal/simd_test/shift_test.go +++ b/src/simd/archsimd/internal/simd_test/shift_amd64_test.go @@ -11,7 +11,7 @@ "simd/archsimd" "testing" ) -func TestRotateAllLeft(t *testing.T) { +func TestRotateAllLeftAMD64(t *testing.T) { x := uint8(0x81) if y := rotl(x, 1); y != 3 { t.Errorf("Expected 3, got 0x%x", y) @@ -23,12 +23,6 @@ if y := rotr(x, 4); y != 0x18 { t.Errorf("Expected 0x18, got 0x%x", y) } - for i := uint64(0); i < 65; i++ { - testUint64x2Unary(t, curry2(archsimd.Uint64x2.RotateAllLeft, i), rotlOfSlice[uint64](i)) - testUint32x4Unary(t, curry2(archsimd.Uint32x4.RotateAllLeft, i), rotlOfSlice[uint32](i)) - // testUint16x8Unary(t, curry2(archsimd.Uint16x8.RotateAllLeft, i), rotlOfSlice[uint16](i)) - // testUint8x16Unary(t, curry2(archsimd.Uint8x16.RotateAllLeft, i), rotlOfSlice[uint8](i)) - } for i := uint64(0); i < 65; i++ { testUint64x4Unary(t, curry2(archsimd.Uint64x4.RotateAllLeft, i), rotlOfSlice[uint64](i)) testUint32x8Unary(t, curry2(archsimd.Uint32x8.RotateAllLeft, i), rotlOfSlice[uint32](i)) @@ -38,7 +32,7 @@ } } -func TestRotateAllRight(t *testing.T) { +func TestRotateAllRightAMD64(t *testing.T) { x := uint8(0x81) if y := rotr(x, 1); y != 0xc0 { t.Errorf("Expected 0xc0, got 0x%x", y) @@ -50,12 +44,6 @@ if y := rotr(x, 4); y != 0x18 { t.Errorf("Expected 0x18, got 0x%x", y) } - for i := uint64(0); i < 65; i++ { - testUint64x2Unary(t, curry2(archsimd.Uint64x2.RotateAllRight, i), rotrOfSlice[uint64](i)) - testUint32x4Unary(t, curry2(archsimd.Uint32x4.RotateAllRight, i), rotrOfSlice[uint32](i)) - // testUint16x8Unary(t, curry2(archsimd.Uint16x8.RotateAllLeft, i), rotlOfSlice[uint16](i)) - // testUint8x16Unary(t, curry2(archsimd.Uint8x16.RotateAllLeft, i), rotlOfSlice[uint8](i)) - } for i := uint64(0); i < 65; i++ { testUint64x4Unary(t, curry2(archsimd.Uint64x4.RotateAllRight, i), rotrOfSlice[uint64](i)) testUint32x8Unary(t, curry2(archsimd.Uint32x8.RotateAllRight, i), rotrOfSlice[uint32](i)) @@ -250,3 +238,48 @@ grouped2(csbr(hide(shift)))) } }) } + +func TestShiftAllAMD64(t *testing.T) { + if archsimd.X86.AVX2() { + // ShiftAllLeft + testInt16x16ShiftAll(t, archsimd.Int16x16.ShiftAllLeft, shiftAllLeftSlice[int16]) + testInt32x8ShiftAll(t, archsimd.Int32x8.ShiftAllLeft, shiftAllLeftSlice[int32]) + testInt64x4ShiftAll(t, archsimd.Int64x4.ShiftAllLeft, shiftAllLeftSlice[int64]) + testUint16x16ShiftAll(t, archsimd.Uint16x16.ShiftAllLeft, shiftAllLeftSlice[uint16]) + testUint32x8ShiftAll(t, archsimd.Uint32x8.ShiftAllLeft, shiftAllLeftSlice[uint32]) + testUint64x4ShiftAll(t, archsimd.Uint64x4.ShiftAllLeft, shiftAllLeftSlice[uint64]) + + // ShiftAllRight signed + testInt16x16ShiftAll(t, archsimd.Int16x16.ShiftAllRight, shiftAllRightSlice[int16]) + testInt32x8ShiftAll(t, archsimd.Int32x8.ShiftAllRight, shiftAllRightSlice[int32]) + // Int64x4 ShiftAllRight requires AVX-512 + + // ShiftAllRight unsigned + testUint16x16ShiftAll(t, archsimd.Uint16x16.ShiftAllRight, shiftAllRightSlice[uint16]) + testUint32x8ShiftAll(t, archsimd.Uint32x8.ShiftAllRight, shiftAllRightSlice[uint32]) + testUint64x4ShiftAll(t, archsimd.Uint64x4.ShiftAllRight, shiftAllRightSlice[uint64]) + } + + if archsimd.X86.AVX512() { + // 512-bit vectors (AVX512) + // ShiftAllLeft + testInt16x32ShiftAll(t, archsimd.Int16x32.ShiftAllLeft, shiftAllLeftSlice[int16]) + testInt32x16ShiftAll(t, archsimd.Int32x16.ShiftAllLeft, shiftAllLeftSlice[int32]) + testInt64x8ShiftAll(t, archsimd.Int64x8.ShiftAllLeft, shiftAllLeftSlice[int64]) + testUint16x32ShiftAll(t, archsimd.Uint16x32.ShiftAllLeft, shiftAllLeftSlice[uint16]) + testUint32x16ShiftAll(t, archsimd.Uint32x16.ShiftAllLeft, shiftAllLeftSlice[uint32]) + testUint64x8ShiftAll(t, archsimd.Uint64x8.ShiftAllLeft, shiftAllLeftSlice[uint64]) + + // ShiftAllRight signed + testInt16x32ShiftAll(t, archsimd.Int16x32.ShiftAllRight, shiftAllRightSlice[int16]) + testInt32x16ShiftAll(t, archsimd.Int32x16.ShiftAllRight, shiftAllRightSlice[int32]) + testInt64x8ShiftAll(t, archsimd.Int64x8.ShiftAllRight, shiftAllRightSlice[int64]) + // 256-bit Int64x4 ShiftAllRight (requires AVX-512) + testInt64x4ShiftAll(t, archsimd.Int64x4.ShiftAllRight, shiftAllRightSlice[int64]) + + // ShiftAllRight unsigned + testUint16x32ShiftAll(t, archsimd.Uint16x32.ShiftAllRight, shiftAllRightSlice[uint16]) + testUint32x16ShiftAll(t, archsimd.Uint32x16.ShiftAllRight, shiftAllRightSlice[uint32]) + testUint64x8ShiftAll(t, archsimd.Uint64x8.ShiftAllRight, shiftAllRightSlice[uint64]) + } +} diff --git a/src/simd/archsimd/internal/simd_test/shift_wasm_test.go b/src/simd/archsimd/internal/simd_test/shift_wasm_test.go new file mode 100644 index 0000000000000000000000000000000000000000..46bf9fe7ac736ecadba37a33b8c009be8758b513 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/shift_wasm_test.go @@ -0,0 +1,19 @@ +// 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 && wasm + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +func TestShiftAll8(t *testing.T) { + testInt8x16ShiftAll(t, archsimd.Int8x16.ShiftAllLeft, shiftAllLeftSlice[int8]) + testUint8x16ShiftAll(t, archsimd.Uint8x16.ShiftAllLeft, shiftAllLeftSlice[uint8]) + testInt8x16ShiftAll(t, archsimd.Int8x16.ShiftAllRight, shiftAllRightSlice[int8]) + testUint8x16ShiftAll(t, archsimd.Uint8x16.ShiftAllRight, shiftAllRightSlice[uint8]) +} diff --git a/src/simd/archsimd/internal/simd_test/simd_amd64_test.go b/src/simd/archsimd/internal/simd_test/simd_amd64_test.go new file mode 100644 index 0000000000000000000000000000000000000000..5ec9dbe49302e87c674b1df0cc183816f5b3b800 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/simd_amd64_test.go @@ -0,0 +1,1567 @@ +// Copyright 2025 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 && amd64 + +package simd_test + +import ( + "fmt" + "os" + "simd/archsimd" + "slices" + "testing" + "unsafe" +) + +func TestMain(m *testing.M) { + if !archsimd.X86.AVX() { + fmt.Fprintln(os.Stderr, "Skipping tests: AVX is not available") + os.Exit(0) + } + os.Exit(m.Run()) +} + +func TestPermute(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + x := []int64{1, 2, 3, 4, 5, 6, 7, 8} + indices := []uint64{7, 6, 5, 4, 3, 2, 1, 0} + want := []int64{8, 7, 6, 5, 4, 3, 2, 1} + got := make([]int64, 8) + archsimd.LoadInt64x8(x).Permute(archsimd.LoadUint64x8(indices)).Store(got) + checkSlices(t, got, want) +} + +func TestPermuteOrZero(t *testing.T) { + x := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + indices := []int8{7, 6, 5, 4, 3, 2, 1, 0, -1, 8, -1, 9, -1, 10, -1, 11} + want := []uint8{8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 0, 10, 0, 11, 0, 12} + got := make([]uint8, len(x)) + archsimd.LoadUint8x16(x).PermuteOrZero(archsimd.LoadInt8x16(indices)).Store(got) + checkSlices(t, got, want) +} + +func TestConcatPermute(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + x := []int64{1, 2, 3, 4, 5, 6, 7, 8} + y := []int64{-1, -2, -3, -4, -5, -6, -7, -8} + indices := []uint64{7 + 8, 6, 5 + 8, 4, 3 + 8, 2, 1 + 8, 0} + want := []int64{-8, 7, -6, 5, -4, 3, -2, 1} + got := make([]int64, 8) + archsimd.LoadInt64x8(x).ConcatPermute(archsimd.LoadInt64x8(y), archsimd.LoadUint64x8(indices)).Store(got) + checkSlices(t, got, want) +} + +func TestCompress(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + v1234 := archsimd.LoadInt32x4([]int32{1, 2, 3, 4}) + v2400 := v1234.Compress(archsimd.Mask32x4FromBits(0b1010)) + got := make([]int32, 4) + v2400.Store(got) + want := []int32{2, 4, 0, 0} + if !slices.Equal(got, want) { + t.Errorf("want and got differ, want=%v, got=%v", want, got) + } +} + +func TestExpand(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + v3400 := archsimd.LoadInt32x4([]int32{3, 4, 0, 0}) + v2400 := v3400.Expand(archsimd.Mask32x4FromBits(0b1010)) + got := make([]int32, 4) + v2400.Store(got) + want := []int32{0, 3, 0, 4} + if !slices.Equal(got, want) { + t.Errorf("want and got differ, want=%v, got=%v", want, got) + } +} + +func TestSlicesInt8(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} + v := archsimd.LoadInt8x32(a) + b := make([]int8, 32, 32) + v.Store(b) + checkSlices(t, a, b) +} + +func TestSlicesInt8TooShortLoad(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + defer func() { + if r := recover(); r != nil { + t.Logf("Saw EXPECTED panic %v", r) + } else { + t.Errorf("Did not see expected panic") + } + }() + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} // TOO SHORT, should panic + v := archsimd.LoadInt8x32(a) + b := make([]int8, 32, 32) + v.Store(b) + checkSlices(t, a, b) +} + +func TestSlicesInt8TooShortStore(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + defer func() { + if r := recover(); r != nil { + t.Logf("Saw EXPECTED panic %v", r) + } else { + t.Errorf("Did not see expected panic") + } + }() + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} + v := archsimd.LoadInt8x32(a) + b := make([]int8, 31) // TOO SHORT, should panic + v.Store(b) + checkSlices(t, a, b) +} + +func TestSlicesFloat64(t *testing.T) { + a := []float64{1, 2, 3, 4, 5, 6, 7, 8} // too long, should be fine + v := archsimd.LoadFloat64x4(a) + b := make([]float64, 4, 4) + v.Store(b) + for i := range b { + if a[i] != b[i] { + t.Errorf("a and b differ at index %d, a=%f, b=%f", i, a[i], b[i]) + } + } +} + +// TODO: try to reduce this test to be smaller. +func TestMergeLocals(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + testMergeLocalswrapper(t, archsimd.Int64x4.Add) +} + +//go:noinline +func forceSpill() {} + +func testMergeLocalswrapper(t *testing.T, op func(archsimd.Int64x4, archsimd.Int64x4) archsimd.Int64x4) { + t.Helper() + s0 := []int64{0, 1, 2, 3} + s1 := []int64{-1, 0, -1, 0} + want := []int64{-1, 1, 1, 3} + v := archsimd.LoadInt64x4(s0) + m := archsimd.LoadInt64x4(s1) + forceSpill() + got := make([]int64, 4) + gotv := op(v, m) + gotv.Store(got) + for i := range len(want) { + if !(got[i] == want[i]) { + t.Errorf("Result at %d incorrect: want %v, got %v", i, want[i], got[i]) + } + } +} + +func TestBitMaskFromBits(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + results := [2]int64{} + want := [2]int64{0, 6} + m := archsimd.Mask64x2FromBits(0b10) + archsimd.LoadInt64x2([]int64{1, 2}).Add(archsimd.LoadInt64x2([]int64{3, 4})).Masked(m).StoreArray(&results) + for i := range 2 { + if results[i] != want[i] { + t.Errorf("Result at %d incorrect: want %v, got %v", i, want[i], results[i]) + } + } +} + +var maskForTestBitMaskFromBitsLoad = uint8(0b10) + +func TestBitMaskFromBitsLoad(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + results := [2]int64{} + want := [2]int64{0, 6} + m := archsimd.Mask64x2FromBits(maskForTestBitMaskFromBitsLoad) + archsimd.LoadInt64x2([]int64{1, 2}).Add(archsimd.LoadInt64x2([]int64{3, 4})).Masked(m).StoreArray(&results) + for i := range 2 { + if results[i] != want[i] { + t.Errorf("Result at %d incorrect: want %v, got %v", i, want[i], results[i]) + } + } +} + +func TestBitMaskToBits(t *testing.T) { + int8s := []int8{ + 0, 1, 1, 0, 0, 1, 0, 1, + 1, 0, 1, 1, 0, 0, 1, 0, + 1, 0, 0, 1, 1, 0, 1, 0, + 0, 1, 1, 0, 0, 1, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 0, 1, 1, 0, 0, 1, + 1, 0, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + } + int16s := make([]int16, 32) + for i := range int16s { + int16s[i] = int16(int8s[i]) + } + int32s := make([]int32, 16) + for i := range int32s { + int32s[i] = int32(int8s[i]) + } + int64s := make([]int64, 8) + for i := range int64s { + int64s[i] = int64(int8s[i]) + } + want64 := uint64(0) + for i := range int8s { + want64 |= uint64(int8s[i]) << i + } + want32 := uint32(want64) + want16 := uint16(want64) + want8 := uint8(want64) + want4 := want8 & 0b1111 + want2 := want4 & 0b11 + + if v := archsimd.LoadInt8x16(int8s[:16]).ToMask().ToBits(); v != want16 { + t.Errorf("want %b, got %b", want16, v) + } + if v := archsimd.LoadInt32x4(int32s[:4]).ToMask().ToBits(); v != want4 { + t.Errorf("want %b, got %b", want4, v) + } + if v := archsimd.LoadInt32x8(int32s[:8]).ToMask().ToBits(); v != want8 { + t.Errorf("want %b, got %b", want8, v) + } + if v := archsimd.LoadInt64x2(int64s[:2]).ToMask().ToBits(); v != want2 { + t.Errorf("want %b, got %b", want2, v) + } + if v := archsimd.LoadInt64x4(int64s[:4]).ToMask().ToBits(); v != want4 { + t.Errorf("want %b, got %b", want4, v) + } + + if archsimd.X86.AVX2() { + if v := archsimd.LoadInt8x32(int8s[:32]).ToMask().ToBits(); v != want32 { + t.Errorf("want %b, got %b", want32, v) + } + } + + if archsimd.X86.AVX512() { + if v := archsimd.LoadInt8x64(int8s).ToMask().ToBits(); v != want64 { + t.Errorf("want %b, got %b", want64, v) + } + if v := archsimd.LoadInt16x8(int16s[:8]).ToMask().ToBits(); v != want8 { + t.Errorf("want %b, got %b", want8, v) + } + if v := archsimd.LoadInt16x16(int16s[:16]).ToMask().ToBits(); v != want16 { + t.Errorf("want %b, got %b", want16, v) + } + if v := archsimd.LoadInt16x32(int16s).ToMask().ToBits(); v != want32 { + t.Errorf("want %b, got %b", want32, v) + } + if v := archsimd.LoadInt32x16(int32s).ToMask().ToBits(); v != want16 { + t.Errorf("want %b, got %b", want16, v) + } + if v := archsimd.LoadInt64x8(int64s).ToMask().ToBits(); v != want8 { + t.Errorf("want %b, got %b", want8, v) + } + } +} + +var maskForTestBitMaskFromBitsStore uint8 + +func TestBitMaskToBitsStore(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + maskForTestBitMaskFromBitsStore = archsimd.LoadInt16x8([]int16{1, 0, 1, 0, 0, 0, 0, 0}).ToMask().ToBits() + if maskForTestBitMaskFromBitsStore != 0b101 { + t.Errorf("Want 0b101, got %b", maskForTestBitMaskFromBitsStore) + } +} + +func TestMergeFloat(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + k := make([]int64, 4, 4) + s := make([]float64, 4, 4) + + a := archsimd.LoadFloat64x4([]float64{1, 2, 3, 4}) + b := archsimd.LoadFloat64x4([]float64{4, 2, 3, 1}) + g := a.Greater(b) + g.ToInt64x4().Store(k) + c := a.Merge(b, g) + + c.Store(s) + + checkSlices[int64](t, k, []int64{0, 0, 0, -1}) + checkSlices[float64](t, s, []float64{4, 2, 3, 4}) +} + +func TestIfElseFloat(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + k := make([]int64, 4, 4) + s := make([]float64, 4, 4) + + a := archsimd.LoadFloat64x4([]float64{1, 2, 3, 4}) + b := archsimd.LoadFloat64x4([]float64{4, 2, 3, 1}) + g := a.Greater(b) + g.ToInt64x4().Store(k) + c := a.IfElse(g, b) + + c.Store(s) + + checkSlices[int64](t, k, []int64{0, 0, 0, -1}) + checkSlices[float64](t, s, []float64{4, 2, 3, 4}) +} + +func TestMergeFloat512(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + + k := make([]int64, 8, 8) + s := make([]float64, 8, 8) + + a := archsimd.LoadFloat64x8([]float64{1, 2, 3, 4, 5, 6, 7, 8}) + b := archsimd.LoadFloat64x8([]float64{8, 7, 6, 5, 4, 2, 3, 1}) + g := a.Greater(b) + g.ToInt64x8().Store(k) + c := a.Merge(b, g) + d := a.Masked(g) + + checkSlices[int64](t, k, []int64{0, 0, 0, 0, -1, -1, -1, -1}) + + c.Store(s) + checkSlices[float64](t, s, []float64{8, 7, 6, 5, 5, 6, 7, 8}) + + d.Store(s) + checkSlices[float64](t, s, []float64{0, 0, 0, 0, 5, 6, 7, 8}) +} + +func TestIfElseFloat512(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + + k := make([]int64, 8, 8) + s := make([]float64, 8, 8) + + a := archsimd.LoadFloat64x8([]float64{1, 2, 3, 4, 5, 6, 7, 8}) + b := archsimd.LoadFloat64x8([]float64{8, 7, 6, 5, 4, 2, 3, 1}) + g := a.Greater(b) + g.ToInt64x8().Store(k) + c := a.IfElse(g, b) + d := a.Masked(g) + + checkSlices[int64](t, k, []int64{0, 0, 0, 0, -1, -1, -1, -1}) + + c.Store(s) + checkSlices[float64](t, s, []float64{8, 7, 6, 5, 5, 6, 7, 8}) + + d.Store(s) + checkSlices[float64](t, s, []float64{0, 0, 0, 0, 5, 6, 7, 8}) +} + +var ro uint64 = 2 +var roBig uint64 = 1024 + 2 + +func TestRotateAllVariable(t *testing.T) { + got := make([]int32, 4) + archsimd.LoadInt32x4([]int32{0b11, 0b11, 0b11, 0b11}).RotateAllLeft(ro).Store(got) + for _, v := range got { + if v != 0b1100 { + t.Errorf("Want 0b1100, got %b", v) + } + } + archsimd.LoadInt32x4([]int32{0b11, 0b11, 0b11, 0b11}).RotateAllLeft(roBig).Store(got) + for _, v := range got { + if v != 0b1100 { + t.Errorf("Want 0b1100, got %b", v) + } + } +} + +func TestRotateAllConst(t *testing.T) { + got := make([]int32, 4) + archsimd.LoadInt32x4([]int32{0b11, 0b11, 0b11, 0b11}).RotateAllLeft(2).Store(got) + for _, v := range got { + if v != 0b1100 { + t.Errorf("Want 0b1100, got %b", v) + } + } +} + +func TestBroadcastFloat32x8(t *testing.T) { + s := make([]float32, 8, 8) + archsimd.BroadcastFloat32x8(123456789).Store(s) + checkSlices(t, s, []float32{123456789, 123456789, 123456789, 123456789, 123456789, 123456789, 123456789, 123456789}) +} + +func TestBroadcastInt8x32(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + s := make([]int8, 32, 32) + archsimd.BroadcastInt8x32(-123).Store(s) + checkSlices(t, s, []int8{-123, -123, -123, -123, -123, -123, -123, -123, + -123, -123, -123, -123, -123, -123, -123, -123, + -123, -123, -123, -123, -123, -123, -123, -123, + -123, -123, -123, -123, -123, -123, -123, -123, + }) +} + +func TestMaskOpt512(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + + k := make([]int64, 8, 8) + s := make([]float64, 8, 8) + + a := archsimd.LoadFloat64x8([]float64{2, 0, 2, 0, 2, 0, 2, 0}) + b := archsimd.LoadFloat64x8([]float64{1, 1, 1, 1, 1, 1, 1, 1}) + c := archsimd.LoadFloat64x8([]float64{1, 2, 3, 4, 5, 6, 7, 8}) + d := archsimd.LoadFloat64x8([]float64{2, 4, 6, 8, 10, 12, 14, 16}) + g := a.Greater(b) + e := c.Add(d).Masked(g) + e.Store(s) + g.ToInt64x8().Store(k) + checkSlices[int64](t, k, []int64{-1, 0, -1, 0, -1, 0, -1, 0}) + checkSlices[float64](t, s, []float64{3, 0, 9, 0, 15, 0, 21, 0}) +} + +// flattenedTranspose tranposes x and y, regarded as a pair of 2x2 +// matrices, but then flattens the rows in order, i.e +// x: ABCD ==> a: A1B2 +// y: 1234 b: C3D4 +func flattenedTranspose(x, y archsimd.Int32x4) (a, b archsimd.Int32x4) { + return x.InterleaveLo(y), x.InterleaveHi(y) +} + +func TestFlattenedTranspose(t *testing.T) { + r := make([]int32, 4, 4) + s := make([]int32, 4, 4) + + x := archsimd.LoadInt32x4([]int32{0xA, 0xB, 0xC, 0xD}) + y := archsimd.LoadInt32x4([]int32{1, 2, 3, 4}) + a, b := flattenedTranspose(x, y) + + a.Store(r) + b.Store(s) + + checkSlices[int32](t, r, []int32{0xA, 1, 0xB, 2}) + checkSlices[int32](t, s, []int32{0xC, 3, 0xD, 4}) + +} + +func TestClearAVXUpperBits(t *testing.T) { + // Test that ClearAVXUpperBits is safe even if there are SIMD values + // alive (although usually one should not do this). + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + + r := make([]int64, 4) + s := make([]int64, 4) + + x := archsimd.LoadInt64x4([]int64{10, 20, 30, 40}) + y := archsimd.LoadInt64x4([]int64{1, 2, 3, 4}) + + x.Add(y).Store(r) + archsimd.ClearAVXUpperBits() + x.Sub(y).Store(s) + + checkSlices[int64](t, r, []int64{11, 22, 33, 44}) + checkSlices[int64](t, s, []int64{9, 18, 27, 36}) +} + +func TestLeadingZeros(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + + src := []uint64{0b1111, 0} + want := []uint64{60, 64} + got := make([]uint64, 2) + archsimd.LoadUint64x2(src).LeadingZeros().Store(got) + for i := range 2 { + if want[i] != got[i] { + t.Errorf("Result incorrect at %d: want %d, got %d", i, want[i], got[i]) + } + } +} + +func TestIsZero(t *testing.T) { + v1 := archsimd.LoadUint64x2([]uint64{0, 1}) + v2 := archsimd.LoadUint64x2([]uint64{0, 0}) + if v1.IsZero() { + t.Errorf("Result incorrect, want false, got true") + } + if !v2.IsZero() { + t.Errorf("Result incorrect, want true, got false") + } + if !v1.And(v2).IsZero() { + t.Errorf("Result incorrect, want true, got false") + } + if v1.AndNot(v2).IsZero() { + t.Errorf("Result incorrect, want false, got true") + } + if !v2.And(v1).IsZero() { + t.Errorf("Result incorrect, want true, got false") + } + if !v2.AndNot(v1).IsZero() { + t.Errorf("Result incorrect, want true, got false") + } +} + +func TestSelect4FromPairConst(t *testing.T) { + x := archsimd.LoadInt32x4([]int32{0, 1, 2, 3}) + y := archsimd.LoadInt32x4([]int32{4, 5, 6, 7}) + + llll := x.ConcatPermuteScalars(0, 1, 2, 3, y) + hhhh := x.ConcatPermuteScalars(4, 5, 6, 7, y) + llhh := x.ConcatPermuteScalars(0, 1, 6, 7, y) + hhll := x.ConcatPermuteScalars(6, 7, 0, 1, y) + + lllh := x.ConcatPermuteScalars(0, 1, 2, 7, y) + llhl := x.ConcatPermuteScalars(0, 1, 7, 2, y) + lhll := x.ConcatPermuteScalars(0, 7, 1, 2, y) + hlll := x.ConcatPermuteScalars(7, 0, 1, 2, y) + + hhhl := x.ConcatPermuteScalars(4, 5, 6, 0, y) + hhlh := x.ConcatPermuteScalars(4, 5, 0, 6, y) + hlhh := x.ConcatPermuteScalars(4, 0, 5, 6, y) + lhhh := x.ConcatPermuteScalars(0, 4, 5, 6, y) + + lhlh := x.ConcatPermuteScalars(0, 4, 1, 5, y) + hlhl := x.ConcatPermuteScalars(4, 0, 5, 1, y) + lhhl := x.ConcatPermuteScalars(0, 4, 5, 1, y) + hllh := x.ConcatPermuteScalars(4, 0, 1, 5, y) + + r := make([]int32, 4, 4) + + foo := func(v archsimd.Int32x4, a, b, c, d int32) { + v.Store(r) + checkSlices[int32](t, r, []int32{a, b, c, d}) + } + + foo(llll, 0, 1, 2, 3) + foo(hhhh, 4, 5, 6, 7) + foo(llhh, 0, 1, 6, 7) + foo(hhll, 6, 7, 0, 1) + + foo(lllh, 0, 1, 2, 7) + foo(llhl, 0, 1, 7, 2) + foo(lhll, 0, 7, 1, 2) + foo(hlll, 7, 0, 1, 2) + + foo(hhhl, 4, 5, 6, 0) + foo(hhlh, 4, 5, 0, 6) + foo(hlhh, 4, 0, 5, 6) + foo(lhhh, 0, 4, 5, 6) + + foo(lhlh, 0, 4, 1, 5) + foo(hlhl, 4, 0, 5, 1) + foo(lhhl, 0, 4, 5, 1) + foo(hllh, 4, 0, 1, 5) +} + +//go:noinline +func selectFromPairInt32x4(x archsimd.Int32x4, a, b, c, d uint8, y archsimd.Int32x4) archsimd.Int32x4 { + return x.ConcatPermuteScalars(a, b, c, d, y) +} + +func TestSelect4FromPairVar(t *testing.T) { + x := archsimd.LoadInt32x4([]int32{0, 1, 2, 3}) + y := archsimd.LoadInt32x4([]int32{4, 5, 6, 7}) + + llll := selectFromPairInt32x4(x, 0, 1, 2, 3, y) + hhhh := selectFromPairInt32x4(x, 4, 5, 6, 7, y) + llhh := selectFromPairInt32x4(x, 0, 1, 6, 7, y) + hhll := selectFromPairInt32x4(x, 6, 7, 0, 1, y) + + lllh := selectFromPairInt32x4(x, 0, 1, 2, 7, y) + llhl := selectFromPairInt32x4(x, 0, 1, 7, 2, y) + lhll := selectFromPairInt32x4(x, 0, 7, 1, 2, y) + hlll := selectFromPairInt32x4(x, 7, 0, 1, 2, y) + + hhhl := selectFromPairInt32x4(x, 4, 5, 6, 0, y) + hhlh := selectFromPairInt32x4(x, 4, 5, 0, 6, y) + hlhh := selectFromPairInt32x4(x, 4, 0, 5, 6, y) + lhhh := selectFromPairInt32x4(x, 0, 4, 5, 6, y) + + lhlh := selectFromPairInt32x4(x, 0, 4, 1, 5, y) + hlhl := selectFromPairInt32x4(x, 4, 0, 5, 1, y) + lhhl := selectFromPairInt32x4(x, 0, 4, 5, 1, y) + hllh := selectFromPairInt32x4(x, 4, 0, 1, 5, y) + + r := make([]int32, 4, 4) + + foo := func(v archsimd.Int32x4, a, b, c, d int32) { + v.Store(r) + checkSlices[int32](t, r, []int32{a, b, c, d}) + } + + foo(llll, 0, 1, 2, 3) + foo(hhhh, 4, 5, 6, 7) + foo(llhh, 0, 1, 6, 7) + foo(hhll, 6, 7, 0, 1) + + foo(lllh, 0, 1, 2, 7) + foo(llhl, 0, 1, 7, 2) + foo(lhll, 0, 7, 1, 2) + foo(hlll, 7, 0, 1, 2) + + foo(hhhl, 4, 5, 6, 0) + foo(hhlh, 4, 5, 0, 6) + foo(hlhh, 4, 0, 5, 6) + foo(lhhh, 0, 4, 5, 6) + + foo(lhlh, 0, 4, 1, 5) + foo(hlhl, 4, 0, 5, 1) + foo(lhhl, 0, 4, 5, 1) + foo(hllh, 4, 0, 1, 5) +} + +func TestSelect4FromPairConstGrouped(t *testing.T) { + x := archsimd.LoadFloat32x8([]float32{0, 1, 2, 3, 10, 11, 12, 13}) + y := archsimd.LoadFloat32x8([]float32{4, 5, 6, 7, 14, 15, 16, 17}) + + llll := x.ConcatPermuteScalarsGrouped(0, 1, 2, 3, y) + hhhh := x.ConcatPermuteScalarsGrouped(4, 5, 6, 7, y) + llhh := x.ConcatPermuteScalarsGrouped(0, 1, 6, 7, y) + hhll := x.ConcatPermuteScalarsGrouped(6, 7, 0, 1, y) + + lllh := x.ConcatPermuteScalarsGrouped(0, 1, 2, 7, y) + llhl := x.ConcatPermuteScalarsGrouped(0, 1, 7, 2, y) + lhll := x.ConcatPermuteScalarsGrouped(0, 7, 1, 2, y) + hlll := x.ConcatPermuteScalarsGrouped(7, 0, 1, 2, y) + + hhhl := x.ConcatPermuteScalarsGrouped(4, 5, 6, 0, y) + hhlh := x.ConcatPermuteScalarsGrouped(4, 5, 0, 6, y) + hlhh := x.ConcatPermuteScalarsGrouped(4, 0, 5, 6, y) + lhhh := x.ConcatPermuteScalarsGrouped(0, 4, 5, 6, y) + + lhlh := x.ConcatPermuteScalarsGrouped(0, 4, 1, 5, y) + hlhl := x.ConcatPermuteScalarsGrouped(4, 0, 5, 1, y) + lhhl := x.ConcatPermuteScalarsGrouped(0, 4, 5, 1, y) + hllh := x.ConcatPermuteScalarsGrouped(4, 0, 1, 5, y) + + r := make([]float32, 8, 8) + + foo := func(v archsimd.Float32x8, a, b, c, d float32) { + v.Store(r) + checkSlices[float32](t, r, []float32{a, b, c, d, 10 + a, 10 + b, 10 + c, 10 + d}) + } + + foo(llll, 0, 1, 2, 3) + foo(hhhh, 4, 5, 6, 7) + foo(llhh, 0, 1, 6, 7) + foo(hhll, 6, 7, 0, 1) + + foo(lllh, 0, 1, 2, 7) + foo(llhl, 0, 1, 7, 2) + foo(lhll, 0, 7, 1, 2) + foo(hlll, 7, 0, 1, 2) + + foo(hhhl, 4, 5, 6, 0) + foo(hhlh, 4, 5, 0, 6) + foo(hlhh, 4, 0, 5, 6) + foo(lhhh, 0, 4, 5, 6) + + foo(lhlh, 0, 4, 1, 5) + foo(hlhl, 4, 0, 5, 1) + foo(lhhl, 0, 4, 5, 1) + foo(hllh, 4, 0, 1, 5) +} + +func TestConcatPermuteScalarsConstGroupedUint32x16(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + x := archsimd.LoadUint32x16([]uint32{0, 1, 2, 3, 10, 11, 12, 13, 20, 21, 22, 23, 30, 31, 32, 33}) + y := archsimd.LoadUint32x16([]uint32{4, 5, 6, 7, 14, 15, 16, 17, 24, 25, 26, 27, 34, 35, 36, 37}) + + llll := x.ConcatPermuteScalarsGrouped(0, 1, 2, 3, y) + hhhh := x.ConcatPermuteScalarsGrouped(4, 5, 6, 7, y) + llhh := x.ConcatPermuteScalarsGrouped(0, 1, 6, 7, y) + hhll := x.ConcatPermuteScalarsGrouped(6, 7, 0, 1, y) + + lllh := x.ConcatPermuteScalarsGrouped(0, 1, 2, 7, y) + llhl := x.ConcatPermuteScalarsGrouped(0, 1, 7, 2, y) + lhll := x.ConcatPermuteScalarsGrouped(0, 7, 1, 2, y) + hlll := x.ConcatPermuteScalarsGrouped(7, 0, 1, 2, y) + + hhhl := x.ConcatPermuteScalarsGrouped(4, 5, 6, 0, y) + hhlh := x.ConcatPermuteScalarsGrouped(4, 5, 0, 6, y) + hlhh := x.ConcatPermuteScalarsGrouped(4, 0, 5, 6, y) + lhhh := x.ConcatPermuteScalarsGrouped(0, 4, 5, 6, y) + + lhlh := x.ConcatPermuteScalarsGrouped(0, 4, 1, 5, y) + hlhl := x.ConcatPermuteScalarsGrouped(4, 0, 5, 1, y) + lhhl := x.ConcatPermuteScalarsGrouped(0, 4, 5, 1, y) + hllh := x.ConcatPermuteScalarsGrouped(4, 0, 1, 5, y) + + r := make([]uint32, 16, 16) + + foo := func(v archsimd.Uint32x16, a, b, c, d uint32) { + v.Store(r) + checkSlices[uint32](t, r, []uint32{a, b, c, d, + 10 + a, 10 + b, 10 + c, 10 + d, + 20 + a, 20 + b, 20 + c, 20 + d, + 30 + a, 30 + b, 30 + c, 30 + d, + }) + } + + foo(llll, 0, 1, 2, 3) + foo(hhhh, 4, 5, 6, 7) + foo(llhh, 0, 1, 6, 7) + foo(hhll, 6, 7, 0, 1) + + foo(lllh, 0, 1, 2, 7) + foo(llhl, 0, 1, 7, 2) + foo(lhll, 0, 7, 1, 2) + foo(hlll, 7, 0, 1, 2) + + foo(hhhl, 4, 5, 6, 0) + foo(hhlh, 4, 5, 0, 6) + foo(hlhh, 4, 0, 5, 6) + foo(lhhh, 0, 4, 5, 6) + + foo(lhlh, 0, 4, 1, 5) + foo(hlhl, 4, 0, 5, 1) + foo(lhhl, 0, 4, 5, 1) + foo(hllh, 4, 0, 1, 5) +} + +func TestConcatPermute128Scalars(t *testing.T) { + x := archsimd.LoadUint64x4([]uint64{0, 1, 2, 3}) + y := archsimd.LoadUint64x4([]uint64{4, 5, 6, 7}) + + aa := x.ConcatPermute128Scalars(0, 0, y) + ab := x.ConcatPermute128Scalars(0, 1, y) + bc := x.ConcatPermute128Scalars(1, 2, y) + cd := x.ConcatPermute128Scalars(2, 3, y) + da := x.ConcatPermute128Scalars(3, 0, y) + dc := x.ConcatPermute128Scalars(3, 2, y) + + r := make([]uint64, 4, 4) + + foo := func(v archsimd.Uint64x4, a, b uint64) { + a, b = 2*a, 2*b + v.Store(r) + checkSlices[uint64](t, r, []uint64{a, a + 1, b, b + 1}) + } + + foo(aa, 0, 0) + foo(ab, 0, 1) + foo(bc, 1, 2) + foo(cd, 2, 3) + foo(da, 3, 0) + foo(dc, 3, 2) +} + +func TestConcatPermute128ScalarsError(t *testing.T) { + x := archsimd.LoadUint64x4([]uint64{0, 1, 2, 3}) + y := archsimd.LoadUint64x4([]uint64{4, 5, 6, 7}) + + defer func() { + if r := recover(); r != nil { + t.Logf("Saw expected panic %v", r) + } + }() + _ = x.ConcatPermute128Scalars(0, 4, y) + + t.Errorf("Should have panicked") +} + +//go:noinline +func select128FromPair(x archsimd.Uint64x4, lo, hi uint8, y archsimd.Uint64x4) archsimd.Uint64x4 { + return x.ConcatPermute128Scalars(lo, hi, y) +} + +func TestConcatPermute128ScalarsVar(t *testing.T) { + x := archsimd.LoadUint64x4([]uint64{0, 1, 2, 3}) + y := archsimd.LoadUint64x4([]uint64{4, 5, 6, 7}) + + aa := select128FromPair(x, 0, 0, y) + ab := select128FromPair(x, 0, 1, y) + bc := select128FromPair(x, 1, 2, y) + cd := select128FromPair(x, 2, 3, y) + da := select128FromPair(x, 3, 0, y) + dc := select128FromPair(x, 3, 2, y) + + r := make([]uint64, 4, 4) + + foo := func(v archsimd.Uint64x4, a, b uint64) { + a, b = 2*a, 2*b + v.Store(r) + checkSlices[uint64](t, r, []uint64{a, a + 1, b, b + 1}) + } + + foo(aa, 0, 0) + foo(ab, 0, 1) + foo(bc, 1, 2) + foo(cd, 2, 3) + foo(da, 3, 0) + foo(dc, 3, 2) +} + +func TestSelect2FromPairConst(t *testing.T) { + x := archsimd.LoadUint64x2([]uint64{0, 1}) + y := archsimd.LoadUint64x2([]uint64{2, 3}) + + ll := x.ConcatPermuteScalars(0, 1, y) + hh := x.ConcatPermuteScalars(3, 2, y) + lh := x.ConcatPermuteScalars(0, 3, y) + hl := x.ConcatPermuteScalars(2, 1, y) + + r := make([]uint64, 2, 2) + + foo := func(v archsimd.Uint64x2, a, b uint64) { + v.Store(r) + checkSlices[uint64](t, r, []uint64{a, b}) + } + + foo(ll, 0, 1) + foo(hh, 3, 2) + foo(lh, 0, 3) + foo(hl, 2, 1) +} + +func TestSelect2FromPairConstGroupedUint(t *testing.T) { + x := archsimd.LoadUint64x4([]uint64{0, 1, 10, 11}) + y := archsimd.LoadUint64x4([]uint64{2, 3, 12, 13}) + + ll := x.ConcatPermuteScalarsGrouped(0, 1, y) + hh := x.ConcatPermuteScalarsGrouped(3, 2, y) + lh := x.ConcatPermuteScalarsGrouped(0, 3, y) + hl := x.ConcatPermuteScalarsGrouped(2, 1, y) + + r := make([]uint64, 4, 4) + + foo := func(v archsimd.Uint64x4, a, b uint64) { + v.Store(r) + checkSlices[uint64](t, r, []uint64{a, b, a + 10, b + 10}) + } + + foo(ll, 0, 1) + foo(hh, 3, 2) + foo(lh, 0, 3) + foo(hl, 2, 1) +} + +func TestSelect2FromPairConstGroupedFloat(t *testing.T) { + x := archsimd.LoadFloat64x4([]float64{0, 1, 10, 11}) + y := archsimd.LoadFloat64x4([]float64{2, 3, 12, 13}) + + ll := x.ConcatPermuteScalarsGrouped(0, 1, y) + hh := x.ConcatPermuteScalarsGrouped(3, 2, y) + lh := x.ConcatPermuteScalarsGrouped(0, 3, y) + hl := x.ConcatPermuteScalarsGrouped(2, 1, y) + + r := make([]float64, 4, 4) + + foo := func(v archsimd.Float64x4, a, b float64) { + v.Store(r) + checkSlices[float64](t, r, []float64{a, b, a + 10, b + 10}) + } + + foo(ll, 0, 1) + foo(hh, 3, 2) + foo(lh, 0, 3) + foo(hl, 2, 1) +} + +func TestSelect2FromPairConstGroupedInt(t *testing.T) { + x := archsimd.LoadInt64x4([]int64{0, 1, 10, 11}) + y := archsimd.LoadInt64x4([]int64{2, 3, 12, 13}) + + ll := x.ConcatPermuteScalarsGrouped(0, 1, y) + hh := x.ConcatPermuteScalarsGrouped(3, 2, y) + lh := x.ConcatPermuteScalarsGrouped(0, 3, y) + hl := x.ConcatPermuteScalarsGrouped(2, 1, y) + + r := make([]int64, 4, 4) + + foo := func(v archsimd.Int64x4, a, b int64) { + v.Store(r) + checkSlices[int64](t, r, []int64{a, b, a + 10, b + 10}) + } + + foo(ll, 0, 1) + foo(hh, 3, 2) + foo(lh, 0, 3) + foo(hl, 2, 1) +} + +func TestSelect2FromPairConstGroupedInt512(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + + x := archsimd.LoadInt64x8([]int64{0, 1, 10, 11, 20, 21, 30, 31}) + y := archsimd.LoadInt64x8([]int64{2, 3, 12, 13, 22, 23, 32, 33}) + + ll := x.ConcatPermuteScalarsGrouped(0, 1, y) + hh := x.ConcatPermuteScalarsGrouped(3, 2, y) + lh := x.ConcatPermuteScalarsGrouped(0, 3, y) + hl := x.ConcatPermuteScalarsGrouped(2, 1, y) + + r := make([]int64, 8, 8) + + foo := func(v archsimd.Int64x8, a, b int64) { + v.Store(r) + checkSlices[int64](t, r, []int64{a, b, a + 10, b + 10, a + 20, b + 20, a + 30, b + 30}) + } + + foo(ll, 0, 1) + foo(hh, 3, 2) + foo(lh, 0, 3) + foo(hl, 2, 1) +} + +func TestStringAMD64(t *testing.T) { + x := archsimd.LoadUint32x4([]uint32{0, 1, 2, 3}) + y := archsimd.LoadInt64x4([]int64{-4, -5, -6, -7}) + z := archsimd.LoadFloat32x4([]float32{0.5, 1.5, -2.5, 3.5e9}) + w := archsimd.LoadFloat64x4([]float64{0.5, 1.5, -2.5, 3.5e9}) + + sx := "{0,1,2,3}" + sy := "{-4,-5,-6,-7}" + sz := "{0.5,1.5,-2.5,3.5e+09}" + sw := sz + + if x.String() != sx { + t.Errorf("x=%s wanted %s", x, sx) + } + if y.String() != sy { + t.Errorf("y=%s wanted %s", y, sy) + } + if z.String() != sz { + t.Errorf("z=%s wanted %s", z, sz) + } + if w.String() != sw { + t.Errorf("w=%s wanted %s", w, sw) + } + t.Logf("w=%s", w) + t.Logf("x=%s", x) + t.Logf("y=%s", y) + t.Logf("z=%s", z) +} + +func TestMaskString(t *testing.T) { + x := archsimd.LoadUint32x4([]uint32{0, 1, 2, 3}) + var y archsimd.Uint32x4 + + m := x.Equal(y) + + w := "{1,0,0,0}" + + if g := m.String(); g != w { + t.Errorf("got=%s wanted %s", g, w) + } +} + +// a returns an slice of 16 int32 +func a() []int32 { + return make([]int32, 16, 16) +} + +// applyTo3 returns a 16-element slice of the results of +// applying f to the respective elements of vectors x, y, and z. +func applyTo3(x, y, z archsimd.Int32x16, f func(x, y, z int32) int32) []int32 { + ax, ay, az := a(), a(), a() + x.Store(ax) + y.Store(ay) + z.Store(az) + + r := a() + for i := range r { + r[i] = f(ax[i], ay[i], az[i]) + } + return r +} + +// applyTo4 returns a 16-element slice of the results of +// applying f to the respective elements of vectors x, y, z, and w. +func applyTo4(x, y, z, w archsimd.Int32x16, f func(x, y, z, w int32) int32) []int32 { + ax, ay, az, aw := a(), a(), a(), a() + x.Store(ax) + y.Store(ay) + z.Store(az) + w.Store(aw) + + r := make([]int32, len(ax), len(ax)) + for i := range r { + r[i] = f(ax[i], ay[i], az[i], aw[i]) + } + return r +} + +func TestSelectTernOptInt32x16(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + return + } + ax := []int32{0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1} + ay := []int32{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1} + az := []int32{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1} + aw := []int32{0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1} + am := []int32{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + + x := archsimd.LoadInt32x16(ax) + y := archsimd.LoadInt32x16(ay) + z := archsimd.LoadInt32x16(az) + w := archsimd.LoadInt32x16(aw) + m := archsimd.LoadInt32x16(am) + + foo := func(v archsimd.Int32x16, s []int32) { + r := make([]int32, 16, 16) + v.Store(r) + checkSlices[int32](t, r, s) + } + + t0 := w.Xor(y).Xor(z) + ft0 := func(w, y, z int32) int32 { + return w ^ y ^ z + } + foo(t0, applyTo3(w, y, z, ft0)) + + t1 := m.And(w.Xor(y).Xor(z.Not())) + ft1 := func(m, w, y, z int32) int32 { + return m & (w ^ y ^ ^z) + } + foo(t1, applyTo4(m, w, y, z, ft1)) + + t2 := x.Xor(y).Xor(z).And(x.Xor(y).Xor(z.Not())) + ft2 := func(x, y, z int32) int32 { + return (x ^ y ^ z) & (x ^ y ^ ^z) + } + foo(t2, applyTo3(x, y, z, ft2)) +} + +func TestMaskedMerge(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + x := archsimd.LoadInt64x4([]int64{1, 2, 3, 4}) + y := archsimd.LoadInt64x4([]int64{5, 6, 1, 1}) + z := archsimd.LoadInt64x4([]int64{-1, -2, -3, -4}) + res := make([]int64, 4) + expected := []int64{6, 8, -3, -4} + mask := x.Less(y) + if archsimd.X86.AVX512() { + x.Add(y).Merge(z, mask).Store(res) + } else { + x.Add(y).Merge(z, mask).Store(res) + } + for i := range 4 { + if res[i] != expected[i] { + t.Errorf("got %d wanted %d", res[i], expected[i]) + } + } +} + +func TestMaskedIfElse(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + x := archsimd.LoadInt64x4([]int64{1, 2, 3, 4}) + y := archsimd.LoadInt64x4([]int64{5, 6, 1, 1}) + z := archsimd.LoadInt64x4([]int64{-1, -2, -3, -4}) + res := make([]int64, 4) + expected := []int64{6, 8, -3, -4} + mask := x.Less(y) + if archsimd.X86.AVX512() { + x.Add(y).IfElse(mask, z).Store(res) + } else { + x.Add(y).IfElse(mask, z).Store(res) + } + for i := range 4 { + if res[i] != expected[i] { + t.Errorf("got %d wanted %d", res[i], expected[i]) + } + } +} + +func TestPermuteScalars(t *testing.T) { + x := []int32{11, 12, 13, 14} + want := []int32{12, 13, 14, 11} + got := make([]int32, 4) + archsimd.LoadInt32x4(x).PermuteScalars(1, 2, 3, 0).Store(got) + checkSlices(t, got, want) +} + +func TestPermuteScalarsGrouped(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + x := []int32{11, 12, 13, 14, 21, 22, 23, 24} + want := []int32{12, 13, 14, 11, 22, 23, 24, 21} + got := make([]int32, 8) + archsimd.LoadInt32x8(x).PermuteScalarsGrouped(1, 2, 3, 0).Store(got) + checkSlices(t, got, want) +} + +func TestPermuteScalarsHi(t *testing.T) { + x := []int16{-1, -2, -3, -4, 11, 12, 13, 14} + want := []int16{-1, -2, -3, -4, 12, 13, 14, 11} + got := make([]int16, len(x)) + archsimd.LoadInt16x8(x).PermuteScalarsHi(1, 2, 3, 0).Store(got) + checkSlices(t, got, want) +} + +func TestPermuteScalarsLo(t *testing.T) { + x := []int16{11, 12, 13, 14, 4, 5, 6, 7} + want := []int16{12, 13, 14, 11, 4, 5, 6, 7} + got := make([]int16, len(x)) + archsimd.LoadInt16x8(x).PermuteScalarsLo(1, 2, 3, 0).Store(got) + checkSlices(t, got, want) +} + +func TestPermuteScalarsHiGrouped(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + x := []int16{-1, -2, -3, -4, 11, 12, 13, 14, -11, -12, -13, -14, 111, 112, 113, 114} + want := []int16{-1, -2, -3, -4, 12, 13, 14, 11, -11, -12, -13, -14, 112, 113, 114, 111} + got := make([]int16, len(x)) + archsimd.LoadInt16x16(x).PermuteScalarsHiGrouped(1, 2, 3, 0).Store(got) + checkSlices(t, got, want) +} + +func TestPermuteScalarsLoGrouped(t *testing.T) { + if !archsimd.X86.AVX2() { + t.Skip("Test requires X86.AVX2, not available on this hardware") + return + } + x := []int16{11, 12, 13, 14, 4, 5, 6, 7, 111, 112, 113, 114, 14, 15, 16, 17} + want := []int16{12, 13, 14, 11, 4, 5, 6, 7, 112, 113, 114, 111, 14, 15, 16, 17} + got := make([]int16, len(x)) + archsimd.LoadInt16x16(x).PermuteScalarsLoGrouped(1, 2, 3, 0).Store(got) + checkSlices(t, got, want) +} + +func TestClMul(t *testing.T) { + var x = archsimd.LoadUint64x2([]uint64{1, 5}) + var y = archsimd.LoadUint64x2([]uint64{3, 9}) + + foo := func(v archsimd.Uint64x2, s []uint64) { + r := make([]uint64, 2, 2) + v.Store(r) + checkSlices[uint64](t, r, s) + } + + foo(x.CarrylessMultiplyEven(y), []uint64{3, 0}) + foo(x.CarrylessMultiplyEvenOdd(y), []uint64{9, 0}) + foo(x.CarrylessMultiplyOddEven(y), []uint64{15, 0}) + foo(x.CarrylessMultiplyOdd(y), []uint64{45, 0}) + foo(y.CarrylessMultiplyEven(y), []uint64{5, 0}) + +} + +func addPairsSlice[T number](a, b []T) []T { + r := make([]T, len(a)) + for i := range len(a) / 2 { + r[i] = a[2*i] + a[2*i+1] + r[i+len(a)/2] = b[2*i] + b[2*i+1] + } + return r +} + +func subPairsSlice[T number](a, b []T) []T { + r := make([]T, len(a)) + for i := range len(a) / 2 { + r[i] = a[2*i] - a[2*i+1] + r[i+len(a)/2] = b[2*i] - b[2*i+1] + } + return r +} + +func addPairsGroupedSlice[T number](a, b []T) []T { + group := int(128 / unsafe.Sizeof(a[0])) + r := make([]T, 0, len(a)) + for i := range len(a) / group { + r = append(r, addPairsSlice(a[i*group:(i+1)*group], b[i*group:(i+1)*group])...) + } + return r +} + +func subPairsGroupedSlice[T number](a, b []T) []T { + group := int(128 / unsafe.Sizeof(a[0])) + r := make([]T, 0, len(a)) + for i := range len(a) / group { + r = append(r, subPairsSlice(a[i*group:(i+1)*group], b[i*group:(i+1)*group])...) + } + return r +} + +func TestAddSubPairs(t *testing.T) { + testInt16x8Binary(t, archsimd.Int16x8.ConcatAddPairs, addPairsSlice[int16]) + testInt16x8Binary(t, archsimd.Int16x8.ConcatSubPairs, subPairsSlice[int16]) + testUint16x8Binary(t, archsimd.Uint16x8.ConcatAddPairs, addPairsSlice[uint16]) + testUint16x8Binary(t, archsimd.Uint16x8.ConcatSubPairs, subPairsSlice[uint16]) + testInt32x4Binary(t, archsimd.Int32x4.ConcatAddPairs, addPairsSlice[int32]) + testInt32x4Binary(t, archsimd.Int32x4.ConcatSubPairs, subPairsSlice[int32]) + testUint32x4Binary(t, archsimd.Uint32x4.ConcatAddPairs, addPairsSlice[uint32]) + testUint32x4Binary(t, archsimd.Uint32x4.ConcatSubPairs, subPairsSlice[uint32]) + testFloat32x4Binary(t, archsimd.Float32x4.ConcatAddPairs, addPairsSlice[float32]) + testFloat32x4Binary(t, archsimd.Float32x4.ConcatSubPairs, subPairsSlice[float32]) + testFloat64x2Binary(t, archsimd.Float64x2.ConcatAddPairs, addPairsSlice[float64]) + testFloat64x2Binary(t, archsimd.Float64x2.ConcatSubPairs, subPairsSlice[float64]) + + // Grouped versions + if archsimd.X86.AVX2() { + testInt16x16Binary(t, archsimd.Int16x16.ConcatAddPairsGrouped, addPairsGroupedSlice[int16]) + testInt16x16Binary(t, archsimd.Int16x16.ConcatSubPairsGrouped, subPairsGroupedSlice[int16]) + testUint16x16Binary(t, archsimd.Uint16x16.ConcatAddPairsGrouped, addPairsGroupedSlice[uint16]) + testUint16x16Binary(t, archsimd.Uint16x16.ConcatSubPairsGrouped, subPairsGroupedSlice[uint16]) + testInt32x8Binary(t, archsimd.Int32x8.ConcatAddPairsGrouped, addPairsGroupedSlice[int32]) + testInt32x8Binary(t, archsimd.Int32x8.ConcatSubPairsGrouped, subPairsGroupedSlice[int32]) + testUint32x8Binary(t, archsimd.Uint32x8.ConcatAddPairsGrouped, addPairsGroupedSlice[uint32]) + testUint32x8Binary(t, archsimd.Uint32x8.ConcatSubPairsGrouped, subPairsGroupedSlice[uint32]) + testFloat32x8Binary(t, archsimd.Float32x8.ConcatAddPairsGrouped, addPairsGroupedSlice[float32]) + testFloat32x8Binary(t, archsimd.Float32x8.ConcatSubPairsGrouped, subPairsGroupedSlice[float32]) + testFloat64x4Binary(t, archsimd.Float64x4.ConcatAddPairsGrouped, addPairsGroupedSlice[float64]) + testFloat64x4Binary(t, archsimd.Float64x4.ConcatSubPairsGrouped, subPairsGroupedSlice[float64]) + } +} + +func convConcatSlice[T, U number](a, b []T, conv func(T) U) []U { + r := make([]U, len(a)+len(b)) + for i, v := range a { + r[i] = conv(v) + } + for i, v := range b { + r[len(a)+i] = conv(v) + } + return r +} + +func convConcatGroupedSlice[T, U number](a, b []T, conv func(T) U) []U { + group := int(128 / unsafe.Sizeof(a[0])) + r := make([]U, 0, len(a)+len(b)) + for i := 0; i < len(a)/group; i++ { + r = append(r, convConcatSlice(a[i*group:(i+1)*group], b[i*group:(i+1)*group], conv)...) + } + return r +} + +func TestSaturateConcat(t *testing.T) { + // Int32x4.SaturateToInt16Concat + forSlicePair(t, int32s, 4, func(x, y []int32) bool { + a, b := archsimd.LoadInt32x4(x), archsimd.LoadInt32x4(y) + var out [8]int16 + a.SaturateToInt16Concat(b).StoreArray(&out) + want := convConcatSlice(x, y, satToInt16) + return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) + }) + // Int32x4.SaturateToUint16Concat + forSlicePair(t, int32s, 4, func(x, y []int32) bool { + a, b := archsimd.LoadInt32x4(x), archsimd.LoadInt32x4(y) + var out [8]uint16 + a.SaturateToUint16Concat(b).StoreArray(&out) + want := convConcatSlice(x, y, satToUint16) + return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) + }) + + if archsimd.X86.AVX2() { + // Int32x8.SaturateToInt16ConcatGrouped + forSlicePair(t, int32s, 8, func(x, y []int32) bool { + a, b := archsimd.LoadInt32x8(x), archsimd.LoadInt32x8(y) + var out [16]int16 + a.SaturateToInt16ConcatGrouped(b).StoreArray(&out) + want := convConcatGroupedSlice(x, y, satToInt16) + return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) + }) + // Int32x8.SaturateToUint16ConcatGrouped + forSlicePair(t, int32s, 8, func(x, y []int32) bool { + a, b := archsimd.LoadInt32x8(x), archsimd.LoadInt32x8(y) + var out [16]uint16 + a.SaturateToUint16ConcatGrouped(b).StoreArray(&out) + want := convConcatGroupedSlice(x, y, satToUint16) + return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) + }) + } + + if archsimd.X86.AVX512() { + // Int32x16.SaturateToInt16ConcatGrouped + forSlicePair(t, int32s, 16, func(x, y []int32) bool { + a, b := archsimd.LoadInt32x16(x), archsimd.LoadInt32x16(y) + var out [32]int16 + a.SaturateToInt16ConcatGrouped(b).StoreArray(&out) + want := convConcatGroupedSlice(x, y, satToInt16) + return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) + }) + // Int32x16.SaturateToUint16ConcatGrouped + forSlicePair(t, int32s, 16, func(x, y []int32) bool { + a, b := archsimd.LoadInt32x16(x), archsimd.LoadInt32x16(y) + var out [32]uint16 + a.SaturateToUint16ConcatGrouped(b).StoreArray(&out) + want := convConcatGroupedSlice(x, y, satToUint16) + return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) + }) + } +} + +func testMaskOr8x64(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int8, 64) + want := []int8{-1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, + -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, + -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, + -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1} + var a archsimd.Int8x64 + b := archsimd.LoadInt8x64(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt8x64() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr16x32(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int16, 32) + want := []int16{-1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, + -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1} + var a archsimd.Int16x32 + b := archsimd.LoadInt16x32(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt16x32() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr32x16(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int32, 16) + want := []int32{-1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1} + var a archsimd.Int32x16 + b := archsimd.LoadInt32x16(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt32x16() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr64x8(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int64, 8) + want := []int64{-1, 0, 0, 0, 0, 0, -1, -1} + var a archsimd.Int64x8 + b := archsimd.LoadInt64x8(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt64x8() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr8x32(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int8, 32) + want := []int8{-1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, + -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1} + var a archsimd.Int8x32 + b := archsimd.LoadInt8x32(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt8x32() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr16x16(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int16, 16) + want := []int16{-1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1} + var a archsimd.Int16x16 + b := archsimd.LoadInt16x16(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt16x16() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr32x8(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int32, 8) + want := []int32{-1, 0, 0, 0, 0, 0, -1, -1} + var a archsimd.Int32x8 + b := archsimd.LoadInt32x8(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt32x8() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr64x4(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int64, 4) + want := []int64{-1, 0, 0, -1} + var a archsimd.Int64x4 + b := archsimd.LoadInt64x4(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt64x4() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr8x16(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int8, 16) + want := []int8{-1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1} + var a archsimd.Int8x16 + b := archsimd.LoadInt8x16(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt8x16() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr16x8(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int16, 8) + want := []int16{-1, 0, 0, 0, 0, 0, -1, -1} + var a archsimd.Int16x8 + b := archsimd.LoadInt16x8(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt16x8() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr32x4(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int32, 4) + want := []int32{-1, 0, 0, -1} + var a archsimd.Int32x4 + b := archsimd.LoadInt32x4(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt32x4() + c.Store(s) + checkSlices(t, s, want) +} + +func testMaskOr64x2(t *testing.T) { + if !archsimd.X86.AVX512() { + return // compiler needs to see check+return to ensure mask register use + } + s := make([]int64, 2) + want := []int64{-1, 0} + var a archsimd.Int64x2 + b := archsimd.LoadInt64x2(want) + m1 := a.Less(a) + m2 := b.Less(a) + m3 := m1.Or(m2) + c := m3.ToInt64x2() + c.Store(s) + checkSlices(t, s, want) +} + +func TestMaskOr(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Test requires X86.AVX512, not available on this hardware") + } + testMaskOr8x64(t) + testMaskOr16x32(t) + testMaskOr32x16(t) + testMaskOr64x8(t) + testMaskOr8x32(t) + testMaskOr16x16(t) + testMaskOr32x8(t) + testMaskOr64x4(t) + testMaskOr8x16(t) + testMaskOr16x8(t) + testMaskOr32x4(t) + testMaskOr64x2(t) +} diff --git a/src/simd/archsimd/internal/simd_test/simd_arm64_test.go b/src/simd/archsimd/internal/simd_test/simd_arm64_test.go new file mode 100644 index 0000000000000000000000000000000000000000..5a779b1831e323ab72ce6649b65996eb44082e16 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/simd_arm64_test.go @@ -0,0 +1,39 @@ +// 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 && arm64 + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +func TestLookupOrZero(t *testing.T) { + // Out-of-range indices produce zero lane value. + x := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + indices := []uint8{7, 6, 5, 4, 3, 2, 1, 0, 0xff, 8, 16, 9, 128, 10, 20, 11} + want := []uint8{8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 0, 10, 0, 11, 0, 12} + got := make([]uint8, len(x)) + archsimd.LoadUint8x16(x).LookupOrZero(archsimd.LoadUint8x16(indices)).Store(got) + checkSlices(t, got, want) +} + +func TestClMul(t *testing.T) { + var x = archsimd.LoadUint64x2([]uint64{1, 5}) + var y = archsimd.LoadUint64x2([]uint64{3, 9}) + + foo := func(v archsimd.Uint64x2, s []uint64) { + r := make([]uint64, 2, 2) + v.Store(r) + checkSlices[uint64](t, r, s) + } + + foo(x.CarrylessMultiplyEven(y), []uint64{3, 0}) + foo(x.CarrylessMultiplyEvenOdd(y), []uint64{9, 0}) + foo(x.CarrylessMultiplyOddEven(y), []uint64{15, 0}) + foo(x.CarrylessMultiplyOdd(y), []uint64{45, 0}) + foo(y.CarrylessMultiplyEven(y), []uint64{5, 0}) +} diff --git a/src/simd/archsimd/internal/simd_test/simd_test.go b/src/simd/archsimd/internal/simd_test/simd_test.go index b23ba1341872058d4895f23aa17107a26b155493..47cf989996346afa6551b23344a6ebf8872e16dd 100644 --- a/src/simd/archsimd/internal/simd_test/simd_test.go +++ b/src/simd/archsimd/internal/simd_test/simd_test.go @@ -2,59 +2,42 @@ // Copyright 2025 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 && amd64 +//go:build goexperiment.simd && (amd64 || wasm || arm64) package simd_test import ( - "fmt" - "os" "reflect" "simd/archsimd" - "slices" "testing" - "unsafe" ) -func TestMain(m *testing.M) { - if !archsimd.X86.AVX() { - fmt.Fprintln(os.Stderr, "Skipping tests: AVX is not available") - os.Exit(0) - } - os.Exit(m.Run()) -} - var sink any func TestType(t *testing.T) { // Testing: // - Defined as another struct's field is ok // - Pointer is ok - // - Type defition is ok + // - Type definition is ok // - Type alias is ok // - Type conversion is ok // - Conversion to interface is ok type alias = archsimd.Int32x4 - type maskT archsimd.Mask32x4 + type vecT archsimd.Int32x4 type myStruct struct { x alias y *archsimd.Int32x4 - z maskT + z vecT } vals := [4]int32{1, 2, 3, 4} v := myStruct{x: archsimd.LoadInt32x4Array(&vals)} - // masking elements 1 and 2. - want := []int32{2, 4, 0, 0} + want := []int32{12, 24, 36, 48} y := archsimd.LoadInt32x4Array(&vals) v.y = &y sink = y - if !archsimd.X86.AVX512GFNI() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - v.z = maskT(archsimd.Mask32x4FromBits(0b0011)) - *v.y = v.y.Add(v.x).Masked(archsimd.Mask32x4(v.z)) + v.z = vecT(archsimd.LoadInt32x4Array(&[4]int32{10, 20, 30, 40})) + *v.y = v.y.Add(v.x).Add(archsimd.Int32x4(v.z)) got := [4]int32{} v.y.StoreArray(&got) @@ -110,14 +93,10 @@ checkSlices(t, got[:], want) } func TestVectorConversion(t *testing.T) { - if !archsimd.X86.AVX512GFNI() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } xv := [4]int32{1, 2, 3, 4} x := archsimd.LoadInt32x4Array(&xv) - xPromoted := x.AsInt64x2() - xPromotedDemoted := xPromoted.AsInt32x4() + xPromoted := x.ToBits().ReshapeToUint64s().BitsToInt64() + xPromotedDemoted := xPromoted.ToBits().ReshapeToUint32s().BitsToInt32() got := [4]int32{} xPromotedDemoted.StoreArray(&got) for i := range 4 { @@ -128,10 +107,6 @@ } } func TestMaskConversion(t *testing.T) { - if !archsimd.X86.AVX512GFNI() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } x := archsimd.LoadInt32x4([]int32{5, 0, 7, 0}) mask := archsimd.Int32x4{}.Sub(x).ToMask() y := archsimd.LoadInt32x4([]int32{1, 2, 3, 4}).Add(x).Masked(mask) @@ -141,1080 +116,78 @@ y.Store(got) checkSlices(t, got[:], want[:]) } -func TestPermute(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - x := []int64{1, 2, 3, 4, 5, 6, 7, 8} - indices := []uint64{7, 6, 5, 4, 3, 2, 1, 0} - want := []int64{8, 7, 6, 5, 4, 3, 2, 1} - got := make([]int64, 8) - archsimd.LoadInt64x8(x).Permute(archsimd.LoadUint64x8(indices)).Store(got) - checkSlices(t, got, want) -} - -func TestPermuteOrZero(t *testing.T) { - x := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - indices := []int8{7, 6, 5, 4, 3, 2, 1, 0, -1, 8, -1, 9, -1, 10, -1, 11} - want := []uint8{8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 0, 10, 0, 11, 0, 12} - got := make([]uint8, len(x)) - archsimd.LoadUint8x16(x).PermuteOrZero(archsimd.LoadInt8x16(indices)).Store(got) - checkSlices(t, got, want) -} - -func TestConcatPermute(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - x := []int64{1, 2, 3, 4, 5, 6, 7, 8} - y := []int64{-1, -2, -3, -4, -5, -6, -7, -8} - indices := []uint64{7 + 8, 6, 5 + 8, 4, 3 + 8, 2, 1 + 8, 0} - want := []int64{-8, 7, -6, 5, -4, 3, -2, 1} - got := make([]int64, 8) - archsimd.LoadInt64x8(x).ConcatPermute(archsimd.LoadInt64x8(y), archsimd.LoadUint64x8(indices)).Store(got) - checkSlices(t, got, want) -} - -func TestCompress(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - v1234 := archsimd.LoadInt32x4([]int32{1, 2, 3, 4}) - v2400 := v1234.Compress(archsimd.Mask32x4FromBits(0b1010)) - got := make([]int32, 4) - v2400.Store(got) - want := []int32{2, 4, 0, 0} - if !slices.Equal(got, want) { - t.Errorf("want and got differ, want=%v, got=%v", want, got) - } -} - -func TestExpand(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - v3400 := archsimd.LoadInt32x4([]int32{3, 4, 0, 0}) - v2400 := v3400.Expand(archsimd.Mask32x4FromBits(0b1010)) - got := make([]int32, 4) - v2400.Store(got) - want := []int32{0, 3, 0, 4} - if !slices.Equal(got, want) { - t.Errorf("want and got differ, want=%v, got=%v", want, got) - } -} - -func TestSlicesInt8(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} - v := archsimd.LoadInt8x32(a) - b := make([]int8, 32, 32) - v.Store(b) - checkSlices(t, a, b) -} - -func TestSlicesInt8SetElem(t *testing.T) { - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} - v := archsimd.LoadInt8x16(a) - - v = v.SetElem(3, 13) - a[3] = 13 - - b := make([]int8, 16, 16) - v.Store(b) - checkSlices(t, a, b) -} - -func TestSlicesInt8GetElem(t *testing.T) { - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} - v := archsimd.LoadInt8x16(a) - e := v.GetElem(2) - if e != a[2] { - t.Errorf("GetElem(2) = %d != a[2] = %d", e, a[2]) - } - -} - -var seventeen = uint8(17) - -func TestSlicesInt8GetElem16(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Logf("Saw EXPECTED panic %v", r) - } else { - t.Errorf("Did not see expected panic") - } - }() - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - v := archsimd.LoadInt8x16(a) - e := v.GetElem(seventeen - 1) - t.Errorf("Should have panicked, e=%v", e) -} - -func TestSlicesInt8GetElem16const(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Logf("Saw EXPECTED panic %v", r) - } else { - t.Errorf("Did not see expected panic") - } - }() - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - v := archsimd.LoadInt8x16(a) - e := v.GetElem(16) - t.Errorf("Should have panicked, e=%v", e) -} - -func TestSlicesInt8GetElem15(t *testing.T) { - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - v := archsimd.LoadInt8x16(a) - e := v.GetElem(seventeen - 2) - if e != a[15] { - t.Errorf("GetElem(15) = %d != a[15] = %d", e, a[15]) - } -} - -func TestSlicesInt8GetElem15const(t *testing.T) { - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - v := archsimd.LoadInt8x16(a) - e := v.GetElem(15) - if e != a[15] { - t.Errorf("GetElem(15) = %d != a[15] = %d", e, a[15]) - } -} - -func TestSlicesInt8SetElem17(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Logf("Saw EXPECTED panic %v", r) - } else { - t.Errorf("Did not see expected panic") - } - }() - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - v := archsimd.LoadInt8x16(a) - e := v.SetElem(seventeen, 18).GetElem(2) - t.Errorf("Should have panicked, e=%v", e) -} - -func TestSlicesInt8SetElem17const(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Logf("Saw EXPECTED panic %v", r) - } else { - t.Errorf("Did not see expected panic") - } - }() - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - v := archsimd.LoadInt8x16(a) - e := v.SetElem(17, 18).GetElem(2) - t.Errorf("Should have panicked, e=%v", e) -} - -func TestSlicesInt8TooShortLoad(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - defer func() { - if r := recover(); r != nil { - t.Logf("Saw EXPECTED panic %v", r) - } else { - t.Errorf("Did not see expected panic") - } - }() - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} // TOO SHORT, should panic - v := archsimd.LoadInt8x32(a) - b := make([]int8, 32, 32) - v.Store(b) - checkSlices(t, a, b) -} - -func TestSlicesInt8TooShortStore(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - defer func() { - if r := recover(); r != nil { - t.Logf("Saw EXPECTED panic %v", r) - } else { - t.Errorf("Did not see expected panic") - } - }() - a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} - v := archsimd.LoadInt8x32(a) - b := make([]int8, 31) // TOO SHORT, should panic - v.Store(b) - checkSlices(t, a, b) -} - -func TestSlicesFloat64(t *testing.T) { - a := []float64{1, 2, 3, 4, 5, 6, 7, 8} // too long, should be fine - v := archsimd.LoadFloat64x4(a) - b := make([]float64, 4, 4) - v.Store(b) - for i := range b { - if a[i] != b[i] { - t.Errorf("a and b differ at index %d, a=%f, b=%f", i, a[i], b[i]) - } - } -} - -// TODO: try to reduce this test to be smaller. -func TestMergeLocals(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - testMergeLocalswrapper(t, archsimd.Int64x4.Add) -} - -//go:noinline -func forceSpill() {} - -func testMergeLocalswrapper(t *testing.T, op func(archsimd.Int64x4, archsimd.Int64x4) archsimd.Int64x4) { - t.Helper() - s0 := []int64{0, 1, 2, 3} - s1 := []int64{-1, 0, -1, 0} - want := []int64{-1, 1, 1, 3} - v := archsimd.LoadInt64x4(s0) - m := archsimd.LoadInt64x4(s1) - forceSpill() - got := make([]int64, 4) - gotv := op(v, m) - gotv.Store(got) - for i := range len(want) { - if !(got[i] == want[i]) { - t.Errorf("Result at %d incorrect: want %v, got %v", i, want[i], got[i]) - } - } -} - -func TestBitMaskFromBits(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - results := [2]int64{} - want := [2]int64{0, 6} - m := archsimd.Mask64x2FromBits(0b10) - archsimd.LoadInt64x2([]int64{1, 2}).Add(archsimd.LoadInt64x2([]int64{3, 4})).Masked(m).StoreArray(&results) - for i := range 2 { - if results[i] != want[i] { - t.Errorf("Result at %d incorrect: want %v, got %v", i, want[i], results[i]) - } - } -} - -var maskForTestBitMaskFromBitsLoad = uint8(0b10) - -func TestBitMaskFromBitsLoad(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - results := [2]int64{} - want := [2]int64{0, 6} - m := archsimd.Mask64x2FromBits(maskForTestBitMaskFromBitsLoad) - archsimd.LoadInt64x2([]int64{1, 2}).Add(archsimd.LoadInt64x2([]int64{3, 4})).Masked(m).StoreArray(&results) - for i := range 2 { - if results[i] != want[i] { - t.Errorf("Result at %d incorrect: want %v, got %v", i, want[i], results[i]) - } - } -} - -func TestBitMaskToBits(t *testing.T) { - int8s := []int8{ - 0, 1, 1, 0, 0, 1, 0, 1, - 1, 0, 1, 1, 0, 0, 1, 0, - 1, 0, 0, 1, 1, 0, 1, 0, - 0, 1, 1, 0, 0, 1, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 0, 1, 1, 0, 0, 1, - 1, 0, 1, 0, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - } - int16s := make([]int16, 32) - for i := range int16s { - int16s[i] = int16(int8s[i]) - } - int32s := make([]int32, 16) - for i := range int32s { - int32s[i] = int32(int8s[i]) - } - int64s := make([]int64, 8) - for i := range int64s { - int64s[i] = int64(int8s[i]) - } - want64 := uint64(0) - for i := range int8s { - want64 |= uint64(int8s[i]) << i - } - want32 := uint32(want64) - want16 := uint16(want64) - want8 := uint8(want64) - want4 := want8 & 0b1111 - want2 := want4 & 0b11 - - if v := archsimd.LoadInt8x16(int8s[:16]).ToMask().ToBits(); v != want16 { - t.Errorf("want %b, got %b", want16, v) - } - if v := archsimd.LoadInt32x4(int32s[:4]).ToMask().ToBits(); v != want4 { - t.Errorf("want %b, got %b", want4, v) - } - if v := archsimd.LoadInt32x8(int32s[:8]).ToMask().ToBits(); v != want8 { - t.Errorf("want %b, got %b", want8, v) - } - if v := archsimd.LoadInt64x2(int64s[:2]).ToMask().ToBits(); v != want2 { - t.Errorf("want %b, got %b", want2, v) - } - if v := archsimd.LoadInt64x4(int64s[:4]).ToMask().ToBits(); v != want4 { - t.Errorf("want %b, got %b", want4, v) - } - - if archsimd.X86.AVX2() { - if v := archsimd.LoadInt8x32(int8s[:32]).ToMask().ToBits(); v != want32 { - t.Errorf("want %b, got %b", want32, v) - } - } - - if archsimd.X86.AVX512() { - if v := archsimd.LoadInt8x64(int8s).ToMask().ToBits(); v != want64 { - t.Errorf("want %b, got %b", want64, v) - } - if v := archsimd.LoadInt16x8(int16s[:8]).ToMask().ToBits(); v != want8 { - t.Errorf("want %b, got %b", want8, v) - } - if v := archsimd.LoadInt16x16(int16s[:16]).ToMask().ToBits(); v != want16 { - t.Errorf("want %b, got %b", want16, v) - } - if v := archsimd.LoadInt16x32(int16s).ToMask().ToBits(); v != want32 { - t.Errorf("want %b, got %b", want32, v) - } - if v := archsimd.LoadInt32x16(int32s).ToMask().ToBits(); v != want16 { - t.Errorf("want %b, got %b", want16, v) - } - if v := archsimd.LoadInt64x8(int64s).ToMask().ToBits(); v != want8 { - t.Errorf("want %b, got %b", want8, v) - } - } -} - -var maskForTestBitMaskFromBitsStore uint8 - -func TestBitMaskToBitsStore(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - maskForTestBitMaskFromBitsStore = archsimd.LoadInt16x8([]int16{1, 0, 1, 0, 0, 0, 0, 0}).ToMask().ToBits() - if maskForTestBitMaskFromBitsStore != 0b101 { - t.Errorf("Want 0b101, got %b", maskForTestBitMaskFromBitsStore) - } -} - -func TestMergeFloat(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - k := make([]int64, 4, 4) - s := make([]float64, 4, 4) - - a := archsimd.LoadFloat64x4([]float64{1, 2, 3, 4}) - b := archsimd.LoadFloat64x4([]float64{4, 2, 3, 1}) - g := a.Greater(b) - g.ToInt64x4().Store(k) - c := a.Merge(b, g) - - c.Store(s) - - checkSlices[int64](t, k, []int64{0, 0, 0, -1}) - checkSlices[float64](t, s, []float64{4, 2, 3, 4}) -} - -func TestIfElseFloat(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - k := make([]int64, 4, 4) - s := make([]float64, 4, 4) - - a := archsimd.LoadFloat64x4([]float64{1, 2, 3, 4}) - b := archsimd.LoadFloat64x4([]float64{4, 2, 3, 1}) - g := a.Greater(b) - g.ToInt64x4().Store(k) - c := a.IfElse(g, b) - - c.Store(s) - - checkSlices[int64](t, k, []int64{0, 0, 0, -1}) - checkSlices[float64](t, s, []float64{4, 2, 3, 4}) -} - -func TestMergeFloat512(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - - k := make([]int64, 8, 8) - s := make([]float64, 8, 8) - - a := archsimd.LoadFloat64x8([]float64{1, 2, 3, 4, 5, 6, 7, 8}) - b := archsimd.LoadFloat64x8([]float64{8, 7, 6, 5, 4, 2, 3, 1}) - g := a.Greater(b) - g.ToInt64x8().Store(k) - c := a.Merge(b, g) - d := a.Masked(g) - - checkSlices[int64](t, k, []int64{0, 0, 0, 0, -1, -1, -1, -1}) - - c.Store(s) - checkSlices[float64](t, s, []float64{8, 7, 6, 5, 5, 6, 7, 8}) - - d.Store(s) - checkSlices[float64](t, s, []float64{0, 0, 0, 0, 5, 6, 7, 8}) -} - -func TestIfElseFloat512(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - - k := make([]int64, 8, 8) - s := make([]float64, 8, 8) - - a := archsimd.LoadFloat64x8([]float64{1, 2, 3, 4, 5, 6, 7, 8}) - b := archsimd.LoadFloat64x8([]float64{8, 7, 6, 5, 4, 2, 3, 1}) - g := a.Greater(b) - g.ToInt64x8().Store(k) - c := a.IfElse(g, b) - d := a.Masked(g) - - checkSlices[int64](t, k, []int64{0, 0, 0, 0, -1, -1, -1, -1}) - - c.Store(s) - checkSlices[float64](t, s, []float64{8, 7, 6, 5, 5, 6, 7, 8}) - - d.Store(s) - checkSlices[float64](t, s, []float64{0, 0, 0, 0, 5, 6, 7, 8}) -} - -var ro uint64 = 2 -var roBig uint64 = 1024 + 2 - -func TestRotateAllVariable(t *testing.T) { - got := make([]int32, 4) - archsimd.LoadInt32x4([]int32{0b11, 0b11, 0b11, 0b11}).RotateAllLeft(ro).Store(got) - for _, v := range got { - if v != 0b1100 { - t.Errorf("Want 0b1100, got %b", v) - } - } - archsimd.LoadInt32x4([]int32{0b11, 0b11, 0b11, 0b11}).RotateAllLeft(roBig).Store(got) - for _, v := range got { - if v != 0b1100 { - t.Errorf("Want 0b1100, got %b", v) - } - } -} - -func TestRotateAllConst(t *testing.T) { - got := make([]int32, 4) - archsimd.LoadInt32x4([]int32{0b11, 0b11, 0b11, 0b11}).RotateAllLeft(2).Store(got) - for _, v := range got { - if v != 0b1100 { - t.Errorf("Want 0b1100, got %b", v) - } - } -} - func TestBroadcastUint32x4(t *testing.T) { s := make([]uint32, 4, 4) archsimd.BroadcastUint32x4(123456789).Store(s) checkSlices(t, s, []uint32{123456789, 123456789, 123456789, 123456789}) } -func TestBroadcastFloat32x8(t *testing.T) { - s := make([]float32, 8, 8) - archsimd.BroadcastFloat32x8(123456789).Store(s) - checkSlices(t, s, []float32{123456789, 123456789, 123456789, 123456789, 123456789, 123456789, 123456789, 123456789}) +func TestBroadcastFloat32x4(t *testing.T) { + s := make([]float32, 4, 4) + archsimd.BroadcastFloat32x4(3.14).Store(s) + checkSlices(t, s, []float32{3.14, 3.14, 3.14, 3.14}) } func TestBroadcastFloat64x2(t *testing.T) { s := make([]float64, 2, 2) - archsimd.BroadcastFloat64x2(123456789).Store(s) - checkSlices(t, s, []float64{123456789, 123456789}) + archsimd.BroadcastFloat64x2(3.14).Store(s) + checkSlices(t, s, []float64{3.14, 3.14}) } func TestBroadcastUint64x2(t *testing.T) { s := make([]uint64, 2, 2) - archsimd.BroadcastUint64x2(123456789).Store(s) - checkSlices(t, s, []uint64{123456789, 123456789}) + archsimd.BroadcastUint64x2(123456789012345).Store(s) + checkSlices(t, s, []uint64{123456789012345, 123456789012345}) } func TestBroadcastUint16x8(t *testing.T) { s := make([]uint16, 8, 8) archsimd.BroadcastUint16x8(12345).Store(s) - checkSlices(t, s, []uint16{12345, 12345, 12345, 12345}) + checkSlices(t, s, []uint16{12345, 12345, 12345, 12345, 12345, 12345, 12345, 12345}) } -func TestBroadcastInt8x32(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - s := make([]int8, 32, 32) - archsimd.BroadcastInt8x32(-123).Store(s) +func TestBroadcastInt8x16(t *testing.T) { + s := make([]int8, 16, 16) + archsimd.BroadcastInt8x16(-123).Store(s) checkSlices(t, s, []int8{-123, -123, -123, -123, -123, -123, -123, -123, - -123, -123, -123, -123, -123, -123, -123, -123, - -123, -123, -123, -123, -123, -123, -123, -123, - -123, -123, -123, -123, -123, -123, -123, -123, - }) + -123, -123, -123, -123, -123, -123, -123, -123}) } -func TestMaskOpt512(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - - k := make([]int64, 8, 8) - s := make([]float64, 8, 8) - - a := archsimd.LoadFloat64x8([]float64{2, 0, 2, 0, 2, 0, 2, 0}) - b := archsimd.LoadFloat64x8([]float64{1, 1, 1, 1, 1, 1, 1, 1}) - c := archsimd.LoadFloat64x8([]float64{1, 2, 3, 4, 5, 6, 7, 8}) - d := archsimd.LoadFloat64x8([]float64{2, 4, 6, 8, 10, 12, 14, 16}) - g := a.Greater(b) - e := c.Add(d).Masked(g) - e.Store(s) - g.ToInt64x8().Store(k) - checkSlices[int64](t, k, []int64{-1, 0, -1, 0, -1, 0, -1, 0}) - checkSlices[float64](t, s, []float64{3, 0, 9, 0, 15, 0, 21, 0}) +func TestBroadcastUint8x16(t *testing.T) { + s := make([]uint8, 16, 16) + archsimd.BroadcastUint8x16(200).Store(s) + checkSlices(t, s, []uint8{200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200}) } -// flattenedTranspose tranposes x and y, regarded as a pair of 2x2 -// matrices, but then flattens the rows in order, i.e -// x: ABCD ==> a: A1B2 -// y: 1234 b: C3D4 -func flattenedTranspose(x, y archsimd.Int32x4) (a, b archsimd.Int32x4) { - return x.InterleaveLo(y), x.InterleaveHi(y) +func TestBroadcastInt16x8(t *testing.T) { + s := make([]int16, 8, 8) + archsimd.BroadcastInt16x8(-12345).Store(s) + checkSlices(t, s, []int16{-12345, -12345, -12345, -12345, -12345, -12345, -12345, -12345}) } -func TestFlattenedTranspose(t *testing.T) { - r := make([]int32, 4, 4) +func TestBroadcastInt32x4(t *testing.T) { s := make([]int32, 4, 4) - - x := archsimd.LoadInt32x4([]int32{0xA, 0xB, 0xC, 0xD}) - y := archsimd.LoadInt32x4([]int32{1, 2, 3, 4}) - a, b := flattenedTranspose(x, y) - - a.Store(r) - b.Store(s) - - checkSlices[int32](t, r, []int32{0xA, 1, 0xB, 2}) - checkSlices[int32](t, s, []int32{0xC, 3, 0xD, 4}) - -} - -func TestClearAVXUpperBits(t *testing.T) { - // Test that ClearAVXUpperBits is safe even if there are SIMD values - // alive (although usually one should not do this). - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - - r := make([]int64, 4) - s := make([]int64, 4) - - x := archsimd.LoadInt64x4([]int64{10, 20, 30, 40}) - y := archsimd.LoadInt64x4([]int64{1, 2, 3, 4}) - - x.Add(y).Store(r) - archsimd.ClearAVXUpperBits() - x.Sub(y).Store(s) - - checkSlices[int64](t, r, []int64{11, 22, 33, 44}) - checkSlices[int64](t, s, []int64{9, 18, 27, 36}) -} - -func TestLeadingZeros(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - - src := []uint64{0b1111, 0} - want := []uint64{60, 64} - got := make([]uint64, 2) - archsimd.LoadUint64x2(src).LeadingZeros().Store(got) - for i := range 2 { - if want[i] != got[i] { - t.Errorf("Result incorrect at %d: want %d, got %d", i, want[i], got[i]) - } - } -} - -func TestIsZero(t *testing.T) { - v1 := archsimd.LoadUint64x2([]uint64{0, 1}) - v2 := archsimd.LoadUint64x2([]uint64{0, 0}) - if v1.IsZero() { - t.Errorf("Result incorrect, want false, got true") - } - if !v2.IsZero() { - t.Errorf("Result incorrect, want true, got false") - } - if !v1.And(v2).IsZero() { - t.Errorf("Result incorrect, want true, got false") - } - if v1.AndNot(v2).IsZero() { - t.Errorf("Result incorrect, want false, got true") - } - if !v2.And(v1).IsZero() { - t.Errorf("Result incorrect, want true, got false") - } - if !v2.AndNot(v1).IsZero() { - t.Errorf("Result incorrect, want true, got false") - } -} - -func TestSelect4FromPairConst(t *testing.T) { - x := archsimd.LoadInt32x4([]int32{0, 1, 2, 3}) - y := archsimd.LoadInt32x4([]int32{4, 5, 6, 7}) - - llll := x.ConcatPermuteScalars(0, 1, 2, 3, y) - hhhh := x.ConcatPermuteScalars(4, 5, 6, 7, y) - llhh := x.ConcatPermuteScalars(0, 1, 6, 7, y) - hhll := x.ConcatPermuteScalars(6, 7, 0, 1, y) - - lllh := x.ConcatPermuteScalars(0, 1, 2, 7, y) - llhl := x.ConcatPermuteScalars(0, 1, 7, 2, y) - lhll := x.ConcatPermuteScalars(0, 7, 1, 2, y) - hlll := x.ConcatPermuteScalars(7, 0, 1, 2, y) - - hhhl := x.ConcatPermuteScalars(4, 5, 6, 0, y) - hhlh := x.ConcatPermuteScalars(4, 5, 0, 6, y) - hlhh := x.ConcatPermuteScalars(4, 0, 5, 6, y) - lhhh := x.ConcatPermuteScalars(0, 4, 5, 6, y) - - lhlh := x.ConcatPermuteScalars(0, 4, 1, 5, y) - hlhl := x.ConcatPermuteScalars(4, 0, 5, 1, y) - lhhl := x.ConcatPermuteScalars(0, 4, 5, 1, y) - hllh := x.ConcatPermuteScalars(4, 0, 1, 5, y) - - r := make([]int32, 4, 4) - - foo := func(v archsimd.Int32x4, a, b, c, d int32) { - v.Store(r) - checkSlices[int32](t, r, []int32{a, b, c, d}) - } - - foo(llll, 0, 1, 2, 3) - foo(hhhh, 4, 5, 6, 7) - foo(llhh, 0, 1, 6, 7) - foo(hhll, 6, 7, 0, 1) - - foo(lllh, 0, 1, 2, 7) - foo(llhl, 0, 1, 7, 2) - foo(lhll, 0, 7, 1, 2) - foo(hlll, 7, 0, 1, 2) - - foo(hhhl, 4, 5, 6, 0) - foo(hhlh, 4, 5, 0, 6) - foo(hlhh, 4, 0, 5, 6) - foo(lhhh, 0, 4, 5, 6) - - foo(lhlh, 0, 4, 1, 5) - foo(hlhl, 4, 0, 5, 1) - foo(lhhl, 0, 4, 5, 1) - foo(hllh, 4, 0, 1, 5) -} - -//go:noinline -func selectFromPairInt32x4(x archsimd.Int32x4, a, b, c, d uint8, y archsimd.Int32x4) archsimd.Int32x4 { - return x.ConcatPermuteScalars(a, b, c, d, y) -} - -func TestSelect4FromPairVar(t *testing.T) { - x := archsimd.LoadInt32x4([]int32{0, 1, 2, 3}) - y := archsimd.LoadInt32x4([]int32{4, 5, 6, 7}) - - llll := selectFromPairInt32x4(x, 0, 1, 2, 3, y) - hhhh := selectFromPairInt32x4(x, 4, 5, 6, 7, y) - llhh := selectFromPairInt32x4(x, 0, 1, 6, 7, y) - hhll := selectFromPairInt32x4(x, 6, 7, 0, 1, y) - - lllh := selectFromPairInt32x4(x, 0, 1, 2, 7, y) - llhl := selectFromPairInt32x4(x, 0, 1, 7, 2, y) - lhll := selectFromPairInt32x4(x, 0, 7, 1, 2, y) - hlll := selectFromPairInt32x4(x, 7, 0, 1, 2, y) - - hhhl := selectFromPairInt32x4(x, 4, 5, 6, 0, y) - hhlh := selectFromPairInt32x4(x, 4, 5, 0, 6, y) - hlhh := selectFromPairInt32x4(x, 4, 0, 5, 6, y) - lhhh := selectFromPairInt32x4(x, 0, 4, 5, 6, y) - - lhlh := selectFromPairInt32x4(x, 0, 4, 1, 5, y) - hlhl := selectFromPairInt32x4(x, 4, 0, 5, 1, y) - lhhl := selectFromPairInt32x4(x, 0, 4, 5, 1, y) - hllh := selectFromPairInt32x4(x, 4, 0, 1, 5, y) - - r := make([]int32, 4, 4) - - foo := func(v archsimd.Int32x4, a, b, c, d int32) { - v.Store(r) - checkSlices[int32](t, r, []int32{a, b, c, d}) - } - - foo(llll, 0, 1, 2, 3) - foo(hhhh, 4, 5, 6, 7) - foo(llhh, 0, 1, 6, 7) - foo(hhll, 6, 7, 0, 1) - - foo(lllh, 0, 1, 2, 7) - foo(llhl, 0, 1, 7, 2) - foo(lhll, 0, 7, 1, 2) - foo(hlll, 7, 0, 1, 2) - - foo(hhhl, 4, 5, 6, 0) - foo(hhlh, 4, 5, 0, 6) - foo(hlhh, 4, 0, 5, 6) - foo(lhhh, 0, 4, 5, 6) - - foo(lhlh, 0, 4, 1, 5) - foo(hlhl, 4, 0, 5, 1) - foo(lhhl, 0, 4, 5, 1) - foo(hllh, 4, 0, 1, 5) -} - -func TestSelect4FromPairConstGrouped(t *testing.T) { - x := archsimd.LoadFloat32x8([]float32{0, 1, 2, 3, 10, 11, 12, 13}) - y := archsimd.LoadFloat32x8([]float32{4, 5, 6, 7, 14, 15, 16, 17}) - - llll := x.ConcatPermuteScalarsGrouped(0, 1, 2, 3, y) - hhhh := x.ConcatPermuteScalarsGrouped(4, 5, 6, 7, y) - llhh := x.ConcatPermuteScalarsGrouped(0, 1, 6, 7, y) - hhll := x.ConcatPermuteScalarsGrouped(6, 7, 0, 1, y) - - lllh := x.ConcatPermuteScalarsGrouped(0, 1, 2, 7, y) - llhl := x.ConcatPermuteScalarsGrouped(0, 1, 7, 2, y) - lhll := x.ConcatPermuteScalarsGrouped(0, 7, 1, 2, y) - hlll := x.ConcatPermuteScalarsGrouped(7, 0, 1, 2, y) - - hhhl := x.ConcatPermuteScalarsGrouped(4, 5, 6, 0, y) - hhlh := x.ConcatPermuteScalarsGrouped(4, 5, 0, 6, y) - hlhh := x.ConcatPermuteScalarsGrouped(4, 0, 5, 6, y) - lhhh := x.ConcatPermuteScalarsGrouped(0, 4, 5, 6, y) - - lhlh := x.ConcatPermuteScalarsGrouped(0, 4, 1, 5, y) - hlhl := x.ConcatPermuteScalarsGrouped(4, 0, 5, 1, y) - lhhl := x.ConcatPermuteScalarsGrouped(0, 4, 5, 1, y) - hllh := x.ConcatPermuteScalarsGrouped(4, 0, 1, 5, y) - - r := make([]float32, 8, 8) - - foo := func(v archsimd.Float32x8, a, b, c, d float32) { - v.Store(r) - checkSlices[float32](t, r, []float32{a, b, c, d, 10 + a, 10 + b, 10 + c, 10 + d}) - } - - foo(llll, 0, 1, 2, 3) - foo(hhhh, 4, 5, 6, 7) - foo(llhh, 0, 1, 6, 7) - foo(hhll, 6, 7, 0, 1) - - foo(lllh, 0, 1, 2, 7) - foo(llhl, 0, 1, 7, 2) - foo(lhll, 0, 7, 1, 2) - foo(hlll, 7, 0, 1, 2) - - foo(hhhl, 4, 5, 6, 0) - foo(hhlh, 4, 5, 0, 6) - foo(hlhh, 4, 0, 5, 6) - foo(lhhh, 0, 4, 5, 6) - - foo(lhlh, 0, 4, 1, 5) - foo(hlhl, 4, 0, 5, 1) - foo(lhhl, 0, 4, 5, 1) - foo(hllh, 4, 0, 1, 5) -} - -func TestConcatPermuteScalarsConstGroupedUint32x16(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - x := archsimd.LoadUint32x16([]uint32{0, 1, 2, 3, 10, 11, 12, 13, 20, 21, 22, 23, 30, 31, 32, 33}) - y := archsimd.LoadUint32x16([]uint32{4, 5, 6, 7, 14, 15, 16, 17, 24, 25, 26, 27, 34, 35, 36, 37}) - - llll := x.ConcatPermuteScalarsGrouped(0, 1, 2, 3, y) - hhhh := x.ConcatPermuteScalarsGrouped(4, 5, 6, 7, y) - llhh := x.ConcatPermuteScalarsGrouped(0, 1, 6, 7, y) - hhll := x.ConcatPermuteScalarsGrouped(6, 7, 0, 1, y) - - lllh := x.ConcatPermuteScalarsGrouped(0, 1, 2, 7, y) - llhl := x.ConcatPermuteScalarsGrouped(0, 1, 7, 2, y) - lhll := x.ConcatPermuteScalarsGrouped(0, 7, 1, 2, y) - hlll := x.ConcatPermuteScalarsGrouped(7, 0, 1, 2, y) - - hhhl := x.ConcatPermuteScalarsGrouped(4, 5, 6, 0, y) - hhlh := x.ConcatPermuteScalarsGrouped(4, 5, 0, 6, y) - hlhh := x.ConcatPermuteScalarsGrouped(4, 0, 5, 6, y) - lhhh := x.ConcatPermuteScalarsGrouped(0, 4, 5, 6, y) - - lhlh := x.ConcatPermuteScalarsGrouped(0, 4, 1, 5, y) - hlhl := x.ConcatPermuteScalarsGrouped(4, 0, 5, 1, y) - lhhl := x.ConcatPermuteScalarsGrouped(0, 4, 5, 1, y) - hllh := x.ConcatPermuteScalarsGrouped(4, 0, 1, 5, y) - - r := make([]uint32, 16, 16) - - foo := func(v archsimd.Uint32x16, a, b, c, d uint32) { - v.Store(r) - checkSlices[uint32](t, r, []uint32{a, b, c, d, - 10 + a, 10 + b, 10 + c, 10 + d, - 20 + a, 20 + b, 20 + c, 20 + d, - 30 + a, 30 + b, 30 + c, 30 + d, - }) - } - - foo(llll, 0, 1, 2, 3) - foo(hhhh, 4, 5, 6, 7) - foo(llhh, 0, 1, 6, 7) - foo(hhll, 6, 7, 0, 1) - - foo(lllh, 0, 1, 2, 7) - foo(llhl, 0, 1, 7, 2) - foo(lhll, 0, 7, 1, 2) - foo(hlll, 7, 0, 1, 2) - - foo(hhhl, 4, 5, 6, 0) - foo(hhlh, 4, 5, 0, 6) - foo(hlhh, 4, 0, 5, 6) - foo(lhhh, 0, 4, 5, 6) - - foo(lhlh, 0, 4, 1, 5) - foo(hlhl, 4, 0, 5, 1) - foo(lhhl, 0, 4, 5, 1) - foo(hllh, 4, 0, 1, 5) -} - -func TestConcatPermute128Scalars(t *testing.T) { - x := archsimd.LoadUint64x4([]uint64{0, 1, 2, 3}) - y := archsimd.LoadUint64x4([]uint64{4, 5, 6, 7}) - - aa := x.ConcatPermute128Scalars(0, 0, y) - ab := x.ConcatPermute128Scalars(0, 1, y) - bc := x.ConcatPermute128Scalars(1, 2, y) - cd := x.ConcatPermute128Scalars(2, 3, y) - da := x.ConcatPermute128Scalars(3, 0, y) - dc := x.ConcatPermute128Scalars(3, 2, y) - - r := make([]uint64, 4, 4) - - foo := func(v archsimd.Uint64x4, a, b uint64) { - a, b = 2*a, 2*b - v.Store(r) - checkSlices[uint64](t, r, []uint64{a, a + 1, b, b + 1}) - } - - foo(aa, 0, 0) - foo(ab, 0, 1) - foo(bc, 1, 2) - foo(cd, 2, 3) - foo(da, 3, 0) - foo(dc, 3, 2) -} - -func TestConcatPermute128ScalarsError(t *testing.T) { - x := archsimd.LoadUint64x4([]uint64{0, 1, 2, 3}) - y := archsimd.LoadUint64x4([]uint64{4, 5, 6, 7}) - - defer func() { - if r := recover(); r != nil { - t.Logf("Saw expected panic %v", r) - } - }() - _ = x.ConcatPermute128Scalars(0, 4, y) - - t.Errorf("Should have panicked") -} - -//go:noinline -func select128FromPair(x archsimd.Uint64x4, lo, hi uint8, y archsimd.Uint64x4) archsimd.Uint64x4 { - return x.ConcatPermute128Scalars(lo, hi, y) -} - -func TestConcatPermute128ScalarsVar(t *testing.T) { - x := archsimd.LoadUint64x4([]uint64{0, 1, 2, 3}) - y := archsimd.LoadUint64x4([]uint64{4, 5, 6, 7}) - - aa := select128FromPair(x, 0, 0, y) - ab := select128FromPair(x, 0, 1, y) - bc := select128FromPair(x, 1, 2, y) - cd := select128FromPair(x, 2, 3, y) - da := select128FromPair(x, 3, 0, y) - dc := select128FromPair(x, 3, 2, y) - - r := make([]uint64, 4, 4) - - foo := func(v archsimd.Uint64x4, a, b uint64) { - a, b = 2*a, 2*b - v.Store(r) - checkSlices[uint64](t, r, []uint64{a, a + 1, b, b + 1}) - } - - foo(aa, 0, 0) - foo(ab, 0, 1) - foo(bc, 1, 2) - foo(cd, 2, 3) - foo(da, 3, 0) - foo(dc, 3, 2) -} - -func TestSelect2FromPairConst(t *testing.T) { - x := archsimd.LoadUint64x2([]uint64{0, 1}) - y := archsimd.LoadUint64x2([]uint64{2, 3}) - - ll := x.ConcatPermuteScalars(0, 1, y) - hh := x.ConcatPermuteScalars(3, 2, y) - lh := x.ConcatPermuteScalars(0, 3, y) - hl := x.ConcatPermuteScalars(2, 1, y) - - r := make([]uint64, 2, 2) - - foo := func(v archsimd.Uint64x2, a, b uint64) { - v.Store(r) - checkSlices[uint64](t, r, []uint64{a, b}) - } - - foo(ll, 0, 1) - foo(hh, 3, 2) - foo(lh, 0, 3) - foo(hl, 2, 1) + archsimd.BroadcastInt32x4(-123456789).Store(s) + checkSlices(t, s, []int32{-123456789, -123456789, -123456789, -123456789}) } -func TestSelect2FromPairConstGroupedUint(t *testing.T) { - x := archsimd.LoadUint64x4([]uint64{0, 1, 10, 11}) - y := archsimd.LoadUint64x4([]uint64{2, 3, 12, 13}) - - ll := x.ConcatPermuteScalarsGrouped(0, 1, y) - hh := x.ConcatPermuteScalarsGrouped(3, 2, y) - lh := x.ConcatPermuteScalarsGrouped(0, 3, y) - hl := x.ConcatPermuteScalarsGrouped(2, 1, y) - - r := make([]uint64, 4, 4) - - foo := func(v archsimd.Uint64x4, a, b uint64) { - v.Store(r) - checkSlices[uint64](t, r, []uint64{a, b, a + 10, b + 10}) - } - - foo(ll, 0, 1) - foo(hh, 3, 2) - foo(lh, 0, 3) - foo(hl, 2, 1) -} - -func TestSelect2FromPairConstGroupedFloat(t *testing.T) { - x := archsimd.LoadFloat64x4([]float64{0, 1, 10, 11}) - y := archsimd.LoadFloat64x4([]float64{2, 3, 12, 13}) - - ll := x.ConcatPermuteScalarsGrouped(0, 1, y) - hh := x.ConcatPermuteScalarsGrouped(3, 2, y) - lh := x.ConcatPermuteScalarsGrouped(0, 3, y) - hl := x.ConcatPermuteScalarsGrouped(2, 1, y) - - r := make([]float64, 4, 4) - - foo := func(v archsimd.Float64x4, a, b float64) { - v.Store(r) - checkSlices[float64](t, r, []float64{a, b, a + 10, b + 10}) - } - - foo(ll, 0, 1) - foo(hh, 3, 2) - foo(lh, 0, 3) - foo(hl, 2, 1) -} - -func TestSelect2FromPairConstGroupedInt(t *testing.T) { - x := archsimd.LoadInt64x4([]int64{0, 1, 10, 11}) - y := archsimd.LoadInt64x4([]int64{2, 3, 12, 13}) - - ll := x.ConcatPermuteScalarsGrouped(0, 1, y) - hh := x.ConcatPermuteScalarsGrouped(3, 2, y) - lh := x.ConcatPermuteScalarsGrouped(0, 3, y) - hl := x.ConcatPermuteScalarsGrouped(2, 1, y) - - r := make([]int64, 4, 4) - - foo := func(v archsimd.Int64x4, a, b int64) { - v.Store(r) - checkSlices[int64](t, r, []int64{a, b, a + 10, b + 10}) - } - - foo(ll, 0, 1) - foo(hh, 3, 2) - foo(lh, 0, 3) - foo(hl, 2, 1) -} - -func TestSelect2FromPairConstGroupedInt512(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - - x := archsimd.LoadInt64x8([]int64{0, 1, 10, 11, 20, 21, 30, 31}) - y := archsimd.LoadInt64x8([]int64{2, 3, 12, 13, 22, 23, 32, 33}) - - ll := x.ConcatPermuteScalarsGrouped(0, 1, y) - hh := x.ConcatPermuteScalarsGrouped(3, 2, y) - lh := x.ConcatPermuteScalarsGrouped(0, 3, y) - hl := x.ConcatPermuteScalarsGrouped(2, 1, y) - - r := make([]int64, 8, 8) - - foo := func(v archsimd.Int64x8, a, b int64) { - v.Store(r) - checkSlices[int64](t, r, []int64{a, b, a + 10, b + 10, a + 20, b + 20, a + 30, b + 30}) - } - - foo(ll, 0, 1) - foo(hh, 3, 2) - foo(lh, 0, 3) - foo(hl, 2, 1) +func TestBroadcastInt64x2(t *testing.T) { + s := make([]int64, 2, 2) + archsimd.BroadcastInt64x2(-123456789).Store(s) + checkSlices(t, s, []int64{-123456789, -123456789}) } func TestString(t *testing.T) { x := archsimd.LoadUint32x4([]uint32{0, 1, 2, 3}) - y := archsimd.LoadInt64x4([]int64{-4, -5, -6, -7}) + y := archsimd.LoadInt64x2([]int64{-44, -5}) z := archsimd.LoadFloat32x4([]float32{0.5, 1.5, -2.5, 3.5e9}) - w := archsimd.LoadFloat64x4([]float64{0.5, 1.5, -2.5, 3.5e9}) + w := archsimd.LoadFloat64x2([]float64{-2.5, 3.5e9}) sx := "{0,1,2,3}" - sy := "{-4,-5,-6,-7}" + sy := "{-44,-5}" sz := "{0.5,1.5,-2.5,3.5e+09}" - sw := sz + sw := "{-2.5,3.5e+09}" if x.String() != sx { t.Errorf("x=%s wanted %s", x, sx) @@ -1234,365 +207,6 @@ t.Logf("y=%s", y) t.Logf("z=%s", z) } -func TestMaskString(t *testing.T) { - x := archsimd.LoadUint32x4([]uint32{0, 1, 2, 3}) - var y archsimd.Uint32x4 - - m := x.Equal(y) - - w := "{1,0,0,0}" - - if g := m.String(); g != w { - t.Errorf("got=%s wanted %s", g, w) - } -} - -// a returns an slice of 16 int32 -func a() []int32 { - return make([]int32, 16, 16) -} - -// applyTo3 returns a 16-element slice of the results of -// applying f to the respective elements of vectors x, y, and z. -func applyTo3(x, y, z archsimd.Int32x16, f func(x, y, z int32) int32) []int32 { - ax, ay, az := a(), a(), a() - x.Store(ax) - y.Store(ay) - z.Store(az) - - r := a() - for i := range r { - r[i] = f(ax[i], ay[i], az[i]) - } - return r -} - -// applyTo4 returns a 16-element slice of the results of -// applying f to the respective elements of vectors x, y, z, and w. -func applyTo4(x, y, z, w archsimd.Int32x16, f func(x, y, z, w int32) int32) []int32 { - ax, ay, az, aw := a(), a(), a(), a() - x.Store(ax) - y.Store(ay) - z.Store(az) - w.Store(aw) - - r := make([]int32, len(ax), len(ax)) - for i := range r { - r[i] = f(ax[i], ay[i], az[i], aw[i]) - } - return r -} - -func TestSelectTernOptInt32x16(t *testing.T) { - if !archsimd.X86.AVX512() { - t.Skip("Test requires X86.AVX512, not available on this hardware") - return - } - ax := []int32{0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1} - ay := []int32{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1} - az := []int32{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1} - aw := []int32{0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1} - am := []int32{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} - - x := archsimd.LoadInt32x16(ax) - y := archsimd.LoadInt32x16(ay) - z := archsimd.LoadInt32x16(az) - w := archsimd.LoadInt32x16(aw) - m := archsimd.LoadInt32x16(am) - - foo := func(v archsimd.Int32x16, s []int32) { - r := make([]int32, 16, 16) - v.Store(r) - checkSlices[int32](t, r, s) - } - - t0 := w.Xor(y).Xor(z) - ft0 := func(w, y, z int32) int32 { - return w ^ y ^ z - } - foo(t0, applyTo3(w, y, z, ft0)) - - t1 := m.And(w.Xor(y).Xor(z.Not())) - ft1 := func(m, w, y, z int32) int32 { - return m & (w ^ y ^ ^z) - } - foo(t1, applyTo4(m, w, y, z, ft1)) - - t2 := x.Xor(y).Xor(z).And(x.Xor(y).Xor(z.Not())) - ft2 := func(x, y, z int32) int32 { - return (x ^ y ^ z) & (x ^ y ^ ^z) - } - foo(t2, applyTo3(x, y, z, ft2)) -} - -func TestMaskedMerge(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - x := archsimd.LoadInt64x4([]int64{1, 2, 3, 4}) - y := archsimd.LoadInt64x4([]int64{5, 6, 1, 1}) - z := archsimd.LoadInt64x4([]int64{-1, -2, -3, -4}) - res := make([]int64, 4) - expected := []int64{6, 8, -3, -4} - mask := x.Less(y) - if archsimd.X86.AVX512() { - x.Add(y).Merge(z, mask).Store(res) - } else { - x.Add(y).Merge(z, mask).Store(res) - } - for i := range 4 { - if res[i] != expected[i] { - t.Errorf("got %d wanted %d", res[i], expected[i]) - } - } -} - -func TestMaskedIfElse(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - x := archsimd.LoadInt64x4([]int64{1, 2, 3, 4}) - y := archsimd.LoadInt64x4([]int64{5, 6, 1, 1}) - z := archsimd.LoadInt64x4([]int64{-1, -2, -3, -4}) - res := make([]int64, 4) - expected := []int64{6, 8, -3, -4} - mask := x.Less(y) - if archsimd.X86.AVX512() { - x.Add(y).IfElse(mask, z).Store(res) - } else { - x.Add(y).IfElse(mask, z).Store(res) - } - for i := range 4 { - if res[i] != expected[i] { - t.Errorf("got %d wanted %d", res[i], expected[i]) - } - } -} - -func TestPermuteScalars(t *testing.T) { - x := []int32{11, 12, 13, 14} - want := []int32{12, 13, 14, 11} - got := make([]int32, 4) - archsimd.LoadInt32x4(x).PermuteScalars(1, 2, 3, 0).Store(got) - checkSlices(t, got, want) -} - -func TestPermuteScalarsGrouped(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - x := []int32{11, 12, 13, 14, 21, 22, 23, 24} - want := []int32{12, 13, 14, 11, 22, 23, 24, 21} - got := make([]int32, 8) - archsimd.LoadInt32x8(x).PermuteScalarsGrouped(1, 2, 3, 0).Store(got) - checkSlices(t, got, want) -} - -func TestPermuteScalarsHi(t *testing.T) { - x := []int16{-1, -2, -3, -4, 11, 12, 13, 14} - want := []int16{-1, -2, -3, -4, 12, 13, 14, 11} - got := make([]int16, len(x)) - archsimd.LoadInt16x8(x).PermuteScalarsHi(1, 2, 3, 0).Store(got) - checkSlices(t, got, want) -} - -func TestPermuteScalarsLo(t *testing.T) { - x := []int16{11, 12, 13, 14, 4, 5, 6, 7} - want := []int16{12, 13, 14, 11, 4, 5, 6, 7} - got := make([]int16, len(x)) - archsimd.LoadInt16x8(x).PermuteScalarsLo(1, 2, 3, 0).Store(got) - checkSlices(t, got, want) -} - -func TestPermuteScalarsHiGrouped(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - x := []int16{-1, -2, -3, -4, 11, 12, 13, 14, -11, -12, -13, -14, 111, 112, 113, 114} - want := []int16{-1, -2, -3, -4, 12, 13, 14, 11, -11, -12, -13, -14, 112, 113, 114, 111} - got := make([]int16, len(x)) - archsimd.LoadInt16x16(x).PermuteScalarsHiGrouped(1, 2, 3, 0).Store(got) - checkSlices(t, got, want) -} - -func TestPermuteScalarsLoGrouped(t *testing.T) { - if !archsimd.X86.AVX2() { - t.Skip("Test requires X86.AVX2, not available on this hardware") - return - } - x := []int16{11, 12, 13, 14, 4, 5, 6, 7, 111, 112, 113, 114, 14, 15, 16, 17} - want := []int16{12, 13, 14, 11, 4, 5, 6, 7, 112, 113, 114, 111, 14, 15, 16, 17} - got := make([]int16, len(x)) - archsimd.LoadInt16x16(x).PermuteScalarsLoGrouped(1, 2, 3, 0).Store(got) - checkSlices(t, got, want) -} - -func TestClMul(t *testing.T) { - var x = archsimd.LoadUint64x2([]uint64{1, 5}) - var y = archsimd.LoadUint64x2([]uint64{3, 9}) - - foo := func(v archsimd.Uint64x2, s []uint64) { - r := make([]uint64, 2, 2) - v.Store(r) - checkSlices[uint64](t, r, s) - } - - foo(x.CarrylessMultiplyEven(y), []uint64{3, 0}) - foo(x.CarrylessMultiplyEvenOdd(y), []uint64{9, 0}) - foo(x.CarrylessMultiplyOddEven(y), []uint64{15, 0}) - foo(x.CarrylessMultiplyOdd(y), []uint64{45, 0}) - foo(y.CarrylessMultiplyEven(y), []uint64{5, 0}) - -} - -func addPairsSlice[T number](a, b []T) []T { - r := make([]T, len(a)) - for i := range len(a) / 2 { - r[i] = a[2*i] + a[2*i+1] - r[i+len(a)/2] = b[2*i] + b[2*i+1] - } - return r -} - -func subPairsSlice[T number](a, b []T) []T { - r := make([]T, len(a)) - for i := range len(a) / 2 { - r[i] = a[2*i] - a[2*i+1] - r[i+len(a)/2] = b[2*i] - b[2*i+1] - } - return r -} - -func addPairsGroupedSlice[T number](a, b []T) []T { - group := int(128 / unsafe.Sizeof(a[0])) - r := make([]T, 0, len(a)) - for i := range len(a) / group { - r = append(r, addPairsSlice(a[i*group:(i+1)*group], b[i*group:(i+1)*group])...) - } - return r -} - -func subPairsGroupedSlice[T number](a, b []T) []T { - group := int(128 / unsafe.Sizeof(a[0])) - r := make([]T, 0, len(a)) - for i := range len(a) / group { - r = append(r, subPairsSlice(a[i*group:(i+1)*group], b[i*group:(i+1)*group])...) - } - return r -} - -func TestAddSubPairs(t *testing.T) { - testInt16x8Binary(t, archsimd.Int16x8.ConcatAddPairs, addPairsSlice[int16]) - testInt16x8Binary(t, archsimd.Int16x8.ConcatSubPairs, subPairsSlice[int16]) - testUint16x8Binary(t, archsimd.Uint16x8.ConcatAddPairs, addPairsSlice[uint16]) - testUint16x8Binary(t, archsimd.Uint16x8.ConcatSubPairs, subPairsSlice[uint16]) - testInt32x4Binary(t, archsimd.Int32x4.ConcatAddPairs, addPairsSlice[int32]) - testInt32x4Binary(t, archsimd.Int32x4.ConcatSubPairs, subPairsSlice[int32]) - testUint32x4Binary(t, archsimd.Uint32x4.ConcatAddPairs, addPairsSlice[uint32]) - testUint32x4Binary(t, archsimd.Uint32x4.ConcatSubPairs, subPairsSlice[uint32]) - testFloat32x4Binary(t, archsimd.Float32x4.ConcatAddPairs, addPairsSlice[float32]) - testFloat32x4Binary(t, archsimd.Float32x4.ConcatSubPairs, subPairsSlice[float32]) - testFloat64x2Binary(t, archsimd.Float64x2.ConcatAddPairs, addPairsSlice[float64]) - testFloat64x2Binary(t, archsimd.Float64x2.ConcatSubPairs, subPairsSlice[float64]) - - // Grouped versions - if archsimd.X86.AVX2() { - testInt16x16Binary(t, archsimd.Int16x16.ConcatAddPairsGrouped, addPairsGroupedSlice[int16]) - testInt16x16Binary(t, archsimd.Int16x16.ConcatSubPairsGrouped, subPairsGroupedSlice[int16]) - testUint16x16Binary(t, archsimd.Uint16x16.ConcatAddPairsGrouped, addPairsGroupedSlice[uint16]) - testUint16x16Binary(t, archsimd.Uint16x16.ConcatSubPairsGrouped, subPairsGroupedSlice[uint16]) - testInt32x8Binary(t, archsimd.Int32x8.ConcatAddPairsGrouped, addPairsGroupedSlice[int32]) - testInt32x8Binary(t, archsimd.Int32x8.ConcatSubPairsGrouped, subPairsGroupedSlice[int32]) - testUint32x8Binary(t, archsimd.Uint32x8.ConcatAddPairsGrouped, addPairsGroupedSlice[uint32]) - testUint32x8Binary(t, archsimd.Uint32x8.ConcatSubPairsGrouped, subPairsGroupedSlice[uint32]) - testFloat32x8Binary(t, archsimd.Float32x8.ConcatAddPairsGrouped, addPairsGroupedSlice[float32]) - testFloat32x8Binary(t, archsimd.Float32x8.ConcatSubPairsGrouped, subPairsGroupedSlice[float32]) - testFloat64x4Binary(t, archsimd.Float64x4.ConcatAddPairsGrouped, addPairsGroupedSlice[float64]) - testFloat64x4Binary(t, archsimd.Float64x4.ConcatSubPairsGrouped, subPairsGroupedSlice[float64]) - } -} - -func convConcatSlice[T, U number](a, b []T, conv func(T) U) []U { - r := make([]U, len(a)+len(b)) - for i, v := range a { - r[i] = conv(v) - } - for i, v := range b { - r[len(a)+i] = conv(v) - } - return r -} - -func convConcatGroupedSlice[T, U number](a, b []T, conv func(T) U) []U { - group := int(128 / unsafe.Sizeof(a[0])) - r := make([]U, 0, len(a)+len(b)) - for i := 0; i < len(a)/group; i++ { - r = append(r, convConcatSlice(a[i*group:(i+1)*group], b[i*group:(i+1)*group], conv)...) - } - return r -} - -func TestSaturateConcat(t *testing.T) { - // Int32x4.SaturateToInt16Concat - forSlicePair(t, int32s, 4, func(x, y []int32) bool { - a, b := archsimd.LoadInt32x4(x), archsimd.LoadInt32x4(y) - var out [8]int16 - a.SaturateToInt16Concat(b).StoreArray(&out) - want := convConcatSlice(x, y, satToInt16) - return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) - }) - // Int32x4.SaturateToUint16Concat - forSlicePair(t, int32s, 4, func(x, y []int32) bool { - a, b := archsimd.LoadInt32x4(x), archsimd.LoadInt32x4(y) - var out [8]uint16 - a.SaturateToUint16Concat(b).StoreArray(&out) - want := convConcatSlice(x, y, satToUint16) - return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) - }) - - if archsimd.X86.AVX2() { - // Int32x8.SaturateToInt16ConcatGrouped - forSlicePair(t, int32s, 8, func(x, y []int32) bool { - a, b := archsimd.LoadInt32x8(x), archsimd.LoadInt32x8(y) - var out [16]int16 - a.SaturateToInt16ConcatGrouped(b).StoreArray(&out) - want := convConcatGroupedSlice(x, y, satToInt16) - return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) - }) - // Int32x8.SaturateToUint16ConcatGrouped - forSlicePair(t, int32s, 8, func(x, y []int32) bool { - a, b := archsimd.LoadInt32x8(x), archsimd.LoadInt32x8(y) - var out [16]uint16 - a.SaturateToUint16ConcatGrouped(b).StoreArray(&out) - want := convConcatGroupedSlice(x, y, satToUint16) - return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) - }) - } - - if archsimd.X86.AVX512() { - // Int32x16.SaturateToInt16ConcatGrouped - forSlicePair(t, int32s, 16, func(x, y []int32) bool { - a, b := archsimd.LoadInt32x16(x), archsimd.LoadInt32x16(y) - var out [32]int16 - a.SaturateToInt16ConcatGrouped(b).StoreArray(&out) - want := convConcatGroupedSlice(x, y, satToInt16) - return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) - }) - // Int32x16.SaturateToUint16ConcatGrouped - forSlicePair(t, int32s, 16, func(x, y []int32) bool { - a, b := archsimd.LoadInt32x16(x), archsimd.LoadInt32x16(y) - var out [32]uint16 - a.SaturateToUint16ConcatGrouped(b).StoreArray(&out) - want := convConcatGroupedSlice(x, y, satToUint16) - return checkSlicesLogInput(t, out[:], want, 0, func() { t.Logf("x=%v, y=%v", x, y) }) - }) - } -} - func stringy[T interface{ String() string }](v T) string { return v.String() } @@ -1608,8 +222,10 @@ y := archsimd.LoadInt64x2([]int64{1, 1}) if got := stringy(x); got != y.String() { t.Fatalf("string(x) = %q, want %q", got, y.String()) } - want := y.Add(y) - if got := double(x); got.NotEqual(want).ToBits() != 0 { + var want, got [2]int64 + y.Add(y).StoreArray(&want) + double(x).StoreArray(&got) + if got != want { t.Fatalf("double(x) = %v, want %v", got, want) } } @@ -1661,3 +277,103 @@ float64Sink *= a30 float64Sink -= a31 float64Sink /= a32 } + +func TestSlicesInt8SetElem(t *testing.T) { + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} + v := archsimd.LoadInt8x16(a) + + v = v.SetElem(3, 13) + a[3] = 13 + + b := make([]int8, 16, 16) + v.Store(b) + checkSlices(t, a, b) +} + +func TestSlicesInt8GetElem(t *testing.T) { + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} + v := archsimd.LoadInt8x16(a) + e := v.GetElem(2) + if e != a[2] { + t.Errorf("GetElem(2) = %d != a[2] = %d", e, a[2]) + } + +} + +var seventeen = uint8(17) + +func TestSlicesInt8GetElem16(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Logf("Saw EXPECTED panic %v", r) + } else { + t.Errorf("Did not see expected panic") + } + }() + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + v := archsimd.LoadInt8x16(a) + e := v.GetElem(seventeen - 1) + t.Errorf("Should have panicked, e=%v", e) +} + +func TestSlicesInt8GetElem16const(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Logf("Saw EXPECTED panic %v", r) + } else { + t.Errorf("Did not see expected panic") + } + }() + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + v := archsimd.LoadInt8x16(a) + e := v.GetElem(16) + t.Errorf("Should have panicked, e=%v", e) +} + +func TestSlicesInt8GetElem15(t *testing.T) { + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + v := archsimd.LoadInt8x16(a) + e := v.GetElem(seventeen - 2) + if e != a[15] { + t.Errorf("GetElem(15) = %d != a[15] = %d", e, a[15]) + } +} + +func TestSlicesInt8GetElem15const(t *testing.T) { + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + v := archsimd.LoadInt8x16(a) + e := v.GetElem(15) + if e != a[15] { + t.Errorf("GetElem(15) = %d != a[15] = %d", e, a[15]) + } +} + +func TestSlicesInt8SetElem17(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Logf("Saw EXPECTED panic %v", r) + } else { + t.Errorf("Did not see expected panic") + } + }() + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + v := archsimd.LoadInt8x16(a) + e := v.SetElem(seventeen, 18).GetElem(2) + t.Errorf("Should have panicked, e=%v", e) +} + +func TestSlicesInt8SetElem17const(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Logf("Saw EXPECTED panic %v", r) + } else { + t.Errorf("Did not see expected panic") + } + }() + a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + v := archsimd.LoadInt8x16(a) + e := v.SetElem(17, 18).GetElem(2) + t.Errorf("Should have panicked, e=%v", e) +} diff --git a/src/simd/archsimd/internal/simd_test/slicepart_128_test.go b/src/simd/archsimd/internal/simd_test/slicepart_128_test.go index 5cb7cff49288fcfb25e8891ee1b06380fe709868..0e1eda243d76bdd950bd2b68b901b54b2f5b4890 100644 --- a/src/simd/archsimd/internal/simd_test/slicepart_128_test.go +++ b/src/simd/archsimd/internal/simd_test/slicepart_128_test.go @@ -169,3 +169,16 @@ } } } } + +func TestStorePartReturnValues128(t *testing.T) { + testStorePartReturnValue[int8, archsimd.Int8x16](t) + testStorePartReturnValue[uint8, archsimd.Uint8x16](t) + testStorePartReturnValue[int16, archsimd.Int16x8](t) + testStorePartReturnValue[uint16, archsimd.Uint16x8](t) + testStorePartReturnValue[int32, archsimd.Int32x4](t) + testStorePartReturnValue[uint32, archsimd.Uint32x4](t) + testStorePartReturnValue[int64, archsimd.Int64x2](t) + testStorePartReturnValue[uint64, archsimd.Uint64x2](t) + testStorePartReturnValue[float32, archsimd.Float32x4](t) + testStorePartReturnValue[float64, archsimd.Float64x2](t) +} diff --git a/src/simd/archsimd/internal/simd_test/slicepart_wider_test.go b/src/simd/archsimd/internal/simd_test/slicepart_wider_test.go index 58ecb1578b44b7b3fc7638fe63dd7e9ccd96bc8a..dfc3cc69eb23be3c0af17e311bc3d7c7cfe51afc 100644 --- a/src/simd/archsimd/internal/simd_test/slicepart_wider_test.go +++ b/src/simd/archsimd/internal/simd_test/slicepart_wider_test.go @@ -299,3 +299,31 @@ } } } } + +func TestStorePartReturnValuesWider(t *testing.T) { + // AVX2 / 256-bit types + testStorePartReturnValue[int8, archsimd.Int8x32](t) + testStorePartReturnValue[uint8, archsimd.Uint8x32](t) + testStorePartReturnValue[int16, archsimd.Int16x16](t) + testStorePartReturnValue[uint16, archsimd.Uint16x16](t) + testStorePartReturnValue[int32, archsimd.Int32x8](t) + testStorePartReturnValue[uint32, archsimd.Uint32x8](t) + testStorePartReturnValue[int64, archsimd.Int64x4](t) + testStorePartReturnValue[uint64, archsimd.Uint64x4](t) + testStorePartReturnValue[float32, archsimd.Float32x8](t) + testStorePartReturnValue[float64, archsimd.Float64x4](t) + + // AVX512 / 512-bit types + if archsimd.X86.AVX512() { + testStorePartReturnValue[int8, archsimd.Int8x64](t) + testStorePartReturnValue[uint8, archsimd.Uint8x64](t) + testStorePartReturnValue[int16, archsimd.Int16x32](t) + testStorePartReturnValue[uint16, archsimd.Uint16x32](t) + testStorePartReturnValue[int32, archsimd.Int32x16](t) + testStorePartReturnValue[uint32, archsimd.Uint32x16](t) + testStorePartReturnValue[int64, archsimd.Int64x8](t) + testStorePartReturnValue[uint64, archsimd.Uint64x8](t) + testStorePartReturnValue[float32, archsimd.Float32x16](t) + testStorePartReturnValue[float64, archsimd.Float64x8](t) + } +} diff --git a/src/simd/archsimd/internal/simd_test/ternary_arm64_helpers_test.go b/src/simd/archsimd/internal/simd_test/ternary_arm64_helpers_test.go deleted file mode 100644 index de5e6cee6e8d3e273cffb360ef1072ea6760e42f..0000000000000000000000000000000000000000 --- a/src/simd/archsimd/internal/simd_test/ternary_arm64_helpers_test.go +++ /dev/null @@ -1,344 +0,0 @@ -// Code generated by 'tmplgen'; DO NOT EDIT. - -//go:build goexperiment.simd && arm64 - -// This file contains functions testing ternary simd methods. -// Each function in this file is specialized for a -// particular simd type x. - -package simd_test - -import ( - "simd/archsimd" - "testing" -) - -// testInt8x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt8x16Ternary(t *testing.T, f func(_, _, _ archsimd.Int8x16) archsimd.Int8x16, want func(_, _, _ []int8) []int8) { - n := 16 - t.Helper() - forSliceTriple(t, int8s, n, func(x, y, z []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - b := archsimd.LoadInt8x16(y) - c := archsimd.LoadInt8x16(z) - g := make([]int8, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testInt16x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt16x8Ternary(t *testing.T, f func(_, _, _ archsimd.Int16x8) archsimd.Int16x8, want func(_, _, _ []int16) []int16) { - n := 8 - t.Helper() - forSliceTriple(t, int16s, n, func(x, y, z []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - b := archsimd.LoadInt16x8(y) - c := archsimd.LoadInt16x8(z) - g := make([]int16, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testInt32x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Int32x4) archsimd.Int32x4, want func(_, _, _ []int32) []int32) { - n := 4 - t.Helper() - forSliceTriple(t, int32s, n, func(x, y, z []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - b := archsimd.LoadInt32x4(y) - c := archsimd.LoadInt32x4(z) - g := make([]int32, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testInt64x2Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Int64x2) archsimd.Int64x2, want func(_, _, _ []int64) []int64) { - n := 2 - t.Helper() - forSliceTriple(t, int64s, n, func(x, y, z []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - b := archsimd.LoadInt64x2(y) - c := archsimd.LoadInt64x2(z) - g := make([]int64, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint8x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint8x16Ternary(t *testing.T, f func(_, _, _ archsimd.Uint8x16) archsimd.Uint8x16, want func(_, _, _ []uint8) []uint8) { - n := 16 - t.Helper() - forSliceTriple(t, uint8s, n, func(x, y, z []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - b := archsimd.LoadUint8x16(y) - c := archsimd.LoadUint8x16(z) - g := make([]uint8, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint16x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint16x8Ternary(t *testing.T, f func(_, _, _ archsimd.Uint16x8) archsimd.Uint16x8, want func(_, _, _ []uint16) []uint16) { - n := 8 - t.Helper() - forSliceTriple(t, uint16s, n, func(x, y, z []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - b := archsimd.LoadUint16x8(y) - c := archsimd.LoadUint16x8(z) - g := make([]uint16, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint32x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Uint32x4) archsimd.Uint32x4, want func(_, _, _ []uint32) []uint32) { - n := 4 - t.Helper() - forSliceTriple(t, uint32s, n, func(x, y, z []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - b := archsimd.LoadUint32x4(y) - c := archsimd.LoadUint32x4(z) - g := make([]uint32, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint64x2Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Uint64x2) archsimd.Uint64x2, want func(_, _, _ []uint64) []uint64) { - n := 2 - t.Helper() - forSliceTriple(t, uint64s, n, func(x, y, z []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - b := archsimd.LoadUint64x2(y) - c := archsimd.LoadUint64x2(z) - g := make([]uint64, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testFloat32x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testFloat32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Float32x4) archsimd.Float32x4, want func(_, _, _ []float32) []float32) { - n := 4 - t.Helper() - forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - b := archsimd.LoadFloat32x4(y) - c := archsimd.LoadFloat32x4(z) - g := make([]float32, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testFloat64x2Ternary tests the simd ternary method f against the expected behavior generated by want -func testFloat64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Float64x2) archsimd.Float64x2, want func(_, _, _ []float64) []float64) { - n := 2 - t.Helper() - forSliceTriple(t, float64s, n, func(x, y, z []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - b := archsimd.LoadFloat64x2(y) - c := archsimd.LoadFloat64x2(z) - g := make([]float64, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testInt8x16TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testInt8x16TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Int8x16) archsimd.Int8x16, want func(x, y, z []int8) []int8, flakiness float64) { - n := 16 - t.Helper() - forSliceTriple(t, int8s, n, func(x, y, z []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - b := archsimd.LoadInt8x16(y) - c := archsimd.LoadInt8x16(z) - g := make([]int8, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testInt16x8TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testInt16x8TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Int16x8) archsimd.Int16x8, want func(x, y, z []int16) []int16, flakiness float64) { - n := 8 - t.Helper() - forSliceTriple(t, int16s, n, func(x, y, z []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - b := archsimd.LoadInt16x8(y) - c := archsimd.LoadInt16x8(z) - g := make([]int16, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testInt32x4TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testInt32x4TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Int32x4) archsimd.Int32x4, want func(x, y, z []int32) []int32, flakiness float64) { - n := 4 - t.Helper() - forSliceTriple(t, int32s, n, func(x, y, z []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - b := archsimd.LoadInt32x4(y) - c := archsimd.LoadInt32x4(z) - g := make([]int32, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testInt64x2TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testInt64x2TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Int64x2) archsimd.Int64x2, want func(x, y, z []int64) []int64, flakiness float64) { - n := 2 - t.Helper() - forSliceTriple(t, int64s, n, func(x, y, z []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - b := archsimd.LoadInt64x2(y) - c := archsimd.LoadInt64x2(z) - g := make([]int64, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint8x16TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testUint8x16TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Uint8x16) archsimd.Uint8x16, want func(x, y, z []uint8) []uint8, flakiness float64) { - n := 16 - t.Helper() - forSliceTriple(t, uint8s, n, func(x, y, z []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - b := archsimd.LoadUint8x16(y) - c := archsimd.LoadUint8x16(z) - g := make([]uint8, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint16x8TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testUint16x8TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Uint16x8) archsimd.Uint16x8, want func(x, y, z []uint16) []uint16, flakiness float64) { - n := 8 - t.Helper() - forSliceTriple(t, uint16s, n, func(x, y, z []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - b := archsimd.LoadUint16x8(y) - c := archsimd.LoadUint16x8(z) - g := make([]uint16, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint32x4TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testUint32x4TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Uint32x4) archsimd.Uint32x4, want func(x, y, z []uint32) []uint32, flakiness float64) { - n := 4 - t.Helper() - forSliceTriple(t, uint32s, n, func(x, y, z []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - b := archsimd.LoadUint32x4(y) - c := archsimd.LoadUint32x4(z) - g := make([]uint32, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint64x2TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testUint64x2TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Uint64x2) archsimd.Uint64x2, want func(x, y, z []uint64) []uint64, flakiness float64) { - n := 2 - t.Helper() - forSliceTriple(t, uint64s, n, func(x, y, z []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - b := archsimd.LoadUint64x2(y) - c := archsimd.LoadUint64x2(z) - g := make([]uint64, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testFloat32x4TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat32x4TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float32x4) archsimd.Float32x4, want func(x, y, z []float32) []float32, flakiness float64) { - n := 4 - t.Helper() - forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - b := archsimd.LoadFloat32x4(y) - c := archsimd.LoadFloat32x4(z) - g := make([]float32, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testFloat64x2TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, -// but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat64x2TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float64x2) archsimd.Float64x2, want func(x, y, z []float64) []float64, flakiness float64) { - n := 2 - t.Helper() - forSliceTriple(t, float64s, n, func(x, y, z []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - b := archsimd.LoadFloat64x2(y) - c := archsimd.LoadFloat64x2(z) - g := make([]float64, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} diff --git a/src/simd/archsimd/internal/simd_test/ternary_helpers_128_test.go b/src/simd/archsimd/internal/simd_test/ternary_helpers_128_test.go new file mode 100644 index 0000000000000000000000000000000000000000..76722d97494944f5e58e86d894ab339579bb93e6 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/ternary_helpers_128_test.go @@ -0,0 +1,208 @@ +// Code generated by 'tmplgen'; DO NOT EDIT. + +//go:build goexperiment.simd && (amd64 || wasm || arm64) + +// This file contains functions testing ternary simd methods. +// Each function in this file is specialized for a +// particular simd type x. + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +// testInt8x16Ternary tests the simd ternary method f against the expected behavior generated by want +func testInt8x16Ternary(t *testing.T, f func(_, _, _ archsimd.Int8x16) archsimd.Int8x16, want func(_, _, _ []int8) []int8) { + n := 16 + t.Helper() + forSliceTriple(t, int8s, n, func(x, y, z []int8) bool { + t.Helper() + a := archsimd.LoadInt8x16(x) + b := archsimd.LoadInt8x16(y) + c := archsimd.LoadInt8x16(z) + g := make([]int8, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testInt16x8Ternary tests the simd ternary method f against the expected behavior generated by want +func testInt16x8Ternary(t *testing.T, f func(_, _, _ archsimd.Int16x8) archsimd.Int16x8, want func(_, _, _ []int16) []int16) { + n := 8 + t.Helper() + forSliceTriple(t, int16s, n, func(x, y, z []int16) bool { + t.Helper() + a := archsimd.LoadInt16x8(x) + b := archsimd.LoadInt16x8(y) + c := archsimd.LoadInt16x8(z) + g := make([]int16, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testInt32x4Ternary tests the simd ternary method f against the expected behavior generated by want +func testInt32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Int32x4) archsimd.Int32x4, want func(_, _, _ []int32) []int32) { + n := 4 + t.Helper() + forSliceTriple(t, int32s, n, func(x, y, z []int32) bool { + t.Helper() + a := archsimd.LoadInt32x4(x) + b := archsimd.LoadInt32x4(y) + c := archsimd.LoadInt32x4(z) + g := make([]int32, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testInt64x2Ternary tests the simd ternary method f against the expected behavior generated by want +func testInt64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Int64x2) archsimd.Int64x2, want func(_, _, _ []int64) []int64) { + n := 2 + t.Helper() + forSliceTriple(t, int64s, n, func(x, y, z []int64) bool { + t.Helper() + a := archsimd.LoadInt64x2(x) + b := archsimd.LoadInt64x2(y) + c := archsimd.LoadInt64x2(z) + g := make([]int64, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testUint8x16Ternary tests the simd ternary method f against the expected behavior generated by want +func testUint8x16Ternary(t *testing.T, f func(_, _, _ archsimd.Uint8x16) archsimd.Uint8x16, want func(_, _, _ []uint8) []uint8) { + n := 16 + t.Helper() + forSliceTriple(t, uint8s, n, func(x, y, z []uint8) bool { + t.Helper() + a := archsimd.LoadUint8x16(x) + b := archsimd.LoadUint8x16(y) + c := archsimd.LoadUint8x16(z) + g := make([]uint8, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testUint16x8Ternary tests the simd ternary method f against the expected behavior generated by want +func testUint16x8Ternary(t *testing.T, f func(_, _, _ archsimd.Uint16x8) archsimd.Uint16x8, want func(_, _, _ []uint16) []uint16) { + n := 8 + t.Helper() + forSliceTriple(t, uint16s, n, func(x, y, z []uint16) bool { + t.Helper() + a := archsimd.LoadUint16x8(x) + b := archsimd.LoadUint16x8(y) + c := archsimd.LoadUint16x8(z) + g := make([]uint16, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testUint32x4Ternary tests the simd ternary method f against the expected behavior generated by want +func testUint32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Uint32x4) archsimd.Uint32x4, want func(_, _, _ []uint32) []uint32) { + n := 4 + t.Helper() + forSliceTriple(t, uint32s, n, func(x, y, z []uint32) bool { + t.Helper() + a := archsimd.LoadUint32x4(x) + b := archsimd.LoadUint32x4(y) + c := archsimd.LoadUint32x4(z) + g := make([]uint32, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testUint64x2Ternary tests the simd ternary method f against the expected behavior generated by want +func testUint64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Uint64x2) archsimd.Uint64x2, want func(_, _, _ []uint64) []uint64) { + n := 2 + t.Helper() + forSliceTriple(t, uint64s, n, func(x, y, z []uint64) bool { + t.Helper() + a := archsimd.LoadUint64x2(x) + b := archsimd.LoadUint64x2(y) + c := archsimd.LoadUint64x2(z) + g := make([]uint64, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testFloat32x4Ternary tests the simd ternary method f against the expected behavior generated by want +func testFloat32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Float32x4) archsimd.Float32x4, want func(_, _, _ []float32) []float32) { + n := 4 + t.Helper() + forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + b := archsimd.LoadFloat32x4(y) + c := archsimd.LoadFloat32x4(z) + g := make([]float32, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testFloat64x2Ternary tests the simd ternary method f against the expected behavior generated by want +func testFloat64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Float64x2) archsimd.Float64x2, want func(_, _, _ []float64) []float64) { + n := 2 + t.Helper() + forSliceTriple(t, float64s, n, func(x, y, z []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + b := archsimd.LoadFloat64x2(y) + c := archsimd.LoadFloat64x2(z) + g := make([]float64, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testFloat32x4TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, +// but using a flakiness parameter because we haven't exactly figured out how simd floating point works +func testFloat32x4TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float32x4) archsimd.Float32x4, want func(x, y, z []float32) []float32, flakiness float64) { + n := 4 + t.Helper() + forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { + t.Helper() + a := archsimd.LoadFloat32x4(x) + b := archsimd.LoadFloat32x4(y) + c := archsimd.LoadFloat32x4(z) + g := make([]float32, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} + +// testFloat64x2TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, +// but using a flakiness parameter because we haven't exactly figured out how simd floating point works +func testFloat64x2TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float64x2) archsimd.Float64x2, want func(x, y, z []float64) []float64, flakiness float64) { + n := 2 + t.Helper() + forSliceTriple(t, float64s, n, func(x, y, z []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x2(x) + b := archsimd.LoadFloat64x2(y) + c := archsimd.LoadFloat64x2(z) + g := make([]float64, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} diff --git a/src/simd/archsimd/internal/simd_test/ternary_helpers_test.go b/src/simd/archsimd/internal/simd_test/ternary_helpers_wider_test.go rename from src/simd/archsimd/internal/simd_test/ternary_helpers_test.go rename to src/simd/archsimd/internal/simd_test/ternary_helpers_wider_test.go index 03ab91891b042c8e48af4a9244f6829c291b4c3c..74b4f03055cd1200ea8298372bd126d55de66d7b 100644 --- a/src/simd/archsimd/internal/simd_test/ternary_helpers_test.go +++ b/src/simd/archsimd/internal/simd_test/ternary_helpers_wider_test.go @@ -13,166 +13,6 @@ "simd/archsimd" "testing" ) -// testInt8x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt8x16Ternary(t *testing.T, f func(_, _, _ archsimd.Int8x16) archsimd.Int8x16, want func(_, _, _ []int8) []int8) { - n := 16 - t.Helper() - forSliceTriple(t, int8s, n, func(x, y, z []int8) bool { - t.Helper() - a := archsimd.LoadInt8x16(x) - b := archsimd.LoadInt8x16(y) - c := archsimd.LoadInt8x16(z) - g := make([]int8, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testInt16x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt16x8Ternary(t *testing.T, f func(_, _, _ archsimd.Int16x8) archsimd.Int16x8, want func(_, _, _ []int16) []int16) { - n := 8 - t.Helper() - forSliceTriple(t, int16s, n, func(x, y, z []int16) bool { - t.Helper() - a := archsimd.LoadInt16x8(x) - b := archsimd.LoadInt16x8(y) - c := archsimd.LoadInt16x8(z) - g := make([]int16, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testInt32x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Int32x4) archsimd.Int32x4, want func(_, _, _ []int32) []int32) { - n := 4 - t.Helper() - forSliceTriple(t, int32s, n, func(x, y, z []int32) bool { - t.Helper() - a := archsimd.LoadInt32x4(x) - b := archsimd.LoadInt32x4(y) - c := archsimd.LoadInt32x4(z) - g := make([]int32, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testInt64x2Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Int64x2) archsimd.Int64x2, want func(_, _, _ []int64) []int64) { - n := 2 - t.Helper() - forSliceTriple(t, int64s, n, func(x, y, z []int64) bool { - t.Helper() - a := archsimd.LoadInt64x2(x) - b := archsimd.LoadInt64x2(y) - c := archsimd.LoadInt64x2(z) - g := make([]int64, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint8x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint8x16Ternary(t *testing.T, f func(_, _, _ archsimd.Uint8x16) archsimd.Uint8x16, want func(_, _, _ []uint8) []uint8) { - n := 16 - t.Helper() - forSliceTriple(t, uint8s, n, func(x, y, z []uint8) bool { - t.Helper() - a := archsimd.LoadUint8x16(x) - b := archsimd.LoadUint8x16(y) - c := archsimd.LoadUint8x16(z) - g := make([]uint8, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint16x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint16x8Ternary(t *testing.T, f func(_, _, _ archsimd.Uint16x8) archsimd.Uint16x8, want func(_, _, _ []uint16) []uint16) { - n := 8 - t.Helper() - forSliceTriple(t, uint16s, n, func(x, y, z []uint16) bool { - t.Helper() - a := archsimd.LoadUint16x8(x) - b := archsimd.LoadUint16x8(y) - c := archsimd.LoadUint16x8(z) - g := make([]uint16, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint32x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Uint32x4) archsimd.Uint32x4, want func(_, _, _ []uint32) []uint32) { - n := 4 - t.Helper() - forSliceTriple(t, uint32s, n, func(x, y, z []uint32) bool { - t.Helper() - a := archsimd.LoadUint32x4(x) - b := archsimd.LoadUint32x4(y) - c := archsimd.LoadUint32x4(z) - g := make([]uint32, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testUint64x2Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Uint64x2) archsimd.Uint64x2, want func(_, _, _ []uint64) []uint64) { - n := 2 - t.Helper() - forSliceTriple(t, uint64s, n, func(x, y, z []uint64) bool { - t.Helper() - a := archsimd.LoadUint64x2(x) - b := archsimd.LoadUint64x2(y) - c := archsimd.LoadUint64x2(z) - g := make([]uint64, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testFloat32x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testFloat32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Float32x4) archsimd.Float32x4, want func(_, _, _ []float32) []float32) { - n := 4 - t.Helper() - forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { - t.Helper() - a := archsimd.LoadFloat32x4(x) - b := archsimd.LoadFloat32x4(y) - c := archsimd.LoadFloat32x4(z) - g := make([]float32, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - -// testFloat64x2Ternary tests the simd ternary method f against the expected behavior generated by want -func testFloat64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Float64x2) archsimd.Float64x2, want func(_, _, _ []float64) []float64) { - n := 2 - t.Helper() - forSliceTriple(t, float64s, n, func(x, y, z []float64) bool { - t.Helper() - a := archsimd.LoadFloat64x2(x) - b := archsimd.LoadFloat64x2(y) - c := archsimd.LoadFloat64x2(z) - g := make([]float64, n) - f(a, b, c).Store(g) - w := want(x, y, z) - return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) - }) -} - // testInt8x32Ternary tests the simd ternary method f against the expected behavior generated by want func testInt8x32Ternary(t *testing.T, f func(_, _, _ archsimd.Int8x32) archsimd.Int8x32, want func(_, _, _ []int8) []int8) { n := 32 @@ -493,16 +333,16 @@ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) }) } -// testFloat32x4TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, +// testFloat32x8TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat32x4TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float32x4) archsimd.Float32x4, want func(x, y, z []float32) []float32, flakiness float64) { - n := 4 +func testFloat32x8TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float32x8) archsimd.Float32x8, want func(x, y, z []float32) []float32, flakiness float64) { + n := 8 t.Helper() forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { t.Helper() - a := archsimd.LoadFloat32x4(x) - b := archsimd.LoadFloat32x4(y) - c := archsimd.LoadFloat32x4(z) + a := archsimd.LoadFloat32x8(x) + b := archsimd.LoadFloat32x8(y) + c := archsimd.LoadFloat32x8(z) g := make([]float32, n) f(a, b, c).Store(g) w := want(x, y, z) @@ -510,17 +350,17 @@ return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) }) } -// testFloat32x8TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, +// testFloat64x4TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat32x8TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float32x8) archsimd.Float32x8, want func(x, y, z []float32) []float32, flakiness float64) { - n := 8 +func testFloat64x4TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float64x4) archsimd.Float64x4, want func(x, y, z []float64) []float64, flakiness float64) { + n := 4 t.Helper() - forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { + forSliceTriple(t, float64s, n, func(x, y, z []float64) bool { t.Helper() - a := archsimd.LoadFloat32x8(x) - b := archsimd.LoadFloat32x8(y) - c := archsimd.LoadFloat32x8(z) - g := make([]float32, n) + a := archsimd.LoadFloat64x4(x) + b := archsimd.LoadFloat64x4(y) + c := archsimd.LoadFloat64x4(z) + g := make([]float64, n) f(a, b, c).Store(g) w := want(x, y, z) return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) @@ -543,3 +383,20 @@ w := want(x, y, z) return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) }) } + +// testFloat64x8TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, +// but using a flakiness parameter because we haven't exactly figured out how simd floating point works +func testFloat64x8TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float64x8) archsimd.Float64x8, want func(x, y, z []float64) []float64, flakiness float64) { + n := 8 + t.Helper() + forSliceTriple(t, float64s, n, func(x, y, z []float64) bool { + t.Helper() + a := archsimd.LoadFloat64x8(x) + b := archsimd.LoadFloat64x8(y) + c := archsimd.LoadFloat64x8(z) + g := make([]float64, n) + f(a, b, c).Store(g) + w := want(x, y, z) + return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) }) + }) +} diff --git a/src/simd/archsimd/internal/simd_test/unary_128_test.go b/src/simd/archsimd/internal/simd_test/unary_128_test.go index 416978d13dcf5d2add15b6af9cffeeb2775bad66..afad2665b8ec5783662c94eff6c9593fb3cfa7c7 100644 --- a/src/simd/archsimd/internal/simd_test/unary_128_test.go +++ b/src/simd/archsimd/internal/simd_test/unary_128_test.go @@ -2,11 +2,12 @@ // Copyright 2025 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 && wasm +//go:build goexperiment.simd && (amd64 || wasm || arm64) package simd_test import ( + "runtime" "simd/archsimd" "testing" ) @@ -46,25 +47,30 @@ testInt32x4Unary(t, archsimd.Int32x4.Not, map1[int32](not)) testInt64x2Unary(t, archsimd.Int64x2.Not, map1[int64](not)) } -func TestAbsolute(t *testing.T) { +func TestAbs(t *testing.T) { + testFloat32x4Unary(t, archsimd.Float32x4.Abs, map1[float32](abs)) + testFloat64x2Unary(t, archsimd.Float64x2.Abs, map1[float64](abs)) testInt8x16Unary(t, archsimd.Int8x16.Abs, map1[int8](abs)) testInt16x8Unary(t, archsimd.Int16x8.Abs, map1[int16](abs)) testInt32x4Unary(t, archsimd.Int32x4.Abs, map1[int32](abs)) + if runtime.GOARCH != "amd64" || archsimd.X86.AVX512() { + testInt64x2Unary(t, archsimd.Int64x2.Abs, map1[int64](abs)) + } +} + +func TestNeg(t *testing.T) { + testFloat32x4Unary(t, archsimd.Float32x4.Neg, map1[float32](neg)) + testFloat64x2Unary(t, archsimd.Float64x2.Neg, map1[float64](neg)) + testInt8x16Unary(t, archsimd.Int8x16.Neg, map1[int8](neg)) + testInt16x8Unary(t, archsimd.Int16x8.Neg, map1[int16](neg)) + testInt32x4Unary(t, archsimd.Int32x4.Neg, map1[int32](neg)) + testInt64x2Unary(t, archsimd.Int64x2.Neg, map1[int64](neg)) } func TestOnesCount(t *testing.T) { + if runtime.GOARCH == "amd64" && !archsimd.X86.AVX512BITALG() { + t.Skip("OnesCount on 128-bit 8-bit vectors on amd64 requires AVX512BITALG") + } testInt8x16Unary(t, archsimd.Int8x16.OnesCount, map1[int8](onesCount)) - testInt16x8Unary(t, archsimd.Int16x8.OnesCount, map1[int16](onesCount)) - testInt32x4Unary(t, archsimd.Int32x4.OnesCount, map1[int32](onesCount)) + testUint8x16Unary(t, archsimd.Uint8x16.OnesCount, map1[uint8](onesCount)) } - -// func TestConvert(t *testing.T) { -// testFloat64x2ConvertToFloat32(t, archsimd.Float64x2.ConvertToFloat32, map1n[float64](toFloat32, 4)) -// testFloat32x4ConvertToFloat64(t, archsimd.Float32x4.ConvertToFloat64, map1[float32](toFloat64)) - -// testFloat32x4ConvertToInt32(t, archsimd.Float32x4.ConvertToInt32, map1[float32](floatToInt32_x86)) -// testFloat64x2ConvertToInt32(t, archsimd.Float64x2.ConvertToInt32, map1n[float64](floatToInt32_x86, 4)) - -// testInt32x4ConvertToFloat32(t, archsimd.Int32x4.ConvertToFloat32, map1[int32](toFloat32)) -// testInt32x4ConvertToFloat64(t, archsimd.Int32x4.ConvertToFloat64, map1[int32](toFloat64)) -// } diff --git a/src/simd/archsimd/internal/simd_test/unary_helpers_128_test.go b/src/simd/archsimd/internal/simd_test/unary_helpers_128_test.go index dee8c3ac1cc25664e0224d661b925da68e9fdbf8..dc6bf82cf3a3a9b7400d89aa0fc0860d170484ea 100644 --- a/src/simd/archsimd/internal/simd_test/unary_helpers_128_test.go +++ b/src/simd/archsimd/internal/simd_test/unary_helpers_128_test.go @@ -1,6 +1,6 @@ // Code generated by 'tmplgen'; DO NOT EDIT. -//go:build goexperiment.simd && (amd64 || wasm) +//go:build goexperiment.simd && (amd64 || wasm || arm64) // This file contains functions testing unary simd methods. // Each function in this file is specialized for a diff --git a/src/simd/archsimd/internal/simd_test/unary_test.go b/src/simd/archsimd/internal/simd_test/unary_amd64_test.go rename from src/simd/archsimd/internal/simd_test/unary_test.go rename to src/simd/archsimd/internal/simd_test/unary_amd64_test.go index 8d390f039bf6435dbfb7bdb085ee98ec468f2d76..734e21d281b6bc7490730b3a9a2acd98e9730626 100644 --- a/src/simd/archsimd/internal/simd_test/unary_test.go +++ b/src/simd/archsimd/internal/simd_test/unary_amd64_test.go @@ -12,32 +12,46 @@ "simd/archsimd" "testing" ) -func TestAbsFP(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Abs, map1[float32](abs)) +func TestAbsAMD64(t *testing.T) { testFloat32x8Unary(t, archsimd.Float32x8.Abs, map1[float32](abs)) - testFloat64x2Unary(t, archsimd.Float64x2.Abs, map1[float64](abs)) testFloat64x4Unary(t, archsimd.Float64x4.Abs, map1[float64](abs)) + if archsimd.X86.AVX2() { + testInt8x32Unary(t, archsimd.Int8x32.Abs, map1[int8](abs)) + testInt16x16Unary(t, archsimd.Int16x16.Abs, map1[int16](abs)) + testInt32x8Unary(t, archsimd.Int32x8.Abs, map1[int32](abs)) + } if archsimd.X86.AVX512() { - testFloat32x16Unary(t, archsimd.Float32x16.Abs, map1[float32](abs)) // missing - testFloat64x8Unary(t, archsimd.Float64x8.Abs, map1[float64](abs)) // missing + testInt8x64Unary(t, archsimd.Int8x64.Abs, map1[int8](abs)) + testInt16x32Unary(t, archsimd.Int16x32.Abs, map1[int16](abs)) + testInt32x16Unary(t, archsimd.Int32x16.Abs, map1[int32](abs)) + testInt64x4Unary(t, archsimd.Int64x4.Abs, map1[int64](abs)) + testInt64x8Unary(t, archsimd.Int64x8.Abs, map1[int64](abs)) + testFloat32x16Unary(t, archsimd.Float32x16.Abs, map1[float32](abs)) + testFloat64x8Unary(t, archsimd.Float64x8.Abs, map1[float64](abs)) } } -func TestNegFP(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Neg, map1[float32](neg)) +func TestNegAMD64(t *testing.T) { testFloat32x8Unary(t, archsimd.Float32x8.Neg, map1[float32](neg)) - testFloat64x2Unary(t, archsimd.Float64x2.Neg, map1[float64](neg)) testFloat64x4Unary(t, archsimd.Float64x4.Neg, map1[float64](neg)) + if archsimd.X86.AVX2() { + testInt8x32Unary(t, archsimd.Int8x32.Neg, map1[int8](neg)) + testInt16x16Unary(t, archsimd.Int16x16.Neg, map1[int16](neg)) + testInt32x8Unary(t, archsimd.Int32x8.Neg, map1[int32](neg)) + testInt64x4Unary(t, archsimd.Int64x4.Neg, map1[int64](neg)) + } if archsimd.X86.AVX512() { - testFloat32x16Unary(t, archsimd.Float32x16.Neg, map1[float32](neg)) // missing - testFloat64x8Unary(t, archsimd.Float64x8.Neg, map1[float64](neg)) // missing + testFloat32x16Unary(t, archsimd.Float32x16.Neg, map1[float32](neg)) + testFloat64x8Unary(t, archsimd.Float64x8.Neg, map1[float64](neg)) + testInt8x64Unary(t, archsimd.Int8x64.Neg, map1[int8](neg)) + testInt16x32Unary(t, archsimd.Int16x32.Neg, map1[int16](neg)) + testInt32x16Unary(t, archsimd.Int32x16.Neg, map1[int32](neg)) + testInt64x8Unary(t, archsimd.Int64x8.Neg, map1[int64](neg)) } } -func TestCeil(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Ceil, ceilSlice[float32]) +func TestCeilAMD64(t *testing.T) { testFloat32x8Unary(t, archsimd.Float32x8.Ceil, ceilSlice[float32]) - testFloat64x2Unary(t, archsimd.Float64x2.Ceil, ceilSlice[float64]) testFloat64x4Unary(t, archsimd.Float64x4.Ceil, ceilSlice[float64]) if archsimd.X86.AVX512() { // testFloat32x16Unary(t, archsimd.Float32x16.Ceil, ceilSlice[float32]) // missing @@ -45,10 +59,8 @@ // testFloat64x8Unary(t, archsimd.Float64x8.Ceil, ceilSlice[float64]) // missing } } -func TestFloor(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Floor, floorSlice[float32]) +func TestFloorAMD64(t *testing.T) { testFloat32x8Unary(t, archsimd.Float32x8.Floor, floorSlice[float32]) - testFloat64x2Unary(t, archsimd.Float64x2.Floor, floorSlice[float64]) testFloat64x4Unary(t, archsimd.Float64x4.Floor, floorSlice[float64]) if archsimd.X86.AVX512() { // testFloat32x16Unary(t, archsimd.Float32x16.Floor, floorSlice[float32]) // missing @@ -56,10 +68,8 @@ // testFloat64x8Unary(t, archsimd.Float64x8.Floor, floorSlice[float64]) // missing } } -func TestTrunc(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Trunc, truncSlice[float32]) +func TestTruncAMD64(t *testing.T) { testFloat32x8Unary(t, archsimd.Float32x8.Trunc, truncSlice[float32]) - testFloat64x2Unary(t, archsimd.Float64x2.Trunc, truncSlice[float64]) testFloat64x4Unary(t, archsimd.Float64x4.Trunc, truncSlice[float64]) if archsimd.X86.AVX512() { // testFloat32x16Unary(t, archsimd.Float32x16.Trunc, truncSlice[float32]) // missing @@ -67,10 +77,8 @@ // testFloat64x8Unary(t, archsimd.Float64x8.Trunc, truncSlice[float64]) // missing } } -func TestRound(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Round, roundSlice[float32]) +func TestRoundAMD64(t *testing.T) { testFloat32x8Unary(t, archsimd.Float32x8.Round, roundSlice[float32]) - testFloat64x2Unary(t, archsimd.Float64x2.Round, roundSlice[float64]) testFloat64x4Unary(t, archsimd.Float64x4.Round, roundSlice[float64]) if archsimd.X86.AVX512() { // testFloat32x16Unary(t, archsimd.Float32x16.Round, roundSlice[float32]) // missing @@ -78,10 +86,8 @@ // testFloat64x8Unary(t, archsimd.Float64x8.Round, roundSlice[float64]) // missing } } -func TestSqrt(t *testing.T) { - testFloat32x4Unary(t, archsimd.Float32x4.Sqrt, sqrtSlice[float32]) +func TestSqrtAMD64(t *testing.T) { testFloat32x8Unary(t, archsimd.Float32x8.Sqrt, sqrtSlice[float32]) - testFloat64x2Unary(t, archsimd.Float64x2.Sqrt, sqrtSlice[float64]) testFloat64x4Unary(t, archsimd.Float64x4.Sqrt, sqrtSlice[float64]) if archsimd.X86.AVX512() { testFloat32x16Unary(t, archsimd.Float32x16.Sqrt, sqrtSlice[float32]) @@ -89,41 +95,13 @@ testFloat64x8Unary(t, archsimd.Float64x8.Sqrt, sqrtSlice[float64]) } } -func TestNot(t *testing.T) { - testInt8x16Unary(t, archsimd.Int8x16.Not, map1[int8](not)) +func TestNotAMD64(t *testing.T) { testInt16x8Unary(t, archsimd.Int16x8.Not, map1[int16](not)) - testInt32x4Unary(t, archsimd.Int32x4.Not, map1[int32](not)) if archsimd.X86.AVX2() { testInt8x32Unary(t, archsimd.Int8x32.Not, map1[int8](not)) testInt16x16Unary(t, archsimd.Int16x16.Not, map1[int16](not)) testInt32x8Unary(t, archsimd.Int32x8.Not, map1[int32](not)) - } -} - -func TestAbsolute(t *testing.T) { - testInt8x16Unary(t, archsimd.Int8x16.Abs, map1[int8](abs)) - testInt16x8Unary(t, archsimd.Int16x8.Abs, map1[int16](abs)) - testInt32x4Unary(t, archsimd.Int32x4.Abs, map1[int32](abs)) - testFloat32x4Unary(t, archsimd.Float32x4.Abs, map1[float32](abs)) - testFloat64x2Unary(t, archsimd.Float64x2.Abs, map1[float64](abs)) - - if archsimd.X86.AVX2() { - testInt8x32Unary(t, archsimd.Int8x32.Abs, map1[int8](abs)) - testInt16x16Unary(t, archsimd.Int16x16.Abs, map1[int16](abs)) - testInt32x8Unary(t, archsimd.Int32x8.Abs, map1[int32](abs)) - testFloat32x8Unary(t, archsimd.Float32x8.Abs, map1[float32](abs)) - testFloat64x4Unary(t, archsimd.Float64x4.Abs, map1[float64](abs)) - } - if archsimd.X86.AVX512() { - testInt8x64Unary(t, archsimd.Int8x64.Abs, map1[int8](abs)) - testInt16x32Unary(t, archsimd.Int16x32.Abs, map1[int16](abs)) - testInt32x16Unary(t, archsimd.Int32x16.Abs, map1[int32](abs)) - testInt64x2Unary(t, archsimd.Int64x2.Abs, map1[int64](abs)) - testInt64x4Unary(t, archsimd.Int64x4.Abs, map1[int64](abs)) - testInt64x8Unary(t, archsimd.Int64x8.Abs, map1[int64](abs)) - testFloat32x16Unary(t, archsimd.Float32x16.Abs, map1[float32](abs)) - testFloat64x8Unary(t, archsimd.Float64x8.Abs, map1[float64](abs)) } } @@ -340,3 +318,43 @@ testUint64x4ConvertToUint32(t, archsimd.Uint64x4.SaturateToUint32, map1[uint64](satToUint32)) testUint64x8ConvertToUint32(t, archsimd.Uint64x8.SaturateToUint32, map1[uint64](satToUint32)) } } + +func TestOnesCountAMD64(t *testing.T) { + if archsimd.X86.AVX512BITALG() { + // 128-bit + testInt16x8Unary(t, archsimd.Int16x8.OnesCount, map1[int16](onesCount)) + testUint16x8Unary(t, archsimd.Uint16x8.OnesCount, map1[uint16](onesCount)) + + // 256-bit + testInt8x32Unary(t, archsimd.Int8x32.OnesCount, map1[int8](onesCount)) + testUint8x32Unary(t, archsimd.Uint8x32.OnesCount, map1[uint8](onesCount)) + testInt16x16Unary(t, archsimd.Int16x16.OnesCount, map1[int16](onesCount)) + testUint16x16Unary(t, archsimd.Uint16x16.OnesCount, map1[uint16](onesCount)) + + // 512-bit + testInt8x64Unary(t, archsimd.Int8x64.OnesCount, map1[int8](onesCount)) + testUint8x64Unary(t, archsimd.Uint8x64.OnesCount, map1[uint8](onesCount)) + testInt16x32Unary(t, archsimd.Int16x32.OnesCount, map1[int16](onesCount)) + testUint16x32Unary(t, archsimd.Uint16x32.OnesCount, map1[uint16](onesCount)) + } + + if archsimd.X86.AVX512VPOPCNTDQ() { + // 128-bit + testInt32x4Unary(t, archsimd.Int32x4.OnesCount, map1[int32](onesCount)) + testUint32x4Unary(t, archsimd.Uint32x4.OnesCount, map1[uint32](onesCount)) + testInt64x2Unary(t, archsimd.Int64x2.OnesCount, map1[int64](onesCount)) + testUint64x2Unary(t, archsimd.Uint64x2.OnesCount, map1[uint64](onesCount)) + + // 256-bit + testInt32x8Unary(t, archsimd.Int32x8.OnesCount, map1[int32](onesCount)) + testUint32x8Unary(t, archsimd.Uint32x8.OnesCount, map1[uint32](onesCount)) + testInt64x4Unary(t, archsimd.Int64x4.OnesCount, map1[int64](onesCount)) + testUint64x4Unary(t, archsimd.Uint64x4.OnesCount, map1[uint64](onesCount)) + + // 512-bit + testInt32x16Unary(t, archsimd.Int32x16.OnesCount, map1[int32](onesCount)) + testUint32x16Unary(t, archsimd.Uint32x16.OnesCount, map1[uint32](onesCount)) + testInt64x8Unary(t, archsimd.Int64x8.OnesCount, map1[int64](onesCount)) + testUint64x8Unary(t, archsimd.Uint64x8.OnesCount, map1[uint64](onesCount)) + } +} diff --git a/src/simd/archsimd/internal/simd_test/unary_wasm_test.go b/src/simd/archsimd/internal/simd_test/unary_wasm_test.go new file mode 100644 index 0000000000000000000000000000000000000000..3275030ce84ef51b69dcf5b2711469284e638bd8 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/unary_wasm_test.go @@ -0,0 +1,21 @@ +// 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 && wasm + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +func TestOnesCountWasm(t *testing.T) { + testInt16x8Unary(t, archsimd.Int16x8.OnesCount, map1[int16](onesCount)) + testUint16x8Unary(t, archsimd.Uint16x8.OnesCount, map1[uint16](onesCount)) + testInt32x4Unary(t, archsimd.Int32x4.OnesCount, map1[int32](onesCount)) + testUint32x4Unary(t, archsimd.Uint32x4.OnesCount, map1[uint32](onesCount)) + testInt64x2Unary(t, archsimd.Int64x2.OnesCount, map1[int64](onesCount)) + testUint64x2Unary(t, archsimd.Uint64x2.OnesCount, map1[uint64](onesCount)) +} diff --git a/src/simd/archsimd/ops_internal_arm64.go b/src/simd/archsimd/ops_internal_arm64.go index 8a47bfe0de9fe0f70ac8e3ebdd18df5cbe8f99a1..49f92db776d150b7891c5ab8820c76d45c435ed6 100644 --- a/src/simd/archsimd/ops_internal_arm64.go +++ b/src/simd/archsimd/ops_internal_arm64.go @@ -6,16 +6,16 @@ package archsimd /* bitSelect */ -// bitSelect selects bits from y where mask is 1, keeps bits from x where mask is 0. +// bitSelect returns the bitwise selection if mask[i] then x[i] else y[i]. // -// Asm: VBIT, CPU Feature: NEON +// Asm: VBIF, CPU Feature: NEON func (x Int8x16) bitSelect(y Int8x16, mask Int8x16) Int8x16 /* bitSelectNot */ -// bitSelectNot selects bits from y where mask is 0, keeps bits from x where mask is 1. +// bitSelectNot returns the bitwise selection if mask[i] then y[i] else x[i]. // -// Asm: VBIF, CPU Feature: NEON +// Asm: VBIT, CPU Feature: NEON func (x Int8x16) bitSelectNot(y Int8x16, mask Int8x16) Int8x16 /* broadcast1To2 */ diff --git a/src/simd/archsimd/slice_gen_amd64.go b/src/simd/archsimd/slice_gen_amd64.go index 2fddda74829afbf25f9098f8ce15f6fd465fd56c..3005809f14108e9f162fcab252dabdd324c59437 100644 --- a/src/simd/archsimd/slice_gen_amd64.go +++ b/src/simd/archsimd/slice_gen_amd64.go @@ -726,17 +726,18 @@ // StorePart stores the 4 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 4 or more elements, the method is equivalent to x.Store. -func (x Int32x4) StorePart(s []int32) { +func (x Int32x4) StorePart(s []int32) int { l := len(s) if l >= 4 { x.Store(s) - return + return 4 } if l == 0 { - return + return 0 } mask := vecMask32[len(vecMask32)/2-l:] x.StoreArrayMasked(paInt32x4(s), LoadInt32x4(mask).asMask()) + return l } // LoadInt64x2Part loads a Int64x2 from the slice s, it returns the loaded vector and the @@ -759,17 +760,18 @@ // StorePart stores the 2 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 2 or more elements, the method is equivalent to x.Store. -func (x Int64x2) StorePart(s []int64) { +func (x Int64x2) StorePart(s []int64) int { l := len(s) if l >= 2 { x.Store(s) - return + return 2 } if l == 0 { - return + return 0 } mask := vecMask64[len(vecMask64)/2-l:] x.StoreArrayMasked(paInt64x2(s), LoadInt64x2(mask).asMask()) + return l } // LoadUint32x4Part loads a Uint32x4 from the slice s, it returns the loaded vector and the @@ -792,17 +794,18 @@ // StorePart stores the 4 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 4 or more elements, the method is equivalent to x.Store. -func (x Uint32x4) StorePart(s []uint32) { +func (x Uint32x4) StorePart(s []uint32) int { l := len(s) if l >= 4 { x.Store(s) - return + return 4 } if l == 0 { - return + return 0 } mask := vecMask32[len(vecMask32)/2-l:] x.StoreArrayMasked(paUint32x4(s), LoadInt32x4(mask).asMask()) + return l } // LoadUint64x2Part loads a Uint64x2 from the slice s, it returns the loaded vector and the @@ -825,17 +828,18 @@ // StorePart stores the 2 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 2 or more elements, the method is equivalent to x.Store. -func (x Uint64x2) StorePart(s []uint64) { +func (x Uint64x2) StorePart(s []uint64) int { l := len(s) if l >= 2 { x.Store(s) - return + return 2 } if l == 0 { - return + return 0 } mask := vecMask64[len(vecMask64)/2-l:] x.StoreArrayMasked(paUint64x2(s), LoadInt64x2(mask).asMask()) + return l } // LoadFloat32x4Part loads a Float32x4 from the slice s, it returns the loaded vector and the @@ -858,17 +862,18 @@ // StorePart stores the 4 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 4 or more elements, the method is equivalent to x.Store. -func (x Float32x4) StorePart(s []float32) { +func (x Float32x4) StorePart(s []float32) int { l := len(s) if l >= 4 { x.Store(s) - return + return 4 } if l == 0 { - return + return 0 } mask := vecMask32[len(vecMask32)/2-l:] x.StoreArrayMasked(paFloat32x4(s), LoadInt32x4(mask).asMask()) + return l } // LoadFloat64x2Part loads a Float64x2 from the slice s, it returns the loaded vector and the @@ -891,17 +896,18 @@ // StorePart stores the 2 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 2 or more elements, the method is equivalent to x.Store. -func (x Float64x2) StorePart(s []float64) { +func (x Float64x2) StorePart(s []float64) int { l := len(s) if l >= 2 { x.Store(s) - return + return 2 } if l == 0 { - return + return 0 } mask := vecMask64[len(vecMask64)/2-l:] x.StoreArrayMasked(paFloat64x2(s), LoadInt64x2(mask).asMask()) + return l } // LoadInt32x8Part loads a Int32x8 from the slice s, it returns the loaded vector and the @@ -924,17 +930,18 @@ // StorePart stores the 8 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 8 or more elements, the method is equivalent to x.Store. -func (x Int32x8) StorePart(s []int32) { +func (x Int32x8) StorePart(s []int32) int { l := len(s) if l >= 8 { x.Store(s) - return + return 8 } if l == 0 { - return + return 0 } mask := vecMask32[len(vecMask32)/2-l:] x.StoreArrayMasked(paInt32x8(s), LoadInt32x8(mask).asMask()) + return l } // LoadInt64x4Part loads a Int64x4 from the slice s, it returns the loaded vector and the @@ -957,17 +964,18 @@ // StorePart stores the 4 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 4 or more elements, the method is equivalent to x.Store. -func (x Int64x4) StorePart(s []int64) { +func (x Int64x4) StorePart(s []int64) int { l := len(s) if l >= 4 { x.Store(s) - return + return 4 } if l == 0 { - return + return 0 } mask := vecMask64[len(vecMask64)/2-l:] x.StoreArrayMasked(paInt64x4(s), LoadInt64x4(mask).asMask()) + return l } // LoadUint32x8Part loads a Uint32x8 from the slice s, it returns the loaded vector and the @@ -990,17 +998,18 @@ // StorePart stores the 8 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 8 or more elements, the method is equivalent to x.Store. -func (x Uint32x8) StorePart(s []uint32) { +func (x Uint32x8) StorePart(s []uint32) int { l := len(s) if l >= 8 { x.Store(s) - return + return 8 } if l == 0 { - return + return 0 } mask := vecMask32[len(vecMask32)/2-l:] x.StoreArrayMasked(paUint32x8(s), LoadInt32x8(mask).asMask()) + return l } // LoadUint64x4Part loads a Uint64x4 from the slice s, it returns the loaded vector and the @@ -1023,17 +1032,18 @@ // StorePart stores the 4 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 4 or more elements, the method is equivalent to x.Store. -func (x Uint64x4) StorePart(s []uint64) { +func (x Uint64x4) StorePart(s []uint64) int { l := len(s) if l >= 4 { x.Store(s) - return + return 4 } if l == 0 { - return + return 0 } mask := vecMask64[len(vecMask64)/2-l:] x.StoreArrayMasked(paUint64x4(s), LoadInt64x4(mask).asMask()) + return l } // LoadFloat32x8Part loads a Float32x8 from the slice s, it returns the loaded vector and the @@ -1056,17 +1066,18 @@ // StorePart stores the 8 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 8 or more elements, the method is equivalent to x.Store. -func (x Float32x8) StorePart(s []float32) { +func (x Float32x8) StorePart(s []float32) int { l := len(s) if l >= 8 { x.Store(s) - return + return 8 } if l == 0 { - return + return 0 } mask := vecMask32[len(vecMask32)/2-l:] x.StoreArrayMasked(paFloat32x8(s), LoadInt32x8(mask).asMask()) + return l } // LoadFloat64x4Part loads a Float64x4 from the slice s, it returns the loaded vector and the @@ -1089,17 +1100,18 @@ // StorePart stores the 4 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 4 or more elements, the method is equivalent to x.Store. -func (x Float64x4) StorePart(s []float64) { +func (x Float64x4) StorePart(s []float64) int { l := len(s) if l >= 4 { x.Store(s) - return + return 4 } if l == 0 { - return + return 0 } mask := vecMask64[len(vecMask64)/2-l:] x.StoreArrayMasked(paFloat64x4(s), LoadInt64x4(mask).asMask()) + return l } // LoadUint8x32Part loads a Uint8x32 from the slice s, it returns the loaded vector and the @@ -1119,12 +1131,12 @@ // StorePart stores the 32 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 32 or more elements, the method is equivalent to x.Store. -func (x Uint8x32) StorePart(s []uint8) { +func (x Uint8x32) StorePart(s []uint8) int { if len(s) == 0 { - return + return 0 } t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s)) - x.AsInt8x32().StorePart(t) + return x.AsInt8x32().StorePart(t) } // LoadUint16x16Part loads a Uint16x16 from the slice s, it returns the loaded vector and the @@ -1144,10 +1156,10 @@ // StorePart stores the 16 elements of x into the slice s. // It stores as many elements as will fit in s. // If s has 16 or more elements, the method is equivalent to x.Store. -func (x Uint16x16) StorePart(s []uint16) { +func (x Uint16x16) StorePart(s []uint16) int { if len(s) == 0 { - return + return 0 } t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s)) - x.AsInt16x16().StorePart(t) + return x.AsInt16x16().StorePart(t) } diff --git a/src/simd/internal/bridge/decls_amd64.go b/src/simd/internal/bridge/decls_amd64.go index 7bd141085bbfb11c2ba7678baebc02c82f4ce2f4..57083c8e2faf1b380fd8daaed4e97425c418aff5 100644 --- a/src/simd/internal/bridge/decls_amd64.go +++ b/src/simd/internal/bridge/decls_amd64.go @@ -1472,12 +1472,12 @@ func (x Int32x16) StorePart(s []int32) int { return (archsimd.Int32x16(x)).StorePart(s) } -func (x Int32x4) StorePart(s []int32) { - (archsimd.Int32x4(x)).StorePart(s) +func (x Int32x4) StorePart(s []int32) int { + return (archsimd.Int32x4(x)).StorePart(s) } -func (x Int32x8) StorePart(s []int32) { - (archsimd.Int32x8(x)).StorePart(s) +func (x Int32x8) StorePart(s []int32) int { + return (archsimd.Int32x8(x)).StorePart(s) } func (x Int32x16) String() string { @@ -1780,12 +1780,12 @@ func (x Int64x8) Store(s []int64) { (archsimd.Int64x8(x)).Store(s) } -func (x Int64x2) StorePart(s []int64) { - (archsimd.Int64x2(x)).StorePart(s) +func (x Int64x2) StorePart(s []int64) int { + return (archsimd.Int64x2(x)).StorePart(s) } -func (x Int64x4) StorePart(s []int64) { - (archsimd.Int64x4(x)).StorePart(s) +func (x Int64x4) StorePart(s []int64) int { + return (archsimd.Int64x4(x)).StorePart(s) } func (x Int64x8) StorePart(s []int64) int { @@ -2108,8 +2108,8 @@ func (x Uint8x16) StorePart(s []uint8) int { return (archsimd.Uint8x16(x)).StorePart(s) } -func (x Uint8x32) StorePart(s []uint8) { - (archsimd.Uint8x32(x)).StorePart(s) +func (x Uint8x32) StorePart(s []uint8) int { + return (archsimd.Uint8x32(x)).StorePart(s) } func (x Uint8x64) StorePart(s []uint8) int { @@ -2512,8 +2512,8 @@ func (x Uint16x8) Store(s []uint16) { (archsimd.Uint16x8(x)).Store(s) } -func (x Uint16x16) StorePart(s []uint16) { - (archsimd.Uint16x16(x)).StorePart(s) +func (x Uint16x16) StorePart(s []uint16) int { + return (archsimd.Uint16x16(x)).StorePart(s) } func (x Uint16x32) StorePart(s []uint16) int { @@ -2912,12 +2912,12 @@ func (x Uint32x16) StorePart(s []uint32) int { return (archsimd.Uint32x16(x)).StorePart(s) } -func (x Uint32x4) StorePart(s []uint32) { - (archsimd.Uint32x4(x)).StorePart(s) +func (x Uint32x4) StorePart(s []uint32) int { + return (archsimd.Uint32x4(x)).StorePart(s) } -func (x Uint32x8) StorePart(s []uint32) { - (archsimd.Uint32x8(x)).StorePart(s) +func (x Uint32x8) StorePart(s []uint32) int { + return (archsimd.Uint32x8(x)).StorePart(s) } func (x Uint32x16) String() string { @@ -3280,12 +3280,12 @@ func (x Uint64x8) Store(s []uint64) { (archsimd.Uint64x8(x)).Store(s) } -func (x Uint64x2) StorePart(s []uint64) { - (archsimd.Uint64x2(x)).StorePart(s) +func (x Uint64x2) StorePart(s []uint64) int { + return (archsimd.Uint64x2(x)).StorePart(s) } -func (x Uint64x4) StorePart(s []uint64) { - (archsimd.Uint64x4(x)).StorePart(s) +func (x Uint64x4) StorePart(s []uint64) int { + return (archsimd.Uint64x4(x)).StorePart(s) } func (x Uint64x8) StorePart(s []uint64) int { @@ -3572,12 +3572,12 @@ func (x Float32x16) StorePart(s []float32) int { return (archsimd.Float32x16(x)).StorePart(s) } -func (x Float32x4) StorePart(s []float32) { - (archsimd.Float32x4(x)).StorePart(s) +func (x Float32x4) StorePart(s []float32) int { + return (archsimd.Float32x4(x)).StorePart(s) } -func (x Float32x8) StorePart(s []float32) { - (archsimd.Float32x8(x)).StorePart(s) +func (x Float32x8) StorePart(s []float32) int { + return (archsimd.Float32x8(x)).StorePart(s) } func (x Float32x16) String() string { @@ -3844,12 +3844,12 @@ func (x Float64x8) Store(s []float64) { (archsimd.Float64x8(x)).Store(s) } -func (x Float64x2) StorePart(s []float64) { - (archsimd.Float64x2(x)).StorePart(s) +func (x Float64x2) StorePart(s []float64) int { + return (archsimd.Float64x2(x)).StorePart(s) } -func (x Float64x4) StorePart(s []float64) { - (archsimd.Float64x4(x)).StorePart(s) +func (x Float64x4) StorePart(s []float64) int { + return (archsimd.Float64x4(x)).StorePart(s) } func (x Float64x8) StorePart(s []float64) int { @@ -3928,15 +3928,15 @@ func (x Mask8x64) String() string { return (archsimd.Mask8x64(x)).String() } -func (x Mask8x16) ToInt8x16() Int8x16 { +func (x Mask8x16) ToInt8s() Int8x16 { return Int8x16((archsimd.Mask8x16(x)).ToInt8x16()) } -func (x Mask8x32) ToInt8x32() Int8x32 { +func (x Mask8x32) ToInt8s() Int8x32 { return Int8x32((archsimd.Mask8x32(x)).ToInt8x32()) } -func (x Mask8x64) ToInt8x64() Int8x64 { +func (x Mask8x64) ToInt8s() Int8x64 { return Int8x64((archsimd.Mask8x64(x)).ToInt8x64()) } @@ -3976,15 +3976,15 @@ func (x Mask16x8) String() string { return (archsimd.Mask16x8(x)).String() } -func (x Mask16x16) ToInt16x16() Int16x16 { +func (x Mask16x16) ToInt16s() Int16x16 { return Int16x16((archsimd.Mask16x16(x)).ToInt16x16()) } -func (x Mask16x32) ToInt16x32() Int16x32 { +func (x Mask16x32) ToInt16s() Int16x32 { return Int16x32((archsimd.Mask16x32(x)).ToInt16x32()) } -func (x Mask16x8) ToInt16x8() Int16x8 { +func (x Mask16x8) ToInt16s() Int16x8 { return Int16x8((archsimd.Mask16x8(x)).ToInt16x8()) } @@ -4024,15 +4024,15 @@ func (x Mask32x8) String() string { return (archsimd.Mask32x8(x)).String() } -func (x Mask32x16) ToInt32x16() Int32x16 { +func (x Mask32x16) ToInt32s() Int32x16 { return Int32x16((archsimd.Mask32x16(x)).ToInt32x16()) } -func (x Mask32x4) ToInt32x4() Int32x4 { +func (x Mask32x4) ToInt32s() Int32x4 { return Int32x4((archsimd.Mask32x4(x)).ToInt32x4()) } -func (x Mask32x8) ToInt32x8() Int32x8 { +func (x Mask32x8) ToInt32s() Int32x8 { return Int32x8((archsimd.Mask32x8(x)).ToInt32x8()) } @@ -4072,14 +4072,14 @@ func (x Mask64x8) String() string { return (archsimd.Mask64x8(x)).String() } -func (x Mask64x2) ToInt64x2() Int64x2 { +func (x Mask64x2) ToInt64s() Int64x2 { return Int64x2((archsimd.Mask64x2(x)).ToInt64x2()) } -func (x Mask64x4) ToInt64x4() Int64x4 { +func (x Mask64x4) ToInt64s() Int64x4 { return Int64x4((archsimd.Mask64x4(x)).ToInt64x4()) } -func (x Mask64x8) ToInt64x8() Int64x8 { +func (x Mask64x8) ToInt64s() Int64x8 { return Int64x8((archsimd.Mask64x8(x)).ToInt64x8()) } diff --git a/src/simd/internal/bridge/decls_arm64.go b/src/simd/internal/bridge/decls_arm64.go index 335e7af3ea9acdd994a6b392f997fb3b393bdf05..a0f971ef04e3d5f92cc1f33da2cf9fbfda5ab539 100644 --- a/src/simd/internal/bridge/decls_arm64.go +++ b/src/simd/internal/bridge/decls_arm64.go @@ -1316,7 +1316,7 @@ func (x Mask8x16) String() string { return (archsimd.Mask8x16(x)).String() } -func (x Mask8x16) ToInt8x16() Int8x16 { +func (x Mask8x16) ToInt8s() Int8x16 { return Int8x16((archsimd.Mask8x16(x)).ToInt8x16()) } @@ -1332,7 +1332,7 @@ func (x Mask16x8) String() string { return (archsimd.Mask16x8(x)).String() } -func (x Mask16x8) ToInt16x8() Int16x8 { +func (x Mask16x8) ToInt16s() Int16x8 { return Int16x8((archsimd.Mask16x8(x)).ToInt16x8()) } @@ -1348,7 +1348,7 @@ func (x Mask32x4) String() string { return (archsimd.Mask32x4(x)).String() } -func (x Mask32x4) ToInt32x4() Int32x4 { +func (x Mask32x4) ToInt32s() Int32x4 { return Int32x4((archsimd.Mask32x4(x)).ToInt32x4()) } @@ -1364,6 +1364,6 @@ func (x Mask64x2) String() string { return (archsimd.Mask64x2(x)).String() } -func (x Mask64x2) ToInt64x2() Int64x2 { +func (x Mask64x2) ToInt64s() Int64x2 { return Int64x2((archsimd.Mask64x2(x)).ToInt64x2()) } diff --git a/src/simd/internal/bridge/decls_wasm.go b/src/simd/internal/bridge/decls_wasm.go index 013482e3274dedf1e124b6479feb287925abb024..72064dc535116c319ff78772d2ec4948b977043c 100644 --- a/src/simd/internal/bridge/decls_wasm.go +++ b/src/simd/internal/bridge/decls_wasm.go @@ -1316,7 +1316,7 @@ func (x Mask8x16) String() string { return (archsimd.Mask8x16(x)).String() } -func (x Mask8x16) ToInt8x16() Int8x16 { +func (x Mask8x16) ToInt8s() Int8x16 { return Int8x16((archsimd.Mask8x16(x)).ToInt8x16()) } @@ -1332,7 +1332,7 @@ func (x Mask16x8) String() string { return (archsimd.Mask16x8(x)).String() } -func (x Mask16x8) ToInt16x8() Int16x8 { +func (x Mask16x8) ToInt16s() Int16x8 { return Int16x8((archsimd.Mask16x8(x)).ToInt16x8()) } @@ -1348,7 +1348,7 @@ func (x Mask32x4) String() string { return (archsimd.Mask32x4(x)).String() } -func (x Mask32x4) ToInt32x4() Int32x4 { +func (x Mask32x4) ToInt32s() Int32x4 { return Int32x4((archsimd.Mask32x4(x)).ToInt32x4()) } @@ -1364,6 +1364,6 @@ func (x Mask64x2) String() string { return (archsimd.Mask64x2(x)).String() } -func (x Mask64x2) ToInt64x2() Int64x2 { +func (x Mask64x2) ToInt64s() Int64x2 { return Int64x2((archsimd.Mask64x2(x)).ToInt64x2()) } diff --git a/src/simd/internal/bridge/simd_emulated.go b/src/simd/internal/bridge/simd_emulated.go index 4a82d166c9956a4af2bc4ea3c0189e2b5969bf7c..b6d0d729ea55c28e7da2f7a6cfde27275b214cad 100644 --- a/src/simd/internal/bridge/simd_emulated.go +++ b/src/simd/internal/bridge/simd_emulated.go @@ -7,7 +7,7 @@ package bridge import ( - "fmt" + "internal/strconv" "math" "math/bits" ) @@ -32,14 +32,41 @@ func HasHardwareCarrylessMultiply() bool { return false } -type _simd struct { - _ [0]func(*_simd) *_simd +type number interface { + ~int8 | ~int16 | ~int32 | ~int64 | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64 } -// Int8s represents a 128-bit vector of 16 int8 elements. -type Int8s struct { - _ _simd - a, b uint64 +func sliceToString[T number](x []T) string { + s := "" + pfx := "{" + for _, y := range x { + s += pfx + pfx = "," + switch e := any(y).(type) { + case int8: + s += strconv.Itoa(int(e)) + case int16: + s += strconv.Itoa(int(e)) + case int32: + s += strconv.Itoa(int(e)) + case int64: + s += strconv.FormatInt(int64(e), 10) + case uint8: + s += strconv.FormatUint(uint64(e), 10) + case uint16: + s += strconv.FormatUint(uint64(e), 10) + case uint32: + s += strconv.FormatUint(uint64(e), 10) + case uint64: + s += strconv.FormatUint(uint64(e), 10) + case float32: + s += strconv.FormatFloat(float64(e), 'g', -1, 32) + case float64: + s += strconv.FormatFloat(e, 'g', -1, 64) + } + } + s += "}" + return s } // LoadInt8s loads a slice of int8 into an Int8s vector. @@ -302,7 +329,7 @@ var parts [16]int8 for i := 0; i < 16; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -356,12 +383,6 @@ func (x Int8s) ToBits() Uint8s { return Uint8s{a: x.a, b: x.b} } -// Int16s represents a 128-bit vector of 8 int16 elements. -type Int16s struct { - _ _simd - a, b uint64 -} - // LoadInt16s loads a slice of int16 into an Int16s vector. func LoadInt16s(s []int16) Int16s { var a, b uint64 @@ -664,7 +685,7 @@ var parts [8]int16 for i := 0; i < 8; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -716,12 +737,6 @@ // ToBits reinterprets the vector bits as a Uint16s vector. func (x Int16s) ToBits() Uint16s { return Uint16s{a: x.a, b: x.b} -} - -// Int32s represents a 128-bit vector of 4 int32 elements. -type Int32s struct { - _ _simd - a, b uint64 } // LoadInt32s loads a slice of int32 into an Int32s vector. @@ -1019,7 +1034,7 @@ var parts [4]int32 for i := 0; i < 4; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -1057,12 +1072,6 @@ func (x Int32s) ToBits() Uint32s { return Uint32s{a: x.a, b: x.b} } -// Int64s represents a 128-bit vector of 2 int64 elements. -type Int64s struct { - _ _simd - a, b uint64 -} - // LoadInt64s loads a slice of int64 into an Int64s vector. func LoadInt64s(s []int64) Int64s { var a, b uint64 @@ -1259,7 +1268,7 @@ } // String returns a string representation of the vector. func (x Int64s) String() string { - return fmt.Sprint([2]int64{int64(x.a), int64(x.b)}) + return sliceToString([]int64{int64(x.a), int64(x.b)}) } // Sub returns the element-wise difference of x and y. @@ -1294,12 +1303,6 @@ func (x Int64s) ToBits() Uint64s { return Uint64s{a: x.a, b: x.b} } -// Uint8s represents a 128-bit vector of 16 uint8 elements. -type Uint8s struct { - _ _simd - a, b uint64 -} - // LoadUint8s loads a slice of uint8 into an Uint8s vector. func LoadUint8s(s []uint8) Uint8s { var a, b uint64 @@ -1500,7 +1503,7 @@ var parts [16]uint8 for i := 0; i < 16; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -1557,12 +1560,6 @@ func (x Uint8s) ReshapeToUint64s() Uint64s { return Uint64s{a: x.a, b: x.b} } -// Uint16s represents a 128-bit vector of 8 uint16 elements. -type Uint16s struct { - _ _simd - a, b uint64 -} - // LoadUint16s loads a slice of uint16 into an Uint16s vector. func LoadUint16s(s []uint16) Uint16s { var a, b uint64 @@ -1849,7 +1846,7 @@ var parts [8]uint16 for i := 0; i < 8; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -1904,12 +1901,6 @@ // ReshapeToUint8s reinterprets the vector bits as a Uint8s vector. func (x Uint16s) ReshapeToUint8s() Uint8s { return Uint8s{a: x.a, b: x.b} -} - -// Uint32s represents a 128-bit vector of 4 uint32 elements. -type Uint32s struct { - _ _simd - a, b uint64 } // LoadUint32s loads a slice of uint32 into an Uint32s vector. @@ -2175,7 +2166,7 @@ var parts [4]uint32 for i := 0; i < 4; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -2220,12 +2211,6 @@ // ReshapeToUint8s reinterprets the vector bits as a Uint8s vector. func (x Uint32s) ReshapeToUint8s() Uint8s { return Uint8s{a: x.a, b: x.b} -} - -// Uint64s represents a 128-bit vector of 2 uint64 elements. -type Uint64s struct { - _ _simd - a, b uint64 } // LoadUint64s loads a slice of uint64 into an Uint64s vector. @@ -2421,7 +2406,7 @@ } // String returns a string representation of the vector. func (x Uint64s) String() string { - return fmt.Sprint([2]uint64{x.a, x.b}) + return sliceToString([]uint64{x.a, x.b}) } // Sub returns the element-wise difference of x and y. @@ -2464,12 +2449,6 @@ func (x Uint64s) ReshapeToUint8s() Uint8s { return Uint8s{a: x.a, b: x.b} } -// Float32s represents a 128-bit vector of 4 float32 elements. -type Float32s struct { - _ _simd - a, b uint64 -} - // LoadFloat32s loads a slice of float32 into an Float32s vector. func LoadFloat32s(s []float32) Float32s { var a, b uint64 @@ -2672,7 +2651,6 @@ res.set(0, x.get(0)*y.get(0)) res.set(1, x.get(1)*y.get(1)) res.set(2, x.get(2)*y.get(2)) res.set(3, x.get(3)*y.get(3)) - return res } @@ -2684,7 +2662,6 @@ res.set(0, x.get(0)*y.get(0)+z.get(0)) res.set(1, x.get(1)*y.get(1)+z.get(1)) res.set(2, x.get(2)*y.get(2)+z.get(2)) res.set(3, x.get(3)*y.get(3)+z.get(3)) - return res } @@ -2736,7 +2713,7 @@ var parts [4]float32 for i := 0; i < 4; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -2753,12 +2730,6 @@ func (x Float32s) ToBits() Uint32s { return Uint32s{a: x.a, b: x.b} } -// Float64s represents a 128-bit vector of 2 float64 elements. -type Float64s struct { - _ _simd - a, b uint64 -} - // LoadFloat64s loads a slice of float64 into an Float64s vector. func LoadFloat64s(s []float64) Float64s { var a, b uint64 @@ -3006,7 +2977,7 @@ } // String returns a string representation of the vector. func (x Float64s) String() string { - return fmt.Sprint([2]float64{x.get(0), x.get(1)}) + return sliceToString([]float64{x.get(0), x.get(1)}) } // Sub returns the element-wise difference of x and y. @@ -3022,12 +2993,6 @@ func (x Float64s) ToBits() Uint64s { return Uint64s{a: x.a, b: x.b} } -// Mask8s represents a 128-bit mask vector for 16 int8/uint8 elements. -type Mask8s struct { - _ _simd - a, b uint64 -} - func (x *Mask8s) set(i int, v bool) { if v { if i < 8 { @@ -3052,7 +3017,9 @@ } // String returns a string representation of the vector. func (x Mask8s) String() string { - return fmt.Sprintf("{a:%#x, b:%#x}", x.a, x.b) + var s [16]int8 + x.ToInt8s().Neg().Store(s[:]) + return sliceToString(s[:]) } // ToInt8s converts the mask to an Int8s vector. @@ -3060,12 +3027,6 @@ func (x Mask8s) ToInt8s() Int8s { return Int8s{a: x.a, b: x.b} } -// Mask16s represents a 128-bit mask vector for 8 int16/uint16 elements. -type Mask16s struct { - _ _simd - a, b uint64 -} - func (x *Mask16s) set(i int, v bool) { if v { if i < 4 { @@ -3090,7 +3051,9 @@ } // String returns a string representation of the vector. func (x Mask16s) String() string { - return fmt.Sprintf("{a:%#x, b:%#x}", x.a, x.b) + var s [8]int16 + x.ToInt16s().Neg().Store(s[:]) + return sliceToString(s[:]) } // ToInt16s converts the mask to an Int16s vector. @@ -3098,12 +3061,6 @@ func (x Mask16s) ToInt16s() Int16s { return Int16s{a: x.a, b: x.b} } -// Mask32s represents a 128-bit mask vector for 4 int32/uint32/float32 elements. -type Mask32s struct { - _ _simd - a, b uint64 -} - func (x *Mask32s) set(i int, v bool) { if v { if i < 2 { @@ -3128,7 +3085,9 @@ } // String returns a string representation of the vector. func (x Mask32s) String() string { - return fmt.Sprintf("{a:%#x, b:%#x}", x.a, x.b) + var s [4]int32 + x.ToInt32s().Neg().Store(s[:]) + return sliceToString(s[:]) } // ToInt32s converts the mask to an Int32s vector. @@ -3136,12 +3095,6 @@ func (x Mask32s) ToInt32s() Int32s { return Int32s{a: x.a, b: x.b} } -// Mask64s represents a 128-bit mask vector for 2 int64/uint64/float64 elements. -type Mask64s struct { - _ _simd - a, b uint64 -} - func (x *Mask64s) set(i int, v bool) { if v { if i == 0 { @@ -3164,7 +3117,9 @@ } // String returns a string representation of the vector. func (x Mask64s) String() string { - return fmt.Sprintf("{a:%#x, b:%#x}", x.a, x.b) + var s [2]int64 + x.ToInt64s().Neg().Store(s[:]) + return sliceToString(s[:]) } // ToInt64s converts the mask to an Int64s vector. diff --git a/src/simd/internal/bridge/simd_types_emulated.go b/src/simd/internal/bridge/simd_types_emulated.go new file mode 100644 index 0000000000000000000000000000000000000000..d7aa0bee03daa5b580a813a34ea4bcd48ff544a1 --- /dev/null +++ b/src/simd/internal/bridge/simd_types_emulated.go @@ -0,0 +1,95 @@ +// 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 && (amd64 || wasm || arm64) + +package bridge + +type _simd struct { + _ [0]func(*_simd) *_simd +} + +// Int8s represents a 128-bit vector of 16 int8 elements. +type Int8s struct { + _ _simd + a, b uint64 +} + +// Int16s represents a 128-bit vector of 8 int16 elements. +type Int16s struct { + _ _simd + a, b uint64 +} + +// Int32s represents a 128-bit vector of 4 int32 elements. +type Int32s struct { + _ _simd + a, b uint64 +} + +// Int64s represents a 128-bit vector of 2 int64 elements. +type Int64s struct { + _ _simd + a, b uint64 +} + +// Uint8s represents a 128-bit vector of 16 uint8 elements. +type Uint8s struct { + _ _simd + a, b uint64 +} + +// Uint16s represents a 128-bit vector of 8 uint16 elements. +type Uint16s struct { + _ _simd + a, b uint64 +} + +// Uint32s represents a 128-bit vector of 4 uint32 elements. +type Uint32s struct { + _ _simd + a, b uint64 +} + +// Uint64s represents a 128-bit vector of 2 uint64 elements. +type Uint64s struct { + _ _simd + a, b uint64 +} + +// Float32s represents a 128-bit vector of 4 float32 elements. +type Float32s struct { + _ _simd + a, b uint64 +} + +// Float64s represents a 128-bit vector of 2 float64 elements. +type Float64s struct { + _ _simd + a, b uint64 +} + +// Mask8s represents a 128-bit mask vector for 16 int8/uint8 elements. +type Mask8s struct { + _ _simd + a, b uint64 +} + +// Mask16s represents a 128-bit mask vector for 8 int16/uint16 elements. +type Mask16s struct { + _ _simd + a, b uint64 +} + +// Mask32s represents a 128-bit mask vector for 4 int32/uint32/float32 elements. +type Mask32s struct { + _ _simd + a, b uint64 +} + +// Mask64s represents a 128-bit mask vector for 2 int64/uint64/float64 elements. +type Mask64s struct { + _ _simd + a, b uint64 +} diff --git a/src/simd/simd_emulated.go b/src/simd/simd_emulated.go index d6d560794b2b6a21de61c5768c9689ba5ea05f3e..3737297eb49a2062068873ea050f310cddfed242 100644 --- a/src/simd/simd_emulated.go +++ b/src/simd/simd_emulated.go @@ -7,7 +7,7 @@ package simd import ( - "fmt" + "internal/strconv" "math" "math/bits" ) @@ -32,6 +32,43 @@ func HasHardwareCarrylessMultiply() bool { return false } +type number interface { + ~int8 | ~int16 | ~int32 | ~int64 | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64 +} + +func sliceToString[T number](x []T) string { + s := "" + pfx := "{" + for _, y := range x { + s += pfx + pfx = "," + switch e := any(y).(type) { + case int8: + s += strconv.Itoa(int(e)) + case int16: + s += strconv.Itoa(int(e)) + case int32: + s += strconv.Itoa(int(e)) + case int64: + s += strconv.FormatInt(int64(e), 10) + case uint8: + s += strconv.FormatUint(uint64(e), 10) + case uint16: + s += strconv.FormatUint(uint64(e), 10) + case uint32: + s += strconv.FormatUint(uint64(e), 10) + case uint64: + s += strconv.FormatUint(uint64(e), 10) + case float32: + s += strconv.FormatFloat(float64(e), 'g', -1, 32) + case float64: + s += strconv.FormatFloat(e, 'g', -1, 64) + } + } + s += "}" + return s +} + // LoadInt8s loads a slice of int8 into an Int8s vector. func LoadInt8s(s []int8) Int8s { var a, b uint64 @@ -292,7 +329,7 @@ var parts [16]int8 for i := 0; i < 16; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -648,7 +685,7 @@ var parts [8]int16 for i := 0; i < 8; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -997,7 +1034,7 @@ var parts [4]int32 for i := 0; i < 4; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -1231,7 +1268,7 @@ } // String returns a string representation of the vector. func (x Int64s) String() string { - return fmt.Sprint([2]int64{int64(x.a), int64(x.b)}) + return sliceToString([]int64{int64(x.a), int64(x.b)}) } // Sub returns the element-wise difference of x and y. @@ -1466,7 +1503,7 @@ var parts [16]uint8 for i := 0; i < 16; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -1809,7 +1846,7 @@ var parts [8]uint16 for i := 0; i < 8; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -2129,7 +2166,7 @@ var parts [4]uint32 for i := 0; i < 4; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -2369,7 +2406,7 @@ } // String returns a string representation of the vector. func (x Uint64s) String() string { - return fmt.Sprint([2]uint64{x.a, x.b}) + return sliceToString([]uint64{x.a, x.b}) } // Sub returns the element-wise difference of x and y. @@ -2614,7 +2651,6 @@ res.set(0, x.get(0)*y.get(0)) res.set(1, x.get(1)*y.get(1)) res.set(2, x.get(2)*y.get(2)) res.set(3, x.get(3)*y.get(3)) - return res } @@ -2677,7 +2713,7 @@ var parts [4]float32 for i := 0; i < 4; i++ { parts[i] = x.get(i) } - return fmt.Sprint(parts) + return sliceToString(parts[:]) } // Sub returns the element-wise difference of x and y. @@ -2941,7 +2977,7 @@ } // String returns a string representation of the vector. func (x Float64s) String() string { - return fmt.Sprint([2]float64{x.get(0), x.get(1)}) + return sliceToString([]float64{x.get(0), x.get(1)}) } // Sub returns the element-wise difference of x and y. @@ -2981,7 +3017,9 @@ } // String returns a string representation of the vector. func (x Mask8s) String() string { - return fmt.Sprintf("{a:%#x, b:%#x}", x.a, x.b) + var s [16]int8 + x.ToInt8s().Neg().Store(s[:]) + return sliceToString(s[:]) } // ToInt8s converts the mask to an Int8s vector. @@ -3013,7 +3051,9 @@ } // String returns a string representation of the vector. func (x Mask16s) String() string { - return fmt.Sprintf("{a:%#x, b:%#x}", x.a, x.b) + var s [8]int16 + x.ToInt16s().Neg().Store(s[:]) + return sliceToString(s[:]) } // ToInt16s converts the mask to an Int16s vector. @@ -3045,7 +3085,9 @@ } // String returns a string representation of the vector. func (x Mask32s) String() string { - return fmt.Sprintf("{a:%#x, b:%#x}", x.a, x.b) + var s [4]int32 + x.ToInt32s().Neg().Store(s[:]) + return sliceToString(s[:]) } // ToInt32s converts the mask to an Int32s vector. @@ -3075,7 +3117,9 @@ } // String returns a string representation of the vector. func (x Mask64s) String() string { - return fmt.Sprintf("{a:%#x, b:%#x}", x.a, x.b) + var s [2]int64 + x.ToInt64s().Neg().Store(s[:]) + return sliceToString(s[:]) } // ToInt64s converts the mask to an Int64s vector. diff --git a/src/simd/simd_test.go b/src/simd/simd_test.go index 099c52e7ee7169704b32f9f2e69db3bb648f4b0f..b5e775989759120cf4c52b2f464aa9ef8828b4cd 100644 --- a/src/simd/simd_test.go +++ b/src/simd/simd_test.go @@ -8,6 +8,7 @@ package simd_test import ( "simd" + "slices" "testing" ) @@ -446,3 +447,13 @@ testBroadcast(t, float32(99991111), simd.BroadcastFloat32s) testBroadcast(t, float64(112233445599887766), simd.BroadcastFloat64s) } + +func TestMaskToInt(t *testing.T) { + topBits := simd.BroadcastUint8s(0x80) + got := make([]int8, topBits.Len()) + topBits.Equal(topBits).ToInt8s().Store(got) + want := slices.Repeat([]int8{-1}, topBits.Len()) + if !slices.Equal(want, got) { + t.Errorf("Wanted %v, got %v", want, got) + } +} diff --git a/src/simd/testdata/tostring_test.go b/src/simd/testdata/tostring_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2e03c7a08c678ce3f4fe463ce67c0be3f5246edc --- /dev/null +++ b/src/simd/testdata/tostring_test.go @@ -0,0 +1,75 @@ +// 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 testdata_test + +import ( + "fmt" + "simd" + "testing" +) + +func fillUint8s(f func(i int) uint8) simd.Uint8s { + l := simd.Uint8s{}.Len() + x := make([]uint8, l, l) + for i := range l { + x[i] = f(i) + } + return simd.LoadUint8s(x) +} + +func fillFloat32s(f func(i int) float32) simd.Float32s { + l := simd.Float32s{}.Len() + x := make([]float32, l, l) + for i := range l { + x[i] = f(i) + } + return simd.LoadFloat32s(x) +} + +func stringFor(l int, f func(i int) int) string { + pfx := "{" + var want string + for i := range l { + want += pfx + pfx = "," + want += fmt.Sprintf("%d", f(i)) + } + want += "}" + return want +} + +func TestToString(t *testing.T) { + a := fillUint8s(func(i int) uint8 { return uint8(i) & 1 }) + b := fillUint8s(func(i int) uint8 { return uint8(i>>1) & 1 }) + m := a.Equal(b) + wantM := stringFor(a.Len(), + func(i int) int { + if i&1 == (i>>1)&1 { + return 1 + } + return 0 + }) + if got := m.String(); wantM != got { + t.Errorf("wantM=%s, got=%s", wantM, got) + } + wantA := stringFor(a.Len(), + func(i int) int { + return i & 1 + }) + if got := a.String(); wantA != got { + t.Errorf("wantA=%s, got=%s", wantA, got) + } + + f := fillFloat32s(func(i int) float32 { return float32(i) }) + wantF := stringFor(f.Len(), + func(i int) int { + return i + }) + if got := f.String(); wantF != got { + t.Errorf("wantF=%s, got=%s", wantF, got) + } +} diff --git a/src/simd/testdata_test.go b/src/simd/testdata_test.go index b8623cfcee995df25915dabe6147b7128654e00c..c485aae5dda422cd5e4b0d8b40c49c6a416176a9 100644 --- a/src/simd/testdata_test.go +++ b/src/simd/testdata_test.go @@ -9,11 +9,12 @@ import ( "internal/testenv" "os" + "runtime" "strings" "testing" ) -func common(t *testing.T, dir, what, failWith string) { +func common(t *testing.T, dir, what, failWith string, moreEnv ...string) { t.Helper() t.Logf("subprocess test in testdata") testenv.MustHaveGoRun(t) @@ -23,6 +24,16 @@ args = append(args, "-v") } args = append(args, what) cmd := testenv.Command(t, testenv.GoToolPath(t), args...) + + goexp := os.Getenv("GOEXPERIMENT") + if !strings.Contains(","+goexp+",", ",simd,") { + if goexp != "" { + goexp += "," + } + goexp += "simd" + } + cmd.Env = append(cmd.Environ(), "GOEXPERIMENT="+goexp) + cmd.Env = append(cmd.Env, moreEnv...) if failWith == "" { cmd.Stdout = os.Stdout @@ -61,3 +72,10 @@ func TestCompileError(t *testing.T) { common(t, "testdata", "errors_test.go", "array length unsafe.Sizeof(v_from_simd) (value of type uintptr) must be constant") } + +func TestToString(t *testing.T) { + common(t, "testdata", "tostring_test.go", "") + if runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" { + common(t, "testdata", "tostring_test.go", "", "GODEBUG=simd=0") + } +} diff --git a/test/codegen/simd_arm64.go b/test/codegen/simd_arm64.go index 5be078beb5bd6de9038bb9053935b3283335776e..209e1fed51a2a4ddf4fac8c102b34356aeed469d 100644 --- a/test/codegen/simd_arm64.go +++ b/test/codegen/simd_arm64.go @@ -110,14 +110,14 @@ return lo.Xor(hi) } func mergeWithNotMask(x, y archsimd.Int8x16, mask archsimd.Mask8x16, f1, f2 archsimd.Float32x4) { - // arm64:`VBIF` -`VBIT` -`VNOT` + // arm64:`VBIT` -`VBIF` -`VNOT` sinkI8 = x.IfElse(mask.Not(), y) // arm64: `VFCMEQ` eq := f1.Equal(f2) // The next line `ne` should be CSEd with `eq` above ne := f1.NotEqual(f2) // arm64: -`.*` - fne := f1.IfElse(eq, f2) // arm64:`VBIT` - feq := f1.IfElse(ne, f2) // arm64:`VBIF` + feq := f1.IfElse(eq, f2) // arm64:`VBIF` + fne := f1.IfElse(ne, f2) // arm64:`VBIT` sinkF32 = fne.Add(feq) } diff --git a/test/fixedbugs/issue80096.go b/test/fixedbugs/issue80096.go new file mode 100644 index 0000000000000000000000000000000000000000..308a2e60f0ceef4b0377c5b11693aff184776a4a --- /dev/null +++ b/test/fixedbugs/issue80096.go @@ -0,0 +1,18 @@ +// compile + +// 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. + +package p + +var M map[float64]string + +func f() int { + switch M[0.1] != "a" { + case true: + return 1 + default: + return 0 + } +} diff --git a/test/fixedbugs/issue80097.go b/test/fixedbugs/issue80097.go new file mode 100644 index 0000000000000000000000000000000000000000..314a84f6a447d72d435e5159f2d94120604727bf --- /dev/null +++ b/test/fixedbugs/issue80097.go @@ -0,0 +1,23 @@ +// compile + +// 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. + +// Issue 80097: ICE "invalid heap allocated var without Heapaddr" +// when a heap-escaping variable is declared in unreachable code. +// Escape analysis marks the variable as heap-allocated, but because +// the declaration is dead, SSA generation never assigns it a heap +// address. DWARF generation must tolerate this state. + +package p + +var foo = func() int { +label: + goto label + x := [1024 * 64]*[2]*int{} + if x != x { + _ = x + } + return 1 +}()