surpass/simd/
mod.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#![allow(non_camel_case_types)]
6
7#[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
8mod aarch64;
9#[cfg(not(any(
10    all(
11        target_arch = "x86_64",
12        target_feature = "avx",
13        target_feature = "avx2",
14        target_feature = "fma",
15    ),
16    all(target_arch = "aarch64", target_feature = "neon"),
17    all(target_arch = "wasm32", target_feature = "simd128"),
18)))]
19mod auto;
20#[cfg(all(
21    target_arch = "x86_64",
22    target_feature = "avx",
23    target_feature = "avx2",
24    target_feature = "fma"
25))]
26mod avx;
27#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
28mod wasm32;
29
30#[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
31pub use aarch64::*;
32#[cfg(not(any(
33    all(
34        target_arch = "x86_64",
35        target_feature = "avx",
36        target_feature = "avx2",
37        target_feature = "fma",
38    ),
39    all(target_arch = "aarch64", target_feature = "neon"),
40    all(target_arch = "wasm32", target_feature = "simd128"),
41)))]
42pub use auto::*;
43#[cfg(all(
44    target_arch = "x86_64",
45    target_feature = "avx",
46    target_feature = "avx2",
47    target_feature = "fma",
48))]
49pub use avx::*;
50#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
51pub use wasm32::*;
52
53pub trait Simd {
54    const LANES: usize;
55}
56
57impl Simd for u8x32 {
58    const LANES: usize = 32;
59}
60
61impl Simd for i8x16 {
62    const LANES: usize = 16;
63}
64
65impl Simd for i16x16 {
66    const LANES: usize = 16;
67}
68
69impl Simd for i32x8 {
70    const LANES: usize = 8;
71}
72
73impl Simd for f32x8 {
74    const LANES: usize = 8;
75}
76
77#[cfg(test)]
78mod tests {
79    use std::f32::INFINITY;
80
81    use super::*;
82
83    #[test]
84    fn f32x8_splat() {
85        for v in [1.0, 0.0, f32::INFINITY, f32::NEG_INFINITY] {
86            assert_eq!(f32x8::splat(v).to_array(), [v; 8]);
87        }
88    }
89
90    #[test]
91    fn f32x8_indexed() {
92        let index: Vec<f32> = (0..8).map(|v| v as f32).collect();
93        assert_eq!(f32x8::indexed().to_array(), index[..]);
94    }
95
96    #[test]
97    fn f32x8_from_array() {
98        let value = [-5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0];
99        assert_eq!(f32x8::from_array(value).to_array(), value);
100    }
101
102    #[test]
103    fn u32x8_splat() {
104        assert_eq!([0; 8], u32x8::splat(0).to_array());
105        assert_eq!([u32::MAX; 8], u32x8::splat(u32::MAX).to_array());
106        assert_eq!([u32::MIN; 8], u32x8::splat(u32::MIN).to_array());
107    }
108
109    #[test]
110    fn u32x8_mul_add() {
111        let a = u32x8::from(f32x8::from_array([10.0, 20.0, 30.0, 50.0, 70.0, 110.0, 130.0, 170.0]));
112        let b = u32x8::from(f32x8::from_array([19.0, 23.0, 29.0, 31.0, 37.0, 41.0, 43.0, 47.0]));
113        let c = u32x8::from(f32x8::from_array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]));
114        let expected = [191, 462, 873, 1554, 2595, 4516, 5597, 7998];
115        assert_eq!(expected, u32x8::mul_add(a, b, c).to_array());
116
117        let a = u32x8::from(f32x8::splat(0x007f_ffff as f32));
118        let b = u32x8::from(f32x8::splat(0x200 as f32));
119        let c = u32x8::from(f32x8::splat(0x1ff as f32));
120        let expected = [u32::MAX; 8];
121        assert_eq!(expected, u32x8::mul_add(a, b, c).to_array());
122    }
123
124    #[test]
125    fn u32x8_from_f32x8() {
126        let values = u32x8::from(f32x8::from_array([
127            -INFINITY,
128            -f32::MAX,
129            -2.5,
130            -1.0,
131            -0.5,
132            -f32::MIN_POSITIVE,
133            -0.0,
134            0.0,
135        ]));
136        assert_eq!(values.to_array(), [0u32; 8]);
137
138        let f32_before = |f| f32::from_bits(f32::to_bits(f) - 1);
139        let values = u32x8::from(f32x8::from_array([
140            0.0,
141            f32::MIN_POSITIVE,
142            0.4,
143            0.5,
144            0.6,
145            0.7,
146            0.8,
147            f32_before(1.),
148        ]));
149        assert_eq!(values.to_array(), [0u32; 8]);
150
151        let values = u32x8::from(f32x8::from_array([
152            1.0,
153            1.4,
154            1.5,
155            f32_before(2.0),
156            2.0,
157            2.4,
158            2.5,
159            f32_before(3.0),
160        ]));
161        assert_eq!(values.to_array(), [1, 1, 1, 1, 2, 2, 2, 2]);
162
163        const MAX_INT_F32: u32 = 1u32 << 24;
164        for value in (MAX_INT_F32 - 255)..MAX_INT_F32 {
165            assert_eq!([value; 8], u32x8::from(f32x8::splat(value as f32)).to_array());
166        }
167    }
168}