Skip to content

Commit 5b5d898

Browse files
Andrewjturner314
Andrew
authored andcommitted
CowArray feature (#632)
1 parent d6ecbf2 commit 5b5d898

File tree

6 files changed

+425
-12
lines changed

6 files changed

+425
-12
lines changed

src/data_traits.rs

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
use std::mem::{self, size_of};
1212
use std::sync::Arc;
1313

14-
use crate::{ArrayBase, Dimension, OwnedArcRepr, OwnedRcRepr, OwnedRepr, RawViewRepr, ViewRepr};
14+
use crate::{
15+
ArrayBase, CowRepr, Dimension, OwnedArcRepr, OwnedRcRepr, OwnedRepr, RawViewRepr, ViewRepr,
16+
};
1517

1618
/// Array representation trait.
1719
///
@@ -423,3 +425,103 @@ unsafe impl<A> DataOwned for OwnedArcRepr<A> {
423425
self
424426
}
425427
}
428+
429+
unsafe impl<'a, A> RawData for CowRepr<'a, A> {
430+
type Elem = A;
431+
fn _data_slice(&self) -> Option<&[A]> {
432+
match self {
433+
CowRepr::View(view) => view._data_slice(),
434+
CowRepr::Owned(data) => data._data_slice(),
435+
}
436+
}
437+
private_impl! {}
438+
}
439+
440+
unsafe impl<'a, A> RawDataMut for CowRepr<'a, A>
441+
where
442+
A: Clone,
443+
{
444+
#[inline]
445+
fn try_ensure_unique<D>(array: &mut ArrayBase<Self, D>)
446+
where
447+
Self: Sized,
448+
D: Dimension,
449+
{
450+
match array.data {
451+
CowRepr::View(_) => {
452+
let owned = array.to_owned();
453+
array.data = CowRepr::Owned(owned.data);
454+
array.ptr = owned.ptr;
455+
array.dim = owned.dim;
456+
array.strides = owned.strides;
457+
}
458+
CowRepr::Owned(_) => {}
459+
}
460+
}
461+
462+
#[inline]
463+
fn try_is_unique(&mut self) -> Option<bool> {
464+
Some(self.is_owned())
465+
}
466+
}
467+
468+
unsafe impl<'a, A> RawDataClone for CowRepr<'a, A>
469+
where
470+
A: Clone,
471+
{
472+
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
473+
match self {
474+
CowRepr::View(view) => {
475+
let (new_view, ptr) = view.clone_with_ptr(ptr);
476+
(CowRepr::View(new_view), ptr)
477+
}
478+
CowRepr::Owned(data) => {
479+
let (new_data, ptr) = data.clone_with_ptr(ptr);
480+
(CowRepr::Owned(new_data), ptr)
481+
}
482+
}
483+
}
484+
485+
#[doc(hidden)]
486+
unsafe fn clone_from_with_ptr(
487+
&mut self,
488+
other: &Self,
489+
ptr: *mut Self::Elem,
490+
) -> *mut Self::Elem {
491+
match (&mut *self, other) {
492+
(CowRepr::View(self_), CowRepr::View(other)) => self_.clone_from_with_ptr(other, ptr),
493+
(CowRepr::Owned(self_), CowRepr::Owned(other)) => self_.clone_from_with_ptr(other, ptr),
494+
(_, CowRepr::Owned(other)) => {
495+
let (cloned, ptr) = other.clone_with_ptr(ptr);
496+
*self = CowRepr::Owned(cloned);
497+
ptr
498+
}
499+
(_, CowRepr::View(other)) => {
500+
let (cloned, ptr) = other.clone_with_ptr(ptr);
501+
*self = CowRepr::View(cloned);
502+
ptr
503+
}
504+
}
505+
}
506+
}
507+
508+
unsafe impl<'a, A> Data for CowRepr<'a, A> {
509+
#[inline]
510+
fn into_owned<D>(self_: ArrayBase<CowRepr<'a, A>, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
511+
where
512+
A: Clone,
513+
D: Dimension,
514+
{
515+
match self_.data {
516+
CowRepr::View(_) => self_.to_owned(),
517+
CowRepr::Owned(data) => ArrayBase {
518+
data,
519+
ptr: self_.ptr,
520+
dim: self_.dim,
521+
strides: self_.strides,
522+
},
523+
}
524+
}
525+
}
526+
527+
unsafe impl<'a, A> DataMut for CowRepr<'a, A> where A: Clone {}

src/doc/ndarray_for_numpy_users/mod.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,11 @@
7272
//! In `ndarray`, all arrays are instances of [`ArrayBase`][ArrayBase], but
7373
//! `ArrayBase` is generic over the ownership of the data. [`Array`][Array]
7474
//! owns its data; [`ArrayView`][ArrayView] is a view;
75-
//! [`ArrayViewMut`][ArrayViewMut] is a mutable view; and
76-
//! [`ArcArray`][ArcArray] has a reference-counted pointer to its data (with
77-
//! copy-on-write mutation). Arrays and views follow Rust's aliasing rules.
75+
//! [`ArrayViewMut`][ArrayViewMut] is a mutable view; [`CowArray`][CowArray]
76+
//! either owns its data or is a view (with copy-on-write mutation of the view
77+
//! variant); and [`ArcArray`][ArcArray] has a reference-counted pointer to its
78+
//! data (with copy-on-write mutation). Arrays and views follow Rust's aliasing
79+
//! rules.
7880
//!
7981
//! </td>
8082
//! </tr>
@@ -572,6 +574,7 @@
572574
//! [.cols()]: ../../struct.ArrayBase.html#method.cols
573575
//! [.column()]: ../../struct.ArrayBase.html#method.column
574576
//! [.column_mut()]: ../../struct.ArrayBase.html#method.column_mut
577+
//! [CowArray]: ../../type.CowArray.html
575578
//! [::default()]: ../../struct.ArrayBase.html#method.default
576579
//! [.diag()]: ../../struct.ArrayBase.html#method.diag
577580
//! [.dim()]: ../../struct.ArrayBase.html#method.dim

src/impl_cow.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2019 ndarray developers.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
use crate::imp_prelude::*;
10+
11+
/// Methods specific to `CowArray`.
12+
///
13+
/// ***See also all methods for [`ArrayBase`]***
14+
///
15+
/// [`ArrayBase`]: struct.ArrayBase.html
16+
impl<'a, A, D> CowArray<'a, A, D>
17+
where
18+
D: Dimension,
19+
{
20+
/// Returns `true` iff the array is the view (borrowed) variant.
21+
pub fn is_view(&self) -> bool {
22+
self.data.is_view()
23+
}
24+
25+
/// Returns `true` iff the array is the owned variant.
26+
pub fn is_owned(&self) -> bool {
27+
self.data.is_owned()
28+
}
29+
}
30+
31+
impl<'a, A, D> From<ArrayView<'a, A, D>> for CowArray<'a, A, D>
32+
where
33+
D: Dimension,
34+
{
35+
fn from(view: ArrayView<'a, A, D>) -> CowArray<'a, A, D> {
36+
ArrayBase {
37+
data: CowRepr::View(view.data),
38+
ptr: view.ptr,
39+
dim: view.dim,
40+
strides: view.strides,
41+
}
42+
}
43+
}
44+
45+
impl<'a, A, D> From<Array<A, D>> for CowArray<'a, A, D>
46+
where
47+
D: Dimension,
48+
{
49+
fn from(array: Array<A, D>) -> CowArray<'a, A, D> {
50+
ArrayBase {
51+
data: CowRepr::Owned(array.data),
52+
ptr: array.ptr,
53+
dim: array.dim,
54+
strides: array.strides,
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)