2 * IBM Accurate Mathematical Library
3 * written by International Business Machines Corp.
4 * Copyright (C) 2001-2016 Free Software Foundation, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 /**************************************************************************/
20 /* MODULE_NAME urem.c */
22 /* FUNCTION: uremainder */
24 /* An ultimate remainder routine. Given two IEEE double machine numbers x */
25 /* ,y it computes the correctly rounded (to nearest) value of remainder */
26 /* of dividing x by y. */
27 /* Assumption: Machine arithmetic operations are performed in */
28 /* round to nearest mode of IEEE 754 standard. */
30 /* ************************************************************************/
37 #include <math_private.h>
39 /**************************************************************************/
40 /* An ultimate remainder routine. Given two IEEE double machine numbers x */
41 /* ,y it computes the correctly rounded (to nearest) value of remainder */
42 /**************************************************************************/
44 __ieee754_remainder (double x
, double y
)
47 int4 kx
, ky
, n
, nn
, n1
, m1
, l
;
48 mynumber u
, t
, w
= { { 0, 0 } }, v
= { { 0, 0 } }, ww
= { { 0, 0 } }, r
;
51 kx
= u
.i
[HIGH_HALF
] & 0x7fffffff; /* no sign for x*/
52 t
.i
[HIGH_HALF
] &= 0x7fffffff; /*no sign for y */
54 /*------ |x| < 2^1023 and 2^-970 < |y| < 2^1024 ------------------*/
55 if (kx
< 0x7fe00000 && ky
< 0x7ff00000 && ky
>= 0x03500000)
57 SET_RESTORE_ROUND_NOEX (FE_TONEAREST
);
58 if (kx
+ 0x00100000 < ky
)
60 if ((kx
- 0x01500000) < ky
)
63 v
.i
[HIGH_HALF
] = t
.i
[HIGH_HALF
];
64 d
= (z
+ big
.x
) - big
.x
;
65 xx
= (x
- d
* v
.x
) - d
* (t
.x
- v
.x
);
66 if (d
- z
!= 0.5 && d
- z
!= -0.5)
67 return (xx
!= 0) ? xx
: ((x
> 0) ? ZERO
.x
: nZERO
.x
);
70 if (fabs (xx
) > 0.5 * t
.x
)
71 return (z
> d
) ? xx
- t
.x
: xx
+ t
.x
;
75 } /* (kx<(ky+0x01500000)) */
80 nn
= (n
& 0x7ff00000) + 0x01400000;
83 l
= (kx
- nn
) & 0xfff00000;
88 r
.i
[HIGH_HALF
] = m1
- l
;
90 w
.i
[HIGH_HALF
] = n
+ l
;
91 ww
.i
[HIGH_HALF
] = (n1
) ? n1
+ l
: n1
;
92 d
= (z
+ big
.x
) - big
.x
;
93 u
.x
= (u
.x
- d
* w
.x
) - d
* ww
.x
;
94 l
= (u
.i
[HIGH_HALF
] & 0x7ff00000) - nn
;
100 d
= (z
+ big
.x
) - big
.x
;
101 u
.x
= (u
.x
- d
* w
.x
) - d
* ww
.x
;
102 if (fabs (u
.x
) < 0.5 * t
.x
)
103 return (u
.x
!= 0) ? u
.x
: ((x
> 0) ? ZERO
.x
: nZERO
.x
);
105 if (fabs (u
.x
) > 0.5 * t
.x
)
106 return (d
> z
) ? u
.x
+ t
.x
: u
.x
- t
.x
;
109 z
= u
.x
/ t
.x
; d
= (z
+ big
.x
) - big
.x
;
110 return ((u
.x
- d
* w
.x
) - d
* ww
.x
);
113 } /* (kx<0x7fe00000&&ky<0x7ff00000&&ky>=0x03500000) */
116 if (kx
< 0x7fe00000 && ky
< 0x7ff00000 && (ky
> 0 || t
.i
[LOW_HALF
] != 0))
118 y
= fabs (y
) * t128
.x
;
119 z
= __ieee754_remainder (x
, y
) * t128
.x
;
120 z
= __ieee754_remainder (z
, y
) * tm128
.x
;
125 if ((kx
& 0x7ff00000) == 0x7fe00000 && ky
< 0x7ff00000 &&
126 (ky
> 0 || t
.i
[LOW_HALF
] != 0))
129 z
= 2.0 * __ieee754_remainder (0.5 * x
, y
);
131 if (d
<= fabs (d
- y
))
136 return (z
> 0) ? z
- y
: z
+ y
;
138 else /* if x is too big */
140 if (ky
== 0 && t
.i
[LOW_HALF
] == 0) /* y = 0 */
141 return (x
* y
) / (x
* y
);
142 else if (kx
>= 0x7ff00000 /* x not finite */
143 || (ky
> 0x7ff00000 /* y is NaN */
144 || (ky
== 0x7ff00000 && t
.i
[LOW_HALF
] != 0)))
145 return (x
* y
) / (x
* y
);
152 strong_alias (__ieee754_remainder
, __remainder_finite
)