Skip to content

Commit 8cd5d5a

Browse files
author
Andrew
authored
Merge pull request rust-ndarray#8 from rust-ndarray/master
Update master
2 parents efd686d + 5b5d898 commit 8cd5d5a

File tree

7 files changed

+458
-24
lines changed

7 files changed

+458
-24
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/dimension/mod.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -375,18 +375,29 @@ pub fn do_slice(dim: &mut usize, stride: &mut usize, slice: Slice) -> isize {
375375
let m = end - start;
376376
let s = (*stride) as isize;
377377

378-
// Data pointer offset
379-
let mut offset = stride_offset(start, *stride);
380-
// Adjust for strides
381-
//
382-
// How to implement negative strides:
383-
//
384-
// Increase start pointer by
385-
// old stride * (old dim - 1)
386-
// to put the pointer completely in the other end
387-
if step < 0 {
388-
offset += stride_offset(m - 1, *stride);
389-
}
378+
// Compute data pointer offset.
379+
let offset = if m == 0 {
380+
// In this case, the resulting array is empty, so we *can* avoid performing a nonzero
381+
// offset.
382+
//
383+
// In two special cases (which are the true reason for this `m == 0` check), we *must* avoid
384+
// the nonzero offset corresponding to the general case.
385+
//
386+
// * When `end == 0 && step < 0`. (These conditions imply that `m == 0` since `to_abs_slice`
387+
// ensures that `0 <= start <= end`.) We cannot execute `stride_offset(end - 1, *stride)`
388+
// because the `end - 1` would underflow.
389+
//
390+
// * When `start == *dim && step > 0`. (These conditions imply that `m == 0` since
391+
// `to_abs_slice` ensures that `start <= end <= *dim`.) We cannot use the offset returned
392+
// by `stride_offset(start, *stride)` because that would be past the end of the axis.
393+
0
394+
} else if step < 0 {
395+
// When the step is negative, the new first element is `end - 1`, not `start`, since the
396+
// direction is reversed.
397+
stride_offset(end - 1, *stride)
398+
} else {
399+
stride_offset(start, *stride)
400+
};
390401

391402
// Update dimension.
392403
let abs_step = step.abs() as usize;

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)