fn_norm.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2009 NICTA
00002 // 
00003 // Authors:
00004 // - Conrad Sanderson (conradsand at ieee dot org)
00005 // 
00006 // This file is part of the Armadillo C++ library.
00007 // It is provided without any warranty of fitness
00008 // for any purpose. You can redistribute this file
00009 // and/or modify it under the terms of the GNU
00010 // Lesser General Public License (LGPL) as published
00011 // by the Free Software Foundation, either version 3
00012 // of the License or (at your option) any later version.
00013 // (see http://www.opensource.org/licenses for more info)
00014 
00015 
00016 //! \addtogroup fn_norm
00017 //! @{
00018 
00019 template<typename T1>
00020 inline
00021 typename T1::elem_type
00022 norm(const Base<typename T1::elem_type,T1>& X, const u32 k)
00023   {
00024   arma_extra_debug_sigprint();
00025   
00026   typedef typename T1::elem_type eT;
00027   
00028   const unwrap<T1> A_tmp(X.get_ref());
00029   const Mat<eT>& A = A_tmp.M;
00030 
00031   arma_debug_check(    (A.n_elem == 0),                      "norm(): given object has no elements" );
00032   arma_debug_check( !( (A.n_rows == 1) || (A.n_cols == 1) ), "norm(): first argument must be a vector" );
00033   arma_debug_check(    (k == 0),                             "norm(): second argument must be greater than zero" );
00034 
00035 
00036   if(k==1)
00037     {
00038     eT acc = eT(0);
00039     
00040     for(u32 i=0; i<A.n_elem; ++i)
00041       {
00042       acc += std::abs(A.mem[i]);
00043       }
00044     
00045     return acc;
00046     }
00047   else
00048   if(k==2)
00049     {
00050     if(is_complex<eT>::value == false)
00051       {
00052       eT acc = eT(0);
00053       
00054       for(u32 i=0; i<A.n_elem; ++i)
00055         {
00056         const eT tmp = A.mem[i];
00057         acc += tmp*tmp;
00058         }
00059       
00060       return std::sqrt(acc);
00061       }
00062     else
00063       {
00064       eT acc = eT(0);
00065       
00066       for(u32 i=0; i<A.n_elem; ++i)
00067         {
00068         acc += std::abs(A.mem[i]);
00069         }
00070       
00071       return std::sqrt(acc);
00072       
00073       }
00074     }
00075   else
00076     {
00077     eT acc = eT(0);
00078     
00079     for(u32 i=0; i<A.n_elem; ++i)
00080       {
00081       acc += std::pow(std::abs(A.mem[i]), int(k));
00082       }
00083     
00084     return std::pow(acc, eT(1)/eT(k));
00085     }
00086   
00087   }
00088 
00089 
00090 
00091 //
00092 // giving vector arguments works, as operator-() takes two mat arguments.
00093 // i.e. it has no specific form for dealing with colvec and rowvec,
00094 // and colvec and rowvec are derived from mat (hence they are a type of mat)
00095 
00096 template<typename T1, typename T2>
00097 inline
00098 typename T1::elem_type
00099 norm(const Glue<T1,T2,glue_minus>& X, const u32 k)
00100   {
00101   arma_extra_debug_sigprint();
00102   
00103   isnt_same_type<typename T1::elem_type,typename T2::elem_type>::check();
00104   
00105   const unwrap<T1> tmp1(X.A);
00106   const unwrap<T2> tmp2(X.B);
00107   
00108   typedef typename T1::elem_type eT;
00109   
00110   const Mat<eT>& A = tmp1.M;
00111   const Mat<eT>& B = tmp2.M;
00112   
00113   arma_debug_check(  ( (A.n_elem == 0) || (B.n_elem == 0) ), "norm(): one or more of given objects has no elements" );
00114   arma_debug_check( !( (A.n_rows == 1) || (A.n_cols == 1) ), "norm(): non-vector argument detected" );
00115   arma_debug_check( !( (B.n_rows == 1) || (B.n_cols == 1) ), "norm(): non-vector argument detected" );
00116   arma_debug_check(    (A.n_elem != B.n_elem),               "norm(): vectors have different lengths" );
00117   arma_debug_check(    (k == 0),                             "norm(): second argument must be greater than zero" );
00118   
00119   if(k==1)
00120     {
00121     eT acc = eT(0);
00122     
00123     for(u32 i=0; i<A.n_elem; ++i)
00124       {
00125       acc += std::abs(A.mem[i] - B.mem[i]);
00126       }
00127     
00128     return acc;
00129     }
00130   else
00131   if(k==2)
00132     {
00133     eT acc = eT(0);
00134     
00135     for(u32 i=0; i<A.n_elem; ++i)
00136       {
00137       const eT tmp = A.mem[i] - B.mem[i];
00138       
00139       acc += tmp*tmp;
00140       }
00141     
00142     return std::sqrt(acc);
00143     }
00144   else
00145     {
00146     eT acc = eT(0);
00147     
00148     for(u32 i=0; i<A.n_elem; ++i)
00149       {
00150       acc += std::pow( std::abs(A.mem[i] - B.mem[i]), int(k) );
00151       }
00152     
00153     return std::pow(acc, eT(1)/eT(k));
00154     }
00155   
00156   }
00157 
00158 
00159 
00160 template<typename T1, typename T2>
00161 inline
00162 typename T1::elem_type
00163 norm(const Glue<T1,T2,glue_plus>& X, const u32 k)
00164   {
00165   arma_extra_debug_sigprint();
00166   
00167   isnt_same_type<typename T1::elem_type,typename T2::elem_type>::check();
00168   
00169   const unwrap<T1> tmp1(X.A);
00170   const unwrap<T2> tmp2(X.B);
00171   
00172   typedef typename T1::elem_type eT;
00173   
00174   const Mat<eT>& A = tmp1.M;
00175   const Mat<eT>& B = tmp2.M;
00176   
00177   arma_debug_check(  ( (A.n_elem == 0) || (B.n_elem == 0) ), "norm(): one or more of given objects has no elements" );
00178   arma_debug_check( !( (A.n_rows == 1) || (A.n_cols == 1) ), "norm(): non-vector argument detected" );
00179   arma_debug_check( !( (B.n_rows == 1) || (B.n_cols == 1) ), "norm(): non-vector argument detected" );
00180   arma_debug_check(    (A.n_elem != B.n_elem),               "norm(): vectors have different lengths" );
00181   arma_debug_check(    (k == 0),                             "norm(): second argument must be greater than zero" );
00182   
00183   if(k==1)
00184     {
00185     eT acc = eT(0);
00186     
00187     for(u32 i=0; i<A.n_elem; ++i)
00188       {
00189       acc += std::abs(A.mem[i] + B.mem[i]);
00190       }
00191     
00192     return acc;
00193     }
00194   else
00195   if(k==2)
00196     {
00197     eT acc = eT(0);
00198     
00199     for(u32 i=0; i<A.n_elem; ++i)
00200       {
00201       const eT tmp = A.mem[i] + B.mem[i];
00202       
00203       acc += tmp*tmp;
00204       }
00205     
00206     return std::sqrt(acc);
00207     }
00208   else
00209     {
00210     eT acc = eT(0);
00211     
00212     for(u32 i=0; i<A.n_elem; ++i)
00213       {
00214       acc += std::pow( std::abs(A.mem[i] + B.mem[i]), int(k) );
00215       }
00216     
00217     return std::pow(acc, eT(1)/eT(k));
00218     }
00219   
00220   }
00221 
00222 
00223 //! @}