/* lround adapted to be llround for Newlib, 2009 by Craig Howland. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #include <limits.h> #ifdef _NEED_FLOAT64 long long int llround64(__float64 x) { __int32_t sign, exponent_less_1023; /* Most significant word, least significant word. */ __uint32_t msw, lsw; long long int result; EXTRACT_WORDS(msw, lsw, x); /* Extract sign. */ sign = ((msw & 0x80000000) ? -1 : 1); /* Extract exponent field. */ exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023; msw &= 0x000fffff; msw |= 0x00100000; /* exponent_less_1023 in [-1023,1024] */ if (exponent_less_1023 < 20) { /* exponent_less_1023 in [-1023,19] */ if (exponent_less_1023 < 0) { if (exponent_less_1023 < -1) return 0; else return sign; } else { /* exponent_less_1023 in [0,19] */ /* shift amt in [0,19] */ msw += 0x80000 >> exponent_less_1023; /* shift amt in [20,1] */ result = msw >> (20 - exponent_less_1023); } } else if (exponent_less_1023 < (__int32_t) ((8 * sizeof (long long int)) - 1)) { /* 64bit longlong: exponent_less_1023 in [20,62] */ if (exponent_less_1023 >= 52) /* 64bit longlong: exponent_less_1023 in [52,62] */ /* 64bit longlong: shift amt in [32,42] */ result = ((long long int) msw << (exponent_less_1023 - 20)) /* 64bit longlong: shift amt in [0,10] */ | ((long long int) lsw << (exponent_less_1023 - 52)); else { /* 64bit longlong: exponent_less_1023 in [20,51] */ unsigned int tmp = lsw /* 64bit longlong: shift amt in [0,31] */ + (0x80000000 >> (exponent_less_1023 - 20)); if (tmp < lsw) ++msw; /* 64bit longlong: shift amt in [0,31] */ result = ((long long int) msw << (exponent_less_1023 - 20)) /* ***64bit longlong: shift amt in [32,1] */ | SAFE_RIGHT_SHIFT (tmp, (52 - exponent_less_1023)); } } else { /* Result is too large to be represented by a long long int. */ if (sign == 1 || !((sizeof(long long) == 4 && x > LLONG_MIN - 0.5) || (sizeof(long long) > 4 && x >= LLONG_MIN))) { __math_set_invalid(); return sign == 1 ? LLONG_MAX : LLONG_MIN; } return (long long)x; } return sign * result; } _MATH_ALIAS_k_d(llround) #endif /* _NEED_FLOAT64 */