newlib-cygwin/newlib/libm/common/s_lround.c

130 lines
3.6 KiB
C
Raw Normal View History

2002-06-08 05:59:57 +08:00
/*
* ====================================================
* 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.
* ====================================================
*/
2009-03-25 Craig Howland <howland@LGSInnovations.com> * libc/include/math.h: (llround, llroundf): Declare. * libm/common/s_llround.c: New file, implementing llround(). * libm/common/sf_llround.c: New file, implementing llroundf(). * libm/common/sf_lround.c: Remove spurious cast in _DOUBLE_IS_32BITS version of function. * libm/common/sf_lrint.c: Ditto. * libm/common/sf_logb.c: Corrected return for subnormal argument by replacing existing function with a version created from sf_ilogb.c. * libm/common/s_logb.c: Ditto, except starting point s_ilogb.c. Also added documentation for logb() and logbf(). * libm/common/s_signbit.c: Add signbit() documentation. * libm/common/s_log2.c: Update return values to match what w_log2.c has, since log2 uses log(); add note about being derived instead of direct. * libm/common/sf_fma.c: Add casts to attempt to get correct results, as well as comments pointing out problems with the implementation. * libm/common/s_fma.c: Add fma() and fmaf() documentation. * libm/common/sf_remquo.c: Incorrect quotient returns for large values corrected by discarding existing function and replacing with Sun verion, with some enhancements. * libm/common/s_remquo.c: Ditto. Add remquo() and remquof() documentation. * libm/common/s_fmax.c: Add fmax() and fmaxf() documentation. * libm/common/s_fmin.c: Add fmin() and fminf() documentation. * libm/common/s_fdim.c: Return NAN for NAN arg, add fdim() and fdimf() documentation. * libm/common/sf_fdim.c: Return NAN for NAN arg, HUGE_VALF for inf arg. * libm/common/s_trunc.c: Add trunc() and truncf() documentation. * libm/common/s_rint.c: Add rint() and rintf() documentation. * libm/common/s_round.c: Add round() and roundf() documentation. * libm/common/s_scalbn.c: Add scalbln() and scalblnf() documentation. * libm/common/s_infinity.c: Add infinity() and infinityf() documentation. * libm/common/s_lround.c: Add lround(), lroundf(), llround(), and llroundf() documentation. * libm/common/s_lrint.c: Add lrint(), lrintf(), llrint(), and llrintf() documentation. * libm/common/isgreater.c: New file for documenting math.h function-like macros isgreater(), isgreaterequal(), isless(), islessequal(), islessgreater(), and isunordered(). * libm/common/s_isnan.c: Add documentation for function-like macros fpclassify(), isfinite(), isinf(), isnan(), and isnormal(). * libm/common/s_nearbyint.c: Add nearbyint() and nearbyintf() documentation. * libm/common/Makefile.am: Add s_llround.c (src); sf_llround.c (fsrc); s_fdim.def, s_fma.def, s_fmax.def, s_fmin.def, s_logb.def, s_lrint.def, s_lround.def, s_nearbyint.def, s_remquo.def, s_rint.def, s_round.def, s_signbit.def, s_trunc.def, and isgreater.def (chobj); re-name all existing chew files (chobj) to match source file base names (put in underscores), delete all special targets for chew files (leaving all to be generated by rule). * libm/common/Makefile.in: regenerate. * libm/math/w_exp2.c: Add "base 2" to documentation description (and delete TRAD_SYNOPSIS). * libm/math/w_gamma.c: Add tgamma() and tgammaf() documentation, along with some history behind the function names. * libm/math/math.tex: Add includes for newly-added documentation (see .def additions to common/Makefile.am and math/Makefile.am in this ChangeLog list), adjusted existing .def file names to match source file base names (added underscores); add mention of HUGE_VALF; rename "Version of library" section to "Error Handling" and add some text about floating-point exception; added section "Standards Compliance And Portability". * libm/math/Makefile.am: Add w_exp2.def (chobj); re-name all existing chew files (chobj) to match source file base names, delete all special targets for chew files (leaving all to be generated by rule). * libm/math/Makefile.in: regenerated * doc/makedoc.c: Change silent ignoring of commands < 5 characters to a failure when reading macro file for commands < 4 characters; add -v (verbose) option for printing some debugging information; get rid of spurious translation of "@*" to "*" (no source files used @*, so no existing doc pages were affected); clean up some compiler warnings. * doc/doc.str: add BUGS and SEEALSO sections (to match texi2pod.pl which has them); Remove ITEM command (redundant with makedoc built-in "o", not used in any present source file so nothing is lost, anyway). * HOWTO: New file to hold information for maintainers regarding how to do things. Initial sections on documentation and ELIX levels.
2009-03-26 03:13:24 +08:00
/*
FUNCTION
<<lround>>, <<lroundf>>, <<llround>>, <<llroundf>>--round to integer, to nearest
INDEX
lround
INDEX
lroundf
INDEX
llround
INDEX
llroundf
ANSI_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
*/
2002-06-08 05:59:57 +08:00
#include "fdlibm.h"
#ifndef _DOUBLE_IS_32BITS
#ifdef __STDC__
long int lround(double x)
#else
long int lround(x)
double x;
#endif
{
__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] */
2002-06-08 05:59:57 +08:00
if (exponent_less_1023 < 20)
{
/* exponent_less_1023 in [-1023,19] */
2002-06-08 05:59:57 +08:00
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] */
2002-06-08 05:59:57 +08:00
msw += 0x80000 >> exponent_less_1023;
/* shift amt in [20,1] */
2002-06-08 05:59:57 +08:00
result = msw >> (20 - exponent_less_1023);
}
}
else if (exponent_less_1023 < (8 * sizeof (long int)) - 1)
{
/* 32bit long: exponent_less_1023 in [20,30] */
/* 64bit long: exponent_less_1023 in [20,62] */
2002-06-08 05:59:57 +08:00
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] */
| (lsw << (exponent_less_1023 - 52));
2002-06-08 05:59:57 +08:00
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));
2002-06-08 05:59:57 +08:00
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));
2002-06-08 05:59:57 +08:00
}
}
else
/* Result is too large to be represented by a long int. */
return (long int)x;
return sign * result;
}
#endif /* _DOUBLE_IS_32BITS */