Home | History | Annotate | Line # | Download | only in math
      1  1.1  mrg /* Complex square root of a float type.
      2  1.1  mrg    Copyright (C) 1997-2018 Free Software Foundation, Inc.
      3  1.1  mrg    This file is part of the GNU C Library.
      4  1.1  mrg    Based on an algorithm by Stephen L. Moshier <moshier (at) world.std.com>.
      5  1.1  mrg    Contributed by Ulrich Drepper <drepper (at) cygnus.com>, 1997.
      6  1.1  mrg 
      7  1.1  mrg    The GNU C Library is free software; you can redistribute it and/or
      8  1.1  mrg    modify it under the terms of the GNU Lesser General Public
      9  1.1  mrg    License as published by the Free Software Foundation; either
     10  1.1  mrg    version 2.1 of the License, or (at your option) any later version.
     11  1.1  mrg 
     12  1.1  mrg    The GNU C Library is distributed in the hope that it will be useful,
     13  1.1  mrg    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  mrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  1.1  mrg    Lesser General Public License for more details.
     16  1.1  mrg 
     17  1.1  mrg    You should have received a copy of the GNU Lesser General Public
     18  1.1  mrg    License along with the GNU C Library; if not, see
     19  1.1  mrg    <http://www.gnu.org/licenses/>.  */
     20  1.1  mrg 
     21  1.1  mrg #include "quadmath-imp.h"
     22  1.1  mrg 
     23  1.1  mrg __complex128
     24  1.1  mrg csqrtq (__complex128 x)
     25  1.1  mrg {
     26  1.1  mrg   __complex128 res;
     27  1.1  mrg   int rcls = fpclassifyq (__real__ x);
     28  1.1  mrg   int icls = fpclassifyq (__imag__ x);
     29  1.1  mrg 
     30  1.1  mrg   if (__glibc_unlikely (rcls <= QUADFP_INFINITE || icls <= QUADFP_INFINITE))
     31  1.1  mrg     {
     32  1.1  mrg       if (icls == QUADFP_INFINITE)
     33  1.1  mrg 	{
     34  1.1  mrg 	  __real__ res = HUGE_VALQ;
     35  1.1  mrg 	  __imag__ res = __imag__ x;
     36  1.1  mrg 	}
     37  1.1  mrg       else if (rcls == QUADFP_INFINITE)
     38  1.1  mrg 	{
     39  1.1  mrg 	  if (__real__ x < 0)
     40  1.1  mrg 	    {
     41  1.1  mrg 	      __real__ res = icls == QUADFP_NAN ? nanq ("") : 0;
     42  1.1  mrg 	      __imag__ res = copysignq (HUGE_VALQ, __imag__ x);
     43  1.1  mrg 	    }
     44  1.1  mrg 	  else
     45  1.1  mrg 	    {
     46  1.1  mrg 	      __real__ res = __real__ x;
     47  1.1  mrg 	      __imag__ res = (icls == QUADFP_NAN
     48  1.1  mrg 			      ? nanq ("") : copysignq (0, __imag__ x));
     49  1.1  mrg 	    }
     50  1.1  mrg 	}
     51  1.1  mrg       else
     52  1.1  mrg 	{
     53  1.1  mrg 	  __real__ res = nanq ("");
     54  1.1  mrg 	  __imag__ res = nanq ("");
     55  1.1  mrg 	}
     56  1.1  mrg     }
     57  1.1  mrg   else
     58  1.1  mrg     {
     59  1.1  mrg       if (__glibc_unlikely (icls == QUADFP_ZERO))
     60  1.1  mrg 	{
     61  1.1  mrg 	  if (__real__ x < 0)
     62  1.1  mrg 	    {
     63  1.1  mrg 	      __real__ res = 0;
     64  1.1  mrg 	      __imag__ res = copysignq (sqrtq (-__real__ x), __imag__ x);
     65  1.1  mrg 	    }
     66  1.1  mrg 	  else
     67  1.1  mrg 	    {
     68  1.1  mrg 	      __real__ res = fabsq (sqrtq (__real__ x));
     69  1.1  mrg 	      __imag__ res = copysignq (0, __imag__ x);
     70  1.1  mrg 	    }
     71  1.1  mrg 	}
     72  1.1  mrg       else if (__glibc_unlikely (rcls == QUADFP_ZERO))
     73  1.1  mrg 	{
     74  1.1  mrg 	  __float128 r;
     75  1.1  mrg 	  if (fabsq (__imag__ x) >= 2 * FLT128_MIN)
     76  1.1  mrg 	    r = sqrtq (0.5Q * fabsq (__imag__ x));
     77  1.1  mrg 	  else
     78  1.1  mrg 	    r = 0.5Q * sqrtq (2 * fabsq (__imag__ x));
     79  1.1  mrg 
     80  1.1  mrg 	  __real__ res = r;
     81  1.1  mrg 	  __imag__ res = copysignq (r, __imag__ x);
     82  1.1  mrg 	}
     83  1.1  mrg       else
     84  1.1  mrg 	{
     85  1.1  mrg 	  __float128 d, r, s;
     86  1.1  mrg 	  int scale = 0;
     87  1.1  mrg 
     88  1.1  mrg 	  if (fabsq (__real__ x) > FLT128_MAX / 4)
     89  1.1  mrg 	    {
     90  1.1  mrg 	      scale = 1;
     91  1.1  mrg 	      __real__ x = scalbnq (__real__ x, -2 * scale);
     92  1.1  mrg 	      __imag__ x = scalbnq (__imag__ x, -2 * scale);
     93  1.1  mrg 	    }
     94  1.1  mrg 	  else if (fabsq (__imag__ x) > FLT128_MAX / 4)
     95  1.1  mrg 	    {
     96  1.1  mrg 	      scale = 1;
     97  1.1  mrg 	      if (fabsq (__real__ x) >= 4 * FLT128_MIN)
     98  1.1  mrg 		__real__ x = scalbnq (__real__ x, -2 * scale);
     99  1.1  mrg 	      else
    100  1.1  mrg 		__real__ x = 0;
    101  1.1  mrg 	      __imag__ x = scalbnq (__imag__ x, -2 * scale);
    102  1.1  mrg 	    }
    103  1.1  mrg 	  else if (fabsq (__real__ x) < 2 * FLT128_MIN
    104  1.1  mrg 		   && fabsq (__imag__ x) < 2 * FLT128_MIN)
    105  1.1  mrg 	    {
    106  1.1  mrg 	      scale = -((FLT128_MANT_DIG + 1) / 2);
    107  1.1  mrg 	      __real__ x = scalbnq (__real__ x, -2 * scale);
    108  1.1  mrg 	      __imag__ x = scalbnq (__imag__ x, -2 * scale);
    109  1.1  mrg 	    }
    110  1.1  mrg 
    111  1.1  mrg 	  d = hypotq (__real__ x, __imag__ x);
    112  1.1  mrg 	  /* Use the identity   2  Re res  Im res = Im x
    113  1.1  mrg 	     to avoid cancellation error in  d +/- Re x.  */
    114  1.1  mrg 	  if (__real__ x > 0)
    115  1.1  mrg 	    {
    116  1.1  mrg 	      r = sqrtq (0.5Q * (d + __real__ x));
    117  1.1  mrg 	      if (scale == 1 && fabsq (__imag__ x) < 1)
    118  1.1  mrg 		{
    119  1.1  mrg 		  /* Avoid possible intermediate underflow.  */
    120  1.1  mrg 		  s = __imag__ x / r;
    121  1.1  mrg 		  r = scalbnq (r, scale);
    122  1.1  mrg 		  scale = 0;
    123  1.1  mrg 		}
    124  1.1  mrg 	      else
    125  1.1  mrg 		s = 0.5Q * (__imag__ x / r);
    126  1.1  mrg 	    }
    127  1.1  mrg 	  else
    128  1.1  mrg 	    {
    129  1.1  mrg 	      s = sqrtq (0.5Q * (d - __real__ x));
    130  1.1  mrg 	      if (scale == 1 && fabsq (__imag__ x) < 1)
    131  1.1  mrg 		{
    132  1.1  mrg 		  /* Avoid possible intermediate underflow.  */
    133  1.1  mrg 		  r = fabsq (__imag__ x / s);
    134  1.1  mrg 		  s = scalbnq (s, scale);
    135  1.1  mrg 		  scale = 0;
    136  1.1  mrg 		}
    137  1.1  mrg 	      else
    138  1.1  mrg 		r = fabsq (0.5Q * (__imag__ x / s));
    139  1.1  mrg 	    }
    140  1.1  mrg 
    141  1.1  mrg 	  if (scale)
    142  1.1  mrg 	    {
    143  1.1  mrg 	      r = scalbnq (r, scale);
    144  1.1  mrg 	      s = scalbnq (s, scale);
    145  1.1  mrg 	    }
    146  1.1  mrg 
    147  1.1  mrg 	  math_check_force_underflow (r);
    148  1.1  mrg 	  math_check_force_underflow (s);
    149  1.1  mrg 
    150  1.1  mrg 	  __real__ res = r;
    151  1.1  mrg 	  __imag__ res = copysignq (s, __imag__ x);
    152  1.1  mrg 	}
    153  1.1  mrg     }
    154  1.1  mrg 
    155  1.1  mrg   return res;
    156  1.1  mrg }
    157