mirror of
https://github.com/fluencelabs/musl
synced 2025-07-01 15:42:05 +00:00
math: rewrite rounding functions (ceil, floor, trunc, round, rint)
* faster, smaller, cleaner implementation than the bit hacks of fdlibm * use arithmetics like y=(double)(x+0x1p52)-0x1p52, which is an integer neighbor of x in all rounding modes (0<=x<0x1p52) and only use bithacks when that's faster and smaller (for float it usually is) * the code assumes standard excess precision handling for casts * long double code supports both ld80 and ld128 * nearbyint is not changed (it is a wrapper around rint)
This commit is contained in:
@ -1,82 +1,24 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_ceil.c */
|
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
* 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.
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* ceil(x)
|
|
||||||
* Return x rounded toward -inf to integral value
|
|
||||||
* Method:
|
|
||||||
* Bit twiddling.
|
|
||||||
* Exception:
|
|
||||||
* Inexact flag raised if x not equal to ceil(x).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
static const double huge = 1.0e300;
|
|
||||||
|
|
||||||
double ceil(double x)
|
double ceil(double x)
|
||||||
{
|
{
|
||||||
int32_t i0,i1,j0;
|
union {double f; uint64_t i;} u = {x};
|
||||||
uint32_t i,j;
|
int e = u.i >> 52 & 0x7ff;
|
||||||
|
double_t y;
|
||||||
|
|
||||||
EXTRACT_WORDS(i0, i1, x);
|
if (e >= 0x3ff+52 || x == 0)
|
||||||
// FIXME signed shift
|
|
||||||
j0 = ((i0>>20)&0x7ff) - 0x3ff;
|
|
||||||
if (j0 < 20) {
|
|
||||||
if (j0 < 0) {
|
|
||||||
/* raise inexact if x != 0 */
|
|
||||||
if (huge+x > 0.0) {
|
|
||||||
if (i0 < 0) {
|
|
||||||
i0 = 0x80000000;
|
|
||||||
i1=0;
|
|
||||||
} else if ((i0|i1) != 0) {
|
|
||||||
i0=0x3ff00000;
|
|
||||||
i1=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
i = 0x000fffff>>j0;
|
|
||||||
if (((i0&i)|i1) == 0) /* x is integral */
|
|
||||||
return x;
|
return x;
|
||||||
/* raise inexact flag */
|
/* y = int(x) - x, where int(x) is an integer neighbor of x */
|
||||||
if (huge+x > 0.0) {
|
if (u.i >> 63)
|
||||||
if (i0 > 0)
|
y = (double)(x - 0x1p52) + 0x1p52 - x;
|
||||||
i0 += 0x00100000>>j0;
|
else
|
||||||
i0 &= ~i;
|
y = (double)(x + 0x1p52) - 0x1p52 - x;
|
||||||
i1 = 0;
|
/* special case because of non-nearest rounding modes */
|
||||||
|
if (e <= 0x3ff-1) {
|
||||||
|
FORCE_EVAL(y);
|
||||||
|
return u.i >> 63 ? -0.0 : 1;
|
||||||
}
|
}
|
||||||
}
|
if (y < 0)
|
||||||
} else if (j0 > 51) {
|
return x + y + 1;
|
||||||
if (j0 == 0x400) /* inf or NaN */
|
return x + y;
|
||||||
return x+x;
|
|
||||||
return x; /* x is integral */
|
|
||||||
} else {
|
|
||||||
i = (uint32_t)0xffffffff>>(j0-20);
|
|
||||||
if ((i1&i) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
/* raise inexact flag */
|
|
||||||
if (huge+x > 0.0) {
|
|
||||||
if (i0 > 0) {
|
|
||||||
if (j0 == 20)
|
|
||||||
i0 += 1;
|
|
||||||
else {
|
|
||||||
j = i1 + (1<<(52-j0));
|
|
||||||
if (j < i1) /* got a carry */
|
|
||||||
i0 += 1;
|
|
||||||
i1 = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i1 &= ~i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
INSERT_WORDS(x, i0, i1);
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
@ -1,54 +1,27 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_ceilf.c */
|
|
||||||
/*
|
|
||||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
* 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 "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
static const float huge = 1.0e30;
|
|
||||||
|
|
||||||
float ceilf(float x)
|
float ceilf(float x)
|
||||||
{
|
{
|
||||||
int32_t i0,j0;
|
union {float f; uint32_t i;} u = {x};
|
||||||
uint32_t i;
|
int e = (int)(u.i >> 23 & 0xff) - 0x7f;
|
||||||
|
uint32_t m;
|
||||||
|
|
||||||
GET_FLOAT_WORD(i0, x);
|
if (e >= 23)
|
||||||
j0 = ((i0>>23)&0xff) - 0x7f;
|
|
||||||
if (j0 < 23) {
|
|
||||||
if (j0 < 0) {
|
|
||||||
/* raise inexact if x != 0 */
|
|
||||||
if (huge+x > 0.0f) {
|
|
||||||
if (i0 < 0)
|
|
||||||
i0 = 0x80000000;
|
|
||||||
else if(i0 != 0)
|
|
||||||
i0 = 0x3f800000;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
i = 0x007fffff>>j0;
|
|
||||||
if ((i0&i) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
/* raise inexact flag */
|
|
||||||
if (huge+x > 0.0f) {
|
|
||||||
if (i0 > 0)
|
|
||||||
i0 += 0x00800000>>j0;
|
|
||||||
i0 &= ~i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (j0 == 0x80) /* inf or NaN */
|
|
||||||
return x+x;
|
|
||||||
return x; /* x is integral */
|
|
||||||
}
|
|
||||||
SET_FLOAT_WORD(x, i0);
|
|
||||||
return x;
|
return x;
|
||||||
|
if (e >= 0) {
|
||||||
|
m = 0x007fffff >> e;
|
||||||
|
if ((u.i & m) == 0)
|
||||||
|
return x;
|
||||||
|
FORCE_EVAL(x + 0x1p120f);
|
||||||
|
if (u.i >> 31 == 0)
|
||||||
|
u.i += m;
|
||||||
|
u.i &= ~m;
|
||||||
|
} else {
|
||||||
|
FORCE_EVAL(x + 0x1p120f);
|
||||||
|
if (u.i >> 31)
|
||||||
|
u.f = -0.0;
|
||||||
|
else if (u.i << 1)
|
||||||
|
u.f = 1.0;
|
||||||
|
}
|
||||||
|
return u.f;
|
||||||
}
|
}
|
||||||
|
106
src/math/ceill.c
106
src/math/ceill.c
@ -1,23 +1,3 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_ceill.c */
|
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
* 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.
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* ceill(x)
|
|
||||||
* Return x rounded toward -inf to integral value
|
|
||||||
* Method:
|
|
||||||
* Bit twiddling.
|
|
||||||
* Exception:
|
|
||||||
* Inexact flag raised if x not equal to ceill(x).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||||
@ -26,77 +6,31 @@ long double ceill(long double x)
|
|||||||
return ceil(x);
|
return ceil(x);
|
||||||
}
|
}
|
||||||
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
||||||
|
#if LDBL_MANT_DIG == 64
|
||||||
#ifdef LDBL_IMPLICIT_NBIT
|
#define TOINT 0x1p63
|
||||||
#define MANH_SIZE (LDBL_MANH_SIZE + 1)
|
#elif LDBL_MANT_DIG == 113
|
||||||
#define INC_MANH(u, c) do { \
|
#define TOINT 0x1p112
|
||||||
uint64_t o = u.bits.manh; \
|
|
||||||
u.bits.manh += (c); \
|
|
||||||
if (u.bits.manh < o) \
|
|
||||||
u.bits.exp++; \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
#define MANH_SIZE LDBL_MANH_SIZE
|
|
||||||
#define INC_MANH(u, c) do { \
|
|
||||||
uint64_t o = u.bits.manh; \
|
|
||||||
u.bits.manh += (c); \
|
|
||||||
if (u.bits.manh < o) { \
|
|
||||||
u.bits.exp++; \
|
|
||||||
u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const long double huge = 1.0e300;
|
|
||||||
|
|
||||||
long double ceill(long double x)
|
long double ceill(long double x)
|
||||||
{
|
{
|
||||||
union IEEEl2bits u = { .e = x };
|
union ldshape u = {x};
|
||||||
int e = u.bits.exp - LDBL_MAX_EXP + 1;
|
int e = u.i.se & 0x7fff;
|
||||||
|
long double y;
|
||||||
|
|
||||||
if (e < MANH_SIZE - 1) {
|
if (e >= 0x3fff+LDBL_MANT_DIG-1 || x == 0)
|
||||||
if (e < 0) {
|
return x;
|
||||||
/* raise inexact if x != 0 */
|
/* y = int(x) - x, where int(x) is an integer neighbor of x */
|
||||||
if (huge + x > 0.0)
|
if (u.i.se >> 15)
|
||||||
if (u.bits.exp > 0 ||
|
y = x - TOINT + TOINT - x;
|
||||||
(u.bits.manh | u.bits.manl) != 0)
|
|
||||||
u.e = u.bits.sign ? -0.0 : 1.0;
|
|
||||||
} else {
|
|
||||||
uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
|
|
||||||
if (((u.bits.manh & m) | u.bits.manl) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
if (!u.bits.sign) {
|
|
||||||
#ifdef LDBL_IMPLICIT_NBIT
|
|
||||||
if (e == 0)
|
|
||||||
u.bits.exp++;
|
|
||||||
else
|
else
|
||||||
#endif
|
y = x + TOINT - TOINT - x;
|
||||||
INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
|
/* special case because of non-nearest rounding modes */
|
||||||
|
if (e <= 0x3fff-1) {
|
||||||
|
FORCE_EVAL(y);
|
||||||
|
return u.i.se >> 15 ? -0.0 : 1;
|
||||||
}
|
}
|
||||||
/* raise inexact flag */
|
if (y < 0)
|
||||||
if (huge + x > 0.0) {
|
return x + y + 1;
|
||||||
u.bits.manh &= ~m;
|
return x + y;
|
||||||
u.bits.manl = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (e < LDBL_MANT_DIG - 1) {
|
|
||||||
uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
|
|
||||||
if ((u.bits.manl & m) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
if (!u.bits.sign) {
|
|
||||||
if (e == MANH_SIZE - 1)
|
|
||||||
INC_MANH(u, 1);
|
|
||||||
else {
|
|
||||||
uint64_t o = u.bits.manl;
|
|
||||||
u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
|
|
||||||
if (u.bits.manl < o) /* got a carry */
|
|
||||||
INC_MANH(u, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* raise inexact flag */
|
|
||||||
if (huge + x > 0.0)
|
|
||||||
u.bits.manl &= ~m;
|
|
||||||
}
|
|
||||||
return u.e;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,82 +1,24 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_floor.c */
|
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
* 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.
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* floor(x)
|
|
||||||
* Return x rounded toward -inf to integral value
|
|
||||||
* Method:
|
|
||||||
* Bit twiddling.
|
|
||||||
* Exception:
|
|
||||||
* Inexact flag raised if x not equal to floor(x).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
static const double huge = 1.0e300;
|
|
||||||
|
|
||||||
double floor(double x)
|
double floor(double x)
|
||||||
{
|
{
|
||||||
int32_t i0,i1,j0;
|
union {double f; uint64_t i;} u = {x};
|
||||||
uint32_t i,j;
|
int e = u.i >> 52 & 0x7ff;
|
||||||
|
double_t y;
|
||||||
|
|
||||||
EXTRACT_WORDS(i0, i1, x);
|
if (e >= 0x3ff+52 || x == 0)
|
||||||
// FIXME: signed shift
|
|
||||||
j0 = ((i0>>20)&0x7ff) - 0x3ff;
|
|
||||||
if (j0 < 20) {
|
|
||||||
if (j0 < 0) { /* |x| < 1 */
|
|
||||||
/* raise inexact if x != 0 */
|
|
||||||
if (huge+x > 0.0) {
|
|
||||||
if (i0 >= 0) { /* x >= 0 */
|
|
||||||
i0 = i1 = 0;
|
|
||||||
} else if (((i0&0x7fffffff)|i1) != 0) {
|
|
||||||
i0 = 0xbff00000;
|
|
||||||
i1 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
i = 0x000fffff>>j0;
|
|
||||||
if (((i0&i)|i1) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
/* raise inexact flag */
|
|
||||||
if (huge+x > 0.0) {
|
|
||||||
if (i0 < 0)
|
|
||||||
i0 += 0x00100000>>j0;
|
|
||||||
i0 &= ~i;
|
|
||||||
i1 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (j0 > 51) {
|
|
||||||
if (j0 == 0x400)
|
|
||||||
return x+x; /* inf or NaN */
|
|
||||||
else
|
|
||||||
return x; /* x is integral */
|
|
||||||
} else {
|
|
||||||
i = (uint32_t)0xffffffff>>(j0-20);
|
|
||||||
if ((i1&i) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
/* raise inexact flag */
|
|
||||||
if (huge+x > 0.0) {
|
|
||||||
if (i0 < 0) {
|
|
||||||
if (j0 == 20)
|
|
||||||
i0++;
|
|
||||||
else {
|
|
||||||
j = i1+(1<<(52-j0));
|
|
||||||
if (j < i1)
|
|
||||||
i0++; /* got a carry */
|
|
||||||
i1 = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i1 &= ~i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
INSERT_WORDS(x, i0, i1);
|
|
||||||
return x;
|
return x;
|
||||||
|
/* y = int(x) - x, where int(x) is an integer neighbor of x */
|
||||||
|
if (u.i >> 63)
|
||||||
|
y = (double)(x - 0x1p52) + 0x1p52 - x;
|
||||||
|
else
|
||||||
|
y = (double)(x + 0x1p52) - 0x1p52 - x;
|
||||||
|
/* special case because of non-nearest rounding modes */
|
||||||
|
if (e <= 0x3ff-1) {
|
||||||
|
FORCE_EVAL(y);
|
||||||
|
return u.i >> 63 ? -1 : 0;
|
||||||
|
}
|
||||||
|
if (y > 0)
|
||||||
|
return x + y - 1;
|
||||||
|
return x + y;
|
||||||
}
|
}
|
||||||
|
@ -1,64 +1,27 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_floorf.c */
|
|
||||||
/*
|
|
||||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
* 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.
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* floorf(x)
|
|
||||||
* Return x rounded toward -inf to integral value
|
|
||||||
* Method:
|
|
||||||
* Bit twiddling.
|
|
||||||
* Exception:
|
|
||||||
* Inexact flag raised if x not equal to floorf(x).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
static const float huge = 1.0e30;
|
|
||||||
|
|
||||||
float floorf(float x)
|
float floorf(float x)
|
||||||
{
|
{
|
||||||
int32_t i0,j0;
|
union {float f; uint32_t i;} u = {x};
|
||||||
uint32_t i;
|
int e = (int)(u.i >> 23 & 0xff) - 0x7f;
|
||||||
|
uint32_t m;
|
||||||
|
|
||||||
GET_FLOAT_WORD(i0, x);
|
if (e >= 23)
|
||||||
// FIXME: signed shift
|
|
||||||
j0 = ((i0>>23)&0xff) - 0x7f;
|
|
||||||
if (j0 < 23) {
|
|
||||||
if (j0 < 0) { /* |x| < 1 */
|
|
||||||
/* raise inexact if x != 0 */
|
|
||||||
if (huge+x > 0.0f) {
|
|
||||||
if (i0 >= 0) /* x >= 0 */
|
|
||||||
i0 = 0;
|
|
||||||
else if ((i0&0x7fffffff) != 0)
|
|
||||||
i0 = 0xbf800000;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
i = 0x007fffff>>j0;
|
|
||||||
if ((i0&i) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
/* raise inexact flag */
|
|
||||||
if (huge+x > 0.0f) {
|
|
||||||
if (i0 < 0)
|
|
||||||
i0 += 0x00800000>>j0;
|
|
||||||
i0 &= ~i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (j0 == 0x80) /* inf or NaN */
|
|
||||||
return x+x;
|
|
||||||
else
|
|
||||||
return x; /* x is integral */
|
|
||||||
}
|
|
||||||
SET_FLOAT_WORD(x, i0);
|
|
||||||
return x;
|
return x;
|
||||||
|
if (e >= 0) {
|
||||||
|
m = 0x007fffff >> e;
|
||||||
|
if ((u.i & m) == 0)
|
||||||
|
return x;
|
||||||
|
FORCE_EVAL(x + 0x1p120f);
|
||||||
|
if (u.i >> 31)
|
||||||
|
u.i += m;
|
||||||
|
u.i &= ~m;
|
||||||
|
} else {
|
||||||
|
FORCE_EVAL(x + 0x1p120f);
|
||||||
|
if (u.i >> 31 == 0)
|
||||||
|
u.i = 0;
|
||||||
|
else if (u.i << 1)
|
||||||
|
u.f = -1.0;
|
||||||
|
}
|
||||||
|
return u.f;
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,3 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_floorl.c */
|
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
* 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.
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* floorl(x)
|
|
||||||
* Return x rounded toward -inf to integral value
|
|
||||||
* Method:
|
|
||||||
* Bit twiddling.
|
|
||||||
* Exception:
|
|
||||||
* Inexact flag raised if x not equal to floorl(x).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||||
@ -26,77 +6,31 @@ long double floorl(long double x)
|
|||||||
return floor(x);
|
return floor(x);
|
||||||
}
|
}
|
||||||
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
||||||
|
#if LDBL_MANT_DIG == 64
|
||||||
#ifdef LDBL_IMPLICIT_NBIT
|
#define TOINT 0x1p63
|
||||||
#define MANH_SIZE (LDBL_MANH_SIZE + 1)
|
#elif LDBL_MANT_DIG == 113
|
||||||
#define INC_MANH(u, c) do { \
|
#define TOINT 0x1p112
|
||||||
uint64_t o = u.bits.manh; \
|
|
||||||
u.bits.manh += (c); \
|
|
||||||
if (u.bits.manh < o) \
|
|
||||||
u.bits.exp++; \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
#define MANH_SIZE LDBL_MANH_SIZE
|
|
||||||
#define INC_MANH(u, c) do { \
|
|
||||||
uint64_t o = u.bits.manh; \
|
|
||||||
u.bits.manh += (c); \
|
|
||||||
if (u.bits.manh < o) { \
|
|
||||||
u.bits.exp++; \
|
|
||||||
u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const long double huge = 1.0e300;
|
|
||||||
|
|
||||||
long double floorl(long double x)
|
long double floorl(long double x)
|
||||||
{
|
{
|
||||||
union IEEEl2bits u = { .e = x };
|
union ldshape u = {x};
|
||||||
int e = u.bits.exp - LDBL_MAX_EXP + 1;
|
int e = u.i.se & 0x7fff;
|
||||||
|
long double y;
|
||||||
|
|
||||||
if (e < MANH_SIZE - 1) {
|
if (e >= 0x3fff+LDBL_MANT_DIG-1 || x == 0)
|
||||||
if (e < 0) {
|
return x;
|
||||||
/* raise inexact if x != 0 */
|
/* y = int(x) - x, where int(x) is an integer neighbor of x */
|
||||||
if (huge + x > 0.0)
|
if (u.i.se >> 15)
|
||||||
if (u.bits.exp > 0 ||
|
y = x - TOINT + TOINT - x;
|
||||||
(u.bits.manh | u.bits.manl) != 0)
|
|
||||||
u.e = u.bits.sign ? -1.0 : 0.0;
|
|
||||||
} else {
|
|
||||||
uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
|
|
||||||
if (((u.bits.manh & m) | u.bits.manl) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
if (u.bits.sign) {
|
|
||||||
#ifdef LDBL_IMPLICIT_NBIT
|
|
||||||
if (e == 0)
|
|
||||||
u.bits.exp++;
|
|
||||||
else
|
else
|
||||||
#endif
|
y = x + TOINT - TOINT - x;
|
||||||
INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
|
/* special case because of non-nearest rounding modes */
|
||||||
|
if (e <= 0x3fff-1) {
|
||||||
|
FORCE_EVAL(y);
|
||||||
|
return u.i.se >> 15 ? -1 : 0;
|
||||||
}
|
}
|
||||||
/* raise inexact flag */
|
if (y > 0)
|
||||||
if (huge + x > 0.0) {
|
return x + y - 1;
|
||||||
u.bits.manh &= ~m;
|
return x + y;
|
||||||
u.bits.manl = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (e < LDBL_MANT_DIG - 1) {
|
|
||||||
uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
|
|
||||||
if ((u.bits.manl & m) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
if (u.bits.sign) {
|
|
||||||
if (e == MANH_SIZE - 1)
|
|
||||||
INC_MANH(u, 1);
|
|
||||||
else {
|
|
||||||
uint64_t o = u.bits.manl;
|
|
||||||
u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
|
|
||||||
if (u.bits.manl < o) /* got a carry */
|
|
||||||
INC_MANH(u, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* raise inexact flag */
|
|
||||||
if (huge + x > 0.0)
|
|
||||||
u.bits.manl &= ~m;
|
|
||||||
}
|
|
||||||
return u.e;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,90 +1,20 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_rint.c */
|
#include <math.h>
|
||||||
/*
|
#include <stdint.h>
|
||||||
* ====================================================
|
|
||||||
* 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.
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* rint(x)
|
|
||||||
* Return x rounded to integral value according to the prevailing
|
|
||||||
* rounding mode.
|
|
||||||
* Method:
|
|
||||||
* Using floating addition.
|
|
||||||
* Exception:
|
|
||||||
* Inexact flag raised if x not equal to rint(x).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libm.h"
|
|
||||||
|
|
||||||
static const double
|
|
||||||
TWO52[2] = {
|
|
||||||
4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
|
|
||||||
-4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
|
|
||||||
};
|
|
||||||
|
|
||||||
double rint(double x)
|
double rint(double x)
|
||||||
{
|
{
|
||||||
int32_t i0,j0,sx;
|
union {double f; uint64_t i;} u = {x};
|
||||||
uint32_t i,i1;
|
int e = u.i>>52 & 0x7ff;
|
||||||
double w,t;
|
int s = u.i>>63;
|
||||||
|
double_t y;
|
||||||
|
|
||||||
EXTRACT_WORDS(i0, i1, x);
|
if (e >= 0x3ff+52)
|
||||||
// FIXME: signed shift
|
|
||||||
sx = (i0>>31) & 1;
|
|
||||||
j0 = ((i0>>20)&0x7ff) - 0x3ff;
|
|
||||||
if (j0 < 20) {
|
|
||||||
if (j0 < 0) {
|
|
||||||
if (((i0&0x7fffffff)|i1) == 0)
|
|
||||||
return x;
|
return x;
|
||||||
i1 |= i0 & 0x0fffff;
|
if (s)
|
||||||
i0 &= 0xfffe0000;
|
y = (double)(x - 0x1p52) + 0x1p52;
|
||||||
i0 |= ((i1|-i1)>>12) & 0x80000;
|
|
||||||
SET_HIGH_WORD(x, i0);
|
|
||||||
STRICT_ASSIGN(double, w, TWO52[sx] + x);
|
|
||||||
t = w - TWO52[sx];
|
|
||||||
GET_HIGH_WORD(i0, t);
|
|
||||||
SET_HIGH_WORD(t, (i0&0x7fffffff)|(sx<<31));
|
|
||||||
return t;
|
|
||||||
} else {
|
|
||||||
i = 0x000fffff>>j0;
|
|
||||||
if (((i0&i)|i1) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
i >>= 1;
|
|
||||||
if (((i0&i)|i1) != 0) {
|
|
||||||
/*
|
|
||||||
* Some bit is set after the 0.5 bit. To avoid the
|
|
||||||
* possibility of errors from double rounding in
|
|
||||||
* w = TWO52[sx]+x, adjust the 0.25 bit to a lower
|
|
||||||
* guard bit. We do this for all j0<=51. The
|
|
||||||
* adjustment is trickiest for j0==18 and j0==19
|
|
||||||
* since then it spans the word boundary.
|
|
||||||
*/
|
|
||||||
if (j0 == 19)
|
|
||||||
i1 = 0x40000000;
|
|
||||||
else if (j0 == 18)
|
|
||||||
i1 = 0x80000000;
|
|
||||||
else
|
else
|
||||||
i0 = (i0 & ~i)|(0x20000>>j0);
|
y = (double)(x + 0x1p52) - 0x1p52;
|
||||||
}
|
if (y == 0)
|
||||||
}
|
return s ? -0.0 : 0;
|
||||||
} else if (j0 > 51) {
|
return y;
|
||||||
if (j0 == 0x400)
|
|
||||||
return x+x; /* inf or NaN */
|
|
||||||
return x; /* x is integral */
|
|
||||||
} else {
|
|
||||||
i = (uint32_t)0xffffffff>>(j0-20);
|
|
||||||
if ((i1&i) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
i >>= 1;
|
|
||||||
if ((i1&i) != 0)
|
|
||||||
i1 = (i1 & ~i)|(0x40000000>>(j0-20));
|
|
||||||
}
|
|
||||||
INSERT_WORDS(x, i0, i1);
|
|
||||||
STRICT_ASSIGN(double, w, TWO52[sx] + x);
|
|
||||||
return w - TWO52[sx];
|
|
||||||
}
|
}
|
||||||
|
@ -1,48 +1,20 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_rintf.c */
|
#include <math.h>
|
||||||
/*
|
#include <stdint.h>
|
||||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
* 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 "libm.h"
|
|
||||||
|
|
||||||
static const float
|
|
||||||
TWO23[2] = {
|
|
||||||
8.3886080000e+06, /* 0x4b000000 */
|
|
||||||
-8.3886080000e+06, /* 0xcb000000 */
|
|
||||||
};
|
|
||||||
|
|
||||||
float rintf(float x)
|
float rintf(float x)
|
||||||
{
|
{
|
||||||
int32_t i0,j0,sx;
|
union {float f; uint32_t i;} u = {x};
|
||||||
float w,t;
|
int e = u.i>>23 & 0xff;
|
||||||
|
int s = u.i>>31;
|
||||||
|
float_t y;
|
||||||
|
|
||||||
GET_FLOAT_WORD(i0, x);
|
if (e >= 0x7f+23)
|
||||||
sx = (i0>>31) & 1;
|
|
||||||
j0 = ((i0>>23)&0xff) - 0x7f;
|
|
||||||
if (j0 < 23) {
|
|
||||||
if (j0 < 0) {
|
|
||||||
if ((i0&0x7fffffff) == 0)
|
|
||||||
return x;
|
return x;
|
||||||
STRICT_ASSIGN(float, w, TWO23[sx] + x);
|
if (s)
|
||||||
t = w - TWO23[sx];
|
y = (float)(x - 0x1p23f) + 0x1p23f;
|
||||||
GET_FLOAT_WORD(i0, t);
|
else
|
||||||
SET_FLOAT_WORD(t, (i0&0x7fffffff)|(sx<<31));
|
y = (float)(x + 0x1p23f) - 0x1p23f;
|
||||||
return t;
|
if (y == 0)
|
||||||
}
|
return s ? -0.0f : 0.0f;
|
||||||
STRICT_ASSIGN(float, w, TWO23[sx] + x);
|
return y;
|
||||||
return w - TWO23[sx];
|
|
||||||
}
|
|
||||||
if (j0 == 0x80)
|
|
||||||
return x+x; /* inf or NaN */
|
|
||||||
return x; /* x is integral */
|
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,3 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_rintl.c */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||||
@ -33,53 +6,26 @@ long double rintl(long double x)
|
|||||||
return rint(x);
|
return rint(x);
|
||||||
}
|
}
|
||||||
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
||||||
|
|
||||||
#define BIAS (LDBL_MAX_EXP - 1)
|
|
||||||
|
|
||||||
static const float
|
|
||||||
shift[2] = {
|
|
||||||
#if LDBL_MANT_DIG == 64
|
#if LDBL_MANT_DIG == 64
|
||||||
0x1.0p63, -0x1.0p63
|
#define TOINT 0x1p63
|
||||||
#elif LDBL_MANT_DIG == 113
|
#elif LDBL_MANT_DIG == 113
|
||||||
0x1.0p112, -0x1.0p112
|
#define TOINT 0x1p112
|
||||||
#endif
|
#endif
|
||||||
};
|
|
||||||
static const float zero[2] = { 0.0, -0.0 };
|
|
||||||
|
|
||||||
long double rintl(long double x)
|
long double rintl(long double x)
|
||||||
{
|
{
|
||||||
union IEEEl2bits u;
|
union ldshape u = {x};
|
||||||
uint32_t expsign;
|
int e = u.i.se & 0x7fff;
|
||||||
int ex, sign;
|
int s = u.i.se >> 15;
|
||||||
|
long double y;
|
||||||
u.e = x;
|
|
||||||
expsign = u.xbits.expsign;
|
|
||||||
ex = expsign & 0x7fff;
|
|
||||||
|
|
||||||
if (ex >= BIAS + LDBL_MANT_DIG - 1) {
|
|
||||||
if (ex == BIAS + LDBL_MAX_EXP)
|
|
||||||
return x + x; /* Inf, NaN, or unsupported format */
|
|
||||||
return x; /* finite and already an integer */
|
|
||||||
}
|
|
||||||
sign = expsign >> 15;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following code assumes that intermediate results are
|
|
||||||
* evaluated in long double precision. If they are evaluated in
|
|
||||||
* greater precision, double rounding may occur, and if they are
|
|
||||||
* evaluated in less precision (as on i386), results will be
|
|
||||||
* wildly incorrect.
|
|
||||||
*/
|
|
||||||
x += shift[sign];
|
|
||||||
x -= shift[sign];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the result is +-0, then it must have the same sign as x, but
|
|
||||||
* the above calculation doesn't always give this. Fix up the sign.
|
|
||||||
*/
|
|
||||||
if (ex < BIAS && x == 0.0)
|
|
||||||
return zero[sign];
|
|
||||||
|
|
||||||
|
if (e >= 0x3fff+LDBL_MANT_DIG-1)
|
||||||
return x;
|
return x;
|
||||||
|
if (s)
|
||||||
|
y = x - TOINT + TOINT;
|
||||||
|
else
|
||||||
|
y = x + TOINT - TOINT;
|
||||||
|
if (y == 0)
|
||||||
|
return 0*x;
|
||||||
|
return y;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,48 +1,28 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_round.c */
|
#include "libm.h"
|
||||||
/*-
|
|
||||||
* Copyright (c) 2003, Steven G. Kargl
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice unmodified, this list of conditions, and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
double round(double x)
|
double round(double x)
|
||||||
{
|
{
|
||||||
double t;
|
union {double f; uint64_t i;} u = {x};
|
||||||
|
int e = u.i >> 52 & 0x7ff;
|
||||||
|
double_t y;
|
||||||
|
|
||||||
if (!isfinite(x))
|
if (e >= 0x3ff+52)
|
||||||
return x;
|
return x;
|
||||||
|
if (u.i >> 63)
|
||||||
if (x >= 0.0) {
|
x = -x;
|
||||||
t = floor(x);
|
if (e < 0x3ff-1) {
|
||||||
if (t - x <= -0.5)
|
/* raise inexact if x!=0 */
|
||||||
t += 1.0;
|
FORCE_EVAL(x + 0x1p52);
|
||||||
return t;
|
return 0*u.f;
|
||||||
} else {
|
|
||||||
t = floor(-x);
|
|
||||||
if (t + x <= -0.5)
|
|
||||||
t += 1.0;
|
|
||||||
return -t;
|
|
||||||
}
|
}
|
||||||
|
y = (double)(x + 0x1p52) - 0x1p52 - x;
|
||||||
|
if (y > 0.5)
|
||||||
|
y = y + x - 1;
|
||||||
|
else if (y <= -0.5)
|
||||||
|
y = y + x + 1;
|
||||||
|
else
|
||||||
|
y = y + x;
|
||||||
|
if (u.i >> 63)
|
||||||
|
y = -y;
|
||||||
|
return y;
|
||||||
}
|
}
|
||||||
|
@ -1,48 +1,27 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_roundf.c */
|
#include "libm.h"
|
||||||
/*-
|
|
||||||
* Copyright (c) 2003, Steven G. Kargl
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice unmodified, this list of conditions, and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
float roundf(float x)
|
float roundf(float x)
|
||||||
{
|
{
|
||||||
float t;
|
union {float f; uint32_t i;} u = {x};
|
||||||
|
int e = u.i >> 23 & 0xff;
|
||||||
|
float_t y;
|
||||||
|
|
||||||
if (!isfinite(x))
|
if (e >= 0x7f+23)
|
||||||
return x;
|
return x;
|
||||||
|
if (u.i >> 31)
|
||||||
if (x >= 0.0) {
|
x = -x;
|
||||||
t = floorf(x);
|
if (e < 0x7f-1) {
|
||||||
if (t - x <= -0.5)
|
FORCE_EVAL(x + 0x1p23f);
|
||||||
t += 1.0;
|
return 0*u.f;
|
||||||
return t;
|
|
||||||
} else {
|
|
||||||
t = floorf(-x);
|
|
||||||
if (t + x <= -0.5)
|
|
||||||
t += 1.0;
|
|
||||||
return -t;
|
|
||||||
}
|
}
|
||||||
|
y = (float)(x + 0x1p23f) - 0x1p23f - x;
|
||||||
|
if (y > 0.5f)
|
||||||
|
y = y + x - 1;
|
||||||
|
else if (y <= -0.5f)
|
||||||
|
y = y + x + 1;
|
||||||
|
else
|
||||||
|
y = y + x;
|
||||||
|
if (u.i >> 31)
|
||||||
|
y = -y;
|
||||||
|
return y;
|
||||||
}
|
}
|
||||||
|
@ -1,56 +1,39 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_roundl.c */
|
#include "libm.h"
|
||||||
/*-
|
|
||||||
* Copyright (c) 2003, Steven G. Kargl
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice unmodified, this list of conditions, and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <float.h>
|
|
||||||
|
|
||||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||||
long double roundl(long double x)
|
long double roundl(long double x)
|
||||||
{
|
{
|
||||||
return round(x);
|
return round(x);
|
||||||
}
|
}
|
||||||
#else
|
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
||||||
|
#if LDBL_MANT_DIG == 64
|
||||||
|
#define TOINT 0x1p63
|
||||||
|
#elif LDBL_MANT_DIG == 113
|
||||||
|
#define TOINT 0x1p112
|
||||||
|
#endif
|
||||||
long double roundl(long double x)
|
long double roundl(long double x)
|
||||||
{
|
{
|
||||||
long double t;
|
union ldshape u = {x};
|
||||||
|
int e = u.i.se & 0x7fff;
|
||||||
|
long double y;
|
||||||
|
|
||||||
if (!isfinite(x))
|
if (e >= 0x3fff+LDBL_MANT_DIG-1)
|
||||||
return x;
|
return x;
|
||||||
|
if (u.i.se >> 15)
|
||||||
if (x >= 0.0) {
|
x = -x;
|
||||||
t = floorl(x);
|
if (e < 0x3fff-1) {
|
||||||
if (t - x <= -0.5)
|
FORCE_EVAL(x + TOINT);
|
||||||
t += 1.0;
|
return 0*u.f;
|
||||||
return t;
|
|
||||||
} else {
|
|
||||||
t = floorl(-x);
|
|
||||||
if (t + x <= -0.5)
|
|
||||||
t += 1.0;
|
|
||||||
return -t;
|
|
||||||
}
|
}
|
||||||
|
y = x + TOINT - TOINT - x;
|
||||||
|
if (y > 0.5)
|
||||||
|
y = y + x - 1;
|
||||||
|
else if (y <= -0.5)
|
||||||
|
y = y + x + 1;
|
||||||
|
else
|
||||||
|
y = y + x;
|
||||||
|
if (u.i.se >> 15)
|
||||||
|
y = -y;
|
||||||
|
return y;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,63 +1,19 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_trunc.c */
|
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
* 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.
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* trunc(x)
|
|
||||||
* Return x rounded toward 0 to integral value
|
|
||||||
* Method:
|
|
||||||
* Bit twiddling.
|
|
||||||
* Exception:
|
|
||||||
* Inexact flag raised if x not equal to trunc(x).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
static const double huge = 1.0e300;
|
|
||||||
|
|
||||||
double trunc(double x)
|
double trunc(double x)
|
||||||
{
|
{
|
||||||
int32_t i0,i1,j0;
|
union {double f; uint64_t i;} u = {x};
|
||||||
uint32_t i;
|
int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff + 12;
|
||||||
|
uint64_t m;
|
||||||
|
|
||||||
EXTRACT_WORDS(i0, i1, x);
|
if (e >= 52 + 12)
|
||||||
j0 = ((i0>>20)&0x7ff) - 0x3ff;
|
|
||||||
if (j0 < 20) {
|
|
||||||
if (j0 < 0) { /* |x|<1, return 0*sign(x) */
|
|
||||||
/* raise inexact if x != 0 */
|
|
||||||
if (huge+x > 0.0) {
|
|
||||||
i0 &= 0x80000000U;
|
|
||||||
i1 = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
i = 0x000fffff>>j0;
|
|
||||||
if (((i0&i)|i1) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
/* raise inexact */
|
|
||||||
if (huge+x > 0.0) {
|
|
||||||
i0 &= ~i;
|
|
||||||
i1 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (j0 > 51) {
|
|
||||||
if (j0 == 0x400)
|
|
||||||
return x + x; /* inf or NaN */
|
|
||||||
return x; /* x is integral */
|
|
||||||
} else {
|
|
||||||
i = (uint32_t)0xffffffff>>(j0-20);
|
|
||||||
if ((i1&i) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
/* raise inexact */
|
|
||||||
if (huge+x > 0.0)
|
|
||||||
i1 &= ~i;
|
|
||||||
}
|
|
||||||
INSERT_WORDS(x, i0, i1);
|
|
||||||
return x;
|
return x;
|
||||||
|
if (e < 12)
|
||||||
|
e = 1;
|
||||||
|
m = -1ULL >> e;
|
||||||
|
if ((u.i & m) == 0)
|
||||||
|
return x;
|
||||||
|
FORCE_EVAL(x + 0x1p120f);
|
||||||
|
u.i &= ~m;
|
||||||
|
return u.f;
|
||||||
}
|
}
|
||||||
|
@ -1,52 +1,19 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_truncf.c */
|
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
* 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.
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* truncf(x)
|
|
||||||
* Return x rounded toward 0 to integral value
|
|
||||||
* Method:
|
|
||||||
* Bit twiddling.
|
|
||||||
* Exception:
|
|
||||||
* Inexact flag raised if x not equal to truncf(x).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
static const float huge = 1.0e30f;
|
|
||||||
|
|
||||||
float truncf(float x)
|
float truncf(float x)
|
||||||
{
|
{
|
||||||
int32_t i0,j0;
|
union {float f; uint32_t i;} u = {x};
|
||||||
uint32_t i;
|
int e = (int)(u.i >> 23 & 0xff) - 0x7f + 9;
|
||||||
|
uint32_t m;
|
||||||
|
|
||||||
GET_FLOAT_WORD(i0, x);
|
if (e >= 23 + 9)
|
||||||
j0 = ((i0>>23)&0xff) - 0x7f;
|
|
||||||
if (j0 < 23) {
|
|
||||||
if (j0 < 0) { /* |x|<1, return 0*sign(x) */
|
|
||||||
/* raise inexact if x != 0 */
|
|
||||||
if (huge+x > 0.0f)
|
|
||||||
i0 &= 0x80000000;
|
|
||||||
} else {
|
|
||||||
i = 0x007fffff>>j0;
|
|
||||||
if ((i0&i) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
/* raise inexact */
|
|
||||||
if (huge+x > 0.0f)
|
|
||||||
i0 &= ~i;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (j0 == 0x80)
|
|
||||||
return x + x; /* inf or NaN */
|
|
||||||
return x; /* x is integral */
|
|
||||||
}
|
|
||||||
SET_FLOAT_WORD(x, i0);
|
|
||||||
return x;
|
return x;
|
||||||
|
if (e < 9)
|
||||||
|
e = 1;
|
||||||
|
m = -1U >> e;
|
||||||
|
if ((u.i & m) == 0)
|
||||||
|
return x;
|
||||||
|
FORCE_EVAL(x + 0x1p120f);
|
||||||
|
u.i &= ~m;
|
||||||
|
return u.f;
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,3 @@
|
|||||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_truncl.c */
|
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
* 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.
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* truncl(x)
|
|
||||||
* Return x rounded toward 0 to integral value
|
|
||||||
* Method:
|
|
||||||
* Bit twiddling.
|
|
||||||
* Exception:
|
|
||||||
* Inexact flag raised if x not equal to truncl(x).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||||
@ -26,43 +6,31 @@ long double truncl(long double x)
|
|||||||
return trunc(x);
|
return trunc(x);
|
||||||
}
|
}
|
||||||
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
||||||
#ifdef LDBL_IMPLICIT_NBIT
|
#if LDBL_MANT_DIG == 64
|
||||||
#define MANH_SIZE (LDBL_MANH_SIZE + 1)
|
#define TOINT 0x1p63
|
||||||
#else
|
#elif LDBL_MANT_DIG == 113
|
||||||
#define MANH_SIZE LDBL_MANH_SIZE
|
#define TOINT 0x1p112
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const long double huge = 1.0e300;
|
|
||||||
static const float zero[] = { 0.0, -0.0 };
|
|
||||||
|
|
||||||
long double truncl(long double x)
|
long double truncl(long double x)
|
||||||
{
|
{
|
||||||
union IEEEl2bits u = { .e = x };
|
union ldshape u = {x};
|
||||||
int e = u.bits.exp - LDBL_MAX_EXP + 1;
|
int e = u.i.se & 0x7fff;
|
||||||
|
int s = u.i.se >> 15;
|
||||||
|
long double y;
|
||||||
|
|
||||||
if (e < MANH_SIZE - 1) {
|
if (e >= 0x3fff+LDBL_MANT_DIG-1)
|
||||||
if (e < 0) {
|
return x;
|
||||||
/* raise inexact if x != 0 */
|
if (e <= 0x3fff-1) {
|
||||||
if (huge + x > 0.0)
|
FORCE_EVAL(x + 0x1p120f);
|
||||||
u.e = zero[u.bits.sign];
|
return x*0;
|
||||||
} else {
|
|
||||||
uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
|
|
||||||
if (((u.bits.manh & m) | u.bits.manl) == 0)
|
|
||||||
return x; /* x is integral */
|
|
||||||
/* raise inexact */
|
|
||||||
if (huge + x > 0.0) {
|
|
||||||
u.bits.manh &= ~m;
|
|
||||||
u.bits.manl = 0;
|
|
||||||
}
|
}
|
||||||
}
|
/* y = int(|x|) - |x|, where int(|x|) is an integer neighbor of |x| */
|
||||||
} else if (e < LDBL_MANT_DIG - 1) {
|
if (s)
|
||||||
uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
|
x = -x;
|
||||||
if ((u.bits.manl & m) == 0)
|
y = x + TOINT - TOINT - x;
|
||||||
return x; /* x is integral */
|
if (y > 0)
|
||||||
/* raise inexact */
|
y -= 1;
|
||||||
if (huge + x > 0.0)
|
x += y;
|
||||||
u.bits.manl &= ~m;
|
return s ? -x : x;
|
||||||
}
|
|
||||||
return u.e;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user