1 /* s_modfl.c -- long double version of s_modf.c.
2  */
3 
4 /*
5  * ====================================================
6  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
7  *
8  * Developed at SunPro, a Sun Microsystems, Inc. business.
9  * Permission to use, copy, modify, and distribute this
10  * software is freely granted, provided that this notice
11  * is preserved.
12  * ====================================================
13  */
14 
15 #if defined(LIBM_SCCS) && !defined(lint)
16 static char rcsid[] = "$NetBSD: $";
17 #endif
18 
19 /*
20  * modfl(long double x, long double *iptr)
21  * return fraction part of x, and return x's integral part in *iptr.
22  * Method:
23  *	Bit twiddling.
24  *
25  * Exception:
26  *	No exception.
27  */
28 
29 #include <math.h>
30 #include <math_private.h>
31 #include <math_ldbl_opt.h>
32 
33 static const long double one = 1.0;
34 
__modfl(long double x,long double * iptr)35 long double __modfl(long double x, long double *iptr)
36 {
37 	int64_t i0,i1,j0;
38 	uint64_t i;
39 	double xhi, xlo;
40 
41 	ldbl_unpack (x, &xhi, &xlo);
42 	EXTRACT_WORDS64 (i0, xhi);
43 	EXTRACT_WORDS64 (i1, xlo);
44 	i1 &= 0x000fffffffffffffLL;
45 	j0 = ((i0>>52)&0x7ff)-0x3ff;	/* exponent of x */
46 	if(j0<52) {			/* integer part in high x */
47 	    if(j0<0) {			/* |x|<1 */
48 		/* *iptr = +-0 */
49 		INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL);
50 		*iptr = xhi;
51 		return x;
52 	    } else {
53 		i = (0x000fffffffffffffLL)>>j0;
54 		if(((i0&i)|(i1&0x7fffffffffffffffLL))==0) {		/* x is integral */
55 		    *iptr = x;
56 		    /* return +-0 */
57 		    INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL);
58 		    x = xhi;
59 		    return x;
60 		} else {
61 		    INSERT_WORDS64 (xhi, i0&(~i));
62 		    *iptr = xhi;
63 		    return x - *iptr;
64 		}
65 	    }
66 	} else if (j0>103) {		/* no fraction part */
67 	    *iptr = x*one;
68 	    /* We must handle NaNs separately.  */
69 	    if ((i0 & 0x7fffffffffffffffLL) > 0x7ff0000000000000LL)
70 	      return x*one;
71 	    /* return +-0 */
72 	    INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL);
73 	    x = xhi;
74 	    return x;
75 	} else {			/* fraction part in low x */
76 	    i = -1ULL>>(j0-52);
77 	    if((i1&i)==0) { 		/* x is integral */
78 		*iptr = x;
79 		/* return +-0 */
80 		INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL);
81 		x = xhi;
82 		return x;
83 	    } else {
84 		INSERT_WORDS64 (xhi, i0);
85 		INSERT_WORDS64 (xlo, i1&(~i));
86 		*iptr = ldbl_pack (xhi, xlo);
87 		return x - *iptr;
88 	    }
89 	}
90 }
91 #if IS_IN (libm)
92 long_double_symbol (libm, __modfl, modfl);
93 #else
94 long_double_symbol (libc, __modfl, modfl);
95 #endif
96