8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libbc / libc / gen / common / fmod.c
blob4692f54609b0d7b5e90504dd123e67b128a372c0
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 1988 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 /* Special version adapted from libm for use in libc. */
31 static int n0 = 0, n1 = 1;
33 static double two52 = 4.503599627370496000E+15;
34 static double twom52 = 2.220446049250313081E-16;
36 static double
37 setexception(int n, double x)
39 return (0.0);
42 double
43 copysign(double x, double y)
45 long *px = (long *) &x;
46 long *py = (long *) &y;
47 px[n0] = (px[n0] & 0x7fffffff) | (py[n0] & 0x80000000);
48 return (x);
51 static double
52 fabs(double x)
54 long *px = (long *) &x;
55 px[0] &= 0x7fffffff;
57 return (x);
60 static int
61 finite(double x)
63 long *px = (long *) &x;
64 return ((px[n0] & 0x7ff00000) != 0x7ff00000);
67 static int
68 ilogb(double x)
70 long *px = (long *) &x, k;
71 k = px[n0] & 0x7ff00000;
72 if (k == 0) {
73 if ((px[n1] | (px[n0] & 0x7fffffff)) == 0)
74 return (0x80000001);
75 else {
76 x *= two52;
77 return ((px[n0] & 0x7ff00000) >> 20) - 1075;
79 } else if (k != 0x7ff00000)
80 return (k >> 20) - 1023;
81 else
82 return (0x7fffffff);
85 static double
86 scalbn(double x, int n)
88 long *px = (long *) &x, k;
89 double twom54 = twom52 * 0.25;
90 k = (px[n0] & 0x7ff00000) >> 20;
91 if (k == 0x7ff)
92 return (x + x);
93 if ((px[n1] | (px[n0] & 0x7fffffff)) == 0)
94 return (x);
95 if (k == 0) {
96 x *= two52;
97 k = ((px[n0] & 0x7ff00000) >> 20) - 52;
99 k = k + n;
100 if (n > 5000)
101 return (setexception(2, x));
102 if (n < -5000)
103 return (setexception(1, x));
104 if (k > 0x7fe)
105 return (setexception(2, x));
106 if (k <= -54)
107 return (setexception(1, x));
108 if (k > 0) {
109 px[n0] = (px[n0] & 0x800fffff) | (k << 20);
110 return (x);
112 k += 54;
113 px[n0] = (px[n0] & 0x800fffff) | (k << 20);
114 return (x * twom54);
117 double
118 fmod(double x, double y)
120 int ny, nr;
121 double r, z, w;
123 int finite(), ilogb();
124 double fabs(), scalbn(), copysign();
126 /* purge off exception values */
127 if (!finite(x) || y != y || y == 0.0) {
128 return ((x * y) / (x * y));
130 /* scale and subtract to get the remainder */
131 r = fabs(x);
132 y = fabs(y);
133 ny = ilogb(y);
134 while (r >= y) {
135 nr = ilogb(r);
136 if (nr == ny)
137 w = y;
138 else {
139 z = scalbn(y, nr - ny - 1);
140 w = z + z;
142 if (r >= w)
143 r -= w;
144 else
145 r -= z;
148 /* restore sign */
149 return (copysign(r, x));