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 __remquof = remquof
34 * float remquof(float x, float y, int *quo) return remainderf(x,y) and an
35 * integer pointer quo such that *quo = N mod (2**31), where N is the
36 * exact integeral part of x/y rounded to nearest even.
38 * remquof call internal fmodquof
42 #include "libm_protos.h"
44 extern float fabsf(float);
47 is
= (int) 0x80000000,
52 static const float zero
= 0.0F
, half
= 0.5F
;
56 fmodquof(float x
, float y
, int *quo
) {
58 int hx
, ix
, iy
, iz
, k
, ny
, nd
, m
, sq
;
63 sq
= (iy
^ hx
) & is
; /* sign of x/y */
66 /* purge off exception values */
68 if (ix
>= ii
|| iy
> ii
|| iy
== 0) {
71 } else if (ix
<= iy
) {
73 w
= x
; /* return x if |x|<|y| */
75 *quo
= 1 + (sq
>> 30);
76 w
= zero
* x
; /* return sign(x)*0.0 */
81 * scale x,y to "normal" with
83 * nd = exponent of x minus exponent of y
89 /* special case for subnormal y or x */
111 /* fix point fmod for normalized ix and iy */
117 * else if (iz == 0) {
118 * *(int *) &w = is & hx;
125 /* unroll the above loop 4 times to gain performance */
165 *quo
= sq
>= 0 ? m
: -m
;
166 *(int *) &w
= is
& hx
;
179 /* end of unrolling */
187 *quo
= sq
>= 0 ? m
: -m
;
189 /* convert back to floating value and restore the sign */
191 *(int *) &w
= is
& hx
;
198 while (ix
> (iu
+ iu
)) {
203 *(int *) &w
= (is
& hx
) | (ix
& im
) | (ny
<< 23);
204 else { /* subnormal output */
207 *(int *) &w
= (is
& hx
) | ix
;
214 remquof(float x
, float y
, int *quo
) {
218 hx
= *(int *) &x
; /* high word of x */
219 hy
= *(int *) &y
; /* high word of y */
220 sx
= hx
& is
; /* sign of x */
221 sq
= (hx
^ hy
) & is
; /* sign of x/y */
223 hy
&= 0x7fffffff; /* |y| */
225 /* purge off exception values: y is 0 or NaN, x is Inf or NaN */
227 if (hx
>= ii
|| hy
> ii
|| hy
== 0) {
234 if (hy
<= 0x7f7fffff) {
235 x
= fmodquof(x
, y
+ y
, quo
);
236 *quo
= ((*quo
) & 0x3fffffff) << 1;
238 if (hy
< 0x01000000) {
266 return (sx
== 0 ? x
: -x
);