4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
30 #pragma weak __remquo = remquo
34 * double remquo(double x, double y, int *quo) return remainder(x,y) and an
35 * integer pointer quo such that *quo = N mod {2**31}, where N is the
36 * exact integral part of x/y rounded to nearest even.
38 * remquo call internal fmodquo
43 #include "libm_protos.h"
44 #include <math.h> /* fabs() */
45 #include <sys/isa_defs.h>
47 #if defined(_BIG_ENDIAN)
54 #define __HI(x) ((int *) &x)[HIWORD]
55 #define __LO(x) ((int *) &x)[LOWORD]
57 static const double one
= 1.0, Zero
[] = {0.0, -0.0};
60 fmodquo(double x
, double y
, int *quo
) {
61 int n
, hx
, hy
, hz
, ix
, iy
, sx
, sq
, i
, m
;
64 hx
= __HI(x
); /* high word of x */
65 lx
= __LO(x
); /* low word of x */
66 hy
= __HI(y
); /* high word of y */
67 ly
= __LO(y
); /* low word of y */
68 sx
= hx
& 0x80000000; /* sign of x */
69 sq
= (hx
^ hy
) & 0x80000000; /* sign of x/y */
71 hy
&= 0x7fffffff; /* |y| */
73 /* purge off exception values */
75 if ((hy
| ly
) == 0 || hx
>= 0x7ff00000 || /* y=0, or x !finite */
76 (hy
| ((ly
| -ly
) >> 31)) > 0x7ff00000) /* or y is NaN */
77 return ((x
* y
) / (x
* y
));
79 if (hx
< hy
|| lx
< ly
)
80 return (x
); /* |x|<|y| return x */
82 *quo
= 1 + (sq
>> 30);
83 /* |x|=|y| return x*0 */
84 return (Zero
[(unsigned) sx
>> 31]);
88 /* determine ix = ilogb(x) */
89 if (hx
< 0x00100000) { /* subnormal x */
91 for (ix
= -1043, i
= lx
; i
> 0; i
<<= 1)
94 for (ix
= -1022, i
= (hx
<< 11); i
> 0; i
<<= 1)
98 ix
= (hx
>> 20) - 1023;
100 /* determine iy = ilogb(y) */
101 if (hy
< 0x00100000) { /* subnormal y */
103 for (iy
= -1043, i
= ly
; i
> 0; i
<<= 1)
106 for (iy
= -1022, i
= (hy
<< 11); i
> 0; i
<<= 1)
110 iy
= (hy
>> 20) - 1023;
112 /* set up {hx,lx}, {hy,ly} and align y to x */
114 hx
= 0x00100000 | (0x000fffff & hx
);
115 else { /* subnormal x, shift x to normal */
118 hx
= (hx
<< n
) | (lx
>> (32 - n
));
126 hy
= 0x00100000 | (0x000fffff & hy
);
127 else { /* subnormal y, shift y to normal */
130 hy
= (hy
<< n
) | (ly
>> (32 - n
));
147 hx
= hx
+ hx
+ (lx
>> 31);
151 if ((hz
| lz
) == 0) { /* return sign(x)*0 */
157 *quo
= sq
>= 0 ? m
: -m
;
158 return (Zero
[(unsigned) sx
>> 31]);
160 hx
= hz
+ hz
+ (lz
>> 31);
175 *quo
= sq
>= 0 ? m
: -m
;
177 /* convert back to floating value and restore the sign */
178 if ((hx
| lx
) == 0) { /* return sign(x)*0 */
179 return (Zero
[(unsigned) sx
>> 31]);
181 while (hx
< 0x00100000) { /* normalize x */
182 hx
= hx
+ hx
+ (lx
>> 31);
186 if (iy
>= -1022) { /* normalize output */
187 hx
= (hx
- 0x00100000) | ((iy
+ 1023) << 20);
190 } else { /* subnormal output */
193 lx
= (lx
>> n
) | ((unsigned) hx
<< (32 - n
));
195 } else if (n
<= 31) {
196 lx
= (hx
<< (32 - n
)) | (lx
>> n
);
204 x
*= one
; /* create necessary signal */
206 return (x
); /* exact output */
212 remquo(double x
, double y
, int *quo
) {
217 hx
= __HI(x
); /* high word of x */
218 hy
= __HI(y
); /* high word of y */
219 ly
= __LO(y
); /* low word of y */
220 sx
= hx
& 0x80000000; /* sign of x */
221 sq
= (hx
^ hy
) & 0x80000000; /* sign of x/y */
223 hy
&= 0x7fffffff; /* |y| */
225 /* purge off exception values */
227 if ((hy
| ly
) == 0 || hx
>= 0x7ff00000 || /* y=0, or x !finite */
228 (hy
| ((ly
| -ly
) >> 31)) > 0x7ff00000) /* or y is NaN */
229 return ((x
* y
) / (x
* y
));
233 if (hy
<= 0x7fdfffff) {
234 x
= fmodquo(x
, y
+ y
, quo
);
235 *quo
= ((*quo
) & 0x3fffffff) << 1;
237 if (hy
< 0x00200000) {
265 return (sx
== 0 ? x
: -x
);