1 /* Round long double to integer away from zero. 2 Copyright (C) 1997-2018 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and 5 Jakub Jelinek <jj@ultra.linux.cz>, 1999. 6 7 The GNU C Library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Lesser General Public 9 License as published by the Free Software Foundation; either 10 version 2.1 of the License, or (at your option) any later version. 11 12 The GNU C Library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Lesser General Public License for more details. 16 17 You should have received a copy of the GNU Lesser General Public 18 License along with the GNU C Library; if not, see 19 <http://www.gnu.org/licenses/>. */ 20 21 #define NO_MATH_REDIRECT 22 23 #include "quadmath-imp.h" 24 25 __float128 26 roundq (__float128 x) 27 { 28 int32_t j0; 29 uint64_t i1, i0; 30 31 GET_FLT128_WORDS64 (i0, i1, x); 32 j0 = ((i0 >> 48) & 0x7fff) - 0x3fff; 33 if (j0 < 48) 34 { 35 if (j0 < 0) 36 { 37 i0 &= 0x8000000000000000ULL; 38 if (j0 == -1) 39 i0 |= 0x3fff000000000000LL; 40 i1 = 0; 41 } 42 else 43 { 44 uint64_t i = 0x0000ffffffffffffLL >> j0; 45 if (((i0 & i) | i1) == 0) 46 /* X is integral. */ 47 return x; 48 49 i0 += 0x0000800000000000LL >> j0; 50 i0 &= ~i; 51 i1 = 0; 52 } 53 } 54 else if (j0 > 111) 55 { 56 if (j0 == 0x4000) 57 /* Inf or NaN. */ 58 return x + x; 59 else 60 return x; 61 } 62 else 63 { 64 uint64_t i = -1ULL >> (j0 - 48); 65 if ((i1 & i) == 0) 66 /* X is integral. */ 67 return x; 68 69 uint64_t j = i1 + (1LL << (111 - j0)); 70 if (j < i1) 71 i0 += 1; 72 i1 = j; 73 i1 &= ~i; 74 } 75 76 SET_FLT128_WORDS64 (x, i0, i1); 77 return x; 78 } 79