]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/ieee754/ldbl-128ibm/e_fmodl.c
a140fb322d7c6a61bdb372e5bb0e47d01b715443
1 /* e_fmodl.c -- long double version of e_fmod.c.
2 * Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
5 * ====================================================
6 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
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
12 * ====================================================
16 * __ieee754_fmodl(x,y)
17 * Return x mod y in exact arithmetic
18 * Method: shift and subtract
22 #include <math_private.h>
25 static const long double one
= 1.0, Zero
[] = {0.0, -0.0,};
28 __ieee754_fmodl (long double x
, long double y
)
30 int64_t hx
, hy
, hz
, sx
, sy
;
33 double xhi
, xlo
, yhi
, ylo
;
35 ldbl_unpack (x
, &xhi
, &xlo
);
36 EXTRACT_WORDS64 (hx
, xhi
);
37 EXTRACT_WORDS64 (lx
, xlo
);
38 ldbl_unpack (y
, &yhi
, &ylo
);
39 EXTRACT_WORDS64 (hy
, yhi
);
40 EXTRACT_WORDS64 (ly
, ylo
);
41 sx
= hx
&0x8000000000000000ULL
; /* sign of x */
43 sy
= hy
&0x8000000000000000ULL
; /* sign of y */
46 /* purge off exception values */
47 if(__builtin_expect(hy
==0 ||
48 (hx
>=0x7ff0000000000000LL
)|| /* y=0,or x not finite */
49 (hy
>0x7ff0000000000000LL
),0)) /* or y is NaN */
51 if (__builtin_expect (hx
<= hy
, 0))
53 /* If |x| < |y| return x. */
56 /* At this point the absolute value of the high doubles of
57 x and y must be equal. */
58 /* If the low double of y is the same sign as the high
59 double of y (ie. the low double increases |y|)... */
60 if (((ly
^ sy
) & 0x8000000000000000LL
) == 0
61 /* ... then a different sign low double to high double
62 for x or same sign but lower magnitude... */
63 && (int64_t) (lx
^ sx
) < (int64_t) (ly
^ sy
))
64 /* ... means |x| < |y|. */
66 /* If the low double of x differs in sign to the high
67 double of x (ie. the low double decreases |x|)... */
68 if (((lx
^ sx
) & 0x8000000000000000LL
) != 0
69 /* ... then a different sign low double to high double
70 for y with lower magnitude (we've already caught
71 the same sign for y case above)... */
72 && (int64_t) (lx
^ sx
) > (int64_t) (ly
^ sy
))
73 /* ... means |x| < |y|. */
75 /* If |x| == |y| return x*0. */
76 if ((lx
^ sx
) == (ly
^ sy
))
77 return Zero
[(uint64_t) sx
>> 63];
80 /* Make the IBM extended format 105 bit mantissa look like the ieee854 112
81 bit mantissa so the following operations will give the correct
83 ldbl_extract_mantissa(&hx
, &lx
, &ix
, x
);
84 ldbl_extract_mantissa(&hy
, &ly
, &iy
, y
);
86 if (__builtin_expect (ix
== -IEEE754_DOUBLE_BIAS
, 0))
88 /* subnormal x, shift x to normal. */
89 while ((hx
& (1LL << 48)) == 0)
91 hx
= (hx
<< 1) | (lx
>> 63);
97 if (__builtin_expect (iy
== -IEEE754_DOUBLE_BIAS
, 0))
99 /* subnormal y, shift y to normal. */
100 while ((hy
& (1LL << 48)) == 0)
102 hy
= (hy
<< 1) | (ly
>> 63);
111 hz
=hx
-hy
;lz
=lx
-ly
; if(lx
<ly
) hz
-= 1;
112 if(hz
<0){hx
= hx
+hx
+(lx
>>63); lx
= lx
+lx
;}
114 if((hz
|lz
)==0) /* return sign(x)*0 */
115 return Zero
[(u_int64_t
)sx
>>63];
116 hx
= hz
+hz
+(lz
>>63); lx
= lz
+lz
;
119 hz
=hx
-hy
;lz
=lx
-ly
; if(lx
<ly
) hz
-= 1;
120 if(hz
>=0) {hx
=hz
;lx
=lz
;}
122 /* convert back to floating value and restore the sign */
123 if((hx
|lx
)==0) /* return sign(x)*0 */
124 return Zero
[(u_int64_t
)sx
>>63];
125 while(hx
<0x0001000000000000LL
) { /* normalize x */
126 hx
= hx
+hx
+(lx
>>63); lx
= lx
+lx
;
129 if(__builtin_expect(iy
>= -1022,0)) { /* normalize output */
130 x
= ldbl_insert_mantissa((sx
>>63), iy
, hx
, lx
);
131 } else { /* subnormal output */
134 lx
= (lx
>>n
)|((u_int64_t
)hx
<<(64-n
));
137 lx
= (hx
<<(64-n
))|(lx
>>n
); hx
= sx
;
139 lx
= hx
>>(n
-64); hx
= sx
;
141 x
= ldbl_insert_mantissa((sx
>>63), iy
, hx
, lx
);
142 x
*= one
; /* create necessary signal */
144 return x
; /* exact output */
146 strong_alias (__ieee754_fmodl
, __fmodl_finite
)