sortix-mirror/libm/src/s_modf.c
Jonas 'Sortie' Termansen 5980be9b3c Add Sortix Math Library.
This work is based in part on code from NetBSD libm, libc and kernel.

The library is partly public domain and partly BSD-style licensed.
2013-12-17 14:30:39 +01:00

79 lines
2 KiB
C

/* @(#)s_modf.c 5.1 93/09/24 */
/*
* ====================================================
* 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 <sys/cdefs.h>
#if defined(LIBM_SCCS) && !defined(lint)
__RCSID("$NetBSD: s_modf.c,v 1.14 2010/01/27 14:07:41 drochner Exp $");
#endif
/*
* modf(double x, double *iptr)
* return fraction part of x, and return x's integral part in *iptr.
* Method:
* Bit twiddling.
*
* Exception:
* No exception.
*/
#include "math.h"
#include "math_private.h"
static const double one = 1.0;
double
modf(double x, double *iptr)
{
int32_t i0,i1,jj0;
uint32_t i;
EXTRACT_WORDS(i0,i1,x);
jj0 = (((uint32_t)i0>>20)&0x7ff)-0x3ff; /* exponent of x */
if(jj0<20) { /* integer part in high x */
if(jj0<0) { /* |x|<1 */
INSERT_WORDS(*iptr,i0&0x80000000,0); /* *iptr = +-0 */
return x;
} else {
i = (0x000fffff)>>jj0;
if(((i0&i)|i1)==0) { /* x is integral */
uint32_t high;
*iptr = x;
GET_HIGH_WORD(high,x);
INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
return x;
} else {
INSERT_WORDS(*iptr,i0&(~i),0);
return x - *iptr;
}
}
} else if (jj0>51) { /* no fraction part */
uint32_t high;
*iptr = x*one;
if (jj0 == 0x400) /* +-inf or NaN */
return 0.0 / x; /* +-0 or NaN */
GET_HIGH_WORD(high,x);
INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
return x;
} else { /* fraction part in low x */
i = ((uint32_t)(0xffffffff))>>(jj0-20);
if((i1&i)==0) { /* x is integral */
uint32_t high;
*iptr = x;
GET_HIGH_WORD(high,x);
INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
return x;
} else {
INSERT_WORDS(*iptr,i0,i1&(~i));
return x - *iptr;
}
}
}