operator_plus.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  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_plus
  16. //! @{
  17. //! unary plus operation (does nothing, but is required for completeness)
  18. template<typename T1>
  19. arma_inline
  20. typename enable_if2< is_arma_type<T1>::value, const T1& >::result
  21. operator+
  22. (const T1& X)
  23. {
  24. arma_extra_debug_sigprint();
  25. return X;
  26. }
  27. //! Base + scalar
  28. template<typename T1>
  29. arma_inline
  30. typename enable_if2< is_arma_type<T1>::value, const eOp<T1, eop_scalar_plus> >::result
  31. operator+
  32. (const T1& X, const typename T1::elem_type k)
  33. {
  34. arma_extra_debug_sigprint();
  35. return eOp<T1, eop_scalar_plus>(X, k);
  36. }
  37. //! scalar + Base
  38. template<typename T1>
  39. arma_inline
  40. typename enable_if2< is_arma_type<T1>::value, const eOp<T1, eop_scalar_plus> >::result
  41. operator+
  42. (const typename T1::elem_type k, const T1& X)
  43. {
  44. arma_extra_debug_sigprint();
  45. return eOp<T1, eop_scalar_plus>(X, k); // NOTE: order is swapped
  46. }
  47. //! non-complex Base + complex scalar
  48. template<typename T1>
  49. arma_inline
  50. typename
  51. enable_if2
  52. <
  53. (is_arma_type<T1>::value && is_cx<typename T1::elem_type>::no),
  54. const mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_plus>
  55. >::result
  56. operator+
  57. (
  58. const T1& X,
  59. const std::complex<typename T1::pod_type>& k
  60. )
  61. {
  62. arma_extra_debug_sigprint();
  63. return mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_plus>('j', X, k);
  64. }
  65. //! complex scalar + non-complex Base
  66. template<typename T1>
  67. arma_inline
  68. typename
  69. enable_if2
  70. <
  71. (is_arma_type<T1>::value && is_cx<typename T1::elem_type>::no),
  72. const mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_plus>
  73. >::result
  74. operator+
  75. (
  76. const std::complex<typename T1::pod_type>& k,
  77. const T1& X
  78. )
  79. {
  80. arma_extra_debug_sigprint();
  81. return mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_plus>('j', X, k); // NOTE: order is swapped
  82. }
  83. //! addition of user-accessible Armadillo objects with same element type
  84. template<typename T1, typename T2>
  85. arma_inline
  86. typename
  87. enable_if2
  88. <
  89. is_arma_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value,
  90. const eGlue<T1, T2, eglue_plus>
  91. >::result
  92. operator+
  93. (
  94. const T1& X,
  95. const T2& Y
  96. )
  97. {
  98. arma_extra_debug_sigprint();
  99. return eGlue<T1, T2, eglue_plus>(X, Y);
  100. }
  101. //! addition of user-accessible Armadillo objects with different element types
  102. template<typename T1, typename T2>
  103. inline
  104. typename
  105. enable_if2
  106. <
  107. (is_arma_type<T1>::value && is_arma_type<T2>::value && (is_same_type<typename T1::elem_type, typename T2::elem_type>::no)),
  108. const mtGlue<typename promote_type<typename T1::elem_type, typename T2::elem_type>::result, T1, T2, glue_mixed_plus>
  109. >::result
  110. operator+
  111. (
  112. const T1& X,
  113. const T2& Y
  114. )
  115. {
  116. arma_extra_debug_sigprint();
  117. typedef typename T1::elem_type eT1;
  118. typedef typename T2::elem_type eT2;
  119. typedef typename promote_type<eT1,eT2>::result out_eT;
  120. promote_type<eT1,eT2>::check();
  121. return mtGlue<out_eT, T1, T2, glue_mixed_plus>( X, Y );
  122. }
  123. //! addition of two sparse objects
  124. template<typename T1, typename T2>
  125. inline
  126. typename
  127. enable_if2
  128. <
  129. (is_arma_sparse_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
  130. SpGlue<T1,T2,spglue_plus>
  131. >::result
  132. operator+
  133. (
  134. const T1& x,
  135. const T2& y
  136. )
  137. {
  138. arma_extra_debug_sigprint();
  139. return SpGlue<T1,T2,spglue_plus>(x, y);
  140. }
  141. //! addition of one dense and one sparse object
  142. template<typename T1, typename T2>
  143. inline
  144. typename
  145. enable_if2
  146. <
  147. (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
  148. Mat<typename T1::elem_type>
  149. >::result
  150. operator+
  151. (
  152. const T1& x,
  153. const T2& y
  154. )
  155. {
  156. arma_extra_debug_sigprint();
  157. Mat<typename T1::elem_type> result(x);
  158. const SpProxy<T2> pb(y);
  159. arma_debug_assert_same_size( result.n_rows, result.n_cols, pb.get_n_rows(), pb.get_n_cols(), "addition" );
  160. typename SpProxy<T2>::const_iterator_type it = pb.begin();
  161. typename SpProxy<T2>::const_iterator_type it_end = pb.end();
  162. while(it != it_end)
  163. {
  164. result.at(it.row(), it.col()) += (*it);
  165. ++it;
  166. }
  167. return result;
  168. }
  169. //! addition of one sparse and one dense object
  170. template<typename T1, typename T2>
  171. inline
  172. typename
  173. enable_if2
  174. <
  175. (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
  176. Mat<typename T1::elem_type>
  177. >::result
  178. operator+
  179. (
  180. const T1& x,
  181. const T2& y
  182. )
  183. {
  184. arma_extra_debug_sigprint();
  185. const SpProxy<T1> pa(x);
  186. Mat<typename T1::elem_type> result(y);
  187. arma_debug_assert_same_size( pa.get_n_rows(), pa.get_n_cols(), result.n_rows, result.n_cols, "addition" );
  188. typename SpProxy<T1>::const_iterator_type it = pa.begin();
  189. typename SpProxy<T1>::const_iterator_type it_end = pa.end();
  190. while(it != it_end)
  191. {
  192. result.at(it.row(), it.col()) += (*it);
  193. ++it;
  194. }
  195. return result;
  196. }
  197. //! addition of two sparse objects with different element types
  198. template<typename T1, typename T2>
  199. inline
  200. typename
  201. enable_if2
  202. <
  203. (is_arma_sparse_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::no),
  204. const mtSpGlue< typename promote_type<typename T1::elem_type, typename T2::elem_type>::result, T1, T2, spglue_plus_mixed >
  205. >::result
  206. operator+
  207. (
  208. const T1& X,
  209. const T2& Y
  210. )
  211. {
  212. arma_extra_debug_sigprint();
  213. typedef typename T1::elem_type eT1;
  214. typedef typename T2::elem_type eT2;
  215. typedef typename promote_type<eT1,eT2>::result out_eT;
  216. promote_type<eT1,eT2>::check();
  217. return mtSpGlue<out_eT, T1, T2, spglue_plus_mixed>( X, Y );
  218. }
  219. //! addition of sparse and non-sparse objects with different element types
  220. template<typename T1, typename T2>
  221. inline
  222. typename
  223. enable_if2
  224. <
  225. (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::no),
  226. Mat< typename promote_type<typename T1::elem_type, typename T2::elem_type>::result >
  227. >::result
  228. operator+
  229. (
  230. const T1& x,
  231. const T2& y
  232. )
  233. {
  234. arma_extra_debug_sigprint();
  235. Mat< typename promote_type<typename T1::elem_type, typename T2::elem_type>::result > out;
  236. spglue_plus_mixed::dense_plus_sparse(out, x, y);
  237. return out;
  238. }
  239. //! addition of sparse and non-sparse objects with different element types
  240. template<typename T1, typename T2>
  241. inline
  242. typename
  243. enable_if2
  244. <
  245. (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::no),
  246. Mat< typename promote_type<typename T1::elem_type, typename T2::elem_type>::result >
  247. >::result
  248. operator+
  249. (
  250. const T1& x,
  251. const T2& y
  252. )
  253. {
  254. arma_extra_debug_sigprint();
  255. Mat< typename promote_type<typename T1::elem_type, typename T2::elem_type>::result > out;
  256. // Just call the other order (these operations are commutative)
  257. // TODO: if there is a matrix size mismatch, the debug assert will print the matrix sizes in wrong order
  258. spglue_plus_mixed::dense_plus_sparse(out, y, x);
  259. return out;
  260. }
  261. //! addition of sparse object with scalar
  262. template<typename T1>
  263. inline
  264. typename enable_if2< is_arma_sparse_type<T1>::value, const SpToDOp<T1, op_sp_plus> >::result
  265. operator+
  266. (
  267. const T1& X,
  268. const typename T1::elem_type k
  269. )
  270. {
  271. arma_extra_debug_sigprint();
  272. return SpToDOp<T1, op_sp_plus>(X, k);
  273. }
  274. template<typename T1>
  275. inline
  276. typename enable_if2< is_arma_sparse_type<T1>::value, const SpToDOp<T1, op_sp_plus> >::result
  277. operator+
  278. (
  279. const typename T1::elem_type k,
  280. const T1& X
  281. )
  282. {
  283. arma_extra_debug_sigprint();
  284. return SpToDOp<T1, op_sp_plus>(X, k); // NOTE: swapped order
  285. }
  286. // TODO: this is an uncommon use case; remove?
  287. //! multiple applications of add/subtract scalars can be condensed
  288. template<typename T1, typename op_type>
  289. inline
  290. typename
  291. enable_if2
  292. <
  293. (is_arma_sparse_type<T1>::value &&
  294. (is_same_type<op_type, op_sp_plus>::value ||
  295. is_same_type<op_type, op_sp_minus_post>::value)),
  296. const SpToDOp<T1, op_sp_plus>
  297. >::result
  298. operator+
  299. (
  300. const SpToDOp<T1, op_type>& x,
  301. const typename T1::elem_type k
  302. )
  303. {
  304. arma_extra_debug_sigprint();
  305. const typename T1::elem_type aux = (is_same_type<op_type, op_sp_plus>::value) ? x.aux : -x.aux;
  306. return SpToDOp<T1, op_sp_plus>(x.m, aux + k);
  307. }
  308. // TODO: this is an uncommon use case; remove?
  309. //! multiple applications of add/subtract scalars can be condensed
  310. template<typename T1, typename op_type>
  311. inline
  312. typename
  313. enable_if2
  314. <
  315. (is_arma_sparse_type<T1>::value &&
  316. is_same_type<op_type, op_sp_minus_pre>::value),
  317. const SpToDOp<T1, op_sp_minus_pre>
  318. >::result
  319. operator+
  320. (
  321. const SpToDOp<T1, op_type>& x,
  322. const typename T1::elem_type k
  323. )
  324. {
  325. arma_extra_debug_sigprint();
  326. return SpToDOp<T1, op_sp_minus_pre>(x.m, x.aux + k);
  327. }
  328. // TODO: this is an uncommon use case; remove?
  329. //! multiple applications of add/subtract scalars can be condensed
  330. template<typename T1, typename op_type>
  331. inline
  332. typename
  333. enable_if2
  334. <
  335. (is_arma_sparse_type<T1>::value &&
  336. (is_same_type<op_type, op_sp_plus>::value ||
  337. is_same_type<op_type, op_sp_minus_post>::value)),
  338. const SpToDOp<T1, op_sp_plus>
  339. >::result
  340. operator+
  341. (
  342. const typename T1::elem_type k,
  343. const SpToDOp<T1, op_type>& x
  344. )
  345. {
  346. arma_extra_debug_sigprint();
  347. const typename T1::elem_type aux = (is_same_type<op_type, op_sp_plus>::value) ? x.aux : -x.aux;
  348. return SpToDOp<T1, op_sp_plus>(x.m, aux + k);
  349. }
  350. // TODO: this is an uncommon use case; remove?
  351. //! multiple applications of add/subtract scalars can be condensed
  352. template<typename T1, typename op_type>
  353. inline
  354. typename
  355. enable_if2
  356. <
  357. (is_arma_sparse_type<T1>::value &&
  358. is_same_type<op_type, op_sp_minus_pre>::value),
  359. const SpToDOp<T1, op_sp_minus_pre>
  360. >::result
  361. operator+
  362. (
  363. const typename T1::elem_type k,
  364. const SpToDOp<T1, op_type>& x
  365. )
  366. {
  367. arma_extra_debug_sigprint();
  368. return SpToDOp<T1, op_sp_minus_pre>(x.m, x.aux + k);
  369. }
  370. template<typename parent, unsigned int mode, typename T2>
  371. arma_inline
  372. Mat<typename parent::elem_type>
  373. operator+
  374. (
  375. const subview_each1<parent,mode>& X,
  376. const Base<typename parent::elem_type,T2>& Y
  377. )
  378. {
  379. arma_extra_debug_sigprint();
  380. return subview_each1_aux::operator_plus(X, Y.get_ref());
  381. }
  382. template<typename T1, typename parent, unsigned int mode>
  383. arma_inline
  384. Mat<typename parent::elem_type>
  385. operator+
  386. (
  387. const Base<typename parent::elem_type,T1>& X,
  388. const subview_each1<parent,mode>& Y
  389. )
  390. {
  391. arma_extra_debug_sigprint();
  392. return subview_each1_aux::operator_plus(Y, X.get_ref()); // NOTE: swapped order
  393. }
  394. template<typename parent, unsigned int mode, typename TB, typename T2>
  395. arma_inline
  396. Mat<typename parent::elem_type>
  397. operator+
  398. (
  399. const subview_each2<parent,mode,TB>& X,
  400. const Base<typename parent::elem_type,T2>& Y
  401. )
  402. {
  403. arma_extra_debug_sigprint();
  404. return subview_each2_aux::operator_plus(X, Y.get_ref());
  405. }
  406. template<typename T1, typename parent, unsigned int mode, typename TB>
  407. arma_inline
  408. Mat<typename parent::elem_type>
  409. operator+
  410. (
  411. const Base<typename parent::elem_type,T1>& X,
  412. const subview_each2<parent,mode,TB>& Y
  413. )
  414. {
  415. arma_extra_debug_sigprint();
  416. return subview_each2_aux::operator_plus(Y, X.get_ref()); // NOTE: swapped order
  417. }
  418. //! @}