6
6
// option. This file may not be copied, modified, or distributed
7
7
// except according to those terms.
8
8
9
+ use crate :: dimension:: BroadcastShape ;
9
10
use num_complex:: Complex ;
10
11
11
12
/// Elements that can be used as direct operands in arithmetic with arrays.
@@ -53,24 +54,48 @@ macro_rules! impl_binary_op(
53
54
/// Perform elementwise
54
55
#[ doc=$doc]
55
56
/// 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.
59
58
///
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.
61
61
///
62
62
/// **Panics** if broadcasting isn’t possible.
63
63
impl <A , B , S , S2 , D , E > $trt<ArrayBase <S2 , E >> for ArrayBase <S , D >
64
64
where
65
65
A : Clone + $trt<B , Output =A >,
66
66
B : Clone ,
67
- S : DataOwned <Elem =A > + DataMut ,
67
+ S : Data <Elem =A >,
68
68
S2 : Data <Elem =B >,
69
- D : Dimension ,
69
+ D : Dimension + BroadcastShape < E > ,
70
70
E : Dimension ,
71
71
{
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
74
99
{
75
100
self . $mth( & rhs)
76
101
}
@@ -79,27 +104,34 @@ where
79
104
/// Perform elementwise
80
105
#[ doc=$doc]
81
106
/// between `self` and reference `rhs`,
82
- /// and return the result (based on `self`) .
107
+ /// and return the result.
83
108
///
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.
85
111
///
86
112
/// **Panics** if broadcasting isn’t possible.
87
113
impl <' a, A , B , S , S2 , D , E > $trt<& ' a ArrayBase <S2 , E >> for ArrayBase <S , D >
88
114
where
89
115
A : Clone + $trt<B , Output =A >,
90
116
B : Clone ,
91
- S : DataOwned <Elem =A > + DataMut ,
117
+ S : Data <Elem =A >,
92
118
S2 : Data <Elem =B >,
93
- D : Dimension ,
119
+ D : Dimension + BroadcastShape < E > ,
94
120
E : Dimension ,
95
121
{
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
98
124
{
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| {
100
132
* x = x. clone( ) $operator y. clone( ) ;
101
133
} ) ;
102
- self
134
+ self_
103
135
}
104
136
}
105
137
@@ -108,7 +140,8 @@ where
108
140
/// between references `self` and `rhs`,
109
141
/// and return the result as a new `Array`.
110
142
///
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.
112
145
///
113
146
/// **Panics** if broadcasting isn’t possible.
114
147
impl <' a, A , B , S , S2 , D , E > $trt<& ' a ArrayBase <S2 , E >> for & ' a ArrayBase <S , D >
@@ -117,13 +150,21 @@ where
117
150
B : Clone ,
118
151
S : Data <Elem =A >,
119
152
S2 : Data <Elem =B >,
120
- D : Dimension ,
153
+ D : Dimension + BroadcastShape < E > ,
121
154
E : Dimension ,
122
155
{
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_
127
168
}
128
169
}
129
170
0 commit comments