Skip to content

Split lib.rs into many files #102

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 11 commits into from
Mar 1, 2016
177 changes: 177 additions & 0 deletions src/data_traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@

//! The data (inner representation) traits for ndarray

use std::mem;
use std::rc::Rc;

use {
ArrayBase,
Dimension,
ViewRepr,
};

/// Array’s inner representation.
///
/// ***Note:*** `Data` is not an extension interface at this point.
/// Traits in Rust can serve many different roles. This trait is public because
/// it is used as a bound on public methods.
pub unsafe trait Data {
type Elem;
fn slice(&self) -> &[Self::Elem];
}

/// Array’s writable inner representation.
pub unsafe trait DataMut : Data {
fn slice_mut(&mut self) -> &mut [Self::Elem];
#[inline]
fn ensure_unique<D>(&mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension
{ }

#[inline]
fn is_unique(&mut self) -> bool {
true
}
}

/// Clone an Array’s storage.
pub unsafe trait DataClone : Data {
/// Unsafe because, `ptr` must point inside the current storage.
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem);
}

unsafe impl<A> Data for Rc<Vec<A>> {
type Elem = A;
fn slice(&self) -> &[A] {
self
}
}

// NOTE: Copy on write
unsafe impl<A> DataMut for Rc<Vec<A>>
where A: Clone
{
fn slice_mut(&mut self) -> &mut [A] {
&mut Rc::make_mut(self)[..]
}

fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension
{
if Rc::get_mut(&mut self_.data).is_some() {
return;
}
if self_.dim.size() <= self_.data.len() / 2 {
// 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()
.cloned()
.collect());
}
return;
}
let our_off = (self_.ptr as isize - self_.data.as_ptr() as isize) /
mem::size_of::<A>() as isize;
let rvec = Rc::make_mut(&mut self_.data);
unsafe {
self_.ptr = rvec.as_mut_ptr().offset(our_off);
}
}

fn is_unique(&mut self) -> bool {
Rc::get_mut(self).is_some()
}
}

unsafe impl<A> DataClone for Rc<Vec<A>> {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
// pointer is preserved
(self.clone(), ptr)
}
}

unsafe impl<A> Data for Vec<A> {
type Elem = A;
fn slice(&self) -> &[A] {
self
}
}

unsafe impl<A> DataMut for Vec<A> {
fn slice_mut(&mut self) -> &mut [A] {
self
}
}

unsafe impl<A> DataClone for Vec<A>
where A: Clone
{
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
let mut u = self.clone();
let our_off = (self.as_ptr() as isize - ptr as isize) /
mem::size_of::<A>() as isize;
let new_ptr = u.as_mut_ptr().offset(our_off);
(u, new_ptr)
}
}

unsafe impl<'a, A> Data for ViewRepr<&'a A> {
type Elem = A;
fn slice(&self) -> &[A] {
&[]
}
}

unsafe impl<'a, A> DataClone for ViewRepr<&'a A> {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
(*self, ptr)
}
}

unsafe impl<'a, A> Data for ViewRepr<&'a mut A> {
type Elem = A;
fn slice(&self) -> &[A] {
&[]
}
}

unsafe impl<'a, A> DataMut for ViewRepr<&'a mut A> {
fn slice_mut(&mut self) -> &mut [A] {
&mut []
}
}

/// Array representation that is a unique or shared owner of its data.
pub unsafe trait DataOwned : Data {
fn new(elements: Vec<Self::Elem>) -> Self;
fn into_shared(self) -> Rc<Vec<Self::Elem>>;
}

/// Array representation that is a lightweight view.
pub unsafe trait DataShared : Clone + DataClone { }

unsafe impl<A> DataShared for Rc<Vec<A>> {}
unsafe impl<'a, A> DataShared for ViewRepr<&'a A> {}

unsafe impl<A> DataOwned for Vec<A> {
fn new(elements: Vec<A>) -> Self {
elements
}
fn into_shared(self) -> Rc<Vec<A>> {
Rc::new(self)
}
}

unsafe impl<A> DataOwned for Rc<Vec<A>> {
fn new(elements: Vec<A>) -> Self {
Rc::new(elements)
}
fn into_shared(self) -> Rc<Vec<A>> {
self
}
}

194 changes: 194 additions & 0 deletions src/free_functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@

use std::slice;

use libnum;
use imp_prelude::*;

/// ***Deprecated: Use `ArrayBase::zeros` instead.***
///
/// Return an array filled with zeros
#[cfg_attr(has_deprecated, deprecated(note="Use `ArrayBase::zeros` instead."))]
pub fn zeros<A, D>(dim: D) -> OwnedArray<A, D>
where A: Clone + libnum::Zero, D: Dimension,
{
ArrayBase::zeros(dim)
}

/// Return a zero-dimensional array with the element `x`.
pub fn arr0<A>(x: A) -> OwnedArray<A, ()>
{
unsafe { ArrayBase::from_vec_dim_unchecked((), vec![x]) }
}

/// Return a one-dimensional array with elements from `xs`.
pub fn arr1<A: Clone>(xs: &[A]) -> OwnedArray<A, Ix> {
ArrayBase::from_vec(xs.to_vec())
}

/// Return a one-dimensional array with elements from `xs`.
pub fn rcarr1<A: Clone>(xs: &[A]) -> RcArray<A, Ix> {
arr1(xs).into_shared()
}

/// Return a zero-dimensional array view borrowing `x`.
pub fn aview0<A>(x: &A) -> ArrayView<A, ()> {
unsafe { ArrayView::new_(x, (), ()) }
}

/// Return a one-dimensional array view with elements borrowing `xs`.
///
/// ```
/// use ndarray::aview1;
///
/// let data = [1.0; 1024];
///
/// // Create a 2D array view from borrowed data
/// let a2d = aview1(&data).into_shape((32, 32)).unwrap();
///
/// assert!(
/// a2d.scalar_sum() == 1024.0
/// );
/// ```
pub fn aview1<A>(xs: &[A]) -> ArrayView<A, Ix> {
ArrayView::from_slice(xs)
}

/// Return a two-dimensional array view with elements borrowing `xs`.
pub fn aview2<A, V: FixedInitializer<Elem=A>>(xs: &[V]) -> ArrayView<A, (Ix, Ix)> {
let cols = V::len();
let rows = xs.len();
let data = unsafe {
slice::from_raw_parts(xs.as_ptr() as *const A, cols * rows)
};
let dim = (rows as Ix, cols as Ix);
unsafe {
let strides = dim.default_strides();
ArrayView::new_(data.as_ptr(), dim, strides)
}
}

/// Return a one-dimensional read-write array view with elements borrowing `xs`.
///
/// ```
/// #[macro_use(s)]
/// extern crate ndarray;
///
/// use ndarray::aview_mut1;
///
/// // Create an array view over some data, then slice it and modify it.
/// fn main() {
/// let mut data = [0; 1024];
/// {
/// let mut a = aview_mut1(&mut data).into_shape((32, 32)).unwrap();
/// a.slice_mut(s![.., ..;3]).assign_scalar(&5);
/// }
/// assert_eq!(&data[..10], [5, 0, 0, 5, 0, 0, 5, 0, 0, 5]);
/// }
/// ```
pub fn aview_mut1<A>(xs: &mut [A]) -> ArrayViewMut<A, Ix> {
ArrayViewMut::from_slice(xs)
}

/// Fixed-size array used for array initialization
pub unsafe trait FixedInitializer {
type Elem;
fn as_init_slice(&self) -> &[Self::Elem];
fn len() -> usize;
}

macro_rules! impl_arr_init {
(__impl $n: expr) => (
unsafe impl<T> FixedInitializer for [T; $n] {
type Elem = T;
fn as_init_slice(&self) -> &[T] { self }
fn len() -> usize { $n }
}
);
() => ();
($n: expr, $($m:expr,)*) => (
impl_arr_init!(__impl $n);
impl_arr_init!($($m,)*);
)

}

impl_arr_init!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,);

/// Return a two-dimensional array with elements from `xs`.
///
/// ```
/// use ndarray::arr2;
///
/// let a = arr2(&[[1, 2, 3],
/// [4, 5, 6]]);
/// assert!(
/// a.shape() == [2, 3]
/// );
/// ```
pub fn arr2<A: Clone, V: FixedInitializer<Elem = A>>(xs: &[V]) -> OwnedArray<A, (Ix, Ix)> {
// FIXME: Simplify this when V is fix size array
let (m, n) = (xs.len() as Ix,
xs.get(0).map_or(0, |snd| snd.as_init_slice().len() as Ix));
let dim = (m, n);
let mut result = Vec::<A>::with_capacity(dim.size());
for snd in xs {
let snd = snd.as_init_slice();
result.extend(snd.iter().cloned());
}
unsafe {
ArrayBase::from_vec_dim_unchecked(dim, result)
}
}

/// Return a two-dimensional array with elements from `xs`.
///
pub fn rcarr2<A: Clone, V: FixedInitializer<Elem = A>>(xs: &[V]) -> RcArray<A, (Ix, Ix)> {
arr2(xs).into_shared()
}

/// Return a three-dimensional array with elements from `xs`.
///
/// **Panics** if the slices are not all of the same length.
///
/// ```
/// use ndarray::arr3;
///
/// let a = arr3(&[[[1, 2],
/// [3, 4]],
/// [[5, 6],
/// [7, 8]],
/// [[9, 0],
/// [1, 2]]]);
/// assert!(
/// a.shape() == [3, 2, 2]
/// );
/// ```
pub fn arr3<A: Clone, V: FixedInitializer<Elem=U>, U: FixedInitializer<Elem=A>>(xs: &[V])
-> OwnedArray<A, (Ix, Ix, Ix)>
{
// FIXME: Simplify this when U/V are fix size arrays
let m = xs.len() as Ix;
let fst = xs.get(0).map(|snd| snd.as_init_slice());
let thr = fst.and_then(|elt| elt.get(0).map(|elt2| elt2.as_init_slice()));
let n = fst.map_or(0, |v| v.len() as Ix);
let o = thr.map_or(0, |v| v.len() as Ix);
let dim = (m, n, o);
let mut result = Vec::<A>::with_capacity(dim.size());
for snd in xs {
let snd = snd.as_init_slice();
for thr in snd.iter() {
let thr = thr.as_init_slice();
result.extend(thr.iter().cloned());
}
}
unsafe {
ArrayBase::from_vec_dim_unchecked(dim, result)
}
}

/// Return a three-dimensional array with elements from `xs`.
pub fn rcarr3<A: Clone, V: FixedInitializer<Elem=U>, U: FixedInitializer<Elem=A>>(xs: &[V])
-> RcArray<A, (Ix, Ix, Ix)>
{
arr3(xs).into_shared()
}
19 changes: 19 additions & 0 deletions src/impl_clone.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use imp_prelude::*;
use DataClone;

impl<S: DataClone, D: Clone> Clone for ArrayBase<S, D> {
fn clone(&self) -> ArrayBase<S, D> {
unsafe {
let (data, ptr) = self.data.clone_with_ptr(self.ptr);
ArrayBase {
data: data,
ptr: ptr,
dim: self.dim.clone(),
strides: self.strides.clone(),
}
}
}
}

impl<S: DataClone + Copy, D: Copy> Copy for ArrayBase<S, D> {}

Loading