Skip to content

Commit 28e887e

Browse files
committed
Impl a lifetime-relaxed broadcast for ArrayView
ArrayView::broadcast has a lifetime that depends on &self instead of its internal buffer. This prevents writing some types of functions in an allocation-free way. For instance, take the numpy `meshgrid` function: It could be implemented like so: ```rust fn meshgrid_2d<'a, 'b>(coords_x: ArrayView1<'a, X>, coords_y: ArrayView1<'b, X>) -> (ArrayView2<'a, X>, ArrayView2<'b, X>) { let x_len = coords_x.shape()[0]; let y_len = coords_y.shape()[0]; let coords_x_s = coords_x.into_shape((1, y_len)).unwrap(); let coords_x_b = coords_x_s.broadcast((x_len, y_len)).unwrap(); let coords_y_s = coords_y.into_shape((x_len, 1)).unwrap(); let coords_y_b = coords_y_s.broadcast((x_len, y_len)).unwrap(); (coords_x_b, coords_y_b) } ``` Unfortunately, this doesn't work, because `coords_x_b` is bound to the lifetime of `coord_x_s`, instead of being bound to 'a. This commit introduces a new function, broadcast_ref, that does just that.
1 parent e797a77 commit 28e887e

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

src/impl_views/methods.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2014-2016 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::imp_prelude::*;
10+
use crate::dimension::IntoDimension;
11+
use crate::dimension::broadcast::upcast;
12+
13+
impl<'a, A, D> ArrayView<'a, A, D>
14+
where
15+
D: Dimension,
16+
{
17+
/// Broadcasts an `ArrayView`. See [`ArrayBase::broadcast`].
18+
///
19+
/// This is a specialized version of [`ArrayBase::broadcast`] that transfers
20+
/// the view's lifetime to the output.
21+
pub fn broadcast_ref<E>(&self, dim: E) -> Option<ArrayView<'a, A, E::Dim>>
22+
where
23+
E: IntoDimension,
24+
{
25+
let dim = dim.into_dimension();
26+
27+
// Note: zero strides are safe precisely because we return an read-only view
28+
let broadcast_strides = match upcast(&dim, &self.dim, &self.strides) {
29+
Some(st) => st,
30+
None => return None,
31+
};
32+
unsafe { Some(ArrayView::new(self.ptr, dim, broadcast_strides)) }
33+
}
34+
}

src/impl_views/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod constructors;
22
mod conversions;
33
mod indexing;
4+
mod methods;
45
mod splitting;
56

67
pub use constructors::*;

0 commit comments

Comments
 (0)