1 //===-- Fast rounding to nearest integer for floating point -----*- C++ -*-===// 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_NEAREST_INTEGER_H 10 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_NEAREST_INTEGER_H 11 12 #include "src/__support/architectures.h" 13 #include "src/__support/common.h" 14 15 #if (defined(LLVM_LIBC_ARCH_X86_64) && defined(__SSE4_2__)) 16 #include "x86_64/nearest_integer.h" 17 #elif defined(LLVM_LIBC_ARCH_AARCH64) 18 #include "aarch64/nearest_integer.h" 19 #else 20 21 namespace __llvm_libc { 22 namespace fputil { 23 24 // This is a fast implementation for rounding to a nearest integer that, in case 25 // of a tie, might pick a random one among 2 closest integers when the rounding 26 // mode is not FE_TONEAREST. 27 // 28 // Notice that for AARCH64 and x86-64 with SSE4.2 support, we will use their 29 // corresponding rounding instruction instead. And in those cases, the results 30 // are rounded to the nearest integer, tie-to-even. 31 static inline double nearest_integer(double x) { 32 if (x < 0x1p53 && x > -0x1p53) { 33 double r = x < 0 ? (x - 0x1.0p52) + 0x1.0p52 : (x + 0x1.0p52) - 0x1.0p52; 34 double diff = x - r; 35 // The expression above is correct for the default rounding mode, round-to- 36 // nearest, tie-to-even. For other rounding modes, it might be off by 1, 37 // which is corrected below. 38 if (unlikely(diff > 0.5)) 39 return r + 1.0; 40 if (unlikely(diff < -0.5)) 41 return r - 1.0; 42 return r; 43 } 44 return x; 45 } 46 47 } // namespace fputil 48 } // namespace __llvm_libc 49 50 #endif 51 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_NEAREST_INTEGER_H 52