2 * IBM Accurate Mathematical Library
3 * written by International Business Machines Corp.
4 * Copyright (C) 2001 Free Software Foundation
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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 /**************************************************************************/
21 /* MODULE_NAME urem.c */
23 /* FUNCTION: uremainder */
25 /* An ultimate remainder routine. Given two IEEE double machine numbers x */
26 /* ,y it computes the correctly rounded (to nearest) value of remainder */
27 /* of dividing x by y. */
28 /* Assumption: Machine arithmetic operations are performed in */
29 /* round to nearest mode of IEEE 754 standard. */
31 /* ************************************************************************/
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 /**************************************************************************/
43 double __ieee754_remainder(double x
, double y
)
49 int4 kx
,ky
,n
,nn
,n1
,m1
,l
;
53 mynumber u
,t
,w
={{0,0}},v
={{0,0}},ww
={{0,0}},r
;
56 kx
=u
.i
[HIGH_HALF
]&0x7fffffff; /* no sign for x*/
57 t
.i
[HIGH_HALF
]&=0x7fffffff; /*no sign for y */
59 /*------ |x| < 2^1023 and 2^-970 < |y| < 2^1024 ------------------*/
60 if (kx
<0x7fe00000 && ky
<0x7ff00000 && ky
>=0x03500000) {
61 if (kx
+0x00100000<ky
) return x
;
62 if ((kx
-0x01500000)<ky
) {
64 v
.i
[HIGH_HALF
]=t
.i
[HIGH_HALF
];
66 xx
=(x
-d
*v
.x
)-d
*(t
.x
-v
.x
);
67 if (d
-z
!=0.5&&d
-z
!=-0.5) return (xx
!=0)?xx
:((x
>0)?ZERO
.x
:nZERO
.x
);
69 if (ABS(xx
)>0.5*t
.x
) return (z
>d
)?xx
-t
.x
:xx
+t
.x
;
72 } /* (kx<(ky+0x01500000)) */
76 nn
=(n
&0x7ff00000)+0x01400000;
86 ww
.i
[HIGH_HALF
]=(n1
)?n1
+l
:n1
;
88 u
.x
=(u
.x
-d
*w
.x
)-d
*ww
.x
;
89 l
=(u
.i
[HIGH_HALF
]&0x7ff00000)-nn
;
96 u
.x
=(u
.x
-d
*w
.x
)-d
*ww
.x
;
97 if (ABS(u
.x
)<0.5*t
.x
) return (u
.x
!=0)?u
.x
:((x
>0)?ZERO
.x
:nZERO
.x
);
99 if (ABS(u
.x
)>0.5*t
.x
) return (d
>z
)?u
.x
+t
.x
:u
.x
-t
.x
;
101 {z
=u
.x
/t
.x
; d
=(z
+big
.x
)-big
.x
; return ((u
.x
-d
*w
.x
)-d
*ww
.x
);}
104 } /* (kx<0x7fe00000&&ky<0x7ff00000&&ky>=0x03500000) */
106 if (kx
<0x7fe00000&&ky
<0x7ff00000&&(ky
>0||t
.i
[LOW_HALF
]!=0)) {
108 z
=__ieee754_remainder(x
,y
)*t128
.x
;
109 z
=__ieee754_remainder(z
,y
)*tm128
.x
;
113 if ((kx
&0x7ff00000)==0x7fe00000&&ky
<0x7ff00000&&(ky
>0||t
.i
[LOW_HALF
]!=0)) {
115 z
=2.0*__ieee754_remainder(0.5*x
,y
);
117 if (d
<= ABS(d
-y
)) return z
;
118 else return (z
>0)?z
-y
:z
+y
;
120 else { /* if x is too big */
121 if (kx
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0 && y
== 1.0)
123 if (kx
>=0x7ff00000||(ky
==0&&t
.i
[LOW_HALF
]==0)||ky
>0x7ff00000||
124 (ky
==0x7ff00000&&t
.i
[LOW_HALF
]!=0))
125 return (u
.i
[HIGH_HALF
]&0x80000000)?nNAN
.x
:NAN
.x
;