66// option. This file may not be copied, modified, or distributed
77// except according to those terms.
88
9+ use crate :: dimension:: BroadcastShape ;
910use num_complex:: Complex ;
1011
1112/// Elements that can be used as direct operands in arithmetic with arrays.
@@ -53,24 +54,48 @@ macro_rules! impl_binary_op(
5354/// Perform elementwise
5455 #[ doc=$doc]
5556/// between `self` and `rhs`,
56- /// and return the result (based on `self`).
57- ///
58- /// `self` must be an `Array` or `ArcArray`.
57+ /// and return the result.
5958///
60- /// If their shapes disagree, `rhs` is broadcast to the shape of `self`.
59+ /// If their shapes disagree, `self` is broadcast to their broadcast shape,
60+ /// cloning the data if needed.
6161///
6262/// **Panics** if broadcasting isn’t possible.
6363impl <A , B , S , S2 , D , E > $trt<ArrayBase <S2 , E >> for ArrayBase <S , D >
6464where
6565 A : Clone + $trt<B , Output =A >,
6666 B : Clone ,
67- S : DataOwned <Elem =A > + DataMut ,
67+ S : Data <Elem =A >,
6868 S2 : Data <Elem =B >,
69- D : Dimension ,
69+ D : Dimension + BroadcastShape < E > ,
7070 E : Dimension ,
7171{
72- type Output = ArrayBase <S , D >;
73- fn $mth( self , rhs: ArrayBase <S2 , E >) -> ArrayBase <S , D >
72+ type Output = Array <A , <D as BroadcastShape <E >>:: BroadcastOutput >;
73+ fn $mth( self , rhs: ArrayBase <S2 , E >) -> Self :: Output
74+ {
75+ self . $mth( & rhs)
76+ }
77+ }
78+
79+ /// Perform elementwise
80+ #[ doc=$doc]
81+ /// between reference `self` and `rhs`,
82+ /// and return the result as a new `Array`.
83+ ///
84+ /// If their shapes disagree, `self` is broadcast to their broadcast shape,
85+ /// cloning the data if needed.
86+ ///
87+ /// **Panics** if broadcasting isn’t possible.
88+ impl <' a, A , B , S , S2 , D , E > $trt<ArrayBase <S2 , E >> for & ' a ArrayBase <S , D >
89+ where
90+ A : Clone + $trt<B , Output =A >,
91+ B : Clone ,
92+ S : Data <Elem =A >,
93+ S2 : Data <Elem =B >,
94+ D : Dimension + BroadcastShape <E >,
95+ E : Dimension ,
96+ {
97+ type Output = Array <A , <D as BroadcastShape <E >>:: BroadcastOutput >;
98+ fn $mth( self , rhs: ArrayBase <S2 , E >) -> Self :: Output
7499 {
75100 self . $mth( & rhs)
76101 }
@@ -79,27 +104,34 @@ where
79104/// Perform elementwise
80105 #[ doc=$doc]
81106/// between `self` and reference `rhs`,
82- /// and return the result (based on `self`) .
107+ /// and return the result.
83108///
84- /// If their shapes disagree, `rhs` is broadcast to the shape of `self`.
109+ /// If their shapes disagree, `self` is broadcast to their broadcast shape,
110+ /// cloning the data if needed.
85111///
86112/// **Panics** if broadcasting isn’t possible.
87113impl <' a, A , B , S , S2 , D , E > $trt<& ' a ArrayBase <S2 , E >> for ArrayBase <S , D >
88114where
89115 A : Clone + $trt<B , Output =A >,
90116 B : Clone ,
91- S : DataOwned <Elem =A > + DataMut ,
117+ S : Data <Elem =A >,
92118 S2 : Data <Elem =B >,
93- D : Dimension ,
119+ D : Dimension + BroadcastShape < E > ,
94120 E : Dimension ,
95121{
96- type Output = ArrayBase < S , D >;
97- fn $mth( mut self , rhs: & ArrayBase <S2 , E >) -> ArrayBase < S , D >
122+ type Output = Array < A , < D as BroadcastShape < E >> :: BroadcastOutput >;
123+ fn $mth( self , rhs: & ArrayBase <S2 , E >) -> Self :: Output
98124 {
99- self . zip_mut_with( rhs, |x, y| {
125+ let shape = self . dim. broadcast_shape( & rhs. dim) . unwrap( ) ;
126+ let mut self_ = if shape. slice( ) == self . dim. slice( ) {
127+ self . into_owned( ) . into_dimensionality:: <<D as BroadcastShape <E >>:: BroadcastOutput >( ) . unwrap( )
128+ } else {
129+ self . broadcast( shape) . unwrap( ) . to_owned( )
130+ } ;
131+ self_. zip_mut_with( rhs, |x, y| {
100132 * x = x. clone( ) $operator y. clone( ) ;
101133 } ) ;
102- self
134+ self_
103135 }
104136}
105137
@@ -108,7 +140,8 @@ where
108140/// between references `self` and `rhs`,
109141/// and return the result as a new `Array`.
110142///
111- /// If their shapes disagree, `rhs` is broadcast to the shape of `self`.
143+ /// If their shapes disagree, `self` is broadcast to their broadcast shape,
144+ /// cloning the data if needed.
112145///
113146/// **Panics** if broadcasting isn’t possible.
114147impl <' a, A , B , S , S2 , D , E > $trt<& ' a ArrayBase <S2 , E >> for & ' a ArrayBase <S , D >
@@ -117,13 +150,21 @@ where
117150 B : Clone ,
118151 S : Data <Elem =A >,
119152 S2 : Data <Elem =B >,
120- D : Dimension ,
153+ D : Dimension + BroadcastShape < E > ,
121154 E : Dimension ,
122155{
123- type Output = Array <A , D >;
124- fn $mth( self , rhs: & ' a ArrayBase <S2 , E >) -> Array <A , D > {
125- // FIXME: Can we co-broadcast arrays here? And how?
126- self . to_owned( ) . $mth( rhs)
156+ type Output = Array <A , <D as BroadcastShape <E >>:: BroadcastOutput >;
157+ fn $mth( self , rhs: & ' a ArrayBase <S2 , E >) -> Self :: Output {
158+ let shape = self . dim. broadcast_shape( & rhs. dim) . unwrap( ) ;
159+ let mut self_ = if shape. slice( ) == self . dim. slice( ) {
160+ self . to_owned( ) . into_dimensionality:: <<D as BroadcastShape <E >>:: BroadcastOutput >( ) . unwrap( )
161+ } else {
162+ self . broadcast( shape) . unwrap( ) . to_owned( )
163+ } ;
164+ self_. zip_mut_with( rhs, |x, y| {
165+ * x = x. clone( ) $operator y. clone( ) ;
166+ } ) ;
167+ self_
127168 }
128169}
129170
0 commit comments