Skip to content

Commit b90f1f9

Browse files
committed
FIX: Factor out rotate1_front function from remove_index
1 parent 0d5ea84 commit b90f1f9

File tree

2 files changed

+36
-27
lines changed

2 files changed

+36
-27
lines changed

src/impl_1d.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88

99
//! Methods for one-dimensional arrays.
1010
use alloc::vec::Vec;
11+
use std::mem::MaybeUninit;
12+
1113
use crate::imp_prelude::*;
14+
use crate::low_level_util::AbortIfPanic;
1215

1316
/// # Methods For 1-D Arrays
1417
impl<A, S> ArrayBase<S, Ix1>
@@ -27,4 +30,35 @@ where
2730
crate::iterators::to_vec(self.iter().cloned())
2831
}
2932
}
33+
34+
/// Rotate the elements of the array by 1 element towards the front;
35+
/// the former first element becomes the last.
36+
pub(crate) fn rotate1_front(&mut self)
37+
where
38+
S: DataMut,
39+
{
40+
// use swapping to keep all elements initialized (as required by owned storage)
41+
let mut lane_iter = self.iter_mut();
42+
let mut dst = if let Some(dst) = lane_iter.next() { dst } else { return };
43+
44+
// Logically we do a circular swap here, all elements in a chain
45+
// Using MaybeUninit to avoid unecessary writes in the safe swap solution
46+
//
47+
// for elt in lane_iter {
48+
// std::mem::swap(dst, elt);
49+
// dst = elt;
50+
// }
51+
//
52+
let guard = AbortIfPanic(&"rotate1_front: temporarily moving out of owned value");
53+
let mut slot = MaybeUninit::<A>::uninit();
54+
unsafe {
55+
slot.as_mut_ptr().copy_from_nonoverlapping(dst, 1);
56+
for elt in lane_iter {
57+
(dst as *mut A).copy_from_nonoverlapping(elt, 1);
58+
dst = elt;
59+
}
60+
(dst as *mut A).copy_from_nonoverlapping(slot.as_ptr(), 1);
61+
}
62+
guard.defuse();
63+
}
3064
}

src/impl_methods.rs

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9-
use std::mem::{size_of, ManuallyDrop, MaybeUninit};
9+
use std::mem::{size_of, ManuallyDrop};
1010
use alloc::slice;
1111
use alloc::vec;
1212
use alloc::vec::Vec;
@@ -26,7 +26,6 @@ use crate::dimension::broadcast::co_broadcast;
2626
use crate::error::{self, ErrorKind, ShapeError, from_kind};
2727
use crate::math_cell::MathCell;
2828
use crate::itertools::zip;
29-
use crate::low_level_util::AbortIfPanic;
3029
use crate::zip::{IntoNdProducer, Zip};
3130
use crate::AxisDescription;
3231

@@ -2464,31 +2463,7 @@ where
24642463
index, axis.index());
24652464
let (_, mut tail) = self.view_mut().split_at(axis, index);
24662465
// shift elements to the front
2467-
// use swapping to keep all elements initialized (as required by owned storage)
2468-
Zip::from(tail.lanes_mut(axis)).for_each(|mut lane| {
2469-
let mut lane_iter = lane.iter_mut();
2470-
let mut dst = if let Some(dst) = lane_iter.next() { dst } else { return };
2471-
2472-
// Logically we do a circular swap here, all elements in a chain
2473-
// Using MaybeUninit to avoid unecessary writes in the safe swap solution
2474-
//
2475-
// for elt in lane_iter {
2476-
// std::mem::swap(dst, elt);
2477-
// dst = elt;
2478-
// }
2479-
//
2480-
let guard = AbortIfPanic(&"remove_index: temporarily moving out of owned value");
2481-
let mut slot = MaybeUninit::<A>::uninit();
2482-
unsafe {
2483-
slot.as_mut_ptr().copy_from_nonoverlapping(dst, 1);
2484-
for elt in lane_iter {
2485-
(dst as *mut A).copy_from_nonoverlapping(elt, 1);
2486-
dst = elt;
2487-
}
2488-
(dst as *mut A).copy_from_nonoverlapping(slot.as_ptr(), 1);
2489-
}
2490-
guard.defuse();
2491-
});
2466+
Zip::from(tail.lanes_mut(axis)).for_each(|mut lane| lane.rotate1_front());
24922467
// then slice the axis in place to cut out the removed final element
24932468
self.slice_axis_inplace(axis, Slice::new(0, Some(-1), 1));
24942469
}

0 commit comments

Comments
 (0)