cmath_wrap.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 
00018 //! \addtogroup cmath_wrap
00019 //! @{
00020 
00021 
00022 
00023 //
00024 // wrappers for isfinite
00025 //
00026 
00027 
00028 
00029 template<typename eT>
00030 arma_inline
00031 bool
00032 arma_isfinite(eT val)
00033   {
00034   return true;
00035   }
00036 
00037 
00038 
00039 template<>
00040 arma_inline
00041 bool
00042 arma_isfinite(float x)
00043   {
00044   #if defined(ARMA_HAVE_STD_ISFINITE)
00045     {
00046     return (std::isfinite(x) != 0);
00047     }
00048   #else
00049     {
00050     const bool x_is_inf = ( (x == x) && ((x - x) != float(0)) );
00051     const bool x_is_nan = (x != x);
00052 
00053     return ( (x_is_inf == false) && (x_is_nan == false) );
00054     }
00055   #endif
00056   }
00057 
00058 
00059 
00060 template<>
00061 arma_inline
00062 bool
00063 arma_isfinite(double x)
00064   {
00065   #if defined(ARMA_HAVE_STD_ISFINITE)
00066     {
00067     return (std::isfinite(x) != 0);
00068     }
00069   #else
00070     {
00071     const bool x_is_inf = ( (x == x) && ((x - x) != double(0)) );
00072     const bool x_is_nan = (x != x);
00073 
00074     return ( (x_is_inf == false) && (x_is_nan == false) );
00075     }
00076   #endif
00077   }
00078 
00079 
00080 
00081 template<typename T>
00082 arma_inline
00083 bool
00084 arma_isfinite(const std::complex<T>& x)
00085   {
00086   if( (arma_isfinite(x.real()) == false) || (arma_isfinite(x.imag()) == false) )
00087     {
00088     return false;
00089     }
00090   else
00091     {
00092     return true;
00093     }
00094   }
00095 
00096 
00097 
00098 //
00099 // wrappers for trigonometric functions
00100 //
00101 
00102 
00103 
00104 // Wherever possible, try to use TR1 versions of the functions below,
00105 // otherwise fall back to Boost Math.
00106 //
00107 // complex acos
00108 // complex asin
00109 // complex atan
00110 //
00111 // real    acosh
00112 // real    asinh
00113 // real    atanh
00114 //
00115 // complex acosh
00116 // complex asinh
00117 // complex atanh
00118 // 
00119 // 
00120 // If TR1 not present and Boost math not present,
00121 // we have our own rudimentary versions of:
00122 // 
00123 // real    acosh
00124 // real    asinh
00125 // real    atanh
00126 
00127 
00128 
00129 #if defined(ARMA_USE_BOOST)
00130   #define arma_boost_wrap(trig_fn, val) ( (boost::math::trig_fn)(val) )
00131 #else
00132   #define arma_boost_wrap(trig_fn, val) ( arma_stop( #trig_fn "(): need Boost libraries" ), val )
00133 #endif
00134 
00135 
00136 template<typename T>
00137 arma_inline
00138 std::complex<T>
00139 arma_acos(const std::complex<T>& x)
00140   {
00141   #if defined(ARMA_HAVE_STD_TR1)
00142     {
00143     return std::tr1::acos(x);
00144     }
00145   #else
00146     {
00147     return arma_boost_wrap(acos, x);
00148     }
00149   #endif
00150   }
00151 
00152 
00153 
00154 template<typename T>
00155 arma_inline
00156 std::complex<T>
00157 arma_asin(const std::complex<T>& x)
00158   {
00159   #if defined(ARMA_HAVE_STD_TR1)
00160     {
00161     return std::tr1::asin(x);
00162     }
00163   #else
00164     {
00165     return arma_boost_wrap(asin, x);
00166     }
00167   #endif
00168   }
00169 
00170 
00171 
00172 template<typename T>
00173 arma_inline
00174 std::complex<T>
00175 arma_atan(const std::complex<T>& x)
00176   {
00177   #if defined(ARMA_HAVE_STD_TR1)
00178     {
00179     return std::tr1::atan(x);
00180     }
00181   #else
00182     {
00183     return arma_boost_wrap(atan, x);
00184     }
00185   #endif
00186   }
00187 
00188 
00189 
00190 template<typename eT>
00191 arma_inline
00192 eT
00193 arma_acosh(const eT x)
00194   {
00195   #if defined(ARMA_HAVE_STD_TR1)
00196     {
00197     return std::tr1::acosh(x);
00198     }
00199   #elif defined(ARMA_USE_BOOST)
00200     {
00201     return boost::math::acosh(x);
00202     }
00203   #else
00204     {
00205     if(x >= eT(1))
00206       {
00207       // http://functions.wolfram.com/ElementaryFunctions/ArcCosh/02/
00208       return std::log( x + std::sqrt(x*x - eT(1)) );
00209       }
00210     else
00211       {
00212       if(std::numeric_limits<eT>::has_quiet_NaN == true)
00213         {
00214         return -(std::numeric_limits<eT>::quiet_NaN());
00215         }
00216       else
00217         {
00218         return eT(0);
00219         }
00220       }
00221     }
00222   #endif
00223   }
00224 
00225 
00226 
00227 template<typename eT>
00228 arma_inline
00229 eT
00230 arma_asinh(const eT x)
00231   {
00232   #if defined(ARMA_HAVE_STD_TR1)
00233     {
00234     return std::tr1::asinh(x);
00235     }
00236   #elif defined(ARMA_USE_BOOST)
00237     {
00238     return boost::math::asinh(x);
00239     }
00240   #else
00241     {
00242     // http://functions.wolfram.com/ElementaryFunctions/ArcSinh/02/
00243     return std::log( x + std::sqrt(x*x + eT(1)) );
00244     }
00245   #endif
00246   }
00247 
00248 
00249 
00250 template<typename eT>
00251 arma_inline
00252 eT
00253 arma_atanh(const eT x)
00254   {
00255   #if defined(ARMA_HAVE_STD_TR1)
00256     {
00257     return std::tr1::atanh(x);
00258     }
00259   #elif defined(ARMA_USE_BOOST)
00260     {
00261     return boost::math::atanh(x);
00262     }
00263   #else
00264     {
00265     if( (x >= eT(-1)) && (x <= eT(+1)) )
00266       {
00267       // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/02/
00268       return std::log( ( eT(1)+x ) / ( eT(1)-x ) ) / eT(2);
00269       }
00270     else
00271       {
00272       if(std::numeric_limits<eT>::has_quiet_NaN == true)
00273         {
00274         return -(std::numeric_limits<eT>::quiet_NaN());
00275         }
00276       else
00277         {
00278         return eT(0);
00279         }
00280       }
00281     }
00282   #endif
00283   }
00284 
00285 
00286 
00287 template<typename T>
00288 arma_inline
00289 std::complex<T>
00290 arma_acosh(const std::complex<T>& x)
00291   {
00292   #if defined(ARMA_HAVE_STD_TR1)
00293     {
00294     return std::tr1::acosh(x);
00295     }
00296   #else
00297     {
00298     return arma_boost_wrap(acosh, x);
00299     }
00300   #endif
00301   }
00302 
00303 
00304 
00305 template<typename T>
00306 arma_inline
00307 std::complex<T>
00308 arma_asinh(const std::complex<T>& x)
00309   {
00310   #if defined(ARMA_HAVE_STD_TR1)
00311     {
00312     return std::tr1::asinh(x);
00313     }
00314   #else
00315     {
00316     return arma_boost_wrap(asinh, x);
00317     }
00318   #endif
00319   }
00320 
00321 
00322 
00323 template<typename T>
00324 arma_inline
00325 std::complex<T>
00326 arma_atanh(const std::complex<T>& x)
00327   {
00328   #if defined(ARMA_HAVE_STD_TR1)
00329     {
00330     return std::tr1::atanh(x);
00331     }
00332   #else
00333     {
00334     return arma_boost_wrap(atanh, x);
00335     }
00336   #endif
00337   }
00338 
00339 
00340 
00341 #undef arma_boost_wrap
00342 
00343 
00344 
00345 //! @}