1 //===-- Implementation of hypotf function ---------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_HYPOT_H 10 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_HYPOT_H 11 12 #include "BasicOperations.h" 13 #include "FEnvImpl.h" 14 #include "FPBits.h" 15 #include "builtin_wrappers.h" 16 #include "src/__support/CPP/Bit.h" 17 #include "src/__support/CPP/TypeTraits.h" 18 #include "src/__support/CPP/UInt128.h" 19 20 namespace __llvm_libc { 21 namespace fputil { 22 23 namespace internal { 24 25 template <typename T> 26 static inline T find_leading_one(T mant, int &shift_length) { 27 shift_length = 0; 28 if (mant > 0) { 29 shift_length = (sizeof(mant) * 8) - 1 - unsafe_clz(mant); 30 } 31 return T(1) << shift_length; 32 } 33 34 } // namespace internal 35 36 template <typename T> struct DoubleLength; 37 38 template <> struct DoubleLength<uint16_t> { using Type = uint32_t; }; 39 40 template <> struct DoubleLength<uint32_t> { using Type = uint64_t; }; 41 42 template <> struct DoubleLength<uint64_t> { 43 using Type = UInt128; 44 }; 45 46 // Correctly rounded IEEE 754 HYPOT(x, y) with round to nearest, ties to even. 47 // 48 // Algorithm: 49 // - Let a = max(|x|, |y|), b = min(|x|, |y|), then we have that: 50 // a <= sqrt(a^2 + b^2) <= min(a + b, a*sqrt(2)) 51 // 1. So if b < eps(a)/2, then HYPOT(x, y) = a. 52 // 53 // - Moreover, the exponent part of HYPOT(x, y) is either the same or 1 more 54 // than the exponent part of a. 55 // 56 // 2. For the remaining cases, we will use the digit-by-digit (shift-and-add) 57 // algorithm to compute SQRT(Z): 58 // 59 // - For Y = y0.y1...yn... = SQRT(Z), 60 // let Y(n) = y0.y1...yn be the first n fractional digits of Y. 61 // 62 // - The nth scaled residual R(n) is defined to be: 63 // R(n) = 2^n * (Z - Y(n)^2) 64 // 65 // - Since Y(n) = Y(n - 1) + yn * 2^(-n), the scaled residual 66 // satisfies the following recurrence formula: 67 // R(n) = 2*R(n - 1) - yn*(2*Y(n - 1) + 2^(-n)), 68 // with the initial conditions: 69 // Y(0) = y0, and R(0) = Z - y0. 70 // 71 // - So the nth fractional digit of Y = SQRT(Z) can be decided by: 72 // yn = 1 if 2*R(n - 1) >= 2*Y(n - 1) + 2^(-n), 73 // 0 otherwise. 74 // 75 // 3. Precision analysis: 76 // 77 // - Notice that in the decision function: 78 // 2*R(n - 1) >= 2*Y(n - 1) + 2^(-n), 79 // the right hand side only uses up to the 2^(-n)-bit, and both sides are 80 // non-negative, so R(n - 1) can be truncated at the 2^(-(n + 1))-bit, so 81 // that 2*R(n - 1) is corrected up to the 2^(-n)-bit. 82 // 83 // - Thus, in order to round SQRT(a^2 + b^2) correctly up to n-fractional 84 // bits, we need to perform the summation (a^2 + b^2) correctly up to (2n + 85 // 2)-fractional bits, and the remaining bits are sticky bits (i.e. we only 86 // care if they are 0 or > 0), and the comparisons, additions/subtractions 87 // can be done in n-fractional bits precision. 88 // 89 // - For single precision (float), we can use uint64_t to store the sum a^2 + 90 // b^2 exact up to (2n + 2)-fractional bits. 91 // 92 // - Then we can feed this sum into the digit-by-digit algorithm for SQRT(Z) 93 // described above. 94 // 95 // 96 // Special cases: 97 // - HYPOT(x, y) is +Inf if x or y is +Inf or -Inf; else 98 // - HYPOT(x, y) is NaN if x or y is NaN. 99 // 100 template <typename T, 101 cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> 102 static inline T hypot(T x, T y) { 103 using FPBits_t = FPBits<T>; 104 using UIntType = typename FPBits<T>::UIntType; 105 using DUIntType = typename DoubleLength<UIntType>::Type; 106 107 FPBits_t x_bits(x), y_bits(y); 108 109 if (x_bits.is_inf() || y_bits.is_inf()) { 110 return T(FPBits_t::inf()); 111 } 112 if (x_bits.is_nan()) { 113 return x; 114 } 115 if (y_bits.is_nan()) { 116 return y; 117 } 118 119 uint16_t x_exp = x_bits.get_unbiased_exponent(); 120 uint16_t y_exp = y_bits.get_unbiased_exponent(); 121 uint16_t exp_diff = (x_exp > y_exp) ? (x_exp - y_exp) : (y_exp - x_exp); 122 123 if ((exp_diff >= MantissaWidth<T>::VALUE + 2) || (x == 0) || (y == 0)) { 124 return abs(x) + abs(y); 125 } 126 127 uint16_t a_exp, b_exp, out_exp; 128 UIntType a_mant, b_mant; 129 DUIntType a_mant_sq, b_mant_sq; 130 bool sticky_bits; 131 132 if (abs(x) >= abs(y)) { 133 a_exp = x_exp; 134 a_mant = x_bits.get_mantissa(); 135 b_exp = y_exp; 136 b_mant = y_bits.get_mantissa(); 137 } else { 138 a_exp = y_exp; 139 a_mant = y_bits.get_mantissa(); 140 b_exp = x_exp; 141 b_mant = x_bits.get_mantissa(); 142 } 143 144 out_exp = a_exp; 145 146 // Add an extra bit to simplify the final rounding bit computation. 147 constexpr UIntType ONE = UIntType(1) << (MantissaWidth<T>::VALUE + 1); 148 149 a_mant <<= 1; 150 b_mant <<= 1; 151 152 UIntType leading_one; 153 int y_mant_width; 154 if (a_exp != 0) { 155 leading_one = ONE; 156 a_mant |= ONE; 157 y_mant_width = MantissaWidth<T>::VALUE + 1; 158 } else { 159 leading_one = internal::find_leading_one(a_mant, y_mant_width); 160 a_exp = 1; 161 } 162 163 if (b_exp != 0) { 164 b_mant |= ONE; 165 } else { 166 b_exp = 1; 167 } 168 169 a_mant_sq = static_cast<DUIntType>(a_mant) * a_mant; 170 b_mant_sq = static_cast<DUIntType>(b_mant) * b_mant; 171 172 // At this point, a_exp >= b_exp > a_exp - 25, so in order to line up aSqMant 173 // and bSqMant, we need to shift bSqMant to the right by (a_exp - b_exp) bits. 174 // But before that, remember to store the losing bits to sticky. 175 // The shift length is for a^2 and b^2, so it's double of the exponent 176 // difference between a and b. 177 uint16_t shift_length = 2 * (a_exp - b_exp); 178 sticky_bits = 179 ((b_mant_sq & ((DUIntType(1) << shift_length) - DUIntType(1))) != 180 DUIntType(0)); 181 b_mant_sq >>= shift_length; 182 183 DUIntType sum = a_mant_sq + b_mant_sq; 184 if (sum >= (DUIntType(1) << (2 * y_mant_width + 2))) { 185 // a^2 + b^2 >= 4* leading_one^2, so we will need an extra bit to the left. 186 if (leading_one == ONE) { 187 // For normal result, we discard the last 2 bits of the sum and increase 188 // the exponent. 189 sticky_bits = sticky_bits || ((sum & 0x3U) != 0); 190 sum >>= 2; 191 ++out_exp; 192 if (out_exp >= FPBits_t::MAX_EXPONENT) { 193 return T(FPBits_t::inf()); 194 } 195 } else { 196 // For denormal result, we simply move the leading bit of the result to 197 // the left by 1. 198 leading_one <<= 1; 199 ++y_mant_width; 200 } 201 } 202 203 UIntType y_new = leading_one; 204 UIntType r = static_cast<UIntType>(sum >> y_mant_width) - leading_one; 205 UIntType tail_bits = static_cast<UIntType>(sum) & (leading_one - 1); 206 207 for (UIntType current_bit = leading_one >> 1; current_bit; 208 current_bit >>= 1) { 209 r = (r << 1) + ((tail_bits & current_bit) ? 1 : 0); 210 UIntType tmp = (y_new << 1) + current_bit; // 2*y_new(n - 1) + 2^(-n) 211 if (r >= tmp) { 212 r -= tmp; 213 y_new += current_bit; 214 } 215 } 216 217 bool round_bit = y_new & UIntType(1); 218 bool lsb = y_new & UIntType(2); 219 220 if (y_new >= ONE) { 221 y_new -= ONE; 222 223 if (out_exp == 0) { 224 out_exp = 1; 225 } 226 } 227 228 y_new >>= 1; 229 230 // Round to the nearest, tie to even. 231 switch (get_round()) { 232 case FE_TONEAREST: 233 // Round to nearest, ties to even 234 if (round_bit && (lsb || sticky_bits || (r != 0))) 235 ++y_new; 236 break; 237 case FE_UPWARD: 238 if (round_bit || sticky_bits || (r != 0)) 239 ++y_new; 240 break; 241 } 242 243 if (y_new >= (ONE >> 1)) { 244 y_new -= ONE >> 1; 245 ++out_exp; 246 if (out_exp >= FPBits_t::MAX_EXPONENT) { 247 return T(FPBits_t::inf()); 248 } 249 } 250 251 y_new |= static_cast<UIntType>(out_exp) << MantissaWidth<T>::VALUE; 252 return __llvm_libc::bit_cast<T>(y_new); 253 } 254 255 } // namespace fputil 256 } // namespace __llvm_libc 257 258 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_HYPOT_H 259