Chris@49
|
1 // Copyright (C) 2011-2012 Ryan Curtin
|
Chris@49
|
2 // Copyright (C) 2012 Conrad Sanderson
|
Chris@49
|
3 //
|
Chris@49
|
4 // This Source Code Form is subject to the terms of the Mozilla Public
|
Chris@49
|
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
|
Chris@49
|
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
Chris@49
|
7
|
Chris@49
|
8 //! \addtogroup SpValProxy
|
Chris@49
|
9 //! @{
|
Chris@49
|
10
|
Chris@49
|
11 //! SpValProxy implementation.
|
Chris@49
|
12 template<typename T1>
|
Chris@49
|
13 arma_inline
|
Chris@49
|
14 SpValProxy<T1>::SpValProxy(uword in_row, uword in_col, T1& in_parent, eT* in_val_ptr)
|
Chris@49
|
15 : row(in_row)
|
Chris@49
|
16 , col(in_col)
|
Chris@49
|
17 , val_ptr(in_val_ptr)
|
Chris@49
|
18 , parent(in_parent)
|
Chris@49
|
19 {
|
Chris@49
|
20 // Nothing to do.
|
Chris@49
|
21 }
|
Chris@49
|
22
|
Chris@49
|
23
|
Chris@49
|
24
|
Chris@49
|
25 template<typename T1>
|
Chris@49
|
26 arma_inline
|
Chris@49
|
27 SpValProxy<T1>&
|
Chris@49
|
28 SpValProxy<T1>::operator=(const SpValProxy<T1>& rhs)
|
Chris@49
|
29 {
|
Chris@49
|
30 return (*this).operator=(eT(rhs));
|
Chris@49
|
31 }
|
Chris@49
|
32
|
Chris@49
|
33
|
Chris@49
|
34
|
Chris@49
|
35 template<typename T1>
|
Chris@49
|
36 template<typename T2>
|
Chris@49
|
37 arma_inline
|
Chris@49
|
38 SpValProxy<T1>&
|
Chris@49
|
39 SpValProxy<T1>::operator=(const SpValProxy<T2>& rhs)
|
Chris@49
|
40 {
|
Chris@49
|
41 return (*this).operator=(eT(rhs));
|
Chris@49
|
42 }
|
Chris@49
|
43
|
Chris@49
|
44
|
Chris@49
|
45
|
Chris@49
|
46 template<typename T1>
|
Chris@49
|
47 arma_inline
|
Chris@49
|
48 SpValProxy<T1>&
|
Chris@49
|
49 SpValProxy<T1>::operator=(const eT rhs)
|
Chris@49
|
50 {
|
Chris@49
|
51 if (rhs != eT(0)) // A nonzero element is being assigned.
|
Chris@49
|
52 {
|
Chris@49
|
53
|
Chris@49
|
54 if (val_ptr)
|
Chris@49
|
55 {
|
Chris@49
|
56 // The value exists and merely needs to be updated.
|
Chris@49
|
57 *val_ptr = rhs;
|
Chris@49
|
58 }
|
Chris@49
|
59
|
Chris@49
|
60 else
|
Chris@49
|
61 {
|
Chris@49
|
62 // The value is nonzero and must be added.
|
Chris@49
|
63 val_ptr = &parent.add_element(row, col, rhs);
|
Chris@49
|
64 }
|
Chris@49
|
65
|
Chris@49
|
66 }
|
Chris@49
|
67 else // A zero is being assigned.~
|
Chris@49
|
68 {
|
Chris@49
|
69
|
Chris@49
|
70 if (val_ptr)
|
Chris@49
|
71 {
|
Chris@49
|
72 // The element exists, but we need to remove it, because it is being set to 0.
|
Chris@49
|
73 parent.delete_element(row, col);
|
Chris@49
|
74 val_ptr = NULL;
|
Chris@49
|
75 }
|
Chris@49
|
76
|
Chris@49
|
77 // If the element does not exist, we do not need to do anything at all.
|
Chris@49
|
78
|
Chris@49
|
79 }
|
Chris@49
|
80
|
Chris@49
|
81 return *this;
|
Chris@49
|
82 }
|
Chris@49
|
83
|
Chris@49
|
84
|
Chris@49
|
85
|
Chris@49
|
86 template<typename T1>
|
Chris@49
|
87 arma_inline
|
Chris@49
|
88 SpValProxy<T1>&
|
Chris@49
|
89 SpValProxy<T1>::operator+=(const eT rhs)
|
Chris@49
|
90 {
|
Chris@49
|
91 if (val_ptr)
|
Chris@49
|
92 {
|
Chris@49
|
93 // The value already exists and merely needs to be updated.
|
Chris@49
|
94 *val_ptr += rhs;
|
Chris@49
|
95 check_zero();
|
Chris@49
|
96 }
|
Chris@49
|
97 else
|
Chris@49
|
98 {
|
Chris@49
|
99 if (rhs != eT(0))
|
Chris@49
|
100 {
|
Chris@49
|
101 // The value does not exist and must be added.
|
Chris@49
|
102 val_ptr = &parent.add_element(row, col, rhs);
|
Chris@49
|
103 }
|
Chris@49
|
104 }
|
Chris@49
|
105
|
Chris@49
|
106 return *this;
|
Chris@49
|
107 }
|
Chris@49
|
108
|
Chris@49
|
109
|
Chris@49
|
110
|
Chris@49
|
111 template<typename T1>
|
Chris@49
|
112 arma_inline
|
Chris@49
|
113 SpValProxy<T1>&
|
Chris@49
|
114 SpValProxy<T1>::operator-=(const eT rhs)
|
Chris@49
|
115 {
|
Chris@49
|
116 if (val_ptr)
|
Chris@49
|
117 {
|
Chris@49
|
118 // The value already exists and merely needs to be updated.
|
Chris@49
|
119 *val_ptr -= rhs;
|
Chris@49
|
120 check_zero();
|
Chris@49
|
121 }
|
Chris@49
|
122 else
|
Chris@49
|
123 {
|
Chris@49
|
124 if (rhs != eT(0))
|
Chris@49
|
125 {
|
Chris@49
|
126 // The value does not exist and must be added.
|
Chris@49
|
127 val_ptr = &parent.add_element(row, col, -rhs);
|
Chris@49
|
128 }
|
Chris@49
|
129 }
|
Chris@49
|
130
|
Chris@49
|
131 return *this;
|
Chris@49
|
132 }
|
Chris@49
|
133
|
Chris@49
|
134
|
Chris@49
|
135
|
Chris@49
|
136 template<typename T1>
|
Chris@49
|
137 arma_inline
|
Chris@49
|
138 SpValProxy<T1>&
|
Chris@49
|
139 SpValProxy<T1>::operator*=(const eT rhs)
|
Chris@49
|
140 {
|
Chris@49
|
141 if (rhs != eT(0))
|
Chris@49
|
142 {
|
Chris@49
|
143
|
Chris@49
|
144 if (val_ptr)
|
Chris@49
|
145 {
|
Chris@49
|
146 // The value already exists and merely needs to be updated.
|
Chris@49
|
147 *val_ptr *= rhs;
|
Chris@49
|
148 check_zero();
|
Chris@49
|
149 }
|
Chris@49
|
150
|
Chris@49
|
151 }
|
Chris@49
|
152 else
|
Chris@49
|
153 {
|
Chris@49
|
154
|
Chris@49
|
155 if (val_ptr)
|
Chris@49
|
156 {
|
Chris@49
|
157 // Since we are multiplying by zero, the value can be deleted.
|
Chris@49
|
158 parent.delete_element(row, col);
|
Chris@49
|
159 val_ptr = NULL;
|
Chris@49
|
160 }
|
Chris@49
|
161
|
Chris@49
|
162 }
|
Chris@49
|
163
|
Chris@49
|
164 return *this;
|
Chris@49
|
165 }
|
Chris@49
|
166
|
Chris@49
|
167
|
Chris@49
|
168
|
Chris@49
|
169 template<typename T1>
|
Chris@49
|
170 arma_inline
|
Chris@49
|
171 SpValProxy<T1>&
|
Chris@49
|
172 SpValProxy<T1>::operator/=(const eT rhs)
|
Chris@49
|
173 {
|
Chris@49
|
174 if (rhs != eT(0)) // I hope this is true!
|
Chris@49
|
175 {
|
Chris@49
|
176
|
Chris@49
|
177 if (val_ptr)
|
Chris@49
|
178 {
|
Chris@49
|
179 *val_ptr /= rhs;
|
Chris@49
|
180 check_zero();
|
Chris@49
|
181 }
|
Chris@49
|
182
|
Chris@49
|
183 }
|
Chris@49
|
184 else
|
Chris@49
|
185 {
|
Chris@49
|
186
|
Chris@49
|
187 if (val_ptr)
|
Chris@49
|
188 {
|
Chris@49
|
189 *val_ptr /= rhs; // That is where it gets ugly.
|
Chris@49
|
190 // Now check if it's 0.
|
Chris@49
|
191 if (*val_ptr == eT(0))
|
Chris@49
|
192 {
|
Chris@49
|
193 parent.delete_element(row, col);
|
Chris@49
|
194 val_ptr = NULL;
|
Chris@49
|
195 }
|
Chris@49
|
196 }
|
Chris@49
|
197
|
Chris@49
|
198 else
|
Chris@49
|
199 {
|
Chris@49
|
200 eT val = eT(0) / rhs; // This may vary depending on type and implementation.
|
Chris@49
|
201
|
Chris@49
|
202 if (val != eT(0))
|
Chris@49
|
203 {
|
Chris@49
|
204 // Ok, now we have to add it.
|
Chris@49
|
205 val_ptr = &parent.add_element(row, col, val);
|
Chris@49
|
206 }
|
Chris@49
|
207
|
Chris@49
|
208 }
|
Chris@49
|
209 }
|
Chris@49
|
210
|
Chris@49
|
211 return *this;
|
Chris@49
|
212 }
|
Chris@49
|
213
|
Chris@49
|
214
|
Chris@49
|
215
|
Chris@49
|
216 template<typename T1>
|
Chris@49
|
217 arma_inline
|
Chris@49
|
218 SpValProxy<T1>&
|
Chris@49
|
219 SpValProxy<T1>::operator++()
|
Chris@49
|
220 {
|
Chris@49
|
221 if (val_ptr)
|
Chris@49
|
222 {
|
Chris@49
|
223 (*val_ptr) += eT(1);
|
Chris@49
|
224 check_zero();
|
Chris@49
|
225 }
|
Chris@49
|
226
|
Chris@49
|
227 else
|
Chris@49
|
228 {
|
Chris@49
|
229 val_ptr = &parent.add_element(row, col, eT(1));
|
Chris@49
|
230 }
|
Chris@49
|
231
|
Chris@49
|
232 return *this;
|
Chris@49
|
233 }
|
Chris@49
|
234
|
Chris@49
|
235
|
Chris@49
|
236
|
Chris@49
|
237 template<typename T1>
|
Chris@49
|
238 arma_inline
|
Chris@49
|
239 SpValProxy<T1>&
|
Chris@49
|
240 SpValProxy<T1>::operator--()
|
Chris@49
|
241 {
|
Chris@49
|
242 if (val_ptr)
|
Chris@49
|
243 {
|
Chris@49
|
244 (*val_ptr) -= eT(1);
|
Chris@49
|
245 check_zero();
|
Chris@49
|
246 }
|
Chris@49
|
247
|
Chris@49
|
248 else
|
Chris@49
|
249 {
|
Chris@49
|
250 val_ptr = &parent.add_element(row, col, eT(-1));
|
Chris@49
|
251 }
|
Chris@49
|
252
|
Chris@49
|
253 return *this;
|
Chris@49
|
254 }
|
Chris@49
|
255
|
Chris@49
|
256
|
Chris@49
|
257
|
Chris@49
|
258 template<typename T1>
|
Chris@49
|
259 arma_inline
|
Chris@49
|
260 typename T1::elem_type
|
Chris@49
|
261 SpValProxy<T1>::operator++(const int)
|
Chris@49
|
262 {
|
Chris@49
|
263 if (val_ptr)
|
Chris@49
|
264 {
|
Chris@49
|
265 (*val_ptr) += eT(1);
|
Chris@49
|
266 check_zero();
|
Chris@49
|
267 }
|
Chris@49
|
268
|
Chris@49
|
269 else
|
Chris@49
|
270 {
|
Chris@49
|
271 val_ptr = &parent.add_element(row, col, eT(1));
|
Chris@49
|
272 }
|
Chris@49
|
273
|
Chris@49
|
274 if (val_ptr) // It may have changed to now be 0.
|
Chris@49
|
275 {
|
Chris@49
|
276 return *(val_ptr) - eT(1);
|
Chris@49
|
277 }
|
Chris@49
|
278 else
|
Chris@49
|
279 {
|
Chris@49
|
280 return eT(0);
|
Chris@49
|
281 }
|
Chris@49
|
282 }
|
Chris@49
|
283
|
Chris@49
|
284
|
Chris@49
|
285
|
Chris@49
|
286 template<typename T1>
|
Chris@49
|
287 arma_inline
|
Chris@49
|
288 typename T1::elem_type
|
Chris@49
|
289 SpValProxy<T1>::operator--(const int)
|
Chris@49
|
290 {
|
Chris@49
|
291 if (val_ptr)
|
Chris@49
|
292 {
|
Chris@49
|
293 (*val_ptr) -= eT(1);
|
Chris@49
|
294 check_zero();
|
Chris@49
|
295 }
|
Chris@49
|
296
|
Chris@49
|
297 else
|
Chris@49
|
298 {
|
Chris@49
|
299 val_ptr = &parent.add_element(row, col, eT(-1));
|
Chris@49
|
300 }
|
Chris@49
|
301
|
Chris@49
|
302 if (val_ptr) // It may have changed to now be 0.
|
Chris@49
|
303 {
|
Chris@49
|
304 return *(val_ptr) + eT(1);
|
Chris@49
|
305 }
|
Chris@49
|
306 else
|
Chris@49
|
307 {
|
Chris@49
|
308 return eT(0);
|
Chris@49
|
309 }
|
Chris@49
|
310 }
|
Chris@49
|
311
|
Chris@49
|
312
|
Chris@49
|
313
|
Chris@49
|
314 template<typename T1>
|
Chris@49
|
315 arma_inline
|
Chris@49
|
316 SpValProxy<T1>::operator eT() const
|
Chris@49
|
317 {
|
Chris@49
|
318 if (val_ptr)
|
Chris@49
|
319 {
|
Chris@49
|
320 return *val_ptr;
|
Chris@49
|
321 }
|
Chris@49
|
322 else
|
Chris@49
|
323 {
|
Chris@49
|
324 return eT(0);
|
Chris@49
|
325 }
|
Chris@49
|
326 }
|
Chris@49
|
327
|
Chris@49
|
328
|
Chris@49
|
329
|
Chris@49
|
330 template<typename T1>
|
Chris@49
|
331 arma_inline
|
Chris@49
|
332 arma_hot
|
Chris@49
|
333 void
|
Chris@49
|
334 SpValProxy<T1>::check_zero()
|
Chris@49
|
335 {
|
Chris@49
|
336 if (*val_ptr == eT(0))
|
Chris@49
|
337 {
|
Chris@49
|
338 parent.delete_element(row, col);
|
Chris@49
|
339 val_ptr = NULL;
|
Chris@49
|
340 }
|
Chris@49
|
341 }
|
Chris@49
|
342
|
Chris@49
|
343
|
Chris@49
|
344
|
Chris@49
|
345 //! @}
|