Skip to content

Commit a1c327a

Browse files
authored
Merge pull request rust-lang#27 from thomcc/abs_from_to_bits
Implement abs, to_bits, and from_bits for float vectors
2 parents 0b39351 + 8d3d616 commit a1c327a

File tree

4 files changed

+110
-7
lines changed

4 files changed

+110
-7
lines changed

crates/core_simd/src/macros.rs

+45
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,51 @@ 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+
Self::from_bits(self.to_bits() & no_sign)
299+
}
300+
}
301+
};
302+
}
303+
304+
/// Defines a float vector `$name` containing multiple `$lanes` of float
305+
/// `$type`, which uses `$bits_ty` as its binary representation.
306+
macro_rules! define_float_vector {
307+
{ $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); bits $bits_ty:ty; } => {
308+
define_vector! {
309+
$(#[$attr])*
310+
struct $name([$type; $lanes]);
311+
}
312+
313+
impl_float_vector! { $name => [$type; $lanes]; bits $bits_ty; }
314+
}
315+
}
316+
317+
273318
/// Defines an integer vector `$name` containing multiple `$lanes` of integer `$type`.
274319
macro_rules! define_integer_vector {
275320
{ $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {

crates/core_simd/src/vectors_f32.rs

+10-4
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

+6-3
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

+49
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,32 @@ macro_rules! float_tests {
1919
value
2020
}
2121

22+
fn slice_chunks(slice: &[$scalar]) -> impl Iterator<Item = core_simd::$vector> + '_ {
23+
let lanes = core::mem::size_of::<core_simd::$vector>() / core::mem::size_of::<$scalar>();
24+
slice.chunks_exact(lanes).map(from_slice)
25+
}
26+
2227
const A: [$scalar; 16] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15.];
2328
const B: [$scalar; 16] = [16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28., 29., 30., 31.];
29+
const C: [$scalar; 16] = [
30+
-0.0,
31+
0.0,
32+
-1.0,
33+
1.0,
34+
<$scalar>::MIN,
35+
<$scalar>::MAX,
36+
<$scalar>::INFINITY,
37+
<$scalar>::NEG_INFINITY,
38+
<$scalar>::MIN_POSITIVE,
39+
-<$scalar>::MIN_POSITIVE,
40+
<$scalar>::EPSILON,
41+
-<$scalar>::EPSILON,
42+
<$scalar>::NAN,
43+
-<$scalar>::NAN,
44+
// TODO: Would be nice to check sNaN...
45+
100.0 / 3.0,
46+
-100.0 / 3.0,
47+
];
2448

2549
#[test]
2650
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
@@ -264,6 +288,31 @@ macro_rules! float_tests {
264288
let expected = apply_unary_lanewise(v, core::ops::Neg::neg);
265289
assert_biteq!(-v, expected);
266290
}
291+
292+
#[test]
293+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
294+
fn abs_negative() {
295+
let v = -from_slice(&A);
296+
let expected = apply_unary_lanewise(v, <$scalar>::abs);
297+
assert_biteq!(v.abs(), expected);
298+
}
299+
300+
#[test]
301+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
302+
fn abs_positive() {
303+
let v = from_slice(&B);
304+
let expected = apply_unary_lanewise(v, <$scalar>::abs);
305+
assert_biteq!(v.abs(), expected);
306+
}
307+
308+
#[test]
309+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
310+
fn abs_odd_floats() {
311+
for v in slice_chunks(&C) {
312+
let expected = apply_unary_lanewise(v, <$scalar>::abs);
313+
assert_biteq!(v.abs(), expected);
314+
}
315+
}
267316
}
268317
}
269318
}

0 commit comments

Comments
 (0)