1 /* @(#)e_fmod.c 1.3 95/01/18 */
3 * ====================================================
4 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6 * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 * Permission to use, copy, modify, and distribute this
8 * software is freely granted, provided that this notice
10 * ====================================================
13 #include <sys/cdefs.h>
14 __RCSID("$NetBSD: e_fmodl.c,v 1.2 2013/11/14 15:25:22 martin Exp $");
16 __FBSDID("$FreeBSD: head/lib/msun/src/e_fmodl.c 181063 2008-07-31 20:09:47Z das $");
19 #include "namespace.h"
25 #include "math_private.h"
26 #include <machine/ieee.h>
28 #ifdef __HAVE_LONG_DOUBLE
30 #define BIAS (LDBL_MAX_EXP - 1)
32 #if EXT_FRACLBITS > 32
33 typedef uint64_t manl_t
;
35 typedef uint32_t manl_t
;
38 #if EXT_FRACHBITS > 32
39 typedef uint64_t manh_t
;
41 typedef uint32_t manh_t
;
45 * These macros add and remove an explicit integer bit in front of the
46 * fractional mantissa, if the architecture doesn't have such a bit by
49 #ifdef LDBL_IMPLICIT_NBIT
50 #define SET_NBIT(hx) ((hx) | (1ULL << EXT_FRACHBITS))
51 #define HFRAC_BITS EXT_FRACHBITS
54 #define SET_NBIT(hx) (hx)
55 #define HFRAC_BITS (EXT_FRACHBITS - 1)
58 #define MANL_SHIFT (EXT_FRACLBITS - 1)
60 static const long double one
= 1.0, Zero
[] = {0.0, -0.0,};
64 * Return x mod y in exact arithmetic
65 * Method: shift and subtract
68 * - The low part of the mantissa fits in a manl_t exactly.
69 * - The high part of the mantissa fits in an int64_t with enough room
70 * for an explicit integer bit in front of the fractional bits.
73 __ieee754_fmodl(long double x
, long double y
)
75 union ieee_ext_u ux
= { .extu_ld
= x
, };
76 union ieee_ext_u uy
= { .extu_ld
= y
, };
77 int64_t hx
,hz
; /* We need a carry bit even if EXT_FRACHBITS is 32. */
84 /* purge off exception values */
85 if((uy
.extu_exp
|uy
.extu_frach
|uy
.extu_fracl
)==0 || /* y=0 */
86 (ux
.extu_exp
== BIAS
+ LDBL_MAX_EXP
) || /* or x not finite */
87 (uy
.extu_exp
== BIAS
+ LDBL_MAX_EXP
&&
88 ((uy
.extu_frach
&~LDBL_NBIT
)|uy
.extu_fracl
)!=0)) /* or y is NaN */
90 if(ux
.extu_exp
<=uy
.extu_exp
) {
91 if((ux
.extu_exp
<uy
.extu_exp
) ||
92 (ux
.extu_frach
<=uy
.extu_frach
&&
93 (ux
.extu_frach
<uy
.extu_frach
||
94 ux
.extu_fracl
<uy
.extu_fracl
))) {
95 return x
; /* |x|<|y| return x or x-y */
97 if(ux
.extu_frach
==uy
.extu_frach
&& ux
.extu_fracl
==uy
.extu_fracl
) {
98 return Zero
[sx
]; /* |x|=|y| return x*0*/
102 /* determine ix = ilogb(x) */
103 if(ux
.extu_exp
== 0) { /* subnormal x */
104 ux
.extu_ld
*= 0x1.0p512
;
105 ix
= ux
.extu_exp
- (BIAS
+ 512);
107 ix
= ux
.extu_exp
- BIAS
;
110 /* determine iy = ilogb(y) */
111 if(uy
.extu_exp
== 0) { /* subnormal y */
112 uy
.extu_ld
*= 0x1.0p512
;
113 iy
= uy
.extu_exp
- (BIAS
+ 512);
115 iy
= uy
.extu_exp
- BIAS
;
118 /* set up {hx,lx}, {hy,ly} and align y to x */
119 hx
= SET_NBIT(ux
.extu_frach
);
120 hy
= SET_NBIT(uy
.extu_frach
);
128 hz
=hx
-hy
;lz
=lx
-ly
; if(lx
<ly
) hz
-= 1;
129 if(hz
<0){hx
= hx
+hx
+(lx
>>MANL_SHIFT
); lx
= lx
+lx
;}
131 if ((hz
|lz
)==0) /* return sign(x)*0 */
133 hx
= hz
+hz
+(lz
>>MANL_SHIFT
); lx
= lz
+lz
;
136 hz
=hx
-hy
;lz
=lx
-ly
; if(lx
<ly
) hz
-= 1;
137 if(hz
>=0) {hx
=hz
;lx
=lz
;}
139 /* convert back to floating value and restore the sign */
140 if((hx
|lx
)==0) /* return sign(x)*0 */
142 while(hx
<(1LL<<HFRAC_BITS
)) { /* normalize x */
143 hx
= hx
+hx
+(lx
>>MANL_SHIFT
); lx
= lx
+lx
;
146 ux
.extu_frach
= hx
; /* The mantissa is truncated here if needed. */
148 if (iy
< LDBL_MIN_EXP
) {
149 ux
.extu_exp
= iy
+ (BIAS
+ 512);
150 ux
.extu_ld
*= 0x1p
-512;
152 ux
.extu_exp
= iy
+ BIAS
;
154 x
= ux
.extu_ld
* one
; /* create necessary signal */
155 return x
; /* exact output */
158 #endif /* __HAVE_LONG_DOUBLE */