williamr@2: // (C) Copyright John Maddock 2005. williamr@2: // Use, modification and distribution are subject to the williamr@2: // Boost Software License, Version 1.0. (See accompanying file williamr@2: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) williamr@2: williamr@2: #ifndef BOOST_MATH_HYPOT_INCLUDED williamr@2: #define BOOST_MATH_HYPOT_INCLUDED williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include // swap williamr@2: williamr@2: #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS williamr@2: # include williamr@2: #else williamr@2: # include williamr@2: #endif williamr@2: williamr@2: #ifdef BOOST_NO_STDC_NAMESPACE williamr@2: namespace std{ using ::sqrt; using ::fabs; } williamr@2: #endif williamr@2: williamr@2: williamr@2: namespace boost{ namespace math{ williamr@2: williamr@2: template williamr@2: T hypot(T x, T y) williamr@2: { williamr@2: #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS williamr@2: BOOST_STATIC_ASSERT(::std::numeric_limits::is_specialized); williamr@2: #else williamr@2: BOOST_ASSERT(std::numeric_limits::is_specialized); williamr@2: #endif williamr@2: williamr@2: // williamr@2: // normalize x and y, so that both are positive and x >= y: williamr@2: // williamr@2: x = (std::fabs)(x); williamr@2: y = (std::fabs)(y); williamr@2: williamr@2: // special case, see C99 Annex F: williamr@2: if(std::numeric_limits::has_infinity williamr@2: && ((x == std::numeric_limits::infinity()) williamr@2: || (y == std::numeric_limits::infinity()))) williamr@2: return std::numeric_limits::infinity(); williamr@2: williamr@2: if(y > x) williamr@2: (std::swap)(x, y); williamr@2: // williamr@2: // figure out overflow and underflow limits: williamr@2: // williamr@2: T safe_upper = (std::sqrt)((std::numeric_limits::max)()) / 2; williamr@2: T safe_lower = (std::sqrt)((std::numeric_limits::min)()); williamr@2: static const T one = 1; williamr@2: // williamr@2: // Now handle special cases: williamr@2: // williamr@2: if(x >= safe_upper) williamr@2: { williamr@2: if(y <= one) williamr@2: { williamr@2: // y is neligible: williamr@2: return x; williamr@2: } williamr@2: return (std::sqrt)(x) * (std::sqrt)(y) * (std::sqrt)(x/y + y/x); williamr@2: } williamr@2: else if(y <= safe_lower) williamr@2: { williamr@2: if((x >= one) || (y == 0)) williamr@2: { williamr@2: // y is negligible: williamr@2: return x; williamr@2: } williamr@2: return (std::sqrt)(x) * (std::sqrt)(y) * (std::sqrt)(x/y + y/x); williamr@2: } williamr@2: // williamr@2: // If we get here then x^2+y^2 will not overflow or underflow: williamr@2: // williamr@2: return (std::sqrt)(x*x + y*y); williamr@2: } williamr@2: williamr@2: } } // namespaces williamr@2: williamr@2: #endif // BOOST_MATH_HYPOT_INCLUDED