Chris@49
|
1 // Copyright (C) 2008-2013 NICTA (www.nicta.com.au)
|
Chris@49
|
2 // Copyright (C) 2008-2013 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
|
Chris@49
|
9 //! \addtogroup diagview
|
Chris@49
|
10 //! @{
|
Chris@49
|
11
|
Chris@49
|
12
|
Chris@49
|
13 template<typename eT>
|
Chris@49
|
14 inline
|
Chris@49
|
15 diagview<eT>::~diagview()
|
Chris@49
|
16 {
|
Chris@49
|
17 arma_extra_debug_sigprint();
|
Chris@49
|
18 }
|
Chris@49
|
19
|
Chris@49
|
20
|
Chris@49
|
21 template<typename eT>
|
Chris@49
|
22 arma_inline
|
Chris@49
|
23 diagview<eT>::diagview(const Mat<eT>& in_m, const uword in_row_offset, const uword in_col_offset, const uword in_len)
|
Chris@49
|
24 : m(in_m)
|
Chris@49
|
25 , row_offset(in_row_offset)
|
Chris@49
|
26 , col_offset(in_col_offset)
|
Chris@49
|
27 , n_rows(in_len)
|
Chris@49
|
28 , n_elem(in_len)
|
Chris@49
|
29 {
|
Chris@49
|
30 arma_extra_debug_sigprint();
|
Chris@49
|
31 }
|
Chris@49
|
32
|
Chris@49
|
33
|
Chris@49
|
34
|
Chris@49
|
35 //! set a diagonal of our matrix using a diagonal from a foreign matrix
|
Chris@49
|
36 template<typename eT>
|
Chris@49
|
37 inline
|
Chris@49
|
38 void
|
Chris@49
|
39 diagview<eT>::operator= (const diagview<eT>& x)
|
Chris@49
|
40 {
|
Chris@49
|
41 arma_extra_debug_sigprint();
|
Chris@49
|
42
|
Chris@49
|
43 diagview<eT>& d = *this;
|
Chris@49
|
44
|
Chris@49
|
45 arma_debug_check( (d.n_elem != x.n_elem), "diagview: diagonals have incompatible lengths");
|
Chris@49
|
46
|
Chris@49
|
47 Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
|
Chris@49
|
48 const Mat<eT>& x_m = x.m;
|
Chris@49
|
49
|
Chris@49
|
50 if(&d_m != &x_m)
|
Chris@49
|
51 {
|
Chris@49
|
52 const uword d_n_elem = d.n_elem;
|
Chris@49
|
53 const uword d_row_offset = d.row_offset;
|
Chris@49
|
54 const uword d_col_offset = d.col_offset;
|
Chris@49
|
55
|
Chris@49
|
56 const uword x_row_offset = x.row_offset;
|
Chris@49
|
57 const uword x_col_offset = x.col_offset;
|
Chris@49
|
58
|
Chris@49
|
59 uword ii,jj;
|
Chris@49
|
60 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
61 {
|
Chris@49
|
62 const eT tmp_i = x_m.at(ii + x_row_offset, ii + x_col_offset);
|
Chris@49
|
63 const eT tmp_j = x_m.at(jj + x_row_offset, jj + x_col_offset);
|
Chris@49
|
64
|
Chris@49
|
65 d_m.at(ii + d_row_offset, ii + d_col_offset) = tmp_i;
|
Chris@49
|
66 d_m.at(jj + d_row_offset, jj + d_col_offset) = tmp_j;
|
Chris@49
|
67 }
|
Chris@49
|
68
|
Chris@49
|
69 if(ii < d_n_elem)
|
Chris@49
|
70 {
|
Chris@49
|
71 d_m.at(ii + d_row_offset, ii + d_col_offset) = x_m.at(ii + x_row_offset, ii + x_col_offset);
|
Chris@49
|
72 }
|
Chris@49
|
73 }
|
Chris@49
|
74 else
|
Chris@49
|
75 {
|
Chris@49
|
76 const Mat<eT> tmp = x;
|
Chris@49
|
77
|
Chris@49
|
78 (*this).operator=(tmp);
|
Chris@49
|
79 }
|
Chris@49
|
80 }
|
Chris@49
|
81
|
Chris@49
|
82
|
Chris@49
|
83
|
Chris@49
|
84 template<typename eT>
|
Chris@49
|
85 inline
|
Chris@49
|
86 void
|
Chris@49
|
87 diagview<eT>::operator+=(const eT val)
|
Chris@49
|
88 {
|
Chris@49
|
89 arma_extra_debug_sigprint();
|
Chris@49
|
90
|
Chris@49
|
91 Mat<eT>& t_m = const_cast< Mat<eT>& >(m);
|
Chris@49
|
92
|
Chris@49
|
93 const uword t_n_elem = n_elem;
|
Chris@49
|
94 const uword t_row_offset = row_offset;
|
Chris@49
|
95 const uword t_col_offset = col_offset;
|
Chris@49
|
96
|
Chris@49
|
97 for(uword ii=0; ii < t_n_elem; ++ii)
|
Chris@49
|
98 {
|
Chris@49
|
99 t_m.at( ii + t_row_offset, ii + t_col_offset) += val;
|
Chris@49
|
100 }
|
Chris@49
|
101 }
|
Chris@49
|
102
|
Chris@49
|
103
|
Chris@49
|
104
|
Chris@49
|
105 template<typename eT>
|
Chris@49
|
106 inline
|
Chris@49
|
107 void
|
Chris@49
|
108 diagview<eT>::operator-=(const eT val)
|
Chris@49
|
109 {
|
Chris@49
|
110 arma_extra_debug_sigprint();
|
Chris@49
|
111
|
Chris@49
|
112 Mat<eT>& t_m = const_cast< Mat<eT>& >(m);
|
Chris@49
|
113
|
Chris@49
|
114 const uword t_n_elem = n_elem;
|
Chris@49
|
115 const uword t_row_offset = row_offset;
|
Chris@49
|
116 const uword t_col_offset = col_offset;
|
Chris@49
|
117
|
Chris@49
|
118 for(uword ii=0; ii < t_n_elem; ++ii)
|
Chris@49
|
119 {
|
Chris@49
|
120 t_m.at( ii + t_row_offset, ii + t_col_offset) -= val;
|
Chris@49
|
121 }
|
Chris@49
|
122 }
|
Chris@49
|
123
|
Chris@49
|
124
|
Chris@49
|
125
|
Chris@49
|
126 template<typename eT>
|
Chris@49
|
127 inline
|
Chris@49
|
128 void
|
Chris@49
|
129 diagview<eT>::operator*=(const eT val)
|
Chris@49
|
130 {
|
Chris@49
|
131 arma_extra_debug_sigprint();
|
Chris@49
|
132
|
Chris@49
|
133 Mat<eT>& t_m = const_cast< Mat<eT>& >(m);
|
Chris@49
|
134
|
Chris@49
|
135 const uword t_n_elem = n_elem;
|
Chris@49
|
136 const uword t_row_offset = row_offset;
|
Chris@49
|
137 const uword t_col_offset = col_offset;
|
Chris@49
|
138
|
Chris@49
|
139 for(uword ii=0; ii < t_n_elem; ++ii)
|
Chris@49
|
140 {
|
Chris@49
|
141 t_m.at( ii + t_row_offset, ii + t_col_offset) *= val;
|
Chris@49
|
142 }
|
Chris@49
|
143 }
|
Chris@49
|
144
|
Chris@49
|
145
|
Chris@49
|
146
|
Chris@49
|
147 template<typename eT>
|
Chris@49
|
148 inline
|
Chris@49
|
149 void
|
Chris@49
|
150 diagview<eT>::operator/=(const eT val)
|
Chris@49
|
151 {
|
Chris@49
|
152 arma_extra_debug_sigprint();
|
Chris@49
|
153
|
Chris@49
|
154 Mat<eT>& t_m = const_cast< Mat<eT>& >(m);
|
Chris@49
|
155
|
Chris@49
|
156 const uword t_n_elem = n_elem;
|
Chris@49
|
157 const uword t_row_offset = row_offset;
|
Chris@49
|
158 const uword t_col_offset = col_offset;
|
Chris@49
|
159
|
Chris@49
|
160 for(uword ii=0; ii < t_n_elem; ++ii)
|
Chris@49
|
161 {
|
Chris@49
|
162 t_m.at( ii + t_row_offset, ii + t_col_offset) /= val;
|
Chris@49
|
163 }
|
Chris@49
|
164 }
|
Chris@49
|
165
|
Chris@49
|
166
|
Chris@49
|
167
|
Chris@49
|
168 //! set a diagonal of our matrix using data from a foreign object
|
Chris@49
|
169 template<typename eT>
|
Chris@49
|
170 template<typename T1>
|
Chris@49
|
171 inline
|
Chris@49
|
172 void
|
Chris@49
|
173 diagview<eT>::operator= (const Base<eT,T1>& o)
|
Chris@49
|
174 {
|
Chris@49
|
175 arma_extra_debug_sigprint();
|
Chris@49
|
176
|
Chris@49
|
177 diagview<eT>& d = *this;
|
Chris@49
|
178
|
Chris@49
|
179 Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
|
Chris@49
|
180
|
Chris@49
|
181 const uword d_n_elem = d.n_elem;
|
Chris@49
|
182 const uword d_row_offset = d.row_offset;
|
Chris@49
|
183 const uword d_col_offset = d.col_offset;
|
Chris@49
|
184
|
Chris@49
|
185 const Proxy<T1> P( o.get_ref() );
|
Chris@49
|
186
|
Chris@49
|
187 arma_debug_check
|
Chris@49
|
188 (
|
Chris@49
|
189 ( (d.n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ),
|
Chris@49
|
190 "diagview: given object has incompatible size"
|
Chris@49
|
191 );
|
Chris@49
|
192
|
Chris@49
|
193 const bool is_alias = P.is_alias(d_m);
|
Chris@49
|
194
|
Chris@49
|
195 arma_extra_debug_warn(is_alias, "aliasing detected");
|
Chris@49
|
196
|
Chris@49
|
197 if( (is_Mat<typename Proxy<T1>::stored_type>::value == true) || (Proxy<T1>::prefer_at_accessor == true) || (is_alias == true) )
|
Chris@49
|
198 {
|
Chris@49
|
199 const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
|
Chris@49
|
200 const Mat<eT>& x = tmp.M;
|
Chris@49
|
201
|
Chris@49
|
202 const eT* x_mem = x.memptr();
|
Chris@49
|
203
|
Chris@49
|
204 uword ii,jj;
|
Chris@49
|
205 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
206 {
|
Chris@49
|
207 const eT tmp_i = x_mem[ii];
|
Chris@49
|
208 const eT tmp_j = x_mem[jj];
|
Chris@49
|
209
|
Chris@49
|
210 d_m.at( ii + d_row_offset, ii + d_col_offset) = tmp_i;
|
Chris@49
|
211 d_m.at( jj + d_row_offset, jj + d_col_offset) = tmp_j;
|
Chris@49
|
212 }
|
Chris@49
|
213
|
Chris@49
|
214 if(ii < d_n_elem)
|
Chris@49
|
215 {
|
Chris@49
|
216 d_m.at( ii + d_row_offset, ii + d_col_offset) = x_mem[ii];
|
Chris@49
|
217 }
|
Chris@49
|
218 }
|
Chris@49
|
219 else
|
Chris@49
|
220 {
|
Chris@49
|
221 typename Proxy<T1>::ea_type Pea = P.get_ea();
|
Chris@49
|
222
|
Chris@49
|
223 uword ii,jj;
|
Chris@49
|
224 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
225 {
|
Chris@49
|
226 const eT tmp_i = Pea[ii];
|
Chris@49
|
227 const eT tmp_j = Pea[jj];
|
Chris@49
|
228
|
Chris@49
|
229 d_m.at( ii + d_row_offset, ii + d_col_offset) = tmp_i;
|
Chris@49
|
230 d_m.at( jj + d_row_offset, jj + d_col_offset) = tmp_j;
|
Chris@49
|
231 }
|
Chris@49
|
232
|
Chris@49
|
233 if(ii < d_n_elem)
|
Chris@49
|
234 {
|
Chris@49
|
235 d_m.at( ii + d_row_offset, ii + d_col_offset) = Pea[ii];
|
Chris@49
|
236 }
|
Chris@49
|
237 }
|
Chris@49
|
238 }
|
Chris@49
|
239
|
Chris@49
|
240
|
Chris@49
|
241
|
Chris@49
|
242 template<typename eT>
|
Chris@49
|
243 template<typename T1>
|
Chris@49
|
244 inline
|
Chris@49
|
245 void
|
Chris@49
|
246 diagview<eT>::operator+=(const Base<eT,T1>& o)
|
Chris@49
|
247 {
|
Chris@49
|
248 arma_extra_debug_sigprint();
|
Chris@49
|
249
|
Chris@49
|
250 diagview<eT>& d = *this;
|
Chris@49
|
251
|
Chris@49
|
252 Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
|
Chris@49
|
253
|
Chris@49
|
254 const uword d_n_elem = d.n_elem;
|
Chris@49
|
255 const uword d_row_offset = d.row_offset;
|
Chris@49
|
256 const uword d_col_offset = d.col_offset;
|
Chris@49
|
257
|
Chris@49
|
258 const Proxy<T1> P( o.get_ref() );
|
Chris@49
|
259
|
Chris@49
|
260 arma_debug_check
|
Chris@49
|
261 (
|
Chris@49
|
262 ( (d.n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ),
|
Chris@49
|
263 "diagview: given object has incompatible size"
|
Chris@49
|
264 );
|
Chris@49
|
265
|
Chris@49
|
266 const bool is_alias = P.is_alias(d_m);
|
Chris@49
|
267
|
Chris@49
|
268 arma_extra_debug_warn(is_alias, "aliasing detected");
|
Chris@49
|
269
|
Chris@49
|
270 if( (is_Mat<typename Proxy<T1>::stored_type>::value == true) || (Proxy<T1>::prefer_at_accessor == true) || (is_alias == true) )
|
Chris@49
|
271 {
|
Chris@49
|
272 const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
|
Chris@49
|
273 const Mat<eT>& x = tmp.M;
|
Chris@49
|
274
|
Chris@49
|
275 const eT* x_mem = x.memptr();
|
Chris@49
|
276
|
Chris@49
|
277 uword ii,jj;
|
Chris@49
|
278 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
279 {
|
Chris@49
|
280 const eT tmp_i = x_mem[ii];
|
Chris@49
|
281 const eT tmp_j = x_mem[jj];
|
Chris@49
|
282
|
Chris@49
|
283 d_m.at( ii + d_row_offset, ii + d_col_offset) += tmp_i;
|
Chris@49
|
284 d_m.at( jj + d_row_offset, jj + d_col_offset) += tmp_j;
|
Chris@49
|
285 }
|
Chris@49
|
286
|
Chris@49
|
287 if(ii < d_n_elem)
|
Chris@49
|
288 {
|
Chris@49
|
289 d_m.at( ii + d_row_offset, ii + d_col_offset) += x_mem[ii];
|
Chris@49
|
290 }
|
Chris@49
|
291 }
|
Chris@49
|
292 else
|
Chris@49
|
293 {
|
Chris@49
|
294 typename Proxy<T1>::ea_type Pea = P.get_ea();
|
Chris@49
|
295
|
Chris@49
|
296 uword ii,jj;
|
Chris@49
|
297 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
298 {
|
Chris@49
|
299 const eT tmp_i = Pea[ii];
|
Chris@49
|
300 const eT tmp_j = Pea[jj];
|
Chris@49
|
301
|
Chris@49
|
302 d_m.at( ii + d_row_offset, ii + d_col_offset) += tmp_i;
|
Chris@49
|
303 d_m.at( jj + d_row_offset, jj + d_col_offset) += tmp_j;
|
Chris@49
|
304 }
|
Chris@49
|
305
|
Chris@49
|
306 if(ii < d_n_elem)
|
Chris@49
|
307 {
|
Chris@49
|
308 d_m.at( ii + d_row_offset, ii + d_col_offset) += Pea[ii];
|
Chris@49
|
309 }
|
Chris@49
|
310 }
|
Chris@49
|
311 }
|
Chris@49
|
312
|
Chris@49
|
313
|
Chris@49
|
314
|
Chris@49
|
315 template<typename eT>
|
Chris@49
|
316 template<typename T1>
|
Chris@49
|
317 inline
|
Chris@49
|
318 void
|
Chris@49
|
319 diagview<eT>::operator-=(const Base<eT,T1>& o)
|
Chris@49
|
320 {
|
Chris@49
|
321 arma_extra_debug_sigprint();
|
Chris@49
|
322
|
Chris@49
|
323 diagview<eT>& d = *this;
|
Chris@49
|
324
|
Chris@49
|
325 Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
|
Chris@49
|
326
|
Chris@49
|
327 const uword d_n_elem = d.n_elem;
|
Chris@49
|
328 const uword d_row_offset = d.row_offset;
|
Chris@49
|
329 const uword d_col_offset = d.col_offset;
|
Chris@49
|
330
|
Chris@49
|
331 const Proxy<T1> P( o.get_ref() );
|
Chris@49
|
332
|
Chris@49
|
333 arma_debug_check
|
Chris@49
|
334 (
|
Chris@49
|
335 ( (d.n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ),
|
Chris@49
|
336 "diagview: given object has incompatible size"
|
Chris@49
|
337 );
|
Chris@49
|
338
|
Chris@49
|
339 const bool is_alias = P.is_alias(d_m);
|
Chris@49
|
340
|
Chris@49
|
341 arma_extra_debug_warn(is_alias, "aliasing detected");
|
Chris@49
|
342
|
Chris@49
|
343 if( (is_Mat<typename Proxy<T1>::stored_type>::value == true) || (Proxy<T1>::prefer_at_accessor == true) || (is_alias == true) )
|
Chris@49
|
344 {
|
Chris@49
|
345 const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
|
Chris@49
|
346 const Mat<eT>& x = tmp.M;
|
Chris@49
|
347
|
Chris@49
|
348 const eT* x_mem = x.memptr();
|
Chris@49
|
349
|
Chris@49
|
350 uword ii,jj;
|
Chris@49
|
351 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
352 {
|
Chris@49
|
353 const eT tmp_i = x_mem[ii];
|
Chris@49
|
354 const eT tmp_j = x_mem[jj];
|
Chris@49
|
355
|
Chris@49
|
356 d_m.at( ii + d_row_offset, ii + d_col_offset) -= tmp_i;
|
Chris@49
|
357 d_m.at( jj + d_row_offset, jj + d_col_offset) -= tmp_j;
|
Chris@49
|
358 }
|
Chris@49
|
359
|
Chris@49
|
360 if(ii < d_n_elem)
|
Chris@49
|
361 {
|
Chris@49
|
362 d_m.at( ii + d_row_offset, ii + d_col_offset) -= x_mem[ii];
|
Chris@49
|
363 }
|
Chris@49
|
364 }
|
Chris@49
|
365 else
|
Chris@49
|
366 {
|
Chris@49
|
367 typename Proxy<T1>::ea_type Pea = P.get_ea();
|
Chris@49
|
368
|
Chris@49
|
369 uword ii,jj;
|
Chris@49
|
370 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
371 {
|
Chris@49
|
372 const eT tmp_i = Pea[ii];
|
Chris@49
|
373 const eT tmp_j = Pea[jj];
|
Chris@49
|
374
|
Chris@49
|
375 d_m.at( ii + d_row_offset, ii + d_col_offset) -= tmp_i;
|
Chris@49
|
376 d_m.at( jj + d_row_offset, jj + d_col_offset) -= tmp_j;
|
Chris@49
|
377 }
|
Chris@49
|
378
|
Chris@49
|
379 if(ii < d_n_elem)
|
Chris@49
|
380 {
|
Chris@49
|
381 d_m.at( ii + d_row_offset, ii + d_col_offset) -= Pea[ii];
|
Chris@49
|
382 }
|
Chris@49
|
383 }
|
Chris@49
|
384 }
|
Chris@49
|
385
|
Chris@49
|
386
|
Chris@49
|
387
|
Chris@49
|
388 template<typename eT>
|
Chris@49
|
389 template<typename T1>
|
Chris@49
|
390 inline
|
Chris@49
|
391 void
|
Chris@49
|
392 diagview<eT>::operator%=(const Base<eT,T1>& o)
|
Chris@49
|
393 {
|
Chris@49
|
394 arma_extra_debug_sigprint();
|
Chris@49
|
395
|
Chris@49
|
396 diagview<eT>& d = *this;
|
Chris@49
|
397
|
Chris@49
|
398 Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
|
Chris@49
|
399
|
Chris@49
|
400 const uword d_n_elem = d.n_elem;
|
Chris@49
|
401 const uword d_row_offset = d.row_offset;
|
Chris@49
|
402 const uword d_col_offset = d.col_offset;
|
Chris@49
|
403
|
Chris@49
|
404 const Proxy<T1> P( o.get_ref() );
|
Chris@49
|
405
|
Chris@49
|
406 arma_debug_check
|
Chris@49
|
407 (
|
Chris@49
|
408 ( (d.n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ),
|
Chris@49
|
409 "diagview: given object has incompatible size"
|
Chris@49
|
410 );
|
Chris@49
|
411
|
Chris@49
|
412 const bool is_alias = P.is_alias(d_m);
|
Chris@49
|
413
|
Chris@49
|
414 arma_extra_debug_warn(is_alias, "aliasing detected");
|
Chris@49
|
415
|
Chris@49
|
416 if( (is_Mat<typename Proxy<T1>::stored_type>::value == true) || (Proxy<T1>::prefer_at_accessor == true) || (is_alias == true) )
|
Chris@49
|
417 {
|
Chris@49
|
418 const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
|
Chris@49
|
419 const Mat<eT>& x = tmp.M;
|
Chris@49
|
420
|
Chris@49
|
421 const eT* x_mem = x.memptr();
|
Chris@49
|
422
|
Chris@49
|
423 uword ii,jj;
|
Chris@49
|
424 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
425 {
|
Chris@49
|
426 const eT tmp_i = x_mem[ii];
|
Chris@49
|
427 const eT tmp_j = x_mem[jj];
|
Chris@49
|
428
|
Chris@49
|
429 d_m.at( ii + d_row_offset, ii + d_col_offset) *= tmp_i;
|
Chris@49
|
430 d_m.at( jj + d_row_offset, jj + d_col_offset) *= tmp_j;
|
Chris@49
|
431 }
|
Chris@49
|
432
|
Chris@49
|
433 if(ii < d_n_elem)
|
Chris@49
|
434 {
|
Chris@49
|
435 d_m.at( ii + d_row_offset, ii + d_col_offset) *= x_mem[ii];
|
Chris@49
|
436 }
|
Chris@49
|
437 }
|
Chris@49
|
438 else
|
Chris@49
|
439 {
|
Chris@49
|
440 typename Proxy<T1>::ea_type Pea = P.get_ea();
|
Chris@49
|
441
|
Chris@49
|
442 uword ii,jj;
|
Chris@49
|
443 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
444 {
|
Chris@49
|
445 const eT tmp_i = Pea[ii];
|
Chris@49
|
446 const eT tmp_j = Pea[jj];
|
Chris@49
|
447
|
Chris@49
|
448 d_m.at( ii + d_row_offset, ii + d_col_offset) *= tmp_i;
|
Chris@49
|
449 d_m.at( jj + d_row_offset, jj + d_col_offset) *= tmp_j;
|
Chris@49
|
450 }
|
Chris@49
|
451
|
Chris@49
|
452 if(ii < d_n_elem)
|
Chris@49
|
453 {
|
Chris@49
|
454 d_m.at( ii + d_row_offset, ii + d_col_offset) *= Pea[ii];
|
Chris@49
|
455 }
|
Chris@49
|
456 }
|
Chris@49
|
457 }
|
Chris@49
|
458
|
Chris@49
|
459
|
Chris@49
|
460
|
Chris@49
|
461 template<typename eT>
|
Chris@49
|
462 template<typename T1>
|
Chris@49
|
463 inline
|
Chris@49
|
464 void
|
Chris@49
|
465 diagview<eT>::operator/=(const Base<eT,T1>& o)
|
Chris@49
|
466 {
|
Chris@49
|
467 arma_extra_debug_sigprint();
|
Chris@49
|
468
|
Chris@49
|
469 diagview<eT>& d = *this;
|
Chris@49
|
470
|
Chris@49
|
471 Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
|
Chris@49
|
472
|
Chris@49
|
473 const uword d_n_elem = d.n_elem;
|
Chris@49
|
474 const uword d_row_offset = d.row_offset;
|
Chris@49
|
475 const uword d_col_offset = d.col_offset;
|
Chris@49
|
476
|
Chris@49
|
477 const Proxy<T1> P( o.get_ref() );
|
Chris@49
|
478
|
Chris@49
|
479 arma_debug_check
|
Chris@49
|
480 (
|
Chris@49
|
481 ( (d.n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ),
|
Chris@49
|
482 "diagview: given object has incompatible size"
|
Chris@49
|
483 );
|
Chris@49
|
484
|
Chris@49
|
485 const bool is_alias = P.is_alias(d_m);
|
Chris@49
|
486
|
Chris@49
|
487 arma_extra_debug_warn(is_alias, "aliasing detected");
|
Chris@49
|
488
|
Chris@49
|
489 if( (is_Mat<typename Proxy<T1>::stored_type>::value == true) || (Proxy<T1>::prefer_at_accessor == true) || (is_alias == true) )
|
Chris@49
|
490 {
|
Chris@49
|
491 const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
|
Chris@49
|
492 const Mat<eT>& x = tmp.M;
|
Chris@49
|
493
|
Chris@49
|
494 const eT* x_mem = x.memptr();
|
Chris@49
|
495
|
Chris@49
|
496 uword ii,jj;
|
Chris@49
|
497 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
498 {
|
Chris@49
|
499 const eT tmp_i = x_mem[ii];
|
Chris@49
|
500 const eT tmp_j = x_mem[jj];
|
Chris@49
|
501
|
Chris@49
|
502 d_m.at( ii + d_row_offset, ii + d_col_offset) /= tmp_i;
|
Chris@49
|
503 d_m.at( jj + d_row_offset, jj + d_col_offset) /= tmp_j;
|
Chris@49
|
504 }
|
Chris@49
|
505
|
Chris@49
|
506 if(ii < d_n_elem)
|
Chris@49
|
507 {
|
Chris@49
|
508 d_m.at( ii + d_row_offset, ii + d_col_offset) /= x_mem[ii];
|
Chris@49
|
509 }
|
Chris@49
|
510 }
|
Chris@49
|
511 else
|
Chris@49
|
512 {
|
Chris@49
|
513 typename Proxy<T1>::ea_type Pea = P.get_ea();
|
Chris@49
|
514
|
Chris@49
|
515 uword ii,jj;
|
Chris@49
|
516 for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
|
Chris@49
|
517 {
|
Chris@49
|
518 const eT tmp_i = Pea[ii];
|
Chris@49
|
519 const eT tmp_j = Pea[jj];
|
Chris@49
|
520
|
Chris@49
|
521 d_m.at( ii + d_row_offset, ii + d_col_offset) /= tmp_i;
|
Chris@49
|
522 d_m.at( jj + d_row_offset, jj + d_col_offset) /= tmp_j;
|
Chris@49
|
523 }
|
Chris@49
|
524
|
Chris@49
|
525 if(ii < d_n_elem)
|
Chris@49
|
526 {
|
Chris@49
|
527 d_m.at( ii + d_row_offset, ii + d_col_offset) /= Pea[ii];
|
Chris@49
|
528 }
|
Chris@49
|
529 }
|
Chris@49
|
530 }
|
Chris@49
|
531
|
Chris@49
|
532
|
Chris@49
|
533
|
Chris@49
|
534 //! extract a diagonal and store it as a column vector
|
Chris@49
|
535 template<typename eT>
|
Chris@49
|
536 inline
|
Chris@49
|
537 void
|
Chris@49
|
538 diagview<eT>::extract(Mat<eT>& out, const diagview<eT>& in)
|
Chris@49
|
539 {
|
Chris@49
|
540 arma_extra_debug_sigprint();
|
Chris@49
|
541
|
Chris@49
|
542 // NOTE: we're assuming that the matrix has already been set to the correct size and there is no aliasing;
|
Chris@49
|
543 // size setting and alias checking is done by either the Mat contructor or operator=()
|
Chris@49
|
544
|
Chris@49
|
545 const Mat<eT>& in_m = in.m;
|
Chris@49
|
546
|
Chris@49
|
547 const uword in_n_elem = in.n_elem;
|
Chris@49
|
548 const uword in_row_offset = in.row_offset;
|
Chris@49
|
549 const uword in_col_offset = in.col_offset;
|
Chris@49
|
550
|
Chris@49
|
551 eT* out_mem = out.memptr();
|
Chris@49
|
552
|
Chris@49
|
553 uword i,j;
|
Chris@49
|
554 for(i=0, j=1; j < in_n_elem; i+=2, j+=2)
|
Chris@49
|
555 {
|
Chris@49
|
556 const eT tmp_i = in_m.at( i + in_row_offset, i + in_col_offset );
|
Chris@49
|
557 const eT tmp_j = in_m.at( j + in_row_offset, j + in_col_offset );
|
Chris@49
|
558
|
Chris@49
|
559 out_mem[i] = tmp_i;
|
Chris@49
|
560 out_mem[j] = tmp_j;
|
Chris@49
|
561 }
|
Chris@49
|
562
|
Chris@49
|
563 if(i < in_n_elem)
|
Chris@49
|
564 {
|
Chris@49
|
565 out_mem[i] = in_m.at( i + in_row_offset, i + in_col_offset );
|
Chris@49
|
566 }
|
Chris@49
|
567 }
|
Chris@49
|
568
|
Chris@49
|
569
|
Chris@49
|
570
|
Chris@49
|
571 //! X += Y.diag()
|
Chris@49
|
572 template<typename eT>
|
Chris@49
|
573 inline
|
Chris@49
|
574 void
|
Chris@49
|
575 diagview<eT>::plus_inplace(Mat<eT>& out, const diagview<eT>& in)
|
Chris@49
|
576 {
|
Chris@49
|
577 arma_extra_debug_sigprint();
|
Chris@49
|
578
|
Chris@49
|
579 arma_debug_assert_same_size(out.n_rows, out.n_cols, in.n_rows, in.n_cols, "addition");
|
Chris@49
|
580
|
Chris@49
|
581 const Mat<eT>& in_m = in.m;
|
Chris@49
|
582
|
Chris@49
|
583 const uword in_n_elem = in.n_elem;
|
Chris@49
|
584 const uword in_row_offset = in.row_offset;
|
Chris@49
|
585 const uword in_col_offset = in.col_offset;
|
Chris@49
|
586
|
Chris@49
|
587 eT* out_mem = out.memptr();
|
Chris@49
|
588
|
Chris@49
|
589 uword i,j;
|
Chris@49
|
590 for(i=0, j=1; j < in_n_elem; i+=2, j+=2)
|
Chris@49
|
591 {
|
Chris@49
|
592 const eT tmp_i = in_m.at( i + in_row_offset, i + in_col_offset );
|
Chris@49
|
593 const eT tmp_j = in_m.at( j + in_row_offset, j + in_col_offset );
|
Chris@49
|
594
|
Chris@49
|
595 out_mem[i] += tmp_i;
|
Chris@49
|
596 out_mem[j] += tmp_j;
|
Chris@49
|
597 }
|
Chris@49
|
598
|
Chris@49
|
599 if(i < in_n_elem)
|
Chris@49
|
600 {
|
Chris@49
|
601 out_mem[i] += in_m.at( i + in_row_offset, i + in_col_offset );
|
Chris@49
|
602 }
|
Chris@49
|
603 }
|
Chris@49
|
604
|
Chris@49
|
605
|
Chris@49
|
606
|
Chris@49
|
607 //! X -= Y.diag()
|
Chris@49
|
608 template<typename eT>
|
Chris@49
|
609 inline
|
Chris@49
|
610 void
|
Chris@49
|
611 diagview<eT>::minus_inplace(Mat<eT>& out, const diagview<eT>& in)
|
Chris@49
|
612 {
|
Chris@49
|
613 arma_extra_debug_sigprint();
|
Chris@49
|
614
|
Chris@49
|
615 arma_debug_assert_same_size(out.n_rows, out.n_cols, in.n_rows, in.n_cols, "subtraction");
|
Chris@49
|
616
|
Chris@49
|
617 const Mat<eT>& in_m = in.m;
|
Chris@49
|
618
|
Chris@49
|
619 const uword in_n_elem = in.n_elem;
|
Chris@49
|
620 const uword in_row_offset = in.row_offset;
|
Chris@49
|
621 const uword in_col_offset = in.col_offset;
|
Chris@49
|
622
|
Chris@49
|
623 eT* out_mem = out.memptr();
|
Chris@49
|
624
|
Chris@49
|
625 uword i,j;
|
Chris@49
|
626 for(i=0, j=1; j < in_n_elem; i+=2, j+=2)
|
Chris@49
|
627 {
|
Chris@49
|
628 const eT tmp_i = in_m.at( i + in_row_offset, i + in_col_offset );
|
Chris@49
|
629 const eT tmp_j = in_m.at( j + in_row_offset, j + in_col_offset );
|
Chris@49
|
630
|
Chris@49
|
631 out_mem[i] -= tmp_i;
|
Chris@49
|
632 out_mem[j] -= tmp_j;
|
Chris@49
|
633 }
|
Chris@49
|
634
|
Chris@49
|
635 if(i < in_n_elem)
|
Chris@49
|
636 {
|
Chris@49
|
637 out_mem[i] -= in_m.at( i + in_row_offset, i + in_col_offset );
|
Chris@49
|
638 }
|
Chris@49
|
639 }
|
Chris@49
|
640
|
Chris@49
|
641
|
Chris@49
|
642
|
Chris@49
|
643 //! X %= Y.diag()
|
Chris@49
|
644 template<typename eT>
|
Chris@49
|
645 inline
|
Chris@49
|
646 void
|
Chris@49
|
647 diagview<eT>::schur_inplace(Mat<eT>& out, const diagview<eT>& in)
|
Chris@49
|
648 {
|
Chris@49
|
649 arma_extra_debug_sigprint();
|
Chris@49
|
650
|
Chris@49
|
651 arma_debug_assert_same_size(out.n_rows, out.n_cols, in.n_rows, in.n_cols, "element-wise multiplication");
|
Chris@49
|
652
|
Chris@49
|
653 const Mat<eT>& in_m = in.m;
|
Chris@49
|
654
|
Chris@49
|
655 const uword in_n_elem = in.n_elem;
|
Chris@49
|
656 const uword in_row_offset = in.row_offset;
|
Chris@49
|
657 const uword in_col_offset = in.col_offset;
|
Chris@49
|
658
|
Chris@49
|
659 eT* out_mem = out.memptr();
|
Chris@49
|
660
|
Chris@49
|
661 uword i,j;
|
Chris@49
|
662 for(i=0, j=1; j < in_n_elem; i+=2, j+=2)
|
Chris@49
|
663 {
|
Chris@49
|
664 const eT tmp_i = in_m.at( i + in_row_offset, i + in_col_offset );
|
Chris@49
|
665 const eT tmp_j = in_m.at( j + in_row_offset, j + in_col_offset );
|
Chris@49
|
666
|
Chris@49
|
667 out_mem[i] *= tmp_i;
|
Chris@49
|
668 out_mem[j] *= tmp_j;
|
Chris@49
|
669 }
|
Chris@49
|
670
|
Chris@49
|
671 if(i < in_n_elem)
|
Chris@49
|
672 {
|
Chris@49
|
673 out_mem[i] *= in_m.at( i + in_row_offset, i + in_col_offset );
|
Chris@49
|
674 }
|
Chris@49
|
675 }
|
Chris@49
|
676
|
Chris@49
|
677
|
Chris@49
|
678
|
Chris@49
|
679 //! X /= Y.diag()
|
Chris@49
|
680 template<typename eT>
|
Chris@49
|
681 inline
|
Chris@49
|
682 void
|
Chris@49
|
683 diagview<eT>::div_inplace(Mat<eT>& out, const diagview<eT>& in)
|
Chris@49
|
684 {
|
Chris@49
|
685 arma_extra_debug_sigprint();
|
Chris@49
|
686
|
Chris@49
|
687 arma_debug_assert_same_size(out.n_rows, out.n_cols, in.n_rows, in.n_cols, "element-wise division");
|
Chris@49
|
688
|
Chris@49
|
689 const Mat<eT>& in_m = in.m;
|
Chris@49
|
690
|
Chris@49
|
691 const uword in_n_elem = in.n_elem;
|
Chris@49
|
692 const uword in_row_offset = in.row_offset;
|
Chris@49
|
693 const uword in_col_offset = in.col_offset;
|
Chris@49
|
694
|
Chris@49
|
695 eT* out_mem = out.memptr();
|
Chris@49
|
696
|
Chris@49
|
697 uword i,j;
|
Chris@49
|
698 for(i=0, j=1; j < in_n_elem; i+=2, j+=2)
|
Chris@49
|
699 {
|
Chris@49
|
700 const eT tmp_i = in_m.at( i + in_row_offset, i + in_col_offset );
|
Chris@49
|
701 const eT tmp_j = in_m.at( j + in_row_offset, j + in_col_offset );
|
Chris@49
|
702
|
Chris@49
|
703 out_mem[i] /= tmp_i;
|
Chris@49
|
704 out_mem[j] /= tmp_j;
|
Chris@49
|
705 }
|
Chris@49
|
706
|
Chris@49
|
707 if(i < in_n_elem)
|
Chris@49
|
708 {
|
Chris@49
|
709 out_mem[i] /= in_m.at( i + in_row_offset, i + in_col_offset );
|
Chris@49
|
710 }
|
Chris@49
|
711 }
|
Chris@49
|
712
|
Chris@49
|
713
|
Chris@49
|
714
|
Chris@49
|
715 template<typename eT>
|
Chris@49
|
716 arma_inline
|
Chris@49
|
717 eT
|
Chris@49
|
718 diagview<eT>::at_alt(const uword ii) const
|
Chris@49
|
719 {
|
Chris@49
|
720 return m.at(ii+row_offset, ii+col_offset);
|
Chris@49
|
721 }
|
Chris@49
|
722
|
Chris@49
|
723
|
Chris@49
|
724
|
Chris@49
|
725 template<typename eT>
|
Chris@49
|
726 arma_inline
|
Chris@49
|
727 eT&
|
Chris@49
|
728 diagview<eT>::operator[](const uword ii)
|
Chris@49
|
729 {
|
Chris@49
|
730 return (const_cast< Mat<eT>& >(m)).at(ii+row_offset, ii+col_offset);
|
Chris@49
|
731 }
|
Chris@49
|
732
|
Chris@49
|
733
|
Chris@49
|
734
|
Chris@49
|
735 template<typename eT>
|
Chris@49
|
736 arma_inline
|
Chris@49
|
737 eT
|
Chris@49
|
738 diagview<eT>::operator[](const uword ii) const
|
Chris@49
|
739 {
|
Chris@49
|
740 return m.at(ii+row_offset, ii+col_offset);
|
Chris@49
|
741 }
|
Chris@49
|
742
|
Chris@49
|
743
|
Chris@49
|
744
|
Chris@49
|
745 template<typename eT>
|
Chris@49
|
746 arma_inline
|
Chris@49
|
747 eT&
|
Chris@49
|
748 diagview<eT>::at(const uword ii)
|
Chris@49
|
749 {
|
Chris@49
|
750 return (const_cast< Mat<eT>& >(m)).at(ii+row_offset, ii+col_offset);
|
Chris@49
|
751 }
|
Chris@49
|
752
|
Chris@49
|
753
|
Chris@49
|
754
|
Chris@49
|
755 template<typename eT>
|
Chris@49
|
756 arma_inline
|
Chris@49
|
757 eT
|
Chris@49
|
758 diagview<eT>::at(const uword ii) const
|
Chris@49
|
759 {
|
Chris@49
|
760 return m.at(ii+row_offset, ii+col_offset);
|
Chris@49
|
761 }
|
Chris@49
|
762
|
Chris@49
|
763
|
Chris@49
|
764
|
Chris@49
|
765 template<typename eT>
|
Chris@49
|
766 arma_inline
|
Chris@49
|
767 eT&
|
Chris@49
|
768 diagview<eT>::operator()(const uword ii)
|
Chris@49
|
769 {
|
Chris@49
|
770 arma_debug_check( (ii >= n_elem), "diagview::operator(): out of bounds" );
|
Chris@49
|
771
|
Chris@49
|
772 return (const_cast< Mat<eT>& >(m)).at(ii+row_offset, ii+col_offset);
|
Chris@49
|
773 }
|
Chris@49
|
774
|
Chris@49
|
775
|
Chris@49
|
776
|
Chris@49
|
777 template<typename eT>
|
Chris@49
|
778 arma_inline
|
Chris@49
|
779 eT
|
Chris@49
|
780 diagview<eT>::operator()(const uword ii) const
|
Chris@49
|
781 {
|
Chris@49
|
782 arma_debug_check( (ii >= n_elem), "diagview::operator(): out of bounds" );
|
Chris@49
|
783
|
Chris@49
|
784 return m.at(ii+row_offset, ii+col_offset);
|
Chris@49
|
785 }
|
Chris@49
|
786
|
Chris@49
|
787
|
Chris@49
|
788
|
Chris@49
|
789 template<typename eT>
|
Chris@49
|
790 arma_inline
|
Chris@49
|
791 eT&
|
Chris@49
|
792 diagview<eT>::at(const uword row, const uword)
|
Chris@49
|
793 {
|
Chris@49
|
794 return (const_cast< Mat<eT>& >(m)).at(row+row_offset, row+col_offset);
|
Chris@49
|
795 }
|
Chris@49
|
796
|
Chris@49
|
797
|
Chris@49
|
798
|
Chris@49
|
799 template<typename eT>
|
Chris@49
|
800 arma_inline
|
Chris@49
|
801 eT
|
Chris@49
|
802 diagview<eT>::at(const uword row, const uword) const
|
Chris@49
|
803 {
|
Chris@49
|
804 return m.at(row+row_offset, row+col_offset);
|
Chris@49
|
805 }
|
Chris@49
|
806
|
Chris@49
|
807
|
Chris@49
|
808
|
Chris@49
|
809 template<typename eT>
|
Chris@49
|
810 arma_inline
|
Chris@49
|
811 eT&
|
Chris@49
|
812 diagview<eT>::operator()(const uword row, const uword col)
|
Chris@49
|
813 {
|
Chris@49
|
814 arma_debug_check( ((row >= n_elem) || (col > 0)), "diagview::operator(): out of bounds" );
|
Chris@49
|
815
|
Chris@49
|
816 return (const_cast< Mat<eT>& >(m)).at(row+row_offset, row+col_offset);
|
Chris@49
|
817 }
|
Chris@49
|
818
|
Chris@49
|
819
|
Chris@49
|
820
|
Chris@49
|
821 template<typename eT>
|
Chris@49
|
822 arma_inline
|
Chris@49
|
823 eT
|
Chris@49
|
824 diagview<eT>::operator()(const uword row, const uword col) const
|
Chris@49
|
825 {
|
Chris@49
|
826 arma_debug_check( ((row >= n_elem) || (col > 0)), "diagview::operator(): out of bounds" );
|
Chris@49
|
827
|
Chris@49
|
828 return m.at(row+row_offset, row+col_offset);
|
Chris@49
|
829 }
|
Chris@49
|
830
|
Chris@49
|
831
|
Chris@49
|
832
|
Chris@49
|
833 template<typename eT>
|
Chris@49
|
834 arma_inline
|
Chris@49
|
835 const Op<diagview<eT>,op_htrans>
|
Chris@49
|
836 diagview<eT>::t() const
|
Chris@49
|
837 {
|
Chris@49
|
838 return Op<diagview<eT>,op_htrans>(*this);
|
Chris@49
|
839 }
|
Chris@49
|
840
|
Chris@49
|
841
|
Chris@49
|
842
|
Chris@49
|
843 template<typename eT>
|
Chris@49
|
844 arma_inline
|
Chris@49
|
845 const Op<diagview<eT>,op_htrans>
|
Chris@49
|
846 diagview<eT>::ht() const
|
Chris@49
|
847 {
|
Chris@49
|
848 return Op<diagview<eT>,op_htrans>(*this);
|
Chris@49
|
849 }
|
Chris@49
|
850
|
Chris@49
|
851
|
Chris@49
|
852
|
Chris@49
|
853 template<typename eT>
|
Chris@49
|
854 arma_inline
|
Chris@49
|
855 const Op<diagview<eT>,op_strans>
|
Chris@49
|
856 diagview<eT>::st() const
|
Chris@49
|
857 {
|
Chris@49
|
858 return Op<diagview<eT>,op_strans>(*this);
|
Chris@49
|
859 }
|
Chris@49
|
860
|
Chris@49
|
861
|
Chris@49
|
862
|
Chris@49
|
863 template<typename eT>
|
Chris@49
|
864 inline
|
Chris@49
|
865 void
|
Chris@49
|
866 diagview<eT>::fill(const eT val)
|
Chris@49
|
867 {
|
Chris@49
|
868 arma_extra_debug_sigprint();
|
Chris@49
|
869
|
Chris@49
|
870 Mat<eT>& x = const_cast< Mat<eT>& >(m);
|
Chris@49
|
871
|
Chris@49
|
872 for(uword ii=0; ii < n_elem; ++ii)
|
Chris@49
|
873 {
|
Chris@49
|
874 x.at(ii+row_offset, ii+col_offset) = val;
|
Chris@49
|
875 }
|
Chris@49
|
876 }
|
Chris@49
|
877
|
Chris@49
|
878
|
Chris@49
|
879
|
Chris@49
|
880 template<typename eT>
|
Chris@49
|
881 inline
|
Chris@49
|
882 void
|
Chris@49
|
883 diagview<eT>::zeros()
|
Chris@49
|
884 {
|
Chris@49
|
885 arma_extra_debug_sigprint();
|
Chris@49
|
886
|
Chris@49
|
887 (*this).fill(eT(0));
|
Chris@49
|
888 }
|
Chris@49
|
889
|
Chris@49
|
890
|
Chris@49
|
891
|
Chris@49
|
892 template<typename eT>
|
Chris@49
|
893 inline
|
Chris@49
|
894 void
|
Chris@49
|
895 diagview<eT>::ones()
|
Chris@49
|
896 {
|
Chris@49
|
897 arma_extra_debug_sigprint();
|
Chris@49
|
898
|
Chris@49
|
899 (*this).fill(eT(1));
|
Chris@49
|
900 }
|
Chris@49
|
901
|
Chris@49
|
902
|
Chris@49
|
903
|
Chris@49
|
904 //! @}
|