fn_misc.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2010 NICTA and the authors listed below
00002 // http://nicta.com.au
00003 // 
00004 // Authors:
00005 // - Conrad Sanderson (conradsand at ieee dot org)
00006 // 
00007 // This file is part of the Armadillo C++ library.
00008 // It is provided without any warranty of fitness
00009 // for any purpose. You can redistribute this file
00010 // and/or modify it under the terms of the GNU
00011 // Lesser General Public License (LGPL) as published
00012 // by the Free Software Foundation, either version 3
00013 // of the License or (at your option) any later version.
00014 // (see http://www.opensource.org/licenses for more info)
00015 
00016 
00017 //! \addtogroup fn_misc
00018 //! @{
00019 
00020 
00021 
00022 //! \brief
00023 //! Generate a vector with 'num' elements.
00024 //! The values of the elements linearly increase from 'start' upto (and including) 'end'.
00025 
00026 template<typename vec_type>
00027 inline
00028 vec_type
00029 linspace
00030   (
00031   const typename vec_type::pod_type start,
00032   const typename vec_type::pod_type end,
00033   const u32 num
00034   )
00035   {
00036   arma_extra_debug_sigprint();
00037   
00038   arma_type_check< (is_Mat<vec_type>::value == false) >::apply();
00039   
00040   arma_debug_check( (num < 2), "linspace(): num must be >= 2");
00041   
00042   typedef typename vec_type::elem_type eT;
00043   typedef typename vec_type::pod_type   T;
00044   
00045   const u32 n_rows = (is_Row<vec_type>::value == true) ? 1   : num;
00046   const u32 n_cols = (is_Row<vec_type>::value == true) ? num : 1;
00047   
00048   Mat<eT> x(n_rows, n_cols);
00049   eT* x_mem = x.memptr();
00050   
00051   const u32 num_m1 = num - 1;
00052   
00053   if(is_non_integral<T>::value == true)
00054     {
00055     const T delta = (end-start)/T(num_m1);
00056     
00057     for(u32 i=0; i<num_m1; ++i)
00058       {
00059       x_mem[i] = eT(start + i*delta);
00060       }
00061     
00062     x_mem[num_m1] = eT(end);
00063     }
00064   else
00065     {
00066     const double delta = (end >= start) ? double(end-start)/double(num_m1) : -double(start-end)/double(num_m1);
00067     
00068     for(u32 i=0; i<num_m1; ++i)
00069       {
00070       x_mem[i] = eT(double(start) + i*delta);
00071       }
00072     
00073     x_mem[num_m1] = eT(end);
00074     }
00075   
00076   return x;
00077   }
00078 
00079 
00080 
00081 inline
00082 mat
00083 linspace(const double start, const double end, const u32 num)
00084   {
00085   arma_extra_debug_sigprint();
00086   return linspace<mat>(start, end, num);
00087   }
00088 
00089 
00090 
00091 template<typename eT, typename T1>
00092 inline
00093 const mtOp<u32, T1, op_find>
00094 find(const Base<eT,T1>& X, const u32 k = 0, const char* direction = "first")
00095   {
00096   arma_extra_debug_sigprint();
00097   
00098   const char sig = direction[0];
00099   
00100   arma_debug_check( (sig != 'f' && sig != 'F' && sig != 'l' && sig != 'L'), "find(): 3rd input argument must be \"first\" or \"last\"" );
00101   
00102   const u32 type = (sig == 'f' || sig == 'F') ? 0 : 1;
00103   
00104   return mtOp<u32, T1, op_find>(X.get_ref(), k, type);
00105   }
00106 
00107 
00108 
00109 //
00110 // real
00111 
00112 template<typename T1>
00113 arma_inline
00114 const T1&
00115 real(const Base<typename T1::pod_type, T1>& X)
00116   {
00117   arma_extra_debug_sigprint();
00118   
00119   return X.get_ref();
00120   }
00121 
00122 
00123 
00124 template<typename T1>
00125 arma_inline
00126 const T1&
00127 real(const BaseCube<typename T1::pod_type, T1>& X)
00128   {
00129   arma_extra_debug_sigprint();
00130   
00131   return X.get_ref();
00132   }
00133 
00134 
00135 
00136 template<typename T1>
00137 inline
00138 const mtOp<typename T1::pod_type, T1, op_real>
00139 real(const Base<std::complex<typename T1::pod_type>, T1>& X)
00140   {
00141   arma_extra_debug_sigprint();
00142   
00143   return mtOp<typename T1::pod_type, T1, op_real>( X.get_ref() );
00144   }
00145 
00146 
00147 
00148 template<typename T1>
00149 inline
00150 Cube<typename T1::pod_type>
00151 real(const BaseCube<std::complex<typename T1::pod_type>, T1>& X)
00152   {
00153   arma_extra_debug_sigprint();
00154   
00155   typedef typename T1::pod_type T;
00156   
00157   const ProxyCube<T1> A(X.get_ref());
00158   
00159   Cube<T> out(A.n_rows, A.n_cols, A.n_slices);
00160   
00161   T* out_mem = out.memptr();
00162   
00163   for(u32 i=0; i<out.n_elem; ++i)
00164     {
00165     out_mem[i] = std::real(A[i]);
00166     }
00167   
00168   return out;
00169   }
00170 
00171 
00172 
00173 //
00174 // imag
00175 
00176 template<typename T1>
00177 inline
00178 const eOp<Mat<typename T1::pod_type>, eop_zeros>
00179 imag(const Base<typename T1::pod_type,T1>& X)
00180   {
00181   arma_extra_debug_sigprint();
00182   
00183   const Proxy<T1> A(X.get_ref());
00184   
00185   return eOp<Mat<typename T1::pod_type>, eop_zeros>(A.n_rows, A.n_cols);
00186   }
00187 
00188 
00189 
00190 template<typename T1>
00191 inline
00192 const eOpCube<Cube<typename T1::pod_type>, eop_cube_zeros>
00193 imag(const BaseCube<typename T1::pod_type,T1>& X)
00194   {
00195   arma_extra_debug_sigprint();
00196   
00197   const ProxyCube<T1> A(X.get_ref());
00198   
00199   return eOpCube<Cube<typename T1::pod_type>, eop_cube_zeros>(A.n_rows, A.n_cols, A.n_slices);
00200   }
00201 
00202 
00203 
00204 template<typename T1>
00205 inline
00206 const mtOp<typename T1::pod_type, T1, op_imag>
00207 imag(const Base<std::complex<typename T1::pod_type>, T1>& X)
00208   {
00209   arma_extra_debug_sigprint();
00210   
00211   return mtOp<typename T1::pod_type, T1, op_imag>( X.get_ref() );
00212   }
00213 
00214 
00215 
00216 template<typename T1>
00217 inline
00218 Cube<typename T1::pod_type>
00219 imag(const BaseCube<std::complex<typename T1::pod_type>,T1>& X)
00220   {
00221   arma_extra_debug_sigprint();
00222   
00223   typedef typename T1::pod_type T;
00224   
00225   const ProxyCube<T1> A(X.get_ref());
00226   
00227   Cube<T> out(A.n_rows, A.n_cols, A.n_slices);
00228   
00229   T* out_mem = out.memptr();
00230   
00231   for(u32 i=0; i<out.n_elem; ++i)
00232     {
00233     out_mem[i] = std::imag(A[i]);
00234     }
00235   
00236   return out;
00237   }
00238 
00239 
00240 
00241 //
00242 // log_add
00243 
00244 template<typename eT>
00245 inline
00246 typename arma_float_only<eT>::result
00247 log_add(eT log_a, eT log_b)
00248   {
00249   if(log_a < log_b)
00250     {
00251     std::swap(log_a, log_b);
00252     }
00253   
00254   const eT negdelta = log_b - log_a;
00255   
00256   if( (negdelta < Math<eT>::log_min()) || (arma_isfinite(negdelta) == false) )
00257     {
00258     return log_a;
00259     }
00260   else
00261     {
00262     #if defined(ARMA_HAVE_LOG1P)
00263       return (log_a + log1p(std::exp(negdelta)));
00264     #else
00265       return (log_a + std::log(1.0 + std::exp(negdelta)));
00266     #endif
00267     }
00268   }
00269 
00270 
00271 
00272 //
00273 // log
00274 
00275 template<typename T1>
00276 arma_inline
00277 const eOp<T1, eop_log>
00278 log(const Base<typename T1::elem_type,T1>& A)
00279   {
00280   arma_extra_debug_sigprint();
00281   
00282   return eOp<T1, eop_log>(A.get_ref());
00283   }
00284 
00285 
00286 
00287 template<typename T1>
00288 arma_inline
00289 const eOpCube<T1, eop_cube_log>
00290 log(const BaseCube<typename T1::elem_type,T1>& A)
00291   {
00292   arma_extra_debug_sigprint();
00293   
00294   return eOpCube<T1, eop_cube_log>(A.get_ref());
00295   }
00296 
00297 
00298 
00299 //
00300 // log10
00301 
00302 template<typename T1>
00303 arma_inline
00304 const eOp<T1, eop_log10>
00305 log10(const Base<typename T1::elem_type,T1>& A)
00306   {
00307   arma_extra_debug_sigprint();
00308   
00309   return eOp<T1, eop_log10>(A.get_ref());
00310   }
00311 
00312 
00313 
00314 template<typename T1>
00315 arma_inline
00316 const eOpCube<T1, eop_cube_log10>
00317 log10(const BaseCube<typename T1::elem_type,T1>& A)
00318   {
00319   arma_extra_debug_sigprint();
00320   
00321   return eOpCube<T1, eop_cube_log10>(A.get_ref());
00322   }
00323 
00324 
00325 
00326 //
00327 // exp
00328 
00329 template<typename T1>
00330 arma_inline
00331 const eOp<T1, eop_exp>
00332 exp(const Base<typename T1::elem_type,T1>& A)
00333   {
00334   arma_extra_debug_sigprint();
00335   
00336   return eOp<T1, eop_exp>(A.get_ref());
00337   }
00338 
00339 
00340 
00341 template<typename T1>
00342 arma_inline
00343 const eOpCube<T1, eop_cube_exp>
00344 exp(const BaseCube<typename T1::elem_type,T1>& A)
00345   {
00346   arma_extra_debug_sigprint();
00347   
00348   return eOpCube<T1, eop_cube_exp>(A.get_ref());
00349   }
00350 
00351 
00352 
00353 //
00354 // abs
00355 
00356 
00357 template<typename T1>
00358 arma_inline
00359 const eOp<T1, eop_abs>
00360 abs(const Base<typename T1::elem_type,T1>& X)
00361   {
00362   arma_extra_debug_sigprint();
00363   
00364   return eOp<T1, eop_abs>(X.get_ref());
00365   }
00366 
00367 
00368 
00369 template<typename T1>
00370 arma_inline
00371 const eOpCube<T1, eop_cube_abs>
00372 abs(const BaseCube<typename T1::elem_type,T1>& X)
00373   {
00374   arma_extra_debug_sigprint();
00375   
00376   return eOpCube<T1, eop_cube_abs>(X.get_ref());
00377   }
00378 
00379 
00380 
00381 template<typename T1>
00382 inline
00383 const mtOp<typename T1::pod_type, T1, op_abs>
00384 abs(const Base<std::complex<typename T1::pod_type>, T1>& X)
00385   {
00386   arma_extra_debug_sigprint();
00387   
00388   return mtOp<typename T1::pod_type, T1, op_abs>( X.get_ref() );
00389   }
00390 
00391 
00392 
00393 template<typename T1>
00394 inline
00395 Mat<typename T1::pod_type>
00396 abs(const BaseCube< std::complex<typename T1::pod_type>,T1>& X)
00397   {
00398   arma_extra_debug_sigprint();
00399   
00400   const ProxyCube<T1> A(X.get_ref());
00401 
00402   // if T1 is a complex matrix,
00403   // pod_type is the underlying type used by std::complex;
00404   // otherwise pod_type is the same as elem_type
00405   
00406   typedef typename T1::elem_type  in_eT;
00407   typedef typename T1::pod_type  out_eT;
00408 
00409   Cube<out_eT> out(A.n_rows, A.n_cols, A.n_slices);
00410   
00411   out_eT* out_mem = out.memptr();
00412   
00413   for(u32 i=0; i<out.n_elem; ++i)
00414     {
00415     out_mem[i] = std::abs(A[i]);
00416     }
00417   
00418   return out;
00419   }
00420 
00421 
00422 
00423 //
00424 // fabs
00425 
00426 template<typename T1>
00427 arma_inline
00428 const eOp<T1, eop_abs>
00429 fabs(const Base<typename T1::pod_type,T1>& X)
00430   {
00431   arma_extra_debug_sigprint();
00432   
00433   return eOp<T1, eop_abs>(X.get_ref());
00434   }
00435 
00436 
00437 
00438 template<typename T1>
00439 arma_inline
00440 const eOpCube<T1, eop_cube_abs>
00441 fabs(const BaseCube<typename T1::pod_type,T1>& X)
00442   {
00443   arma_extra_debug_sigprint();
00444   
00445   return eOpCube<T1, eop_cube_abs>(X.get_ref());
00446   }
00447 
00448 
00449 
00450 template<typename T1>
00451 inline
00452 const mtOp<typename T1::pod_type, T1, op_abs>
00453 fabs(const Base<std::complex<typename T1::pod_type>, T1>& X)
00454   {
00455   arma_extra_debug_sigprint();
00456   
00457   return mtOp<typename T1::pod_type, T1, op_abs>( X.get_ref() );
00458   }
00459 
00460 
00461 
00462 template<typename T1>
00463 arma_inline
00464 Mat<typename T1::pod_type>
00465 fabs(const BaseCube< std::complex<typename T1::pod_type>,T1>& X)
00466   {
00467   arma_extra_debug_sigprint();
00468   
00469   return abs(X);
00470   }
00471 
00472 
00473 
00474 //
00475 // square
00476 
00477 template<typename T1>
00478 arma_inline
00479 const eOp<T1, eop_square>
00480 square(const Base<typename T1::elem_type,T1>& A)
00481   {
00482   arma_extra_debug_sigprint();
00483   
00484   return eOp<T1, eop_square>(A.get_ref());
00485   }
00486 
00487 
00488 
00489 template<typename T1>
00490 arma_inline
00491 const eOpCube<T1, eop_cube_square>
00492 square(const BaseCube<typename T1::elem_type,T1>& A)
00493   {
00494   arma_extra_debug_sigprint();
00495   
00496   return eOpCube<T1, eop_cube_square>(A.get_ref());
00497   }
00498 
00499 
00500 
00501 //
00502 // sqrt
00503 
00504 template<typename T1>
00505 arma_inline
00506 const eOp<T1, eop_sqrt>
00507 sqrt(const Base<typename T1::elem_type,T1>& A)
00508   {
00509   arma_extra_debug_sigprint();
00510   
00511   return eOp<T1, eop_sqrt>(A.get_ref());
00512   }
00513 
00514 
00515 
00516 template<typename T1>
00517 arma_inline
00518 const eOpCube<T1, eop_cube_sqrt>
00519 sqrt(const BaseCube<typename T1::elem_type,T1>& A)
00520   {
00521   arma_extra_debug_sigprint();
00522   
00523   return eOpCube<T1, eop_cube_sqrt>(A.get_ref());
00524   }
00525 
00526 
00527 
00528 //
00529 // conj
00530 
00531 template<typename T1>
00532 arma_inline
00533 const T1&
00534 conj(const Base<typename T1::pod_type,T1>& A)
00535   {
00536   arma_extra_debug_sigprint();
00537 
00538   return A.get_ref();
00539   }
00540 
00541 
00542 
00543 template<typename T1>
00544 arma_inline
00545 const T1&
00546 conj(const BaseCube<typename T1::pod_type,T1>& A)
00547   {
00548   arma_extra_debug_sigprint();
00549 
00550   return A.get_ref();
00551   }
00552 
00553 
00554 
00555 template<typename T1>
00556 arma_inline
00557 const eOp<T1, eop_conj>
00558 conj(const Base<std::complex<typename T1::pod_type>,T1>& A)
00559   {
00560   arma_extra_debug_sigprint();
00561 
00562   return eOp<T1, eop_conj>(A.get_ref());
00563   }
00564 
00565 
00566 
00567 template<typename T1>
00568 arma_inline
00569 const eOpCube<T1, eop_cube_conj>
00570 conj(const BaseCube<std::complex<typename T1::pod_type>,T1>& A)
00571   {
00572   arma_extra_debug_sigprint();
00573 
00574   return eOpCube<T1, eop_cube_conj>(A.get_ref());
00575   }
00576 
00577 
00578 
00579 template<typename T1>
00580 arma_inline
00581 const T1&
00582 conj(const eOp<T1, eop_conj>& A)
00583   {
00584   arma_extra_debug_sigprint();
00585   
00586   return A.m;
00587   }
00588 
00589 
00590 
00591 template<typename T1>
00592 arma_inline
00593 const T1&
00594 conj(const eOpCube<T1, eop_cube_conj>& A)
00595   {
00596   arma_extra_debug_sigprint();
00597   
00598   return A.m;
00599   }
00600 
00601 
00602 
00603 // TODO: this needs a more elaborate template restriction mechanism to work properly,
00604 //       i.e. an overloaded version of thus function should do nothing if the input type is non-complex
00605 // 
00606 // //! the conjugate of the transpose of a complex matrix is the same as the hermitian transpose
00607 // template<typename T1>
00608 // arma_inline
00609 // const Op<T1, op_htrans>
00610 // conj(const Op<T1, op_trans>& A)
00611 //   {
00612 //   arma_extra_debug_sigprint();
00613 //   
00614 //   return Op<T1, op_htrans>(A.m);
00615 //   }
00616 
00617 
00618 
00619 // pow
00620 
00621 template<typename T1>
00622 arma_inline
00623 const eOp<T1, eop_pow>
00624 pow(const Base<typename T1::elem_type,T1>& A, const typename T1::elem_type exponent)
00625   {
00626   arma_extra_debug_sigprint();
00627   
00628   return eOp<T1, eop_pow>(A.get_ref(), exponent);
00629   }
00630 
00631 
00632 
00633 template<typename T1>
00634 arma_inline
00635 const eOpCube<T1, eop_cube_pow>
00636 pow(const BaseCube<typename T1::elem_type,T1>& A, const typename T1::elem_type exponent)
00637   {
00638   arma_extra_debug_sigprint();
00639   
00640   return eOpCube<T1, eop_cube_pow>(A.get_ref(), exponent);
00641   }
00642 
00643 
00644 
00645 // pow, specialised handling (non-complex exponent for complex matrices)
00646 
00647 template<typename T1>
00648 arma_inline
00649 const eOp<T1, eop_pow>
00650 pow(const Base<typename T1::elem_type,T1>& A, const typename T1::elem_type::value_type exponent)
00651   {
00652   arma_extra_debug_sigprint();
00653   
00654   typedef typename T1::elem_type eT;
00655   
00656   return eOp<T1, eop_pow>(A.get_ref(), eT(exponent));
00657   }
00658 
00659 
00660 
00661 template<typename T1>
00662 arma_inline
00663 const eOpCube<T1, eop_cube_pow>
00664 pow(const BaseCube<typename T1::elem_type,T1>& A, const typename T1::elem_type::value_type exponent)
00665   {
00666   arma_extra_debug_sigprint();
00667   
00668   typedef typename T1::elem_type eT;
00669   
00670   return eOpCube<T1, eop_cube_pow>(A.get_ref(), eT(exponent));
00671   }
00672 
00673 
00674 
00675 #if defined(ARMA_GOOD_COMPILER)
00676 
00677 
00678 // pow_s32  (integer exponent)
00679 
00680 template<typename T1>
00681 arma_inline
00682 const eOp<T1, eop_pow_int>
00683 pow(const Base<typename T1::elem_type,T1>& A, const int exponent)
00684   {
00685   arma_extra_debug_sigprint();
00686   
00687   if(exponent >= 0)
00688     {
00689     return eOp<T1, eop_pow_int>(A.get_ref(), exponent, 0);
00690     }
00691   else
00692     {
00693     return eOp<T1, eop_pow_int>(A.get_ref(), -exponent, 1);
00694     }
00695   }
00696 
00697 
00698 
00699 template<typename T1>
00700 arma_inline
00701 const eOpCube<T1, eop_cube_pow_int>
00702 pow(const BaseCube<typename T1::elem_type,T1>& A, const int exponent)
00703   {
00704   arma_extra_debug_sigprint();
00705   
00706   if(exponent >= 0)
00707     {
00708     return eOpCube<T1, eop_cube_pow_int>(A.get_ref(),  exponent, 0);
00709     }
00710   else
00711     {
00712     return eOpCube<T1, eop_cube_pow_int>(A.get_ref(), -exponent, 1);
00713     }
00714   }
00715 
00716 
00717 
00718 #endif
00719 
00720 
00721 
00722 //! @}