summaryrefslogtreecommitdiff
path: root/newlib/libm/common/s_modf.c
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libm/common/s_modf.c')
-rw-r--r--newlib/libm/common/s_modf.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/newlib/libm/common/s_modf.c b/newlib/libm/common/s_modf.c
new file mode 100644
index 00000000000..01151397d64
--- /dev/null
+++ b/newlib/libm/common/s_modf.c
@@ -0,0 +1,131 @@
+
+/* @(#)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.
+ * ====================================================
+ */
+
+/*
+FUNCTION
+ <<modf>>, <<modff>>---split fractional and integer parts
+
+INDEX
+ modf
+INDEX
+ modff
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double modf(double <[val]>, double *<[ipart]>);
+ float modff(float <[val]>, float *<[ipart]>);
+
+TRAD_SYNOPSIS
+ #include <math.h>
+ double modf(<[val]>, <[ipart]>)
+ double <[val]>;
+ double *<[ipart]>;
+
+ float modff(<[val]>, <[ipart]>)
+ float <[val]>;
+ float *<[ipart]>;
+
+DESCRIPTION
+ <<modf>> splits the double <[val]> apart into an integer part
+ and a fractional part, returning the fractional part and
+ storing the integer part in <<*<[ipart]>>>. No rounding
+ whatsoever is done; the sum of the integer and fractional
+ parts is guaranteed to be exactly equal to <[val]>. That
+ is, if . <[realpart]> = modf(<[val]>, &<[intpart]>); then
+ `<<<[realpart]>+<[intpart]>>>' is the same as <[val]>.
+ <<modff>> is identical, save that it takes and returns
+ <<float>> rather than <<double>> values.
+
+RETURNS
+ The fractional part is returned. Each result has the same
+ sign as the supplied argument <[val]>.
+
+PORTABILITY
+ <<modf>> is ANSI C. <<modff>> is an extension.
+
+QUICKREF
+ modf ansi pure
+ modff - pure
+
+*/
+
+/*
+ * 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 "fdlibm.h"
+
+#ifndef _DOUBLE_IS_32BITS
+
+#ifdef __STDC__
+static const double one = 1.0;
+#else
+static double one = 1.0;
+#endif
+
+#ifdef __STDC__
+ double modf(double x, double *iptr)
+#else
+ double modf(x, iptr)
+ double x,*iptr;
+#endif
+{
+ __int32_t i0,i1,j0;
+ __uint32_t i;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff; /* exponent of x */
+ if(j0<20) { /* integer part in high x */
+ if(j0<0) { /* |x|<1 */
+ INSERT_WORDS(*iptr,i0&0x80000000,0); /* *iptr = +-0 */
+ return x;
+ } else {
+ i = (0x000fffff)>>j0;
+ 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 (j0>51) { /* no fraction part */
+ __uint32_t high;
+ *iptr = x*one;
+ 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))>>(j0-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;
+ }
+ }
+}
+
+#endif /* _DOUBLE_IS_32BITS */