@@ -265,16 +265,13 @@ where
265
265
266
266
/// Interleave two vectors.
267
267
///
268
- /// Produces two vectors with lanes taken alternately from `self` and `other`.
268
+ /// The resulting vectors contain lanes taken alternatively from `self` and `other`, first
269
+ /// filling the first result, and then the second.
269
270
///
270
- /// The first result contains the first `LANES / 2` lanes from `self` and `other`,
271
- /// alternating, starting with the first lane of `self`.
272
- ///
273
- /// The second result contains the last `LANES / 2` lanes from `self` and `other`,
274
- /// alternating, starting with the lane `LANES / 2` from the start of `self`.
271
+ /// The reverse of this operation is [`Simd::deinterleave`].
275
272
///
276
273
/// ```
277
- /// #![feature(portable_simd)]
274
+ /// # # ![feature(portable_simd)]
278
275
/// # use core::simd::Simd;
279
276
/// let a = Simd::from_array([0, 1, 2, 3]);
280
277
/// let b = Simd::from_array([4, 5, 6, 7]);
@@ -285,29 +282,17 @@ where
285
282
#[ inline]
286
283
#[ must_use = "method returns a new vector and does not mutate the original inputs" ]
287
284
pub fn interleave ( self , other : Self ) -> ( Self , Self ) {
288
- const fn lo < const LANES : usize > ( ) -> [ Which ; LANES ] {
289
- let mut idx = [ Which :: First ( 0 ) ; LANES ] ;
290
- let mut i = 0 ;
291
- while i < LANES {
292
- let offset = i / 2 ;
293
- idx[ i] = if i % 2 == 0 {
294
- Which :: First ( offset)
295
- } else {
296
- Which :: Second ( offset)
297
- } ;
298
- i += 1 ;
299
- }
300
- idx
301
- }
302
- const fn hi < const LANES : usize > ( ) -> [ Which ; LANES ] {
285
+ const fn interleave < const LANES : usize > ( high : bool ) -> [ Which ; LANES ] {
303
286
let mut idx = [ Which :: First ( 0 ) ; LANES ] ;
304
287
let mut i = 0 ;
305
288
while i < LANES {
306
- let offset = ( LANES + i) / 2 ;
307
- idx[ i] = if i % 2 == 0 {
308
- Which :: First ( offset)
289
+ // Treat the source as a concatenated vector
290
+ let dst_index = if high { i + LANES } else { i } ;
291
+ let src_index = dst_index / 2 + ( dst_index % 2 ) * LANES ;
292
+ idx[ i] = if src_index < LANES {
293
+ Which :: First ( src_index)
309
294
} else {
310
- Which :: Second ( offset )
295
+ Which :: Second ( src_index % LANES )
311
296
} ;
312
297
i += 1 ;
313
298
}
@@ -318,11 +303,11 @@ where
318
303
struct Hi ;
319
304
320
305
impl < const LANES : usize > Swizzle2 < LANES , LANES > for Lo {
321
- const INDEX : [ Which ; LANES ] = lo :: < LANES > ( ) ;
306
+ const INDEX : [ Which ; LANES ] = interleave :: < LANES > ( false ) ;
322
307
}
323
308
324
309
impl < const LANES : usize > Swizzle2 < LANES , LANES > for Hi {
325
- const INDEX : [ Which ; LANES ] = hi :: < LANES > ( ) ;
310
+ const INDEX : [ Which ; LANES ] = interleave :: < LANES > ( true ) ;
326
311
}
327
312
328
313
( Lo :: swizzle2 ( self , other) , Hi :: swizzle2 ( self , other) )
@@ -336,8 +321,10 @@ where
336
321
/// The second result takes every other lane of `self` and then `other`, starting with
337
322
/// the second lane.
338
323
///
324
+ /// The reverse of this operation is [`Simd::interleave`].
325
+ ///
339
326
/// ```
340
- /// #![feature(portable_simd)]
327
+ /// # # ![feature(portable_simd)]
341
328
/// # use core::simd::Simd;
342
329
/// let a = Simd::from_array([0, 4, 1, 5]);
343
330
/// let b = Simd::from_array([2, 6, 3, 7]);
@@ -348,22 +335,17 @@ where
348
335
#[ inline]
349
336
#[ must_use = "method returns a new vector and does not mutate the original inputs" ]
350
337
pub fn deinterleave ( self , other : Self ) -> ( Self , Self ) {
351
- const fn even < const LANES : usize > ( ) -> [ Which ; LANES ] {
352
- let mut idx = [ Which :: First ( 0 ) ; LANES ] ;
353
- let mut i = 0 ;
354
- while i < LANES / 2 {
355
- idx[ i] = Which :: First ( 2 * i) ;
356
- idx[ i + LANES / 2 ] = Which :: Second ( 2 * i) ;
357
- i += 1 ;
358
- }
359
- idx
360
- }
361
- const fn odd < const LANES : usize > ( ) -> [ Which ; LANES ] {
338
+ const fn deinterleave < const LANES : usize > ( second : bool ) -> [ Which ; LANES ] {
362
339
let mut idx = [ Which :: First ( 0 ) ; LANES ] ;
363
340
let mut i = 0 ;
364
- while i < LANES / 2 {
365
- idx[ i] = Which :: First ( 2 * i + 1 ) ;
366
- idx[ i + LANES / 2 ] = Which :: Second ( 2 * i + 1 ) ;
341
+ while i < LANES {
342
+ // Treat the source as a concatenated vector
343
+ let src_index = i * 2 + second as usize ;
344
+ idx[ i] = if src_index < LANES {
345
+ Which :: First ( src_index)
346
+ } else {
347
+ Which :: Second ( src_index % LANES )
348
+ } ;
367
349
i += 1 ;
368
350
}
369
351
idx
@@ -373,11 +355,11 @@ where
373
355
struct Odd ;
374
356
375
357
impl < const LANES : usize > Swizzle2 < LANES , LANES > for Even {
376
- const INDEX : [ Which ; LANES ] = even :: < LANES > ( ) ;
358
+ const INDEX : [ Which ; LANES ] = deinterleave :: < LANES > ( false ) ;
377
359
}
378
360
379
361
impl < const LANES : usize > Swizzle2 < LANES , LANES > for Odd {
380
- const INDEX : [ Which ; LANES ] = odd :: < LANES > ( ) ;
362
+ const INDEX : [ Which ; LANES ] = deinterleave :: < LANES > ( true ) ;
381
363
}
382
364
383
365
( Even :: swizzle2 ( self , other) , Odd :: swizzle2 ( self , other) )
0 commit comments