Home | History | Annotate | Line # | Download | only in math
      1 /* Return arc tangent of complex float type.
      2    Copyright (C) 1997-2018 Free Software Foundation, Inc.
      3    This file is part of the GNU C Library.
      4    Contributed by Ulrich Drepper <drepper (at) cygnus.com>, 1997.
      5 
      6    The GNU C Library is free software; you can redistribute it and/or
      7    modify it under the terms of the GNU Lesser General Public
      8    License as published by the Free Software Foundation; either
      9    version 2.1 of the License, or (at your option) any later version.
     10 
     11    The GNU C Library is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14    Lesser General Public License for more details.
     15 
     16    You should have received a copy of the GNU Lesser General Public
     17    License along with the GNU C Library; if not, see
     18    <http://www.gnu.org/licenses/>.  */
     19 
     20 #include "quadmath-imp.h"
     21 
     22 __complex128
     23 catanq (__complex128 x)
     24 {
     25   __complex128 res;
     26   int rcls = fpclassifyq (__real__ x);
     27   int icls = fpclassifyq (__imag__ x);
     28 
     29   if (__glibc_unlikely (rcls <= QUADFP_INFINITE || icls <= QUADFP_INFINITE))
     30     {
     31       if (rcls == QUADFP_INFINITE)
     32 	{
     33 	  __real__ res = copysignq (M_PI_2q, __real__ x);
     34 	  __imag__ res = copysignq (0, __imag__ x);
     35 	}
     36       else if (icls == QUADFP_INFINITE)
     37 	{
     38 	  if (rcls >= QUADFP_ZERO)
     39 	    __real__ res = copysignq (M_PI_2q, __real__ x);
     40 	  else
     41 	    __real__ res = nanq ("");
     42 	  __imag__ res = copysignq (0, __imag__ x);
     43 	}
     44       else if (icls == QUADFP_ZERO || icls == QUADFP_INFINITE)
     45 	{
     46 	  __real__ res = nanq ("");
     47 	  __imag__ res = copysignq (0, __imag__ x);
     48 	}
     49       else
     50 	{
     51 	  __real__ res = nanq ("");
     52 	  __imag__ res = nanq ("");
     53 	}
     54     }
     55   else if (__glibc_unlikely (rcls == QUADFP_ZERO && icls == QUADFP_ZERO))
     56     {
     57       res = x;
     58     }
     59   else
     60     {
     61       if (fabsq (__real__ x) >= 16 / FLT128_EPSILON
     62 	  || fabsq (__imag__ x) >= 16 / FLT128_EPSILON)
     63 	{
     64 	  __real__ res = copysignq (M_PI_2q, __real__ x);
     65 	  if (fabsq (__real__ x) <= 1)
     66 	    __imag__ res = 1 / __imag__ x;
     67 	  else if (fabsq (__imag__ x) <= 1)
     68 	    __imag__ res = __imag__ x / __real__ x / __real__ x;
     69 	  else
     70 	    {
     71 	      __float128 h = hypotq (__real__ x / 2, __imag__ x / 2);
     72 	      __imag__ res = __imag__ x / h / h / 4;
     73 	    }
     74 	}
     75       else
     76 	{
     77 	  __float128 den, absx, absy;
     78 
     79 	  absx = fabsq (__real__ x);
     80 	  absy = fabsq (__imag__ x);
     81 	  if (absx < absy)
     82 	    {
     83 	      __float128 t = absx;
     84 	      absx = absy;
     85 	      absy = t;
     86 	    }
     87 
     88 	  if (absy < FLT128_EPSILON / 2)
     89 	    {
     90 	      den = (1 - absx) * (1 + absx);
     91 	      if (den == 0)
     92 		den = 0;
     93 	    }
     94 	  else if (absx >= 1)
     95 	    den = (1 - absx) * (1 + absx) - absy * absy;
     96 	  else if (absx >= 0.75Q || absy >= 0.5Q)
     97 	    den = -__quadmath_x2y2m1q (absx, absy);
     98 	  else
     99 	    den = (1 - absx) * (1 + absx) - absy * absy;
    100 
    101 	  __real__ res = 0.5Q * atan2q (2 * __real__ x, den);
    102 
    103 	  if (fabsq (__imag__ x) == 1
    104 	      && fabsq (__real__ x) < FLT128_EPSILON * FLT128_EPSILON)
    105 	    __imag__ res = (copysignq (0.5Q, __imag__ x)
    106 			    * ((__float128) M_LN2q
    107 			       - logq (fabsq (__real__ x))));
    108 	  else
    109 	    {
    110 	      __float128 r2 = 0, num, f;
    111 
    112 	      if (fabsq (__real__ x) >= FLT128_EPSILON * FLT128_EPSILON)
    113 		r2 = __real__ x * __real__ x;
    114 
    115 	      num = __imag__ x + 1;
    116 	      num = r2 + num * num;
    117 
    118 	      den = __imag__ x - 1;
    119 	      den = r2 + den * den;
    120 
    121 	      f = num / den;
    122 	      if (f < 0.5Q)
    123 		__imag__ res = 0.25Q * logq (f);
    124 	      else
    125 		{
    126 		  num = 4 * __imag__ x;
    127 		  __imag__ res = 0.25Q * log1pq (num / den);
    128 		}
    129 	    }
    130 	}
    131 
    132       math_check_force_underflow_complex (res);
    133     }
    134 
    135   return res;
    136 }
    137