|
9 | 9 | use alloc::vec; |
10 | 10 | use alloc::vec::Vec; |
11 | 11 | use std::mem::{forget, size_of}; |
| 12 | +use std::ptr::NonNull; |
12 | 13 |
|
13 | 14 | use crate::imp_prelude::*; |
14 | 15 | use crate::{dimension, ArcArray1, ArcArray2}; |
@@ -64,32 +65,105 @@ pub fn rcarr1<A: Clone>(xs: &[A]) -> ArcArray1<A> { |
64 | 65 | } |
65 | 66 |
|
66 | 67 | /// 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 | + } |
69 | 76 | } |
70 | 77 |
|
71 | 78 | /// Create a one-dimensional array view with elements borrowing `xs`. |
72 | 79 | /// |
| 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 | +/// |
73 | 84 | /// ``` |
74 | | -/// use ndarray::aview1; |
| 85 | +/// use ndarray::{aview1, ArrayView1}; |
75 | 86 | /// |
76 | 87 | /// let data = [1.0; 1024]; |
77 | 88 | /// |
78 | 89 | /// // Create a 2D array view from borrowed data |
79 | 90 | /// let a2d = aview1(&data).into_shape((32, 32)).unwrap(); |
80 | 91 | /// |
81 | 92 | /// 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.); |
82 | 98 | /// ``` |
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 | + } |
85 | 113 | } |
86 | 114 |
|
87 | 115 | /// Create a two-dimensional array view with elements borrowing `xs`. |
88 | 116 | /// |
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 | + } |
93 | 167 | } |
94 | 168 |
|
95 | 169 | /// Create a one-dimensional read-write array view with elements borrowing `xs`. |
|
0 commit comments