source: NonGTP/Boost/boost/math/special_functions/acosh.hpp @ 857

Revision 857, 6.2 KB checked in by igarcia, 18 years ago (diff)
Line 
1//    boost asinh.hpp header file
2
3//  (C) Copyright Eric Ford 2001 & Hubert Holin.
4//  Distributed under the Boost Software License, Version 1.0. (See
5//  accompanying file LICENSE_1_0.txt or copy at
6//  http://www.boost.org/LICENSE_1_0.txt)
7
8// See http://www.boost.org for updates, documentation, and revision history.
9
10#ifndef BOOST_ACOSH_HPP
11#define BOOST_ACOSH_HPP
12
13
14#include <cmath>
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
25namespace boost
26{
27    namespace math
28    {
29#if defined(__GNUC__) && (__GNUC__ < 3)
30        // gcc 2.x ignores function scope using declarations,
31        // put them in the scope of the enclosing namespace instead:
32       
33        using    ::std::abs;
34        using    ::std::sqrt;
35        using    ::std::log;
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}
195
196#endif /* BOOST_ACOSH_HPP */
197
198
Note: See TracBrowser for help on using the repository browser.