annotate DEPENDENCIES/generic/include/boost/math/complex/atanh.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // (C) Copyright John Maddock 2005.
Chris@16 2 // Use, modification and distribution are subject to the
Chris@16 3 // Boost Software License, Version 1.0. (See accompanying file
Chris@16 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 5
Chris@16 6 #ifndef BOOST_MATH_COMPLEX_ATANH_INCLUDED
Chris@16 7 #define BOOST_MATH_COMPLEX_ATANH_INCLUDED
Chris@16 8
Chris@16 9 #ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED
Chris@16 10 # include <boost/math/complex/details.hpp>
Chris@16 11 #endif
Chris@16 12 #ifndef BOOST_MATH_LOG1P_INCLUDED
Chris@16 13 # include <boost/math/special_functions/log1p.hpp>
Chris@16 14 #endif
Chris@16 15 #include <boost/assert.hpp>
Chris@16 16
Chris@16 17 #ifdef BOOST_NO_STDC_NAMESPACE
Chris@16 18 namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; }
Chris@16 19 #endif
Chris@16 20
Chris@16 21 namespace boost{ namespace math{
Chris@16 22
Chris@16 23 template<class T>
Chris@16 24 std::complex<T> atanh(const std::complex<T>& z)
Chris@16 25 {
Chris@16 26 //
Chris@16 27 // References:
Chris@16 28 //
Chris@16 29 // Eric W. Weisstein. "Inverse Hyperbolic Tangent."
Chris@16 30 // From MathWorld--A Wolfram Web Resource.
Chris@16 31 // http://mathworld.wolfram.com/InverseHyperbolicTangent.html
Chris@16 32 //
Chris@16 33 // Also: The Wolfram Functions Site,
Chris@16 34 // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/
Chris@16 35 //
Chris@16 36 // Also "Abramowitz and Stegun. Handbook of Mathematical Functions."
Chris@16 37 // at : http://jove.prohosting.com/~skripty/toc.htm
Chris@16 38 //
Chris@16 39 // See also: https://svn.boost.org/trac/boost/ticket/7291
Chris@16 40 //
Chris@16 41
Chris@16 42 static const T pi = boost::math::constants::pi<T>();
Chris@16 43 static const T half_pi = pi / 2;
Chris@16 44 static const T one = static_cast<T>(1.0L);
Chris@16 45 static const T two = static_cast<T>(2.0L);
Chris@16 46 static const T four = static_cast<T>(4.0L);
Chris@16 47 static const T zero = static_cast<T>(0);
Chris@16 48 static const T log_two = boost::math::constants::ln_two<T>();
Chris@16 49
Chris@16 50 #ifdef BOOST_MSVC
Chris@16 51 #pragma warning(push)
Chris@16 52 #pragma warning(disable:4127)
Chris@16 53 #endif
Chris@16 54
Chris@16 55 T x = std::fabs(z.real());
Chris@16 56 T y = std::fabs(z.imag());
Chris@16 57
Chris@16 58 T real, imag; // our results
Chris@16 59
Chris@16 60 T safe_upper = detail::safe_max(two);
Chris@16 61 T safe_lower = detail::safe_min(static_cast<T>(2));
Chris@16 62
Chris@16 63 //
Chris@16 64 // Begin by handling the special cases specified in C99:
Chris@16 65 //
Chris@16 66 if((boost::math::isnan)(x))
Chris@16 67 {
Chris@16 68 if((boost::math::isnan)(y))
Chris@16 69 return std::complex<T>(x, x);
Chris@16 70 else if((boost::math::isinf)(y))
Chris@16 71 return std::complex<T>(0, ((boost::math::signbit)(z.imag()) ? -half_pi : half_pi));
Chris@16 72 else
Chris@16 73 return std::complex<T>(x, x);
Chris@16 74 }
Chris@16 75 else if((boost::math::isnan)(y))
Chris@16 76 {
Chris@16 77 if(x == 0)
Chris@16 78 return std::complex<T>(x, y);
Chris@16 79 if((boost::math::isinf)(x))
Chris@16 80 return std::complex<T>(0, y);
Chris@16 81 else
Chris@16 82 return std::complex<T>(y, y);
Chris@16 83 }
Chris@16 84 else if((x > safe_lower) && (x < safe_upper) && (y > safe_lower) && (y < safe_upper))
Chris@16 85 {
Chris@16 86
Chris@16 87 T yy = y*y;
Chris@16 88 T mxm1 = one - x;
Chris@16 89 ///
Chris@16 90 // The real part is given by:
Chris@16 91 //
Chris@16 92 // real(atanh(z)) == log1p(4*x / ((x-1)*(x-1) + y^2))
Chris@16 93 //
Chris@16 94 real = boost::math::log1p(four * x / (mxm1*mxm1 + yy));
Chris@16 95 real /= four;
Chris@16 96 if((boost::math::signbit)(z.real()))
Chris@16 97 real = (boost::math::changesign)(real);
Chris@16 98
Chris@16 99 imag = std::atan2((y * two), (mxm1*(one+x) - yy));
Chris@16 100 imag /= two;
Chris@16 101 if(z.imag() < 0)
Chris@16 102 imag = (boost::math::changesign)(imag);
Chris@16 103 }
Chris@16 104 else
Chris@16 105 {
Chris@16 106 //
Chris@16 107 // This section handles exception cases that would normally cause
Chris@16 108 // underflow or overflow in the main formulas.
Chris@16 109 //
Chris@16 110 // Begin by working out the real part, we need to approximate
Chris@16 111 // real = boost::math::log1p(4x / ((x-1)^2 + y^2))
Chris@16 112 // without either overflow or underflow in the squared terms.
Chris@16 113 //
Chris@16 114 T mxm1 = one - x;
Chris@16 115 if(x >= safe_upper)
Chris@16 116 {
Chris@16 117 // x-1 = x to machine precision:
Chris@16 118 if((boost::math::isinf)(x) || (boost::math::isinf)(y))
Chris@16 119 {
Chris@16 120 real = 0;
Chris@16 121 }
Chris@16 122 else if(y >= safe_upper)
Chris@16 123 {
Chris@16 124 // Big x and y: divide through by x*y:
Chris@16 125 real = boost::math::log1p((four/y) / (x/y + y/x));
Chris@16 126 }
Chris@16 127 else if(y > one)
Chris@16 128 {
Chris@16 129 // Big x: divide through by x:
Chris@16 130 real = boost::math::log1p(four / (x + y*y/x));
Chris@16 131 }
Chris@16 132 else
Chris@16 133 {
Chris@16 134 // Big x small y, as above but neglect y^2/x:
Chris@16 135 real = boost::math::log1p(four/x);
Chris@16 136 }
Chris@16 137 }
Chris@16 138 else if(y >= safe_upper)
Chris@16 139 {
Chris@16 140 if(x > one)
Chris@16 141 {
Chris@16 142 // Big y, medium x, divide through by y:
Chris@16 143 real = boost::math::log1p((four*x/y) / (y + mxm1*mxm1/y));
Chris@16 144 }
Chris@16 145 else
Chris@16 146 {
Chris@16 147 // Small or medium x, large y:
Chris@16 148 real = four*x/y/y;
Chris@16 149 }
Chris@16 150 }
Chris@16 151 else if (x != one)
Chris@16 152 {
Chris@16 153 // y is small, calculate divisor carefully:
Chris@16 154 T div = mxm1*mxm1;
Chris@16 155 if(y > safe_lower)
Chris@16 156 div += y*y;
Chris@16 157 real = boost::math::log1p(four*x/div);
Chris@16 158 }
Chris@16 159 else
Chris@16 160 real = boost::math::changesign(two * (std::log(y) - log_two));
Chris@16 161
Chris@16 162 real /= four;
Chris@16 163 if((boost::math::signbit)(z.real()))
Chris@16 164 real = (boost::math::changesign)(real);
Chris@16 165
Chris@16 166 //
Chris@16 167 // Now handle imaginary part, this is much easier,
Chris@16 168 // if x or y are large, then the formula:
Chris@16 169 // atan2(2y, (1-x)*(1+x) - y^2)
Chris@16 170 // evaluates to +-(PI - theta) where theta is negligible compared to PI.
Chris@16 171 //
Chris@16 172 if((x >= safe_upper) || (y >= safe_upper))
Chris@16 173 {
Chris@16 174 imag = pi;
Chris@16 175 }
Chris@16 176 else if(x <= safe_lower)
Chris@16 177 {
Chris@16 178 //
Chris@16 179 // If both x and y are small then atan(2y),
Chris@16 180 // otherwise just x^2 is negligible in the divisor:
Chris@16 181 //
Chris@16 182 if(y <= safe_lower)
Chris@16 183 imag = std::atan2(two*y, one);
Chris@16 184 else
Chris@16 185 {
Chris@16 186 if((y == zero) && (x == zero))
Chris@16 187 imag = 0;
Chris@16 188 else
Chris@16 189 imag = std::atan2(two*y, one - y*y);
Chris@16 190 }
Chris@16 191 }
Chris@16 192 else
Chris@16 193 {
Chris@16 194 //
Chris@16 195 // y^2 is negligible:
Chris@16 196 //
Chris@16 197 if((y == zero) && (x == one))
Chris@16 198 imag = 0;
Chris@16 199 else
Chris@16 200 imag = std::atan2(two*y, mxm1*(one+x));
Chris@16 201 }
Chris@16 202 imag /= two;
Chris@16 203 if((boost::math::signbit)(z.imag()))
Chris@16 204 imag = (boost::math::changesign)(imag);
Chris@16 205 }
Chris@16 206 return std::complex<T>(real, imag);
Chris@16 207 #ifdef BOOST_MSVC
Chris@16 208 #pragma warning(pop)
Chris@16 209 #endif
Chris@16 210 }
Chris@16 211
Chris@16 212 } } // namespaces
Chris@16 213
Chris@16 214 #endif // BOOST_MATH_COMPLEX_ATANH_INCLUDED