1 // unit test file atanh.hpp for the special functions test suite
2 
3 //  (C) Copyright Hubert Holin 2003.
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 
9 #include <functional>
10 #include <iomanip>
11 //#include <iostream>
12 
13 #define BOOST_TEST_MAiN
14 #include <boost/math/special_functions/atanh.hpp>
15 
16 
17 #include <boost/test/unit_test.hpp>
18 
19 template<typename T>
atanh_error_evaluator(T x)20 T    atanh_error_evaluator(T x)
21 {
22     using    ::std::abs;
23     using    ::std::tanh;
24     using    ::std::cosh;
25 
26     using    ::std::numeric_limits;
27 
28     using    ::boost::math::atanh;
29 
30 
31     static T const   epsilon = numeric_limits<float>::epsilon();
32 
33     T                y = tanh(x);
34     T                z = atanh(y);
35 
36     T                absolute_error = abs(z-x);
37     T                relative_error = absolute_error/(cosh(x)*cosh(x));
38     T                scaled_error = relative_error/epsilon;
39 
40     return(scaled_error);
41 }
42 
43 
BOOST_TEST_CASE_TEMPLATE_FUNCTION(atanh_test,T)44 BOOST_TEST_CASE_TEMPLATE_FUNCTION(atanh_test, T)
45 {
46     using    ::std::abs;
47     using    ::std::tanh;
48     using    ::std::log;
49 
50     using    ::std::numeric_limits;
51 
52     using    ::boost::math::atanh;
53 
54 
55     BOOST_TEST_MESSAGE("Testing atanh in the real domain for "
56         << string_type_name<T>::_() << ".");
57 
58     BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
59         (abs(atanh<T>(static_cast<T>(0))))
60         (numeric_limits<T>::epsilon()));
61 
62     BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
63         (abs(atanh<T>(static_cast<T>(3)/5) - log(static_cast<T>(2))))
64         (numeric_limits<T>::epsilon()));
65 
66     BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
67         (abs(atanh<T>(static_cast<T>(-3)/5) + log(static_cast<T>(2))))
68         (numeric_limits<T>::epsilon()));
69 
70     for    (int i = 0; i <= 100; i++)
71     {
72         T    x = static_cast<T>(i-50)/static_cast<T>(5);
73         T    y = tanh(x);
74 
75         if    (
76                 (abs(y-static_cast<T>(1)) >= numeric_limits<T>::epsilon())&&
77                 (abs(y+static_cast<T>(1)) >= numeric_limits<T>::epsilon())
78             )
79         {
80             BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
81                 (atanh_error_evaluator(x))
82                 (static_cast<T>(4)));
83         }
84     }
85     //
86     // Error handling checks:
87     //
88     BOOST_MATH_CHECK_THROW(atanh(T(-1)), std::overflow_error);
89     BOOST_MATH_CHECK_THROW(atanh(T(1)), std::overflow_error);
90     BOOST_MATH_CHECK_THROW(atanh(T(-2)), std::domain_error);
91     BOOST_MATH_CHECK_THROW(atanh(T(2)), std::domain_error);
92 }
93 
94 
atanh_manual_check()95 void    atanh_manual_check()
96 {
97     using    ::std::abs;
98     using    ::std::tanh;
99 
100     using    ::std::numeric_limits;
101 
102 
103     BOOST_TEST_MESSAGE(" ");
104     BOOST_TEST_MESSAGE("atanh");
105 
106     for    (int i = 0; i <= 100; i++)
107     {
108         float        xf = static_cast<float>(i-50)/static_cast<float>(5);
109         double       xd = static_cast<double>(i-50)/static_cast<double>(5);
110         long double  xl =
111                 static_cast<long double>(i-50)/static_cast<long double>(5);
112 
113         float        yf = tanh(xf);
114         double       yd = tanh(xd);
115         (void) &yd;        // avoid "unused variable" warning
116         long double  yl = tanh(xl);
117         (void) &yl;        // avoid "unused variable" warning
118 
119         if    (
120                 std::numeric_limits<float>::has_infinity &&
121                 std::numeric_limits<double>::has_infinity &&
122                 std::numeric_limits<long double>::has_infinity
123             )
124         {
125 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
126             BOOST_TEST_MESSAGE( ::std::setw(15)
127                         << atanh_error_evaluator(xf)
128                         << ::std::setw(15)
129                         << atanh_error_evaluator(xd)
130                         << ::std::setw(15)
131                         << atanh_error_evaluator(xl));
132 #else
133             BOOST_TEST_MESSAGE( ::std::setw(15)
134                         << atanh_error_evaluator(xf)
135                         << ::std::setw(15)
136                         << atanh_error_evaluator(xd));
137 #endif
138         }
139         else
140         {
141             if    (
142                     (abs(yf-static_cast<float>(1)) <
143                         numeric_limits<float>::epsilon())||
144                     (abs(yf+static_cast<float>(1)) <
145                         numeric_limits<float>::epsilon())||
146                     (abs(yf-static_cast<double>(1)) <
147                         numeric_limits<double>::epsilon())||
148                     (abs(yf+static_cast<double>(1)) <
149                         numeric_limits<double>::epsilon())||
150                     (abs(yf-static_cast<long double>(1)) <
151                         numeric_limits<long double>::epsilon())||
152                     (abs(yf+static_cast<long double>(1)) <
153                         numeric_limits<long double>::epsilon())
154                 )
155             {
156                 BOOST_TEST_MESSAGE("Platform's numerics may lack precision.");
157             }
158             else
159             {
160 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
161                 BOOST_TEST_MESSAGE( ::std::setw(15)
162                             << atanh_error_evaluator(xf)
163                             << ::std::setw(15)
164                             << atanh_error_evaluator(xd)
165                             << ::std::setw(15)
166                             << atanh_error_evaluator(xl));
167 #else
168                 BOOST_TEST_MESSAGE( ::std::setw(15)
169                             << atanh_error_evaluator(xf)
170                             << ::std::setw(15)
171                             << atanh_error_evaluator(xd));
172 #endif
173             }
174         }
175     }
176 
177     BOOST_TEST_MESSAGE(" ");
178 }
179 
180