$search
00001 // Copyright (C) 2008-2011 NICTA (www.nicta.com.au) 00002 // Copyright (C) 2008-2011 Conrad Sanderson 00003 // 00004 // This file is part of the Armadillo C++ library. 00005 // It is provided without any warranty of fitness 00006 // for any purpose. You can redistribute this file 00007 // and/or modify it under the terms of the GNU 00008 // Lesser General Public License (LGPL) as published 00009 // by the Free Software Foundation, either version 3 00010 // of the License or (at your option) any later version. 00011 // (see http://www.opensource.org/licenses for more info) 00012 00013 00016 00017 00018 00019 template<typename T1> 00020 arma_hot 00021 inline 00022 typename T1::pod_type 00023 arma_vec_norm_1(const Proxy<T1>& A) 00024 { 00025 arma_extra_debug_sigprint(); 00026 00027 typedef typename T1::pod_type T; 00028 00029 T acc = T(0); 00030 00031 if(Proxy<T1>::prefer_at_accessor == false) 00032 { 00033 typename Proxy<T1>::ea_type P = A.get_ea(); 00034 00035 const uword N = A.get_n_elem(); 00036 00037 uword i,j; 00038 00039 for(i=0, j=1; j<N; i+=2, j+=2) 00040 { 00041 acc += std::abs(P[i]); 00042 acc += std::abs(P[j]); 00043 } 00044 00045 if(i < N) 00046 { 00047 acc += std::abs(P[i]); 00048 } 00049 } 00050 else 00051 { 00052 const uword n_rows = A.get_n_rows(); 00053 const uword n_cols = A.get_n_cols(); 00054 00055 for(uword col=0; col<n_cols; ++col) 00056 { 00057 uword i,j; 00058 00059 for(i=0, j=1; j<n_rows; i+=2, j+=2) 00060 { 00061 acc += std::abs(A.at(i,col)); 00062 acc += std::abs(A.at(j,col)); 00063 } 00064 00065 if(i < n_rows) 00066 { 00067 acc += std::abs(A.at(i,col)); 00068 } 00069 } 00070 } 00071 00072 return acc; 00073 } 00074 00075 00076 00077 template<typename T1> 00078 arma_hot 00079 inline 00080 typename T1::pod_type 00081 arma_vec_norm_2(const Proxy<T1>& A, const typename arma_not_cx<typename T1::elem_type>::result* junk = 0) 00082 { 00083 arma_extra_debug_sigprint(); 00084 arma_ignore(junk); 00085 00086 typedef typename T1::pod_type T; 00087 00088 T acc = T(0); 00089 00090 if(Proxy<T1>::prefer_at_accessor == false) 00091 { 00092 typename Proxy<T1>::ea_type P = A.get_ea(); 00093 00094 const uword N = A.get_n_elem(); 00095 00096 uword i,j; 00097 00098 for(i=0, j=1; j<N; i+=2, j+=2) 00099 { 00100 const T tmp_i = P[i]; 00101 const T tmp_j = P[j]; 00102 00103 acc += tmp_i * tmp_i; 00104 acc += tmp_j * tmp_j; 00105 } 00106 00107 if(i < N) 00108 { 00109 const T tmp_i = P[i]; 00110 00111 acc += tmp_i * tmp_i; 00112 } 00113 } 00114 else 00115 { 00116 const uword n_rows = A.get_n_rows(); 00117 const uword n_cols = A.get_n_cols(); 00118 00119 for(uword col=0; col<n_cols; ++col) 00120 { 00121 uword i,j; 00122 00123 for(i=0, j=1; j<n_rows; i+=2, j+=2) 00124 { 00125 const T tmp_i = A.at(i,col); 00126 const T tmp_j = A.at(j,col); 00127 00128 acc += tmp_i * tmp_i; 00129 acc += tmp_j * tmp_j; 00130 } 00131 00132 if(i < n_rows) 00133 { 00134 const T tmp_i = A.at(i,col); 00135 00136 acc += tmp_i * tmp_i; 00137 } 00138 } 00139 } 00140 00141 return std::sqrt(acc); 00142 } 00143 00144 00145 00146 template<typename T1> 00147 arma_hot 00148 inline 00149 typename T1::pod_type 00150 arma_vec_norm_2(const Proxy<T1>& A, const typename arma_cx_only<typename T1::elem_type>::result* junk = 0) 00151 { 00152 arma_extra_debug_sigprint(); 00153 arma_ignore(junk); 00154 00155 typedef typename T1::pod_type T; 00156 00157 T acc = T(0); 00158 00159 if(Proxy<T1>::prefer_at_accessor == false) 00160 { 00161 typename Proxy<T1>::ea_type P = A.get_ea(); 00162 00163 const uword N = A.get_n_elem(); 00164 00165 for(uword i=0; i<N; ++i) 00166 { 00167 const T tmp = std::abs(P[i]); 00168 acc += tmp*tmp; 00169 } 00170 } 00171 else 00172 { 00173 const uword n_rows = A.get_n_rows(); 00174 const uword n_cols = A.get_n_cols(); 00175 00176 for(uword col=0; col<n_cols; ++col) 00177 for(uword row=0; row<n_rows; ++row) 00178 { 00179 const T tmp = std::abs(A.at(row,col)); 00180 acc += tmp*tmp; 00181 } 00182 } 00183 00184 return std::sqrt(acc); 00185 } 00186 00187 00188 00189 template<typename T1> 00190 arma_hot 00191 inline 00192 typename T1::pod_type 00193 arma_vec_norm_k(const Proxy<T1>& A, const int k) 00194 { 00195 arma_extra_debug_sigprint(); 00196 00197 typedef typename T1::pod_type T; 00198 00199 T acc = T(0); 00200 00201 if(Proxy<T1>::prefer_at_accessor == false) 00202 { 00203 typename Proxy<T1>::ea_type P = A.get_ea(); 00204 00205 const uword N = A.get_n_elem(); 00206 00207 uword i,j; 00208 00209 for(i=0, j=1; j<N; i+=2, j+=2) 00210 { 00211 acc += std::pow(std::abs(P[i]), k); 00212 acc += std::pow(std::abs(P[j]), k); 00213 } 00214 00215 if(i < N) 00216 { 00217 acc += std::pow(std::abs(P[i]), k); 00218 } 00219 } 00220 else 00221 { 00222 const uword n_rows = A.get_n_rows(); 00223 const uword n_cols = A.get_n_cols(); 00224 00225 for(uword col=0; col<n_cols; ++col) 00226 for(uword row=0; row<n_rows; ++row) 00227 { 00228 acc += std::pow(std::abs(A.at(row,col)), k); 00229 } 00230 } 00231 00232 return std::pow(acc, T(1)/T(k)); 00233 } 00234 00235 00236 00237 template<typename T1> 00238 arma_hot 00239 inline 00240 typename T1::pod_type 00241 arma_vec_norm_max(const Proxy<T1>& A) 00242 { 00243 arma_extra_debug_sigprint(); 00244 00245 typedef typename T1::pod_type T; 00246 typedef typename Proxy<T1>::ea_type ea_type; 00247 00248 ea_type P = A.get_ea(); 00249 const uword N = A.get_n_elem(); 00250 00251 T max_val = (N != 1) ? priv::most_neg<T>() : std::abs(P[0]); 00252 00253 uword i,j; 00254 00255 for(i=0, j=1; j<N; i+=2, j+=2) 00256 { 00257 const T tmp_i = std::abs(P[i]); 00258 const T tmp_j = std::abs(P[j]); 00259 00260 if(max_val < tmp_i) { max_val = tmp_i; } 00261 if(max_val < tmp_j) { max_val = tmp_j; } 00262 } 00263 00264 if(i < N) 00265 { 00266 const T tmp_i = std::abs(P[i]); 00267 00268 if(max_val < tmp_i) { max_val = tmp_i; } 00269 } 00270 00271 return max_val; 00272 } 00273 00274 00275 00276 template<typename T1> 00277 arma_hot 00278 inline 00279 typename T1::pod_type 00280 arma_vec_norm_min(const Proxy<T1>& A) 00281 { 00282 arma_extra_debug_sigprint(); 00283 00284 typedef typename T1::pod_type T; 00285 typedef typename Proxy<T1>::ea_type ea_type; 00286 00287 ea_type P = A.get_ea(); 00288 const uword N = A.get_n_elem(); 00289 00290 T min_val = (N != 1) ? priv::most_pos<T>() : std::abs(P[0]); 00291 00292 uword i,j; 00293 00294 for(i=0, j=1; j<N; i+=2, j+=2) 00295 { 00296 const T tmp_i = std::abs(P[i]); 00297 const T tmp_j = std::abs(P[j]); 00298 00299 if(min_val > tmp_i) { min_val = tmp_i; } 00300 if(min_val > tmp_j) { min_val = tmp_j; } 00301 } 00302 00303 if(i < N) 00304 { 00305 const T tmp_i = std::abs(P[i]); 00306 00307 if(min_val > tmp_i) { min_val = tmp_i; } 00308 } 00309 00310 return min_val; 00311 } 00312 00313 00314 00315 template<typename T1> 00316 inline 00317 typename T1::pod_type 00318 arma_mat_norm_1(const Proxy<T1>& A) 00319 { 00320 arma_extra_debug_sigprint(); 00321 00322 typedef typename T1::elem_type eT; 00323 typedef typename T1::pod_type T; 00324 00325 const unwrap<typename Proxy<T1>::stored_type> tmp(A.Q); 00326 const Mat<eT>& X = tmp.M; 00327 00328 // TODO: this can be sped up with a dedicated implementation 00329 return as_scalar( max( sum(abs(X)), 1) ); 00330 } 00331 00332 00333 00334 template<typename T1> 00335 inline 00336 typename T1::pod_type 00337 arma_mat_norm_2(const Proxy<T1>& A) 00338 { 00339 arma_extra_debug_sigprint(); 00340 00341 typedef typename T1::elem_type eT; 00342 typedef typename T1::pod_type T; 00343 00344 const unwrap<typename Proxy<T1>::stored_type> tmp(A.Q); 00345 const Mat<eT>& X = tmp.M; 00346 00347 Col<T> S; 00348 svd(S, X); 00349 00350 return (S.n_elem > 0) ? max(S) : T(0); 00351 } 00352 00353 00354 00355 template<typename T1> 00356 inline 00357 typename T1::pod_type 00358 arma_mat_norm_inf(const Proxy<T1>& A) 00359 { 00360 arma_extra_debug_sigprint(); 00361 00362 typedef typename T1::elem_type eT; 00363 typedef typename T1::pod_type T; 00364 00365 const unwrap<typename Proxy<T1>::stored_type> tmp(A.Q); 00366 const Mat<eT>& X = tmp.M; 00367 00368 // TODO: this can be sped up with a dedicated implementation 00369 return as_scalar( max( sum(abs(X),1) ) ); 00370 } 00371 00372 00373 00374 template<typename T1> 00375 inline 00376 arma_warn_unused 00377 typename T1::pod_type 00378 norm 00379 ( 00380 const Base<typename T1::elem_type,T1>& X, 00381 const uword k, 00382 const typename arma_float_or_cx_only<typename T1::elem_type>::result* junk = 0 00383 ) 00384 { 00385 arma_extra_debug_sigprint(); 00386 arma_ignore(junk); 00387 00388 typedef typename T1::elem_type eT; 00389 typedef typename T1::pod_type T; 00390 00391 const Proxy<T1> A(X.get_ref()); 00392 00393 if(A.get_n_elem() == 0) 00394 { 00395 return T(0); 00396 } 00397 00398 const bool is_vec = (A.get_n_rows() == 1) || (A.get_n_cols() == 1); 00399 00400 if(is_vec == true) 00401 { 00402 switch(k) 00403 { 00404 case 1: 00405 return arma_vec_norm_1(A); 00406 break; 00407 00408 case 2: 00409 return arma_vec_norm_2(A); 00410 break; 00411 00412 default: 00413 { 00414 arma_debug_check( (k == 0), "norm(): k must be greater than zero" ); 00415 return arma_vec_norm_k(A, int(k)); 00416 } 00417 } 00418 } 00419 else 00420 { 00421 switch(k) 00422 { 00423 case 1: 00424 return arma_mat_norm_1(A); 00425 break; 00426 00427 case 2: 00428 return arma_mat_norm_2(A); 00429 break; 00430 00431 default: 00432 arma_stop("norm(): unsupported matrix norm type"); 00433 return T(0); 00434 } 00435 } 00436 } 00437 00438 00439 00440 template<typename T1> 00441 inline 00442 arma_warn_unused 00443 typename T1::pod_type 00444 norm 00445 ( 00446 const Base<typename T1::elem_type,T1>& X, 00447 const char* method, 00448 const typename arma_float_or_cx_only<typename T1::elem_type>::result* junk = 0 00449 ) 00450 { 00451 arma_extra_debug_sigprint(); 00452 arma_ignore(junk); 00453 00454 typedef typename T1::elem_type eT; 00455 typedef typename T1::pod_type T; 00456 00457 const Proxy<T1> A(X.get_ref()); 00458 00459 if(A.get_n_elem() == 0) 00460 { 00461 return T(0); 00462 } 00463 00464 const char sig = method[0]; 00465 const bool is_vec = (A.get_n_rows() == 1) || (A.get_n_cols() == 1); 00466 00467 if(is_vec == true) 00468 { 00469 if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // max norm 00470 { 00471 return arma_vec_norm_max(A); 00472 } 00473 else 00474 if(sig == '-') // min norm 00475 { 00476 return arma_vec_norm_min(A); 00477 } 00478 else 00479 if( (sig == 'f') || (sig == 'F') ) 00480 { 00481 return arma_vec_norm_2(A); 00482 } 00483 else 00484 { 00485 arma_stop("norm(): unsupported vector norm type"); 00486 return T(0); 00487 } 00488 } 00489 else 00490 { 00491 if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // inf norm 00492 { 00493 return arma_mat_norm_inf(A); 00494 } 00495 else 00496 if( (sig == 'f') || (sig == 'F') ) 00497 { 00498 return arma_vec_norm_2(A); 00499 } 00500 else 00501 { 00502 arma_stop("norm(): unsupported matrix norm type"); 00503 return T(0); 00504 } 00505 } 00506 } 00507 00508 00509