Skip to content

Commit 1b45140

Browse files
committed
FIX: Update stack/concatenate to use maybe_uninit
1 parent de1b903 commit 1b45140

File tree

3 files changed

+52
-24
lines changed

3 files changed

+52
-24
lines changed

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2014-2016 bluss and ndarray developers.
1+
// Copyright 2014-2020 bluss and ndarray developers.
22
//
33
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
44
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
@@ -187,6 +187,7 @@ mod shape_builder;
187187
mod slice;
188188
mod split_at;
189189
mod stacking;
190+
mod traversal_utils;
190191
#[macro_use]
191192
mod zip;
192193

src/stacking.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2014-2016 bluss and ndarray developers.
1+
// Copyright 2014-2020 bluss and ndarray developers.
22
//
33
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
44
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
@@ -8,6 +8,7 @@
88

99
use crate::error::{from_kind, ErrorKind, ShapeError};
1010
use crate::imp_prelude::*;
11+
use crate::traversal_utils::assign_to;
1112

1213
/// Stack arrays along the new axis.
1314
///
@@ -88,25 +89,23 @@ where
8889
let stacked_dim = arrays.iter().fold(0, |acc, a| acc + a.len_of(axis));
8990
res_dim.set_axis(axis, stacked_dim);
9091

91-
// we can safely use uninitialized values here because they are Copy
92-
// and we will only ever write to them
93-
let size = res_dim.size();
94-
let mut v = Vec::with_capacity(size);
95-
unsafe {
96-
v.set_len(size);
97-
}
98-
let mut res = Array::from_shape_vec(res_dim, v)?;
92+
// we can safely use uninitialized values here because we will
93+
// overwrite every one of them.
94+
let mut res = Array::maybe_uninit(res_dim);
9995

10096
{
10197
let mut assign_view = res.view_mut();
10298
for array in arrays {
10399
let len = array.len_of(axis);
104-
let (mut front, rest) = assign_view.split_at(axis, len);
105-
front.assign(array);
100+
let (front, rest) = assign_view.split_at(axis, len);
101+
assign_to(array, front);
106102
assign_view = rest;
107103
}
104+
debug_assert_eq!(assign_view.len(), 0);
105+
}
106+
unsafe {
107+
Ok(res.assume_init())
108108
}
109-
Ok(res)
110109
}
111110

112111
/// Stack arrays along the new axis.
@@ -158,22 +157,24 @@ where
158157

159158
res_dim.set_axis(axis, arrays.len());
160159

161-
// we can safely use uninitialized values here because they are Copy
162-
// and we will only ever write to them
163-
let size = res_dim.size();
164-
let mut v = Vec::with_capacity(size);
165-
unsafe {
166-
v.set_len(size);
167-
}
168-
let mut res = Array::from_shape_vec(res_dim, v)?;
160+
// we can safely use uninitialized values here because we will
161+
// overwrite every one of them.
162+
let mut res = Array::maybe_uninit(res_dim);
169163

170164
res.axis_iter_mut(axis)
171165
.zip(arrays.iter())
172-
.for_each(|(mut assign_view, array)| {
173-
assign_view.assign(&array);
166+
.for_each(|(assign_view, array)| {
167+
// assign_view is D::Larger::Smaller which is usually == D
168+
// (but if D is Ix6, we have IxD != Ix6 here; differing types
169+
// but same number of axes).
170+
let assign_view = assign_view.into_dimensionality::<D>()
171+
.expect("same-dimensionality cast");
172+
assign_to(array, assign_view);
174173
});
175174

176-
Ok(res)
175+
unsafe {
176+
Ok(res.assume_init())
177+
}
177178
}
178179

179180
/// Stack arrays along the new axis.

src/traversal_utils.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2020 bluss and ndarray developers.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
use crate::{
10+
IntoNdProducer,
11+
AssignElem,
12+
Zip,
13+
};
14+
15+
/// Assign values from producer P1 to producer P2
16+
/// P1 and P2 must be of the same shape and dimension
17+
pub(crate) fn assign_to<'a, P1, P2, A>(from: P1, to: P2)
18+
where P1: IntoNdProducer<Item = &'a A>,
19+
P2: IntoNdProducer<Dim = P1::Dim>,
20+
P2::Item: AssignElem<A>,
21+
A: Clone + 'a
22+
{
23+
Zip::from(from)
24+
.apply_assign_into(to, A::clone);
25+
}
26+

0 commit comments

Comments
 (0)