1/* Rewritten for 64-bit machines by Ulrich Drepper <drepper@gmail.com>. */
2/*
3 * ====================================================
4 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 *
6 * Developed at SunPro, a Sun Microsystems, Inc. business.
7 * Permission to use, copy, modify, and distribute this
8 * software is freely granted, provided that this notice
9 * is preserved.
10 * ====================================================
11 */
12
13/*
14 * __ieee754_fmod(x,y)
15 * Return x mod y in exact arithmetic
16 * Method: shift and subtract
17 */
18
19#include <math.h>
20#include <math_private.h>
21#include <stdint.h>
22#include <libm-alias-finite.h>
23
24static const double one = 1.0, Zero[] = {0.0, -0.0,};
25
26double
27__ieee754_fmod (double x, double y)
28{
29 int32_t n,ix,iy;
30 int64_t hx,hy,hz,sx,i;
31
32 EXTRACT_WORDS64(hx,x);
33 EXTRACT_WORDS64(hy,y);
34 sx = hx&UINT64_C(0x8000000000000000); /* sign of x */
35 hx ^=sx; /* |x| */
36 hy &= UINT64_C(0x7fffffffffffffff); /* |y| */
37
38 /* purge off exception values */
39 if(__builtin_expect(hy==0
40 || hx >= UINT64_C(0x7ff0000000000000)
41 || hy > UINT64_C(0x7ff0000000000000), 0))
42 /* y=0,or x not finite or y is NaN */
43 return (x*y)/(x*y);
44 if(__builtin_expect(hx<=hy, 0)) {
45 if(hx<hy) return x; /* |x|<|y| return x */
46 return Zero[(uint64_t)sx>>63]; /* |x|=|y| return x*0*/
47 }
48
49 /* determine ix = ilogb(x) */
50 if(__builtin_expect(hx<UINT64_C(0x0010000000000000), 0)) {
51 /* subnormal x */
52 for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
53 } else ix = (hx>>52)-1023;
54
55 /* determine iy = ilogb(y) */
56 if(__builtin_expect(hy<UINT64_C(0x0010000000000000), 0)) { /* subnormal y */
57 for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
58 } else iy = (hy>>52)-1023;
59
60 /* set up hx, hy and align y to x */
61 if(__builtin_expect(ix >= -1022, 1))
62 hx = UINT64_C(0x0010000000000000)|(UINT64_C(0x000fffffffffffff)&hx);
63 else { /* subnormal x, shift x to normal */
64 n = -1022-ix;
65 hx<<=n;
66 }
67 if(__builtin_expect(iy >= -1022, 1))
68 hy = UINT64_C(0x0010000000000000)|(UINT64_C(0x000fffffffffffff)&hy);
69 else { /* subnormal y, shift y to normal */
70 n = -1022-iy;
71 hy<<=n;
72 }
73
74 /* fix point fmod */
75 n = ix - iy;
76 while(n--) {
77 hz=hx-hy;
78 if(hz<0){hx = hx+hx;}
79 else {
80 if(hz==0) /* return sign(x)*0 */
81 return Zero[(uint64_t)sx>>63];
82 hx = hz+hz;
83 }
84 }
85 hz=hx-hy;
86 if(hz>=0) {hx=hz;}
87
88 /* convert back to floating value and restore the sign */
89 if(hx==0) /* return sign(x)*0 */
90 return Zero[(uint64_t)sx>>63];
91 while(hx<UINT64_C(0x0010000000000000)) { /* normalize x */
92 hx = hx+hx;
93 iy -= 1;
94 }
95 if(__builtin_expect(iy>= -1022, 1)) { /* normalize output */
96 hx = ((hx-UINT64_C(0x0010000000000000))|((uint64_t)(iy+1023)<<52));
97 INSERT_WORDS64(x,hx|sx);
98 } else { /* subnormal output */
99 n = -1022 - iy;
100 hx>>=n;
101 INSERT_WORDS64(x,hx|sx);
102 x *= one; /* create necessary signal */
103 }
104 return x; /* exact output */
105}
106libm_alias_finite (__ieee754_fmod, __fmod)
107