1 /*
2 * CDDL HEADER START
3 *
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.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * _X_cplx_div_rx(a, w) returns a / w with infinities handled
29 * according to C99.
30 *
31 * If a and w are both finite and w is nonzero, _X_cplx_div_rx de-
32 * livers the complex quotient q according to the usual formula: let
33 * c = Re(w), and d = Im(w); then q = x + I * y where x = (a * c) / r
34 * and y = (-a * d) / r with r = c * c + d * d. This implementation
35 * scales to avoid premature underflow or overflow.
36 *
37 * If a is neither NaN nor zero and w is zero, or if a is infinite
38 * and w is finite and nonzero, _X_cplx_div_rx delivers an infinite
39 * result. If a is finite and w is infinite, _X_cplx_div_rx delivers
40 * a zero result.
41 *
42 * If a and w are both zero or both infinite, or if either a or w is
43 * NaN, _X_cplx_div_rx delivers NaN + I * NaN. C99 doesn't specify
44 * these cases.
45 *
46 * This implementation can raise spurious underflow, overflow, in-
47 * valid operation, inexact, and division-by-zero exceptions. C99
48 * allows this.
49 */
50
51 #if !defined(i386) && !defined(__i386) && !defined(__amd64)
52 #error This code is for x86 only
53 #endif
54
55 /*
56 * scl[i].e = 2^(4080*(4-i)) for i = 0, ..., 9
57 */
58 static const union {
59 unsigned int i[3];
60 long double e;
61 } scl[9] = {
62 { 0, 0x80000000, 0x7fbf },
63 { 0, 0x80000000, 0x6fcf },
64 { 0, 0x80000000, 0x5fdf },
65 { 0, 0x80000000, 0x4fef },
66 { 0, 0x80000000, 0x3fff },
67 { 0, 0x80000000, 0x300f },
68 { 0, 0x80000000, 0x201f },
69 { 0, 0x80000000, 0x102f },
70 { 0, 0x80000000, 0x003f }
71 };
72
73 /*
74 * Return +1 if x is +Inf, -1 if x is -Inf, and 0 otherwise
75 */
76 static int
testinfl(long double x)77 testinfl(long double x)
78 {
79 union {
80 int i[3];
81 long double e;
82 } xx;
83
84 xx.e = x;
85 if ((xx.i[2] & 0x7fff) != 0x7fff || ((xx.i[1] << 1) | xx.i[0]) != 0)
86 return (0);
87 return (1 | ((xx.i[2] << 16) >> 31));
88 }
89
90 long double _Complex
_X_cplx_div_rx(long double a,long double _Complex w)91 _X_cplx_div_rx(long double a, long double _Complex w)
92 {
93 long double _Complex v;
94 union {
95 int i[3];
96 long double e;
97 } aa, cc, dd;
98 long double c, d, sc, sd, r;
99 int ea, ec, ed, ew, i, j;
100
101 /*
102 * The following is equivalent to
103 *
104 * c = creall(*w); d = cimagl(*w);
105 */
106 c = ((long double *)&w)[0];
107 d = ((long double *)&w)[1];
108
109 /* extract exponents to estimate |z| and |w| */
110 aa.e = a;
111 ea = aa.i[2] & 0x7fff;
112
113 cc.e = c;
114 dd.e = d;
115 ec = cc.i[2] & 0x7fff;
116 ed = dd.i[2] & 0x7fff;
117 ew = (ec > ed)? ec : ed;
118
119 /* check for special cases */
120 if (ew >= 0x7fff) { /* w is inf or nan */
121 i = testinfl(c);
122 j = testinfl(d);
123 if (i | j) { /* w is infinite */
124 c = ((cc.i[2] << 16) < 0)? -0.0f : 0.0f;
125 d = ((dd.i[2] << 16) < 0)? -0.0f : 0.0f;
126 } else /* w is nan */
127 a += c + d;
128 ((long double *)&v)[0] = a * c;
129 ((long double *)&v)[1] = -a * d;
130 return (v);
131 }
132
133 if (ew == 0 && (cc.i[1] | cc.i[0] | dd.i[1] | dd.i[0]) == 0) {
134 /* w is zero; multiply a by 1/Re(w) - I * Im(w) */
135 c = 1.0f / c;
136 i = testinfl(a);
137 if (i) { /* a is infinite */
138 a = i;
139 }
140 ((long double *)&v)[0] = a * c;
141 ((long double *)&v)[1] = (a == 0.0f)? a * c : -a * d;
142 return (v);
143 }
144
145 if (ea >= 0x7fff) { /* a is inf or nan */
146 ((long double *)&v)[0] = a * c;
147 ((long double *)&v)[1] = -a * d;
148 return (v);
149 }
150
151 /*
152 * Compute the real and imaginary parts of the quotient,
153 * scaling to avoid overflow or underflow.
154 */
155 ew = (ew - 0x3800) >> 12;
156 sc = c * scl[ew + 4].e;
157 sd = d * scl[ew + 4].e;
158 r = sc * sc + sd * sd;
159
160 ea = (ea - 0x3800) >> 12;
161 a = (a * scl[ea + 4].e) / r;
162 ea -= (ew + ew);
163
164 ec = (ec - 0x3800) >> 12;
165 c = (c * scl[ec + 4].e) * a;
166 ec += ea;
167
168 ed = (ed - 0x3800) >> 12;
169 d = -(d * scl[ed + 4].e) * a;
170 ed += ea;
171
172 /* compensate for scaling */
173 sc = scl[3].e; /* 2^4080 */
174 if (ec < 0) {
175 ec = -ec;
176 sc = scl[5].e; /* 2^-4080 */
177 }
178 while (ec--)
179 c *= sc;
180
181 sd = scl[3].e;
182 if (ed < 0) {
183 ed = -ed;
184 sd = scl[5].e;
185 }
186 while (ed--)
187 d *= sd;
188
189 ((long double *)&v)[0] = c;
190 ((long double *)&v)[1] = d;
191 return (v);
192 }
193