SpValProxy_meat.hpp 6.4 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 SpValProxy
  16. //! @{
  17. //! SpValProxy implementation.
  18. template<typename T1>
  19. arma_inline
  20. SpValProxy<T1>::SpValProxy(uword in_row, uword in_col, T1& in_parent, eT* in_val_ptr)
  21. : row(in_row)
  22. , col(in_col)
  23. , val_ptr(in_val_ptr)
  24. , parent(in_parent)
  25. {
  26. // Nothing to do.
  27. }
  28. template<typename T1>
  29. arma_inline
  30. SpValProxy<T1>&
  31. SpValProxy<T1>::operator=(const SpValProxy<T1>& rhs)
  32. {
  33. return (*this).operator=(eT(rhs));
  34. }
  35. template<typename T1>
  36. template<typename T2>
  37. arma_inline
  38. SpValProxy<T1>&
  39. SpValProxy<T1>::operator=(const SpValProxy<T2>& rhs)
  40. {
  41. return (*this).operator=(eT(rhs));
  42. }
  43. template<typename T1>
  44. arma_inline
  45. SpValProxy<T1>&
  46. SpValProxy<T1>::operator=(const eT rhs)
  47. {
  48. if (rhs != eT(0)) // A nonzero element is being assigned.
  49. {
  50. if (val_ptr)
  51. {
  52. // The value exists and merely needs to be updated.
  53. *val_ptr = rhs;
  54. parent.invalidate_cache();
  55. }
  56. else
  57. {
  58. // The value is nonzero and must be inserted.
  59. val_ptr = &parent.insert_element(row, col, rhs);
  60. }
  61. }
  62. else // A zero is being assigned.~
  63. {
  64. if (val_ptr)
  65. {
  66. // The element exists, but we need to remove it, because it is being set to 0.
  67. parent.delete_element(row, col);
  68. val_ptr = NULL;
  69. }
  70. // If the element does not exist, we do not need to do anything at all.
  71. }
  72. return *this;
  73. }
  74. template<typename T1>
  75. arma_inline
  76. SpValProxy<T1>&
  77. SpValProxy<T1>::operator+=(const eT rhs)
  78. {
  79. if (val_ptr)
  80. {
  81. // The value already exists and merely needs to be updated.
  82. *val_ptr += rhs;
  83. parent.invalidate_cache();
  84. check_zero();
  85. }
  86. else
  87. {
  88. if (rhs != eT(0))
  89. {
  90. // The value does not exist and must be inserted.
  91. val_ptr = &parent.insert_element(row, col, rhs);
  92. }
  93. }
  94. return *this;
  95. }
  96. template<typename T1>
  97. arma_inline
  98. SpValProxy<T1>&
  99. SpValProxy<T1>::operator-=(const eT rhs)
  100. {
  101. if (val_ptr)
  102. {
  103. // The value already exists and merely needs to be updated.
  104. *val_ptr -= rhs;
  105. parent.invalidate_cache();
  106. check_zero();
  107. }
  108. else
  109. {
  110. if (rhs != eT(0))
  111. {
  112. // The value does not exist and must be inserted.
  113. val_ptr = &parent.insert_element(row, col, -rhs);
  114. }
  115. }
  116. return *this;
  117. }
  118. template<typename T1>
  119. arma_inline
  120. SpValProxy<T1>&
  121. SpValProxy<T1>::operator*=(const eT rhs)
  122. {
  123. if (rhs != eT(0))
  124. {
  125. if (val_ptr)
  126. {
  127. // The value already exists and merely needs to be updated.
  128. *val_ptr *= rhs;
  129. parent.invalidate_cache();
  130. check_zero();
  131. }
  132. }
  133. else
  134. {
  135. if (val_ptr)
  136. {
  137. // Since we are multiplying by zero, the value can be deleted.
  138. parent.delete_element(row, col);
  139. val_ptr = NULL;
  140. }
  141. }
  142. return *this;
  143. }
  144. template<typename T1>
  145. arma_inline
  146. SpValProxy<T1>&
  147. SpValProxy<T1>::operator/=(const eT rhs)
  148. {
  149. if (rhs != eT(0)) // I hope this is true!
  150. {
  151. if (val_ptr)
  152. {
  153. *val_ptr /= rhs;
  154. parent.invalidate_cache();
  155. check_zero();
  156. }
  157. }
  158. else
  159. {
  160. if (val_ptr)
  161. {
  162. *val_ptr /= rhs; // That is where it gets ugly.
  163. // Now check if it's 0.
  164. if (*val_ptr == eT(0))
  165. {
  166. parent.delete_element(row, col);
  167. val_ptr = NULL;
  168. }
  169. }
  170. else
  171. {
  172. eT val = eT(0) / rhs; // This may vary depending on type and implementation.
  173. if (val != eT(0))
  174. {
  175. // Ok, now we have to insert it.
  176. val_ptr = &parent.insert_element(row, col, val);
  177. }
  178. }
  179. }
  180. return *this;
  181. }
  182. template<typename T1>
  183. arma_inline
  184. SpValProxy<T1>&
  185. SpValProxy<T1>::operator++()
  186. {
  187. if (val_ptr)
  188. {
  189. (*val_ptr) += eT(1);
  190. parent.invalidate_cache();
  191. check_zero();
  192. }
  193. else
  194. {
  195. val_ptr = &parent.insert_element(row, col, eT(1));
  196. }
  197. return *this;
  198. }
  199. template<typename T1>
  200. arma_inline
  201. SpValProxy<T1>&
  202. SpValProxy<T1>::operator--()
  203. {
  204. if (val_ptr)
  205. {
  206. (*val_ptr) -= eT(1);
  207. parent.invalidate_cache();
  208. check_zero();
  209. }
  210. else
  211. {
  212. val_ptr = &parent.insert_element(row, col, eT(-1));
  213. }
  214. return *this;
  215. }
  216. template<typename T1>
  217. arma_inline
  218. typename T1::elem_type
  219. SpValProxy<T1>::operator++(const int)
  220. {
  221. if (val_ptr)
  222. {
  223. (*val_ptr) += eT(1);
  224. parent.invalidate_cache();
  225. check_zero();
  226. }
  227. else
  228. {
  229. val_ptr = &parent.insert_element(row, col, eT(1));
  230. }
  231. if (val_ptr) // It may have changed to now be 0.
  232. {
  233. return *(val_ptr) - eT(1);
  234. }
  235. else
  236. {
  237. return eT(0);
  238. }
  239. }
  240. template<typename T1>
  241. arma_inline
  242. typename T1::elem_type
  243. SpValProxy<T1>::operator--(const int)
  244. {
  245. if (val_ptr)
  246. {
  247. (*val_ptr) -= eT(1);
  248. parent.invalidate_cache();
  249. check_zero();
  250. }
  251. else
  252. {
  253. val_ptr = &parent.insert_element(row, col, eT(-1));
  254. }
  255. if (val_ptr) // It may have changed to now be 0.
  256. {
  257. return *(val_ptr) + eT(1);
  258. }
  259. else
  260. {
  261. return eT(0);
  262. }
  263. }
  264. template<typename T1>
  265. arma_inline
  266. SpValProxy<T1>::operator eT() const
  267. {
  268. return (val_ptr) ? eT(*val_ptr) : eT(0);
  269. }
  270. template<typename T1>
  271. arma_inline
  272. typename get_pod_type<typename SpValProxy<T1>::eT>::result
  273. SpValProxy<T1>::real() const
  274. {
  275. typedef typename get_pod_type<eT>::result T;
  276. return T( access::tmp_real( (val_ptr) ? eT(*val_ptr) : eT(0) ) );
  277. }
  278. template<typename T1>
  279. arma_inline
  280. typename get_pod_type<typename SpValProxy<T1>::eT>::result
  281. SpValProxy<T1>::imag() const
  282. {
  283. typedef typename get_pod_type<eT>::result T;
  284. return T( access::tmp_imag( (val_ptr) ? eT(*val_ptr) : eT(0) ) );
  285. }
  286. template<typename T1>
  287. arma_inline
  288. void
  289. SpValProxy<T1>::check_zero()
  290. {
  291. if (*val_ptr == eT(0))
  292. {
  293. parent.delete_element(row, col);
  294. val_ptr = NULL;
  295. }
  296. }
  297. //! @}