Skip to content

Commit

Permalink
Merge pull request #543 from jturner314/clarify-invariants
Browse files Browse the repository at this point in the history
Clarify invariants and fix constructors and is_standard_layout
  • Loading branch information
jturner314 committed Nov 19, 2018
2 parents e064200 + 8727b8a commit 1725928
Show file tree
Hide file tree
Showing 13 changed files with 709 additions and 182 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ serde = { version = "1.0", optional = true }

[dev-dependencies]
defmac = "0.1"
quickcheck = { version = "0.7.2", default-features = false }
rawpointer = "0.1"

[features]
Expand Down
5 changes: 4 additions & 1 deletion src/array_serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use serialize::{Encodable, Encoder, Decodable, Decoder};
use super::arraytraits::ARRAY_FORMAT_VERSION;
use super::dimension;

use imp_prelude::*;

Expand Down Expand Up @@ -74,7 +75,9 @@ impl<A, S, D> Decodable for ArrayBase<S, D>
let elements = try!(
d.read_struct_field("data", 2, |d| {
d.read_seq(|d, len| {
if len != dim.size() {
let dim_size = dimension::size_of_shape_checked(&dim)
.map_err(|_| d.error("overflow calculating array size"))?;
if len != dim_size {
Err(d.error("data and dimension must match in size"))
} else {
let mut elements = Vec::with_capacity(len);
Expand Down
17 changes: 17 additions & 0 deletions src/arraytraits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use std::hash;
use std::iter::FromIterator;
use std::iter::IntoIterator;
use std::mem;
use std::ops::{
Index,
IndexMut,
Expand Down Expand Up @@ -216,11 +217,19 @@ pub const ARRAY_FORMAT_VERSION: u8 = 1u8;
/// Implementation of `ArrayView::from(&S)` where `S` is a slice or slicable.
///
/// Create a one-dimensional read-only array view of the data in `slice`.
///
/// **Panics** if the slice length is greater than `isize::MAX`.
impl<'a, A, Slice: ?Sized> From<&'a Slice> for ArrayView<'a, A, Ix1>
where Slice: AsRef<[A]>
{
fn from(slice: &'a Slice) -> Self {
let xs = slice.as_ref();
if mem::size_of::<A>() == 0 {
assert!(
xs.len() <= ::std::isize::MAX as usize,
"Slice length must fit in `isize`.",
);
}
unsafe {
Self::from_shape_ptr(xs.len(), xs.as_ptr())
}
Expand All @@ -242,11 +251,19 @@ impl<'a, A, S, D> From<&'a ArrayBase<S, D>> for ArrayView<'a, A, D>
/// Implementation of `ArrayViewMut::from(&mut S)` where `S` is a slice or slicable.
///
/// Create a one-dimensional read-write array view of the data in `slice`.
///
/// **Panics** if the slice length is greater than `isize::MAX`.
impl<'a, A, Slice: ?Sized> From<&'a mut Slice> for ArrayViewMut<'a, A, Ix1>
where Slice: AsMut<[A]>
{
fn from(slice: &'a mut Slice) -> Self {
let xs = slice.as_mut();
if mem::size_of::<A>() == 0 {
assert!(
xs.len() <= ::std::isize::MAX as usize,
"Slice length must fit in `isize`.",
);
}
unsafe {
Self::from_shape_ptr(xs.len(), xs.as_mut_ptr())
}
Expand Down
42 changes: 33 additions & 9 deletions src/dimension/dimension_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,17 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default +
self.slice() == rhs.slice()
}

/// Returns the strides for a standard layout array with the given shape.
///
/// If the array is non-empty, the strides result in contiguous layout; if
/// the array is empty, the strides are all zeros.
#[doc(hidden)]
fn default_strides(&self) -> Self {
// Compute default array strides
// Shape (a, b, c) => Give strides (b * c, c, 1)
let mut strides = self.clone();
{
let mut strides = Self::zeros(self.ndim());
// For empty arrays, use all zero strides.
if self.slice().iter().all(|&d| d != 0) {
let mut it = strides.slice_mut().iter_mut().rev();
// Set first element to 1
while let Some(rs) = it.next() {
Expand All @@ -130,12 +135,17 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default +
strides
}

/// Returns the strides for a Fortran layout array with the given shape.
///
/// If the array is non-empty, the strides result in contiguous layout; if
/// the array is empty, the strides are all zeros.
#[doc(hidden)]
fn fortran_strides(&self) -> Self {
// Compute fortran array strides
// Shape (a, b, c) => Give strides (1, a, a * b)
let mut strides = self.clone();
{
let mut strides = Self::zeros(self.ndim());
// For empty arrays, use all zero strides.
if self.slice().iter().all(|&d| d != 0) {
let mut it = strides.slice_mut().iter_mut();
// Set first element to 1
while let Some(rs) = it.next() {
Expand Down Expand Up @@ -432,7 +442,11 @@ impl Dimension for Dim<[Ix; 1]> {

#[inline]
fn default_strides(&self) -> Self {
Ix1(1)
if get!(self, 0) == 0 {
Ix1(0)
} else {
Ix1(1)
}
}

#[inline]
Expand Down Expand Up @@ -548,13 +562,23 @@ impl Dimension for Dim<[Ix; 2]> {

#[inline]
fn default_strides(&self) -> Self {
// Compute default array strides
// Shape (a, b, c) => Give strides (b * c, c, 1)
Ix2(get!(self, 1), 1)
let m = get!(self, 0);
let n = get!(self, 1);
if m == 0 || n == 0 {
Ix2(0, 0)
} else {
Ix2(n, 1)
}
}
#[inline]
fn fortran_strides(&self) -> Self {
Ix2(1, get!(self, 0))
let m = get!(self, 0);
let n = get!(self, 1);
if m == 0 || n == 0 {
Ix2(0, 0)
} else {
Ix2(1, m)
}
}

#[inline]
Expand Down

0 comments on commit 1725928

Please sign in to comment.