Skip to content

Commit

Permalink
roots: first import of a roots-finding package
Browse files Browse the repository at this point in the history
  • Loading branch information
sbinet committed Dec 1, 2020
1 parent 842da9a commit bca99b6
Show file tree
Hide file tree
Showing 5 changed files with 474 additions and 13 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ go 1.13

require (
github.com/hanwen/go-fuse v1.0.0
go-hep.org/x/hep v0.27.1-0.20200619125459-ebbd2a74fca6
go-hep.org/x/hep v0.28.3
gonum.org/v1/gonum v0.8.1
)
14 changes: 2 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/ajstarks/svgo v0.0.0-20190826172357-de52242f3d65 h1:kZegOsPGxfV9mM8WzfllNZOx3MvM5zItmhQlvITKVvA=
github.com/ajstarks/svgo v0.0.0-20190826172357-de52242f3d65/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca h1:kWzLcty5V2rzOqJM7Tp/MfSX0RMSI1x4IOLApEefYxA=
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
Expand Down Expand Up @@ -56,19 +55,16 @@ github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.1.1 h1:O2qnKspkpcKx1RKbm7m0NhTjyTP436kYUqGes56qwiQ=
github.com/jcmturner/gokrb5/v8 v8.1.1/go.mod h1:T1hnNppQsBtxW0tCHMHTkAt8n/sABdzZgZdoFrZaZNM=
github.com/jcmturner/gokrb5/v8 v8.4.0 h1:YhIMzzOSd/9kE5+SahL3m8ygGWE6cB1lKKYYEqpo1hc=
github.com/jcmturner/gokrb5/v8 v8.4.0/go.mod h1:T1hnNppQsBtxW0tCHMHTkAt8n/sABdzZgZdoFrZaZNM=
github.com/jcmturner/rpc/v2 v2.0.2 h1:gMB4IwRXYsWw4Bc6o/az2HJgFUA1ffSh90i26ZJ6Xl0=
github.com/jcmturner/rpc/v2 v2.0.2/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.12.6 h1:uKuWANXSGphk+YcJQe8Aoi7mRo7yDDXcX+OmxcYhap4=
github.com/jung-kurt/gofpdf v1.12.6/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0=
github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc=
github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0=
github.com/klauspost/compress v1.10.2 h1:Znfn6hXZAHaLPNnlqUYRrBSReFHYybslgv4PTiyz6P0=
github.com/klauspost/compress v1.10.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.7 h1:7rix8v8GpI3ZBb0nSozFRgbtXKv+hOe+qfEpZqybrAg=
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
Expand Down Expand Up @@ -114,7 +110,6 @@ go-hep.org/x/exp v0.3.0/go.mod h1:j7kUcLWPIO1Qb+yoWtOuYSqpnN1JsZE0LqDD9yDJOnI=
go-hep.org/x/exp v0.4.0/go.mod h1:eo+NW3dHsADQnqP4Rt3gnelmjVKPngV68+ku0fBImXQ=
go-hep.org/x/exp v0.5.0/go.mod h1:KDxj3uk3sU6NqrrTFR5RuxexPvBE74o+c4lbc+WMQLY=
go-hep.org/x/hep v0.21.0/go.mod h1:gbp4SbxCTtqu91WY/OsD+1bK0W3gpQqEt1IVQLjiMn4=
go-hep.org/x/hep v0.23.1 h1:0YfZHawi8DjhCapdhM77NkNj8M1S0wSlU5/chiMCe4g=
go-hep.org/x/hep v0.23.1/go.mod h1:+/LhRnY/keU6GBS0mbgpFvH3LNOOHQXZ5csL0pnMets=
go-hep.org/x/hep v0.27.1-0.20200619125459-ebbd2a74fca6 h1:IYM25cUylTKxmonEHjT/cMu0mS8aV0CwIFW5xKHaiSI=
go-hep.org/x/hep v0.27.1-0.20200619125459-ebbd2a74fca6/go.mod h1:5zQ24HB6aslu6qqYjz6P3Ouf55DuqzKo5r0A02OOHas=
Expand All @@ -140,7 +135,6 @@ golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86h
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
Expand All @@ -149,7 +143,6 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc
golang.org/x/mobile v0.0.0-20191002175909-6d0d39b2ca82/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
golang.org/x/mobile v0.0.0-20191031020345-0945064e013a/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
golang.org/x/mobile v0.0.0-20191210151939-1a1fef82734d/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
golang.org/x/mobile v0.0.0-20200222142934-3c8601c510d0 h1:nZASbxDuz7CO3227BWCCf0MC6ynyvKh6eMDoLcNXAk0=
golang.org/x/mobile v0.0.0-20200222142934-3c8601c510d0/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
Expand All @@ -162,7 +155,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191011234655-491137f69257/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCTu3mcIURZfNkVweuRKA=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
Expand All @@ -186,7 +178,6 @@ golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa h1:5E4dL8+NgFOgjwbTKz+OOEGGhP+ectTmF842l6KjupQ=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200507050207-a1532b81a28f h1:8vKMSP2LYgBjfB4WCpdfkW5sK5C9eDWguFX9xhqSN2U=
golang.org/x/tools v0.0.0-20200507050207-a1532b81a28f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
Expand All @@ -199,18 +190,17 @@ gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJ
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/gonum v0.0.0-20191013192725-1459092b91f2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
gonum.org/v1/gonum v0.6.1/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
gonum.org/v1/gonum v0.7.0 h1:Hdks0L0hgznZLG9nzXb8vZ0rRvqNvAcgAp84y7Mwkgw=
gonum.org/v1/gonum v0.7.0/go.mod h1:L02bwd0sqlsvRv41G7wGWFCsVNZFv/k1xzGIxeANHGM=
gonum.org/v1/gonum v0.7.1-0.20200602002949-4ff1bb0a480e h1:59R5OJD3msBCNQ2GujO0levDKSwYW6sXT1OxsFsnVfU=
gonum.org/v1/gonum v0.7.1-0.20200602002949-4ff1bb0a480e/go.mod h1:L02bwd0sqlsvRv41G7wGWFCsVNZFv/k1xzGIxeANHGM=
gonum.org/v1/gonum v0.8.1 h1:wGtP3yGpc5mCLOLeTeBdjeui9oZSz5De0eOjMLC/QuQ=
gonum.org/v1/gonum v0.8.1/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
gonum.org/v1/netlib v0.0.0-20180816165226-ebcc3d2662d3/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
gonum.org/v1/plot v0.0.0-20191004082913-159cd04f920c/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
gonum.org/v1/plot v0.0.0-20191107103940-ca91d9d40d0a/go.mod h1:2EC9bQmADoXz4qWOuiPhNNky9U7T8rgIULcW8j/muig=
gonum.org/v1/plot v0.7.0 h1:Otpxyvra6Ie07ft50OX5BrCfS/BWEMvhsCUHwPEJmLI=
gonum.org/v1/plot v0.7.0/go.mod h1:2wtU6YrrdQAhAF9+MTd5tOQjrov/zF70b1i99Npjvgo=
gonum.org/v1/plot v0.7.1-0.20200602093449-6d232e045386 h1:OaEl2Ntk8g56oPNkmQfRyXQN4fgAjYpXQlNunEZrx/k=
gonum.org/v1/plot v0.7.1-0.20200602093449-6d232e045386/go.mod h1:yGbCJMcwFiouE6IEpRGTW4gkKr8zMOKkS13yvgTbA0Y=
Expand Down
6 changes: 6 additions & 0 deletions roots/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright ©2020 The go-hep Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package roots implements algorithms for finding roots of functions.
package roots // import "go-hep.org/x/exp/roots"
282 changes: 282 additions & 0 deletions roots/poly.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
// Copyright ©2020 The go-hep Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package roots

import (
"math"
"math/cmplx"
"sort"
)

// Polynomial returns the roots of an n-th degree polynomial of the form:
// p[0] * x**n + p[1] * x**(n-1) + ... + p[n-1]*x + p[n]
func Polynomial(dst []complex128, ps []float64) []complex128 {
n := len(ps) - 1
if dst == nil {
dst = make([]complex128, n)
}
if len(dst) != n {
panic("roots: length mismatch")
}

for _, v := range ps {
if v != 0 {
break
}
n--
}
dst = dst[:n]

ps = ps[len(ps)-1-n:]

switch n {
case 0:
return dst

case 1:
a := ps[0]
b := ps[1]
if a == 0 {
return dst
}
r := -b / a
dst[0] = complex(r, 0)
return dst

case 2:
dst[0], dst[1] = Poly2(ps[0], ps[1], ps[2])
return dst

case 3:
dst[0], dst[1], dst[2] = Poly3(ps[0], ps[1], ps[2], ps[3])
return dst

case 4:
dst[0], dst[1], dst[2], dst[3] = Poly4(ps[0], ps[1], ps[2], ps[3], ps[4])
return dst

default:
panic("not implemented")
}

sortCmplx(dst)
return dst
}

func sortCmplx(xs []complex128) {
sort.Slice(xs, func(i, j int) bool {
return min128(xs[i], xs[j])
})
}

func min128(zi, zj complex128) bool {
ri := real(zi)
rj := real(zj)
if ri == rj {
ii := imag(zi)
ij := imag(zj)
return ii < ij
}
return ri < rj
}

// Poly2 returns the roots of the following 2nd degree polynomial:
// p0 x^2 + p1 x + p2 = 0
func Poly2(p0, p1, p2 float64) (z0, z1 complex128) {
// reduce to: x^2 + a.x + b = 0
norm := 1 / p0
b := p2 * norm
a := p1 * norm

ha := -0.5 * a
delta := cmplx.Sqrt(complex(ha*ha-b, 0))
z0 = complex(ha, 0) + delta
z1 = complex(ha, 0) - delta
if min128(z0, z1) {
return z0, z1
}
return z1, z0
}

// Poly3 returns the roots of the following 3rd degree polynomial:
// p0 x^3 + p1 x^2 + p2 x + p3 = 0
func Poly3(p0, p1, p2, p3 float64) (z0, z1, z2 complex128) {
// use Cardano/Tartaglia/Vieta formulae.
// see:
// https://en.wikipedia.org/wiki/Cubic_equation#Cardano's_formula
// https://trans4mind.com/personal_development/mathematics/polynomials/cubicAlgebra.htm

// reduce to monic form.
// x^3 + ax^2 + bx + c = 0
ip := 1 / p0
a := p1 * ip
b := p2 * ip
c := p3 * ip

const (
k3 = 1 / 3.0
k27 = 1 / 27.0
)
a2 := a * a
p := k3 * (3*b - a2)
q := k27 * (2*a2*a - 9*a*b + 27*c)

if p == 0 && q == 0 {
x := complex(-a*k3, 0)
return x, x, x
}

Δ := 0.25*(q*q) + (p*p*p)*k27

const ε = 1e-15
switch {
case Δ == 0, math.Abs(Δ) < ε:
cbrt := math.Cbrt(0.5 * q)
x0 := complex(-2*cbrt-a*k3, 0)
x1 := complex(+1*cbrt-a*k3, 0)

if real(x0) < real(x1) {
return x0, x1, x1
}
return x1, x1, x0

case Δ > ε:
sq := math.Sqrt(Δ)
hq := 0.5 * q
u1 := math.Cbrt(-hq + sq)
v1 := math.Cbrt(+hq + sq)
re := -0.5*(u1-v1) - a*k3
im := +0.5 * (u1 + v1) * math.Sqrt(3)

zs := [3]complex128{
complex(u1-v1-a*k3, 0),
complex(re, +im),
complex(re, -im),
}
sortCmplx(zs[:])
return zs[0], zs[1], zs[2]

case Δ < ε:
pp := -p / 3
r := math.Sqrt(pp * pp * pp)
θ := math.Acos(-0.5 * q / r)
math.Cos(θ * k3)

r3 := 2 * math.Cbrt(r)
zs := [3]complex128{
complex(r3*math.Cos(θ*k3)-a*k3, 0),
complex(r3*math.Cos((θ+2*math.Pi)*k3)-a*k3, 0),
complex(r3*math.Cos((θ+4*math.Pi)*k3)-a*k3, 0),
}
sortCmplx(zs[:])
return zs[0], zs[1], zs[2]
}
panic("impossible")
}

// Poly4 returns the roots of the following 4th degree polynomial:
// p0 x^4 + p1 x^3 + p2 x^2 + p3 x + p4 = 0
func Poly4(p0, p1, p2, p3, p4 float64) (z0, z1, z2, z3 complex128) {
// https://en.wikipedia.org/wiki/Quartic_function
// https://doi.org/10.1016/j.cam.2010.04.015

// reduce to monic form.
// x^4 + ax^3 + bx^2 + cx + d = 0
ip := 1 / p0
a := p1 * ip
b := p2 * ip
c := p3 * ip
d := p4 * ip

// handle degenerate cases.
if b == 0 && c == 0 {
// x^4 + ax^3 + d = 0
switch {
case d == 0:
// x^4 + ax^3 = 0
if a > 0 {
z0 = complex(-a, 0)
} else {
z3 = complex(-a, 0)
}
return z0, z1, z2, z3
case a == 0:
// x^4 + d = 0
if d > 0 {
z3 = cmplx.Sqrt(complex(math.Sqrt(d), 0) * complex(0, 1))
z2 = complex(0, -1) * z3
z1 = complex(-real(z2), -imag(z2))
z0 = complex(-real(z3), -imag(z3))
} else {
z3 = cmplx.Sqrt(complex(math.Sqrt(-d), 0))
z2 = z3 * complex(0, 1)
z1 = complex(-real(z2), -imag(z2))
z0 = complex(-real(z3), -imag(z3))
}
return z0, z1, z2, z3
}
}

if c == 0 && d == 0 {
// x^4 + ax^3 + bx^2 = 0
var zs [4]complex128
zs[0], zs[1] = Poly2(1, a, b)
sortCmplx(zs[:])
return zs[0], zs[1], zs[2], zs[3]
}

// construct and solve cubic resolvent.
// y^3 + A y^2 + B y + C = 0
a2 := a * a
ya := -b
yb := c*a - 4*d
yc := 4*b*d - c*c - a2*d
y1, y2, y3 := Poly3(1, ya, yb, yc)
var y float64
switch {
case imag(y1) == 0:
y = real(y1)
case imag(y2) == 0:
y = real(y2)
case imag(y3) == 0:
y = real(y3)
}

var (
R = cmplx.Sqrt(complex(0.25*a2-b+y, 0))

f = complex(0.75*a2-2*b, 0)
g = 2 * cmplx.Sqrt(complex(y*y-4*d, 0))

D complex128
E complex128
)

switch {
case R == 0:
D = cmplx.Sqrt(f + g)
E = cmplx.Sqrt(f - g)
default:
h := complex(0.25*(4*a*b-8*c-a*a2), 0) / R
r := R * R
D = cmplx.Sqrt(f - r + h)
E = cmplx.Sqrt(f - r - h)
}

rr := 0.5 * R
dd := 0.5 * D
ee := 0.5 * E
za := 0.25 * complex(a, 0)

var zs [4]complex128

zs[0] = -za + rr + dd
zs[1] = -za + rr - dd
zs[2] = -za - rr + ee
zs[3] = -za - rr - ee

sortCmplx(zs[:])
return zs[0], zs[1], zs[2], zs[3]
}
Loading

0 comments on commit bca99b6

Please sign in to comment.