gonum.org/v1/gonum@v0.14.0/lapack/gonum/dlags2.go (about) 1 // Copyright ©2017 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 // Dlags2 computes 2-by-2 orthogonal matrices U, V and Q with the 10 // triangles of A and B specified by upper. 11 // 12 // If upper is true 13 // 14 // Uᵀ*A*Q = Uᵀ*[ a1 a2 ]*Q = [ x 0 ] 15 // [ 0 a3 ] [ x x ] 16 // 17 // and 18 // 19 // Vᵀ*B*Q = Vᵀ*[ b1 b2 ]*Q = [ x 0 ] 20 // [ 0 b3 ] [ x x ] 21 // 22 // otherwise 23 // 24 // Uᵀ*A*Q = Uᵀ*[ a1 0 ]*Q = [ x x ] 25 // [ a2 a3 ] [ 0 x ] 26 // 27 // and 28 // 29 // Vᵀ*B*Q = Vᵀ*[ b1 0 ]*Q = [ x x ] 30 // [ b2 b3 ] [ 0 x ]. 31 // 32 // The rows of the transformed A and B are parallel, where 33 // 34 // U = [ csu snu ], V = [ csv snv ], Q = [ csq snq ] 35 // [ -snu csu ] [ -snv csv ] [ -snq csq ] 36 // 37 // Dlags2 is an internal routine. It is exported for testing purposes. 38 func (impl Implementation) Dlags2(upper bool, a1, a2, a3, b1, b2, b3 float64) (csu, snu, csv, snv, csq, snq float64) { 39 if upper { 40 // Input matrices A and B are upper triangular matrices. 41 // 42 // Form matrix C = A*adj(B) = [ a b ] 43 // [ 0 d ] 44 a := a1 * b3 45 d := a3 * b1 46 b := a2*b1 - a1*b2 47 48 // The SVD of real 2-by-2 triangular C. 49 // 50 // [ csl -snl ]*[ a b ]*[ csr snr ] = [ r 0 ] 51 // [ snl csl ] [ 0 d ] [ -snr csr ] [ 0 t ] 52 _, _, snr, csr, snl, csl := impl.Dlasv2(a, b, d) 53 54 if math.Abs(csl) >= math.Abs(snl) || math.Abs(csr) >= math.Abs(snr) { 55 // Compute the [0, 0] and [0, 1] elements of Uᵀ*A and Vᵀ*B, 56 // and [0, 1] element of |U|ᵀ*|A| and |V|ᵀ*|B|. 57 58 ua11r := csl * a1 59 ua12 := csl*a2 + snl*a3 60 61 vb11r := csr * b1 62 vb12 := csr*b2 + snr*b3 63 64 aua12 := math.Abs(csl)*math.Abs(a2) + math.Abs(snl)*math.Abs(a3) 65 avb12 := math.Abs(csr)*math.Abs(b2) + math.Abs(snr)*math.Abs(b3) 66 67 // Zero [0, 1] elements of Uᵀ*A and Vᵀ*B. 68 if math.Abs(ua11r)+math.Abs(ua12) != 0 { 69 if aua12/(math.Abs(ua11r)+math.Abs(ua12)) <= avb12/(math.Abs(vb11r)+math.Abs(vb12)) { 70 csq, snq, _ = impl.Dlartg(-ua11r, ua12) 71 } else { 72 csq, snq, _ = impl.Dlartg(-vb11r, vb12) 73 } 74 } else { 75 csq, snq, _ = impl.Dlartg(-vb11r, vb12) 76 } 77 78 csu = csl 79 snu = -snl 80 csv = csr 81 snv = -snr 82 } else { 83 // Compute the [1, 0] and [1, 1] elements of Uᵀ*A and Vᵀ*B, 84 // and [1, 1] element of |U|ᵀ*|A| and |V|ᵀ*|B|. 85 86 ua21 := -snl * a1 87 ua22 := -snl*a2 + csl*a3 88 89 vb21 := -snr * b1 90 vb22 := -snr*b2 + csr*b3 91 92 aua22 := math.Abs(snl)*math.Abs(a2) + math.Abs(csl)*math.Abs(a3) 93 avb22 := math.Abs(snr)*math.Abs(b2) + math.Abs(csr)*math.Abs(b3) 94 95 // Zero [1, 1] elements of Uᵀ*A and Vᵀ*B, and then swap. 96 if math.Abs(ua21)+math.Abs(ua22) != 0 { 97 if aua22/(math.Abs(ua21)+math.Abs(ua22)) <= avb22/(math.Abs(vb21)+math.Abs(vb22)) { 98 csq, snq, _ = impl.Dlartg(-ua21, ua22) 99 } else { 100 csq, snq, _ = impl.Dlartg(-vb21, vb22) 101 } 102 } else { 103 csq, snq, _ = impl.Dlartg(-vb21, vb22) 104 } 105 106 csu = snl 107 snu = csl 108 csv = snr 109 snv = csr 110 } 111 } else { 112 // Input matrices A and B are lower triangular matrices 113 // 114 // Form matrix C = A*adj(B) = [ a 0 ] 115 // [ c d ] 116 a := a1 * b3 117 d := a3 * b1 118 c := a2*b3 - a3*b2 119 120 // The SVD of real 2-by-2 triangular C 121 // 122 // [ csl -snl ]*[ a 0 ]*[ csr snr ] = [ r 0 ] 123 // [ snl csl ] [ c d ] [ -snr csr ] [ 0 t ] 124 _, _, snr, csr, snl, csl := impl.Dlasv2(a, c, d) 125 126 if math.Abs(csr) >= math.Abs(snr) || math.Abs(csl) >= math.Abs(snl) { 127 // Compute the [1, 0] and [1, 1] elements of Uᵀ*A and Vᵀ*B, 128 // and [1, 0] element of |U|ᵀ*|A| and |V|ᵀ*|B|. 129 130 ua21 := -snr*a1 + csr*a2 131 ua22r := csr * a3 132 133 vb21 := -snl*b1 + csl*b2 134 vb22r := csl * b3 135 136 aua21 := math.Abs(snr)*math.Abs(a1) + math.Abs(csr)*math.Abs(a2) 137 avb21 := math.Abs(snl)*math.Abs(b1) + math.Abs(csl)*math.Abs(b2) 138 139 // Zero [1, 0] elements of Uᵀ*A and Vᵀ*B. 140 if (math.Abs(ua21) + math.Abs(ua22r)) != 0 { 141 if aua21/(math.Abs(ua21)+math.Abs(ua22r)) <= avb21/(math.Abs(vb21)+math.Abs(vb22r)) { 142 csq, snq, _ = impl.Dlartg(ua22r, ua21) 143 } else { 144 csq, snq, _ = impl.Dlartg(vb22r, vb21) 145 } 146 } else { 147 csq, snq, _ = impl.Dlartg(vb22r, vb21) 148 } 149 150 csu = csr 151 snu = -snr 152 csv = csl 153 snv = -snl 154 } else { 155 // Compute the [0, 0] and [0, 1] elements of Uᵀ *A and Vᵀ *B, 156 // and [0, 0] element of |U|ᵀ*|A| and |V|ᵀ*|B|. 157 158 ua11 := csr*a1 + snr*a2 159 ua12 := snr * a3 160 161 vb11 := csl*b1 + snl*b2 162 vb12 := snl * b3 163 164 aua11 := math.Abs(csr)*math.Abs(a1) + math.Abs(snr)*math.Abs(a2) 165 avb11 := math.Abs(csl)*math.Abs(b1) + math.Abs(snl)*math.Abs(b2) 166 167 // Zero [0, 0] elements of Uᵀ*A and Vᵀ*B, and then swap. 168 if (math.Abs(ua11) + math.Abs(ua12)) != 0 { 169 if aua11/(math.Abs(ua11)+math.Abs(ua12)) <= avb11/(math.Abs(vb11)+math.Abs(vb12)) { 170 csq, snq, _ = impl.Dlartg(ua12, ua11) 171 } else { 172 csq, snq, _ = impl.Dlartg(vb12, vb11) 173 } 174 } else { 175 csq, snq, _ = impl.Dlartg(vb12, vb11) 176 } 177 178 csu = snr 179 snu = csr 180 csv = snl 181 snv = csl 182 } 183 } 184 185 return csu, snu, csv, snv, csq, snq 186 }