Skip to content

Commit b2763cc

Browse files
committed
Auto merge of #94899 - workingjubilee:bump-simd-clamp, r=workingjubilee
Bump portable-simd to shadow Ord Yon usual bump. Summary for reference: - We are moving away from the subjective "directional" nomenclature, so `horizontal_*` becomes `reduce_*`, et cetera. - In addition, `Simd<Int, N>` now has methods which shadow Ord's methods directly, making those methods behave like the already "overloaded" float methods do.
2 parents 4800c78 + 2b1f249 commit b2763cc

File tree

20 files changed

+214
-105
lines changed

20 files changed

+214
-105
lines changed

library/core/src/slice/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3536,7 +3536,7 @@ impl<T> [T] {
35363536
/// suffix.iter().copied().sum(),
35373537
/// ]);
35383538
/// let sums = middle.iter().copied().fold(sums, f32x4::add);
3539-
/// sums.horizontal_sum()
3539+
/// sums.reduce_sum()
35403540
/// }
35413541
///
35423542
/// let numbers: Vec<f32> = (1..101).map(|x| x as _).collect();

library/portable-simd/beginners-guide.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ SIMD has a few special vocabulary terms you should know:
3333

3434
* **Vertical:** When an operation is "vertical", each lane processes individually without regard to the other lanes in the same vector. For example, a "vertical add" between two vectors would add lane 0 in `a` with lane 0 in `b`, with the total in lane 0 of `out`, and then the same thing for lanes 1, 2, etc. Most SIMD operations are vertical operations, so if your problem is a vertical problem then you can probably solve it with SIMD.
3535

36-
* **Horizontal:** When an operation is "horizontal", the lanes within a single vector interact in some way. A "horizontal add" might add up lane 0 of `a` with lane 1 of `a`, with the total in lane 0 of `out`.
36+
* **Reducing/Reduce:** When an operation is "reducing" (functions named `reduce_*`), the lanes within a single vector are merged using some operation such as addition, returning the merged value as a scalar. For instance, a reducing add would return the sum of all the lanes' values.
3737

3838
* **Target Feature:** Rust calls a CPU architecture extension a `target_feature`. Proper SIMD requires various CPU extensions to be enabled (details below). Don't confuse this with `feature`, which is a Cargo crate concept.
3939

@@ -83,4 +83,4 @@ Fortunately, most SIMD types have a fairly predictable size. `i32x4` is bit-equi
8383
However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`mem::align_of`].
8484

8585
[`mem::transmute`]: https://doc.rust-lang.org/core/mem/fn.transmute.html
86-
[`mem::align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html
86+
[`mem::align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html

library/portable-simd/crates/core_simd/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ categories = ["hardware-support", "no-std"]
99
license = "MIT OR Apache-2.0"
1010

1111
[features]
12-
default = ["std", "generic_const_exprs"]
12+
default = []
1313
std = []
1414
generic_const_exprs = []
1515

library/portable-simd/crates/core_simd/examples/matrix_inversion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ pub fn simd_inv4x4(m: Matrix4x4) -> Option<Matrix4x4> {
233233
let det = det.rotate_lanes_right::<2>() + det;
234234
let det = det.reverse().rotate_lanes_right::<2>() + det;
235235

236-
if det.horizontal_sum() == 0. {
236+
if det.reduce_sum() == 0. {
237237
return None;
238238
}
239239
// calculate the reciprocal

library/portable-simd/crates/core_simd/examples/nbody.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ mod nbody {
107107
let mut e = 0.;
108108
for i in 0..N_BODIES {
109109
let bi = &bodies[i];
110-
e += bi.mass * (bi.v * bi.v).horizontal_sum() * 0.5;
110+
e += bi.mass * (bi.v * bi.v).reduce_sum() * 0.5;
111111
for bj in bodies.iter().take(N_BODIES).skip(i + 1) {
112112
let dx = bi.x - bj.x;
113-
e -= bi.mass * bj.mass / (dx * dx).horizontal_sum().sqrt()
113+
e -= bi.mass * bj.mass / (dx * dx).reduce_sum().sqrt()
114114
}
115115
}
116116
e
@@ -134,8 +134,8 @@ mod nbody {
134134
let mut mag = [0.0; N];
135135
for i in (0..N).step_by(2) {
136136
let d2s = f64x2::from_array([
137-
(r[i] * r[i]).horizontal_sum(),
138-
(r[i + 1] * r[i + 1]).horizontal_sum(),
137+
(r[i] * r[i]).reduce_sum(),
138+
(r[i + 1] * r[i + 1]).reduce_sum(),
139139
]);
140140
let dmags = f64x2::splat(dt) / (d2s * d2s.sqrt());
141141
mag[i] = dmags[0];

library/portable-simd/crates/core_simd/examples/spectral_norm.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ fn mult_av(v: &[f64], out: &mut [f64]) {
2020
sum += b / a;
2121
j += 2
2222
}
23-
*out = sum.horizontal_sum();
23+
*out = sum.reduce_sum();
2424
}
2525
}
2626

@@ -38,7 +38,7 @@ fn mult_atv(v: &[f64], out: &mut [f64]) {
3838
sum += b / a;
3939
j += 2
4040
}
41-
*out = sum.horizontal_sum();
41+
*out = sum.reduce_sum();
4242
}
4343
}
4444

library/portable-simd/crates/core_simd/src/comparisons.rs

+52
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,55 @@ where
6666
unsafe { Mask::from_int_unchecked(intrinsics::simd_ge(self, other)) }
6767
}
6868
}
69+
70+
macro_rules! impl_ord_methods_vector {
71+
{ $type:ty } => {
72+
impl<const LANES: usize> Simd<$type, LANES>
73+
where
74+
LaneCount<LANES>: SupportedLaneCount,
75+
{
76+
/// Returns the lane-wise minimum with `other`.
77+
#[must_use = "method returns a new vector and does not mutate the original value"]
78+
#[inline]
79+
pub fn min(self, other: Self) -> Self {
80+
self.lanes_gt(other).select(other, self)
81+
}
82+
83+
/// Returns the lane-wise maximum with `other`.
84+
#[must_use = "method returns a new vector and does not mutate the original value"]
85+
#[inline]
86+
pub fn max(self, other: Self) -> Self {
87+
self.lanes_lt(other).select(other, self)
88+
}
89+
90+
/// Restrict each lane to a certain interval.
91+
///
92+
/// For each lane, returns `max` if `self` is greater than `max`, and `min` if `self` is
93+
/// less than `min`. Otherwise returns `self`.
94+
///
95+
/// # Panics
96+
///
97+
/// Panics if `min > max` on any lane.
98+
#[must_use = "method returns a new vector and does not mutate the original value"]
99+
#[inline]
100+
pub fn clamp(self, min: Self, max: Self) -> Self {
101+
assert!(
102+
min.lanes_le(max).all(),
103+
"each lane in `min` must be less than or equal to the corresponding lane in `max`",
104+
);
105+
self.max(min).min(max)
106+
}
107+
}
108+
}
109+
}
110+
111+
impl_ord_methods_vector!(i8);
112+
impl_ord_methods_vector!(i16);
113+
impl_ord_methods_vector!(i32);
114+
impl_ord_methods_vector!(i64);
115+
impl_ord_methods_vector!(isize);
116+
impl_ord_methods_vector!(u8);
117+
impl_ord_methods_vector!(u16);
118+
impl_ord_methods_vector!(u32);
119+
impl_ord_methods_vector!(u64);
120+
impl_ord_methods_vector!(usize);

library/portable-simd/crates/core_simd/src/intrinsics.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
//!
1919
//! Unless stated otherwise, all intrinsics for binary operations require SIMD vectors of equal types and lengths.
2020
21-
2221
// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are
2322
// mostly lowered to the matching LLVM instructions by the compiler in a fairly straightforward manner.
2423
// The associated LLVM instruction or intrinsic is documented alongside each Rust intrinsic function.
@@ -130,6 +129,14 @@ extern "platform-intrinsic" {
130129
pub(crate) fn simd_reduce_xor<T, U>(x: T) -> U;
131130

132131
// truncate integer vector to bitmask
132+
// `fn simd_bitmask(vector) -> unsigned integer` takes a vector of integers and
133+
// returns either an unsigned integer or array of `u8`.
134+
// Every element in the vector becomes a single bit in the returned bitmask.
135+
// If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits.
136+
// The bit order of the result depends on the byte endianness. LSB-first for little
137+
// endian and MSB-first for big endian.
138+
//
139+
// UB if called on a vector with values other than 0 and -1.
133140
#[allow(unused)]
134141
pub(crate) fn simd_bitmask<T, U>(x: T) -> U;
135142

library/portable-simd/crates/core_simd/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
#![cfg_attr(not(feature = "std"), no_std)]
1+
#![no_std]
22
#![feature(
3-
const_fn_trait_bound,
43
convert_float_to_int,
54
decl_macro,
65
intra_doc_pointers,

library/portable-simd/crates/core_simd/src/masks/to_bitmask.rs

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ macro_rules! impl_integer_intrinsic {
5050
}
5151

5252
impl_integer_intrinsic! {
53+
unsafe impl ToBitMask<BitMask=u8> for Mask<_, 1>
54+
unsafe impl ToBitMask<BitMask=u8> for Mask<_, 2>
55+
unsafe impl ToBitMask<BitMask=u8> for Mask<_, 4>
5356
unsafe impl ToBitMask<BitMask=u8> for Mask<_, 8>
5457
unsafe impl ToBitMask<BitMask=u16> for Mask<_, 16>
5558
unsafe impl ToBitMask<BitMask=u32> for Mask<_, 32>

library/portable-simd/crates/core_simd/src/math.rs

+7-14
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ macro_rules! impl_uint_arith {
1010
/// # Examples
1111
/// ```
1212
/// # #![feature(portable_simd)]
13-
/// # #[cfg(feature = "std")] use core_simd::Simd;
14-
/// # #[cfg(not(feature = "std"))] use core::simd::Simd;
13+
/// # use core::simd::Simd;
1514
#[doc = concat!("# use core::", stringify!($ty), "::MAX;")]
1615
/// let x = Simd::from_array([2, 1, 0, MAX]);
1716
/// let max = Simd::splat(MAX);
@@ -31,8 +30,7 @@ macro_rules! impl_uint_arith {
3130
/// # Examples
3231
/// ```
3332
/// # #![feature(portable_simd)]
34-
/// # #[cfg(feature = "std")] use core_simd::Simd;
35-
/// # #[cfg(not(feature = "std"))] use core::simd::Simd;
33+
/// # use core::simd::Simd;
3634
#[doc = concat!("# use core::", stringify!($ty), "::MAX;")]
3735
/// let x = Simd::from_array([2, 1, 0, MAX]);
3836
/// let max = Simd::splat(MAX);
@@ -58,8 +56,7 @@ macro_rules! impl_int_arith {
5856
/// # Examples
5957
/// ```
6058
/// # #![feature(portable_simd)]
61-
/// # #[cfg(feature = "std")] use core_simd::Simd;
62-
/// # #[cfg(not(feature = "std"))] use core::simd::Simd;
59+
/// # use core::simd::Simd;
6360
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
6461
/// let x = Simd::from_array([MIN, 0, 1, MAX]);
6562
/// let max = Simd::splat(MAX);
@@ -79,8 +76,7 @@ macro_rules! impl_int_arith {
7976
/// # Examples
8077
/// ```
8178
/// # #![feature(portable_simd)]
82-
/// # #[cfg(feature = "std")] use core_simd::Simd;
83-
/// # #[cfg(not(feature = "std"))] use core::simd::Simd;
79+
/// # use core::simd::Simd;
8480
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
8581
/// let x = Simd::from_array([MIN, -2, -1, MAX]);
8682
/// let max = Simd::splat(MAX);
@@ -100,8 +96,7 @@ macro_rules! impl_int_arith {
10096
/// # Examples
10197
/// ```
10298
/// # #![feature(portable_simd)]
103-
/// # #[cfg(feature = "std")] use core_simd::Simd;
104-
/// # #[cfg(not(feature = "std"))] use core::simd::Simd;
99+
/// # use core::simd::Simd;
105100
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
106101
/// let xs = Simd::from_array([MIN, MIN +1, -5, 0]);
107102
/// assert_eq!(xs.abs(), Simd::from_array([MIN, MAX, 5, 0]));
@@ -119,8 +114,7 @@ macro_rules! impl_int_arith {
119114
/// # Examples
120115
/// ```
121116
/// # #![feature(portable_simd)]
122-
/// # #[cfg(feature = "std")] use core_simd::Simd;
123-
/// # #[cfg(not(feature = "std"))] use core::simd::Simd;
117+
/// # use core::simd::Simd;
124118
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
125119
/// let xs = Simd::from_array([MIN, -2, 0, 3]);
126120
/// let unsat = xs.abs();
@@ -142,8 +136,7 @@ macro_rules! impl_int_arith {
142136
/// # Examples
143137
/// ```
144138
/// # #![feature(portable_simd)]
145-
/// # #[cfg(feature = "std")] use core_simd::Simd;
146-
/// # #[cfg(not(feature = "std"))] use core::simd::Simd;
139+
/// # use core::simd::Simd;
147140
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
148141
/// let x = Simd::from_array([MIN, -2, 3, MAX]);
149142
/// let unsat = -x;

library/portable-simd/crates/core_simd/src/reduction.rs

+22-22
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,30 @@ macro_rules! impl_integer_reductions {
1111
where
1212
LaneCount<LANES>: SupportedLaneCount,
1313
{
14-
/// Horizontal wrapping add. Returns the sum of the lanes of the vector, with wrapping addition.
14+
/// Reducing wrapping add. Returns the sum of the lanes of the vector, with wrapping addition.
1515
#[inline]
16-
pub fn horizontal_sum(self) -> $scalar {
16+
pub fn reduce_sum(self) -> $scalar {
1717
// Safety: `self` is an integer vector
1818
unsafe { simd_reduce_add_ordered(self, 0) }
1919
}
2020

21-
/// Horizontal wrapping multiply. Returns the product of the lanes of the vector, with wrapping multiplication.
21+
/// Reducing wrapping multiply. Returns the product of the lanes of the vector, with wrapping multiplication.
2222
#[inline]
23-
pub fn horizontal_product(self) -> $scalar {
23+
pub fn reduce_product(self) -> $scalar {
2424
// Safety: `self` is an integer vector
2525
unsafe { simd_reduce_mul_ordered(self, 1) }
2626
}
2727

28-
/// Horizontal maximum. Returns the maximum lane in the vector.
28+
/// Reducing maximum. Returns the maximum lane in the vector.
2929
#[inline]
30-
pub fn horizontal_max(self) -> $scalar {
30+
pub fn reduce_max(self) -> $scalar {
3131
// Safety: `self` is an integer vector
3232
unsafe { simd_reduce_max(self) }
3333
}
3434

35-
/// Horizontal minimum. Returns the minimum lane in the vector.
35+
/// Reducing minimum. Returns the minimum lane in the vector.
3636
#[inline]
37-
pub fn horizontal_min(self) -> $scalar {
37+
pub fn reduce_min(self) -> $scalar {
3838
// Safety: `self` is an integer vector
3939
unsafe { simd_reduce_min(self) }
4040
}
@@ -60,9 +60,9 @@ macro_rules! impl_float_reductions {
6060
LaneCount<LANES>: SupportedLaneCount,
6161
{
6262

63-
/// Horizontal add. Returns the sum of the lanes of the vector.
63+
/// Reducing add. Returns the sum of the lanes of the vector.
6464
#[inline]
65-
pub fn horizontal_sum(self) -> $scalar {
65+
pub fn reduce_sum(self) -> $scalar {
6666
// LLVM sum is inaccurate on i586
6767
if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
6868
self.as_array().iter().sum()
@@ -72,9 +72,9 @@ macro_rules! impl_float_reductions {
7272
}
7373
}
7474

75-
/// Horizontal multiply. Returns the product of the lanes of the vector.
75+
/// Reducing multiply. Returns the product of the lanes of the vector.
7676
#[inline]
77-
pub fn horizontal_product(self) -> $scalar {
77+
pub fn reduce_product(self) -> $scalar {
7878
// LLVM product is inaccurate on i586
7979
if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
8080
self.as_array().iter().product()
@@ -84,22 +84,22 @@ macro_rules! impl_float_reductions {
8484
}
8585
}
8686

87-
/// Horizontal maximum. Returns the maximum lane in the vector.
87+
/// Reducing maximum. Returns the maximum lane in the vector.
8888
///
8989
/// Returns values based on equality, so a vector containing both `0.` and `-0.` may
9090
/// return either. This function will not return `NaN` unless all lanes are `NaN`.
9191
#[inline]
92-
pub fn horizontal_max(self) -> $scalar {
92+
pub fn reduce_max(self) -> $scalar {
9393
// Safety: `self` is a float vector
9494
unsafe { simd_reduce_max(self) }
9595
}
9696

97-
/// Horizontal minimum. Returns the minimum lane in the vector.
97+
/// Reducing minimum. Returns the minimum lane in the vector.
9898
///
9999
/// Returns values based on equality, so a vector containing both `0.` and `-0.` may
100100
/// return either. This function will not return `NaN` unless all lanes are `NaN`.
101101
#[inline]
102-
pub fn horizontal_min(self) -> $scalar {
102+
pub fn reduce_min(self) -> $scalar {
103103
// Safety: `self` is a float vector
104104
unsafe { simd_reduce_min(self) }
105105
}
@@ -116,10 +116,10 @@ where
116116
T: SimdElement + BitAnd<T, Output = T>,
117117
LaneCount<LANES>: SupportedLaneCount,
118118
{
119-
/// Horizontal bitwise "and". Returns the cumulative bitwise "and" across the lanes of
119+
/// Reducing bitwise "and". Returns the cumulative bitwise "and" across the lanes of
120120
/// the vector.
121121
#[inline]
122-
pub fn horizontal_and(self) -> T {
122+
pub fn reduce_and(self) -> T {
123123
unsafe { simd_reduce_and(self) }
124124
}
125125
}
@@ -130,10 +130,10 @@ where
130130
T: SimdElement + BitOr<T, Output = T>,
131131
LaneCount<LANES>: SupportedLaneCount,
132132
{
133-
/// Horizontal bitwise "or". Returns the cumulative bitwise "or" across the lanes of
133+
/// Reducing bitwise "or". Returns the cumulative bitwise "or" across the lanes of
134134
/// the vector.
135135
#[inline]
136-
pub fn horizontal_or(self) -> T {
136+
pub fn reduce_or(self) -> T {
137137
unsafe { simd_reduce_or(self) }
138138
}
139139
}
@@ -144,10 +144,10 @@ where
144144
T: SimdElement + BitXor<T, Output = T>,
145145
LaneCount<LANES>: SupportedLaneCount,
146146
{
147-
/// Horizontal bitwise "xor". Returns the cumulative bitwise "xor" across the lanes of
147+
/// Reducing bitwise "xor". Returns the cumulative bitwise "xor" across the lanes of
148148
/// the vector.
149149
#[inline]
150-
pub fn horizontal_xor(self) -> T {
150+
pub fn reduce_xor(self) -> T {
151151
unsafe { simd_reduce_xor(self) }
152152
}
153153
}

0 commit comments

Comments
 (0)