1 | // boost atanh.hpp header file |
2 | |
3 | // (C) Copyright 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_ATANH_HPP |
12 | #define BOOST_ATANH_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/policies/error_handling.hpp> |
23 | #include <boost/math/special_functions/math_fwd.hpp> |
24 | #include <boost/math/special_functions/log1p.hpp> |
25 | |
26 | // This is the inverse of the hyperbolic tangent function. |
27 | |
28 | namespace boost |
29 | { |
30 | namespace math |
31 | { |
32 | namespace detail |
33 | { |
34 | // This is the main fare |
35 | |
36 | template<typename T, typename Policy> |
37 | inline T atanh_imp(const T x, const Policy& pol) |
38 | { |
39 | BOOST_MATH_STD_USING |
40 | static const char* function = "boost::math::atanh<%1%>(%1%)" ; |
41 | |
42 | if(x < -1) |
43 | { |
44 | return policies::raise_domain_error<T>( |
45 | function, |
46 | "atanh requires x >= -1, but got x = %1%." , x, pol); |
47 | } |
48 | else if(x > 1) |
49 | { |
50 | return policies::raise_domain_error<T>( |
51 | function, |
52 | "atanh requires x <= 1, but got x = %1%." , x, pol); |
53 | } |
54 | else if((boost::math::isnan)(x)) |
55 | { |
56 | return policies::raise_domain_error<T>( |
57 | function, |
58 | "atanh requires -1 <= x <= 1, but got x = %1%." , x, pol); |
59 | } |
60 | else if(x < -1 + tools::epsilon<T>()) |
61 | { |
62 | // -Infinity: |
63 | return -policies::raise_overflow_error<T>(function, 0, pol); |
64 | } |
65 | else if(x > 1 - tools::epsilon<T>()) |
66 | { |
67 | // Infinity: |
68 | return policies::raise_overflow_error<T>(function, 0, pol); |
69 | } |
70 | else if(abs(x) >= tools::forth_root_epsilon<T>()) |
71 | { |
72 | // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/02/ |
73 | if(abs(x) < 0.5f) |
74 | return (boost::math::log1p(x, pol) - boost::math::log1p(-x, pol)) / 2; |
75 | return(log( (1 + x) / (1 - x) ) / 2); |
76 | } |
77 | else |
78 | { |
79 | // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/06/01/03/01/ |
80 | // approximation by taylor series in x at 0 up to order 2 |
81 | T result = x; |
82 | |
83 | if (abs(x) >= tools::root_epsilon<T>()) |
84 | { |
85 | T x3 = x*x*x; |
86 | |
87 | // approximation by taylor series in x at 0 up to order 4 |
88 | result += x3/static_cast<T>(3); |
89 | } |
90 | |
91 | return(result); |
92 | } |
93 | } |
94 | } |
95 | |
96 | template<typename T, typename Policy> |
97 | inline typename tools::promote_args<T>::type atanh(T x, const Policy&) |
98 | { |
99 | typedef typename tools::promote_args<T>::type result_type; |
100 | typedef typename policies::evaluation<result_type, Policy>::type value_type; |
101 | typedef typename policies::normalise< |
102 | Policy, |
103 | policies::promote_float<false>, |
104 | policies::promote_double<false>, |
105 | policies::discrete_quantile<>, |
106 | policies::assert_undefined<> >::type forwarding_policy; |
107 | return policies::checked_narrowing_cast<result_type, forwarding_policy>( |
108 | detail::atanh_imp(static_cast<value_type>(x), forwarding_policy()), |
109 | "boost::math::atanh<%1%>(%1%)" ); |
110 | } |
111 | template<typename T> |
112 | inline typename tools::promote_args<T>::type atanh(T x) |
113 | { |
114 | return boost::math::atanh(x, policies::policy<>()); |
115 | } |
116 | |
117 | } |
118 | } |
119 | |
120 | #endif /* BOOST_ATANH_HPP */ |
121 | |
122 | |
123 | |
124 | |