Skip to content

Commit 866971a

Browse files
committed
Implement abs, to_bits, and from_bits for float vectors
1 parent 0b39351 commit 866971a

File tree

4 files changed

+106
-7
lines changed

4 files changed

+106
-7
lines changed

crates/core_simd/src/macros.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,52 @@ macro_rules! define_vector {
270270
}
271271
}
272272

273+
/// Implements inherent methods for a float vector `$name` containing multiple
274+
/// `$lanes` of float `$type`, which uses `$bits_ty` as its binary
275+
/// representation. Called from `define_float_vector!`.
276+
macro_rules! impl_float_vector {
277+
{ $name:path => [$type:ty; $lanes:literal]; bits $bits_ty:ty; } => {
278+
impl $name {
279+
/// Raw transmutation to an unsigned integer vector type with the
280+
/// same size and number of lanes.
281+
#[inline]
282+
pub fn to_bits(self) -> $bits_ty {
283+
unsafe { core::mem::transmute(self) }
284+
}
285+
286+
/// Raw transmutation from an unsigned integer vector type with the
287+
/// same size and number of lanes.
288+
#[inline]
289+
pub fn from_bits(bits: $bits_ty) -> Self {
290+
unsafe { core::mem::transmute(bits) }
291+
}
292+
293+
/// Produces a vector where every lane has the absolute value of the
294+
/// equivalently-indexed lane in `self`.
295+
#[inline]
296+
pub fn abs(self) -> Self {
297+
let no_sign = <$bits_ty>::splat(!0 >> 1);
298+
let abs = unsafe { crate::intrinsics::simd_and(self.to_bits(), no_sign) };
299+
Self::from_bits(abs)
300+
}
301+
}
302+
};
303+
}
304+
305+
/// Defines a float vector `$name` containing multiple `$lanes` of float
306+
/// `$type`, which uses `$bits_ty` as its binary representation.
307+
macro_rules! define_float_vector {
308+
{ $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); bits $bits_ty:ty; } => {
309+
define_vector! {
310+
$(#[$attr])*
311+
struct $name([$type; $lanes]);
312+
}
313+
314+
impl_float_vector! { $name => [$type; $lanes]; bits $bits_ty; }
315+
}
316+
}
317+
318+
273319
/// Defines an integer vector `$name` containing multiple `$lanes` of integer `$type`.
274320
macro_rules! define_integer_vector {
275321
{ $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {

crates/core_simd/src/vectors_f32.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
1-
define_vector! {
1+
define_float_vector! {
22
/// Vector of two `f32` values
33
struct f32x2([f32; 2]);
4+
bits crate::u32x2;
45
}
56

6-
define_vector! {
7+
define_float_vector! {
78
/// Vector of four `f32` values
89
struct f32x4([f32; 4]);
10+
bits crate::u32x4;
911
}
1012

11-
define_vector! {
13+
define_float_vector! {
1214
/// Vector of eight `f32` values
1315
struct f32x8([f32; 8]);
16+
bits crate::u32x8;
1417
}
1518

16-
define_vector! {
19+
define_float_vector! {
1720
/// Vector of 16 `f32` values
1821
struct f32x16([f32; 16]);
22+
bits crate::u32x16;
1923
}
2024

2125
from_transmute_x86! { unsafe f32x4 => __m128 }
2226
from_transmute_x86! { unsafe f32x8 => __m256 }
2327
//from_transmute_x86! { unsafe f32x16 => __m512 }
28+
29+

crates/core_simd/src/vectors_f64.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
define_vector! {
1+
define_float_vector! {
22
/// Vector of two `f64` values
33
struct f64x2([f64; 2]);
4+
bits crate::u64x2;
45
}
56

6-
define_vector! {
7+
define_float_vector! {
78
/// Vector of four `f64` values
89
struct f64x4([f64; 4]);
10+
bits crate::u64x4;
911
}
1012

11-
define_vector! {
13+
define_float_vector! {
1214
/// Vector of eight `f64` values
1315
struct f64x8([f64; 8]);
16+
bits crate::u64x8;
1417
}
1518

1619
from_transmute_x86! { unsafe f64x2 => __m128d }

crates/core_simd/tests/ops_impl/float_macros.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,26 @@ macro_rules! float_tests {
2121

2222
const A: [$scalar; 16] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15.];
2323
const B: [$scalar; 16] = [16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28., 29., 30., 31.];
24+
const C: [$scalar; 16] = [
25+
-0.0,
26+
0.0,
27+
-1.0,
28+
1.0,
29+
<$scalar>::MIN,
30+
<$scalar>::MAX,
31+
<$scalar>::INFINITY,
32+
-<$scalar>::INFINITY,
33+
<$scalar>::MIN_POSITIVE,
34+
-<$scalar>::MIN_POSITIVE,
35+
<$scalar>::EPSILON,
36+
-<$scalar>::EPSILON,
37+
0.0 / 0.0,
38+
-0.0 / 0.0,
39+
// Still not sure if wasm can have weird nans, or I'd check them
40+
// too. Until then
41+
1.0 / 3.0,
42+
-1.0 / 4.0
43+
];
2444

2545
#[test]
2646
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
@@ -264,6 +284,30 @@ macro_rules! float_tests {
264284
let expected = apply_unary_lanewise(v, core::ops::Neg::neg);
265285
assert_biteq!(-v, expected);
266286
}
287+
288+
#[test]
289+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
290+
fn abs_negative() {
291+
let v = -from_slice(&A);
292+
let expected = apply_unary_lanewise(v, <$scalar>::abs);
293+
assert_biteq!(v.abs(), expected);
294+
}
295+
296+
#[test]
297+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
298+
fn abs_positive() {
299+
let v = from_slice(&B);
300+
let expected = apply_unary_lanewise(v, <$scalar>::abs);
301+
assert_biteq!(v.abs(), expected);
302+
}
303+
304+
#[test]
305+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
306+
fn abs_odd_floats() {
307+
let v = from_slice(&C);
308+
let expected = apply_unary_lanewise(v, <$scalar>::abs);
309+
assert_biteq!(v.abs(), expected);
310+
}
267311
}
268312
}
269313
}

0 commit comments

Comments
 (0)