blob: 267a237725b083c4d3b99a40daa06991ea597404 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#![allow(non_camel_case_types)]
#[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
mod aarch64;
#[cfg(not(any(
all(
target_arch = "x86_64",
target_feature = "avx",
target_feature = "avx2",
target_feature = "fma",
),
all(target_arch = "aarch64", target_feature = "neon"),
all(target_arch = "wasm32", target_feature = "simd128"),
)))]
mod auto;
#[cfg(all(
target_arch = "x86_64",
target_feature = "avx",
target_feature = "avx2",
target_feature = "fma"
))]
mod avx;
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
mod wasm32;
#[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
pub use aarch64::*;
#[cfg(not(any(
all(
target_arch = "x86_64",
target_feature = "avx",
target_feature = "avx2",
target_feature = "fma",
),
all(target_arch = "aarch64", target_feature = "neon"),
all(target_arch = "wasm32", target_feature = "simd128"),
)))]
pub use auto::*;
#[cfg(all(
target_arch = "x86_64",
target_feature = "avx",
target_feature = "avx2",
target_feature = "fma",
))]
pub use avx::*;
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
pub use wasm32::*;
pub trait Simd {
const LANES: usize;
}
impl Simd for u8x32 {
const LANES: usize = 32;
}
impl Simd for i8x16 {
const LANES: usize = 16;
}
impl Simd for i16x16 {
const LANES: usize = 16;
}
impl Simd for i32x8 {
const LANES: usize = 8;
}
impl Simd for f32x8 {
const LANES: usize = 8;
}
#[cfg(test)]
mod tests {
use std::f32::INFINITY;
use super::*;
#[test]
fn f32x8_splat() {
for v in [1.0, 0.0, f32::INFINITY, f32::NEG_INFINITY] {
assert_eq!(f32x8::splat(v).to_array(), [v; 8]);
}
}
#[test]
fn f32x8_indexed() {
let index: Vec<f32> = (0..8).map(|v| v as f32).collect();
assert_eq!(f32x8::indexed().to_array(), index[..]);
}
#[test]
fn f32x8_from_array() {
let value = [-5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0];
assert_eq!(f32x8::from_array(value).to_array(), value);
}
#[test]
fn u32x8_splat() {
assert_eq!([0; 8], u32x8::splat(0).to_array());
assert_eq!([u32::MAX; 8], u32x8::splat(u32::MAX).to_array());
assert_eq!([u32::MIN; 8], u32x8::splat(u32::MIN).to_array());
}
#[test]
fn u32x8_mul_add() {
let a = u32x8::from(f32x8::from_array([10.0, 20.0, 30.0, 50.0, 70.0, 110.0, 130.0, 170.0]));
let b = u32x8::from(f32x8::from_array([19.0, 23.0, 29.0, 31.0, 37.0, 41.0, 43.0, 47.0]));
let c = u32x8::from(f32x8::from_array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]));
let expected = [191, 462, 873, 1554, 2595, 4516, 5597, 7998];
assert_eq!(expected, u32x8::mul_add(a, b, c).to_array());
let a = u32x8::from(f32x8::splat(0x007f_ffff as f32));
let b = u32x8::from(f32x8::splat(0x200 as f32));
let c = u32x8::from(f32x8::splat(0x1ff as f32));
let expected = [u32::MAX; 8];
assert_eq!(expected, u32x8::mul_add(a, b, c).to_array());
}
#[test]
fn u32x8_from_f32x8() {
let values = u32x8::from(f32x8::from_array([
-INFINITY,
-f32::MAX,
-2.5,
-1.0,
-0.5,
-f32::MIN_POSITIVE,
-0.0,
0.0,
]));
assert_eq!(values.to_array(), [0u32; 8]);
let f32_before = |f| f32::from_bits(f32::to_bits(f) - 1);
let values = u32x8::from(f32x8::from_array([
0.0,
f32::MIN_POSITIVE,
0.4,
0.5,
0.6,
0.7,
0.8,
f32_before(1.),
]));
assert_eq!(values.to_array(), [0u32; 8]);
let values = u32x8::from(f32x8::from_array([
1.0,
1.4,
1.5,
f32_before(2.0),
2.0,
2.4,
2.5,
f32_before(3.0),
]));
assert_eq!(values.to_array(), [1, 1, 1, 1, 2, 2, 2, 2]);
const MAX_INT_F32: u32 = 1u32 << 24;
for value in (MAX_INT_F32 - 255)..MAX_INT_F32 {
assert_eq!([value; 8], u32x8::from(f32x8::splat(value as f32)).to_array());
}
}
}