blob: 179b5396abcc4bca5ad635ef0c098b7f25f04284 [file] [log] [blame]
Charles L. Dorian2e90f662010-04-05 22:10:27 -07001// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Rob Pike6ab6c492011-11-08 15:38:47 -08005package cmplx
Charles L. Dorian2e90f662010-04-05 22:10:27 -07006
7import "math"
8
9// The original C code, the long comment, and the constants
10// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
11// The go code is a simplified version of the original C.
12//
13// Cephes Math Library Release 2.8: June, 2000
14// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
15//
16// The readme file at http://netlib.sandia.gov/cephes/ says:
17// Some software in this archive may be from the book _Methods and
18// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
19// International, 1989) or from the Cephes Mathematical Library, a
20// commercial product. In either event, it is copyrighted by the author.
21// What you see here may be used freely but it comes with no support or
22// guarantee.
23//
24// The two known misprints in the book are repaired here in the
25// source listings for the gamma function and the incomplete beta
26// integral.
27//
28// Stephen L. Moshier
29// moshier@na-net.ornl.gov
30
31// Complex square root
32//
33// DESCRIPTION:
34//
35// If z = x + iy, r = |z|, then
36//
37// 1/2
38// Re w = [ (r + x)/2 ] ,
39//
40// 1/2
41// Im w = [ (r - x)/2 ] .
42//
43// Cancellation error in r-x or r+x is avoided by using the
44// identity 2 Re w Im w = y.
45//
46// Note that -w is also a square root of z. The root chosen
47// is always in the right half plane and Im w has the same sign as y.
48//
49// ACCURACY:
50//
51// Relative error:
52// arithmetic domain # trials peak rms
53// DEC -10,+10 25000 3.2e-17 9.6e-18
54// IEEE -10,+10 1,000,000 2.9e-16 6.1e-17
55
56// Sqrt returns the square root of x.
57func Sqrt(x complex128) complex128 {
58 if imag(x) == 0 {
59 if real(x) == 0 {
Russ Coxf2b5a072011-01-19 23:09:00 -050060 return complex(0, 0)
Charles L. Dorian2e90f662010-04-05 22:10:27 -070061 }
62 if real(x) < 0 {
Russ Coxf2b5a072011-01-19 23:09:00 -050063 return complex(0, math.Sqrt(-real(x)))
Charles L. Dorian2e90f662010-04-05 22:10:27 -070064 }
Russ Coxf2b5a072011-01-19 23:09:00 -050065 return complex(math.Sqrt(real(x)), 0)
Charles L. Dorian2e90f662010-04-05 22:10:27 -070066 }
67 if real(x) == 0 {
68 if imag(x) < 0 {
69 r := math.Sqrt(-0.5 * imag(x))
Russ Coxf2b5a072011-01-19 23:09:00 -050070 return complex(r, -r)
Charles L. Dorian2e90f662010-04-05 22:10:27 -070071 }
72 r := math.Sqrt(0.5 * imag(x))
Russ Coxf2b5a072011-01-19 23:09:00 -050073 return complex(r, r)
Charles L. Dorian2e90f662010-04-05 22:10:27 -070074 }
75 a := real(x)
76 b := imag(x)
77 var scale float64
78 // Rescale to avoid internal overflow or underflow.
Rob Pike1a13f9b2011-09-29 09:54:20 -070079 if math.Abs(a) > 4 || math.Abs(b) > 4 {
Charles L. Dorian2e90f662010-04-05 22:10:27 -070080 a *= 0.25
81 b *= 0.25
82 scale = 2
83 } else {
Charles L. Dorian9b1d6332010-04-09 14:37:26 -070084 a *= 1.8014398509481984e16 // 2**54
Charles L. Dorian2e90f662010-04-05 22:10:27 -070085 b *= 1.8014398509481984e16
Charles L. Dorian9b1d6332010-04-09 14:37:26 -070086 scale = 7.450580596923828125e-9 // 2**-27
Charles L. Dorian2e90f662010-04-05 22:10:27 -070087 }
88 r := math.Hypot(a, b)
89 var t float64
90 if a > 0 {
91 t = math.Sqrt(0.5*r + 0.5*a)
Rob Pike1a13f9b2011-09-29 09:54:20 -070092 r = scale * math.Abs((0.5*b)/t)
Charles L. Dorian2e90f662010-04-05 22:10:27 -070093 t *= scale
94 } else {
95 r = math.Sqrt(0.5*r - 0.5*a)
Rob Pike1a13f9b2011-09-29 09:54:20 -070096 t = scale * math.Abs((0.5*b)/r)
Charles L. Dorian2e90f662010-04-05 22:10:27 -070097 r *= scale
98 }
99 if b < 0 {
Russ Coxf2b5a072011-01-19 23:09:00 -0500100 return complex(t, -r)
Charles L. Dorian2e90f662010-04-05 22:10:27 -0700101 }
Russ Coxf2b5a072011-01-19 23:09:00 -0500102 return complex(t, r)
Charles L. Dorian2e90f662010-04-05 22:10:27 -0700103}