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