max@0
|
1 // Copyright (C) 2008-2011 NICTA (www.nicta.com.au)
|
max@0
|
2 // Copyright (C) 2008-2011 Conrad Sanderson
|
max@0
|
3 //
|
max@0
|
4 // This file is part of the Armadillo C++ library.
|
max@0
|
5 // It is provided without any warranty of fitness
|
max@0
|
6 // for any purpose. You can redistribute this file
|
max@0
|
7 // and/or modify it under the terms of the GNU
|
max@0
|
8 // Lesser General Public License (LGPL) as published
|
max@0
|
9 // by the Free Software Foundation, either version 3
|
max@0
|
10 // of the License or (at your option) any later version.
|
max@0
|
11 // (see http://www.opensource.org/licenses for more info)
|
max@0
|
12
|
max@0
|
13
|
max@0
|
14 //! \addtogroup fn_norm
|
max@0
|
15 //! @{
|
max@0
|
16
|
max@0
|
17
|
max@0
|
18
|
max@0
|
19 template<typename T1>
|
max@0
|
20 arma_hot
|
max@0
|
21 inline
|
max@0
|
22 typename T1::pod_type
|
max@0
|
23 arma_vec_norm_1(const Proxy<T1>& A)
|
max@0
|
24 {
|
max@0
|
25 arma_extra_debug_sigprint();
|
max@0
|
26
|
max@0
|
27 typedef typename T1::pod_type T;
|
max@0
|
28
|
max@0
|
29 T acc = T(0);
|
max@0
|
30
|
max@0
|
31 if(Proxy<T1>::prefer_at_accessor == false)
|
max@0
|
32 {
|
max@0
|
33 typename Proxy<T1>::ea_type P = A.get_ea();
|
max@0
|
34
|
max@0
|
35 const uword N = A.get_n_elem();
|
max@0
|
36
|
max@0
|
37 uword i,j;
|
max@0
|
38
|
max@0
|
39 for(i=0, j=1; j<N; i+=2, j+=2)
|
max@0
|
40 {
|
max@0
|
41 acc += std::abs(P[i]);
|
max@0
|
42 acc += std::abs(P[j]);
|
max@0
|
43 }
|
max@0
|
44
|
max@0
|
45 if(i < N)
|
max@0
|
46 {
|
max@0
|
47 acc += std::abs(P[i]);
|
max@0
|
48 }
|
max@0
|
49 }
|
max@0
|
50 else
|
max@0
|
51 {
|
max@0
|
52 const uword n_rows = A.get_n_rows();
|
max@0
|
53 const uword n_cols = A.get_n_cols();
|
max@0
|
54
|
max@0
|
55 for(uword col=0; col<n_cols; ++col)
|
max@0
|
56 {
|
max@0
|
57 uword i,j;
|
max@0
|
58
|
max@0
|
59 for(i=0, j=1; j<n_rows; i+=2, j+=2)
|
max@0
|
60 {
|
max@0
|
61 acc += std::abs(A.at(i,col));
|
max@0
|
62 acc += std::abs(A.at(j,col));
|
max@0
|
63 }
|
max@0
|
64
|
max@0
|
65 if(i < n_rows)
|
max@0
|
66 {
|
max@0
|
67 acc += std::abs(A.at(i,col));
|
max@0
|
68 }
|
max@0
|
69 }
|
max@0
|
70 }
|
max@0
|
71
|
max@0
|
72 return acc;
|
max@0
|
73 }
|
max@0
|
74
|
max@0
|
75
|
max@0
|
76
|
max@0
|
77 template<typename T1>
|
max@0
|
78 arma_hot
|
max@0
|
79 inline
|
max@0
|
80 typename T1::pod_type
|
max@0
|
81 arma_vec_norm_2(const Proxy<T1>& A, const typename arma_not_cx<typename T1::elem_type>::result* junk = 0)
|
max@0
|
82 {
|
max@0
|
83 arma_extra_debug_sigprint();
|
max@0
|
84 arma_ignore(junk);
|
max@0
|
85
|
max@0
|
86 typedef typename T1::pod_type T;
|
max@0
|
87
|
max@0
|
88 T acc = T(0);
|
max@0
|
89
|
max@0
|
90 if(Proxy<T1>::prefer_at_accessor == false)
|
max@0
|
91 {
|
max@0
|
92 typename Proxy<T1>::ea_type P = A.get_ea();
|
max@0
|
93
|
max@0
|
94 const uword N = A.get_n_elem();
|
max@0
|
95
|
max@0
|
96 uword i,j;
|
max@0
|
97
|
max@0
|
98 for(i=0, j=1; j<N; i+=2, j+=2)
|
max@0
|
99 {
|
max@0
|
100 const T tmp_i = P[i];
|
max@0
|
101 const T tmp_j = P[j];
|
max@0
|
102
|
max@0
|
103 acc += tmp_i * tmp_i;
|
max@0
|
104 acc += tmp_j * tmp_j;
|
max@0
|
105 }
|
max@0
|
106
|
max@0
|
107 if(i < N)
|
max@0
|
108 {
|
max@0
|
109 const T tmp_i = P[i];
|
max@0
|
110
|
max@0
|
111 acc += tmp_i * tmp_i;
|
max@0
|
112 }
|
max@0
|
113 }
|
max@0
|
114 else
|
max@0
|
115 {
|
max@0
|
116 const uword n_rows = A.get_n_rows();
|
max@0
|
117 const uword n_cols = A.get_n_cols();
|
max@0
|
118
|
max@0
|
119 for(uword col=0; col<n_cols; ++col)
|
max@0
|
120 {
|
max@0
|
121 uword i,j;
|
max@0
|
122
|
max@0
|
123 for(i=0, j=1; j<n_rows; i+=2, j+=2)
|
max@0
|
124 {
|
max@0
|
125 const T tmp_i = A.at(i,col);
|
max@0
|
126 const T tmp_j = A.at(j,col);
|
max@0
|
127
|
max@0
|
128 acc += tmp_i * tmp_i;
|
max@0
|
129 acc += tmp_j * tmp_j;
|
max@0
|
130 }
|
max@0
|
131
|
max@0
|
132 if(i < n_rows)
|
max@0
|
133 {
|
max@0
|
134 const T tmp_i = A.at(i,col);
|
max@0
|
135
|
max@0
|
136 acc += tmp_i * tmp_i;
|
max@0
|
137 }
|
max@0
|
138 }
|
max@0
|
139 }
|
max@0
|
140
|
max@0
|
141 return std::sqrt(acc);
|
max@0
|
142 }
|
max@0
|
143
|
max@0
|
144
|
max@0
|
145
|
max@0
|
146 template<typename T1>
|
max@0
|
147 arma_hot
|
max@0
|
148 inline
|
max@0
|
149 typename T1::pod_type
|
max@0
|
150 arma_vec_norm_2(const Proxy<T1>& A, const typename arma_cx_only<typename T1::elem_type>::result* junk = 0)
|
max@0
|
151 {
|
max@0
|
152 arma_extra_debug_sigprint();
|
max@0
|
153 arma_ignore(junk);
|
max@0
|
154
|
max@0
|
155 typedef typename T1::pod_type T;
|
max@0
|
156
|
max@0
|
157 T acc = T(0);
|
max@0
|
158
|
max@0
|
159 if(Proxy<T1>::prefer_at_accessor == false)
|
max@0
|
160 {
|
max@0
|
161 typename Proxy<T1>::ea_type P = A.get_ea();
|
max@0
|
162
|
max@0
|
163 const uword N = A.get_n_elem();
|
max@0
|
164
|
max@0
|
165 for(uword i=0; i<N; ++i)
|
max@0
|
166 {
|
max@0
|
167 const T tmp = std::abs(P[i]);
|
max@0
|
168 acc += tmp*tmp;
|
max@0
|
169 }
|
max@0
|
170 }
|
max@0
|
171 else
|
max@0
|
172 {
|
max@0
|
173 const uword n_rows = A.get_n_rows();
|
max@0
|
174 const uword n_cols = A.get_n_cols();
|
max@0
|
175
|
max@0
|
176 for(uword col=0; col<n_cols; ++col)
|
max@0
|
177 for(uword row=0; row<n_rows; ++row)
|
max@0
|
178 {
|
max@0
|
179 const T tmp = std::abs(A.at(row,col));
|
max@0
|
180 acc += tmp*tmp;
|
max@0
|
181 }
|
max@0
|
182 }
|
max@0
|
183
|
max@0
|
184 return std::sqrt(acc);
|
max@0
|
185 }
|
max@0
|
186
|
max@0
|
187
|
max@0
|
188
|
max@0
|
189 template<typename T1>
|
max@0
|
190 arma_hot
|
max@0
|
191 inline
|
max@0
|
192 typename T1::pod_type
|
max@0
|
193 arma_vec_norm_k(const Proxy<T1>& A, const int k)
|
max@0
|
194 {
|
max@0
|
195 arma_extra_debug_sigprint();
|
max@0
|
196
|
max@0
|
197 typedef typename T1::pod_type T;
|
max@0
|
198
|
max@0
|
199 T acc = T(0);
|
max@0
|
200
|
max@0
|
201 if(Proxy<T1>::prefer_at_accessor == false)
|
max@0
|
202 {
|
max@0
|
203 typename Proxy<T1>::ea_type P = A.get_ea();
|
max@0
|
204
|
max@0
|
205 const uword N = A.get_n_elem();
|
max@0
|
206
|
max@0
|
207 uword i,j;
|
max@0
|
208
|
max@0
|
209 for(i=0, j=1; j<N; i+=2, j+=2)
|
max@0
|
210 {
|
max@0
|
211 acc += std::pow(std::abs(P[i]), k);
|
max@0
|
212 acc += std::pow(std::abs(P[j]), k);
|
max@0
|
213 }
|
max@0
|
214
|
max@0
|
215 if(i < N)
|
max@0
|
216 {
|
max@0
|
217 acc += std::pow(std::abs(P[i]), k);
|
max@0
|
218 }
|
max@0
|
219 }
|
max@0
|
220 else
|
max@0
|
221 {
|
max@0
|
222 const uword n_rows = A.get_n_rows();
|
max@0
|
223 const uword n_cols = A.get_n_cols();
|
max@0
|
224
|
max@0
|
225 for(uword col=0; col<n_cols; ++col)
|
max@0
|
226 for(uword row=0; row<n_rows; ++row)
|
max@0
|
227 {
|
max@0
|
228 acc += std::pow(std::abs(A.at(row,col)), k);
|
max@0
|
229 }
|
max@0
|
230 }
|
max@0
|
231
|
max@0
|
232 return std::pow(acc, T(1)/T(k));
|
max@0
|
233 }
|
max@0
|
234
|
max@0
|
235
|
max@0
|
236
|
max@0
|
237 template<typename T1>
|
max@0
|
238 arma_hot
|
max@0
|
239 inline
|
max@0
|
240 typename T1::pod_type
|
max@0
|
241 arma_vec_norm_max(const Proxy<T1>& A)
|
max@0
|
242 {
|
max@0
|
243 arma_extra_debug_sigprint();
|
max@0
|
244
|
max@0
|
245 typedef typename T1::pod_type T;
|
max@0
|
246 typedef typename Proxy<T1>::ea_type ea_type;
|
max@0
|
247
|
max@0
|
248 ea_type P = A.get_ea();
|
max@0
|
249 const uword N = A.get_n_elem();
|
max@0
|
250
|
max@0
|
251 T max_val = (N != 1) ? priv::most_neg<T>() : std::abs(P[0]);
|
max@0
|
252
|
max@0
|
253 uword i,j;
|
max@0
|
254
|
max@0
|
255 for(i=0, j=1; j<N; i+=2, j+=2)
|
max@0
|
256 {
|
max@0
|
257 const T tmp_i = std::abs(P[i]);
|
max@0
|
258 const T tmp_j = std::abs(P[j]);
|
max@0
|
259
|
max@0
|
260 if(max_val < tmp_i) { max_val = tmp_i; }
|
max@0
|
261 if(max_val < tmp_j) { max_val = tmp_j; }
|
max@0
|
262 }
|
max@0
|
263
|
max@0
|
264 if(i < N)
|
max@0
|
265 {
|
max@0
|
266 const T tmp_i = std::abs(P[i]);
|
max@0
|
267
|
max@0
|
268 if(max_val < tmp_i) { max_val = tmp_i; }
|
max@0
|
269 }
|
max@0
|
270
|
max@0
|
271 return max_val;
|
max@0
|
272 }
|
max@0
|
273
|
max@0
|
274
|
max@0
|
275
|
max@0
|
276 template<typename T1>
|
max@0
|
277 arma_hot
|
max@0
|
278 inline
|
max@0
|
279 typename T1::pod_type
|
max@0
|
280 arma_vec_norm_min(const Proxy<T1>& A)
|
max@0
|
281 {
|
max@0
|
282 arma_extra_debug_sigprint();
|
max@0
|
283
|
max@0
|
284 typedef typename T1::pod_type T;
|
max@0
|
285 typedef typename Proxy<T1>::ea_type ea_type;
|
max@0
|
286
|
max@0
|
287 ea_type P = A.get_ea();
|
max@0
|
288 const uword N = A.get_n_elem();
|
max@0
|
289
|
max@0
|
290 T min_val = (N != 1) ? priv::most_pos<T>() : std::abs(P[0]);
|
max@0
|
291
|
max@0
|
292 uword i,j;
|
max@0
|
293
|
max@0
|
294 for(i=0, j=1; j<N; i+=2, j+=2)
|
max@0
|
295 {
|
max@0
|
296 const T tmp_i = std::abs(P[i]);
|
max@0
|
297 const T tmp_j = std::abs(P[j]);
|
max@0
|
298
|
max@0
|
299 if(min_val > tmp_i) { min_val = tmp_i; }
|
max@0
|
300 if(min_val > tmp_j) { min_val = tmp_j; }
|
max@0
|
301 }
|
max@0
|
302
|
max@0
|
303 if(i < N)
|
max@0
|
304 {
|
max@0
|
305 const T tmp_i = std::abs(P[i]);
|
max@0
|
306
|
max@0
|
307 if(min_val > tmp_i) { min_val = tmp_i; }
|
max@0
|
308 }
|
max@0
|
309
|
max@0
|
310 return min_val;
|
max@0
|
311 }
|
max@0
|
312
|
max@0
|
313
|
max@0
|
314
|
max@0
|
315 template<typename T1>
|
max@0
|
316 inline
|
max@0
|
317 typename T1::pod_type
|
max@0
|
318 arma_mat_norm_1(const Proxy<T1>& A)
|
max@0
|
319 {
|
max@0
|
320 arma_extra_debug_sigprint();
|
max@0
|
321
|
max@0
|
322 typedef typename T1::elem_type eT;
|
max@0
|
323 typedef typename T1::pod_type T;
|
max@0
|
324
|
max@0
|
325 const unwrap<typename Proxy<T1>::stored_type> tmp(A.Q);
|
max@0
|
326 const Mat<eT>& X = tmp.M;
|
max@0
|
327
|
max@0
|
328 // TODO: this can be sped up with a dedicated implementation
|
max@0
|
329 return as_scalar( max( sum(abs(X)), 1) );
|
max@0
|
330 }
|
max@0
|
331
|
max@0
|
332
|
max@0
|
333
|
max@0
|
334 template<typename T1>
|
max@0
|
335 inline
|
max@0
|
336 typename T1::pod_type
|
max@0
|
337 arma_mat_norm_2(const Proxy<T1>& A)
|
max@0
|
338 {
|
max@0
|
339 arma_extra_debug_sigprint();
|
max@0
|
340
|
max@0
|
341 typedef typename T1::elem_type eT;
|
max@0
|
342 typedef typename T1::pod_type T;
|
max@0
|
343
|
max@0
|
344 const unwrap<typename Proxy<T1>::stored_type> tmp(A.Q);
|
max@0
|
345 const Mat<eT>& X = tmp.M;
|
max@0
|
346
|
max@0
|
347 Col<T> S;
|
max@0
|
348 svd(S, X);
|
max@0
|
349
|
max@0
|
350 return (S.n_elem > 0) ? max(S) : T(0);
|
max@0
|
351 }
|
max@0
|
352
|
max@0
|
353
|
max@0
|
354
|
max@0
|
355 template<typename T1>
|
max@0
|
356 inline
|
max@0
|
357 typename T1::pod_type
|
max@0
|
358 arma_mat_norm_inf(const Proxy<T1>& A)
|
max@0
|
359 {
|
max@0
|
360 arma_extra_debug_sigprint();
|
max@0
|
361
|
max@0
|
362 typedef typename T1::elem_type eT;
|
max@0
|
363 typedef typename T1::pod_type T;
|
max@0
|
364
|
max@0
|
365 const unwrap<typename Proxy<T1>::stored_type> tmp(A.Q);
|
max@0
|
366 const Mat<eT>& X = tmp.M;
|
max@0
|
367
|
max@0
|
368 // TODO: this can be sped up with a dedicated implementation
|
max@0
|
369 return as_scalar( max( sum(abs(X),1) ) );
|
max@0
|
370 }
|
max@0
|
371
|
max@0
|
372
|
max@0
|
373
|
max@0
|
374 template<typename T1>
|
max@0
|
375 inline
|
max@0
|
376 arma_warn_unused
|
max@0
|
377 typename T1::pod_type
|
max@0
|
378 norm
|
max@0
|
379 (
|
max@0
|
380 const Base<typename T1::elem_type,T1>& X,
|
max@0
|
381 const uword k,
|
max@0
|
382 const typename arma_float_or_cx_only<typename T1::elem_type>::result* junk = 0
|
max@0
|
383 )
|
max@0
|
384 {
|
max@0
|
385 arma_extra_debug_sigprint();
|
max@0
|
386 arma_ignore(junk);
|
max@0
|
387
|
max@0
|
388 typedef typename T1::elem_type eT;
|
max@0
|
389 typedef typename T1::pod_type T;
|
max@0
|
390
|
max@0
|
391 const Proxy<T1> A(X.get_ref());
|
max@0
|
392
|
max@0
|
393 if(A.get_n_elem() == 0)
|
max@0
|
394 {
|
max@0
|
395 return T(0);
|
max@0
|
396 }
|
max@0
|
397
|
max@0
|
398 const bool is_vec = (A.get_n_rows() == 1) || (A.get_n_cols() == 1);
|
max@0
|
399
|
max@0
|
400 if(is_vec == true)
|
max@0
|
401 {
|
max@0
|
402 switch(k)
|
max@0
|
403 {
|
max@0
|
404 case 1:
|
max@0
|
405 return arma_vec_norm_1(A);
|
max@0
|
406 break;
|
max@0
|
407
|
max@0
|
408 case 2:
|
max@0
|
409 return arma_vec_norm_2(A);
|
max@0
|
410 break;
|
max@0
|
411
|
max@0
|
412 default:
|
max@0
|
413 {
|
max@0
|
414 arma_debug_check( (k == 0), "norm(): k must be greater than zero" );
|
max@0
|
415 return arma_vec_norm_k(A, int(k));
|
max@0
|
416 }
|
max@0
|
417 }
|
max@0
|
418 }
|
max@0
|
419 else
|
max@0
|
420 {
|
max@0
|
421 switch(k)
|
max@0
|
422 {
|
max@0
|
423 case 1:
|
max@0
|
424 return arma_mat_norm_1(A);
|
max@0
|
425 break;
|
max@0
|
426
|
max@0
|
427 case 2:
|
max@0
|
428 return arma_mat_norm_2(A);
|
max@0
|
429 break;
|
max@0
|
430
|
max@0
|
431 default:
|
max@0
|
432 arma_stop("norm(): unsupported matrix norm type");
|
max@0
|
433 return T(0);
|
max@0
|
434 }
|
max@0
|
435 }
|
max@0
|
436 }
|
max@0
|
437
|
max@0
|
438
|
max@0
|
439
|
max@0
|
440 template<typename T1>
|
max@0
|
441 inline
|
max@0
|
442 arma_warn_unused
|
max@0
|
443 typename T1::pod_type
|
max@0
|
444 norm
|
max@0
|
445 (
|
max@0
|
446 const Base<typename T1::elem_type,T1>& X,
|
max@0
|
447 const char* method,
|
max@0
|
448 const typename arma_float_or_cx_only<typename T1::elem_type>::result* junk = 0
|
max@0
|
449 )
|
max@0
|
450 {
|
max@0
|
451 arma_extra_debug_sigprint();
|
max@0
|
452 arma_ignore(junk);
|
max@0
|
453
|
max@0
|
454 typedef typename T1::elem_type eT;
|
max@0
|
455 typedef typename T1::pod_type T;
|
max@0
|
456
|
max@0
|
457 const Proxy<T1> A(X.get_ref());
|
max@0
|
458
|
max@0
|
459 if(A.get_n_elem() == 0)
|
max@0
|
460 {
|
max@0
|
461 return T(0);
|
max@0
|
462 }
|
max@0
|
463
|
max@0
|
464 const char sig = method[0];
|
max@0
|
465 const bool is_vec = (A.get_n_rows() == 1) || (A.get_n_cols() == 1);
|
max@0
|
466
|
max@0
|
467 if(is_vec == true)
|
max@0
|
468 {
|
max@0
|
469 if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // max norm
|
max@0
|
470 {
|
max@0
|
471 return arma_vec_norm_max(A);
|
max@0
|
472 }
|
max@0
|
473 else
|
max@0
|
474 if(sig == '-') // min norm
|
max@0
|
475 {
|
max@0
|
476 return arma_vec_norm_min(A);
|
max@0
|
477 }
|
max@0
|
478 else
|
max@0
|
479 if( (sig == 'f') || (sig == 'F') )
|
max@0
|
480 {
|
max@0
|
481 return arma_vec_norm_2(A);
|
max@0
|
482 }
|
max@0
|
483 else
|
max@0
|
484 {
|
max@0
|
485 arma_stop("norm(): unsupported vector norm type");
|
max@0
|
486 return T(0);
|
max@0
|
487 }
|
max@0
|
488 }
|
max@0
|
489 else
|
max@0
|
490 {
|
max@0
|
491 if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // inf norm
|
max@0
|
492 {
|
max@0
|
493 return arma_mat_norm_inf(A);
|
max@0
|
494 }
|
max@0
|
495 else
|
max@0
|
496 if( (sig == 'f') || (sig == 'F') )
|
max@0
|
497 {
|
max@0
|
498 return arma_vec_norm_2(A);
|
max@0
|
499 }
|
max@0
|
500 else
|
max@0
|
501 {
|
max@0
|
502 arma_stop("norm(): unsupported matrix norm type");
|
max@0
|
503 return T(0);
|
max@0
|
504 }
|
max@0
|
505 }
|
max@0
|
506 }
|
max@0
|
507
|
max@0
|
508
|
max@0
|
509
|
max@0
|
510 //! @}
|