Skip to content

Commit 3017dc5

Browse files
committed
Make aview* free functions be const fns
1 parent 102033d commit 3017dc5

File tree

1 file changed

+83
-9
lines changed

1 file changed

+83
-9
lines changed

src/free_functions.rs

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use alloc::vec;
1010
use alloc::vec::Vec;
1111
use std::mem::{forget, size_of};
12+
use std::ptr::NonNull;
1213

1314
use crate::imp_prelude::*;
1415
use crate::{dimension, ArcArray1, ArcArray2};
@@ -64,32 +65,105 @@ pub fn rcarr1<A: Clone>(xs: &[A]) -> ArcArray1<A> {
6465
}
6566

6667
/// Create a zero-dimensional array view borrowing `x`.
67-
pub fn aview0<A>(x: &A) -> ArrayView0<'_, A> {
68-
unsafe { ArrayView::from_shape_ptr(Ix0(), x) }
68+
pub const fn aview0<A>(x: &A) -> ArrayView0<'_, A> {
69+
ArrayBase {
70+
data: ViewRepr::new(),
71+
// Safe because references are always non-null.
72+
ptr: unsafe { NonNull::new_unchecked(x as *const A as *mut A) },
73+
dim: Ix0(),
74+
strides: Ix0(),
75+
}
6976
}
7077

7178
/// Create a one-dimensional array view with elements borrowing `xs`.
7279
///
80+
/// **Panics** if the length of the slice overflows `isize`. (This can only
81+
/// occur if `A` is zero-sized, because slices cannot contain more than
82+
/// `isize::MAX` number of bytes.)
83+
///
7384
/// ```
74-
/// use ndarray::aview1;
85+
/// use ndarray::{aview1, ArrayView1};
7586
///
7687
/// let data = [1.0; 1024];
7788
///
7889
/// // Create a 2D array view from borrowed data
7990
/// let a2d = aview1(&data).into_shape((32, 32)).unwrap();
8091
///
8192
/// assert_eq!(a2d.sum(), 1024.0);
93+
///
94+
/// // Create a const 1D array view
95+
/// const C: ArrayView1<'static, f64> = aview1(&[1., 2., 3.]);
96+
///
97+
/// assert_eq!(C.sum(), 6.);
8298
/// ```
83-
pub fn aview1<A>(xs: &[A]) -> ArrayView1<'_, A> {
84-
ArrayView::from(xs)
99+
pub const fn aview1<A>(xs: &[A]) -> ArrayView1<'_, A> {
100+
if size_of::<A>() == 0 {
101+
assert!(
102+
xs.len() <= isize::MAX as usize,
103+
"Slice length must fit in `isize`.",
104+
);
105+
}
106+
ArrayBase {
107+
data: ViewRepr::new(),
108+
// Safe because references are always non-null.
109+
ptr: unsafe { NonNull::new_unchecked(xs.as_ptr() as *mut A) },
110+
dim: Ix1(xs.len()),
111+
strides: Ix1(1),
112+
}
85113
}
86114

87115
/// Create a two-dimensional array view with elements borrowing `xs`.
88116
///
89-
/// **Panics** if the product of non-zero axis lengths overflows `isize` (This can only occur if A
90-
/// is zero-sized because slices cannot contain more than `isize::MAX` number of bytes).
91-
pub fn aview2<A, const N: usize>(xs: &[[A; N]]) -> ArrayView2<'_, A> {
92-
ArrayView2::from(xs)
117+
/// **Panics** if the product of non-zero axis lengths overflows `isize` (This
118+
/// can only occur if A is zero-sized or if `N` is zero, because slices cannot
119+
/// contain more than `isize::MAX` number of bytes).
120+
///
121+
/// ```
122+
/// use ndarray::{aview2, ArrayView2};
123+
///
124+
/// let data = vec![[1., 2., 3.], [4., 5., 6.]];
125+
///
126+
/// let view = aview2(&data);
127+
/// assert_eq!(view.sum(), 21.);
128+
///
129+
/// // Create a const 2D array view
130+
/// const C: ArrayView2<'static, f64> = aview2(&[[1., 2., 3.], [4., 5., 6.]]);
131+
/// assert_eq!(C.sum(), 21.);
132+
/// ```
133+
pub const fn aview2<A, const N: usize>(xs: &[[A; N]]) -> ArrayView2<'_, A> {
134+
let cols = N;
135+
let rows = xs.len();
136+
if size_of::<A>() == 0 {
137+
if let Some(n_elems) = rows.checked_mul(cols) {
138+
assert!(
139+
rows <= isize::MAX as usize
140+
&& cols <= isize::MAX as usize
141+
&& n_elems <= isize::MAX as usize,
142+
"Product of non-zero axis lengths must not overflow isize.",
143+
);
144+
} else {
145+
panic!("Overflow in number of elements.");
146+
}
147+
} else if N == 0 {
148+
assert!(
149+
rows <= isize::MAX as usize,
150+
"Product of non-zero axis lengths must not overflow isize.",
151+
);
152+
}
153+
// Safe because references are always non-null.
154+
let ptr = unsafe { NonNull::new_unchecked(xs.as_ptr() as *mut A) };
155+
let dim = Ix2(rows, cols);
156+
let strides = if rows == 0 || cols == 0 {
157+
Ix2(0, 0)
158+
} else {
159+
Ix2(cols, 1)
160+
};
161+
ArrayBase {
162+
data: ViewRepr::new(),
163+
ptr,
164+
dim,
165+
strides,
166+
}
93167
}
94168

95169
/// Create a one-dimensional read-write array view with elements borrowing `xs`.

0 commit comments

Comments
 (0)