1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
/*
* ====================================================
* 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.
* ====================================================
*/
/*
FUNCTION
<<lround>>, <<lroundf>>, <<llround>>, <<llroundf>>---round to integer, to nearest
INDEX
lround
INDEX
lroundf
INDEX
llround
INDEX
llroundf
SYNOPSIS
#include <math.h>
long int lround(double <[x]>);
long int lroundf(float <[x]>);
long long int llround(double <[x]>);
long long int llroundf(float <[x]>);
DESCRIPTION
The <<lround>> and <<llround>> functions round their argument to the
nearest integer value, rounding halfway cases away from zero, regardless
of the current rounding direction. If the rounded value is outside the
range of the return type, the numeric result is unspecified (depending
upon the floating-point implementation, not the library). A range
error may occur if the magnitude of x is too large.
RETURNS
<[x]> rounded to an integral value as an integer.
SEEALSO
See the <<round>> functions for the return being the same floating-point type
as the argument. <<lrint>>, <<llrint>>.
PORTABILITY
ANSI C, POSIX
*/
#include "fdlibm.h"
#include <limits.h>
#ifdef _NEED_FLOAT64
long int
lround64(__float64 x)
{
__int32_t sign, exponent_less_1023;
/* Most significant word, least significant word. */
__uint32_t msw, lsw;
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 int)) - 1))
{
/* 32bit long: exponent_less_1023 in [20,30] */
/* 64bit long: exponent_less_1023 in [20,62] */
if (exponent_less_1023 >= 52)
/* 64bit long: exponent_less_1023 in [52,62] */
/* 64bit long: shift amt in [32,42] */
result = ((long int) msw << (exponent_less_1023 - 20))
/* 64bit long: shift amt in [0,10] */
| ((long int) lsw << (exponent_less_1023 - 52));
else
{
/* 32bit long: exponent_less_1023 in [20,30] */
/* 64bit long: exponent_less_1023 in [20,51] */
unsigned int tmp = lsw
/* 32bit long: shift amt in [0,10] */
/* 64bit long: shift amt in [0,31] */
+ (0x80000000 >> (exponent_less_1023 - 20));
if (tmp < lsw)
++msw;
/* 32bit long: shift amt in [0,10] */
/* 64bit long: shift amt in [0,31] */
result = ((long int) msw << (exponent_less_1023 - 20))
/* ***32bit long: shift amt in [32,22] */
/* ***64bit long: shift amt in [32,1] */
| SAFE_RIGHT_SHIFT (tmp, (52 - exponent_less_1023));
}
}
else
{
/* Result is too large to be represented by a long int. */
if (sign == 1 ||
!((sizeof(long) == 4 && x > LONG_MIN - 0.5) ||
(sizeof(long) > 4 && x >= LONG_MIN)))
{
__math_set_invalid();
return sign == 1 ? LONG_MAX : LONG_MIN;
}
return (long int)x;
}
if (sizeof (long) == 4 && sign == 1 && result == LONG_MIN)
__math_set_invalid();
return sign * result;
}
_MATH_ALIAS_j_d(lround)
#endif /* _NEED_FLOAT64 */
|