operator_div.hpp 8.3 KB

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