Chris@49
|
1 // Copyright (C) 2008-2012 NICTA (www.nicta.com.au)
|
Chris@49
|
2 // Copyright (C) 2008-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
|
Chris@49
|
9 //! \addtogroup fn_norm
|
Chris@49
|
10 //! @{
|
Chris@49
|
11
|
Chris@49
|
12
|
Chris@49
|
13
|
Chris@49
|
14 template<typename T1>
|
Chris@49
|
15 arma_hot
|
Chris@49
|
16 inline
|
Chris@49
|
17 typename T1::pod_type
|
Chris@49
|
18 arma_vec_norm_1(const Proxy<T1>& P)
|
Chris@49
|
19 {
|
Chris@49
|
20 arma_extra_debug_sigprint();
|
Chris@49
|
21
|
Chris@49
|
22 typedef typename T1::pod_type T;
|
Chris@49
|
23
|
Chris@49
|
24 T acc = T(0);
|
Chris@49
|
25
|
Chris@49
|
26 if(Proxy<T1>::prefer_at_accessor == false)
|
Chris@49
|
27 {
|
Chris@49
|
28 typename Proxy<T1>::ea_type A = P.get_ea();
|
Chris@49
|
29
|
Chris@49
|
30 const uword N = P.get_n_elem();
|
Chris@49
|
31
|
Chris@49
|
32 T acc1 = T(0);
|
Chris@49
|
33 T acc2 = T(0);
|
Chris@49
|
34
|
Chris@49
|
35 uword i,j;
|
Chris@49
|
36 for(i=0, j=1; j<N; i+=2, j+=2)
|
Chris@49
|
37 {
|
Chris@49
|
38 acc1 += std::abs(A[i]);
|
Chris@49
|
39 acc2 += std::abs(A[j]);
|
Chris@49
|
40 }
|
Chris@49
|
41
|
Chris@49
|
42 if(i < N)
|
Chris@49
|
43 {
|
Chris@49
|
44 acc1 += std::abs(A[i]);
|
Chris@49
|
45 }
|
Chris@49
|
46
|
Chris@49
|
47 acc = acc1 + acc2;
|
Chris@49
|
48 }
|
Chris@49
|
49 else
|
Chris@49
|
50 {
|
Chris@49
|
51 const uword n_rows = P.get_n_rows();
|
Chris@49
|
52 const uword n_cols = P.get_n_cols();
|
Chris@49
|
53
|
Chris@49
|
54 if(n_rows == 1)
|
Chris@49
|
55 {
|
Chris@49
|
56 for(uword col=0; col<n_cols; ++col)
|
Chris@49
|
57 {
|
Chris@49
|
58 acc += std::abs(P.at(0,col));
|
Chris@49
|
59 }
|
Chris@49
|
60 }
|
Chris@49
|
61 else
|
Chris@49
|
62 {
|
Chris@49
|
63 for(uword col=0; col<n_cols; ++col)
|
Chris@49
|
64 {
|
Chris@49
|
65 uword i,j;
|
Chris@49
|
66
|
Chris@49
|
67 for(i=0, j=1; j<n_rows; i+=2, j+=2)
|
Chris@49
|
68 {
|
Chris@49
|
69 acc += std::abs(P.at(i,col));
|
Chris@49
|
70 acc += std::abs(P.at(j,col));
|
Chris@49
|
71 }
|
Chris@49
|
72
|
Chris@49
|
73 if(i < n_rows)
|
Chris@49
|
74 {
|
Chris@49
|
75 acc += std::abs(P.at(i,col));
|
Chris@49
|
76 }
|
Chris@49
|
77 }
|
Chris@49
|
78 }
|
Chris@49
|
79 }
|
Chris@49
|
80
|
Chris@49
|
81 return acc;
|
Chris@49
|
82 }
|
Chris@49
|
83
|
Chris@49
|
84
|
Chris@49
|
85
|
Chris@49
|
86 template<typename T1>
|
Chris@49
|
87 arma_hot
|
Chris@49
|
88 inline
|
Chris@49
|
89 typename T1::pod_type
|
Chris@49
|
90 arma_vec_norm_2
|
Chris@49
|
91 (
|
Chris@49
|
92 const Proxy<T1>& P,
|
Chris@49
|
93 const typename arma_not_cx<typename T1::elem_type>::result* junk = 0
|
Chris@49
|
94 )
|
Chris@49
|
95 {
|
Chris@49
|
96 arma_extra_debug_sigprint();
|
Chris@49
|
97 arma_ignore(junk);
|
Chris@49
|
98
|
Chris@49
|
99 typedef typename T1::pod_type T;
|
Chris@49
|
100
|
Chris@49
|
101 T acc = T(0);
|
Chris@49
|
102
|
Chris@49
|
103 if(Proxy<T1>::prefer_at_accessor == false)
|
Chris@49
|
104 {
|
Chris@49
|
105 typename Proxy<T1>::ea_type A = P.get_ea();
|
Chris@49
|
106
|
Chris@49
|
107 const uword N = P.get_n_elem();
|
Chris@49
|
108
|
Chris@49
|
109 T acc1 = T(0);
|
Chris@49
|
110 T acc2 = T(0);
|
Chris@49
|
111
|
Chris@49
|
112 uword i,j;
|
Chris@49
|
113
|
Chris@49
|
114 for(i=0, j=1; j<N; i+=2, j+=2)
|
Chris@49
|
115 {
|
Chris@49
|
116 const T tmp_i = A[i];
|
Chris@49
|
117 const T tmp_j = A[j];
|
Chris@49
|
118
|
Chris@49
|
119 acc1 += tmp_i * tmp_i;
|
Chris@49
|
120 acc2 += tmp_j * tmp_j;
|
Chris@49
|
121 }
|
Chris@49
|
122
|
Chris@49
|
123 if(i < N)
|
Chris@49
|
124 {
|
Chris@49
|
125 const T tmp_i = A[i];
|
Chris@49
|
126
|
Chris@49
|
127 acc1 += tmp_i * tmp_i;
|
Chris@49
|
128 }
|
Chris@49
|
129
|
Chris@49
|
130 acc = acc1 + acc2;
|
Chris@49
|
131 }
|
Chris@49
|
132 else
|
Chris@49
|
133 {
|
Chris@49
|
134 const uword n_rows = P.get_n_rows();
|
Chris@49
|
135 const uword n_cols = P.get_n_cols();
|
Chris@49
|
136
|
Chris@49
|
137 if(n_rows == 1)
|
Chris@49
|
138 {
|
Chris@49
|
139 for(uword col=0; col<n_cols; ++col)
|
Chris@49
|
140 {
|
Chris@49
|
141 const T tmp = P.at(0,col);
|
Chris@49
|
142
|
Chris@49
|
143 acc += tmp * tmp;
|
Chris@49
|
144 }
|
Chris@49
|
145 }
|
Chris@49
|
146 else
|
Chris@49
|
147 {
|
Chris@49
|
148 for(uword col=0; col<n_cols; ++col)
|
Chris@49
|
149 {
|
Chris@49
|
150 uword i,j;
|
Chris@49
|
151 for(i=0, j=1; j<n_rows; i+=2, j+=2)
|
Chris@49
|
152 {
|
Chris@49
|
153 const T tmp_i = P.at(i,col);
|
Chris@49
|
154 const T tmp_j = P.at(j,col);
|
Chris@49
|
155
|
Chris@49
|
156 acc += tmp_i * tmp_i;
|
Chris@49
|
157 acc += tmp_j * tmp_j;
|
Chris@49
|
158 }
|
Chris@49
|
159
|
Chris@49
|
160 if(i < n_rows)
|
Chris@49
|
161 {
|
Chris@49
|
162 const T tmp_i = P.at(i,col);
|
Chris@49
|
163
|
Chris@49
|
164 acc += tmp_i * tmp_i;
|
Chris@49
|
165 }
|
Chris@49
|
166 }
|
Chris@49
|
167 }
|
Chris@49
|
168 }
|
Chris@49
|
169
|
Chris@49
|
170 return std::sqrt(acc);
|
Chris@49
|
171 }
|
Chris@49
|
172
|
Chris@49
|
173
|
Chris@49
|
174
|
Chris@49
|
175 template<typename T1>
|
Chris@49
|
176 arma_hot
|
Chris@49
|
177 inline
|
Chris@49
|
178 typename T1::pod_type
|
Chris@49
|
179 arma_vec_norm_2
|
Chris@49
|
180 (
|
Chris@49
|
181 const Proxy<T1>& P,
|
Chris@49
|
182 const typename arma_cx_only<typename T1::elem_type>::result* junk = 0
|
Chris@49
|
183 )
|
Chris@49
|
184 {
|
Chris@49
|
185 arma_extra_debug_sigprint();
|
Chris@49
|
186 arma_ignore(junk);
|
Chris@49
|
187
|
Chris@49
|
188 typedef typename T1::pod_type T;
|
Chris@49
|
189
|
Chris@49
|
190 T acc = T(0);
|
Chris@49
|
191
|
Chris@49
|
192 if(Proxy<T1>::prefer_at_accessor == false)
|
Chris@49
|
193 {
|
Chris@49
|
194 typename Proxy<T1>::ea_type A = P.get_ea();
|
Chris@49
|
195
|
Chris@49
|
196 const uword N = P.get_n_elem();
|
Chris@49
|
197
|
Chris@49
|
198 for(uword i=0; i<N; ++i)
|
Chris@49
|
199 {
|
Chris@49
|
200 const T tmp = std::abs(A[i]);
|
Chris@49
|
201 acc += tmp*tmp;
|
Chris@49
|
202 }
|
Chris@49
|
203 }
|
Chris@49
|
204 else
|
Chris@49
|
205 {
|
Chris@49
|
206 const uword n_rows = P.get_n_rows();
|
Chris@49
|
207 const uword n_cols = P.get_n_cols();
|
Chris@49
|
208
|
Chris@49
|
209 if(n_rows == 1)
|
Chris@49
|
210 {
|
Chris@49
|
211 for(uword col=0; col<n_cols; ++col)
|
Chris@49
|
212 {
|
Chris@49
|
213 const T tmp = std::abs(P.at(0,col));
|
Chris@49
|
214 acc += tmp*tmp;
|
Chris@49
|
215 }
|
Chris@49
|
216 }
|
Chris@49
|
217 else
|
Chris@49
|
218 {
|
Chris@49
|
219 for(uword col=0; col<n_cols; ++col)
|
Chris@49
|
220 for(uword row=0; row<n_rows; ++row)
|
Chris@49
|
221 {
|
Chris@49
|
222 const T tmp = std::abs(P.at(row,col));
|
Chris@49
|
223 acc += tmp*tmp;
|
Chris@49
|
224 }
|
Chris@49
|
225 }
|
Chris@49
|
226 }
|
Chris@49
|
227
|
Chris@49
|
228 return std::sqrt(acc);
|
Chris@49
|
229 }
|
Chris@49
|
230
|
Chris@49
|
231
|
Chris@49
|
232
|
Chris@49
|
233 template<typename T1>
|
Chris@49
|
234 arma_hot
|
Chris@49
|
235 inline
|
Chris@49
|
236 typename T1::pod_type
|
Chris@49
|
237 arma_vec_norm_k
|
Chris@49
|
238 (
|
Chris@49
|
239 const Proxy<T1>& P,
|
Chris@49
|
240 const int k
|
Chris@49
|
241 )
|
Chris@49
|
242 {
|
Chris@49
|
243 arma_extra_debug_sigprint();
|
Chris@49
|
244
|
Chris@49
|
245 typedef typename T1::pod_type T;
|
Chris@49
|
246
|
Chris@49
|
247 T acc = T(0);
|
Chris@49
|
248
|
Chris@49
|
249 if(Proxy<T1>::prefer_at_accessor == false)
|
Chris@49
|
250 {
|
Chris@49
|
251 typename Proxy<T1>::ea_type A = P.get_ea();
|
Chris@49
|
252
|
Chris@49
|
253 const uword N = P.get_n_elem();
|
Chris@49
|
254
|
Chris@49
|
255 uword i,j;
|
Chris@49
|
256
|
Chris@49
|
257 for(i=0, j=1; j<N; i+=2, j+=2)
|
Chris@49
|
258 {
|
Chris@49
|
259 acc += std::pow(std::abs(A[i]), k);
|
Chris@49
|
260 acc += std::pow(std::abs(A[j]), k);
|
Chris@49
|
261 }
|
Chris@49
|
262
|
Chris@49
|
263 if(i < N)
|
Chris@49
|
264 {
|
Chris@49
|
265 acc += std::pow(std::abs(A[i]), k);
|
Chris@49
|
266 }
|
Chris@49
|
267 }
|
Chris@49
|
268 else
|
Chris@49
|
269 {
|
Chris@49
|
270 const uword n_rows = P.get_n_rows();
|
Chris@49
|
271 const uword n_cols = P.get_n_cols();
|
Chris@49
|
272
|
Chris@49
|
273 if(n_rows != 1)
|
Chris@49
|
274 {
|
Chris@49
|
275 for(uword col=0; col < n_cols; ++col)
|
Chris@49
|
276 for(uword row=0; row < n_rows; ++row)
|
Chris@49
|
277 {
|
Chris@49
|
278 acc += std::pow(std::abs(P.at(row,col)), k);
|
Chris@49
|
279 }
|
Chris@49
|
280 }
|
Chris@49
|
281 else
|
Chris@49
|
282 {
|
Chris@49
|
283 for(uword col=0; col < n_cols; ++col)
|
Chris@49
|
284 {
|
Chris@49
|
285 acc += std::pow(std::abs(P.at(0,col)), k);
|
Chris@49
|
286 }
|
Chris@49
|
287 }
|
Chris@49
|
288 }
|
Chris@49
|
289
|
Chris@49
|
290 return std::pow(acc, T(1)/T(k));
|
Chris@49
|
291 }
|
Chris@49
|
292
|
Chris@49
|
293
|
Chris@49
|
294
|
Chris@49
|
295 template<typename T1>
|
Chris@49
|
296 arma_hot
|
Chris@49
|
297 inline
|
Chris@49
|
298 typename T1::pod_type
|
Chris@49
|
299 arma_vec_norm_max(const Proxy<T1>& P)
|
Chris@49
|
300 {
|
Chris@49
|
301 arma_extra_debug_sigprint();
|
Chris@49
|
302
|
Chris@49
|
303 typedef typename T1::pod_type T;
|
Chris@49
|
304
|
Chris@49
|
305 const uword N = P.get_n_elem();
|
Chris@49
|
306
|
Chris@49
|
307 T max_val = (N != 1) ? priv::most_neg<T>() : std::abs(P[0]);
|
Chris@49
|
308
|
Chris@49
|
309 if(Proxy<T1>::prefer_at_accessor == false)
|
Chris@49
|
310 {
|
Chris@49
|
311 typename Proxy<T1>::ea_type A = P.get_ea();
|
Chris@49
|
312
|
Chris@49
|
313 uword i,j;
|
Chris@49
|
314 for(i=0, j=1; j<N; i+=2, j+=2)
|
Chris@49
|
315 {
|
Chris@49
|
316 const T tmp_i = std::abs(A[i]);
|
Chris@49
|
317 const T tmp_j = std::abs(A[j]);
|
Chris@49
|
318
|
Chris@49
|
319 if(max_val < tmp_i) { max_val = tmp_i; }
|
Chris@49
|
320 if(max_val < tmp_j) { max_val = tmp_j; }
|
Chris@49
|
321 }
|
Chris@49
|
322
|
Chris@49
|
323 if(i < N)
|
Chris@49
|
324 {
|
Chris@49
|
325 const T tmp_i = std::abs(A[i]);
|
Chris@49
|
326
|
Chris@49
|
327 if(max_val < tmp_i) { max_val = tmp_i; }
|
Chris@49
|
328 }
|
Chris@49
|
329 }
|
Chris@49
|
330 else
|
Chris@49
|
331 {
|
Chris@49
|
332 const uword n_rows = P.get_n_rows();
|
Chris@49
|
333 const uword n_cols = P.get_n_cols();
|
Chris@49
|
334
|
Chris@49
|
335 if(n_rows != 1)
|
Chris@49
|
336 {
|
Chris@49
|
337 for(uword col=0; col < n_cols; ++col)
|
Chris@49
|
338 for(uword row=0; row < n_rows; ++row)
|
Chris@49
|
339 {
|
Chris@49
|
340 const T tmp = std::abs(P.at(row,col));
|
Chris@49
|
341
|
Chris@49
|
342 if(max_val < tmp) { max_val = tmp; }
|
Chris@49
|
343 }
|
Chris@49
|
344 }
|
Chris@49
|
345 else
|
Chris@49
|
346 {
|
Chris@49
|
347 for(uword col=0; col < n_cols; ++col)
|
Chris@49
|
348 {
|
Chris@49
|
349 const T tmp = std::abs(P.at(0,col));
|
Chris@49
|
350
|
Chris@49
|
351 if(max_val < tmp) { max_val = tmp; }
|
Chris@49
|
352 }
|
Chris@49
|
353 }
|
Chris@49
|
354 }
|
Chris@49
|
355
|
Chris@49
|
356 return max_val;
|
Chris@49
|
357 }
|
Chris@49
|
358
|
Chris@49
|
359
|
Chris@49
|
360
|
Chris@49
|
361 template<typename T1>
|
Chris@49
|
362 arma_hot
|
Chris@49
|
363 inline
|
Chris@49
|
364 typename T1::pod_type
|
Chris@49
|
365 arma_vec_norm_min(const Proxy<T1>& P)
|
Chris@49
|
366 {
|
Chris@49
|
367 arma_extra_debug_sigprint();
|
Chris@49
|
368
|
Chris@49
|
369 typedef typename T1::pod_type T;
|
Chris@49
|
370
|
Chris@49
|
371 const uword N = P.get_n_elem();
|
Chris@49
|
372
|
Chris@49
|
373 T min_val = (N != 1) ? priv::most_pos<T>() : std::abs(P[0]);
|
Chris@49
|
374
|
Chris@49
|
375 if(Proxy<T1>::prefer_at_accessor == false)
|
Chris@49
|
376 {
|
Chris@49
|
377 typename Proxy<T1>::ea_type A = P.get_ea();
|
Chris@49
|
378
|
Chris@49
|
379 uword i,j;
|
Chris@49
|
380 for(i=0, j=1; j<N; i+=2, j+=2)
|
Chris@49
|
381 {
|
Chris@49
|
382 const T tmp_i = std::abs(A[i]);
|
Chris@49
|
383 const T tmp_j = std::abs(A[j]);
|
Chris@49
|
384
|
Chris@49
|
385 if(min_val > tmp_i) { min_val = tmp_i; }
|
Chris@49
|
386 if(min_val > tmp_j) { min_val = tmp_j; }
|
Chris@49
|
387 }
|
Chris@49
|
388
|
Chris@49
|
389 if(i < N)
|
Chris@49
|
390 {
|
Chris@49
|
391 const T tmp_i = std::abs(A[i]);
|
Chris@49
|
392
|
Chris@49
|
393 if(min_val > tmp_i) { min_val = tmp_i; }
|
Chris@49
|
394 }
|
Chris@49
|
395 }
|
Chris@49
|
396 else
|
Chris@49
|
397 {
|
Chris@49
|
398 const uword n_rows = P.get_n_rows();
|
Chris@49
|
399 const uword n_cols = P.get_n_cols();
|
Chris@49
|
400
|
Chris@49
|
401 if(n_rows != 1)
|
Chris@49
|
402 {
|
Chris@49
|
403 for(uword col=0; col < n_cols; ++col)
|
Chris@49
|
404 for(uword row=0; row < n_rows; ++row)
|
Chris@49
|
405 {
|
Chris@49
|
406 const T tmp = std::abs(P.at(row,col));
|
Chris@49
|
407
|
Chris@49
|
408 if(min_val > tmp) { min_val = tmp; }
|
Chris@49
|
409 }
|
Chris@49
|
410 }
|
Chris@49
|
411 else
|
Chris@49
|
412 {
|
Chris@49
|
413 for(uword col=0; col < n_cols; ++col)
|
Chris@49
|
414 {
|
Chris@49
|
415 const T tmp = std::abs(P.at(0,col));
|
Chris@49
|
416
|
Chris@49
|
417 if(min_val > tmp) { min_val = tmp; }
|
Chris@49
|
418 }
|
Chris@49
|
419 }
|
Chris@49
|
420 }
|
Chris@49
|
421
|
Chris@49
|
422 return min_val;
|
Chris@49
|
423 }
|
Chris@49
|
424
|
Chris@49
|
425
|
Chris@49
|
426
|
Chris@49
|
427 template<typename T1>
|
Chris@49
|
428 inline
|
Chris@49
|
429 typename T1::pod_type
|
Chris@49
|
430 arma_mat_norm_1(const Proxy<T1>& P)
|
Chris@49
|
431 {
|
Chris@49
|
432 arma_extra_debug_sigprint();
|
Chris@49
|
433
|
Chris@49
|
434 // TODO: this can be sped up with a dedicated implementation
|
Chris@49
|
435 return as_scalar( max( sum(abs(P.Q), 0), 1) );
|
Chris@49
|
436 }
|
Chris@49
|
437
|
Chris@49
|
438
|
Chris@49
|
439
|
Chris@49
|
440 template<typename T1>
|
Chris@49
|
441 inline
|
Chris@49
|
442 typename T1::pod_type
|
Chris@49
|
443 arma_mat_norm_2(const Proxy<T1>& P)
|
Chris@49
|
444 {
|
Chris@49
|
445 arma_extra_debug_sigprint();
|
Chris@49
|
446
|
Chris@49
|
447 typedef typename T1::pod_type T;
|
Chris@49
|
448
|
Chris@49
|
449 // TODO: is the SVD based approach only valid for square matrices?
|
Chris@49
|
450
|
Chris@49
|
451 Col<T> S;
|
Chris@49
|
452 svd(S, P.Q);
|
Chris@49
|
453
|
Chris@49
|
454 return (S.n_elem > 0) ? max(S) : T(0);
|
Chris@49
|
455 }
|
Chris@49
|
456
|
Chris@49
|
457
|
Chris@49
|
458
|
Chris@49
|
459 template<typename T1>
|
Chris@49
|
460 inline
|
Chris@49
|
461 typename T1::pod_type
|
Chris@49
|
462 arma_mat_norm_inf(const Proxy<T1>& P)
|
Chris@49
|
463 {
|
Chris@49
|
464 arma_extra_debug_sigprint();
|
Chris@49
|
465
|
Chris@49
|
466 // TODO: this can be sped up with a dedicated implementation
|
Chris@49
|
467 return as_scalar( max( sum(abs(P.Q), 1), 0) );
|
Chris@49
|
468 }
|
Chris@49
|
469
|
Chris@49
|
470
|
Chris@49
|
471
|
Chris@49
|
472 template<typename T1>
|
Chris@49
|
473 inline
|
Chris@49
|
474 arma_warn_unused
|
Chris@49
|
475 typename enable_if2< is_arma_type<T1>::value, typename T1::pod_type >::result
|
Chris@49
|
476 norm
|
Chris@49
|
477 (
|
Chris@49
|
478 const T1& X,
|
Chris@49
|
479 const uword k,
|
Chris@49
|
480 const typename arma_real_or_cx_only<typename T1::elem_type>::result* junk = 0
|
Chris@49
|
481 )
|
Chris@49
|
482 {
|
Chris@49
|
483 arma_extra_debug_sigprint();
|
Chris@49
|
484 arma_ignore(junk);
|
Chris@49
|
485
|
Chris@49
|
486 typedef typename T1::pod_type T;
|
Chris@49
|
487
|
Chris@49
|
488 const Proxy<T1> P(X);
|
Chris@49
|
489
|
Chris@49
|
490 if(P.get_n_elem() == 0)
|
Chris@49
|
491 {
|
Chris@49
|
492 return T(0);
|
Chris@49
|
493 }
|
Chris@49
|
494
|
Chris@49
|
495 const bool is_vec = (P.get_n_rows() == 1) || (P.get_n_cols() == 1);
|
Chris@49
|
496
|
Chris@49
|
497 if(is_vec == true)
|
Chris@49
|
498 {
|
Chris@49
|
499 switch(k)
|
Chris@49
|
500 {
|
Chris@49
|
501 case 1:
|
Chris@49
|
502 return arma_vec_norm_1(P);
|
Chris@49
|
503 break;
|
Chris@49
|
504
|
Chris@49
|
505 case 2:
|
Chris@49
|
506 return arma_vec_norm_2(P);
|
Chris@49
|
507 break;
|
Chris@49
|
508
|
Chris@49
|
509 default:
|
Chris@49
|
510 {
|
Chris@49
|
511 arma_debug_check( (k == 0), "norm(): k must be greater than zero" );
|
Chris@49
|
512 return arma_vec_norm_k(P, int(k));
|
Chris@49
|
513 }
|
Chris@49
|
514 }
|
Chris@49
|
515 }
|
Chris@49
|
516 else
|
Chris@49
|
517 {
|
Chris@49
|
518 switch(k)
|
Chris@49
|
519 {
|
Chris@49
|
520 case 1:
|
Chris@49
|
521 return arma_mat_norm_1(P);
|
Chris@49
|
522 break;
|
Chris@49
|
523
|
Chris@49
|
524 case 2:
|
Chris@49
|
525 return arma_mat_norm_2(P);
|
Chris@49
|
526 break;
|
Chris@49
|
527
|
Chris@49
|
528 default:
|
Chris@49
|
529 arma_stop("norm(): unsupported matrix norm type");
|
Chris@49
|
530 return T(0);
|
Chris@49
|
531 }
|
Chris@49
|
532 }
|
Chris@49
|
533 }
|
Chris@49
|
534
|
Chris@49
|
535
|
Chris@49
|
536
|
Chris@49
|
537 template<typename T1>
|
Chris@49
|
538 inline
|
Chris@49
|
539 arma_warn_unused
|
Chris@49
|
540 typename enable_if2< is_arma_type<T1>::value, typename T1::pod_type >::result
|
Chris@49
|
541 norm
|
Chris@49
|
542 (
|
Chris@49
|
543 const T1& X,
|
Chris@49
|
544 const char* method,
|
Chris@49
|
545 const typename arma_real_or_cx_only<typename T1::elem_type>::result* junk = 0
|
Chris@49
|
546 )
|
Chris@49
|
547 {
|
Chris@49
|
548 arma_extra_debug_sigprint();
|
Chris@49
|
549 arma_ignore(junk);
|
Chris@49
|
550
|
Chris@49
|
551 typedef typename T1::pod_type T;
|
Chris@49
|
552
|
Chris@49
|
553 const Proxy<T1> P(X);
|
Chris@49
|
554
|
Chris@49
|
555 if(P.get_n_elem() == 0)
|
Chris@49
|
556 {
|
Chris@49
|
557 return T(0);
|
Chris@49
|
558 }
|
Chris@49
|
559
|
Chris@49
|
560 const char sig = method[0];
|
Chris@49
|
561 const bool is_vec = (P.get_n_rows() == 1) || (P.get_n_cols() == 1);
|
Chris@49
|
562
|
Chris@49
|
563 if(is_vec == true)
|
Chris@49
|
564 {
|
Chris@49
|
565 if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // max norm
|
Chris@49
|
566 {
|
Chris@49
|
567 return arma_vec_norm_max(P);
|
Chris@49
|
568 }
|
Chris@49
|
569 else
|
Chris@49
|
570 if(sig == '-') // min norm
|
Chris@49
|
571 {
|
Chris@49
|
572 return arma_vec_norm_min(P);
|
Chris@49
|
573 }
|
Chris@49
|
574 else
|
Chris@49
|
575 if( (sig == 'f') || (sig == 'F') )
|
Chris@49
|
576 {
|
Chris@49
|
577 return arma_vec_norm_2(P);
|
Chris@49
|
578 }
|
Chris@49
|
579 else
|
Chris@49
|
580 {
|
Chris@49
|
581 arma_stop("norm(): unsupported vector norm type");
|
Chris@49
|
582 return T(0);
|
Chris@49
|
583 }
|
Chris@49
|
584 }
|
Chris@49
|
585 else
|
Chris@49
|
586 {
|
Chris@49
|
587 if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // inf norm
|
Chris@49
|
588 {
|
Chris@49
|
589 return arma_mat_norm_inf(P);
|
Chris@49
|
590 }
|
Chris@49
|
591 else
|
Chris@49
|
592 if( (sig == 'f') || (sig == 'F') )
|
Chris@49
|
593 {
|
Chris@49
|
594 return arma_vec_norm_2(P);
|
Chris@49
|
595 }
|
Chris@49
|
596 else
|
Chris@49
|
597 {
|
Chris@49
|
598 arma_stop("norm(): unsupported matrix norm type");
|
Chris@49
|
599 return T(0);
|
Chris@49
|
600 }
|
Chris@49
|
601 }
|
Chris@49
|
602 }
|
Chris@49
|
603
|
Chris@49
|
604
|
Chris@49
|
605
|
Chris@49
|
606 //
|
Chris@49
|
607 // norms for sparse matrices
|
Chris@49
|
608
|
Chris@49
|
609
|
Chris@49
|
610
|
Chris@49
|
611 template<typename T1>
|
Chris@49
|
612 inline
|
Chris@49
|
613 typename T1::pod_type
|
Chris@49
|
614 arma_mat_norm_1(const SpProxy<T1>& P)
|
Chris@49
|
615 {
|
Chris@49
|
616 arma_extra_debug_sigprint();
|
Chris@49
|
617
|
Chris@49
|
618 // TODO: this can be sped up with a dedicated implementation
|
Chris@49
|
619 return as_scalar( max( sum(abs(P.Q), 0), 1) );
|
Chris@49
|
620 }
|
Chris@49
|
621
|
Chris@49
|
622
|
Chris@49
|
623
|
Chris@49
|
624 // template<typename T1>
|
Chris@49
|
625 // inline
|
Chris@49
|
626 // typename T1::pod_type
|
Chris@49
|
627 // arma_mat_norm_2(const SpProxy<T1>& P)
|
Chris@49
|
628 // {
|
Chris@49
|
629 // arma_extra_debug_sigprint();
|
Chris@49
|
630 //
|
Chris@49
|
631 // // TODO: norm = sqrt( largest eigenvalue of (A^H)*A ), where ^H is the conjugate transpose
|
Chris@49
|
632 // // TODO: can use ARPACK or directly implement the Arnoldi iteration
|
Chris@49
|
633 // // http://math.stackexchange.com/questions/4368/computing-the-largest-eigenvalue-of-a-very-large-sparse-matrix
|
Chris@49
|
634 // }
|
Chris@49
|
635
|
Chris@49
|
636
|
Chris@49
|
637
|
Chris@49
|
638 template<typename T1>
|
Chris@49
|
639 inline
|
Chris@49
|
640 typename T1::pod_type
|
Chris@49
|
641 arma_mat_norm_inf(const SpProxy<T1>& P)
|
Chris@49
|
642 {
|
Chris@49
|
643 arma_extra_debug_sigprint();
|
Chris@49
|
644
|
Chris@49
|
645 // TODO: this can be sped up with a dedicated implementation
|
Chris@49
|
646 return as_scalar( max( sum(abs(P.Q), 1), 0) );
|
Chris@49
|
647 }
|
Chris@49
|
648
|
Chris@49
|
649
|
Chris@49
|
650
|
Chris@49
|
651 template<typename T1>
|
Chris@49
|
652 inline
|
Chris@49
|
653 arma_warn_unused
|
Chris@49
|
654 typename enable_if2< is_arma_sparse_type<T1>::value, typename T1::pod_type >::result
|
Chris@49
|
655 norm
|
Chris@49
|
656 (
|
Chris@49
|
657 const T1& X,
|
Chris@49
|
658 const uword k,
|
Chris@49
|
659 const typename arma_real_or_cx_only<typename T1::elem_type>::result* junk = 0
|
Chris@49
|
660 )
|
Chris@49
|
661 {
|
Chris@49
|
662 arma_extra_debug_sigprint();
|
Chris@49
|
663 arma_ignore(junk);
|
Chris@49
|
664
|
Chris@49
|
665 typedef typename T1::elem_type eT;
|
Chris@49
|
666 typedef typename T1::pod_type T;
|
Chris@49
|
667
|
Chris@49
|
668 const SpProxy<T1> P(X);
|
Chris@49
|
669
|
Chris@49
|
670 if(P.get_n_nonzero() == 0)
|
Chris@49
|
671 {
|
Chris@49
|
672 return T(0);
|
Chris@49
|
673 }
|
Chris@49
|
674
|
Chris@49
|
675 const bool is_vec = (P.get_n_rows() == 1) || (P.get_n_cols() == 1);
|
Chris@49
|
676
|
Chris@49
|
677 if(is_vec == true)
|
Chris@49
|
678 {
|
Chris@49
|
679 const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q);
|
Chris@49
|
680 const SpMat<eT>& A = tmp.M;
|
Chris@49
|
681
|
Chris@49
|
682 // create a fake dense vector to allow reuse of code for dense vectors
|
Chris@49
|
683 Col<eT> fake_vector( access::rwp(A.values), A.n_nonzero, false );
|
Chris@49
|
684
|
Chris@49
|
685 const Proxy< Col<eT> > P_fake_vector(fake_vector);
|
Chris@49
|
686
|
Chris@49
|
687 switch(k)
|
Chris@49
|
688 {
|
Chris@49
|
689 case 1:
|
Chris@49
|
690 return arma_vec_norm_1(P_fake_vector);
|
Chris@49
|
691 break;
|
Chris@49
|
692
|
Chris@49
|
693 case 2:
|
Chris@49
|
694 return arma_vec_norm_2(P_fake_vector);
|
Chris@49
|
695 break;
|
Chris@49
|
696
|
Chris@49
|
697 default:
|
Chris@49
|
698 {
|
Chris@49
|
699 arma_debug_check( (k == 0), "norm(): k must be greater than zero" );
|
Chris@49
|
700 return arma_vec_norm_k(P_fake_vector, int(k));
|
Chris@49
|
701 }
|
Chris@49
|
702 }
|
Chris@49
|
703 }
|
Chris@49
|
704 else
|
Chris@49
|
705 {
|
Chris@49
|
706 switch(k)
|
Chris@49
|
707 {
|
Chris@49
|
708 case 1:
|
Chris@49
|
709 return arma_mat_norm_1(P);
|
Chris@49
|
710 break;
|
Chris@49
|
711
|
Chris@49
|
712 // case 2:
|
Chris@49
|
713 // return arma_mat_norm_2(P);
|
Chris@49
|
714 // break;
|
Chris@49
|
715
|
Chris@49
|
716 default:
|
Chris@49
|
717 arma_stop("norm(): unsupported or unimplemented norm type for sparse matrices");
|
Chris@49
|
718 return T(0);
|
Chris@49
|
719 }
|
Chris@49
|
720 }
|
Chris@49
|
721 }
|
Chris@49
|
722
|
Chris@49
|
723
|
Chris@49
|
724
|
Chris@49
|
725 template<typename T1>
|
Chris@49
|
726 inline
|
Chris@49
|
727 arma_warn_unused
|
Chris@49
|
728 typename enable_if2< is_arma_sparse_type<T1>::value, typename T1::pod_type >::result
|
Chris@49
|
729 norm
|
Chris@49
|
730 (
|
Chris@49
|
731 const T1& X,
|
Chris@49
|
732 const char* method,
|
Chris@49
|
733 const typename arma_real_or_cx_only<typename T1::elem_type>::result* junk = 0
|
Chris@49
|
734 )
|
Chris@49
|
735 {
|
Chris@49
|
736 arma_extra_debug_sigprint();
|
Chris@49
|
737 arma_ignore(junk);
|
Chris@49
|
738
|
Chris@49
|
739 typedef typename T1::elem_type eT;
|
Chris@49
|
740 typedef typename T1::pod_type T;
|
Chris@49
|
741
|
Chris@49
|
742 const SpProxy<T1> P(X);
|
Chris@49
|
743
|
Chris@49
|
744 if(P.get_n_nonzero() == 0)
|
Chris@49
|
745 {
|
Chris@49
|
746 return T(0);
|
Chris@49
|
747 }
|
Chris@49
|
748
|
Chris@49
|
749
|
Chris@49
|
750 const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q);
|
Chris@49
|
751 const SpMat<eT>& A = tmp.M;
|
Chris@49
|
752
|
Chris@49
|
753 // create a fake dense vector to allow reuse of code for dense vectors
|
Chris@49
|
754 Col<eT> fake_vector( access::rwp(A.values), A.n_nonzero, false );
|
Chris@49
|
755
|
Chris@49
|
756 const Proxy< Col<eT> > P_fake_vector(fake_vector);
|
Chris@49
|
757
|
Chris@49
|
758
|
Chris@49
|
759 const char sig = method[0];
|
Chris@49
|
760 const bool is_vec = (P.get_n_rows() == 1) || (P.get_n_cols() == 1);
|
Chris@49
|
761
|
Chris@49
|
762 if(is_vec == true)
|
Chris@49
|
763 {
|
Chris@49
|
764 if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // max norm
|
Chris@49
|
765 {
|
Chris@49
|
766 return arma_vec_norm_max(P_fake_vector);
|
Chris@49
|
767 }
|
Chris@49
|
768 else
|
Chris@49
|
769 if(sig == '-') // min norm
|
Chris@49
|
770 {
|
Chris@49
|
771 const T val = arma_vec_norm_min(P_fake_vector);
|
Chris@49
|
772
|
Chris@49
|
773 if( P.get_n_nonzero() < P.get_n_elem() )
|
Chris@49
|
774 {
|
Chris@49
|
775 return (std::min)(T(0), val);
|
Chris@49
|
776 }
|
Chris@49
|
777 else
|
Chris@49
|
778 {
|
Chris@49
|
779 return val;
|
Chris@49
|
780 }
|
Chris@49
|
781 }
|
Chris@49
|
782 else
|
Chris@49
|
783 if( (sig == 'f') || (sig == 'F') )
|
Chris@49
|
784 {
|
Chris@49
|
785 return arma_vec_norm_2(P_fake_vector);
|
Chris@49
|
786 }
|
Chris@49
|
787 else
|
Chris@49
|
788 {
|
Chris@49
|
789 arma_stop("norm(): unsupported vector norm type");
|
Chris@49
|
790 return T(0);
|
Chris@49
|
791 }
|
Chris@49
|
792 }
|
Chris@49
|
793 else
|
Chris@49
|
794 {
|
Chris@49
|
795 if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // inf norm
|
Chris@49
|
796 {
|
Chris@49
|
797 return arma_mat_norm_inf(P);
|
Chris@49
|
798 }
|
Chris@49
|
799 else
|
Chris@49
|
800 if( (sig == 'f') || (sig == 'F') )
|
Chris@49
|
801 {
|
Chris@49
|
802 return arma_vec_norm_2(P_fake_vector);
|
Chris@49
|
803 }
|
Chris@49
|
804 else
|
Chris@49
|
805 {
|
Chris@49
|
806 arma_stop("norm(): unsupported matrix norm type");
|
Chris@49
|
807 return T(0);
|
Chris@49
|
808 }
|
Chris@49
|
809 }
|
Chris@49
|
810 }
|
Chris@49
|
811
|
Chris@49
|
812
|
Chris@49
|
813
|
Chris@49
|
814 //! @}
|