gonum.org/v1/gonum@v0.14.0/lapack/gonum/dlasr.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 (
     8  	"gonum.org/v1/gonum/blas"
     9  	"gonum.org/v1/gonum/lapack"
    10  )
    11  
    12  // Dlasr applies a sequence of plane rotations to the m×n matrix A. This series
    13  // of plane rotations is implicitly represented by a matrix P. P is multiplied
    14  // by a depending on the value of side -- A = P * A if side == lapack.Left,
    15  // A = A * Pᵀ if side == lapack.Right.
    16  //
    17  // The exact value of P depends on the value of pivot, but in all cases P is
    18  // implicitly represented by a series of 2×2 rotation matrices. The entries of
    19  // rotation matrix k are defined by s[k] and c[k]
    20  //
    21  //	R(k) = [ c[k] s[k]]
    22  //	       [-s[k] s[k]]
    23  //
    24  // If direct == lapack.Forward, the rotation matrices are applied as
    25  // P = P(z-1) * ... * P(2) * P(1), while if direct == lapack.Backward they are
    26  // applied as P = P(1) * P(2) * ... * P(n).
    27  //
    28  // pivot defines the mapping of the elements in R(k) to P(k).
    29  // If pivot == lapack.Variable, the rotation is performed for the (k, k+1) plane.
    30  //
    31  //	P(k) = [1                    ]
    32  //	       [    ...              ]
    33  //	       [     1               ]
    34  //	       [       c[k] s[k]     ]
    35  //	       [      -s[k] c[k]     ]
    36  //	       [                 1   ]
    37  //	       [                ...  ]
    38  //	       [                    1]
    39  //
    40  // if pivot == lapack.Top, the rotation is performed for the (1, k+1) plane,
    41  //
    42  //	P(k) = [c[k]        s[k]     ]
    43  //	       [    1                ]
    44  //	       [     ...             ]
    45  //	       [         1           ]
    46  //	       [-s[k]       c[k]     ]
    47  //	       [                 1   ]
    48  //	       [                ...  ]
    49  //	       [                    1]
    50  //
    51  // and if pivot == lapack.Bottom, the rotation is performed for the (k, z) plane.
    52  //
    53  //	P(k) = [1                    ]
    54  //	       [  ...                ]
    55  //	       [      1              ]
    56  //	       [        c[k]     s[k]]
    57  //	       [           1         ]
    58  //	       [            ...      ]
    59  //	       [              1      ]
    60  //	       [       -s[k]     c[k]]
    61  //
    62  // s and c have length m - 1 if side == blas.Left, and n - 1 if side == blas.Right.
    63  //
    64  // Dlasr is an internal routine. It is exported for testing purposes.
    65  func (impl Implementation) Dlasr(side blas.Side, pivot lapack.Pivot, direct lapack.Direct, m, n int, c, s, a []float64, lda int) {
    66  	switch {
    67  	case side != blas.Left && side != blas.Right:
    68  		panic(badSide)
    69  	case pivot != lapack.Variable && pivot != lapack.Top && pivot != lapack.Bottom:
    70  		panic(badPivot)
    71  	case direct != lapack.Forward && direct != lapack.Backward:
    72  		panic(badDirect)
    73  	case m < 0:
    74  		panic(mLT0)
    75  	case n < 0:
    76  		panic(nLT0)
    77  	case lda < max(1, n):
    78  		panic(badLdA)
    79  	}
    80  
    81  	// Quick return if possible.
    82  	if m == 0 || n == 0 {
    83  		return
    84  	}
    85  
    86  	if side == blas.Left {
    87  		if len(c) < m-1 {
    88  			panic(shortC)
    89  		}
    90  		if len(s) < m-1 {
    91  			panic(shortS)
    92  		}
    93  	} else {
    94  		if len(c) < n-1 {
    95  			panic(shortC)
    96  		}
    97  		if len(s) < n-1 {
    98  			panic(shortS)
    99  		}
   100  	}
   101  	if len(a) < (m-1)*lda+n {
   102  		panic(shortA)
   103  	}
   104  
   105  	if side == blas.Left {
   106  		if pivot == lapack.Variable {
   107  			if direct == lapack.Forward {
   108  				for j := 0; j < m-1; j++ {
   109  					ctmp := c[j]
   110  					stmp := s[j]
   111  					if ctmp != 1 || stmp != 0 {
   112  						for i := 0; i < n; i++ {
   113  							tmp2 := a[j*lda+i]
   114  							tmp := a[(j+1)*lda+i]
   115  							a[(j+1)*lda+i] = ctmp*tmp - stmp*tmp2
   116  							a[j*lda+i] = stmp*tmp + ctmp*tmp2
   117  						}
   118  					}
   119  				}
   120  				return
   121  			}
   122  			for j := m - 2; j >= 0; j-- {
   123  				ctmp := c[j]
   124  				stmp := s[j]
   125  				if ctmp != 1 || stmp != 0 {
   126  					for i := 0; i < n; i++ {
   127  						tmp2 := a[j*lda+i]
   128  						tmp := a[(j+1)*lda+i]
   129  						a[(j+1)*lda+i] = ctmp*tmp - stmp*tmp2
   130  						a[j*lda+i] = stmp*tmp + ctmp*tmp2
   131  					}
   132  				}
   133  			}
   134  			return
   135  		} else if pivot == lapack.Top {
   136  			if direct == lapack.Forward {
   137  				for j := 1; j < m; j++ {
   138  					ctmp := c[j-1]
   139  					stmp := s[j-1]
   140  					if ctmp != 1 || stmp != 0 {
   141  						for i := 0; i < n; i++ {
   142  							tmp := a[j*lda+i]
   143  							tmp2 := a[i]
   144  							a[j*lda+i] = ctmp*tmp - stmp*tmp2
   145  							a[i] = stmp*tmp + ctmp*tmp2
   146  						}
   147  					}
   148  				}
   149  				return
   150  			}
   151  			for j := m - 1; j >= 1; j-- {
   152  				ctmp := c[j-1]
   153  				stmp := s[j-1]
   154  				if ctmp != 1 || stmp != 0 {
   155  					for i := 0; i < n; i++ {
   156  						ctmp := c[j-1]
   157  						stmp := s[j-1]
   158  						if ctmp != 1 || stmp != 0 {
   159  							for i := 0; i < n; i++ {
   160  								tmp := a[j*lda+i]
   161  								tmp2 := a[i]
   162  								a[j*lda+i] = ctmp*tmp - stmp*tmp2
   163  								a[i] = stmp*tmp + ctmp*tmp2
   164  							}
   165  						}
   166  					}
   167  				}
   168  			}
   169  			return
   170  		}
   171  		if direct == lapack.Forward {
   172  			for j := 0; j < m-1; j++ {
   173  				ctmp := c[j]
   174  				stmp := s[j]
   175  				if ctmp != 1 || stmp != 0 {
   176  					for i := 0; i < n; i++ {
   177  						tmp := a[j*lda+i]
   178  						tmp2 := a[(m-1)*lda+i]
   179  						a[j*lda+i] = stmp*tmp2 + ctmp*tmp
   180  						a[(m-1)*lda+i] = ctmp*tmp2 - stmp*tmp
   181  					}
   182  				}
   183  			}
   184  			return
   185  		}
   186  		for j := m - 2; j >= 0; j-- {
   187  			ctmp := c[j]
   188  			stmp := s[j]
   189  			if ctmp != 1 || stmp != 0 {
   190  				for i := 0; i < n; i++ {
   191  					tmp := a[j*lda+i]
   192  					tmp2 := a[(m-1)*lda+i]
   193  					a[j*lda+i] = stmp*tmp2 + ctmp*tmp
   194  					a[(m-1)*lda+i] = ctmp*tmp2 - stmp*tmp
   195  				}
   196  			}
   197  		}
   198  		return
   199  	}
   200  	if pivot == lapack.Variable {
   201  		if direct == lapack.Forward {
   202  			for j := 0; j < n-1; j++ {
   203  				ctmp := c[j]
   204  				stmp := s[j]
   205  				if ctmp != 1 || stmp != 0 {
   206  					for i := 0; i < m; i++ {
   207  						tmp := a[i*lda+j+1]
   208  						tmp2 := a[i*lda+j]
   209  						a[i*lda+j+1] = ctmp*tmp - stmp*tmp2
   210  						a[i*lda+j] = stmp*tmp + ctmp*tmp2
   211  					}
   212  				}
   213  			}
   214  			return
   215  		}
   216  		for j := n - 2; j >= 0; j-- {
   217  			ctmp := c[j]
   218  			stmp := s[j]
   219  			if ctmp != 1 || stmp != 0 {
   220  				for i := 0; i < m; i++ {
   221  					tmp := a[i*lda+j+1]
   222  					tmp2 := a[i*lda+j]
   223  					a[i*lda+j+1] = ctmp*tmp - stmp*tmp2
   224  					a[i*lda+j] = stmp*tmp + ctmp*tmp2
   225  				}
   226  			}
   227  		}
   228  		return
   229  	} else if pivot == lapack.Top {
   230  		if direct == lapack.Forward {
   231  			for j := 1; j < n; j++ {
   232  				ctmp := c[j-1]
   233  				stmp := s[j-1]
   234  				if ctmp != 1 || stmp != 0 {
   235  					for i := 0; i < m; i++ {
   236  						tmp := a[i*lda+j]
   237  						tmp2 := a[i*lda]
   238  						a[i*lda+j] = ctmp*tmp - stmp*tmp2
   239  						a[i*lda] = stmp*tmp + ctmp*tmp2
   240  					}
   241  				}
   242  			}
   243  			return
   244  		}
   245  		for j := n - 1; j >= 1; j-- {
   246  			ctmp := c[j-1]
   247  			stmp := s[j-1]
   248  			if ctmp != 1 || stmp != 0 {
   249  				for i := 0; i < m; i++ {
   250  					tmp := a[i*lda+j]
   251  					tmp2 := a[i*lda]
   252  					a[i*lda+j] = ctmp*tmp - stmp*tmp2
   253  					a[i*lda] = stmp*tmp + ctmp*tmp2
   254  				}
   255  			}
   256  		}
   257  		return
   258  	}
   259  	if direct == lapack.Forward {
   260  		for j := 0; j < n-1; j++ {
   261  			ctmp := c[j]
   262  			stmp := s[j]
   263  			if ctmp != 1 || stmp != 0 {
   264  				for i := 0; i < m; i++ {
   265  					tmp := a[i*lda+j]
   266  					tmp2 := a[i*lda+n-1]
   267  					a[i*lda+j] = stmp*tmp2 + ctmp*tmp
   268  					a[i*lda+n-1] = ctmp*tmp2 - stmp*tmp
   269  				}
   270  
   271  			}
   272  		}
   273  		return
   274  	}
   275  	for j := n - 2; j >= 0; j-- {
   276  		ctmp := c[j]
   277  		stmp := s[j]
   278  		if ctmp != 1 || stmp != 0 {
   279  			for i := 0; i < m; i++ {
   280  				tmp := a[i*lda+j]
   281  				tmp2 := a[i*lda+n-1]
   282  				a[i*lda+j] = stmp*tmp2 + ctmp*tmp
   283  				a[i*lda+n-1] = ctmp*tmp2 - stmp*tmp
   284  			}
   285  		}
   286  	}
   287  }