use std::iter::once;
use wide::{
f32x4, f32x8, f32x16, i8x16, i8x32, i16x8, i16x16, i32x4, i32x8, i32x16,
i64x4, u8x16, u16x8, u32x4, u32x8, u32x16, u64x4,
};
use crate::utils::{for_simd_types, random_iter, simd_chunks};
#[test]
fn test_saturating_add() {
for_simd_types!(|T: Integer, N| {
for [left, right] in simd_chunks!(
[1, 2, T::MAX - 1, T::MAX - 1, 15, 20, 100, T::MAX - 1, T::MAX / 2],
[17, 18, 1, 2, 20, 5, T::MAX - 5, 50, 100],
)
.chain(random_iter())
{
let expected =
Simd::new(std::array::from_fn(|i| left[i].saturating_add(right[i])));
let actual = Simd::new(left).saturating_add(Simd::new(right));
assert_eq!(expected, actual);
}
});
for_simd_types!(|T: Signed, N| {
for [left, right] in simd_chunks!(
[1, 2, T::MAX - 1, T::MIN + 1, T::MIN + 2, T::MIN / 2, 9],
[-17, 18, T::MAX, -2, -20, -100, 10],
)
.chain(random_iter())
{
let expected =
Simd::new(std::array::from_fn(|i| left[i].saturating_add(right[i])));
let actual = Simd::new(left).saturating_add(Simd::new(right));
assert_eq!(expected, actual);
}
});
}
#[test]
fn test_saturating_sub() {
for_simd_types!(|T: Integer, N| {
for [left, right] in simd_chunks!(
[1, 2, T::MIN + 1, T::MIN + 1, 15, 20, 100, T::MIN + 1, T::MIN / 2],
[17, 18, 1, 2, 20, 5, T::MAX - 5, 50, 100],
)
.chain(random_iter())
{
let expected =
Simd::new(std::array::from_fn(|i| left[i].saturating_sub(right[i])));
let actual = Simd::new(left).saturating_sub(Simd::new(right));
assert_eq!(expected, actual);
}
});
for_simd_types!(|T: Signed, N| {
for [left, right] in simd_chunks!(
[1, 2, T::MAX - 1, T::MIN + 1, T::MIN + 2, T::MAX / 2],
[17, -18, T::MIN, 2, 20, -100],
)
.chain(random_iter())
{
let expected =
Simd::new(std::array::from_fn(|i| left[i].saturating_sub(right[i])));
let actual = Simd::new(left).saturating_sub(Simd::new(right));
assert_eq!(expected, actual);
}
});
}
#[test]
fn test_saturating_mul() {
for_simd_types!(|T: Signed, N| {
for [left, right] in simd_chunks!(
[
1,
2,
T::MIN + 1,
T::MIN,
2,
3,
4,
5,
T::MAX - 1,
T::MAX,
T::MAX,
T::MAX / 2,
T::MIN / 2,
],
[17, -18, 1, 1, -1, -2, -6, 3, 3, 2, 1, 3, 3],
)
.chain(random_iter())
{
let expected =
Simd::new(std::array::from_fn(|i| left[i].saturating_mul(right[i])));
let actual = Simd::new(left).saturating_mul(Simd::new(right));
assert!(
actual == expected,
"expected: {expected:?}\n actual: {actual:?}\n left: {left:?}\n right: {right:?}"
);
}
});
for_simd_types!(|T: Unsigned, N| {
for [left, right] in simd_chunks!(
[
1,
2,
3,
4,
5,
T::MAX / 4,
T::MAX / 3,
T::MAX / 2,
T::MAX - 1,
T::MAX,
T::MAX,
3,
4,
3,
2,
2,
1,
],
[
17,
18,
9,
1,
0,
3,
4,
3,
2,
2,
1,
T::MAX / 4,
T::MAX / 3,
T::MAX / 2,
T::MAX - 1,
T::MAX,
T::MAX,
],
)
.chain(random_iter())
{
let expected =
Simd::new(std::array::from_fn(|i| left[i].saturating_mul(right[i])));
let actual = Simd::new(left).saturating_mul(Simd::new(right));
assert!(
actual == expected,
"expected: {expected:?}\n actual: {actual:?}\n left: {left:?}\n right: {right:?}"
);
}
});
}
#[test]
fn test_saturating_div() {
for_simd_types!(|T: Integer, N| {
for [left, mut right] in simd_chunks!(
[11, 15, 2, 3, T::MAX, 0, T::MAX, T::MAX - 1],
[2, 5, 5, 8, 10, 5, 2, 10],
)
.chain(random_iter())
{
for right in &mut right {
if *right == 0 {
*right = 3;
}
}
let expected =
Simd::new(std::array::from_fn(|i| left[i].saturating_div(right[i])));
let actual = Simd::new(left).saturating_div(Simd::new(right));
assert!(
actual == expected,
"expected: {expected:?}\n actual: {actual:?}\n left: {left:?}\n right: {right:?}",
);
}
});
for_simd_types!(|T: Signed, N| {
for [left, mut right] in simd_chunks!(
[11, 15, -13, -16, T::MIN, 0, T::MIN, T::MIN + 1],
[-2, -5, 3, -6, -2, -1, -1, -1],
)
.chain(random_iter())
{
for right in &mut right {
if *right == 0 {
*right = 3;
}
}
let expected =
Simd::new(std::array::from_fn(|i| left[i].saturating_div(right[i])));
let actual = Simd::new(left).saturating_div(Simd::new(right));
assert!(
actual == expected,
"expected: {expected:?}\n actual: {actual:?}\n left: {left:?}\n right: {right:?}",
);
}
});
}
#[test]
fn test_from_big_truncate() {
let value = i16x16::new([
10000, 1001, 2, 3, 4, 5, 6, 32767, 10000, 1001, 2, 128, -129, -128, 127,
255,
]);
let expected = i8x16::new([
16, -23, 2, 3, 4, 5, 6, -1, 16, -23, 2, -128, 127, -128, 127, -1,
]);
let actual = i8x16::from_i16x16_truncate(value);
assert_eq!(actual, expected);
let value = i32x8::new([10000, 1001, 2, 3, 4, 5, -65536, 65536]);
let expected = i16x8::new([10000, 1001, 2, 3, 4, 5, 0, 0]);
let actual = i16x8::from_i32x8_truncate(value);
assert_eq!(actual, expected);
}
#[test]
fn test_from_big_saturate() {
let value = i16x16::new([
10000, 1001, 2, 3, 4, 5, 6, 32767, 10000, 1001, 2, 128, -129, -128, 127,
255,
]);
let expected = i8x16::new([
127, 127, 2, 3, 4, 5, 6, 127, 127, 127, 2, 127, -128, -128, 127, 127,
]);
let actual = i8x16::from_i16x16_saturate(value);
assert_eq!(actual, expected);
let value = i32x8::new([10000, 1001, 2, 3, 4, 5, -65535, 65536]);
let expected = i16x8::new([10000, 1001, 2, 3, 4, 5, -32768, 32767]);
let actual = i16x8::from_i32x8_saturate(value);
assert_eq!(actual, expected);
}
#[test]
fn test_mul_keep_high() {
for [left, right] in once([
[i16::MAX, 200, 300, 4568, -1, -2, -3, -4],
[i16::MIN, 600, 700, 8910, -15, -26, -37, 48],
])
.chain(random_iter())
{
let expected = i16x8::new(std::array::from_fn(|i| {
((left[i] as i32 * right[i] as i32) >> 16) as i16
}));
let actual = i16x8::mul_keep_high(i16x8::new(left), i16x8::new(right));
assert_eq!(actual, expected);
}
for [left, right] in once([
[u16::MAX, 200, 300, 4568, 1, 2, 3, 200],
[u16::MAX, 600, 700, 8910, 15, 26, 37, 600],
])
.chain(random_iter())
{
let expected = u16x8::new(std::array::from_fn(|i| {
((left[i] as u32 * right[i] as u32) >> 16) as u16
}));
let actual = u16x8::mul_keep_high(u16x8::new(left), u16x8::new(right));
assert_eq!(actual, expected);
}
for [left, right] in once([
[1, 2 * 10000000, 3 * 1000000, u32::MAX],
[5, 6 * 100, 7 * 1000000, u32::MAX],
])
.chain(random_iter())
{
let expected = u32x4::new(std::array::from_fn(|i| {
((left[i] as u64 * right[i] as u64) >> 32) as u32
}));
let actual = u32x4::mul_keep_high(u32x4::new(left), u32x4::new(right));
assert_eq!(actual, expected);
}
for [left, right] in once([
[
1,
2 * 10000000,
3 * 1000000,
u32::MAX,
1,
2 * 10000000,
3 * 1000000,
u32::MAX,
],
[5, 6 * 100, 7 * 1000000, u32::MAX, 5, 6 * 100, 7 * 1000000, u32::MAX],
])
.chain(random_iter())
{
let expected = u32x8::new(std::array::from_fn(|i| {
((left[i] as u64 * right[i] as u64) >> 32) as u32
}));
let actual = u32x8::mul_keep_high(u32x8::new(left), u32x8::new(right));
assert_eq!(actual, expected);
}
for [left, right] in once([
[
1,
2 * 10000000,
3 * 1000000,
u32::MAX,
1,
2 * 10000000,
3 * 1000000,
u32::MAX,
1,
2 * 10000000,
3 * 1000000,
u32::MAX,
1,
2 * 10000000,
3 * 1000000,
u32::MAX,
],
[
5,
6 * 100,
7 * 1000000,
u32::MAX,
5,
6 * 100,
7 * 1000000,
u32::MAX,
5,
6 * 100,
7 * 1000000,
u32::MAX,
5,
6 * 100,
7 * 1000000,
u32::MAX,
],
])
.chain(random_iter())
{
let expected = u32x16::new(std::array::from_fn(|i| {
((left[i] as u64 * right[i] as u64) >> 32) as u32
}));
let actual = u32x16::mul_keep_high(u32x16::new(left), u32x16::new(right));
assert_eq!(actual, expected);
}
}
#[test]
fn test_mul_widen() {
for [left, right] in once([
[1, 2, 3, 4, 5, 6, i16::MIN, i16::MAX],
[17, -18, 190, -20, 21, -22, i16::MAX, i16::MAX],
])
.chain(random_iter())
{
let expected =
i32x8::new(std::array::from_fn(|i| left[i] as i32 * right[i] as i32));
let actual = i16x8::new(left).mul_widen(i16x8::new(right));
assert_eq!(actual, expected);
}
for [left, right] in
once([[1, 2, 3 * -1000000, i32::MAX], [5, 6, 7 * -1000000, i32::MIN]])
.chain(random_iter())
{
let expected =
i64x4::new(std::array::from_fn(|i| left[i] as i64 * right[i] as i64));
let actual = i32x4::new(left).mul_widen(i32x4::new(right));
assert_eq!(actual, expected);
}
for [left, right] in once([
[1, 2, 3, 4, 5, 6, i16::MAX as u16, u16::MAX],
[17, 18, 190, 20, 21, 22, i16::MAX as u16, u16::MAX],
])
.chain(random_iter())
{
let expected =
u32x8::new(std::array::from_fn(|i| left[i] as u32 * right[i] as u32));
let actual = u16x8::new(left).mul_widen(u16x8::new(right));
assert_eq!(actual, expected);
}
for [left, right] in
once([[1, 2, 3 * 1000000, u32::MAX], [5, 6, 7 * 1000000, u32::MAX]])
.chain(random_iter())
{
let expected =
u64x4::new(std::array::from_fn(|i| left[i] as u64 * right[i] as u64));
let actual = u32x4::new(left).mul_widen(u32x4::new(right));
assert_eq!(actual, expected);
}
}
#[test]
fn test_round_float() {
let value = i32x4::new([-1, 30, i32::MIN, i32::MAX]);
let expected = f32x4::new([-1.0, 30.0, i32::MIN as f32, i32::MAX as f32]);
let actual = value.round_float();
assert_eq!(actual, expected);
let value =
i32x16::new([0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1]);
let expected = f32x16::new([
0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0,
-2.0, -1.0,
]);
let actual = value.round_float();
assert_eq!(actual, expected);
let value = i32x8::new([-1, 30, i32::MIN, i32::MAX, 29, 35, -8, 0]);
let expected = f32x8::new([
-1.0,
30.0,
i32::MIN as f32,
i32::MAX as f32,
29.0,
35.0,
-8.0,
0.0,
]);
let actual = value.round_float();
assert_eq!(actual, expected);
}
#[test]
fn test_swizzle() {
for (value, indices, expected) in [
(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0],
[16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
),
(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[15, 17, -13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, -1, 0],
[16, 0, 0, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 0, 1],
),
] {
let value = i8x16::new(value);
let indices = i8x16::new(indices);
let expected = i8x16::new(expected);
let actual = value.swizzle(indices);
assert_eq!(actual, expected);
}
}
#[test]
fn test_swizzle_relaxed() {
for (value, indices, expected) in [
(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0],
[16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
),
(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[15, -17, -13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, -1, 0],
[16, 0, 0, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 0, 1],
),
] {
let value = i8x16::new(value);
let indices = i8x16::new(indices);
let expected = i8x16::new(expected);
let actual = value.swizzle_relaxed(indices);
assert_eq!(actual, expected);
}
}
#[test]
fn test_swizzle_half() {
let value = i8x32::new([
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
]);
let indices = i8x32::new([
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11,
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
]);
let expected = i8x32::new([
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 32, 31, 30, 29, 28,
27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
]);
let actual = value.swizzle_half(indices);
assert_eq!(actual, expected);
}
#[test]
fn test_from_u8x16_low() {
let value =
u8x16::new([1, 2, 3, 4, 5, 6, 7, u8::MAX, 9, 10, 11, 12, 13, 14, 15, 16]);
let expected = i16x8::new([1, 2, 3, 4, 5, 6, 7, u8::MAX as i16]);
let actual = i16x8::from_u8x16_low(value);
assert_eq!(actual, expected);
let value =
u8x16::from([255, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 255, 128]);
let expected = u16x8::from([255, 2, 3, 4, 5, 6, 7, 8]);
let actual = u16x8::from_u8x16_low(value);
assert_eq!(actual, expected);
}
#[test]
fn test_from_u8x16_high() {
let value =
u8x16::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 255, 128]);
let expected = i16x8::new([9, 10, 11, 12, 13, 14, 255, 128]);
let actual = i16x8::from_u8x16_high(value);
assert_eq!(actual, expected);
let value =
u8x16::from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 255, 128]);
let expected = u16x8::from([9, 10, 11, 12, 13, 14, 255, 128]);
let actual = u16x8::from_u8x16_high(value);
assert_eq!(actual, expected);
}
#[test]
fn test_narrow_i16x8() {
let a = i16x8::new([-1, 2, -3, 4, -5, 6, -7, 8]);
let b = i16x8::new([9, 10, 11, 12, 13, -14, 15, -16]);
let expected =
u8x16::new([0, 2, 0, 4, 0, 6, 0, 8, 9, 10, 11, 12, 13, 0, 15, 0]);
let actual = u8x16::narrow_i16x8(a, b);
assert_eq!(actual, expected);
}