1 // boost asinh.hpp header file |
1 // (C) Copyright John Maddock 2005. |
|
2 // Use, modification and distribution are subject to the |
|
3 // Boost Software License, Version 1.0. (See accompanying file |
|
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
2 |
5 |
3 // (C) Copyright Eric Ford 2001 & Hubert Holin. |
6 #ifndef BOOST_MATH_COMPLEX_ACOSH_INCLUDED |
4 // Distributed under the Boost Software License, Version 1.0. (See |
7 #define BOOST_MATH_COMPLEX_ACOSH_INCLUDED |
5 // accompanying file LICENSE_1_0.txt or copy at |
|
6 // http://www.boost.org/LICENSE_1_0.txt) |
|
7 |
8 |
8 // See http://www.boost.org for updates, documentation, and revision history. |
9 #ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED |
|
10 # include <boost/math/complex/details.hpp> |
|
11 #endif |
|
12 #ifndef BOOST_MATH_COMPLEX_ATANH_INCLUDED |
|
13 # include <boost/math/complex/acos.hpp> |
|
14 #endif |
9 |
15 |
10 #ifndef BOOST_ACOSH_HPP |
16 namespace boost{ namespace math{ |
11 #define BOOST_ACOSH_HPP |
|
12 |
17 |
13 |
18 template<class T> |
14 #include <cmath> |
19 inline std::complex<T> acosh(const std::complex<T>& z) |
15 #include <limits> |
|
16 #include <string> |
|
17 #include <stdexcept> |
|
18 |
|
19 |
|
20 #include <boost/config.hpp> |
|
21 |
|
22 |
|
23 // This is the inverse of the hyperbolic cosine function. |
|
24 |
|
25 namespace boost |
|
26 { |
20 { |
27 namespace math |
21 // |
28 { |
22 // We use the relation acosh(z) = +-i acos(z) |
29 #if defined(__GNUC__) && (__GNUC__ < 3) |
23 // Choosing the sign of multiplier to give real(acosh(z)) >= 0 |
30 // gcc 2.x ignores function scope using declarations, |
24 // as well as compatibility with C99. |
31 // put them in the scope of the enclosing namespace instead: |
25 // |
32 |
26 std::complex<T> result = boost::math::acos(z); |
33 using ::std::abs; |
27 if(!detail::test_is_nan(result.imag()) && result.imag() <= 0) |
34 using ::std::sqrt; |
28 return detail::mult_i(result); |
35 using ::std::log; |
29 return detail::mult_minus_i(result); |
36 |
|
37 using ::std::numeric_limits; |
|
38 #endif |
|
39 |
|
40 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) |
|
41 // This is the main fare |
|
42 |
|
43 template<typename T> |
|
44 inline T acosh(const T x) |
|
45 { |
|
46 using ::std::abs; |
|
47 using ::std::sqrt; |
|
48 using ::std::log; |
|
49 |
|
50 using ::std::numeric_limits; |
|
51 |
|
52 |
|
53 T const one = static_cast<T>(1); |
|
54 T const two = static_cast<T>(2); |
|
55 |
|
56 static T const taylor_2_bound = sqrt(numeric_limits<T>::epsilon()); |
|
57 static T const taylor_n_bound = sqrt(taylor_2_bound); |
|
58 static T const upper_taylor_2_bound = one/taylor_2_bound; |
|
59 |
|
60 if (x < one) |
|
61 { |
|
62 if (numeric_limits<T>::has_quiet_NaN) |
|
63 { |
|
64 return(numeric_limits<T>::quiet_NaN()); |
|
65 } |
|
66 else |
|
67 { |
|
68 ::std::string error_reporting("Argument to atanh is strictly greater than +1 or strictly smaller than -1!"); |
|
69 ::std::domain_error bad_argument(error_reporting); |
|
70 |
|
71 throw(bad_argument); |
|
72 } |
|
73 } |
|
74 else if (x >= taylor_n_bound) |
|
75 { |
|
76 if (x > upper_taylor_2_bound) |
|
77 { |
|
78 // approximation by laurent series in 1/x at 0+ order from -1 to 0 |
|
79 return( log( x*two) ); |
|
80 } |
|
81 else |
|
82 { |
|
83 return( log( x + sqrt(x*x-one) ) ); |
|
84 } |
|
85 } |
|
86 else |
|
87 { |
|
88 T y = sqrt(x-one); |
|
89 |
|
90 // approximation by taylor series in y at 0 up to order 2 |
|
91 T result = y; |
|
92 |
|
93 if (y >= taylor_2_bound) |
|
94 { |
|
95 T y3 = y*y*y; |
|
96 |
|
97 // approximation by taylor series in y at 0 up to order 4 |
|
98 result -= y3/static_cast<T>(12); |
|
99 } |
|
100 |
|
101 return(sqrt(static_cast<T>(2))*result); |
|
102 } |
|
103 } |
|
104 #else |
|
105 // These are implementation details (for main fare see below) |
|
106 |
|
107 namespace detail |
|
108 { |
|
109 template < |
|
110 typename T, |
|
111 bool QuietNanSupported |
|
112 > |
|
113 struct acosh_helper2_t |
|
114 { |
|
115 static T get_NaN() |
|
116 { |
|
117 return(::std::numeric_limits<T>::quiet_NaN()); |
|
118 } |
|
119 }; // boost::detail::acosh_helper2_t |
|
120 |
|
121 |
|
122 template<typename T> |
|
123 struct acosh_helper2_t<T, false> |
|
124 { |
|
125 static T get_NaN() |
|
126 { |
|
127 ::std::string error_reporting("Argument to acosh is greater than or equal to +1!"); |
|
128 ::std::domain_error bad_argument(error_reporting); |
|
129 |
|
130 throw(bad_argument); |
|
131 } |
|
132 }; // boost::detail::acosh_helper2_t |
|
133 |
|
134 } // boost::detail |
|
135 |
|
136 |
|
137 // This is the main fare |
|
138 |
|
139 template<typename T> |
|
140 inline T acosh(const T x) |
|
141 { |
|
142 using ::std::abs; |
|
143 using ::std::sqrt; |
|
144 using ::std::log; |
|
145 |
|
146 using ::std::numeric_limits; |
|
147 |
|
148 typedef detail::acosh_helper2_t<T, std::numeric_limits<T>::has_quiet_NaN> helper2_type; |
|
149 |
|
150 |
|
151 T const one = static_cast<T>(1); |
|
152 T const two = static_cast<T>(2); |
|
153 |
|
154 static T const taylor_2_bound = sqrt(numeric_limits<T>::epsilon()); |
|
155 static T const taylor_n_bound = sqrt(taylor_2_bound); |
|
156 static T const upper_taylor_2_bound = one/taylor_2_bound; |
|
157 |
|
158 if (x < one) |
|
159 { |
|
160 return(helper2_type::get_NaN()); |
|
161 } |
|
162 else if (x >= taylor_n_bound) |
|
163 { |
|
164 if (x > upper_taylor_2_bound) |
|
165 { |
|
166 // approximation by laurent series in 1/x at 0+ order from -1 to 0 |
|
167 return( log( x*two) ); |
|
168 } |
|
169 else |
|
170 { |
|
171 return( log( x + sqrt(x*x-one) ) ); |
|
172 } |
|
173 } |
|
174 else |
|
175 { |
|
176 T y = sqrt(x-one); |
|
177 |
|
178 // approximation by taylor series in y at 0 up to order 2 |
|
179 T result = y; |
|
180 |
|
181 if (y >= taylor_2_bound) |
|
182 { |
|
183 T y3 = y*y*y; |
|
184 |
|
185 // approximation by taylor series in y at 0 up to order 4 |
|
186 result -= y3/static_cast<T>(12); |
|
187 } |
|
188 |
|
189 return(sqrt(static_cast<T>(2))*result); |
|
190 } |
|
191 } |
|
192 #endif /* defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) */ |
|
193 } |
|
194 } |
30 } |
195 |
31 |
196 #endif /* BOOST_ACOSH_HPP */ |
32 } } // namespaces |
197 |
33 |
198 |
34 #endif // BOOST_MATH_COMPLEX_ACOSH_INCLUDED |