Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Const generics Improvements #980

Merged
merged 4 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- stable
- beta
- nightly
- 1.49.0 # MSRV
- 1.51.0 # MSRV

steps:
- uses: actions/checkout@v2
Expand Down
66 changes: 57 additions & 9 deletions src/arraytraits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::hash;
use std::iter::FromIterator;
use alloc::boxed::Box;
use alloc::vec::Vec;
use std::iter::IntoIterator;
use std::mem;
use std::ops::{Index, IndexMut};
use alloc::boxed::Box;
use alloc::vec::Vec;
use std::{hash, mem::size_of};
use std::{iter::FromIterator, slice};

use crate::imp_prelude::*;
use crate::iter::{Iter, IterMut};
use crate::NdIndex;

use crate::numeric_util;
use crate::{FoldWhile, Zip};
use crate::{
dimension,
iter::{Iter, IterMut},
numeric_util, FoldWhile, NdIndex, Zip,
};

#[cold]
#[inline(never)]
Expand Down Expand Up @@ -323,6 +323,30 @@ where
}
}

/// Implementation of ArrayView2::from(&S) where S is a slice to a 2D array
///
/// **Panics** if the product of non-zero axis lengths overflows `isize` (This can only occur if A
/// is zero-sized because slices cannot contain more than `isize::MAX` number of bytes).
impl<'a, A, const N: usize> From<&'a [[A; N]]> for ArrayView<'a, A, Ix2> {
/// Create a two-dimensional read-only array view of the data in `slice`
fn from(xs: &'a [[A; N]]) -> Self {
let cols = N;
let rows = xs.len();
let dim = Ix2(rows, cols);
if size_of::<A>() == 0 {
dimension::size_of_shape_checked(&dim)
.expect("Product of non-zero axis lengths must not overflow isize.");
}

// `cols * rows` is guaranteed to fit in `isize` because we checked that it fits in
// `isize::MAX`
unsafe {
let data = slice::from_raw_parts(xs.as_ptr() as *const A, cols * rows);
ArrayView::from_shape_ptr(dim, data.as_ptr())
}
}
}

/// Implementation of `ArrayView::from(&A)` where `A` is an array.
impl<'a, A, S, D> From<&'a ArrayBase<S, D>> for ArrayView<'a, A, D>
where
Expand Down Expand Up @@ -355,6 +379,30 @@ where
}
}

/// Implementation of ArrayViewMut2::from(&S) where S is a slice to a 2D array
///
/// **Panics** if the product of non-zero axis lengths overflows `isize` (This can only occur if A
/// is zero-sized because slices cannot contain more than `isize::MAX` number of bytes).
impl<'a, A, const N: usize> From<&'a mut [[A; N]]> for ArrayViewMut<'a, A, Ix2> {
/// Create a two-dimensional read-write array view of the data in `slice`
fn from(xs: &'a mut [[A; N]]) -> Self {
let cols = N;
let rows = xs.len();
let dim = Ix2(rows, cols);
if size_of::<A>() == 0 {
dimension::size_of_shape_checked(&dim)
.expect("Product of non-zero axis lengths must not overflow isize.");
}

// `cols * rows` is guaranteed to fit in `isize` because we checked that it fits in
// `isize::MAX`
unsafe {
let data = slice::from_raw_parts_mut(xs.as_mut_ptr() as *mut A, cols * rows);
ArrayViewMut::from_shape_ptr(dim, data.as_mut_ptr())
}
}
}

/// Implementation of `ArrayViewMut::from(&mut A)` where `A` is an array.
impl<'a, A, S, D> From<&'a mut ArrayBase<S, D>> for ArrayViewMut<'a, A, D>
where
Expand Down
102 changes: 58 additions & 44 deletions src/dimension/ndindex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,50 +140,6 @@ macro_rules! ndindex_with_array {
0
}
}

// implement NdIndex<IxDyn> for Dim<[Ix; 2]> and so on
unsafe impl NdIndex<IxDyn> for Dim<[Ix; $n]> {
#[inline]
fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
debug_assert_eq!(strides.ndim(), $n,
"Attempted to index with {:?} in array with {} axes",
self, strides.ndim());
stride_offset_checked(dim.ix(), strides.ix(), self.ix())
}

#[inline]
fn index_unchecked(&self, strides: &IxDyn) -> isize {
debug_assert_eq!(strides.ndim(), $n,
"Attempted to index with {:?} in array with {} axes",
self, strides.ndim());
$(
stride_offset(get!(self, $index), get!(strides, $index)) +
)*
0
}
}

// implement NdIndex<IxDyn> for [Ix; 2] and so on
unsafe impl NdIndex<IxDyn> for [Ix; $n] {
#[inline]
fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
debug_assert_eq!(strides.ndim(), $n,
"Attempted to index with {:?} in array with {} axes",
self, strides.ndim());
stride_offset_checked(dim.ix(), strides.ix(), self)
}

#[inline]
fn index_unchecked(&self, strides: &IxDyn) -> isize {
debug_assert_eq!(strides.ndim(), $n,
"Attempted to index with {:?} in array with {} axes",
self, strides.ndim());
$(
stride_offset(self[$index], get!(strides, $index)) +
)*
0
}
}
)+
};
}
Expand All @@ -198,6 +154,64 @@ ndindex_with_array! {
[6, Ix6 0 1 2 3 4 5]
}

// implement NdIndex<IxDyn> for Dim<[Ix; 2]> and so on
unsafe impl<const N: usize> NdIndex<IxDyn> for Dim<[Ix; N]> {
#[inline]
fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
debug_assert_eq!(
strides.ndim(),
N,
"Attempted to index with {:?} in array with {} axes",
self,
strides.ndim()
);
stride_offset_checked(dim.ix(), strides.ix(), self.ix())
}

#[inline]
fn index_unchecked(&self, strides: &IxDyn) -> isize {
debug_assert_eq!(
strides.ndim(),
N,
"Attempted to index with {:?} in array with {} axes",
self,
strides.ndim()
);
(0..N)
.map(|i| stride_offset(get!(self, i), get!(strides, i)))
.sum()
}
}

// implement NdIndex<IxDyn> for [Ix; 2] and so on
unsafe impl<const N: usize> NdIndex<IxDyn> for [Ix; N] {
#[inline]
fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
debug_assert_eq!(
strides.ndim(),
N,
"Attempted to index with {:?} in array with {} axes",
self,
strides.ndim()
);
stride_offset_checked(dim.ix(), strides.ix(), self)
}

#[inline]
fn index_unchecked(&self, strides: &IxDyn) -> isize {
debug_assert_eq!(
strides.ndim(),
N,
"Attempted to index with {:?} in array with {} axes",
self,
strides.ndim()
);
(0..N)
.map(|i| stride_offset(self[i], get!(strides, i)))
.sum()
}
}

impl<'a> IntoDimension for &'a [Ix] {
type Dim = IxDyn;
fn into_dimension(self) -> Self::Dim {
Expand Down
Loading