Remove "Contributed by" lines
[platform/upstream/glibc.git] / math / s_csqrt_template.c
1 /* Complex square root of a float type.
2    Copyright (C) 1997-2021 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18
19 #include <complex.h>
20 #include <math.h>
21 #include <math_private.h>
22 #include <math-underflow.h>
23 #include <float.h>
24
25 CFLOAT
26 M_DECL_FUNC (__csqrt) (CFLOAT x)
27 {
28   CFLOAT res;
29   int rcls = fpclassify (__real__ x);
30   int icls = fpclassify (__imag__ x);
31
32   if (__glibc_unlikely (rcls <= FP_INFINITE || icls <= FP_INFINITE))
33     {
34       if (icls == FP_INFINITE)
35         {
36           __real__ res = M_HUGE_VAL;
37           __imag__ res = __imag__ x;
38         }
39       else if (rcls == FP_INFINITE)
40         {
41           if (__real__ x < 0)
42             {
43               __real__ res = icls == FP_NAN ? M_NAN : 0;
44               __imag__ res = M_COPYSIGN (M_HUGE_VAL, __imag__ x);
45             }
46           else
47             {
48               __real__ res = __real__ x;
49               __imag__ res = (icls == FP_NAN
50                               ? M_NAN : M_COPYSIGN (0, __imag__ x));
51             }
52         }
53       else
54         {
55           __real__ res = M_NAN;
56           __imag__ res = M_NAN;
57         }
58     }
59   else
60     {
61       if (__glibc_unlikely (icls == FP_ZERO))
62         {
63           if (__real__ x < 0)
64             {
65               __real__ res = 0;
66               __imag__ res = M_COPYSIGN (M_SQRT (-__real__ x), __imag__ x);
67             }
68           else
69             {
70               __real__ res = M_FABS (M_SQRT (__real__ x));
71               __imag__ res = M_COPYSIGN (0, __imag__ x);
72             }
73         }
74       else if (__glibc_unlikely (rcls == FP_ZERO))
75         {
76           FLOAT r;
77           if (M_FABS (__imag__ x) >= 2 * M_MIN)
78             r = M_SQRT (M_LIT (0.5) * M_FABS (__imag__ x));
79           else
80             r = M_LIT (0.5) * M_SQRT (2 * M_FABS (__imag__ x));
81
82           __real__ res = r;
83           __imag__ res = M_COPYSIGN (r, __imag__ x);
84         }
85       else
86         {
87           FLOAT d, r, s;
88           int scale = 0;
89
90           if (M_FABS (__real__ x) > M_MAX / 4)
91             {
92               scale = 1;
93               __real__ x = M_SCALBN (__real__ x, -2 * scale);
94               __imag__ x = M_SCALBN (__imag__ x, -2 * scale);
95             }
96           else if (M_FABS (__imag__ x) > M_MAX / 4)
97             {
98               scale = 1;
99               if (M_FABS (__real__ x) >= 4 * M_MIN)
100                 __real__ x = M_SCALBN (__real__ x, -2 * scale);
101               else
102                 __real__ x = 0;
103               __imag__ x = M_SCALBN (__imag__ x, -2 * scale);
104             }
105           else if (M_FABS (__real__ x) < 2 * M_MIN
106                    && M_FABS (__imag__ x) < 2 * M_MIN)
107             {
108               scale = -((M_MANT_DIG + 1) / 2);
109               __real__ x = M_SCALBN (__real__ x, -2 * scale);
110               __imag__ x = M_SCALBN (__imag__ x, -2 * scale);
111             }
112
113           d = M_HYPOT (__real__ x, __imag__ x);
114           /* Use the identity   2  Re res  Im res = Im x
115              to avoid cancellation error in  d +/- Re x.  */
116           if (__real__ x > 0)
117             {
118               r = M_SQRT (M_LIT (0.5) * (d + __real__ x));
119               if (scale == 1 && M_FABS (__imag__ x) < 1)
120                 {
121                   /* Avoid possible intermediate underflow.  */
122                   s = __imag__ x / r;
123                   r = M_SCALBN (r, scale);
124                   scale = 0;
125                 }
126               else
127                 s = M_LIT (0.5) * (__imag__ x / r);
128             }
129           else
130             {
131               s = M_SQRT (M_LIT (0.5) * (d - __real__ x));
132               if (scale == 1 && M_FABS (__imag__ x) < 1)
133                 {
134                   /* Avoid possible intermediate underflow.  */
135                   r = M_FABS (__imag__ x / s);
136                   s = M_SCALBN (s, scale);
137                   scale = 0;
138                 }
139               else
140                 r = M_FABS (M_LIT (0.5) * (__imag__ x / s));
141             }
142
143           if (scale)
144             {
145               r = M_SCALBN (r, scale);
146               s = M_SCALBN (s, scale);
147             }
148
149           math_check_force_underflow (r);
150           math_check_force_underflow (s);
151
152           __real__ res = r;
153           __imag__ res = M_COPYSIGN (s, __imag__ x);
154         }
155     }
156
157   return res;
158 }
159 declare_mgen_alias (__csqrt, csqrt)