Skip to content

Commit

Permalink
Merge pull request rust-ndarray#4 from jturner314/as-contiguous-method
Browse files Browse the repository at this point in the history
Refine Cow stuff and as_standard_layout impl
  • Loading branch information
Andrew authored May 6, 2019
2 parents 2d453c7 + b14b3de commit 9ec732a
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 98 deletions.
61 changes: 38 additions & 23 deletions src/data_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,9 +414,7 @@ unsafe impl<A> DataOwned for OwnedArcRepr<A> {
}
}

unsafe impl<'a, A> RawData for CowRepr<'a, A>
where A: Clone
{
unsafe impl<'a, A> RawData for CowRepr<'a, A> {
type Elem = A;
fn _data_slice(&self) -> Option<&[A]> {
match self {
Expand All @@ -435,7 +433,16 @@ unsafe impl<'a, A> RawDataMut for CowRepr<'a, A>
where Self: Sized,
D: Dimension
{
array.ensure_is_owned();
match array.data {
CowRepr::View(_) => {
let owned = array.to_owned();
array.data = CowRepr::Owned(owned.data);
array.ptr = owned.ptr;
array.dim = owned.dim;
array.strides = owned.strides;
}
CowRepr::Owned(_) => {}
}
}

#[inline]
Expand All @@ -445,7 +452,7 @@ unsafe impl<'a, A> RawDataMut for CowRepr<'a, A>
}

unsafe impl<'a, A> RawDataClone for CowRepr<'a, A>
where A: Copy
where A: Clone
{
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
match self {
Expand All @@ -462,36 +469,44 @@ unsafe impl<'a, A> RawDataClone for CowRepr<'a, A>

#[doc(hidden)]
unsafe fn clone_from_with_ptr(&mut self, other: &Self, ptr: *mut Self::Elem) -> *mut Self::Elem {
match self {
CowRepr::View(view) => {
match other {
CowRepr::View(other_view) => view.clone_from_with_ptr(other_view, ptr),
CowRepr::Owned(_) => panic!("Cannot copy `CowRepr::View` from `CowRepr::Temp`"),
}
match (&mut *self, other) {
(CowRepr::View(self_), CowRepr::View(other)) => {
self_.clone_from_with_ptr(other, ptr)
},
CowRepr::Owned(data) => {
match other {
CowRepr::View(_) => panic!("Cannot copy `CowRepr::Temp` from `CowRepr::View`"),
CowRepr::Owned(other_data) => data.clone_from_with_ptr(other_data, ptr),
}
(CowRepr::Owned(self_), CowRepr::Owned(other)) => {
self_.clone_from_with_ptr(other, ptr)
},
(_, CowRepr::Owned(other)) => {
let (cloned, ptr) = other.clone_with_ptr(ptr);
*self = CowRepr::Owned(cloned);
ptr
},
(_, CowRepr::View(other)) => {
let (cloned, ptr) = other.clone_with_ptr(ptr);
*self = CowRepr::View(cloned);
ptr
}
}
}
}

unsafe impl<'a, A> Data for CowRepr<'a, A>
where A: Clone
{
unsafe impl<'a, A> Data for CowRepr<'a, A> {
#[inline]
fn into_owned<D>(self_: ArrayBase<CowRepr<'a, A>, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
where
A: Clone,
D: Dimension,
{
if self_.data.is_view() {
ViewRepr::into_owned(self_.into_view_array().unwrap())
} else {
OwnedRepr::into_owned(self_.into_owned_array().unwrap())
match self_.data {
CowRepr::View(_) => self_.to_owned(),
CowRepr::Owned(data) => ArrayBase {
data,
ptr: self_.ptr,
dim: self_.dim,
strides: self_.strides,
},
}
}
}

unsafe impl<'a, A> DataMut for CowRepr<'a, A> where A: Clone {}
55 changes: 55 additions & 0 deletions src/impl_cow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2019 ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::imp_prelude::*;

/// Methods specific to `ArrayCow`.
///
/// ***See also all methods for [`ArrayBase`]***
///
/// [`ArrayBase`]: struct.ArrayBase.html
impl<'a, A, D> ArrayCow<'a, A, D>
where
D: Dimension,
{
pub fn is_view(&self) -> bool {
self.data.is_view()
}

pub fn is_owned(&self) -> bool {
self.data.is_owned()
}
}

impl<'a, A, D> From<ArrayView<'a, A, D>> for ArrayCow<'a, A, D>
where
D: Dimension,
{
fn from(view: ArrayView<'a, A, D>) -> ArrayCow<'a, A, D> {
ArrayBase {
data: CowRepr::View(view.data),
ptr: view.ptr,
dim: view.dim,
strides: view.strides,
}
}
}

impl<'a, A, D> From<Array<A, D>> for ArrayCow<'a, A, D>
where
D: Dimension,
{
fn from(array: Array<A, D>) -> ArrayCow<'a, A, D> {
ArrayBase {
data: CowRepr::Owned(array.data),
ptr: array.ptr,
dim: array.dim,
strides: array.strides,
}
}
}
8 changes: 4 additions & 4 deletions src/impl_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1230,14 +1230,14 @@ where
A: Clone
{
if self.is_standard_layout() {
ArrayCow::from_view_array(self.view())
ArrayCow::from(self.view())
} else {
let v = self.iter().map(|x| x.clone()).collect::<Vec<A>>();
let v = self.iter().cloned().collect::<Vec<A>>();
let owned_array: Array<A, D> = unsafe {
// Safe because we use shape and content of existing array here.
ArrayBase::from_shape_vec_unchecked(self.dim(), v)
ArrayBase::from_shape_vec_unchecked(self.raw_dim(), v)
};
ArrayCow::from_owned_array(owned_array)
ArrayCow::from(owned_array)
}
}

Expand Down
91 changes: 20 additions & 71 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ mod imp_prelude {
DataShared,
RawViewRepr,
ViewRepr,
CowRepr,
Ix, Ixs,
};
pub use crate::dimension::DimensionExt;
Expand Down Expand Up @@ -1230,6 +1231,20 @@ pub type ArcArray<A, D> = ArrayBase<OwnedArcRepr<A>, D>;
/// and so on.
pub type Array<A, D> = ArrayBase<OwnedRepr<A>, D>;

/// An array with copy-on-write behavior.
///
/// An `ArrayCow` represents either a uniquely owned array or a view of an
/// array. The `'a` corresponds to the lifetime of the view variant.
///
/// Array views have all the methods of an array (see [`ArrayBase`][ab]).
///
/// See also [`ArcArray`](type.ArcArray.html), which also provides
/// copy-on-write behavior but has a reference-counted pointer to the data
/// instead of either a view or a uniquely owned copy.
///
/// [ab]: struct.ArrayBase.html
pub type ArrayCow<'a, A, D> = ArrayBase<CowRepr<'a, A>, D>;

/// A read-only array view.
///
/// An array view represents an array or a part of it, created from
Expand Down Expand Up @@ -1374,16 +1389,12 @@ impl<A> ViewRepr<A> {
}
}

pub enum CowRepr<'a, A>
where A: Clone
{
pub enum CowRepr<'a, A> {
View(ViewRepr<&'a A>),
Owned(OwnedRepr<A>),
}

impl<'a, A> CowRepr<'a, A>
where A: Clone
{
impl<'a, A> CowRepr<'a, A> {
pub fn is_view(&self) -> bool {
match self {
CowRepr::View(_) => true,
Expand All @@ -1396,8 +1407,6 @@ impl<'a, A> CowRepr<'a, A>
}
}

pub type ArrayCow<'a, A, D> = ArrayBase<CowRepr<'a, A>, D>;

mod impl_clone;

mod impl_constructors;
Expand Down Expand Up @@ -1496,69 +1505,6 @@ impl<A, S, D> ArrayBase<S, D>
}
}

impl<'a, A, D> ArrayCow<'a, A, D>
where A: Clone,
D: Dimension
{
fn from_view_array(array: ArrayView<'a, A, D>) -> ArrayCow<'a, A, D> {
ArrayBase {
data: CowRepr::View(array.data),
ptr: array.ptr,
dim: array.dim,
strides: array.strides,
}
}

fn from_owned_array(array: Array<A, D>) -> ArrayCow<'a, A, D> {
ArrayBase {
data: CowRepr::Owned(array.data),
ptr: array.ptr,
dim: array.dim,
strides: array.strides,
}
}

fn into_view_array(self) -> Option<ArrayView<'a, A, D>> {
match self.data {
CowRepr::View(view) => Some(ArrayBase {
data: view,
ptr: self.ptr,
dim: self.dim,
strides: self.strides,
}),
CowRepr::Owned(_) => None,
}
}

fn into_owned_array(self) -> Option<Array<A, D>> {
match self.data {
CowRepr::View(_) => None,
CowRepr::Owned(data) => Some(ArrayBase {
data,
ptr: self.ptr,
dim: self.dim,
strides: self.strides,
})
}
}

fn ensure_is_owned(&mut self) {
if self.data.is_view() {
let mut copied_data: Vec<A> = self.iter().map(|x| x.clone()).collect();
self.ptr = copied_data.as_mut_ptr();
self.data = CowRepr::Owned(OwnedRepr(copied_data));
}
}

pub fn is_view(&self) -> bool {
self.data.is_view()
}

pub fn is_owned(&self) -> bool {
self.data.is_owned()
}
}


// parallel methods
#[cfg(feature="rayon")]
Expand All @@ -1581,6 +1527,9 @@ mod impl_views;
// Array raw view methods
mod impl_raw_views;

// Copy-on-write array methods
mod impl_cow;

/// A contiguous array shape of n dimensions.
///
/// Either c- or f- memory ordered (*c* a.k.a *row major* is the default).
Expand Down
1 change: 1 addition & 0 deletions src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub use crate::{
Array,
ArcArray,
RcArray,
ArrayCow,
ArrayView,
ArrayViewMut,
RawArrayView,
Expand Down

0 comments on commit 9ec732a

Please sign in to comment.