Skip to content

Commit 6c8b821

Browse files
authored
Merge pull request #980 from YuhanLiin/const-generics
Const generics Improvements
2 parents d1bb045 + 75a27e5 commit 6c8b821

File tree

6 files changed

+162
-169
lines changed

6 files changed

+162
-169
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- stable
2222
- beta
2323
- nightly
24-
- 1.49.0 # MSRV
24+
- 1.51.0 # MSRV
2525

2626
steps:
2727
- uses: actions/checkout@v2

src/arraytraits.rs

+57-9
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,20 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9-
use std::hash;
10-
use std::iter::FromIterator;
9+
use alloc::boxed::Box;
10+
use alloc::vec::Vec;
1111
use std::iter::IntoIterator;
1212
use std::mem;
1313
use std::ops::{Index, IndexMut};
14-
use alloc::boxed::Box;
15-
use alloc::vec::Vec;
14+
use std::{hash, mem::size_of};
15+
use std::{iter::FromIterator, slice};
1616

1717
use crate::imp_prelude::*;
18-
use crate::iter::{Iter, IterMut};
19-
use crate::NdIndex;
20-
21-
use crate::numeric_util;
22-
use crate::{FoldWhile, Zip};
18+
use crate::{
19+
dimension,
20+
iter::{Iter, IterMut},
21+
numeric_util, FoldWhile, NdIndex, Zip,
22+
};
2323

2424
#[cold]
2525
#[inline(never)]
@@ -323,6 +323,30 @@ where
323323
}
324324
}
325325

326+
/// Implementation of ArrayView2::from(&S) where S is a slice to a 2D array
327+
///
328+
/// **Panics** if the product of non-zero axis lengths overflows `isize` (This can only occur if A
329+
/// is zero-sized because slices cannot contain more than `isize::MAX` number of bytes).
330+
impl<'a, A, const N: usize> From<&'a [[A; N]]> for ArrayView<'a, A, Ix2> {
331+
/// Create a two-dimensional read-only array view of the data in `slice`
332+
fn from(xs: &'a [[A; N]]) -> Self {
333+
let cols = N;
334+
let rows = xs.len();
335+
let dim = Ix2(rows, cols);
336+
if size_of::<A>() == 0 {
337+
dimension::size_of_shape_checked(&dim)
338+
.expect("Product of non-zero axis lengths must not overflow isize.");
339+
}
340+
341+
// `cols * rows` is guaranteed to fit in `isize` because we checked that it fits in
342+
// `isize::MAX`
343+
unsafe {
344+
let data = slice::from_raw_parts(xs.as_ptr() as *const A, cols * rows);
345+
ArrayView::from_shape_ptr(dim, data.as_ptr())
346+
}
347+
}
348+
}
349+
326350
/// Implementation of `ArrayView::from(&A)` where `A` is an array.
327351
impl<'a, A, S, D> From<&'a ArrayBase<S, D>> for ArrayView<'a, A, D>
328352
where
@@ -355,6 +379,30 @@ where
355379
}
356380
}
357381

382+
/// Implementation of ArrayViewMut2::from(&S) where S is a slice to a 2D array
383+
///
384+
/// **Panics** if the product of non-zero axis lengths overflows `isize` (This can only occur if A
385+
/// is zero-sized because slices cannot contain more than `isize::MAX` number of bytes).
386+
impl<'a, A, const N: usize> From<&'a mut [[A; N]]> for ArrayViewMut<'a, A, Ix2> {
387+
/// Create a two-dimensional read-write array view of the data in `slice`
388+
fn from(xs: &'a mut [[A; N]]) -> Self {
389+
let cols = N;
390+
let rows = xs.len();
391+
let dim = Ix2(rows, cols);
392+
if size_of::<A>() == 0 {
393+
dimension::size_of_shape_checked(&dim)
394+
.expect("Product of non-zero axis lengths must not overflow isize.");
395+
}
396+
397+
// `cols * rows` is guaranteed to fit in `isize` because we checked that it fits in
398+
// `isize::MAX`
399+
unsafe {
400+
let data = slice::from_raw_parts_mut(xs.as_mut_ptr() as *mut A, cols * rows);
401+
ArrayViewMut::from_shape_ptr(dim, data.as_mut_ptr())
402+
}
403+
}
404+
}
405+
358406
/// Implementation of `ArrayViewMut::from(&mut A)` where `A` is an array.
359407
impl<'a, A, S, D> From<&'a mut ArrayBase<S, D>> for ArrayViewMut<'a, A, D>
360408
where

src/dimension/ndindex.rs

+58-44
Original file line numberDiff line numberDiff line change
@@ -140,50 +140,6 @@ macro_rules! ndindex_with_array {
140140
0
141141
}
142142
}
143-
144-
// implement NdIndex<IxDyn> for Dim<[Ix; 2]> and so on
145-
unsafe impl NdIndex<IxDyn> for Dim<[Ix; $n]> {
146-
#[inline]
147-
fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
148-
debug_assert_eq!(strides.ndim(), $n,
149-
"Attempted to index with {:?} in array with {} axes",
150-
self, strides.ndim());
151-
stride_offset_checked(dim.ix(), strides.ix(), self.ix())
152-
}
153-
154-
#[inline]
155-
fn index_unchecked(&self, strides: &IxDyn) -> isize {
156-
debug_assert_eq!(strides.ndim(), $n,
157-
"Attempted to index with {:?} in array with {} axes",
158-
self, strides.ndim());
159-
$(
160-
stride_offset(get!(self, $index), get!(strides, $index)) +
161-
)*
162-
0
163-
}
164-
}
165-
166-
// implement NdIndex<IxDyn> for [Ix; 2] and so on
167-
unsafe impl NdIndex<IxDyn> for [Ix; $n] {
168-
#[inline]
169-
fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
170-
debug_assert_eq!(strides.ndim(), $n,
171-
"Attempted to index with {:?} in array with {} axes",
172-
self, strides.ndim());
173-
stride_offset_checked(dim.ix(), strides.ix(), self)
174-
}
175-
176-
#[inline]
177-
fn index_unchecked(&self, strides: &IxDyn) -> isize {
178-
debug_assert_eq!(strides.ndim(), $n,
179-
"Attempted to index with {:?} in array with {} axes",
180-
self, strides.ndim());
181-
$(
182-
stride_offset(self[$index], get!(strides, $index)) +
183-
)*
184-
0
185-
}
186-
}
187143
)+
188144
};
189145
}
@@ -198,6 +154,64 @@ ndindex_with_array! {
198154
[6, Ix6 0 1 2 3 4 5]
199155
}
200156

157+
// implement NdIndex<IxDyn> for Dim<[Ix; 2]> and so on
158+
unsafe impl<const N: usize> NdIndex<IxDyn> for Dim<[Ix; N]> {
159+
#[inline]
160+
fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
161+
debug_assert_eq!(
162+
strides.ndim(),
163+
N,
164+
"Attempted to index with {:?} in array with {} axes",
165+
self,
166+
strides.ndim()
167+
);
168+
stride_offset_checked(dim.ix(), strides.ix(), self.ix())
169+
}
170+
171+
#[inline]
172+
fn index_unchecked(&self, strides: &IxDyn) -> isize {
173+
debug_assert_eq!(
174+
strides.ndim(),
175+
N,
176+
"Attempted to index with {:?} in array with {} axes",
177+
self,
178+
strides.ndim()
179+
);
180+
(0..N)
181+
.map(|i| stride_offset(get!(self, i), get!(strides, i)))
182+
.sum()
183+
}
184+
}
185+
186+
// implement NdIndex<IxDyn> for [Ix; 2] and so on
187+
unsafe impl<const N: usize> NdIndex<IxDyn> for [Ix; N] {
188+
#[inline]
189+
fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
190+
debug_assert_eq!(
191+
strides.ndim(),
192+
N,
193+
"Attempted to index with {:?} in array with {} axes",
194+
self,
195+
strides.ndim()
196+
);
197+
stride_offset_checked(dim.ix(), strides.ix(), self)
198+
}
199+
200+
#[inline]
201+
fn index_unchecked(&self, strides: &IxDyn) -> isize {
202+
debug_assert_eq!(
203+
strides.ndim(),
204+
N,
205+
"Attempted to index with {:?} in array with {} axes",
206+
self,
207+
strides.ndim()
208+
);
209+
(0..N)
210+
.map(|i| stride_offset(self[i], get!(strides, i)))
211+
.sum()
212+
}
213+
}
214+
201215
impl<'a> IntoDimension for &'a [Ix] {
202216
type Dim = IxDyn;
203217
fn into_dimension(self) -> Self::Dim {

0 commit comments

Comments
 (0)