g := make([]int8, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int16, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint8, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint16, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint32, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint64, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]float32, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]float64, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int8, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int16, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint8, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint16, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint32, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint64, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]float32, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]float64, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int8, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int16, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint8, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint16, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint32, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]uint64, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]float32, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]float64, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int8, n)
f(a, b).AsInt8x16().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int16, n)
f(a, b).AsInt16x8().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).AsInt32x4().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).AsInt64x2().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int8, n)
f(a, b).AsInt8x16().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int16, n)
f(a, b).AsInt16x8().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).AsInt32x4().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).AsInt64x2().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).AsInt32x4().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).AsInt64x2().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int8, n)
f(a, b).AsInt8x32().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int16, n)
f(a, b).AsInt16x16().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).AsInt32x8().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).AsInt64x4().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int8, n)
f(a, b).AsInt8x32().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int16, n)
f(a, b).AsInt16x16().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).AsInt32x8().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).AsInt64x4().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).AsInt32x8().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).AsInt64x4().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int8, n)
f(a, b).AsInt8x64().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int16, n)
f(a, b).AsInt16x32().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).AsInt32x16().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).AsInt64x8().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int8, n)
f(a, b).AsInt8x64().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int16, n)
f(a, b).AsInt16x32().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).AsInt32x16().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).AsInt64x8().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int32, n)
f(a, b).AsInt32x16().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
g := make([]int64, n)
f(a, b).AsInt64x8().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
})
}
// slice operations and tests
import (
+ "bufio"
"bytes"
"flag"
"fmt"
// these are the shapes that are currently converted to int32
// (not all conversions are available, yet)
var convert32Shapes = &shapes{
+
+ vecs: []int{128, 256, 512},
+ floats: []int{32},
+}
+
+var avx512MaskedLoadShapes = &shapes{
+ vecs: []int{512},
+ ints: []int{8, 16, 32, 64},
+ uints: []int{8, 16, 32, 64},
+ floats: []int{32, 64},
+}
+
+var avx2MaskedLoadShapes = &shapes{
+ vecs: []int{128, 256},
+ ints: []int{32, 64},
+ uints: []int{32, 64},
+ floats: []int{32, 64},
+}
+
+var avx2SmallLoadPunShapes = &shapes{
+ // ints are done by hand, these are type-punned to int.
+ vecs: []int{128, 256},
+ uints: []int{8, 16},
+}
+
+var unaryFlaky = &shapes{
+ vecs: []int{128, 256, 512},
+ floats: []int{32, 64},
+}
+
+var ternaryFlaky = &shapes{
vecs: []int{128, 256, 512},
floats: []int{32},
}
if strings.Contains("aeiou", baseType[:1]) {
aOrAn = "an"
}
+ oxFF := fmt.Sprintf("0x%x", uint64((1<<count)-1))
t.Execute(out, struct {
Vec string // the type of the vector, e.g. Float32x4
AOrAn string // for documentation, the article "a" or "an"
Count int // the number of elements, e.g. 4
WxC string // the width-by-type string, e.g., "32x4"
Type string // the element type, e.g. "float32"
+ OxFF string // a mask for the lowest 'count' bits
}{
Vec: vType,
AOrAn: aOrAn,
Count: count,
WxC: wxc,
Type: eType,
+ OxFF: oxFF,
})
}
package simd
+import "unsafe"
+
+`, s)
+}
+
+func unsafePrologue(s string, out io.Writer) {
+ fmt.Fprintf(out,
+ `// Code generated by '%s'; DO NOT EDIT.
+
+//go:build goexperiment.simd
+
+package simd
+
+import "unsafe"
`, s)
}
}
}
-// //go:noescape
-// func LoadUint8x16Slice(s []uint8) Uint8x16 {
-// return LoadUint8x16((*[16]uint8)(s[:16]))
-// }
-
-// //go:noescape
-// func (x Uint8x16) StoreSlice(s []uint8) {
-// x.Store((*[16]uint8)(s[:16]))
-// }
-
func templateOf(name, temp string) shapeAndTemplate {
return shapeAndTemplate{s: allShapes,
t: template.Must(template.New(name).Parse(temp))}
g := make([]{{.Type}}, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x)})
+ return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x)})
+ })
+}
+`)
+
+var unaryFlakyTemplate = shapedTemplateOf(unaryFlaky, "unary_flaky_helpers", `
+// test{{.Vec}}UnaryFlaky 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 test{{.Vec}}UnaryFlaky(t *testing.T, f func(x simd.{{.Vec}}) simd.{{.Vec}}, want func(x []{{.Type}}) []{{.Type}}, flakiness float64) {
+ n := {{.Count}}
+ t.Helper()
+ forSlice(t, {{.Type}}s, n, func(x []{{.Type}}) bool {
+ t.Helper()
+ a := simd.Load{{.Vec}}Slice(x)
+ g := make([]{{.Type}}, n)
+ f(a).StoreSlice(g)
+ w := want(x)
+ return checkSlicesLogInput(t, g, w, flakiness, func() {t.Helper(); t.Logf("x=%v", x)})
})
}
`)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x)})
+ return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x)})
})
}
`)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x)})
+ return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x)})
})
}
`)
g := make([]{{.Type}}, n)
f(a, b).StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); })
+ return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); })
})
}
`)
g := make([]{{.Type}}, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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); })
+ })
+}
+`)
+
+var ternaryFlakyTemplate = shapedTemplateOf(ternaryFlaky, "ternary_helpers", `
+// test{{.Vec}}TernaryFlaky 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 test{{.Vec}}TernaryFlaky(t *testing.T, f func(x, y, z simd.{{.Vec}}) simd.{{.Vec}}, want func(x, y, z []{{.Type}}) []{{.Type}}, flakiness float64) {
+ n := {{.Count}}
+ t.Helper()
+ forSliceTriple(t, {{.Type}}s, n, func(x, y, z []{{.Type}}) bool {
+ t.Helper()
+ a := simd.Load{{.Vec}}Slice(x)
+ b := simd.Load{{.Vec}}Slice(y)
+ c := simd.Load{{.Vec}}Slice(z)
+ g := make([]{{.Type}}, n)
+ f(a, b, c).StoreSlice(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); })
})
}
`)
g := make([]int{{.Width}}, n)
f(a, b).AsInt{{.WxC}}().StoreSlice(g)
w := want(x, y)
- return checkSlicesLogInput(t, s64(g), w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); })
})
}
`)
w[i] = 0
}
}
- return checkSlicesLogInput(t, s64(g), w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m); })
+ return checkSlicesLogInput(t, s64(g), w, 0.0, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m); })
})
}
`)
+var avx512MaskedLoadSlicePartTemplate = shapedTemplateOf(avx512MaskedLoadShapes, "avx 512 load slice part", `
+// Load{{.Vec}}SlicePart loads a {{.Vec}} from the slice s.
+// If s has fewer than {{.Count}} elements, the remaining elements of the vector are filled with zeroes.
+// If s has {{.Count}} or more elements, the function is equivalent to Load{{.Vec}}Slice.
+func Load{{.Vec}}SlicePart(s []{{.Type}}) {{.Vec}} {
+ l := len(s)
+ if l >= {{.Count}} {
+ return Load{{.Vec}}Slice(s)
+ }
+ if l == 0 {
+ var x {{.Vec}}
+ return x
+ }
+
+ mask := Mask{{.WxC}}FromBits({{.OxFF}} >> ({{.Count}} - l))
+ return LoadMasked{{.Vec}}(pa{{.Vec}}(s), mask)
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x {{.Vec}}) StoreSlicePart(s []{{.Type}}) {
+ l := len(s)
+ if l >= {{.Count}} {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask{{.WxC}}FromBits({{.OxFF}} >> ({{.Count}} - l))
+ x.StoreMasked(pa{{.Vec}}(s), mask)
+}
+`)
+
+var avx2MaskedLoadSlicePartTemplate = shapedTemplateOf(avx2MaskedLoadShapes, "avx 2 load slice part", `
+// Load{{.Vec}}SlicePart loads a {{.Vec}} from the slice s.
+// If s has fewer than {{.Count}} elements, the remaining elements of the vector are filled with zeroes.
+// If s has {{.Count}} or more elements, the function is equivalent to Load{{.Vec}}Slice.
+func Load{{.Vec}}SlicePart(s []{{.Type}}) {{.Vec}} {
+ l := len(s)
+ if l >= {{.Count}} {
+ return Load{{.Vec}}Slice(s)
+ }
+ if l == 0 {
+ var x {{.Vec}}
+ return x
+ }
+ mask := vecMask{{.Width}}[len(vecMask{{.Width}})/2-l:]
+ return LoadMasked{{.Vec}}(pa{{.Vec}}(s), LoadInt{{.WxC}}Slice(mask).AsMask{{.WxC}}())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x {{.Vec}}) StoreSlicePart(s []{{.Type}}) {
+ l := len(s)
+ if l >= {{.Count}} {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask{{.Width}}[len(vecMask{{.Width}})/2-l:]
+ x.StoreMasked(pa{{.Vec}}(s), LoadInt{{.WxC}}Slice(mask).AsMask{{.WxC}}())
+}
+`)
+
+var avx2SmallLoadSlicePartTemplate = shapedTemplateOf(avx2SmallLoadPunShapes, "avx 2 small load slice part", `
+// Load{{.Vec}}SlicePart loads a {{.Vec}} from the slice s.
+// If s has fewer than {{.Count}} elements, the remaining elements of the vector are filled with zeroes.
+// If s has {{.Count}} or more elements, the function is equivalent to Load{{.Vec}}Slice.
+func Load{{.Vec}}SlicePart(s []{{.Type}}) {{.Vec}} {
+ if len(s) == 0 {
+ var zero {{.Vec}}
+ return zero
+ }
+ t := unsafe.Slice((*int{{.Width}})(unsafe.Pointer(&s[0])), len(s))
+ return LoadInt{{.WxC}}SlicePart(t).As{{.Vec}}()
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x {{.Vec}}) StoreSlicePart(s []{{.Type}}) {
+ if len(s) == 0 {
+ return
+ }
+ t := unsafe.Slice((*int{{.Width}})(unsafe.Pointer(&s[0])), len(s))
+ x.AsInt{{.WxC}}().StoreSlicePart(t)
+}
+`)
+
+var unsafePATemplate = templateOf("unsafe PA helper", `
+// pa{{.Vec}} returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func pa{{.Vec}}(s []{{.Type}}) *[{{.Count}}]{{.Type}} {
+ return (*[{{.Count}}]{{.Type}})(unsafe.Pointer(&s[0]))
+}
+`)
+
func main() {
sl := flag.String("sl", "slice_amd64.go", "file name for slice operations")
+ ush := flag.String("ush", "unsafe_helpers.go", "file name for unsafe helpers")
bh := flag.String("bh", "binary_helpers_test.go", "file name for binary test helpers")
uh := flag.String("uh", "unary_helpers_test.go", "file name for unary test helpers")
th := flag.String("th", "ternary_helpers_test.go", "file name for ternary test helpers")
flag.Parse()
if *sl != "" {
- one(*sl, prologue, sliceTemplate)
+ one(*sl, prologue, sliceTemplate, avx512MaskedLoadSlicePartTemplate, avx2MaskedLoadSlicePartTemplate, avx2SmallLoadSlicePartTemplate)
+ }
+ if *ush != "" {
+ one(*ush, unsafePrologue, unsafePATemplate)
}
if *uh != "" {
- one(*uh, curryTestPrologue("unary simd methods"), unaryTemplate, unaryTemplateToInt32, unaryTemplateToUint32)
+ one(*uh, curryTestPrologue("unary simd methods"), unaryTemplate, unaryTemplateToInt32, unaryTemplateToUint32, unaryFlakyTemplate)
}
if *bh != "" {
one(*bh, curryTestPrologue("binary simd methods"), binaryTemplate)
}
if *th != "" {
- one(*th, curryTestPrologue("ternary simd methods"), ternaryTemplate)
+ one(*th, curryTestPrologue("ternary simd methods"), ternaryTemplate, ternaryFlakyTemplate)
}
if *ch != "" {
one(*ch, curryTestPrologue("simd methods that compare two operands"), compareTemplate)
}
}
+// numberLines takes a slice of bytes, and returns a string where each line
+// is numbered, starting from 1.
+func numberLines(data []byte) string {
+ var buf bytes.Buffer
+ r := bytes.NewReader(data)
+ s := bufio.NewScanner(r)
+ for i := 1; s.Scan(); i++ {
+ fmt.Fprintf(&buf, "%d: %s\n", i, s.Text())
+ }
+ return buf.String()
+}
+
func one(filename string, prologue func(s string, out io.Writer), sats ...shapeAndTemplate) {
if filename == "" {
return
b, err := format.Source(out.Bytes())
if err != nil {
- fmt.Fprintf(os.Stderr, "There was a problem formatting the generated code for %s, %v", filename, err)
+ fmt.Fprintf(os.Stderr, "There was a problem formatting the generated code for %s, %v\n", filename, err)
+ fmt.Fprintf(os.Stderr, "%s\n", numberLines(out.Bytes()))
+ fmt.Fprintf(os.Stderr, "There was a problem formatting the generated code for %s, %v\n", filename, err)
os.Exit(1)
} else {
ofile.Write(b)
func checkSlices[T number](t *testing.T, got, want []T) bool {
t.Helper()
- return checkSlicesLogInput[T](t, got, want, nil)
+ return checkSlicesLogInput[T](t, got, want, 0.0, nil)
}
// checkSlices compares two slices for equality,
// reporting a test error if there is a problem,
// and also consumes the two slices so that a
// test/benchmark won't be dead-code eliminated.
-func checkSlicesLogInput[T number](t *testing.T, got, want []T, logInput func()) bool {
+func checkSlicesLogInput[T number](t *testing.T, got, want []T, flakiness float64, logInput func()) bool {
t.Helper()
var z T
for i := range want {
if math.IsNaN(float64(x)) && math.IsNaN(float64(y)) {
continue
}
+ if flakiness > 0 {
+ if y == 0 {
+ if math.Abs(float64(x)) < flakiness {
+ continue
+ }
+ } else {
+ if math.Abs(float64((x-y)/y)) < flakiness {
+ continue
+ }
+ }
+ }
case float64:
y := ib.(float64)
if math.IsNaN(x) && math.IsNaN(y) {
continue
}
+ if flakiness > 0 {
+ if y == 0 {
+ if math.Abs(x) < flakiness {
+ continue
+ }
+ } else if math.Abs((x-y)/y) < flakiness {
+ continue
+ }
+ }
+
default:
}
)
var zero = 0.0
+var nzero = -zero
+var inf = 1 / zero
+var ninf = -1 / zero
var nan = math.NaN()
// N controls how large the test vectors are
const N = 144
-var float32s = nOf(N, []float32{1, float32(nan), float32(zero), 2, float32(nan), float32(zero), 3, float32(-zero), float32(1 / zero), float32(-1 / zero), 1 / 2, 1 / 4, 1 / 8, 1 / 1000, 1 / 1000000, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat32, 1 / math.MaxFloat32, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -160, -3200, -64, -4, -8, -16, -32, -64})
-var float64s = nOf(N, []float64{nan, zero, -zero, 1 / zero, -1 / zero, 1 / 1000, 1 / 1000000, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat64, 1 / math.MaxFloat64, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -16, -32, -64})
+var float32s = nOf(N, []float32{float32(inf), float32(ninf), 1, float32(nan), float32(zero), 2, float32(nan), float32(zero), 3, float32(-zero), float32(1.0 / zero), float32(-1.0 / zero), 1.0 / 2, 1.0 / 4, 1.0 / 8, 1.0 / 1000, 1.0 / 1000000, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat32, 1 / math.MaxFloat32, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -160, -3200, -64, -4, -8, -16, -32, -64})
+var float64s = nOf(N, []float64{inf, ninf, nan, zero, -zero, 1 / zero, -1 / zero, 0.0001, 0.0000001, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat64, 1.0 / math.MaxFloat64, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -16, -32, -64})
var int32s = nOf(N, []int32{1, -1, 0, 2, 4, 8, 1024, 0xffffff, -0xffffff, 0x55555, 0x77777, 0xccccc, -0x55555, -0x77777, -0xccccc, -4, -8, -16, -32, -64})
var uint32s = nOf(N, []uint32{1, 0, 2, 4, 8, 1024, 0xffffff, ^uint32(0xffffff), 0x55555, 0x77777, 0xccccc, ^uint32(0x55555), ^uint32(0x77777), ^uint32(0xccccc)})
package simd_test
-import "math"
+import (
+ "math"
+)
func less[T number](x, y T) bool {
return x < y
return uint32(x)
}
+func ceilResidueForPrecision[T float](i int) func(T) T {
+ f := 1.0
+ for i > 0 {
+ f *= 2
+ i--
+ }
+ return func(x T) T {
+ y := float64(x)
+ if math.IsInf(float64(x*T(f)), 0) {
+ return 0
+ }
+ // TODO sort out the rounding issues when T === float32
+ return T(y - math.Ceil(y*f)/f)
+ }
+}
+
// Slice versions of all these elementwise operations
func addSlice[T number](x, y []T) []T {
package simd
+import "unsafe"
+
// LoadInt8x16Slice loads an Int8x16 from a slice of at least 16 int8s
func LoadInt8x16Slice(s []int8) Int8x16 {
return LoadInt8x16((*[16]int8)(s))
func (x Float64x8) StoreSlice(s []float64) {
x.Store((*[8]float64)(s))
}
+
+// LoadInt8x64SlicePart loads a Int8x64 from the slice s.
+// If s has fewer than 64 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 64 or more elements, the function is equivalent to LoadInt8x64Slice.
+func LoadInt8x64SlicePart(s []int8) Int8x64 {
+ l := len(s)
+ if l >= 64 {
+ return LoadInt8x64Slice(s)
+ }
+ if l == 0 {
+ var x Int8x64
+ return x
+ }
+
+ mask := Mask8x64FromBits(0xffffffffffffffff >> (64 - l))
+ return LoadMaskedInt8x64(paInt8x64(s), mask)
+}
+
+// StoreSlicePart stores the 64 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 64 or more elements, the method is equivalent to x.StoreSlice.
+func (x Int8x64) StoreSlicePart(s []int8) {
+ l := len(s)
+ if l >= 64 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask8x64FromBits(0xffffffffffffffff >> (64 - l))
+ x.StoreMasked(paInt8x64(s), mask)
+}
+
+// LoadInt16x32SlicePart loads a Int16x32 from the slice s.
+// If s has fewer than 32 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 32 or more elements, the function is equivalent to LoadInt16x32Slice.
+func LoadInt16x32SlicePart(s []int16) Int16x32 {
+ l := len(s)
+ if l >= 32 {
+ return LoadInt16x32Slice(s)
+ }
+ if l == 0 {
+ var x Int16x32
+ return x
+ }
+
+ mask := Mask16x32FromBits(0xffffffff >> (32 - l))
+ return LoadMaskedInt16x32(paInt16x32(s), mask)
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Int16x32) StoreSlicePart(s []int16) {
+ l := len(s)
+ if l >= 32 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask16x32FromBits(0xffffffff >> (32 - l))
+ x.StoreMasked(paInt16x32(s), mask)
+}
+
+// LoadInt32x16SlicePart loads a Int32x16 from the slice s.
+// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 16 or more elements, the function is equivalent to LoadInt32x16Slice.
+func LoadInt32x16SlicePart(s []int32) Int32x16 {
+ l := len(s)
+ if l >= 16 {
+ return LoadInt32x16Slice(s)
+ }
+ if l == 0 {
+ var x Int32x16
+ return x
+ }
+
+ mask := Mask32x16FromBits(0xffff >> (16 - l))
+ return LoadMaskedInt32x16(paInt32x16(s), mask)
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Int32x16) StoreSlicePart(s []int32) {
+ l := len(s)
+ if l >= 16 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask32x16FromBits(0xffff >> (16 - l))
+ x.StoreMasked(paInt32x16(s), mask)
+}
+
+// LoadInt64x8SlicePart loads a Int64x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadInt64x8Slice.
+func LoadInt64x8SlicePart(s []int64) Int64x8 {
+ l := len(s)
+ if l >= 8 {
+ return LoadInt64x8Slice(s)
+ }
+ if l == 0 {
+ var x Int64x8
+ return x
+ }
+
+ mask := Mask64x8FromBits(0xff >> (8 - l))
+ return LoadMaskedInt64x8(paInt64x8(s), mask)
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Int64x8) StoreSlicePart(s []int64) {
+ l := len(s)
+ if l >= 8 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask64x8FromBits(0xff >> (8 - l))
+ x.StoreMasked(paInt64x8(s), mask)
+}
+
+// LoadUint8x64SlicePart loads a Uint8x64 from the slice s.
+// If s has fewer than 64 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 64 or more elements, the function is equivalent to LoadUint8x64Slice.
+func LoadUint8x64SlicePart(s []uint8) Uint8x64 {
+ l := len(s)
+ if l >= 64 {
+ return LoadUint8x64Slice(s)
+ }
+ if l == 0 {
+ var x Uint8x64
+ return x
+ }
+
+ mask := Mask8x64FromBits(0xffffffffffffffff >> (64 - l))
+ return LoadMaskedUint8x64(paUint8x64(s), mask)
+}
+
+// StoreSlicePart stores the 64 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 64 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint8x64) StoreSlicePart(s []uint8) {
+ l := len(s)
+ if l >= 64 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask8x64FromBits(0xffffffffffffffff >> (64 - l))
+ x.StoreMasked(paUint8x64(s), mask)
+}
+
+// LoadUint16x32SlicePart loads a Uint16x32 from the slice s.
+// If s has fewer than 32 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 32 or more elements, the function is equivalent to LoadUint16x32Slice.
+func LoadUint16x32SlicePart(s []uint16) Uint16x32 {
+ l := len(s)
+ if l >= 32 {
+ return LoadUint16x32Slice(s)
+ }
+ if l == 0 {
+ var x Uint16x32
+ return x
+ }
+
+ mask := Mask16x32FromBits(0xffffffff >> (32 - l))
+ return LoadMaskedUint16x32(paUint16x32(s), mask)
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint16x32) StoreSlicePart(s []uint16) {
+ l := len(s)
+ if l >= 32 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask16x32FromBits(0xffffffff >> (32 - l))
+ x.StoreMasked(paUint16x32(s), mask)
+}
+
+// LoadUint32x16SlicePart loads a Uint32x16 from the slice s.
+// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 16 or more elements, the function is equivalent to LoadUint32x16Slice.
+func LoadUint32x16SlicePart(s []uint32) Uint32x16 {
+ l := len(s)
+ if l >= 16 {
+ return LoadUint32x16Slice(s)
+ }
+ if l == 0 {
+ var x Uint32x16
+ return x
+ }
+
+ mask := Mask32x16FromBits(0xffff >> (16 - l))
+ return LoadMaskedUint32x16(paUint32x16(s), mask)
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint32x16) StoreSlicePart(s []uint32) {
+ l := len(s)
+ if l >= 16 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask32x16FromBits(0xffff >> (16 - l))
+ x.StoreMasked(paUint32x16(s), mask)
+}
+
+// LoadUint64x8SlicePart loads a Uint64x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadUint64x8Slice.
+func LoadUint64x8SlicePart(s []uint64) Uint64x8 {
+ l := len(s)
+ if l >= 8 {
+ return LoadUint64x8Slice(s)
+ }
+ if l == 0 {
+ var x Uint64x8
+ return x
+ }
+
+ mask := Mask64x8FromBits(0xff >> (8 - l))
+ return LoadMaskedUint64x8(paUint64x8(s), mask)
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint64x8) StoreSlicePart(s []uint64) {
+ l := len(s)
+ if l >= 8 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask64x8FromBits(0xff >> (8 - l))
+ x.StoreMasked(paUint64x8(s), mask)
+}
+
+// LoadFloat32x16SlicePart loads a Float32x16 from the slice s.
+// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 16 or more elements, the function is equivalent to LoadFloat32x16Slice.
+func LoadFloat32x16SlicePart(s []float32) Float32x16 {
+ l := len(s)
+ if l >= 16 {
+ return LoadFloat32x16Slice(s)
+ }
+ if l == 0 {
+ var x Float32x16
+ return x
+ }
+
+ mask := Mask32x16FromBits(0xffff >> (16 - l))
+ return LoadMaskedFloat32x16(paFloat32x16(s), mask)
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Float32x16) StoreSlicePart(s []float32) {
+ l := len(s)
+ if l >= 16 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask32x16FromBits(0xffff >> (16 - l))
+ x.StoreMasked(paFloat32x16(s), mask)
+}
+
+// LoadFloat64x8SlicePart loads a Float64x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadFloat64x8Slice.
+func LoadFloat64x8SlicePart(s []float64) Float64x8 {
+ l := len(s)
+ if l >= 8 {
+ return LoadFloat64x8Slice(s)
+ }
+ if l == 0 {
+ var x Float64x8
+ return x
+ }
+
+ mask := Mask64x8FromBits(0xff >> (8 - l))
+ return LoadMaskedFloat64x8(paFloat64x8(s), mask)
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Float64x8) StoreSlicePart(s []float64) {
+ l := len(s)
+ if l >= 8 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := Mask64x8FromBits(0xff >> (8 - l))
+ x.StoreMasked(paFloat64x8(s), mask)
+}
+
+// LoadInt32x4SlicePart loads a Int32x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadInt32x4Slice.
+func LoadInt32x4SlicePart(s []int32) Int32x4 {
+ l := len(s)
+ if l >= 4 {
+ return LoadInt32x4Slice(s)
+ }
+ if l == 0 {
+ var x Int32x4
+ return x
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ return LoadMaskedInt32x4(paInt32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Int32x4) StoreSlicePart(s []int32) {
+ l := len(s)
+ if l >= 4 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ x.StoreMasked(paInt32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// LoadInt64x2SlicePart loads a Int64x2 from the slice s.
+// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 2 or more elements, the function is equivalent to LoadInt64x2Slice.
+func LoadInt64x2SlicePart(s []int64) Int64x2 {
+ l := len(s)
+ if l >= 2 {
+ return LoadInt64x2Slice(s)
+ }
+ if l == 0 {
+ var x Int64x2
+ return x
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ return LoadMaskedInt64x2(paInt64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Int64x2) StoreSlicePart(s []int64) {
+ l := len(s)
+ if l >= 2 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ x.StoreMasked(paInt64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// LoadUint32x4SlicePart loads a Uint32x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadUint32x4Slice.
+func LoadUint32x4SlicePart(s []uint32) Uint32x4 {
+ l := len(s)
+ if l >= 4 {
+ return LoadUint32x4Slice(s)
+ }
+ if l == 0 {
+ var x Uint32x4
+ return x
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ return LoadMaskedUint32x4(paUint32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint32x4) StoreSlicePart(s []uint32) {
+ l := len(s)
+ if l >= 4 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ x.StoreMasked(paUint32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// LoadUint64x2SlicePart loads a Uint64x2 from the slice s.
+// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 2 or more elements, the function is equivalent to LoadUint64x2Slice.
+func LoadUint64x2SlicePart(s []uint64) Uint64x2 {
+ l := len(s)
+ if l >= 2 {
+ return LoadUint64x2Slice(s)
+ }
+ if l == 0 {
+ var x Uint64x2
+ return x
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ return LoadMaskedUint64x2(paUint64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint64x2) StoreSlicePart(s []uint64) {
+ l := len(s)
+ if l >= 2 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ x.StoreMasked(paUint64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// LoadFloat32x4SlicePart loads a Float32x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadFloat32x4Slice.
+func LoadFloat32x4SlicePart(s []float32) Float32x4 {
+ l := len(s)
+ if l >= 4 {
+ return LoadFloat32x4Slice(s)
+ }
+ if l == 0 {
+ var x Float32x4
+ return x
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ return LoadMaskedFloat32x4(paFloat32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Float32x4) StoreSlicePart(s []float32) {
+ l := len(s)
+ if l >= 4 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ x.StoreMasked(paFloat32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// LoadFloat64x2SlicePart loads a Float64x2 from the slice s.
+// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 2 or more elements, the function is equivalent to LoadFloat64x2Slice.
+func LoadFloat64x2SlicePart(s []float64) Float64x2 {
+ l := len(s)
+ if l >= 2 {
+ return LoadFloat64x2Slice(s)
+ }
+ if l == 0 {
+ var x Float64x2
+ return x
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ return LoadMaskedFloat64x2(paFloat64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Float64x2) StoreSlicePart(s []float64) {
+ l := len(s)
+ if l >= 2 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ x.StoreMasked(paFloat64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// LoadInt32x8SlicePart loads a Int32x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadInt32x8Slice.
+func LoadInt32x8SlicePart(s []int32) Int32x8 {
+ l := len(s)
+ if l >= 8 {
+ return LoadInt32x8Slice(s)
+ }
+ if l == 0 {
+ var x Int32x8
+ return x
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ return LoadMaskedInt32x8(paInt32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Int32x8) StoreSlicePart(s []int32) {
+ l := len(s)
+ if l >= 8 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ x.StoreMasked(paInt32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// LoadInt64x4SlicePart loads a Int64x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadInt64x4Slice.
+func LoadInt64x4SlicePart(s []int64) Int64x4 {
+ l := len(s)
+ if l >= 4 {
+ return LoadInt64x4Slice(s)
+ }
+ if l == 0 {
+ var x Int64x4
+ return x
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ return LoadMaskedInt64x4(paInt64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Int64x4) StoreSlicePart(s []int64) {
+ l := len(s)
+ if l >= 4 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ x.StoreMasked(paInt64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// LoadUint32x8SlicePart loads a Uint32x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadUint32x8Slice.
+func LoadUint32x8SlicePart(s []uint32) Uint32x8 {
+ l := len(s)
+ if l >= 8 {
+ return LoadUint32x8Slice(s)
+ }
+ if l == 0 {
+ var x Uint32x8
+ return x
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ return LoadMaskedUint32x8(paUint32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint32x8) StoreSlicePart(s []uint32) {
+ l := len(s)
+ if l >= 8 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ x.StoreMasked(paUint32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// LoadUint64x4SlicePart loads a Uint64x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadUint64x4Slice.
+func LoadUint64x4SlicePart(s []uint64) Uint64x4 {
+ l := len(s)
+ if l >= 4 {
+ return LoadUint64x4Slice(s)
+ }
+ if l == 0 {
+ var x Uint64x4
+ return x
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ return LoadMaskedUint64x4(paUint64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint64x4) StoreSlicePart(s []uint64) {
+ l := len(s)
+ if l >= 4 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ x.StoreMasked(paUint64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// LoadFloat32x8SlicePart loads a Float32x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadFloat32x8Slice.
+func LoadFloat32x8SlicePart(s []float32) Float32x8 {
+ l := len(s)
+ if l >= 8 {
+ return LoadFloat32x8Slice(s)
+ }
+ if l == 0 {
+ var x Float32x8
+ return x
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ return LoadMaskedFloat32x8(paFloat32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Float32x8) StoreSlicePart(s []float32) {
+ l := len(s)
+ if l >= 8 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask32[len(vecMask32)/2-l:]
+ x.StoreMasked(paFloat32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// LoadFloat64x4SlicePart loads a Float64x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadFloat64x4Slice.
+func LoadFloat64x4SlicePart(s []float64) Float64x4 {
+ l := len(s)
+ if l >= 4 {
+ return LoadFloat64x4Slice(s)
+ }
+ if l == 0 {
+ var x Float64x4
+ return x
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ return LoadMaskedFloat64x4(paFloat64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Float64x4) StoreSlicePart(s []float64) {
+ l := len(s)
+ if l >= 4 {
+ x.StoreSlice(s)
+ return
+ }
+ if l == 0 {
+ return
+ }
+ mask := vecMask64[len(vecMask64)/2-l:]
+ x.StoreMasked(paFloat64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// LoadUint8x16SlicePart loads a Uint8x16 from the slice s.
+// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 16 or more elements, the function is equivalent to LoadUint8x16Slice.
+func LoadUint8x16SlicePart(s []uint8) Uint8x16 {
+ if len(s) == 0 {
+ var zero Uint8x16
+ return zero
+ }
+ t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
+ return LoadInt8x16SlicePart(t).AsUint8x16()
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint8x16) StoreSlicePart(s []uint8) {
+ if len(s) == 0 {
+ return
+ }
+ t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
+ x.AsInt8x16().StoreSlicePart(t)
+}
+
+// LoadUint16x8SlicePart loads a Uint16x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadUint16x8Slice.
+func LoadUint16x8SlicePart(s []uint16) Uint16x8 {
+ if len(s) == 0 {
+ var zero Uint16x8
+ return zero
+ }
+ t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
+ return LoadInt16x8SlicePart(t).AsUint16x8()
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint16x8) StoreSlicePart(s []uint16) {
+ if len(s) == 0 {
+ return
+ }
+ t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
+ x.AsInt16x8().StoreSlicePart(t)
+}
+
+// LoadUint8x32SlicePart loads a Uint8x32 from the slice s.
+// If s has fewer than 32 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 32 or more elements, the function is equivalent to LoadUint8x32Slice.
+func LoadUint8x32SlicePart(s []uint8) Uint8x32 {
+ if len(s) == 0 {
+ var zero Uint8x32
+ return zero
+ }
+ t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
+ return LoadInt8x32SlicePart(t).AsUint8x32()
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint8x32) StoreSlicePart(s []uint8) {
+ if len(s) == 0 {
+ return
+ }
+ t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
+ x.AsInt8x32().StoreSlicePart(t)
+}
+
+// LoadUint16x16SlicePart loads a Uint16x16 from the slice s.
+// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 16 or more elements, the function is equivalent to LoadUint16x16Slice.
+func LoadUint16x16SlicePart(s []uint16) Uint16x16 {
+ if len(s) == 0 {
+ var zero Uint16x16
+ return zero
+ }
+ t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
+ return LoadInt16x16SlicePart(t).AsUint16x16()
+}
+
+// StoreSlicePart 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.StoreSlice.
+func (x Uint16x16) StoreSlicePart(s []uint16) {
+ if len(s) == 0 {
+ return
+ }
+ t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
+ x.AsInt16x16().StoreSlicePart(t)
+}
// Implementation of all the {Int,Uint}{8,16} load and store slice part
// functions and methods for 128-bit and 256-bit vectors.
-/* pointer-punning functions. */
+/* pointer-punning functions for chunked slice part loads. */
func int16atP8(p *int8) *int16 {
return (*int16)(unsafe.Pointer(p))
return (*int32)(unsafe.Pointer(p))
}
-/* unsigned versions of integer slice part loads */
+/* These two masks are used by generated code */
-// LoadUint8x16SlicePart loads a Uint8x16 from the slice s.
-// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 16 or more elements, the function is equivalent to LoadUint8x16Slice.
-func LoadUint8x16SlicePart(s []uint8) Uint8x16 {
- if len(s) == 0 {
- var zero Uint8x16
- return zero
- }
- t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt8x16SlicePart(t).AsUint8x16()
-}
-
-// LoadUint16x8SlicePart loads a Uint16x8 from the slice s.
-// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 8 or more elements, the function is equivalent to LoadUint16x8Slice.
-func LoadUint16x8SlicePart(s []uint16) Uint16x8 {
- if len(s) == 0 {
- var zero Uint16x8
- return zero
- }
- t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt16x8SlicePart(t).AsUint16x8()
-}
-
-// LoadUint8x32SlicePart loads a Uint8x32 from the slice s.
-// If s has fewer than 32 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 32 or more elements, the function is equivalent to LoadUint8x32Slice.
-func LoadUint8x32SlicePart(s []uint8) Uint8x32 {
- if len(s) == 0 {
- var zero Uint8x32
- return zero
- }
- t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt8x32SlicePart(t).AsUint8x32()
-}
-
-// LoadUint16x16SlicePart loads a Uint16x16 from the slice s.
-// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 16 or more elements, the function is equivalent to LoadUint16x16Slice.
-func LoadUint16x16SlicePart(s []uint16) Uint16x16 {
- if len(s) == 0 {
- var zero Uint16x16
- return zero
- }
- t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt16x16SlicePart(t).AsUint16x16()
-}
-
-/* unsigned versions of integer slice part stores*/
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Uint8x16) StoreSlicePart(s []uint8) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt8x16().StoreSlicePart(t)
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Uint16x8) StoreSlicePart(s []uint16) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt16x8().StoreSlicePart(t)
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Uint8x32) StoreSlicePart(s []uint8) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt8x32().StoreSlicePart(t)
+var vecMask64 = [16]int64{
+ -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
}
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Uint16x16) StoreSlicePart(s []uint16) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt16x16().StoreSlicePart(t)
+var vecMask32 = [32]int32{
+ -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
}
/* 256-bit int vector loads and stores made from 128-bit parts */
}
return
}
-
-var vecMask64 = [16]int64{
- -1, -1, -1, -1,
- -1, -1, -1, -1,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-}
-
-// paInt32x4 is an unchecked cast from a slice to an
-// pointer-to-array type, for used in a masked
-// load/store. In practice, the slice will be too
-// short, so this has to be unsafe, and its only
-// use must be with an instruction with masked
-// load/store effect (including faults).
-func paInt32x4(s []int32) *[4]int32 {
- return (*[4]int32)(unsafe.Pointer(&s[0]))
-}
-
-func paInt32x8(s []int32) *[8]int32 {
- return (*[8]int32)(unsafe.Pointer(&s[0]))
-}
-
-func paInt64x2(s []int64) *[2]int64 {
- return (*[2]int64)(unsafe.Pointer(&s[0]))
-}
-
-func paInt64x4(s []int64) *[4]int64 {
- return (*[4]int64)(unsafe.Pointer(&s[0]))
-}
-
-// For 512-bit masked loads/stores
-
-func paInt64x8(s []int64) *[8]int64 {
- return (*[8]int64)(unsafe.Pointer(&s[0]))
-}
-
-func paInt32x16(s []int32) *[16]int32 {
- return (*[16]int32)(unsafe.Pointer(&s[0]))
-}
-
-func paInt16x32(s []int16) *[32]int16 {
- return (*[32]int16)(unsafe.Pointer(&s[0]))
-}
-
-func paInt8x64(s []int8) *[64]int8 {
- return (*[64]int8)(unsafe.Pointer(&s[0]))
-}
-
-/* 32 and 64-bit slice-part loads for AVX2 (128 and 256 bit) */
-
-// LoadInt32x4SlicePart loads a Int32x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadInt32x4Slice.
-func LoadInt32x4SlicePart(s []int32) Int32x4 {
- l := len(s)
- if l >= 4 {
- return LoadInt32x4Slice(s)
- }
- if l == 0 {
- var x Int32x4
- return x
- }
- p := int32atP64(&vecMask64[0])
- mask := unsafe.Slice(p, 32)[16-l:]
- return LoadMaskedInt32x4(paInt32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Int32x4) StoreSlicePart(s []int32) {
- l := len(s)
- if l >= 4 {
- x.StoreSlice(s)
- return
- }
- if l == 0 {
- return
- }
- p := int32atP64(&vecMask64[0])
- mask := unsafe.Slice(p, 32)[16-l:]
- x.StoreMasked(paInt32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
-}
-
-// LoadInt32x8SlicePart loads a Int32x8 from the slice s.
-// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 8 or more elements, the function is equivalent to LoadInt32x8Slice.
-func LoadInt32x8SlicePart(s []int32) Int32x8 {
- l := len(s)
- if l >= 8 {
- return LoadInt32x8Slice(s)
- }
- if l == 0 {
- var x Int32x8
- return x
- }
- p := int32atP64(&vecMask64[0])
- mask := unsafe.Slice(p, 32)[16-l:]
- return LoadMaskedInt32x8(paInt32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
-}
-
-// LoadInt64x2SlicePart loads a Int64x2 from the slice s.
-// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 2 or more elements, the function is equivalent to LoadInt64x2Slice.
-func LoadInt64x2SlicePart(s []int64) Int64x2 {
- l := len(s)
- if l >= 2 {
- return LoadInt64x2Slice(s)
- }
- if l == 0 {
- var x Int64x2
- return x
- }
-
- mask := vecMask64[8-l:]
- return LoadMaskedInt64x2(paInt64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
-}
-
-// LoadInt64x4SlicePart loads a Int64x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadInt64x4Slice.
-func LoadInt64x4SlicePart(s []int64) Int64x4 {
- l := len(s)
- if l >= 4 {
- return LoadInt64x4Slice(s)
- }
- if l == 0 {
- var x Int64x4
- return x
- }
-
- mask := vecMask64[8-l:]
- return LoadMaskedInt64x4(paInt64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Int32x8) StoreSlicePart(s []int32) {
- l := len(s)
- if l >= 8 {
- x.StoreSlice(s)
- return
- }
- if l == 0 {
- return
- }
- p := int32atP64(&vecMask64[0])
- mask := unsafe.Slice(p, 32)[16-l:]
- x.StoreMasked(paInt32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Int64x2) StoreSlicePart(s []int64) {
- l := len(s)
- if l >= 2 {
- x.StoreSlice(s)
- return
- }
- if l == 0 {
- return
- }
- mask := vecMask64[8-l:]
- x.StoreMasked(paInt64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Int64x4) StoreSlicePart(s []int64) {
- l := len(s)
- if l >= 4 {
- x.StoreSlice(s)
- return
- }
- if l == 0 {
- return
- }
- mask := vecMask64[8-l:]
- x.StoreMasked(paInt64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
-}
-
-// Handle float32, float64, uint32, and uint64 with ugly casts.
-
-// LoadUint32x4SlicePart loads a Uint32x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadUint32x4Slice.
-func LoadUint32x4SlicePart(s []uint32) Uint32x4 {
- if len(s) == 0 {
- var zero Uint32x4
- return zero
- }
- t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt32x4SlicePart(t).AsUint32x4()
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Uint32x4) StoreSlicePart(s []uint32) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt32x4().StoreSlicePart(t)
-}
-
-// LoadUint32x8SlicePart loads a Uint32x8 from the slice s.
-// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 8 or more elements, the function is equivalent to LoadUint32x8Slice.
-func LoadUint32x8SlicePart(s []uint32) Uint32x8 {
- if len(s) == 0 {
- var zero Uint32x8
- return zero
- }
- t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt32x8SlicePart(t).AsUint32x8()
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Uint32x8) StoreSlicePart(s []uint32) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt32x8().StoreSlicePart(t)
-}
-
-// LoadUint64x2SlicePart loads a Uint64x2 from the slice s.
-// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 2 or more elements, the function is equivalent to LoadUint64x2Slice.
-func LoadUint64x2SlicePart(s []uint64) Uint64x2 {
- if len(s) == 0 {
- var zero Uint64x2
- return zero
- }
- t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt64x2SlicePart(t).AsUint64x2()
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Uint64x2) StoreSlicePart(s []uint64) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt64x2().StoreSlicePart(t)
-}
-
-// LoadUint64x4SlicePart loads a Uint64x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadUint64x4Slice.
-func LoadUint64x4SlicePart(s []uint64) Uint64x4 {
- if len(s) == 0 {
- var zero Uint64x4
- return zero
- }
- t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt64x4SlicePart(t).AsUint64x4()
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Uint64x4) StoreSlicePart(s []uint64) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt64x4().StoreSlicePart(t)
-}
-
-// Float32xK and Float64xK
-
-// LoadFloat32x4SlicePart loads a Float32x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadFloat32x4Slice.
-func LoadFloat32x4SlicePart(s []float32) Float32x4 {
- if len(s) == 0 {
- var zero Float32x4
- return zero
- }
- t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt32x4SlicePart(t).AsFloat32x4()
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Float32x4) StoreSlicePart(s []float32) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt32x4().StoreSlicePart(t)
-}
-
-// LoadFloat32x8SlicePart loads a Float32x8 from the slice s.
-// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 8 or more elements, the function is equivalent to LoadFloat32x8Slice.
-func LoadFloat32x8SlicePart(s []float32) Float32x8 {
- if len(s) == 0 {
- var zero Float32x8
- return zero
- }
- t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt32x8SlicePart(t).AsFloat32x8()
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Float32x8) StoreSlicePart(s []float32) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt32x8().StoreSlicePart(t)
-}
-
-// LoadFloat64x2SlicePart loads a Float64x2 from the slice s.
-// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 2 or more elements, the function is equivalent to LoadFloat64x2Slice.
-func LoadFloat64x2SlicePart(s []float64) Float64x2 {
- if len(s) == 0 {
- var zero Float64x2
- return zero
- }
- t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt64x2SlicePart(t).AsFloat64x2()
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Float64x2) StoreSlicePart(s []float64) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt64x2().StoreSlicePart(t)
-}
-
-// LoadFloat64x4SlicePart loads a Float64x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadFloat64x4Slice.
-func LoadFloat64x4SlicePart(s []float64) Float64x4 {
- if len(s) == 0 {
- var zero Float64x4
- return zero
- }
- t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
- return LoadInt64x4SlicePart(t).AsFloat64x4()
-}
-
-// StoreSlicePart stores the 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.StoreSlice.
-func (x Float64x4) StoreSlicePart(s []float64) {
- if len(s) == 0 {
- return
- }
- t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
- x.AsInt64x4().StoreSlicePart(t)
-}
-
-func LoadInt64x8SlicePart(s []int64) Int64x8 {
- l := len(s)
- if l >= 8 {
- return LoadInt64x8Slice(s)
- }
- if l == 0 {
- var x Int64x8
- return x
- }
-
- mask := Mask64x8FromBits(0xff >> (8 - l))
- return LoadMaskedInt64x8(paInt64x8(s), mask)
-}
-
-func (x Int64x8) StoreSlicePart(s []int64) {
- l := len(s)
- if l >= 8 {
- x.StoreSlice(s)
- return
- }
- if l == 0 {
- return
- }
- mask := Mask64x8FromBits(0xff >> (8 - l))
- x.StoreMasked(paInt64x8(s), mask)
-}
b := make([]int64, L)
v.StoreSlice(b)
// test the load
- checkSlicesLogInput(t, b, d, func() { t.Helper(); t.Logf("Len(e)=%d", len(e)) })
+ checkSlicesLogInput(t, b, d, 0.0, func() { t.Helper(); t.Logf("Len(e)=%d", len(e)) })
// Test the store
f := make([]int64, L+1)
g := make([]int8, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int16, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int32, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int64, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint8, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint16, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint32, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint64, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]float32, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]float64, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int8, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int16, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int32, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int64, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint8, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint16, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint32, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint64, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]float32, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]float64, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int8, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int16, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int32, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]int64, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint8, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint16, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint32, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]uint64, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]float32, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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) })
})
}
g := make([]float64, n)
f(a, b, c).StoreSlice(g)
w := want(x, y, z)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", 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 simd.Float32x4) simd.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 := simd.LoadFloat32x4Slice(x)
+ b := simd.LoadFloat32x4Slice(y)
+ c := simd.LoadFloat32x4Slice(z)
+ g := make([]float32, n)
+ f(a, b, c).StoreSlice(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) })
+ })
+}
+
+// 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 testFloat32x8TernaryFlaky(t *testing.T, f func(x, y, z simd.Float32x8) simd.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 := simd.LoadFloat32x8Slice(x)
+ b := simd.LoadFloat32x8Slice(y)
+ c := simd.LoadFloat32x8Slice(z)
+ g := make([]float32, n)
+ f(a, b, c).StoreSlice(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) })
+ })
+}
+
+// testFloat32x16TernaryFlaky 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 testFloat32x16TernaryFlaky(t *testing.T, f func(x, y, z simd.Float32x16) simd.Float32x16, want func(x, y, z []float32) []float32, flakiness float64) {
+ n := 16
+ t.Helper()
+ forSliceTriple(t, float32s, n, func(x, y, z []float32) bool {
+ t.Helper()
+ a := simd.LoadFloat32x16Slice(x)
+ b := simd.LoadFloat32x16Slice(y)
+ c := simd.LoadFloat32x16Slice(z)
+ g := make([]float32, n)
+ f(a, b, c).StoreSlice(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) })
})
}
func TestFMA(t *testing.T) {
if simd.HasAVX512() {
- testFloat32x4Ternary(t, simd.Float32x4.FusedMultiplyAdd, fmaSlice[float32])
- testFloat32x8Ternary(t, simd.Float32x8.FusedMultiplyAdd, fmaSlice[float32])
- testFloat32x16Ternary(t, simd.Float32x16.FusedMultiplyAdd, fmaSlice[float32])
+ testFloat32x4TernaryFlaky(t, simd.Float32x4.FusedMultiplyAdd, fmaSlice[float32], 0.001)
+ testFloat32x8TernaryFlaky(t, simd.Float32x8.FusedMultiplyAdd, fmaSlice[float32], 0.001)
+ testFloat32x16TernaryFlaky(t, simd.Float32x16.FusedMultiplyAdd, fmaSlice[float32], 0.001)
testFloat64x2Ternary(t, simd.Float64x2.FusedMultiplyAdd, fmaSlice[float64])
testFloat64x4Ternary(t, simd.Float64x4.FusedMultiplyAdd, fmaSlice[float64])
testFloat64x8Ternary(t, simd.Float64x8.FusedMultiplyAdd, fmaSlice[float64])
g := make([]int8, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int16, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int64, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint8, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint64, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]float32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]float64, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int8, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int16, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int64, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint8, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint64, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]float32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]float64, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int8, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int16, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int64, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint8, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint64, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]float32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]float64, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+ return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
- return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", 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 simd.Float32x4) simd.Float32x4, want func(x []float32) []float32, flakiness float64) {
+ n := 4
+ t.Helper()
+ forSlice(t, float32s, n, func(x []float32) bool {
+ t.Helper()
+ a := simd.LoadFloat32x4Slice(x)
+ g := make([]float32, n)
+ f(a).StoreSlice(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 simd.Float64x2) simd.Float64x2, want func(x []float64) []float64, flakiness float64) {
+ n := 2
+ t.Helper()
+ forSlice(t, float64s, n, func(x []float64) bool {
+ t.Helper()
+ a := simd.LoadFloat64x2Slice(x)
+ g := make([]float64, n)
+ f(a).StoreSlice(g)
+ w := want(x)
+ return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
+ })
+}
+
+// testFloat32x8UnaryFlaky 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 testFloat32x8UnaryFlaky(t *testing.T, f func(x simd.Float32x8) simd.Float32x8, want func(x []float32) []float32, flakiness float64) {
+ n := 8
+ t.Helper()
+ forSlice(t, float32s, n, func(x []float32) bool {
+ t.Helper()
+ a := simd.LoadFloat32x8Slice(x)
+ g := make([]float32, n)
+ f(a).StoreSlice(g)
+ w := want(x)
+ return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
+ })
+}
+
+// testFloat64x4UnaryFlaky 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 testFloat64x4UnaryFlaky(t *testing.T, f func(x simd.Float64x4) simd.Float64x4, want func(x []float64) []float64, flakiness float64) {
+ n := 4
+ t.Helper()
+ forSlice(t, float64s, n, func(x []float64) bool {
+ t.Helper()
+ a := simd.LoadFloat64x4Slice(x)
+ g := make([]float64, n)
+ f(a).StoreSlice(g)
+ w := want(x)
+ return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
+ })
+}
+
+// testFloat32x16UnaryFlaky 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 testFloat32x16UnaryFlaky(t *testing.T, f func(x simd.Float32x16) simd.Float32x16, want func(x []float32) []float32, flakiness float64) {
+ n := 16
+ t.Helper()
+ forSlice(t, float32s, n, func(x []float32) bool {
+ t.Helper()
+ a := simd.LoadFloat32x16Slice(x)
+ g := make([]float32, n)
+ f(a).StoreSlice(g)
+ w := want(x)
+ return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
+ })
+}
+
+// testFloat64x8UnaryFlaky 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 testFloat64x8UnaryFlaky(t *testing.T, f func(x simd.Float64x8) simd.Float64x8, want func(x []float64) []float64, flakiness float64) {
+ n := 8
+ t.Helper()
+ forSlice(t, float64s, n, func(x []float64) bool {
+ t.Helper()
+ a := simd.LoadFloat64x8Slice(x)
+ g := make([]float64, n)
+ f(a).StoreSlice(g)
+ w := want(x)
+ return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
package simd_test
import (
+ "math"
"simd"
"testing"
)
testFloat32x8UnaryToInt32(t, simd.Float32x8.ConvertToInt32, toInt32Slice[float32])
}
+func TestDiffWithCeilWithPrecision(t *testing.T) {
+ if !simd.HasAVX512() {
+ t.Skip("Needs AVX512")
+ }
+ testFloat64x8UnaryFlaky(t,
+ func(x simd.Float64x8) simd.Float64x8 { return x.DiffWithCeilWithPrecision(0) },
+ map1(ceilResidueForPrecision[float64](0)),
+ 0.001)
+ testFloat64x8UnaryFlaky(t,
+ func(x simd.Float64x8) simd.Float64x8 { return x.DiffWithCeilWithPrecision(1) },
+ map1(ceilResidueForPrecision[float64](1)),
+ 0.001)
+ testFloat64x8Unary(t,
+ func(x simd.Float64x8) simd.Float64x8 { return x.Sub(x.CeilWithPrecision(0)) },
+ map1[float64](func(x float64) float64 { return x - math.Ceil(x) }))
+}
+
func TestToUint32(t *testing.T) {
if !simd.HasAVX512() {
t.Skip("Needs AVX512")
--- /dev/null
+// Code generated by 'go run genfiles.go'; DO NOT EDIT.
+
+//go:build goexperiment.simd
+
+package simd
+
+import "unsafe"
+
+// paInt8x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt8x16(s []int8) *[16]int8 {
+ return (*[16]int8)(unsafe.Pointer(&s[0]))
+}
+
+// paInt16x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt16x8(s []int16) *[8]int16 {
+ return (*[8]int16)(unsafe.Pointer(&s[0]))
+}
+
+// paInt32x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt32x4(s []int32) *[4]int32 {
+ return (*[4]int32)(unsafe.Pointer(&s[0]))
+}
+
+// paInt64x2 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt64x2(s []int64) *[2]int64 {
+ return (*[2]int64)(unsafe.Pointer(&s[0]))
+}
+
+// paUint8x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint8x16(s []uint8) *[16]uint8 {
+ return (*[16]uint8)(unsafe.Pointer(&s[0]))
+}
+
+// paUint16x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint16x8(s []uint16) *[8]uint16 {
+ return (*[8]uint16)(unsafe.Pointer(&s[0]))
+}
+
+// paUint32x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint32x4(s []uint32) *[4]uint32 {
+ return (*[4]uint32)(unsafe.Pointer(&s[0]))
+}
+
+// paUint64x2 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint64x2(s []uint64) *[2]uint64 {
+ return (*[2]uint64)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat32x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat32x4(s []float32) *[4]float32 {
+ return (*[4]float32)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat64x2 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat64x2(s []float64) *[2]float64 {
+ return (*[2]float64)(unsafe.Pointer(&s[0]))
+}
+
+// paInt8x32 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt8x32(s []int8) *[32]int8 {
+ return (*[32]int8)(unsafe.Pointer(&s[0]))
+}
+
+// paInt16x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt16x16(s []int16) *[16]int16 {
+ return (*[16]int16)(unsafe.Pointer(&s[0]))
+}
+
+// paInt32x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt32x8(s []int32) *[8]int32 {
+ return (*[8]int32)(unsafe.Pointer(&s[0]))
+}
+
+// paInt64x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt64x4(s []int64) *[4]int64 {
+ return (*[4]int64)(unsafe.Pointer(&s[0]))
+}
+
+// paUint8x32 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint8x32(s []uint8) *[32]uint8 {
+ return (*[32]uint8)(unsafe.Pointer(&s[0]))
+}
+
+// paUint16x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint16x16(s []uint16) *[16]uint16 {
+ return (*[16]uint16)(unsafe.Pointer(&s[0]))
+}
+
+// paUint32x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint32x8(s []uint32) *[8]uint32 {
+ return (*[8]uint32)(unsafe.Pointer(&s[0]))
+}
+
+// paUint64x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint64x4(s []uint64) *[4]uint64 {
+ return (*[4]uint64)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat32x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat32x8(s []float32) *[8]float32 {
+ return (*[8]float32)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat64x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat64x4(s []float64) *[4]float64 {
+ return (*[4]float64)(unsafe.Pointer(&s[0]))
+}
+
+// paInt8x64 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt8x64(s []int8) *[64]int8 {
+ return (*[64]int8)(unsafe.Pointer(&s[0]))
+}
+
+// paInt16x32 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt16x32(s []int16) *[32]int16 {
+ return (*[32]int16)(unsafe.Pointer(&s[0]))
+}
+
+// paInt32x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt32x16(s []int32) *[16]int32 {
+ return (*[16]int32)(unsafe.Pointer(&s[0]))
+}
+
+// paInt64x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt64x8(s []int64) *[8]int64 {
+ return (*[8]int64)(unsafe.Pointer(&s[0]))
+}
+
+// paUint8x64 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint8x64(s []uint8) *[64]uint8 {
+ return (*[64]uint8)(unsafe.Pointer(&s[0]))
+}
+
+// paUint16x32 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint16x32(s []uint16) *[32]uint16 {
+ return (*[32]uint16)(unsafe.Pointer(&s[0]))
+}
+
+// paUint32x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint32x16(s []uint32) *[16]uint32 {
+ return (*[16]uint32)(unsafe.Pointer(&s[0]))
+}
+
+// paUint64x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint64x8(s []uint64) *[8]uint64 {
+ return (*[8]uint64)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat32x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat32x16(s []float32) *[16]float32 {
+ return (*[16]float32)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat64x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat64x8(s []float64) *[8]float64 {
+ return (*[8]float64)(unsafe.Pointer(&s[0]))
+}