-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add [T]::as_simd(_mut)
#91479
Add [T]::as_simd(_mut)
#91479
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -16,6 +16,8 @@ use crate::option::Option::{None, Some}; | |||||
use crate::ptr; | ||||||
use crate::result::Result; | ||||||
use crate::result::Result::{Err, Ok}; | ||||||
#[cfg(not(miri))] // Miri does not support all SIMD intrinsics | ||||||
use crate::simd::{self, Simd}; | ||||||
use crate::slice; | ||||||
|
||||||
#[unstable( | ||||||
|
@@ -3434,6 +3436,87 @@ impl<T> [T] { | |||||
} | ||||||
} | ||||||
|
||||||
/// Split a slice into a prefix, a middle of aligned simd types, and a suffix. | ||||||
/// | ||||||
/// This is a safe wrapper around [`slice::align_to`], so has the same weak | ||||||
/// preconditions as that method. Notably, you must not assume any particular | ||||||
/// split between the three parts: it's legal for the middle slice to be | ||||||
/// empty even if the input slice is longer than `3 * LANES`. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this wrapper is safe, this should clarify that this is an invalid assumption for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I wrote "preconditions" here when I meant "postconditions" 🤦 |
||||||
/// | ||||||
/// # Examples | ||||||
/// | ||||||
/// ``` | ||||||
/// #![feature(portable_simd)] | ||||||
/// | ||||||
/// let short = &[1, 2, 3]; | ||||||
/// let (prefix, middle, suffix) = short.as_simd::<4>(); | ||||||
/// assert_eq!(middle, []); // Not enough elements for anything in the middle | ||||||
/// | ||||||
/// // They might be split in any possible way between prefix and suffix | ||||||
/// let it = prefix.iter().chain(suffix).copied(); | ||||||
/// assert_eq!(it.collect::<Vec<_>>(), vec![1, 2, 3]); | ||||||
/// | ||||||
/// fn basic_simd_sum(x: &[f32]) -> f32 { | ||||||
/// use std::ops::Add; | ||||||
/// use std::simd::f32x4; | ||||||
/// let (prefix, middle, suffix) = x.as_simd(); | ||||||
/// let sums = f32x4::from_array([ | ||||||
/// prefix.iter().copied().sum(), | ||||||
/// 0.0, | ||||||
/// 0.0, | ||||||
/// suffix.iter().copied().sum(), | ||||||
/// ]); | ||||||
/// let sums = middle.iter().copied().fold(sums, f32x4::add); | ||||||
/// sums.horizontal_sum() | ||||||
/// } | ||||||
/// | ||||||
/// let numbers: Vec<f32> = (1..101).map(|x| x as _).collect(); | ||||||
/// assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0); | ||||||
/// ``` | ||||||
#[unstable(feature = "portable_simd", issue = "86656")] | ||||||
#[cfg(not(miri))] // Miri does not support all SIMD intrinsics | ||||||
pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T]) | ||||||
where | ||||||
Simd<T, LANES>: AsRef<[T; LANES]>, | ||||||
T: simd::SimdElement, | ||||||
simd::LaneCount<LANES>: simd::SupportedLaneCount, | ||||||
{ | ||||||
// These are expected to always match, as vector types are laid out like | ||||||
// arrays per <https://llvm.org/docs/LangRef.html#vector-type>, but we | ||||||
// might as well double-check since it'll optimize away anyhow. | ||||||
assert_eq!(mem::size_of::<Simd<T, LANES>>(), mem::size_of::<[T; LANES]>()); | ||||||
|
||||||
// SAFETY: The simd types have the same layout as arrays, just with | ||||||
// potentially-higher alignment, so the de-facto transmutes are sound. | ||||||
unsafe { self.align_to() } | ||||||
Comment on lines
+3507
to
+3509
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sound, yes, but it would likely exhibit unexpected behavior if
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well I guess my The other possibility would be to have it just return everything in the prefix for that case, since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't consider that, but it is indeed also an option! |
||||||
} | ||||||
|
||||||
/// Split a slice into a prefix, a middle of aligned simd types, and a suffix. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
/// | ||||||
/// This is a safe wrapper around [`slice::align_to`], so has the same weak | ||||||
/// preconditions as that method. Notably, you must not assume any particular | ||||||
/// split between the three parts: it's legal for the middle slice to be | ||||||
/// empty even if the input slice is longer than `3 * LANES`. | ||||||
/// | ||||||
/// This is the mutable version of [`slice::as_simd`]; see that for more. | ||||||
#[unstable(feature = "portable_simd", issue = "86656")] | ||||||
#[cfg(not(miri))] // Miri does not support all SIMD intrinsics | ||||||
pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LANES>], &mut [T]) | ||||||
where | ||||||
Simd<T, LANES>: AsMut<[T; LANES]>, | ||||||
T: simd::SimdElement, | ||||||
simd::LaneCount<LANES>: simd::SupportedLaneCount, | ||||||
{ | ||||||
// These are expected to always match, as vector types are laid out like | ||||||
// arrays per <https://llvm.org/docs/LangRef.html#vector-type>, but we | ||||||
// might as well double-check since it'll optimize away anyhow. | ||||||
assert_eq!(mem::size_of::<Simd<T, LANES>>(), mem::size_of::<[T; LANES]>()); | ||||||
|
||||||
// SAFETY: The simd types have the same layout as arrays, just with | ||||||
// potentially-higher alignment, so the de-facto transmutes are sound. | ||||||
unsafe { self.align_to_mut() } | ||||||
} | ||||||
|
||||||
/// Checks if the elements of this slice are sorted. | ||||||
/// | ||||||
/// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.