1 /*-
2 * Copyright (c) 2014-2018 Carsten Sonne Larsen <cs@innolan.net>
3 * Copyright (c) 2007 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software written by Stephen L. Moshier.
7 * It is redistributed by the NetBSD Foundation by permission of the author.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * The original source code can be obtained from:
30 * http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libm/complex/csqrt.c?rev=1.1
31 *
32 * Project homepage:
33 * https://amath.innolan.net
34 *
35 */
36
37 #include "prim.h"
38
39 /**
40 * @brief Square root of complex number
41 */
csqrt(complex z)42 complex csqrt(complex z)
43 {
44 complex w;
45 double x, y, r, t, scale;
46
47 x = creal(z);
48 y = cimag(z);
49
50 if (y == 0.0)
51 {
52 if (x == 0.0)
53 {
54 w = cpack(0.0, y);
55 }
56 else
57 {
58 r = fabs(x);
59 r = sqrt(r);
60 if (x < 0.0)
61 {
62 w = cpack(0.0, r);
63 }
64 else
65 {
66 w = cpack(r, y);
67 }
68 }
69 return w;
70 }
71 if (x == 0.0)
72 {
73 r = fabs(y);
74 r = sqrt(0.5 * r);
75 if (y > 0)
76 w = cpack(r, r);
77 else
78 w = cpack(r, -r);
79 return w;
80 }
81 /* Rescale to avoid internal overflow or underflow. */
82 if ((fabs(x) > 4.0) || (fabs(y) > 4.0))
83 {
84 x *= 0.25;
85 y *= 0.25;
86 scale = 2.0;
87 }
88 else
89 {
90 #if 1
91 x *= 1.8014398509481984e16; /* 2^54 */
92 y *= 1.8014398509481984e16;
93 scale = 7.450580596923828125e-9; /* 2^-27 */
94 #else
95 x *= 4.0;
96 y *= 4.0;
97 scale = 0.5;
98 #endif
99 }
100 w = cpack(x, y);
101 r = cabs(w);
102 if (x > 0)
103 {
104 t = sqrt(0.5 * r + 0.5 * x);
105 r = scale * fabs((0.5 * y) / t);
106 t *= scale;
107 }
108 else
109 {
110 r = sqrt(0.5 * r - 0.5 * x);
111 t = scale * fabs((0.5 * y) / r);
112 r *= scale;
113 }
114 if (y < 0)
115 w = cpack(t, -r);
116 else
117 w = cpack(t, r);
118 return w;
119 }
120