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 __catan = catan 3125c28e83SPiotr Jasiukajtis 3225c28e83SPiotr Jasiukajtis /* INDENT OFF */ 3325c28e83SPiotr Jasiukajtis /* 3425c28e83SPiotr Jasiukajtis * dcomplex catan(dcomplex z); 3525c28e83SPiotr Jasiukajtis * 3625c28e83SPiotr Jasiukajtis * If 3725c28e83SPiotr Jasiukajtis * z = x + iy, 3825c28e83SPiotr Jasiukajtis * 3925c28e83SPiotr Jasiukajtis * then 4025c28e83SPiotr Jasiukajtis * 1 ( 2x ) 1 2 2 4125c28e83SPiotr Jasiukajtis * Re w = - arctan(-----------) = - ATAN2(2x, 1 - x - y ) 4225c28e83SPiotr Jasiukajtis * 2 ( 2 2) 2 4325c28e83SPiotr Jasiukajtis * (1 - x - y ) 4425c28e83SPiotr Jasiukajtis * 4525c28e83SPiotr Jasiukajtis * ( 2 2) 4625c28e83SPiotr Jasiukajtis * 1 (x + (y+1) ) 1 4y 4725c28e83SPiotr Jasiukajtis * Im w = - log(------------) .= --- log [ 1 + ------------- ] 4825c28e83SPiotr Jasiukajtis * 4 ( 2 2) 4 2 2 4925c28e83SPiotr Jasiukajtis * (x + (y-1) ) x + (y-1) 5025c28e83SPiotr Jasiukajtis * 5125c28e83SPiotr Jasiukajtis * 2 16 3 y 5225c28e83SPiotr Jasiukajtis * = t - 2t + -- t - ..., where t = ----------------- 5325c28e83SPiotr Jasiukajtis * 3 x*x + (y-1)*(y-1) 5425c28e83SPiotr Jasiukajtis * 5525c28e83SPiotr Jasiukajtis * Note that: if catan( x, y) = ( u, v), then 5625c28e83SPiotr Jasiukajtis * catan(-x, y) = (-u, v) 5725c28e83SPiotr Jasiukajtis * catan( x,-y) = ( u,-v) 5825c28e83SPiotr Jasiukajtis * 5925c28e83SPiotr Jasiukajtis * Also, catan(x,y) = -i*catanh(-y,x), or 6025c28e83SPiotr Jasiukajtis * catanh(x,y) = i*catan(-y,x) 6125c28e83SPiotr Jasiukajtis * So, if catanh(y,x) = (v,u), then catan(x,y) = -i*(-v,u) = (u,v), i.e., 6225c28e83SPiotr Jasiukajtis * catan(x,y) = (u,v) 6325c28e83SPiotr Jasiukajtis * 6425c28e83SPiotr Jasiukajtis * EXCEPTION CASES (conform to ISO/IEC 9899:1999(E)): 6525c28e83SPiotr Jasiukajtis * catan( 0 , 0 ) = (0 , 0 ) 6625c28e83SPiotr Jasiukajtis * catan( NaN, 0 ) = (NaN , 0 ) 6725c28e83SPiotr Jasiukajtis * catan( 0 , 1 ) = (0 , +inf) with divide-by-zero 6825c28e83SPiotr Jasiukajtis * catan( inf, y ) = (pi/2 , 0 ) for finite +y 6925c28e83SPiotr Jasiukajtis * catan( NaN, y ) = (NaN , NaN ) with invalid for finite y != 0 7025c28e83SPiotr Jasiukajtis * catan( x , inf ) = (pi/2 , 0 ) for finite +x 7125c28e83SPiotr Jasiukajtis * catan( inf, inf ) = (pi/2 , 0 ) 7225c28e83SPiotr Jasiukajtis * catan( NaN, inf ) = (NaN , 0 ) 7325c28e83SPiotr Jasiukajtis * catan( x , NaN ) = (NaN , NaN ) with invalid for finite x 7425c28e83SPiotr Jasiukajtis * catan( inf, NaN ) = (pi/2 , +-0 ) 7525c28e83SPiotr Jasiukajtis */ 7625c28e83SPiotr Jasiukajtis /* INDENT ON */ 7725c28e83SPiotr Jasiukajtis 7825c28e83SPiotr Jasiukajtis #include "libm.h" /* atan/atan2/fabs/log/log1p */ 7925c28e83SPiotr Jasiukajtis #include "complex_wrapper.h" 8025c28e83SPiotr Jasiukajtis 8125c28e83SPiotr Jasiukajtis /* INDENT OFF */ 8225c28e83SPiotr Jasiukajtis static const double 8325c28e83SPiotr Jasiukajtis pi_2 = 1.570796326794896558e+00, 8425c28e83SPiotr Jasiukajtis zero = 0.0, 8525c28e83SPiotr Jasiukajtis half = 0.5, 8625c28e83SPiotr Jasiukajtis two = 2.0, 8725c28e83SPiotr Jasiukajtis ln2 = 6.931471805599453094172321214581765680755e-0001, 8825c28e83SPiotr Jasiukajtis one = 1.0; 8925c28e83SPiotr Jasiukajtis /* INDENT ON */ 9025c28e83SPiotr Jasiukajtis 9125c28e83SPiotr Jasiukajtis dcomplex 9225c28e83SPiotr Jasiukajtis catan(dcomplex z) { 9325c28e83SPiotr Jasiukajtis dcomplex ans; 9425c28e83SPiotr Jasiukajtis double x, y, ax, ay, t; 9525c28e83SPiotr Jasiukajtis int hx, hy, ix, iy; 9625c28e83SPiotr Jasiukajtis unsigned lx, ly; 9725c28e83SPiotr Jasiukajtis 9825c28e83SPiotr Jasiukajtis x = D_RE(z); 9925c28e83SPiotr Jasiukajtis y = D_IM(z); 10025c28e83SPiotr Jasiukajtis ax = fabs(x); 10125c28e83SPiotr Jasiukajtis ay = fabs(y); 10225c28e83SPiotr Jasiukajtis hx = HI_WORD(x); 10325c28e83SPiotr Jasiukajtis lx = LO_WORD(x); 10425c28e83SPiotr Jasiukajtis hy = HI_WORD(y); 10525c28e83SPiotr Jasiukajtis ly = LO_WORD(y); 10625c28e83SPiotr Jasiukajtis ix = hx & 0x7fffffff; 10725c28e83SPiotr Jasiukajtis iy = hy & 0x7fffffff; 10825c28e83SPiotr Jasiukajtis 10925c28e83SPiotr Jasiukajtis /* x is inf or NaN */ 11025c28e83SPiotr Jasiukajtis if (ix >= 0x7ff00000) { 11125c28e83SPiotr Jasiukajtis if (ISINF(ix, lx)) { 11225c28e83SPiotr Jasiukajtis D_RE(ans) = pi_2; 11325c28e83SPiotr Jasiukajtis D_IM(ans) = zero; 11425c28e83SPiotr Jasiukajtis } else { 11525c28e83SPiotr Jasiukajtis D_RE(ans) = x + x; 11625c28e83SPiotr Jasiukajtis if ((iy | ly) == 0 || (ISINF(iy, ly))) 11725c28e83SPiotr Jasiukajtis D_IM(ans) = zero; 11825c28e83SPiotr Jasiukajtis else 11925c28e83SPiotr Jasiukajtis D_IM(ans) = (fabs(y) - ay) / (fabs(y) - ay); 12025c28e83SPiotr Jasiukajtis } 12125c28e83SPiotr Jasiukajtis } else if (iy >= 0x7ff00000) { 12225c28e83SPiotr Jasiukajtis /* y is inf or NaN */ 12325c28e83SPiotr Jasiukajtis if (ISINF(iy, ly)) { 12425c28e83SPiotr Jasiukajtis D_RE(ans) = pi_2; 12525c28e83SPiotr Jasiukajtis D_IM(ans) = zero; 12625c28e83SPiotr Jasiukajtis } else { 12725c28e83SPiotr Jasiukajtis D_RE(ans) = (fabs(x) - ax) / (fabs(x) - ax); 12825c28e83SPiotr Jasiukajtis D_IM(ans) = y; 12925c28e83SPiotr Jasiukajtis } 13025c28e83SPiotr Jasiukajtis } else if ((ix | lx) == 0) { 13125c28e83SPiotr Jasiukajtis /* INDENT OFF */ 13225c28e83SPiotr Jasiukajtis /* 13325c28e83SPiotr Jasiukajtis * x = 0 13425c28e83SPiotr Jasiukajtis * 1 1 13525c28e83SPiotr Jasiukajtis * A = --- * atan2(2x, 1-x*x-y*y) = --- atan2(0,1-|y|) 13625c28e83SPiotr Jasiukajtis * 2 2 13725c28e83SPiotr Jasiukajtis * 13825c28e83SPiotr Jasiukajtis * 1 [ (y+1)*(y+1) ] 1 2 1 2y 13925c28e83SPiotr Jasiukajtis * B = - log [ ------------ ] = - log (1+ ---) or - log(1+ ----) 14025c28e83SPiotr Jasiukajtis * 4 [ (y-1)*(y-1) ] 2 y-1 2 1-y 14125c28e83SPiotr Jasiukajtis */ 14225c28e83SPiotr Jasiukajtis /* INDENT ON */ 14325c28e83SPiotr Jasiukajtis t = one - ay; 14425c28e83SPiotr Jasiukajtis if (((iy - 0x3ff00000) | ly) == 0) { 14525c28e83SPiotr Jasiukajtis /* y=1: catan(0,1)=(0,+inf) with 1/0 signal */ 14625c28e83SPiotr Jasiukajtis D_IM(ans) = ay / ax; 14725c28e83SPiotr Jasiukajtis D_RE(ans) = zero; 14825c28e83SPiotr Jasiukajtis } else if (iy >= 0x3ff00000) { /* y>1 */ 14925c28e83SPiotr Jasiukajtis D_IM(ans) = half * log1p(two / (-t)); 15025c28e83SPiotr Jasiukajtis D_RE(ans) = pi_2; 15125c28e83SPiotr Jasiukajtis } else { /* y<1 */ 15225c28e83SPiotr Jasiukajtis D_IM(ans) = half * log1p((ay + ay) / t); 15325c28e83SPiotr Jasiukajtis D_RE(ans) = zero; 15425c28e83SPiotr Jasiukajtis } 15525c28e83SPiotr Jasiukajtis } else if (iy < 0x3e200000 || ((ix - iy) >> 20) >= 30) { 15625c28e83SPiotr Jasiukajtis /* INDENT OFF */ 15725c28e83SPiotr Jasiukajtis /* 15825c28e83SPiotr Jasiukajtis * Tiny y (relative to 1+|x|) 15925c28e83SPiotr Jasiukajtis * |y| < E*(1+|x|) 16025c28e83SPiotr Jasiukajtis * where E=2**-29, -35, -60 for double, double extended, quad precision 16125c28e83SPiotr Jasiukajtis * 16225c28e83SPiotr Jasiukajtis * 1 [ x<=1: atan(x) 16325c28e83SPiotr Jasiukajtis * A = --- * atan2(2x, 1-x*x-y*y) ~ [ 1 1+x 16425c28e83SPiotr Jasiukajtis * 2 [ x>=1: - atan2(2,(1-x)*(-----)) 16525c28e83SPiotr Jasiukajtis * 2 x 16625c28e83SPiotr Jasiukajtis * 16725c28e83SPiotr Jasiukajtis * y/x 16825c28e83SPiotr Jasiukajtis * B ~ t*(1-2t), where t = ----------------- is tiny 16925c28e83SPiotr Jasiukajtis * x + (y-1)*(y-1)/x 17025c28e83SPiotr Jasiukajtis */ 17125c28e83SPiotr Jasiukajtis /* INDENT ON */ 17225c28e83SPiotr Jasiukajtis if (ix < 0x3ff00000) 17325c28e83SPiotr Jasiukajtis D_RE(ans) = atan(ax); 17425c28e83SPiotr Jasiukajtis else 17525c28e83SPiotr Jasiukajtis D_RE(ans) = half * atan2(two, (one - ax) * (one + 17625c28e83SPiotr Jasiukajtis one / ax)); 17725c28e83SPiotr Jasiukajtis if ((iy | ly) == 0) { 17825c28e83SPiotr Jasiukajtis D_IM(ans) = ay; 17925c28e83SPiotr Jasiukajtis } else { 18025c28e83SPiotr Jasiukajtis if (ix < 0x3e200000) 18125c28e83SPiotr Jasiukajtis t = ay / ((ay - one) * (ay - one)); 18225c28e83SPiotr Jasiukajtis else if (ix > 0x41c00000) 18325c28e83SPiotr Jasiukajtis t = (ay / ax) / ax; 18425c28e83SPiotr Jasiukajtis else 18525c28e83SPiotr Jasiukajtis t = ay / (ax * ax + (ay - one) * (ay - one)); 18625c28e83SPiotr Jasiukajtis D_IM(ans) = t * (one - (t + t)); 18725c28e83SPiotr Jasiukajtis } 18825c28e83SPiotr Jasiukajtis } else if (iy >= 0x41c00000 && ((iy - ix) >> 20) >= 30) { 18925c28e83SPiotr Jasiukajtis /* INDENT OFF */ 19025c28e83SPiotr Jasiukajtis /* 19125c28e83SPiotr Jasiukajtis * Huge y relative to 1+|x| 19225c28e83SPiotr Jasiukajtis * |y| > Einv*(1+|x|), where Einv~2**(prec/2+3), 19325c28e83SPiotr Jasiukajtis * 1 19425c28e83SPiotr Jasiukajtis * A ~ --- * atan2(2x, -y*y) ~ pi/2 19525c28e83SPiotr Jasiukajtis * 2 19625c28e83SPiotr Jasiukajtis * y 19725c28e83SPiotr Jasiukajtis * B ~ t*(1-2t), where t = --------------- is tiny 19825c28e83SPiotr Jasiukajtis * (y-1)*(y-1) 19925c28e83SPiotr Jasiukajtis */ 20025c28e83SPiotr Jasiukajtis /* INDENT ON */ 20125c28e83SPiotr Jasiukajtis D_RE(ans) = pi_2; 20225c28e83SPiotr Jasiukajtis t = (ay / (ay - one)) / (ay - one); 20325c28e83SPiotr Jasiukajtis D_IM(ans) = t * (one - (t + t)); 20425c28e83SPiotr Jasiukajtis } else if (((iy - 0x3ff00000) | ly) == 0) { 20525c28e83SPiotr Jasiukajtis /* INDENT OFF */ 20625c28e83SPiotr Jasiukajtis /* 20725c28e83SPiotr Jasiukajtis * y = 1 20825c28e83SPiotr Jasiukajtis * 1 1 20925c28e83SPiotr Jasiukajtis * A = --- * atan2(2x, -x*x) = --- atan2(2,-x) 21025c28e83SPiotr Jasiukajtis * 2 2 21125c28e83SPiotr Jasiukajtis * 21225c28e83SPiotr Jasiukajtis * 1 [x*x + 4] 1 4 [ 0.5(log2-logx) if 21325c28e83SPiotr Jasiukajtis * B = - log [-------] = - log (1+ ---) = [ |x|<E, else 0.25* 21425c28e83SPiotr Jasiukajtis * 4 [ x*x ] 4 x*x [ log1p((2/x)*(2/x)) 21525c28e83SPiotr Jasiukajtis */ 21625c28e83SPiotr Jasiukajtis /* INDENT ON */ 21725c28e83SPiotr Jasiukajtis D_RE(ans) = half * atan2(two, -ax); 21825c28e83SPiotr Jasiukajtis if (ix < 0x3e200000) 21925c28e83SPiotr Jasiukajtis D_IM(ans) = half * (ln2 - log(ax)); 22025c28e83SPiotr Jasiukajtis else { 22125c28e83SPiotr Jasiukajtis t = two / ax; 22225c28e83SPiotr Jasiukajtis D_IM(ans) = 0.25 * log1p(t * t); 22325c28e83SPiotr Jasiukajtis } 22425c28e83SPiotr Jasiukajtis } else if (ix >= 0x43900000) { 22525c28e83SPiotr Jasiukajtis /* INDENT OFF */ 22625c28e83SPiotr Jasiukajtis /* 22725c28e83SPiotr Jasiukajtis * Huge x: 22825c28e83SPiotr Jasiukajtis * when |x| > 1/E^2, 22925c28e83SPiotr Jasiukajtis * 1 pi 23025c28e83SPiotr Jasiukajtis * A ~ --- * atan2(2x, -x*x-y*y) ~ --- 23125c28e83SPiotr Jasiukajtis * 2 2 23225c28e83SPiotr Jasiukajtis * y y/x 23325c28e83SPiotr Jasiukajtis * B ~ t*(1-2t), where t = --------------- = (-------------- )/x 23425c28e83SPiotr Jasiukajtis * x*x+(y-1)*(y-1) 1+((y-1)/x)^2 23525c28e83SPiotr Jasiukajtis */ 23625c28e83SPiotr Jasiukajtis /* INDENT ON */ 23725c28e83SPiotr Jasiukajtis D_RE(ans) = pi_2; 23825c28e83SPiotr Jasiukajtis t = ((ay / ax) / (one + ((ay - one) / ax) * ((ay - one) / 23925c28e83SPiotr Jasiukajtis ax))) / ax; 24025c28e83SPiotr Jasiukajtis D_IM(ans) = t * (one - (t + t)); 24125c28e83SPiotr Jasiukajtis } else if (ix < 0x38b00000) { 24225c28e83SPiotr Jasiukajtis /* INDENT OFF */ 24325c28e83SPiotr Jasiukajtis /* 24425c28e83SPiotr Jasiukajtis * Tiny x: 24525c28e83SPiotr Jasiukajtis * when |x| < E^4, (note that y != 1) 24625c28e83SPiotr Jasiukajtis * 1 1 24725c28e83SPiotr Jasiukajtis * A = --- * atan2(2x, 1-x*x-y*y) ~ --- * atan2(2x,(1-y)*(1+y)) 24825c28e83SPiotr Jasiukajtis * 2 2 24925c28e83SPiotr Jasiukajtis * 25025c28e83SPiotr Jasiukajtis * 1 [(y+1)*(y+1)] 1 2 1 2y 25125c28e83SPiotr Jasiukajtis * B = - log [-----------] = - log (1+ ---) or - log(1+ ----) 25225c28e83SPiotr Jasiukajtis * 4 [(y-1)*(y-1)] 2 y-1 2 1-y 25325c28e83SPiotr Jasiukajtis */ 25425c28e83SPiotr Jasiukajtis /* INDENT ON */ 25525c28e83SPiotr Jasiukajtis D_RE(ans) = half * atan2(ax + ax, (one - ay) * (one + ay)); 25625c28e83SPiotr Jasiukajtis if (iy >= 0x3ff00000) 25725c28e83SPiotr Jasiukajtis D_IM(ans) = half * log1p(two / (ay - one)); 25825c28e83SPiotr Jasiukajtis else 25925c28e83SPiotr Jasiukajtis D_IM(ans) = half * log1p((ay + ay) / (one - ay)); 26025c28e83SPiotr Jasiukajtis } else { 26125c28e83SPiotr Jasiukajtis /* INDENT OFF */ 26225c28e83SPiotr Jasiukajtis /* 26325c28e83SPiotr Jasiukajtis * normal x,y 26425c28e83SPiotr Jasiukajtis * 1 26525c28e83SPiotr Jasiukajtis * A = --- * atan2(2x, 1-x*x-y*y) 26625c28e83SPiotr Jasiukajtis * 2 26725c28e83SPiotr Jasiukajtis * 26825c28e83SPiotr Jasiukajtis * 1 [x*x+(y+1)*(y+1)] 1 4y 26925c28e83SPiotr Jasiukajtis * B = - log [---------------] = - log (1+ -----------------) 27025c28e83SPiotr Jasiukajtis * 4 [x*x+(y-1)*(y-1)] 4 x*x + (y-1)*(y-1) 27125c28e83SPiotr Jasiukajtis */ 27225c28e83SPiotr Jasiukajtis /* INDENT ON */ 27325c28e83SPiotr Jasiukajtis t = one - ay; 27425c28e83SPiotr Jasiukajtis if (iy >= 0x3fe00000 && iy < 0x40000000) { 27525c28e83SPiotr Jasiukajtis /* y close to 1 */ 27625c28e83SPiotr Jasiukajtis D_RE(ans) = half * (atan2((ax + ax), (t * (one + ay) - 27725c28e83SPiotr Jasiukajtis ax * ax))); 27825c28e83SPiotr Jasiukajtis } else if (ix >= 0x3fe00000 && ix < 0x40000000) { 27925c28e83SPiotr Jasiukajtis /* x close to 1 */ 28025c28e83SPiotr Jasiukajtis D_RE(ans) = half * atan2((ax + ax), ((one - ax) * 28125c28e83SPiotr Jasiukajtis (one + ax) - ay * ay)); 28225c28e83SPiotr Jasiukajtis } else 28325c28e83SPiotr Jasiukajtis D_RE(ans) = half * atan2((ax + ax), ((one - ax * ax) - 28425c28e83SPiotr Jasiukajtis ay * ay)); 28525c28e83SPiotr Jasiukajtis D_IM(ans) = 0.25 * log1p((4.0 * ay) / (ax * ax + t * t)); 28625c28e83SPiotr Jasiukajtis } 28725c28e83SPiotr Jasiukajtis if (hx < 0) 28825c28e83SPiotr Jasiukajtis D_RE(ans) = -D_RE(ans); 28925c28e83SPiotr Jasiukajtis if (hy < 0) 29025c28e83SPiotr Jasiukajtis D_IM(ans) = -D_IM(ans); 29125c28e83SPiotr Jasiukajtis return (ans); 29225c28e83SPiotr Jasiukajtis } 293