1 // boost asinh.hpp header file 2 3 // (C) Copyright Eric Ford & Hubert Holin 2001. 4 // (C) Copyright John Maddock 2008. 5 // Distributed under the Boost Software License, Version 1.0. (See 6 // accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 9 // See http://www.boost.org for updates, documentation, and revision history. 10 11 #ifndef BOOST_ASINH_HPP 12 #define BOOST_ASINH_HPP 13 14 #ifdef _MSC_VER 15 #pragma once 16 #endif 17 18 19 #include <boost/config/no_tr1/cmath.hpp> 20 #include <boost/config.hpp> 21 #include <boost/math/tools/precision.hpp> 22 #include <boost/math/special_functions/math_fwd.hpp> 23 #include <boost/math/special_functions/sqrt1pm1.hpp> 24 #include <boost/math/special_functions/log1p.hpp> 25 #include <boost/math/constants/constants.hpp> 26 27 // This is the inverse of the hyperbolic sine function. 28 29 namespace boost 30 { 31 namespace math 32 { 33 namespace detail{ 34 template<typename T, class Policy> asinh_imp(const T x,const Policy & pol)35 inline T asinh_imp(const T x, const Policy& pol) 36 { 37 BOOST_MATH_STD_USING 38 39 if((boost::math::isnan)(x)) 40 { 41 return policies::raise_domain_error<T>( 42 "boost::math::asinh<%1%>(%1%)", 43 "asinh requires a finite argument, but got x = %1%.", x, pol); 44 } 45 if (x >= tools::forth_root_epsilon<T>()) 46 { 47 if (x > 1 / tools::root_epsilon<T>()) 48 { 49 // http://functions.wolfram.com/ElementaryFunctions/ArcSinh/06/01/06/01/0001/ 50 // approximation by laurent series in 1/x at 0+ order from -1 to 1 51 return constants::ln_two<T>() + log(x) + 1/ (4 * x * x); 52 } 53 else if(x < 0.5f) 54 { 55 // As below, but rearranged to preserve digits: 56 return boost::math::log1p(x + boost::math::sqrt1pm1(x * x, pol), pol); 57 } 58 else 59 { 60 // http://functions.wolfram.com/ElementaryFunctions/ArcSinh/02/ 61 return( log( x + sqrt(x*x+1) ) ); 62 } 63 } 64 else if (x <= -tools::forth_root_epsilon<T>()) 65 { 66 return(-asinh(-x, pol)); 67 } 68 else 69 { 70 // http://functions.wolfram.com/ElementaryFunctions/ArcSinh/06/01/03/01/0001/ 71 // approximation by taylor series in x at 0 up to order 2 72 T result = x; 73 74 if (abs(x) >= tools::root_epsilon<T>()) 75 { 76 T x3 = x*x*x; 77 78 // approximation by taylor series in x at 0 up to order 4 79 result -= x3/static_cast<T>(6); 80 } 81 82 return(result); 83 } 84 } 85 } 86 87 template<typename T> asinh(T x)88 inline typename tools::promote_args<T>::type asinh(T x) 89 { 90 return boost::math::asinh(x, policies::policy<>()); 91 } 92 template<typename T, typename Policy> asinh(T x,const Policy &)93 inline typename tools::promote_args<T>::type asinh(T x, const Policy&) 94 { 95 typedef typename tools::promote_args<T>::type result_type; 96 typedef typename policies::evaluation<result_type, Policy>::type value_type; 97 typedef typename policies::normalise< 98 Policy, 99 policies::promote_float<false>, 100 policies::promote_double<false>, 101 policies::discrete_quantile<>, 102 policies::assert_undefined<> >::type forwarding_policy; 103 return policies::checked_narrowing_cast<result_type, forwarding_policy>( 104 detail::asinh_imp(static_cast<value_type>(x), forwarding_policy()), 105 "boost::math::asinh<%1%>(%1%)"); 106 } 107 108 } 109 } 110 111 #endif /* BOOST_ASINH_HPP */ 112 113