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  }