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.
9 // Dlags2 computes 2-by-2 orthogonal matrices U, V and Q with the
10 // triangles of A and B specified by upper.
14 // U^T*A*Q = U^T*[ a1 a2 ]*Q = [ x 0 ]
17 // V^T*B*Q = V^T*[ b1 b2 ]*Q = [ x 0 ]
22 // U^T*A*Q = U^T*[ a1 0 ]*Q = [ x x ]
25 // V^T*B*Q = V^T*[ b1 0 ]*Q = [ x x ]
28 // The rows of the transformed A and B are parallel, where
30 // U = [ csu snu ], V = [ csv snv ], Q = [ csq snq ]
31 // [ -snu csu ] [ -snv csv ] [ -snq csq ]
33 // Dlags2 is an internal routine. It is exported for testing purposes.
34 func (impl Implementation) Dlags2(upper bool, a1, a2, a3, b1, b2, b3 float64) (csu, snu, csv, snv, csq, snq float64) {
36 // Input matrices A and B are upper triangular matrices.
38 // Form matrix C = A*adj(B) = [ a b ]
44 // The SVD of real 2-by-2 triangular C.
46 // [ csl -snl ]*[ a b ]*[ csr snr ] = [ r 0 ]
47 // [ snl csl ] [ 0 d ] [ -snr csr ] [ 0 t ]
48 _, _, snr, csr, snl, csl := impl.Dlasv2(a, b, d)
50 if math.Abs(csl) >= math.Abs(snl) || math.Abs(csr) >= math.Abs(snr) {
51 // Compute the [0, 0] and [0, 1] elements of U^T*A and V^T*B,
52 // and [0, 1] element of |U|^T*|A| and |V|^T*|B|.
55 ua12 := csl*a2 + snl*a3
58 vb12 := csr*b2 + snr*b3
60 aua12 := math.Abs(csl)*math.Abs(a2) + math.Abs(snl)*math.Abs(a3)
61 avb12 := math.Abs(csr)*math.Abs(b2) + math.Abs(snr)*math.Abs(b3)
63 // Zero [0, 1] elements of U^T*A and V^T*B.
64 if math.Abs(ua11r)+math.Abs(ua12) != 0 {
65 if aua12/(math.Abs(ua11r)+math.Abs(ua12)) <= avb12/(math.Abs(vb11r)+math.Abs(vb12)) {
66 csq, snq, _ = impl.Dlartg(-ua11r, ua12)
68 csq, snq, _ = impl.Dlartg(-vb11r, vb12)
71 csq, snq, _ = impl.Dlartg(-vb11r, vb12)
79 // Compute the [1, 0] and [1, 1] elements of U^T*A and V^T*B,
80 // and [1, 1] element of |U|^T*|A| and |V|^T*|B|.
83 ua22 := -snl*a2 + csl*a3
86 vb22 := -snr*b2 + csr*b3
88 aua22 := math.Abs(snl)*math.Abs(a2) + math.Abs(csl)*math.Abs(a3)
89 avb22 := math.Abs(snr)*math.Abs(b2) + math.Abs(csr)*math.Abs(b3)
91 // Zero [1, 1] elements of U^T*A and V^T*B, and then swap.
92 if math.Abs(ua21)+math.Abs(ua22) != 0 {
93 if aua22/(math.Abs(ua21)+math.Abs(ua22)) <= avb22/(math.Abs(vb21)+math.Abs(vb22)) {
94 csq, snq, _ = impl.Dlartg(-ua21, ua22)
96 csq, snq, _ = impl.Dlartg(-vb21, vb22)
99 csq, snq, _ = impl.Dlartg(-vb21, vb22)
108 // Input matrices A and B are lower triangular matrices
110 // Form matrix C = A*adj(B) = [ a 0 ]
116 // The SVD of real 2-by-2 triangular C
118 // [ csl -snl ]*[ a 0 ]*[ csr snr ] = [ r 0 ]
119 // [ snl csl ] [ c d ] [ -snr csr ] [ 0 t ]
120 _, _, snr, csr, snl, csl := impl.Dlasv2(a, c, d)
122 if math.Abs(csr) >= math.Abs(snr) || math.Abs(csl) >= math.Abs(snl) {
123 // Compute the [1, 0] and [1, 1] elements of U^T*A and V^T*B,
124 // and [1, 0] element of |U|^T*|A| and |V|^T*|B|.
126 ua21 := -snr*a1 + csr*a2
129 vb21 := -snl*b1 + csl*b2
132 aua21 := math.Abs(snr)*math.Abs(a1) + math.Abs(csr)*math.Abs(a2)
133 avb21 := math.Abs(snl)*math.Abs(b1) + math.Abs(csl)*math.Abs(b2)
135 // Zero [1, 0] elements of U^T*A and V^T*B.
136 if (math.Abs(ua21) + math.Abs(ua22r)) != 0 {
137 if aua21/(math.Abs(ua21)+math.Abs(ua22r)) <= avb21/(math.Abs(vb21)+math.Abs(vb22r)) {
138 csq, snq, _ = impl.Dlartg(ua22r, ua21)
140 csq, snq, _ = impl.Dlartg(vb22r, vb21)
143 csq, snq, _ = impl.Dlartg(vb22r, vb21)
151 // Compute the [0, 0] and [0, 1] elements of U^T *A and V^T *B,
152 // and [0, 0] element of |U|^T*|A| and |V|^T*|B|.
154 ua11 := csr*a1 + snr*a2
157 vb11 := csl*b1 + snl*b2
160 aua11 := math.Abs(csr)*math.Abs(a1) + math.Abs(snr)*math.Abs(a2)
161 avb11 := math.Abs(csl)*math.Abs(b1) + math.Abs(snl)*math.Abs(b2)
163 // Zero [0, 0] elements of U^T*A and V^T*B, and then swap.
164 if (math.Abs(ua11) + math.Abs(ua12)) != 0 {
165 if aua11/(math.Abs(ua11)+math.Abs(ua12)) <= avb11/(math.Abs(vb11)+math.Abs(vb12)) {
166 csq, snq, _ = impl.Dlartg(ua12, ua11)
168 csq, snq, _ = impl.Dlartg(vb12, vb11)
171 csq, snq, _ = impl.Dlartg(vb12, vb11)
181 return csu, snu, csv, snv, csq, snq