12fe8fb19SBen Gras /* @(#)s_modf.c 5.1 93/09/24 */
22fe8fb19SBen Gras /*
32fe8fb19SBen Gras * ====================================================
42fe8fb19SBen Gras * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
52fe8fb19SBen Gras *
62fe8fb19SBen Gras * Developed at SunPro, a Sun Microsystems, Inc. business.
72fe8fb19SBen Gras * Permission to use, copy, modify, and distribute this
82fe8fb19SBen Gras * software is freely granted, provided that this notice
92fe8fb19SBen Gras * is preserved.
102fe8fb19SBen Gras * ====================================================
112fe8fb19SBen Gras */
122fe8fb19SBen Gras
132fe8fb19SBen Gras #include <sys/cdefs.h>
142fe8fb19SBen Gras #if defined(LIBM_SCCS) && !defined(lint)
15*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: s_modf.c,v 1.15 2014/06/16 12:54:43 joerg Exp $");
162fe8fb19SBen Gras #endif
172fe8fb19SBen Gras
182fe8fb19SBen Gras /*
192fe8fb19SBen Gras * modf(double x, double *iptr)
202fe8fb19SBen Gras * return fraction part of x, and return x's integral part in *iptr.
212fe8fb19SBen Gras * Method:
222fe8fb19SBen Gras * Bit twiddling.
232fe8fb19SBen Gras *
242fe8fb19SBen Gras * Exception:
252fe8fb19SBen Gras * No exception.
262fe8fb19SBen Gras */
272fe8fb19SBen Gras
282fe8fb19SBen Gras #include "math.h"
292fe8fb19SBen Gras #include "math_private.h"
302fe8fb19SBen Gras
312fe8fb19SBen Gras static const double one = 1.0;
322fe8fb19SBen Gras
33*0a6a1f1dSLionel Sambuc #ifndef __HAVE_LONG_DOUBLE
__strong_alias(_modfl,modf)34*0a6a1f1dSLionel Sambuc __strong_alias(_modfl, modf)
35*0a6a1f1dSLionel Sambuc __weak_alias(modfl, modf)
36*0a6a1f1dSLionel Sambuc #endif
37*0a6a1f1dSLionel Sambuc
382fe8fb19SBen Gras double
392fe8fb19SBen Gras modf(double x, double *iptr)
402fe8fb19SBen Gras {
412fe8fb19SBen Gras int32_t i0,i1,jj0;
422fe8fb19SBen Gras u_int32_t i;
432fe8fb19SBen Gras EXTRACT_WORDS(i0,i1,x);
442fe8fb19SBen Gras jj0 = (((uint32_t)i0>>20)&0x7ff)-0x3ff; /* exponent of x */
452fe8fb19SBen Gras if(jj0<20) { /* integer part in high x */
462fe8fb19SBen Gras if(jj0<0) { /* |x|<1 */
472fe8fb19SBen Gras INSERT_WORDS(*iptr,i0&0x80000000,0); /* *iptr = +-0 */
482fe8fb19SBen Gras return x;
492fe8fb19SBen Gras } else {
502fe8fb19SBen Gras i = (0x000fffff)>>jj0;
512fe8fb19SBen Gras if(((i0&i)|i1)==0) { /* x is integral */
522fe8fb19SBen Gras u_int32_t high;
532fe8fb19SBen Gras *iptr = x;
542fe8fb19SBen Gras GET_HIGH_WORD(high,x);
552fe8fb19SBen Gras INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
562fe8fb19SBen Gras return x;
572fe8fb19SBen Gras } else {
582fe8fb19SBen Gras INSERT_WORDS(*iptr,i0&(~i),0);
592fe8fb19SBen Gras return x - *iptr;
602fe8fb19SBen Gras }
612fe8fb19SBen Gras }
622fe8fb19SBen Gras } else if (jj0>51) { /* no fraction part */
632fe8fb19SBen Gras u_int32_t high;
642fe8fb19SBen Gras *iptr = x*one;
652fe8fb19SBen Gras if (jj0 == 0x400) /* +-inf or NaN */
662fe8fb19SBen Gras return 0.0 / x; /* +-0 or NaN */
672fe8fb19SBen Gras GET_HIGH_WORD(high,x);
682fe8fb19SBen Gras INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
692fe8fb19SBen Gras return x;
702fe8fb19SBen Gras } else { /* fraction part in low x */
712fe8fb19SBen Gras i = ((u_int32_t)(0xffffffff))>>(jj0-20);
722fe8fb19SBen Gras if((i1&i)==0) { /* x is integral */
732fe8fb19SBen Gras u_int32_t high;
742fe8fb19SBen Gras *iptr = x;
752fe8fb19SBen Gras GET_HIGH_WORD(high,x);
762fe8fb19SBen Gras INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
772fe8fb19SBen Gras return x;
782fe8fb19SBen Gras } else {
792fe8fb19SBen Gras INSERT_WORDS(*iptr,i0,i1&(~i));
802fe8fb19SBen Gras return x - *iptr;
812fe8fb19SBen Gras }
822fe8fb19SBen Gras }
832fe8fb19SBen Gras }
84