Skip to content

Commit

Permalink
CowArray feature (#632)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew authored and jturner314 committed May 30, 2019
1 parent d6ecbf2 commit 5b5d898
Show file tree
Hide file tree
Showing 6 changed files with 425 additions and 12 deletions.
104 changes: 103 additions & 1 deletion src/data_traits.rs
Expand Up @@ -11,7 +11,9 @@
use std::mem::{self, size_of};
use std::sync::Arc;

use crate::{ArrayBase, Dimension, OwnedArcRepr, OwnedRcRepr, OwnedRepr, RawViewRepr, ViewRepr};
use crate::{
ArrayBase, CowRepr, Dimension, OwnedArcRepr, OwnedRcRepr, OwnedRepr, RawViewRepr, ViewRepr,
};

/// Array representation trait.
///
Expand Down Expand Up @@ -423,3 +425,103 @@ unsafe impl<A> DataOwned for OwnedArcRepr<A> {
self
}
}

unsafe impl<'a, A> RawData for CowRepr<'a, A> {
type Elem = A;
fn _data_slice(&self) -> Option<&[A]> {
match self {
CowRepr::View(view) => view._data_slice(),
CowRepr::Owned(data) => data._data_slice(),
}
}
private_impl! {}
}

unsafe impl<'a, A> RawDataMut for CowRepr<'a, A>
where
A: Clone,
{
#[inline]
fn try_ensure_unique<D>(array: &mut ArrayBase<Self, D>)
where
Self: Sized,
D: Dimension,
{
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]
fn try_is_unique(&mut self) -> Option<bool> {
Some(self.is_owned())
}
}

unsafe impl<'a, A> RawDataClone for CowRepr<'a, A>
where
A: Clone,
{
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
match self {
CowRepr::View(view) => {
let (new_view, ptr) = view.clone_with_ptr(ptr);
(CowRepr::View(new_view), ptr)
}
CowRepr::Owned(data) => {
let (new_data, ptr) = data.clone_with_ptr(ptr);
(CowRepr::Owned(new_data), ptr)
}
}
}

#[doc(hidden)]
unsafe fn clone_from_with_ptr(
&mut self,
other: &Self,
ptr: *mut Self::Elem,
) -> *mut Self::Elem {
match (&mut *self, other) {
(CowRepr::View(self_), CowRepr::View(other)) => self_.clone_from_with_ptr(other, 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> {
#[inline]
fn into_owned<D>(self_: ArrayBase<CowRepr<'a, A>, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
where
A: Clone,
D: Dimension,
{
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 {}
9 changes: 6 additions & 3 deletions src/doc/ndarray_for_numpy_users/mod.rs
Expand Up @@ -72,9 +72,11 @@
//! In `ndarray`, all arrays are instances of [`ArrayBase`][ArrayBase], but
//! `ArrayBase` is generic over the ownership of the data. [`Array`][Array]
//! owns its data; [`ArrayView`][ArrayView] is a view;
//! [`ArrayViewMut`][ArrayViewMut] is a mutable view; and
//! [`ArcArray`][ArcArray] has a reference-counted pointer to its data (with
//! copy-on-write mutation). Arrays and views follow Rust's aliasing rules.
//! [`ArrayViewMut`][ArrayViewMut] is a mutable view; [`CowArray`][CowArray]
//! either owns its data or is a view (with copy-on-write mutation of the view
//! variant); and [`ArcArray`][ArcArray] has a reference-counted pointer to its
//! data (with copy-on-write mutation). Arrays and views follow Rust's aliasing
//! rules.
//!
//! </td>
//! </tr>
Expand Down Expand Up @@ -572,6 +574,7 @@
//! [.cols()]: ../../struct.ArrayBase.html#method.cols
//! [.column()]: ../../struct.ArrayBase.html#method.column
//! [.column_mut()]: ../../struct.ArrayBase.html#method.column_mut
//! [CowArray]: ../../type.CowArray.html
//! [::default()]: ../../struct.ArrayBase.html#method.default
//! [.diag()]: ../../struct.ArrayBase.html#method.diag
//! [.dim()]: ../../struct.ArrayBase.html#method.dim
Expand Down
57 changes: 57 additions & 0 deletions src/impl_cow.rs
@@ -0,0 +1,57 @@
// 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 `CowArray`.
///
/// ***See also all methods for [`ArrayBase`]***
///
/// [`ArrayBase`]: struct.ArrayBase.html
impl<'a, A, D> CowArray<'a, A, D>
where
D: Dimension,
{
/// Returns `true` iff the array is the view (borrowed) variant.
pub fn is_view(&self) -> bool {
self.data.is_view()
}

/// Returns `true` iff the array is the owned variant.
pub fn is_owned(&self) -> bool {
self.data.is_owned()
}
}

impl<'a, A, D> From<ArrayView<'a, A, D>> for CowArray<'a, A, D>
where
D: Dimension,
{
fn from(view: ArrayView<'a, A, D>) -> CowArray<'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 CowArray<'a, A, D>
where
D: Dimension,
{
fn from(array: Array<A, D>) -> CowArray<'a, A, D> {
ArrayBase {
data: CowRepr::Owned(array.data),
ptr: array.ptr,
dim: array.dim,
strides: array.strides,
}
}
}

0 comments on commit 5b5d898

Please sign in to comment.