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