github.com/gopherd/gonum@v0.0.4/lapack/gonum/dlartg.go (about) 1 // Copyright ©2015 The Gonum 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 5 package gonum 6 7 import "math" 8 9 // Dlartg generates a plane rotation so that 10 // [ cs sn] * [f] = [r] 11 // [-sn cs] [g] = [0] 12 // where cs*cs + sn*sn = 1. 13 // 14 // This is a more accurate version of BLAS Drotg, with the other differences 15 // that 16 // - if g = 0, then cs = 1 and sn = 0 17 // - if f = 0 and g != 0, then cs = 0 and sn = 1 18 // - r takes the sign of f and so cs is always non-negative 19 // 20 // Dlartg is an internal routine. It is exported for testing purposes. 21 func (impl Implementation) Dlartg(f, g float64) (cs, sn, r float64) { 22 // Implementation based on Supplemental Material to: 23 // Edward Anderson. 2017. Algorithm 978: Safe Scaling in the Level 1 BLAS. 24 // ACM Trans. Math. Softw. 44, 1, Article 12 (July 2017), 28 pages. 25 // DOI: https://doi.org/10.1145/3061665 26 const safmin = dlamchS 27 const safmax = 1 / safmin 28 f1 := math.Abs(f) 29 g1 := math.Abs(g) 30 switch { 31 case g == 0: 32 cs = 1 33 sn = 0 34 r = f 35 case f == 0: 36 cs = 0 37 sn = math.Copysign(1, g) 38 r = g1 39 case drtmin < f1 && f1 < drtmax && drtmin < g1 && g1 < drtmax: 40 d := math.Sqrt(f*f + g*g) 41 p := 1 / d 42 cs = f1 * p 43 sn = g * math.Copysign(p, f) 44 r = math.Copysign(d, f) 45 default: 46 maxfg := math.Max(f1, g1) 47 u := math.Min(math.Max(safmin, maxfg), safmax) 48 uu := 1 / u 49 fs := f * uu 50 gs := g * uu 51 d := math.Sqrt(fs*fs + gs*gs) 52 p := 1 / d 53 cs = math.Abs(fs) * p 54 sn = gs * math.Copysign(p, f) 55 r = math.Copysign(d, f) * u 56 } 57 return cs, sn, r 58 }