1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17
18
19 //! \addtogroup operator_div
20 //! @{
21
22
23
24 //! Base / scalar
25 template<typename T1>
26 arma_inline
27 typename
28 enable_if2< is_arma_type<T1>::value, const eOp< T1, eop_scalar_div_post> >::result
operator /(const T1 & X,const typename T1::elem_type k)29 operator/
30 (
31 const T1& X,
32 const typename T1::elem_type k
33 )
34 {
35 arma_extra_debug_sigprint();
36
37 return eOp<T1, eop_scalar_div_post>(X, k);
38 }
39
40
41
42 //! scalar / Base
43 template<typename T1>
44 arma_inline
45 typename
46 enable_if2< is_arma_type<T1>::value, const eOp< T1, eop_scalar_div_pre> >::result
operator /(const typename T1::elem_type k,const T1 & X)47 operator/
48 (
49 const typename T1::elem_type k,
50 const T1& X
51 )
52 {
53 arma_extra_debug_sigprint();
54
55 return eOp<T1, eop_scalar_div_pre>(X, k);
56 }
57
58
59
60 //! complex scalar / non-complex Base
61 template<typename T1>
62 arma_inline
63 typename
64 enable_if2
65 <
66 (is_arma_type<T1>::value && is_cx<typename T1::elem_type>::no),
67 const mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_div_pre>
68 >::result
operator /(const std::complex<typename T1::pod_type> & k,const T1 & X)69 operator/
70 (
71 const std::complex<typename T1::pod_type>& k,
72 const T1& X
73 )
74 {
75 arma_extra_debug_sigprint();
76
77 return mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_div_pre>('j', X, k);
78 }
79
80
81
82 //! non-complex Base / complex scalar
83 template<typename T1>
84 arma_inline
85 typename
86 enable_if2
87 <
88 (is_arma_type<T1>::value && is_cx<typename T1::elem_type>::no),
89 const mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_div_post>
90 >::result
operator /(const T1 & X,const std::complex<typename T1::pod_type> & k)91 operator/
92 (
93 const T1& X,
94 const std::complex<typename T1::pod_type>& k
95 )
96 {
97 arma_extra_debug_sigprint();
98
99 return mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_div_post>('j', X, k);
100 }
101
102
103
104 //! element-wise division of Base objects with same element type
105 template<typename T1, typename T2>
106 arma_inline
107 typename
108 enable_if2
109 <
110 (is_arma_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
111 const eGlue<T1, T2, eglue_div>
112 >::result
operator /(const T1 & X,const T2 & Y)113 operator/
114 (
115 const T1& X,
116 const T2& Y
117 )
118 {
119 arma_extra_debug_sigprint();
120
121 return eGlue<T1, T2, eglue_div>(X, Y);
122 }
123
124
125
126 //! element-wise division of Base objects with different element types
127 template<typename T1, typename T2>
128 inline
129 typename
130 enable_if2
131 <
132 (is_arma_type<T1>::value && is_arma_type<T2>::value && (is_same_type<typename T1::elem_type, typename T2::elem_type>::no)),
133 const mtGlue<typename promote_type<typename T1::elem_type, typename T2::elem_type>::result, T1, T2, glue_mixed_div>
134 >::result
operator /(const T1 & X,const T2 & Y)135 operator/
136 (
137 const T1& X,
138 const T2& Y
139 )
140 {
141 arma_extra_debug_sigprint();
142
143 typedef typename T1::elem_type eT1;
144 typedef typename T2::elem_type eT2;
145
146 typedef typename promote_type<eT1,eT2>::result out_eT;
147
148 promote_type<eT1,eT2>::check();
149
150 return mtGlue<out_eT, T1, T2, glue_mixed_div>( X, Y );
151 }
152
153
154
155 //! element-wise division of sparse matrix by scalar
156 template<typename T1>
157 inline
158 typename
159 enable_if2< is_arma_sparse_type<T1>::value, SpMat<typename T1::elem_type> >::result
operator /(const T1 & X,const typename T1::elem_type y)160 operator/
161 (
162 const T1& X,
163 const typename T1::elem_type y
164 )
165 {
166 arma_extra_debug_sigprint();
167
168 SpMat<typename T1::elem_type> result(X);
169
170 result /= y;
171
172 return result;
173 }
174
175
176
177 //! element-wise division of one sparse and one dense object
178 template<typename T1, typename T2>
179 inline
180 typename
181 enable_if2
182 <
183 (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
184 SpMat<typename T1::elem_type>
185 >::result
operator /(const T1 & x,const T2 & y)186 operator/
187 (
188 const T1& x,
189 const T2& y
190 )
191 {
192 arma_extra_debug_sigprint();
193
194 typedef typename T1::elem_type eT;
195
196 const SpProxy<T1> pa(x);
197 const Proxy<T2> pb(y);
198
199 const uword n_rows = pa.get_n_rows();
200 const uword n_cols = pa.get_n_cols();
201
202 arma_debug_assert_same_size(n_rows, n_cols, pb.get_n_rows(), pb.get_n_cols(), "element-wise division");
203
204 uword new_n_nonzero = 0;
205
206 for(uword col=0; col < n_cols; ++col)
207 for(uword row=0; row < n_rows; ++row)
208 {
209 const eT val = pa.at(row,col) / pb.at(row, col);
210
211 if(val != eT(0))
212 {
213 ++new_n_nonzero;
214 }
215 }
216
217 SpMat<eT> result(arma_reserve_indicator(), n_rows, n_cols, new_n_nonzero);
218
219 uword cur_pos = 0;
220
221 for(uword col=0; col < n_cols; ++col)
222 for(uword row=0; row < n_rows; ++row)
223 {
224 const eT val = pa.at(row,col) / pb.at(row, col);
225
226 if(val != eT(0))
227 {
228 access::rw(result.values[cur_pos]) = val;
229 access::rw(result.row_indices[cur_pos]) = row;
230 ++access::rw(result.col_ptrs[col + 1]);
231 ++cur_pos;
232 }
233 }
234
235 // Fix column pointers
236 for(uword col = 1; col <= result.n_cols; ++col)
237 {
238 access::rw(result.col_ptrs[col]) += result.col_ptrs[col - 1];
239 }
240
241 return result;
242 }
243
244
245
246 //! optimization: element-wise division of sparse / (sparse +/- scalar)
247 template<typename T1, typename T2, typename op_type>
248 inline
249 typename
250 enable_if2
251 <
252 (
253 is_arma_sparse_type<T1>::value && is_arma_sparse_type<T2>::value &&
254 is_same_type<typename T1::elem_type, typename T2::elem_type>::yes &&
255 (is_same_type<op_type, op_sp_plus>::value ||
256 is_same_type<op_type, op_sp_minus_pre>::value ||
257 is_same_type<op_type, op_sp_minus_post>::value)
258 ),
259 SpMat<typename T1::elem_type>
260 >::result
operator /(const T1 & x,const SpToDOp<T2,op_type> & y)261 operator/
262 (
263 const T1& x,
264 const SpToDOp<T2, op_type>& y
265 )
266 {
267 arma_extra_debug_sigprint();
268
269 SpMat<typename T1::elem_type> out;
270
271 op_type::apply_inside_div(out, x, y);
272
273 return out;
274 }
275
276
277
278 //! element-wise division of one dense and one sparse object
279 template<typename T1, typename T2>
280 inline
281 typename
282 enable_if2
283 <
284 (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
285 Mat<typename T1::elem_type>
286 >::result
operator /(const T1 & x,const T2 & y)287 operator/
288 (
289 const T1& x,
290 const T2& y
291 )
292 {
293 arma_extra_debug_sigprint();
294
295 typedef typename T1::elem_type eT;
296
297 const Proxy<T1> pa(x);
298 const SpProxy<T2> pb(y);
299
300 const uword n_rows = pa.get_n_rows();
301 const uword n_cols = pa.get_n_cols();
302
303 arma_debug_assert_same_size(n_rows, n_cols, pb.get_n_rows(), pb.get_n_cols(), "element-wise division");
304
305 Mat<eT> result(n_rows, n_cols, arma_nozeros_indicator());
306
307 for(uword col=0; col < n_cols; ++col)
308 for(uword row=0; row < n_rows; ++row)
309 {
310 result.at(row, col) = pa.at(row, col) / pb.at(row, col);
311 }
312
313 return result;
314 }
315
316
317
318 template<typename parent, unsigned int mode, typename T2>
319 arma_inline
320 Mat<typename parent::elem_type>
operator /(const subview_each1<parent,mode> & X,const Base<typename parent::elem_type,T2> & Y)321 operator/
322 (
323 const subview_each1<parent,mode>& X,
324 const Base<typename parent::elem_type,T2>& Y
325 )
326 {
327 arma_extra_debug_sigprint();
328
329 return subview_each1_aux::operator_div(X, Y.get_ref());
330 }
331
332
333
334 template<typename T1, typename parent, unsigned int mode>
335 arma_inline
336 Mat<typename parent::elem_type>
operator /(const Base<typename parent::elem_type,T1> & X,const subview_each1<parent,mode> & Y)337 operator/
338 (
339 const Base<typename parent::elem_type,T1>& X,
340 const subview_each1<parent,mode>& Y
341 )
342 {
343 arma_extra_debug_sigprint();
344
345 return subview_each1_aux::operator_div(X.get_ref(), Y);
346 }
347
348
349
350 template<typename parent, unsigned int mode, typename TB, typename T2>
351 arma_inline
352 Mat<typename parent::elem_type>
operator /(const subview_each2<parent,mode,TB> & X,const Base<typename parent::elem_type,T2> & Y)353 operator/
354 (
355 const subview_each2<parent,mode,TB>& X,
356 const Base<typename parent::elem_type,T2>& Y
357 )
358 {
359 arma_extra_debug_sigprint();
360
361 return subview_each2_aux::operator_div(X, Y.get_ref());
362 }
363
364
365
366 template<typename T1, typename parent, unsigned int mode, typename TB>
367 arma_inline
368 Mat<typename parent::elem_type>
operator /(const Base<typename parent::elem_type,T1> & X,const subview_each2<parent,mode,TB> & Y)369 operator/
370 (
371 const Base<typename parent::elem_type,T1>& X,
372 const subview_each2<parent,mode,TB>& Y
373 )
374 {
375 arma_extra_debug_sigprint();
376
377 return subview_each2_aux::operator_div(X.get_ref(), Y);
378 }
379
380
381
382 //! @}
383