1 2 /* @(#)s_lrint.c 5.1 93/09/24 */ 3 /* 4 * ==================================================== 5 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 6 * 7 * Developed at SunPro, a Sun Microsystems, Inc. business. 8 * Permission to use, copy, modify, and distribute this 9 * software is freely granted, provided that this notice 10 * is preserved. 11 * ==================================================== 12 */ 13 14 /* 15 * lrint(x) 16 * Return x rounded to integral value according to the prevailing 17 * rounding mode. 18 * Method: 19 * Using floating addition. 20 * Exception: 21 * Inexact flag raised if x not equal to lrint(x). 22 */ 23 24 #include "fdlibm.h" 25 26 #ifndef _DOUBLE_IS_32BITS 27 28 #ifdef __STDC__ 29 static const double 30 #else 31 static double 32 #endif 33 34 /* Adding a double, x, to 2^52 will cause the result to be rounded based on 35 the fractional part of x, according to the implementation's current rounding 36 mode. 2^52 is the smallest double that can be represented using all 52 significant 37 digits. */ 38 TWO52[2]={ 39 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ 40 -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ 41 }; 42 43 #ifdef __STDC__ lrint(double x)44 long int lrint(double x) 45 #else 46 long int lrint(x) 47 double x; 48 #endif 49 { 50 __int32_t i0,j0,sx; 51 __uint32_t i1; 52 double t; 53 volatile double w; 54 long int result; 55 56 EXTRACT_WORDS(i0,i1,x); 57 sx = (i0>>31)&1; 58 j0 = ((i0 & 0x7ff00000) >> 20) - 1023; 59 60 if(j0 < 20) 61 { 62 if(j0 < -1) 63 return 0; 64 else 65 { 66 w = TWO52[sx] + x; 67 t = w - TWO52[sx]; 68 GET_HIGH_WORD(i0, t); 69 j0 = ((i0 & 0x7ff00000) >> 20) - 1023; 70 i0 &= 0x000fffff; 71 i0 |= 0x00100000; 72 result = i0 >> (20 - j0); 73 } 74 } 75 else if (j0 < (8 * sizeof (long int)) - 1) 76 { 77 if (j0 >= 52) 78 result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52)); 79 else 80 { 81 w = TWO52[sx] + x; 82 t = w - TWO52[sx]; 83 EXTRACT_WORDS (i0, i1, t); 84 j0 = ((i0 & 0x7ff00000) >> 20) - 1023; 85 i0 &= 0x000fffff; 86 i0 |= 0x00100000; 87 result = ((long int) i0 << (j0 - 20)) | (i1 >> (52 - j0)); 88 } 89 } 90 else 91 { 92 return (long int) x; 93 } 94 95 return sx ? -result : result; 96 } 97 98 #endif /* _DOUBLE_IS_32BITS */ 99