125c28e83SPiotr Jasiukajtis /* 225c28e83SPiotr Jasiukajtis * CDDL HEADER START 325c28e83SPiotr Jasiukajtis * 425c28e83SPiotr Jasiukajtis * The contents of this file are subject to the terms of the 525c28e83SPiotr Jasiukajtis * Common Development and Distribution License (the "License"). 625c28e83SPiotr Jasiukajtis * You may not use this file except in compliance with the License. 725c28e83SPiotr Jasiukajtis * 825c28e83SPiotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 925c28e83SPiotr Jasiukajtis * or http://www.opensolaris.org/os/licensing. 1025c28e83SPiotr Jasiukajtis * See the License for the specific language governing permissions 1125c28e83SPiotr Jasiukajtis * and limitations under the License. 1225c28e83SPiotr Jasiukajtis * 1325c28e83SPiotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each 1425c28e83SPiotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1525c28e83SPiotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the 1625c28e83SPiotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying 1725c28e83SPiotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner] 1825c28e83SPiotr Jasiukajtis * 1925c28e83SPiotr Jasiukajtis * CDDL HEADER END 2025c28e83SPiotr Jasiukajtis */ 2125c28e83SPiotr Jasiukajtis 2225c28e83SPiotr Jasiukajtis /* 2325c28e83SPiotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 2425c28e83SPiotr Jasiukajtis */ 2525c28e83SPiotr Jasiukajtis /* 2625c28e83SPiotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 2725c28e83SPiotr Jasiukajtis * Use is subject to license terms. 2825c28e83SPiotr Jasiukajtis */ 2925c28e83SPiotr Jasiukajtis 30*ddc0e0b5SRichard Lowe #pragma weak __cpow = cpow 3125c28e83SPiotr Jasiukajtis 3225c28e83SPiotr Jasiukajtis /* INDENT OFF */ 3325c28e83SPiotr Jasiukajtis /* 3425c28e83SPiotr Jasiukajtis * dcomplex cpow(dcomplex z); 3525c28e83SPiotr Jasiukajtis * 3625c28e83SPiotr Jasiukajtis * z**w analytically equivalent to 3725c28e83SPiotr Jasiukajtis * 3825c28e83SPiotr Jasiukajtis * cpow(z,w) = cexp(w clog(z)) 3925c28e83SPiotr Jasiukajtis * 4025c28e83SPiotr Jasiukajtis * Let z = x+iy, w = u+iv. 4125c28e83SPiotr Jasiukajtis * Since 4225c28e83SPiotr Jasiukajtis * _________ 4325c28e83SPiotr Jasiukajtis * / 2 2 -1 y 4425c28e83SPiotr Jasiukajtis * log(x+iy) = log(\/ x + y ) + i tan (---) 4525c28e83SPiotr Jasiukajtis * x 4625c28e83SPiotr Jasiukajtis * 4725c28e83SPiotr Jasiukajtis * 1 2 2 -1 y 4825c28e83SPiotr Jasiukajtis * = --- log(x + y ) + i tan (---) 4925c28e83SPiotr Jasiukajtis * 2 x 5025c28e83SPiotr Jasiukajtis * u 2 2 -1 y 5125c28e83SPiotr Jasiukajtis * (u+iv)* log(x+iy) = --- log(x + y ) - v tan (---) + (1) 5225c28e83SPiotr Jasiukajtis * 2 x 5325c28e83SPiotr Jasiukajtis * 5425c28e83SPiotr Jasiukajtis * v 2 2 -1 y 5525c28e83SPiotr Jasiukajtis * i * [ --- log(x + y ) + u tan (---) ] (2) 5625c28e83SPiotr Jasiukajtis * 2 x 5725c28e83SPiotr Jasiukajtis * 5825c28e83SPiotr Jasiukajtis * = r + i q 5925c28e83SPiotr Jasiukajtis * 6025c28e83SPiotr Jasiukajtis * Therefore, 6125c28e83SPiotr Jasiukajtis * w r+iq r 6225c28e83SPiotr Jasiukajtis * z = e = e (cos(q)+i*sin(q)) 6325c28e83SPiotr Jasiukajtis * _______ 6425c28e83SPiotr Jasiukajtis * / 2 2 6525c28e83SPiotr Jasiukajtis * r \/ x + y -v*atan2(y,x) 6625c28e83SPiotr Jasiukajtis * Here e can be expressed as: u * e 6725c28e83SPiotr Jasiukajtis * 6825c28e83SPiotr Jasiukajtis * Special cases (in the order of appearance): 6925c28e83SPiotr Jasiukajtis * 1. (anything) ** 0 is 1 7025c28e83SPiotr Jasiukajtis * 2. (anything) ** 1 is itself 7125c28e83SPiotr Jasiukajtis * 3. When v = 0, y = 0: 7225c28e83SPiotr Jasiukajtis * If x is finite and negative, and u is finite, then 7325c28e83SPiotr Jasiukajtis * x ** u = exp(u*pi i) * pow(|x|, u); 7425c28e83SPiotr Jasiukajtis * otherwise, 7525c28e83SPiotr Jasiukajtis * x ** u = pow(x, u); 7625c28e83SPiotr Jasiukajtis * 4. When v = 0, x = 0 or |x| = |y| or x is inf or y is inf: 7725c28e83SPiotr Jasiukajtis * (x + y i) ** u = r * exp(q i) 7825c28e83SPiotr Jasiukajtis * where 7925c28e83SPiotr Jasiukajtis * r = hypot(x,y) ** u 8025c28e83SPiotr Jasiukajtis * q = u * atan2pi(y, x) 8125c28e83SPiotr Jasiukajtis * 8225c28e83SPiotr Jasiukajtis * 5. otherwise, z**w is NAN if any x, y, u, v is a Nan or inf 8325c28e83SPiotr Jasiukajtis * 8425c28e83SPiotr Jasiukajtis * Note: many results of special cases are obtained in terms of 8525c28e83SPiotr Jasiukajtis * polar coordinate. In the conversion from polar to rectangle: 8625c28e83SPiotr Jasiukajtis * r exp(q i) = r * cos(q) + r * sin(q) i, 8725c28e83SPiotr Jasiukajtis * we regard r * 0 is 0 except when r is a NaN. 8825c28e83SPiotr Jasiukajtis */ 8925c28e83SPiotr Jasiukajtis /* INDENT ON */ 9025c28e83SPiotr Jasiukajtis 9125c28e83SPiotr Jasiukajtis #include "libm.h" /* atan2/exp/fabs/hypot/log/pow/scalbn */ 9225c28e83SPiotr Jasiukajtis /* atan2pi/exp2/sincos/sincospi/__k_clog_r/__k_atan2 */ 9325c28e83SPiotr Jasiukajtis #include "complex_wrapper.h" 9425c28e83SPiotr Jasiukajtis 9525c28e83SPiotr Jasiukajtis extern void sincospi(double, double *, double *); 9625c28e83SPiotr Jasiukajtis 9725c28e83SPiotr Jasiukajtis static const double 9825c28e83SPiotr Jasiukajtis huge = 1e300, 9925c28e83SPiotr Jasiukajtis tiny = 1e-300, 10025c28e83SPiotr Jasiukajtis invln2 = 1.44269504088896338700e+00, 10125c28e83SPiotr Jasiukajtis ln2hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ 10225c28e83SPiotr Jasiukajtis ln2lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ 10325c28e83SPiotr Jasiukajtis one = 1.0, 10425c28e83SPiotr Jasiukajtis zero = 0.0; 10525c28e83SPiotr Jasiukajtis 10625c28e83SPiotr Jasiukajtis static const int hiinf = 0x7ff00000; 10725c28e83SPiotr Jasiukajtis extern double atan2pi(double, double); 10825c28e83SPiotr Jasiukajtis 10925c28e83SPiotr Jasiukajtis /* 11025c28e83SPiotr Jasiukajtis * Assuming |t[0]| > |t[1]| and |t[2]| > |t[3]|, sum4fp subroutine 11125c28e83SPiotr Jasiukajtis * compute t[0] + t[1] + t[2] + t[3] into two double fp numbers. 11225c28e83SPiotr Jasiukajtis */ 11325c28e83SPiotr Jasiukajtis static double 11425c28e83SPiotr Jasiukajtis sum4fp(double ta[], double *w) { 11525c28e83SPiotr Jasiukajtis double t1, t2, t3, t4, w1, w2, t; 11625c28e83SPiotr Jasiukajtis t1 = ta[0]; t2 = ta[1]; t3 = ta[2]; t4 = ta[3]; 11725c28e83SPiotr Jasiukajtis /* 11825c28e83SPiotr Jasiukajtis * Rearrange ti so that |t1| >= |t2| >= |t3| >= |t4| 11925c28e83SPiotr Jasiukajtis */ 12025c28e83SPiotr Jasiukajtis if (fabs(t4) > fabs(t1)) { 12125c28e83SPiotr Jasiukajtis t = t1; t1 = t3; t3 = t; 12225c28e83SPiotr Jasiukajtis t = t2; t2 = t4; t4 = t; 12325c28e83SPiotr Jasiukajtis } else if (fabs(t3) > fabs(t1)) { 12425c28e83SPiotr Jasiukajtis t = t1; t1 = t3; 12525c28e83SPiotr Jasiukajtis if (fabs(t4) > fabs(t2)) { 12625c28e83SPiotr Jasiukajtis t3 = t4; t4 = t2; t2 = t; 12725c28e83SPiotr Jasiukajtis } else { 12825c28e83SPiotr Jasiukajtis t3 = t2; t2 = t; 12925c28e83SPiotr Jasiukajtis } 13025c28e83SPiotr Jasiukajtis } else if (fabs(t3) > fabs(t2)) { 13125c28e83SPiotr Jasiukajtis t = t2; t2 = t3; 13225c28e83SPiotr Jasiukajtis if (fabs(t4) > fabs(t2)) { 13325c28e83SPiotr Jasiukajtis t3 = t4; t4 = t; 13425c28e83SPiotr Jasiukajtis } else 13525c28e83SPiotr Jasiukajtis t3 = t; 13625c28e83SPiotr Jasiukajtis } 13725c28e83SPiotr Jasiukajtis /* summing r = t1 + t2 + t3 + t4 to w1 + w2 */ 13825c28e83SPiotr Jasiukajtis w1 = t3 + t4; 13925c28e83SPiotr Jasiukajtis w2 = t4 - (w1 - t3); 14025c28e83SPiotr Jasiukajtis t = t2 + w1; 14125c28e83SPiotr Jasiukajtis w2 += w1 - (t - t2); 14225c28e83SPiotr Jasiukajtis w1 = t + w2; 14325c28e83SPiotr Jasiukajtis w2 += t - w1; 14425c28e83SPiotr Jasiukajtis t = t1 + w1; 14525c28e83SPiotr Jasiukajtis w2 += w1 - (t - t1); 14625c28e83SPiotr Jasiukajtis w1 = t + w2; 14725c28e83SPiotr Jasiukajtis *w = w2 - (w1 - t); 14825c28e83SPiotr Jasiukajtis return (w1); 14925c28e83SPiotr Jasiukajtis } 15025c28e83SPiotr Jasiukajtis 15125c28e83SPiotr Jasiukajtis dcomplex 15225c28e83SPiotr Jasiukajtis cpow(dcomplex z, dcomplex w) { 15325c28e83SPiotr Jasiukajtis dcomplex ans; 15425c28e83SPiotr Jasiukajtis double x, y, u, v, t, c, s, r, x2, y2; 15525c28e83SPiotr Jasiukajtis double b[4], t1, t2, t3, t4, w1, w2, u1, v1, x1, y1; 15625c28e83SPiotr Jasiukajtis int ix, iy, hx, lx, hy, ly, hv, hu, iu, iv, lu, lv; 15725c28e83SPiotr Jasiukajtis int i, j, k; 15825c28e83SPiotr Jasiukajtis 15925c28e83SPiotr Jasiukajtis x = D_RE(z); 16025c28e83SPiotr Jasiukajtis y = D_IM(z); 16125c28e83SPiotr Jasiukajtis u = D_RE(w); 16225c28e83SPiotr Jasiukajtis v = D_IM(w); 16325c28e83SPiotr Jasiukajtis hx = ((int *) &x)[HIWORD]; 16425c28e83SPiotr Jasiukajtis lx = ((int *) &x)[LOWORD]; 16525c28e83SPiotr Jasiukajtis hy = ((int *) &y)[HIWORD]; 16625c28e83SPiotr Jasiukajtis ly = ((int *) &y)[LOWORD]; 16725c28e83SPiotr Jasiukajtis hu = ((int *) &u)[HIWORD]; 16825c28e83SPiotr Jasiukajtis lu = ((int *) &u)[LOWORD]; 16925c28e83SPiotr Jasiukajtis hv = ((int *) &v)[HIWORD]; 17025c28e83SPiotr Jasiukajtis lv = ((int *) &v)[LOWORD]; 17125c28e83SPiotr Jasiukajtis ix = hx & 0x7fffffff; 17225c28e83SPiotr Jasiukajtis iy = hy & 0x7fffffff; 17325c28e83SPiotr Jasiukajtis iu = hu & 0x7fffffff; 17425c28e83SPiotr Jasiukajtis iv = hv & 0x7fffffff; 17525c28e83SPiotr Jasiukajtis 17625c28e83SPiotr Jasiukajtis j = 0; 17725c28e83SPiotr Jasiukajtis if ((iv | lv) == 0) { /* z**(real) */ 17825c28e83SPiotr Jasiukajtis if (((hu - 0x3ff00000) | lu) == 0) { /* z ** 1 = z */ 17925c28e83SPiotr Jasiukajtis D_RE(ans) = x; 18025c28e83SPiotr Jasiukajtis D_IM(ans) = y; 18125c28e83SPiotr Jasiukajtis } else if ((iu | lu) == 0) { /* z ** 0 = 1 */ 18225c28e83SPiotr Jasiukajtis D_RE(ans) = one; 18325c28e83SPiotr Jasiukajtis D_IM(ans) = zero; 18425c28e83SPiotr Jasiukajtis } else if ((iy | ly) == 0) { /* (real)**(real) */ 18525c28e83SPiotr Jasiukajtis D_IM(ans) = zero; 18625c28e83SPiotr Jasiukajtis if (hx < 0 && ix < hiinf && iu < hiinf) { 18725c28e83SPiotr Jasiukajtis /* -x ** u is exp(i*pi*u)*pow(x,u) */ 18825c28e83SPiotr Jasiukajtis r = pow(-x, u); 18925c28e83SPiotr Jasiukajtis sincospi(u, &s, &c); 19025c28e83SPiotr Jasiukajtis D_RE(ans) = (c == zero)? c: c * r; 19125c28e83SPiotr Jasiukajtis D_IM(ans) = (s == zero)? s: s * r; 19225c28e83SPiotr Jasiukajtis } else 19325c28e83SPiotr Jasiukajtis D_RE(ans) = pow(x, u); 19425c28e83SPiotr Jasiukajtis } else if (((ix | lx) == 0) || ix >= hiinf || iy >= hiinf) { 19525c28e83SPiotr Jasiukajtis if (isnan(x) || isnan(y) || isnan(u)) 19625c28e83SPiotr Jasiukajtis D_RE(ans) = D_IM(ans) = x + y + u; 19725c28e83SPiotr Jasiukajtis else { 19825c28e83SPiotr Jasiukajtis if ((ix | lx) == 0) 19925c28e83SPiotr Jasiukajtis r = fabs(y); 20025c28e83SPiotr Jasiukajtis else 20125c28e83SPiotr Jasiukajtis r = fabs(x) + fabs(y); 20225c28e83SPiotr Jasiukajtis t = atan2pi(y, x); 20325c28e83SPiotr Jasiukajtis sincospi(t * u, &s, &c); 20425c28e83SPiotr Jasiukajtis D_RE(ans) = (c == zero)? c: c * r; 20525c28e83SPiotr Jasiukajtis D_IM(ans) = (s == zero)? s: s * r; 20625c28e83SPiotr Jasiukajtis } 20725c28e83SPiotr Jasiukajtis } else if (((ix - iy) | (lx - ly)) == 0) { /* |x| = |y| */ 20825c28e83SPiotr Jasiukajtis if (hx >= 0) { 20925c28e83SPiotr Jasiukajtis t = (hy >= 0)? 0.25 : -0.25; 21025c28e83SPiotr Jasiukajtis sincospi(t * u, &s, &c); 21125c28e83SPiotr Jasiukajtis } else if ((lu & 3) == 0) { 21225c28e83SPiotr Jasiukajtis t = (hy >= 0)? 0.75 : -0.75; 21325c28e83SPiotr Jasiukajtis sincospi(t * u, &s, &c); 21425c28e83SPiotr Jasiukajtis } else { 21525c28e83SPiotr Jasiukajtis r = (hy >= 0)? u : -u; 21625c28e83SPiotr Jasiukajtis t = -0.25 * r; 21725c28e83SPiotr Jasiukajtis w1 = r + t; 21825c28e83SPiotr Jasiukajtis w2 = t - (w1 - r); 21925c28e83SPiotr Jasiukajtis sincospi(w1, &t1, &t2); 22025c28e83SPiotr Jasiukajtis sincospi(w2, &t3, &t4); 22125c28e83SPiotr Jasiukajtis s = t1 * t4 + t3 * t2; 22225c28e83SPiotr Jasiukajtis c = t2 * t4 - t1 * t3; 22325c28e83SPiotr Jasiukajtis } 22425c28e83SPiotr Jasiukajtis if (ix < 0x3fe00000) /* |x| < 1/2 */ 22525c28e83SPiotr Jasiukajtis r = pow(fabs(x + x), u) * exp2(-0.5 * u); 22625c28e83SPiotr Jasiukajtis else if (ix >= 0x3ff00000 || iu < 0x408ff800) 22725c28e83SPiotr Jasiukajtis /* |x| >= 1 or |u| < 1023 */ 22825c28e83SPiotr Jasiukajtis r = pow(fabs(x), u) * exp2(0.5 * u); 22925c28e83SPiotr Jasiukajtis else /* special treatment */ 23025c28e83SPiotr Jasiukajtis j = 2; 23125c28e83SPiotr Jasiukajtis if (j == 0) { 23225c28e83SPiotr Jasiukajtis D_RE(ans) = (c == zero)? c: c * r; 23325c28e83SPiotr Jasiukajtis D_IM(ans) = (s == zero)? s: s * r; 23425c28e83SPiotr Jasiukajtis } 23525c28e83SPiotr Jasiukajtis } else 23625c28e83SPiotr Jasiukajtis j = 1; 23725c28e83SPiotr Jasiukajtis if (j == 0) 23825c28e83SPiotr Jasiukajtis return (ans); 23925c28e83SPiotr Jasiukajtis } 24025c28e83SPiotr Jasiukajtis if (iu >= hiinf || iv >= hiinf || ix >= hiinf || iy >= hiinf) { 24125c28e83SPiotr Jasiukajtis /* 24225c28e83SPiotr Jasiukajtis * non-zero imag part(s) with inf component(s) yields NaN 24325c28e83SPiotr Jasiukajtis */ 24425c28e83SPiotr Jasiukajtis t = fabs(x) + fabs(y) + fabs(u) + fabs(v); 24525c28e83SPiotr Jasiukajtis D_RE(ans) = D_IM(ans) = t - t; 24625c28e83SPiotr Jasiukajtis } else { 24725c28e83SPiotr Jasiukajtis k = 0; /* no scaling */ 24825c28e83SPiotr Jasiukajtis if (iu > 0x7f000000 || iv > 0x7f000000) { 24925c28e83SPiotr Jasiukajtis u *= .0009765625; /* scale 2**-10 to avoid overflow */ 25025c28e83SPiotr Jasiukajtis v *= .0009765625; 25125c28e83SPiotr Jasiukajtis k = 1; /* scale by 2**-10 */ 25225c28e83SPiotr Jasiukajtis } 25325c28e83SPiotr Jasiukajtis /* 25425c28e83SPiotr Jasiukajtis * Use similated higher precision arithmetic to compute: 25525c28e83SPiotr Jasiukajtis * r = u * log(hypot(x, y)) - v * atan2(y, x) 25625c28e83SPiotr Jasiukajtis * q = u * atan2(y, x) + v * log(hypot(x, y)) 25725c28e83SPiotr Jasiukajtis */ 25825c28e83SPiotr Jasiukajtis t1 = __k_clog_r(x, y, &t2); 25925c28e83SPiotr Jasiukajtis t3 = __k_atan2(y, x, &t4); 26025c28e83SPiotr Jasiukajtis x1 = t1; 26125c28e83SPiotr Jasiukajtis y1 = t3; 26225c28e83SPiotr Jasiukajtis u1 = u; 26325c28e83SPiotr Jasiukajtis v1 = v; 26425c28e83SPiotr Jasiukajtis ((int *) &u1)[LOWORD] &= 0xf8000000; 26525c28e83SPiotr Jasiukajtis ((int *) &v1)[LOWORD] &= 0xf8000000; 26625c28e83SPiotr Jasiukajtis ((int *) &x1)[LOWORD] &= 0xf8000000; 26725c28e83SPiotr Jasiukajtis ((int *) &y1)[LOWORD] &= 0xf8000000; 26825c28e83SPiotr Jasiukajtis x2 = t2 - (x1 - t1); /* log(hypot(x,y)) = x1 + x2 */ 26925c28e83SPiotr Jasiukajtis y2 = t4 - (y1 - t3); /* atan2(y,x) = y1 + y2 */ 27025c28e83SPiotr Jasiukajtis /* compute q = u * atan2(y, x) + v * log(hypot(x, y)) */ 27125c28e83SPiotr Jasiukajtis if (j != 2) { 27225c28e83SPiotr Jasiukajtis b[0] = u1 * y1; 27325c28e83SPiotr Jasiukajtis b[1] = (u - u1) * y1 + u * y2; 27425c28e83SPiotr Jasiukajtis if (j == 1) { /* v = 0 */ 27525c28e83SPiotr Jasiukajtis w1 = b[0] + b[1]; 27625c28e83SPiotr Jasiukajtis w2 = b[1] - (w1 - b[0]); 27725c28e83SPiotr Jasiukajtis } else { 27825c28e83SPiotr Jasiukajtis b[2] = v1 * x1; 27925c28e83SPiotr Jasiukajtis b[3] = (v - v1) * x1 + v * x2; 28025c28e83SPiotr Jasiukajtis w1 = sum4fp(b, &w2); 28125c28e83SPiotr Jasiukajtis } 28225c28e83SPiotr Jasiukajtis sincos(w1, &t1, &t2); 28325c28e83SPiotr Jasiukajtis sincos(w2, &t3, &t4); 28425c28e83SPiotr Jasiukajtis s = t1 * t4 + t3 * t2; 28525c28e83SPiotr Jasiukajtis c = t2 * t4 - t1 * t3; 28625c28e83SPiotr Jasiukajtis if (k == 1) 28725c28e83SPiotr Jasiukajtis /* 28825c28e83SPiotr Jasiukajtis * square (cos(q) + i sin(q)) k times to get 28925c28e83SPiotr Jasiukajtis * (cos(2^k * q + i sin(2^k * q) 29025c28e83SPiotr Jasiukajtis */ 29125c28e83SPiotr Jasiukajtis for (i = 0; i < 10; i++) { 29225c28e83SPiotr Jasiukajtis t1 = s * c; 29325c28e83SPiotr Jasiukajtis c = (c + s) * (c - s); 29425c28e83SPiotr Jasiukajtis s = t1 + t1; 29525c28e83SPiotr Jasiukajtis } 29625c28e83SPiotr Jasiukajtis } 29725c28e83SPiotr Jasiukajtis /* compute r = u * (t1, t2) - v * (t3, t4) */ 29825c28e83SPiotr Jasiukajtis b[0] = u1 * x1; 29925c28e83SPiotr Jasiukajtis b[1] = (u - u1) * x1 + u * x2; 30025c28e83SPiotr Jasiukajtis if (j == 1) { /* v = 0 */ 30125c28e83SPiotr Jasiukajtis w1 = b[0] + b[1]; 30225c28e83SPiotr Jasiukajtis w2 = b[1] - (w1 - b[0]); 30325c28e83SPiotr Jasiukajtis } else { 30425c28e83SPiotr Jasiukajtis b[2] = -v1 * y1; 30525c28e83SPiotr Jasiukajtis b[3] = (v1 - v) * y1 - v * y2; 30625c28e83SPiotr Jasiukajtis w1 = sum4fp(b, &w2); 30725c28e83SPiotr Jasiukajtis } 30825c28e83SPiotr Jasiukajtis /* check over/underflow for exp(w1 + w2) */ 30925c28e83SPiotr Jasiukajtis if (k && fabs(w1) < 1000.0) { 31025c28e83SPiotr Jasiukajtis w1 *= 1024; w2 *= 1024; k = 0; 31125c28e83SPiotr Jasiukajtis } 31225c28e83SPiotr Jasiukajtis hx = ((int *) &w1)[HIWORD]; 31325c28e83SPiotr Jasiukajtis lx = ((int *) &w1)[LOWORD]; 31425c28e83SPiotr Jasiukajtis ix = hx & 0x7fffffff; 31525c28e83SPiotr Jasiukajtis /* compute exp(w1 + w2) */ 31625c28e83SPiotr Jasiukajtis if (ix < 0x3c900000) /* exp(tiny < 2**-54) = 1 */ 31725c28e83SPiotr Jasiukajtis r = one; 31825c28e83SPiotr Jasiukajtis else if (ix >= 0x40880000) /* overflow/underflow */ 31925c28e83SPiotr Jasiukajtis r = (hx < 0)? tiny * tiny : huge * huge; 32025c28e83SPiotr Jasiukajtis else { /* compute exp(w1 + w2) */ 32125c28e83SPiotr Jasiukajtis k = (int) (invln2 * w1 + ((hx >= 0)? 0.5 : -0.5)); 32225c28e83SPiotr Jasiukajtis t1 = (double) k; 32325c28e83SPiotr Jasiukajtis t2 = w1 - t1 * ln2hi; 32425c28e83SPiotr Jasiukajtis t3 = w2 - t1 * ln2lo; 32525c28e83SPiotr Jasiukajtis r = exp(t2 + t3); 32625c28e83SPiotr Jasiukajtis } 32725c28e83SPiotr Jasiukajtis if (c != zero) c *= r; 32825c28e83SPiotr Jasiukajtis if (s != zero) s *= r; 32925c28e83SPiotr Jasiukajtis if (k != 0) { 33025c28e83SPiotr Jasiukajtis c = scalbn(c, k); 33125c28e83SPiotr Jasiukajtis s = scalbn(s, k); 33225c28e83SPiotr Jasiukajtis } 33325c28e83SPiotr Jasiukajtis D_RE(ans) = c; 33425c28e83SPiotr Jasiukajtis D_IM(ans) = s; 33525c28e83SPiotr Jasiukajtis } 33625c28e83SPiotr Jasiukajtis return (ans); 33725c28e83SPiotr Jasiukajtis } 338