Chris@49: // Copyright (C) 2008-2010 NICTA (www.nicta.com.au) Chris@49: // Copyright (C) 2008-2010 Conrad Sanderson Chris@49: // Chris@49: // This Source Code Form is subject to the terms of the Mozilla Public Chris@49: // License, v. 2.0. If a copy of the MPL was not distributed with this Chris@49: // file, You can obtain one at http://mozilla.org/MPL/2.0/. Chris@49: Chris@49: Chris@49: Chris@49: //! \addtogroup cmath_wrap Chris@49: //! @{ Chris@49: Chris@49: Chris@49: Chris@49: // Chris@49: // wrappers for isfinite Chris@49: // Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: bool Chris@49: arma_isfinite(eT val) Chris@49: { Chris@49: arma_ignore(val); Chris@49: Chris@49: return true; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template<> Chris@49: arma_inline Chris@49: bool Chris@49: arma_isfinite(float x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_ISFINITE) Chris@49: { Chris@49: return (std::isfinite(x) != 0); Chris@49: } Chris@49: #else Chris@49: { Chris@49: const bool x_is_inf = ( (x == x) && ((x - x) != float(0)) ); Chris@49: const bool x_is_nan = (x != x); Chris@49: Chris@49: return ( (x_is_inf == false) && (x_is_nan == false) ); Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template<> Chris@49: arma_inline Chris@49: bool Chris@49: arma_isfinite(double x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_ISFINITE) Chris@49: { Chris@49: return (std::isfinite(x) != 0); Chris@49: } Chris@49: #else Chris@49: { Chris@49: const bool x_is_inf = ( (x == x) && ((x - x) != double(0)) ); Chris@49: const bool x_is_nan = (x != x); Chris@49: Chris@49: return ( (x_is_inf == false) && (x_is_nan == false) ); Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: bool Chris@49: arma_isfinite(const std::complex& x) Chris@49: { Chris@49: if( (arma_isfinite(x.real()) == false) || (arma_isfinite(x.imag()) == false) ) Chris@49: { Chris@49: return false; Chris@49: } Chris@49: else Chris@49: { Chris@49: return true; Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: // Chris@49: // wrappers for trigonometric functions Chris@49: // Chris@49: Chris@49: Chris@49: Chris@49: // Wherever possible, try to use TR1 versions of the functions below, Chris@49: // otherwise fall back to Boost Math. Chris@49: // Chris@49: // complex acos Chris@49: // complex asin Chris@49: // complex atan Chris@49: // Chris@49: // real acosh Chris@49: // real asinh Chris@49: // real atanh Chris@49: // Chris@49: // complex acosh Chris@49: // complex asinh Chris@49: // complex atanh Chris@49: // Chris@49: // Chris@49: // If TR1 not present and Boost math not present, Chris@49: // we have our own rudimentary versions of: Chris@49: // Chris@49: // real acosh Chris@49: // real asinh Chris@49: // real atanh Chris@49: Chris@49: Chris@49: Chris@49: #if defined(ARMA_USE_BOOST) Chris@49: #define arma_boost_wrap(trig_fn, val) ( (boost::math::trig_fn)(val) ) Chris@49: #else Chris@49: #define arma_boost_wrap(trig_fn, val) ( arma_stop( #trig_fn "(): need Boost libraries" ), val ) Chris@49: #endif Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: std::complex Chris@49: arma_acos(const std::complex& x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_TR1) Chris@49: { Chris@49: return std::tr1::acos(x); Chris@49: } Chris@49: #else Chris@49: { Chris@49: return arma_boost_wrap(acos, x); Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: std::complex Chris@49: arma_asin(const std::complex& x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_TR1) Chris@49: { Chris@49: return std::tr1::asin(x); Chris@49: } Chris@49: #else Chris@49: { Chris@49: return arma_boost_wrap(asin, x); Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: std::complex Chris@49: arma_atan(const std::complex& x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_TR1) Chris@49: { Chris@49: return std::tr1::atan(x); Chris@49: } Chris@49: #else Chris@49: { Chris@49: return arma_boost_wrap(atan, x); Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: eT Chris@49: arma_acosh(const eT x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_TR1) Chris@49: { Chris@49: return std::tr1::acosh(x); Chris@49: } Chris@49: #elif defined(ARMA_USE_BOOST) Chris@49: { Chris@49: return boost::math::acosh(x); Chris@49: } Chris@49: #else Chris@49: { Chris@49: if(x >= eT(1)) Chris@49: { Chris@49: // http://functions.wolfram.com/ElementaryFunctions/ArcCosh/02/ Chris@49: return std::log( x + std::sqrt(x*x - eT(1)) ); Chris@49: } Chris@49: else Chris@49: { Chris@49: if(std::numeric_limits::has_quiet_NaN == true) Chris@49: { Chris@49: return -(std::numeric_limits::quiet_NaN()); Chris@49: } Chris@49: else Chris@49: { Chris@49: return eT(0); Chris@49: } Chris@49: } Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: eT Chris@49: arma_asinh(const eT x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_TR1) Chris@49: { Chris@49: return std::tr1::asinh(x); Chris@49: } Chris@49: #elif defined(ARMA_USE_BOOST) Chris@49: { Chris@49: return boost::math::asinh(x); Chris@49: } Chris@49: #else Chris@49: { Chris@49: // http://functions.wolfram.com/ElementaryFunctions/ArcSinh/02/ Chris@49: return std::log( x + std::sqrt(x*x + eT(1)) ); Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: eT Chris@49: arma_atanh(const eT x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_TR1) Chris@49: { Chris@49: return std::tr1::atanh(x); Chris@49: } Chris@49: #elif defined(ARMA_USE_BOOST) Chris@49: { Chris@49: return boost::math::atanh(x); Chris@49: } Chris@49: #else Chris@49: { Chris@49: if( (x >= eT(-1)) && (x <= eT(+1)) ) Chris@49: { Chris@49: // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/02/ Chris@49: return std::log( ( eT(1)+x ) / ( eT(1)-x ) ) / eT(2); Chris@49: } Chris@49: else Chris@49: { Chris@49: if(std::numeric_limits::has_quiet_NaN == true) Chris@49: { Chris@49: return -(std::numeric_limits::quiet_NaN()); Chris@49: } Chris@49: else Chris@49: { Chris@49: return eT(0); Chris@49: } Chris@49: } Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: std::complex Chris@49: arma_acosh(const std::complex& x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_TR1) Chris@49: { Chris@49: return std::tr1::acosh(x); Chris@49: } Chris@49: #else Chris@49: { Chris@49: return arma_boost_wrap(acosh, x); Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: std::complex Chris@49: arma_asinh(const std::complex& x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_TR1) Chris@49: { Chris@49: return std::tr1::asinh(x); Chris@49: } Chris@49: #else Chris@49: { Chris@49: return arma_boost_wrap(asinh, x); Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: std::complex Chris@49: arma_atanh(const std::complex& x) Chris@49: { Chris@49: #if defined(ARMA_HAVE_STD_TR1) Chris@49: { Chris@49: return std::tr1::atanh(x); Chris@49: } Chris@49: #else Chris@49: { Chris@49: return arma_boost_wrap(atanh, x); Chris@49: } Chris@49: #endif Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: #undef arma_boost_wrap Chris@49: Chris@49: Chris@49: Chris@49: //! @}