generic_simd/arch/wasm/
mod.rs

1//! WebAssembly vector types.
2
3#[cfg(feature = "complex")]
4mod complex;
5#[cfg(feature = "complex")]
6pub use complex::*;
7
8use crate::{
9    arch::{generic, Token},
10    scalar::Scalar,
11    shim::{Shim2, Shim4, ShimToken},
12    vector::{width, Native, Vector},
13};
14use core::arch::wasm32::*;
15
16/// simd128 instruction set token.
17#[derive(Copy, Clone, Debug)]
18pub struct Simd128(());
19
20impl_token! { Simd128 => "simd128" }
21
22impl Native<Simd128> for f32 {
23    type Width = width::W4;
24}
25
26impl Native<Simd128> for f64 {
27    type Width = width::W2;
28}
29
30/// A simd128 vector of `f32`s.
31#[derive(Clone, Copy, Debug)]
32#[repr(transparent)]
33#[allow(non_camel_case_types)]
34pub struct f32x4(v128);
35
36/// A simd128 vector of `f64`s.
37#[derive(Clone, Copy, Debug)]
38#[repr(transparent)]
39#[allow(non_camel_case_types)]
40pub struct f64x2(v128);
41
42impl Scalar<Simd128, width::W1> for f32 {
43    type Vector = ShimToken<generic::f32x1, Self, Simd128>;
44}
45
46impl Scalar<Simd128, width::W2> for f32 {
47    type Vector = ShimToken<Shim2<generic::f32x1, Self>, Self, Simd128>;
48}
49
50impl Scalar<Simd128, width::W4> for f32 {
51    type Vector = f32x4;
52}
53
54impl Scalar<Simd128, width::W8> for f32 {
55    type Vector = Shim2<f32x4, f32>;
56}
57
58impl Scalar<Simd128, width::W1> for f64 {
59    type Vector = ShimToken<generic::f64x1, Self, Simd128>;
60}
61
62impl Scalar<Simd128, width::W2> for f64 {
63    type Vector = f64x2;
64}
65
66impl Scalar<Simd128, width::W4> for f64 {
67    type Vector = Shim2<f64x2, f64>;
68}
69
70impl Scalar<Simd128, width::W8> for f64 {
71    type Vector = Shim4<f64x2, f64>;
72}
73
74as_slice! { f32x4 }
75as_slice! { f64x2 }
76
77unsafe impl Vector for f32x4 {
78    type Scalar = f32;
79    type Token = Simd128;
80    type Width = width::W4;
81    type Underlying = v128;
82
83    #[inline]
84    fn zeroed(_: Self::Token) -> Self {
85        Self(unsafe { f32x4_splat(0.) })
86    }
87
88    #[inline]
89    fn splat(_: Self::Token, value: Self::Scalar) -> Self {
90        Self(unsafe { f32x4_splat(value) })
91    }
92}
93
94unsafe impl Vector for f64x2 {
95    type Scalar = f64;
96    type Token = Simd128;
97    type Width = width::W2;
98    type Underlying = v128;
99
100    #[inline]
101    fn zeroed(_: Self::Token) -> Self {
102        Self(unsafe { f64x2_splat(0.) })
103    }
104
105    #[inline]
106    fn splat(_: Self::Token, value: Self::Scalar) -> Self {
107        Self(unsafe { f64x2_splat(value) })
108    }
109}
110
111arithmetic_ops! {
112    feature: Simd128::new_unchecked(),
113    for f32x4:
114        add -> (f32x4_add),
115        sub -> (f32x4_sub),
116        mul -> (f32x4_mul),
117        div -> (f32x4_div)
118}
119
120arithmetic_ops! {
121    feature: Simd128::new_unchecked(),
122    for f64x2:
123        add -> (f64x2_add),
124        sub -> (f64x2_sub),
125        mul -> (f64x2_mul),
126        div -> (f64x2_div)
127}
128
129impl core::ops::Neg for f32x4 {
130    type Output = Self;
131
132    #[inline]
133    fn neg(self) -> Self {
134        Self(unsafe { f32x4_neg(self.0) })
135    }
136}
137
138impl core::ops::Neg for f64x2 {
139    type Output = Self;
140
141    #[inline]
142    fn neg(self) -> Self {
143        Self(unsafe { f64x2_neg(self.0) })
144    }
145}