1
1
use crate :: simd:: {
2
- intrinsics, LaneCount , Mask , MaskElement , SimdCast , SimdCastPtr , SimdConstPtr , SimdMutPtr ,
3
- SimdPartialOrd , SupportedLaneCount , Swizzle ,
2
+ intrinsics, LaneCount , Mask , MaskElement , SimdConstPtr , SimdMutPtr , SimdPartialOrd ,
3
+ SupportedLaneCount , Swizzle ,
4
4
} ;
5
5
use core:: convert:: { TryFrom , TryInto } ;
6
6
@@ -122,6 +122,7 @@ where
122
122
/// let v = u32x4::splat(0);
123
123
/// assert_eq!(v.lanes(), 4);
124
124
/// ```
125
+ #[ inline]
125
126
pub const fn lanes ( & self ) -> usize {
126
127
Self :: LANES
127
128
}
@@ -136,6 +137,7 @@ where
136
137
/// let v = u32x4::splat(8);
137
138
/// assert_eq!(v.as_array(), &[8, 8, 8, 8]);
138
139
/// ```
140
+ #[ inline]
139
141
pub fn splat ( value : T ) -> Self {
140
142
// This is preferred over `[value; N]`, since it's explicitly a splat:
141
143
// https://github.com/rust-lang/rust/issues/97804
@@ -156,6 +158,7 @@ where
156
158
/// let v: u64x4 = Simd::from_array([0, 1, 2, 3]);
157
159
/// assert_eq!(v.as_array(), &[0, 1, 2, 3]);
158
160
/// ```
161
+ #[ inline]
159
162
pub const fn as_array ( & self ) -> & [ T ; N ] {
160
163
// SAFETY: `Simd<T, N>` is just an overaligned `[T; N]` with
161
164
// potential padding at the end, so pointer casting to a
@@ -167,6 +170,7 @@ where
167
170
}
168
171
169
172
/// Returns a mutable array reference containing the entire SIMD vector.
173
+ #[ inline]
170
174
pub fn as_mut_array ( & mut self ) -> & mut [ T ; N ] {
171
175
// SAFETY: `Simd<T, N>` is just an overaligned `[T; N]` with
172
176
// potential padding at the end, so pointer casting to a
@@ -184,6 +188,7 @@ where
184
188
///
185
189
/// # Safety
186
190
/// Reading `ptr` must be safe, as if by `<*const [T; N]>::read_unaligned`.
191
+ #[ inline]
187
192
const unsafe fn load ( ptr : * const [ T ; N ] ) -> Self {
188
193
// There are potentially simpler ways to write this function, but this should result in
189
194
// LLVM `load <N x T>`
@@ -204,6 +209,7 @@ where
204
209
///
205
210
/// # Safety
206
211
/// Writing to `ptr` must be safe, as if by `<*mut [T; N]>::write_unaligned`.
212
+ #[ inline]
207
213
const unsafe fn store ( self , ptr : * mut [ T ; N ] ) {
208
214
// There are potentially simpler ways to write this function, but this should result in
209
215
// LLVM `store <N x T>`
@@ -216,6 +222,7 @@ where
216
222
}
217
223
218
224
/// Converts an array to a SIMD vector.
225
+ #[ inline]
219
226
pub const fn from_array ( array : [ T ; N ] ) -> Self {
220
227
// SAFETY: `&array` is safe to read.
221
228
//
@@ -228,6 +235,7 @@ where
228
235
}
229
236
230
237
/// Converts a SIMD vector to an array.
238
+ #[ inline]
231
239
pub const fn to_array ( self ) -> [ T ; N ] {
232
240
let mut tmp = core:: mem:: MaybeUninit :: uninit ( ) ;
233
241
// SAFETY: writing to `tmp` is safe and initializes it.
@@ -259,6 +267,8 @@ where
259
267
/// assert_eq!(v.as_array(), &[1, 2, 3, 4]);
260
268
/// ```
261
269
#[ must_use]
270
+ #[ inline]
271
+ #[ track_caller]
262
272
pub const fn from_slice ( slice : & [ T ] ) -> Self {
263
273
assert ! (
264
274
slice. len( ) >= Self :: LANES ,
@@ -287,6 +297,8 @@ where
287
297
/// v.copy_to_slice(&mut dest);
288
298
/// assert_eq!(&dest, &[1, 2, 3, 4, 0, 0]);
289
299
/// ```
300
+ #[ inline]
301
+ #[ track_caller]
290
302
pub fn copy_to_slice ( self , slice : & mut [ T ] ) {
291
303
assert ! (
292
304
slice. len( ) >= Self :: LANES ,
@@ -297,76 +309,6 @@ where
297
309
unsafe { self . store ( slice. as_mut_ptr ( ) . cast ( ) ) }
298
310
}
299
311
300
- /// Performs elementwise conversion of a SIMD vector's elements to another SIMD-valid type.
301
- ///
302
- /// This follows the semantics of Rust's `as` conversion for casting integers between
303
- /// signed and unsigned (interpreting integers as 2s complement, so `-1` to `U::MAX` and
304
- /// `1 << (U::BITS -1)` becoming `I::MIN` ), and from floats to integers (truncating,
305
- /// or saturating at the limits) for each element.
306
- ///
307
- /// # Examples
308
- /// ```
309
- /// # #![feature(portable_simd)]
310
- /// # use core::simd::Simd;
311
- /// let floats: Simd<f32, 4> = Simd::from_array([1.9, -4.5, f32::INFINITY, f32::NAN]);
312
- /// let ints = floats.cast::<i32>();
313
- /// assert_eq!(ints, Simd::from_array([1, -4, i32::MAX, 0]));
314
- ///
315
- /// // Formally equivalent, but `Simd::cast` can optimize better.
316
- /// assert_eq!(ints, Simd::from_array(floats.to_array().map(|x| x as i32)));
317
- ///
318
- /// // The float conversion does not round-trip.
319
- /// let floats_again = ints.cast();
320
- /// assert_ne!(floats, floats_again);
321
- /// assert_eq!(floats_again, Simd::from_array([1.0, -4.0, 2147483647.0, 0.0]));
322
- /// ```
323
- #[ must_use]
324
- #[ inline]
325
- pub fn cast < U : SimdCast > ( self ) -> Simd < U , N >
326
- where
327
- T : SimdCast ,
328
- {
329
- // Safety: supported types are guaranteed by SimdCast
330
- unsafe { intrinsics:: simd_as ( self ) }
331
- }
332
-
333
- /// Casts a vector of pointers to another pointer type.
334
- #[ must_use]
335
- #[ inline]
336
- pub fn cast_ptr < U > ( self ) -> Simd < U , N >
337
- where
338
- T : SimdCastPtr < U > ,
339
- U : SimdElement ,
340
- {
341
- // Safety: supported types are guaranteed by SimdCastPtr
342
- unsafe { intrinsics:: simd_cast_ptr ( self ) }
343
- }
344
-
345
- /// Rounds toward zero and converts to the same-width integer type, assuming that
346
- /// the value is finite and fits in that type.
347
- ///
348
- /// # Safety
349
- /// The value must:
350
- ///
351
- /// * Not be NaN
352
- /// * Not be infinite
353
- /// * Be representable in the return type, after truncating off its fractional part
354
- ///
355
- /// If these requirements are infeasible or costly, consider using the safe function [cast],
356
- /// which saturates on conversion.
357
- ///
358
- /// [cast]: Simd::cast
359
- #[ inline]
360
- #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
361
- pub unsafe fn to_int_unchecked < I > ( self ) -> Simd < I , N >
362
- where
363
- T : core:: convert:: FloatToInt < I > + SimdCast ,
364
- I : SimdCast ,
365
- {
366
- // Safety: supported types are guaranteed by SimdCast, the caller is responsible for the extra invariants
367
- unsafe { intrinsics:: simd_cast ( self ) }
368
- }
369
-
370
312
/// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
371
313
/// If an index is out-of-bounds, the element is instead selected from the `or` vector.
372
314
///
@@ -717,6 +659,7 @@ where
717
659
LaneCount < N > : SupportedLaneCount ,
718
660
T : SimdElement ,
719
661
{
662
+ #[ inline]
720
663
fn clone ( & self ) -> Self {
721
664
* self
722
665
}
@@ -861,6 +804,7 @@ where
861
804
LaneCount < N > : SupportedLaneCount ,
862
805
T : SimdElement ,
863
806
{
807
+ #[ inline]
864
808
fn from ( array : [ T ; N ] ) -> Self {
865
809
Self :: from_array ( array)
866
810
}
@@ -871,6 +815,7 @@ where
871
815
LaneCount < N > : SupportedLaneCount ,
872
816
T : SimdElement ,
873
817
{
818
+ #[ inline]
874
819
fn from ( vector : Simd < T , N > ) -> Self {
875
820
vector. to_array ( )
876
821
}
@@ -883,6 +828,7 @@ where
883
828
{
884
829
type Error = core:: array:: TryFromSliceError ;
885
830
831
+ #[ inline]
886
832
fn try_from ( slice : & [ T ] ) -> Result < Self , core:: array:: TryFromSliceError > {
887
833
Ok ( Self :: from_array ( slice. try_into ( ) ?) )
888
834
}
@@ -895,6 +841,7 @@ where
895
841
{
896
842
type Error = core:: array:: TryFromSliceError ;
897
843
844
+ #[ inline]
898
845
fn try_from ( slice : & mut [ T ] ) -> Result < Self , core:: array:: TryFromSliceError > {
899
846
Ok ( Self :: from_array ( slice. try_into ( ) ?) )
900
847
}
0 commit comments