Skip to content

Unify array with shape construction using Shape & ShapeBuilder #191

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 17, 2016
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
4 changes: 2 additions & 2 deletions src/data_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ unsafe impl<A> DataMut for Rc<Vec<A>>
// Create a new vec if the current view is less than half of
// backing data.
unsafe {
*self_ = ArrayBase::from_vec_dim_unchecked(self_.dim.clone(),
self_.iter()
*self_ = ArrayBase::from_shape_vec_unchecked(self_.dim.clone(),
self_.iter()
.cloned()
.collect());
}
Expand Down
6 changes: 3 additions & 3 deletions src/free_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use imp_prelude::*;
/// Create a zero-dimensional array with the element `x`.
pub fn arr0<A>(x: A) -> OwnedArray<A, ()>
{
unsafe { ArrayBase::from_vec_dim_unchecked((), vec![x]) }
unsafe { ArrayBase::from_shape_vec_unchecked((), vec![x]) }
}

/// Create a one-dimensional array with elements from `xs`.
Expand Down Expand Up @@ -129,7 +129,7 @@ pub fn arr2<A: Clone, V: FixedInitializer<Elem = A>>(xs: &[V]) -> OwnedArray<A,
result.extend_from_slice(snd.as_init_slice());
}
unsafe {
ArrayBase::from_vec_dim_unchecked(dim, result)
ArrayBase::from_shape_vec_unchecked(dim, result)
}
}

Expand Down Expand Up @@ -167,7 +167,7 @@ pub fn arr3<A: Clone, V: FixedInitializer<Elem=U>, U: FixedInitializer<Elem=A>>(
}
}
unsafe {
ArrayBase::from_vec_dim_unchecked(dim, result)
ArrayBase::from_shape_vec_unchecked(dim, result)
}
}

Expand Down
172 changes: 103 additions & 69 deletions src/impl_constructors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@

//! Constructor methods for ndarray
//!
use libnum;
//!

#![allow(deprecated)] // from_shape_vec

use libnum::{Zero, One, Float};

use imp_prelude::*;
use {Shape, StrideShape};
use dimension;
use linspace;
use error::{self, ShapeError, ErrorKind};
Expand All @@ -30,7 +35,7 @@ impl<S> ArrayBase<S, Ix>
/// let array = OwnedArray::from_vec(vec![1., 2., 3., 4.]);
/// ```
pub fn from_vec(v: Vec<S::Elem>) -> ArrayBase<S, Ix> {
unsafe { Self::from_vec_dim_unchecked(v.len() as Ix, v) }
unsafe { Self::from_shape_vec_unchecked(v.len() as Ix, v) }
}

/// Create a one-dimensional array from an iterable.
Expand Down Expand Up @@ -58,7 +63,7 @@ impl<S> ArrayBase<S, Ix>
/// ```
pub fn linspace<F>(start: F, end: F, n: usize) -> ArrayBase<S, Ix>
where S: Data<Elem=F>,
F: libnum::Float,
F: Float,
{
Self::from_vec(::iterators::to_vec(linspace::linspace(start, end, n)))
}
Expand All @@ -74,7 +79,7 @@ impl<S> ArrayBase<S, Ix>
/// ```
pub fn range<F>(start: F, end: F, step: F) -> ArrayBase<S, Ix>
where S: Data<Elem=F>,
F: libnum::Float,
F: Float,
{
Self::from_vec(::iterators::to_vec(linspace::range(start, end, step)))
}
Expand All @@ -89,7 +94,7 @@ impl<S, A> ArrayBase<S, (Ix, Ix)>
/// **Panics** if `n * n` would overflow usize.
pub fn eye(n: Ix) -> ArrayBase<S, (Ix, Ix)>
where S: DataMut,
A: Clone + libnum::Zero + libnum::One,
A: Clone + Zero + One,
{
let mut eye = Self::zeros((n, n));
for a_ii in eye.diag_mut() {
Expand All @@ -113,13 +118,12 @@ impl<S, A, D> ArrayBase<S, D>
where S: DataOwned<Elem=A>,
D: Dimension,
{
/// Create an array with copies of `elem`, dimension `dim`.
/// Create an array with copies of `elem`, shape `shape`.
///
/// **Panics** if the number of elements in `dim` would overflow usize.
/// **Panics** if the number of elements in `shape` would overflow usize.
///
/// ```
/// use ndarray::OwnedArray;
/// use ndarray::arr3;
/// use ndarray::{OwnedArray, arr3, ShapeBuilder};
///
/// let a = OwnedArray::from_elem((2, 2, 2), 1.);
///
Expand All @@ -130,89 +134,128 @@ impl<S, A, D> ArrayBase<S, D>
/// [1., 1.]]])
/// );
/// assert!(a.strides() == &[4, 2, 1]);
///
/// let b = OwnedArray::from_elem((2, 2, 2).f(), 1.);
/// assert!(b.strides() == &[1, 2, 4]);
/// ```
pub fn from_elem(dim: D, elem: A) -> ArrayBase<S, D>
where A: Clone
pub fn from_elem<Sh>(shape: Sh, elem: A) -> ArrayBase<S, D>
where A: Clone,
Sh: Into<Shape<D>>,
{
// Note: We don't need to check the case of a size between
// isize::MAX -> usize::MAX; in this case, the vec constructor itself
// panics.
let size = size_checked_unwrap!(dim);
let shape = shape.into();
let size = size_checked_unwrap!(shape.dim);
let v = vec![elem; size];
unsafe { Self::from_vec_dim_unchecked(dim, v) }
unsafe { Self::from_shape_vec_unchecked(shape, v) }
}

/// Create an array with copies of `elem`, dimension `dim` and fortran
/// memory order.
///
/// **Panics** if the number of elements would overflow usize.
/// Create an array with zeros, shape `shape`.
///
/// ```
/// use ndarray::OwnedArray;
///
/// let a = OwnedArray::from_elem_f((2, 2, 2), 1.);
/// assert!(a.strides() == &[1, 2, 4]);
/// ```
pub fn from_elem_f(dim: D, elem: A) -> ArrayBase<S, D>
where A: Clone
/// **Panics** if the number of elements in `shape` would overflow usize.
pub fn zeros<Sh>(shape: Sh) -> ArrayBase<S, D>
where A: Clone + Zero,
Sh: Into<Shape<D>>,
{
let size = size_checked_unwrap!(dim);
let v = vec![elem; size];
unsafe { Self::from_vec_dim_unchecked_f(dim, v) }
Self::from_elem(shape, A::zero())
}

/// Create an array with zeros, dimension `dim`.
/// Create an array with default values, shape `shape`
///
/// **Panics** if the number of elements in `dim` would overflow usize.
pub fn zeros(dim: D) -> ArrayBase<S, D>
where A: Clone + libnum::Zero
/// **Panics** if the number of elements in `shape` would overflow usize.
pub fn default<Sh>(shape: Sh) -> ArrayBase<S, D>
where A: Default,
Sh: Into<Shape<D>>,
{
Self::from_elem(dim, libnum::zero())
let shape = shape.into();
let v = (0..shape.dim.size()).map(|_| A::default()).collect();
unsafe { Self::from_shape_vec_unchecked(shape, v) }
}

/// Create an array with zeros, dimension `dim` and fortran memory order.
/// Create an array with the given shape from a vector. (No cloning of
/// elements needed.)
///
/// **Panics** if the number of elements in `dim` would overflow usize.
pub fn zeros_f(dim: D) -> ArrayBase<S, D>
where A: Clone + libnum::Zero
/// ----
///
/// For a contiguous c- or f-order shape, the following applies:
///
/// **Errors** if `shape` does not correspond to the number of elements in `v`.
///
/// ----
///
/// For custom strides, the following applies:
///
/// **Errors** if strides and dimensions can point out of bounds of `v`.<br>
/// **Errors** if strides allow multiple indices to point to the same element.
pub fn from_shape_vec<Sh>(shape: Sh, v: Vec<A>) -> Result<ArrayBase<S, D>, ShapeError>
where Sh: Into<StrideShape<D>>,
{
Self::from_elem_f(dim, libnum::zero())
// eliminate the type parameter Sh as soon as possible
Self::from_shape_vec_impl(shape.into(), v)
}

/// Create an array with default values, dimension `dim`.
///
/// **Panics** if the number of elements in `dim` would overflow usize.
pub fn default(dim: D) -> ArrayBase<S, D>
where A: Default
fn from_shape_vec_impl(shape: StrideShape<D>, v: Vec<A>) -> Result<ArrayBase<S, D>, ShapeError>
{
let v = (0..dim.size()).map(|_| A::default()).collect();
unsafe { Self::from_vec_dim_unchecked(dim, v) }
if shape.custom {
Self::from_vec_dim_stride(shape.dim, shape.strides, v)
} else {
let dim = shape.dim;
let strides = shape.strides;
if dim.size_checked() != Some(v.len()) {
return Err(error::incompatible_shapes(&v.len(), &dim));
}
unsafe { Ok(Self::from_vec_dim_stride_unchecked(dim, strides, v)) }
}
}

/// Create an array from a vector (no copying needed).
/// Create an array from a vector and interpret it according to the
/// provided dimensions and strides. (No cloning of elements needed.)
///
/// **Errors** if `dim` does not correspond to the number of elements in `v`.
/// Unsafe because dimension and strides are unchecked.
pub unsafe fn from_shape_vec_unchecked<Sh>(shape: Sh, v: Vec<A>) -> ArrayBase<S, D>
where Sh: Into<StrideShape<D>>,
{
let shape = shape.into();
Self::from_vec_dim_stride_unchecked(shape.dim, shape.strides, v)
}

#[cfg_attr(has_deprecated, deprecated(note="Use from_elem instead."))]
/// ***Deprecated: Use from_elem instead***
pub fn from_elem_f(dim: D, elem: A) -> ArrayBase<S, D>
where A: Clone
{
Self::from_elem(dim.f(), elem)
}

#[cfg_attr(has_deprecated, deprecated(note="Use zeros instead."))]
/// ***Deprecated: Use zeros instead***
pub fn zeros_f(dim: D) -> ArrayBase<S, D>
where A: Clone + Zero
{
Self::from_elem_f(dim, A::zero())
}

#[cfg_attr(has_deprecated, deprecated(note="Use from_shape_vec instead."))]
/// ***Deprecated: Use from_shape_vec instead***
pub fn from_vec_dim(dim: D, v: Vec<A>) -> Result<ArrayBase<S, D>, ShapeError> {
if dim.size_checked() != Some(v.len()) {
return Err(error::incompatible_shapes(&v.len(), &dim));
}
unsafe { Ok(Self::from_vec_dim_unchecked(dim, v)) }
}

/// Create an array from a vector (no copying needed) using fortran
/// memory order to interpret the data.
///
/// **Errors** if `dim` does not correspond to the number of elements in `v`.
#[cfg_attr(has_deprecated, deprecated(note="Use from_shape_vec instead."))]
/// ***Deprecated: Use from_shape_vec instead***
pub fn from_vec_dim_f(dim: D, v: Vec<A>) -> Result<ArrayBase<S, D>, ShapeError> {
if dim.size_checked() != Some(v.len()) {
return Err(error::incompatible_shapes(&v.len(), &dim));
}
unsafe { Ok(Self::from_vec_dim_unchecked_f(dim, v)) }
}

/// Create an array from a vector (no copying needed).
///
/// Unsafe because dimension is unchecked, and must be correct.
#[cfg_attr(has_deprecated, deprecated(note="Use from_shape_vec_unchecked instead."))]
/// ***Deprecated: Use from_shape_vec_unchecked instead***
pub unsafe fn from_vec_dim_unchecked(dim: D, mut v: Vec<A>) -> ArrayBase<S, D> {
debug_assert!(dim.size_checked() == Some(v.len()));
ArrayBase {
Expand All @@ -223,24 +266,16 @@ impl<S, A, D> ArrayBase<S, D>
}
}

/// Create an array from a vector (with no copying needed),
/// using fortran memory order to interpret the data.
///
/// Unsafe because dimension is unchecked, and must be correct.
#[cfg_attr(has_deprecated, deprecated(note="Use from_shape_vec_unchecked instead."))]
/// ***Deprecated: Use from_shape_vec_unchecked instead***
pub unsafe fn from_vec_dim_unchecked_f(dim: D, v: Vec<A>) -> ArrayBase<S, D> {
debug_assert!(dim.size_checked() == Some(v.len()));
let strides = dim.fortran_strides();
Self::from_vec_dim_stride_unchecked(dim, strides, v)
}

/// Create an array from a vector and interpret it according to the
/// provided dimensions and strides. No allocation needed.
///
/// Checks whether `dim` and `strides` are compatible with the vector's
/// length, returning an `Err` if not compatible.
///
/// **Errors** if strides and dimensions can point out of bounds of `v`.<br>
/// **Errors** if strides allow multiple indices to point to the same element.
#[cfg_attr(has_deprecated, deprecated(note="Use from_shape_vec instead."))]
/// ***Deprecated: Use from_shape_vec instead***
pub fn from_vec_dim_stride(dim: D, strides: D, v: Vec<A>)
-> Result<ArrayBase<S, D>, ShapeError>
{
Expand All @@ -251,10 +286,9 @@ impl<S, A, D> ArrayBase<S, D>
})
}

/// Create an array from a vector and interpret it according to the
/// provided dimensions and strides. No allocation needed.
#[cfg_attr(has_deprecated, deprecated(note="Use from_shape_vec_unchecked instead."))]
/// ***Deprecated: Use from_shape_vec_unchecked instead***
///
/// Unsafe because dimension and strides are unchecked.
pub unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec<A>)
-> ArrayBase<S, D>
{
Expand Down
12 changes: 6 additions & 6 deletions src/impl_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
(self.iter().cloned().collect(), self.dim.default_strides())
};
unsafe {
ArrayBase::from_vec_dim_stride_unchecked(self.dim.clone(), strides, data)
ArrayBase::from_shape_vec_unchecked(self.dim.clone().strides(strides), data)
}
}

Expand Down Expand Up @@ -427,7 +427,7 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
let mut dim = self.dim();
dim.set_axis(axis, 0);
unsafe {
OwnedArray::from_vec_dim_unchecked(dim, vec![])
OwnedArray::from_shape_vec_unchecked(dim, vec![])
}
} else {
stack(axis, &subs).unwrap()
Expand Down Expand Up @@ -800,7 +800,7 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
} else {
let v = self.iter().map(|x| x.clone()).collect::<Vec<A>>();
unsafe {
ArrayBase::from_vec_dim_unchecked(shape, v)
ArrayBase::from_shape_vec_unchecked(shape, v)
}
}
}
Expand Down Expand Up @@ -1150,13 +1150,13 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
if let Some(slc) = self.as_slice_memory_order() {
let v = ::iterators::to_vec(slc.iter().map(f));
unsafe {
ArrayBase::from_vec_dim_stride_unchecked(
self.dim.clone(), self.strides.clone(), v)
ArrayBase::from_shape_vec_unchecked(
self.dim.clone().strides(self.strides.clone()), v)
}
} else {
let v = ::iterators::to_vec(self.iter().map(f));
unsafe {
ArrayBase::from_vec_dim_unchecked(self.dim.clone(), v)
ArrayBase::from_shape_vec_unchecked(self.dim.clone(), v)
}
}
}
Expand Down
Loading