Skip to content

Commit a991d48

Browse files
Add Simd::cast
1 parent cad7434 commit a991d48

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

crates/core_simd/src/intrinsics.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ extern "platform-intrinsic" {
3939

4040
/// fptoui/fptosi/uitofp/sitofp
4141
pub(crate) fn simd_cast<T, U>(x: T) -> U;
42+
/// follows Rust's `T as U` semantics, including saturating float casts
43+
/// which amounts to the same as `simd_cast` for many cases
44+
pub(crate) fn simd_as<T, U>(x: T) -> U;
4245

4346
/// neg/fneg
4447
pub(crate) fn simd_neg<T>(x: T) -> T;

crates/core_simd/src/vector.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,35 @@ where
7575
Self(array)
7676
}
7777

78+
/// Performs lanewise conversion of a SIMD vector's elements to another SIMD-valid type.
79+
/// This follows the semantics of Rust's `as` conversion for casting
80+
/// integers to unsigned integers (interpreting as the other type, so `-1` to `MAX`),
81+
/// and from floats to integers (truncating, or saturating at the limits) for each lane,
82+
/// or vice versa.
83+
///
84+
/// # Examples
85+
/// ```
86+
/// # #![feature(portable_simd)]
87+
/// # #[cfg(feature = "std")] use core_simd::Simd;
88+
/// # #[cfg(not(feature = "std"))] use core::simd::Simd;
89+
/// let floats: Simd<f32, 4> = Simd::from_array([1.9, -4.5, f32::INFINITY, f32::NAN]);
90+
/// let ints = floats.cast::<i32>();
91+
/// assert_eq!(ints, Simd::from_array([1, -4, i32::MAX, 0]));
92+
///
93+
/// // Formally equivalent, but `Simd::cast` can optimize better.
94+
/// assert_eq!(ints, Simd::from_array(floats.to_array().map(|x| x as i32)));
95+
///
96+
/// // The float conversion does not round-trip.
97+
/// let floats_again = ints.cast();
98+
/// assert_ne!(floats, floats_again);
99+
/// assert_eq!(floats_again, Simd::from_array([1.0, -4.0, 2147483647.0, 0.0]));
100+
/// ```
101+
#[must_use]
102+
#[inline]
103+
pub fn cast<U: SimdElement>(self) -> Simd<U, LANES> {
104+
unsafe { intrinsics::simd_as(self) }
105+
}
106+
78107
/// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
79108
/// If an index is out-of-bounds, the lane is instead selected from the `or` vector.
80109
///

0 commit comments

Comments
 (0)