diff --git a/src/impl_ops.rs b/src/impl_ops.rs index 4804356e8..23ccd6ddb 100644 --- a/src/impl_ops.rs +++ b/src/impl_ops.rs @@ -53,9 +53,7 @@ macro_rules! impl_binary_op( /// Perform elementwise #[doc=$doc] /// between `self` and `rhs`, -/// and return the result (based on `self`). -/// -/// `self` must be an `Array` or `ArcArray`. +/// and return the result. /// /// If their shapes disagree, `rhs` is broadcast to the shape of `self`. /// @@ -64,13 +62,13 @@ impl $trt> for ArrayBase where A: Clone + $trt, B: Clone, - S: DataOwned + DataMut, + S: Data, S2: Data, D: Dimension, E: Dimension, { - type Output = ArrayBase; - fn $mth(self, rhs: ArrayBase) -> ArrayBase + type Output = Array; + fn $mth(self, rhs: ArrayBase) -> Array { self.$mth(&rhs) } @@ -79,7 +77,7 @@ where /// Perform elementwise #[doc=$doc] /// between `self` and reference `rhs`, -/// and return the result (based on `self`). +/// and return the result. /// /// If their shapes disagree, `rhs` is broadcast to the shape of `self`. /// @@ -88,18 +86,19 @@ impl<'a, A, B, S, S2, D, E> $trt<&'a ArrayBase> for ArrayBase where A: Clone + $trt, B: Clone, - S: DataOwned + DataMut, + S: Data, S2: Data, D: Dimension, E: Dimension, { - type Output = ArrayBase; - fn $mth(mut self, rhs: &ArrayBase) -> ArrayBase + type Output = Array; + fn $mth(self, rhs: &ArrayBase) -> Array { - self.zip_mut_with(rhs, |x, y| { + let mut lhs = self.into_owned(); + lhs.zip_mut_with(rhs, |x, y| { *x = x.clone() $operator y.clone(); }); - self + lhs } } @@ -129,22 +128,45 @@ where /// Perform elementwise #[doc=$doc] -/// between `self` and the scalar `x`, -/// and return the result (based on `self`). +/// between `self` and `rhs`, +/// and return the result as a new `Array`. +/// +/// If their shapes disagree, `rhs` is broadcast to the shape of `self`. /// -/// `self` must be an `Array` or `ArcArray`. +/// **Panics** if broadcasting isn’t possible. +impl<'a, A, B, S, S2, D, E> $trt> for &'a ArrayBase +where + A: Clone + $trt, + B: Clone, + S: Data, + S2: Data, + D: Dimension, + E: Dimension, +{ + type Output = Array; + fn $mth(self, rhs: ArrayBase) -> Array { + // FIXME: Can we co-broadcast arrays here? And how? + self.to_owned().$mth(rhs) + } +} + +/// Perform elementwise +#[doc=$doc] +/// between `self` and the scalar `x`, +/// and return the result. impl $trt for ArrayBase where A: Clone + $trt, - S: DataOwned + DataMut, + S: Data, D: Dimension, B: ScalarOperand, { - type Output = ArrayBase; - fn $mth(mut self, x: B) -> ArrayBase { - self.unordered_foreach_mut(move |elt| { + type Output = Array; + fn $mth(self, x: B) -> Array { + let mut lhs = self.into_owned(); + lhs.unordered_foreach_mut(move |elt| { *elt = elt.clone() $operator x.clone(); }); - self + lhs } } @@ -183,17 +205,17 @@ macro_rules! impl_scalar_lhs_op { // these have no doc -- they are not visible in rustdoc // Perform elementwise // between the scalar `self` and array `rhs`, -// and return the result (based on `self`). +// and return the result. impl $trt> for $scalar - where S: DataOwned + DataMut, + where S: Data, D: Dimension, { - type Output = ArrayBase; - fn $mth(self, rhs: ArrayBase) -> ArrayBase { + type Output = Array<$scalar, D>; + fn $mth(self, rhs: ArrayBase) -> Array<$scalar, D> { if_commutative!($commutative { rhs.$mth(self) } or {{ - let mut rhs = rhs; + let mut rhs = rhs.into_owned(); rhs.unordered_foreach_mut(move |elt| { *elt = self $operator *elt; }); @@ -293,16 +315,17 @@ mod arithmetic_ops { impl Neg for ArrayBase where A: Clone + Neg, - S: DataOwned + DataMut, + S: Data, D: Dimension, { - type Output = Self; + type Output = Array; /// Perform an elementwise negation of `self` and return the result. - fn neg(mut self) -> Self { - self.unordered_foreach_mut(|elt| { + fn neg(self) -> Array { + let mut array = self.into_owned(); + array.unordered_foreach_mut(|elt| { *elt = -elt.clone(); }); - self + array } } @@ -323,16 +346,17 @@ mod arithmetic_ops { impl Not for ArrayBase where A: Clone + Not, - S: DataOwned + DataMut, + S: Data, D: Dimension, { - type Output = Self; + type Output = Array; /// Perform an elementwise unary not of `self` and return the result. - fn not(mut self) -> Self { - self.unordered_foreach_mut(|elt| { + fn not(self) -> Array { + let mut array = self.into_owned(); + array.unordered_foreach_mut(|elt| { *elt = !elt.clone(); }); - self + array } } @@ -359,6 +383,23 @@ mod assign_ops { ($trt:ident, $method:ident, $doc:expr) => { use std::ops::$trt; + #[doc=$doc] + /// If their shapes disagree, `rhs` is broadcast to the shape of `self`. + /// + /// **Panics** if broadcasting isn’t possible. + impl $trt> for ArrayBase + where + A: Clone + $trt, + S: DataMut, + S2: Data, + D: Dimension, + E: Dimension, + { + fn $method(&mut self, rhs: ArrayBase) { + self.$method(&rhs) + } + } + #[doc=$doc] /// If their shapes disagree, `rhs` is broadcast to the shape of `self`. /// diff --git a/src/lib.rs b/src/lib.rs index 35d1e1aab..ca63b8dd8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -607,18 +607,14 @@ pub type Ixs = isize; /// /// ### Binary Operators with Two Arrays /// -/// Let `A` be an array or view of any kind. Let `B` be an array -/// with owned storage (either `Array` or `ArcArray`). -/// Let `C` be an array with mutable data (either `Array`, `ArcArray` -/// or `ArrayViewMut`). -/// The following combinations of operands -/// are supported for an arbitrary binary operator denoted by `@` (it can be -/// `+`, `-`, `*`, `/` and so on). -/// -/// - `&A @ &A` which produces a new `Array` -/// - `B @ A` which consumes `B`, updates it with the result, and returns it -/// - `B @ &A` which consumes `B`, updates it with the result, and returns it -/// - `C @= &A` which performs an arithmetic operation in place +/// Let `A` be an array or view of any kind. Let `M` be an array with mutable +/// data (either `Array`, `ArcArray` or `ArrayViewMut`). The following +/// combinations of operands are supported for an arbitrary binary operator +/// denoted by `@` (it can be `+`, `-`, `*`, `/` and so on). +/// +/// - `&A @ &A` or `&A @ A` which produce a new `Array` +/// - `A @ &A` or `A @ A` which may reuse the allocation of the LHS if it's an owned array +/// - `M @= &A` or `M @= A` which performs an arithmetic operation in place on `M` /// /// Note that the element type needs to implement the operator trait and the /// `Clone` trait. @@ -647,17 +643,16 @@ pub type Ixs = isize; /// `ScalarOperand` docs has the detailed condtions). /// /// - `&A @ K` or `K @ &A` which produces a new `Array` -/// - `B @ K` or `K @ B` which consumes `B`, updates it with the result and returns it -/// - `C @= K` which performs an arithmetic operation in place +/// - `A @ K` or `K @ A` which may reuse the allocation of the array if it's an owned array +/// - `M @= K` which performs an arithmetic operation in place /// /// ### Unary Operators /// -/// Let `A` be an array or view of any kind. Let `B` be an array with owned -/// storage (either `Array` or `ArcArray`). The following operands are supported -/// for an arbitrary unary operator denoted by `@` (it can be `-` or `!`). +/// The following operands are supported for an arbitrary unary operator +/// denoted by `@` (it can be `-` or `!`). /// /// - `@&A` which produces a new `Array` -/// - `@B` which consumes `B`, updates it with the result, and returns it +/// - `@A` which may reuse the allocation of the array if it's an owned array /// /// ## Broadcasting /// diff --git a/tests/array.rs b/tests/array.rs index ea374bc7c..4c997798d 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -394,11 +394,11 @@ fn test_add() { } let B = A.clone(); - A = A + &B; - assert_eq!(A[[0, 0]], 0); - assert_eq!(A[[0, 1]], 2); - assert_eq!(A[[1, 0]], 4); - assert_eq!(A[[1, 1]], 6); + let C = A + &B; + assert_eq!(C[[0, 0]], 0); + assert_eq!(C[[0, 1]], 2); + assert_eq!(C[[1, 0]], 4); + assert_eq!(C[[1, 1]], 6); } #[test] pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy