github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/lapack/gonum/dlarfx.go (about)

     1  // Copyright ©2016 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 "github.com/jingcheng-WU/gonum/blas"
     8  
     9  // Dlarfx applies an elementary reflector H to a real m×n matrix C, from either
    10  // the left or the right, with loop unrolling when the reflector has order less
    11  // than 11.
    12  //
    13  // H is represented in the form
    14  //  H = I - tau * v * vᵀ,
    15  // where tau is a real scalar and v is a real vector. If tau = 0, then H is
    16  // taken to be the identity matrix.
    17  //
    18  // v must have length equal to m if side == blas.Left, and equal to n if side ==
    19  // blas.Right, otherwise Dlarfx will panic.
    20  //
    21  // c and ldc represent the m×n matrix C. On return, C is overwritten by the
    22  // matrix H * C if side == blas.Left, or C * H if side == blas.Right.
    23  //
    24  // work must have length at least n if side == blas.Left, and at least m if side
    25  // == blas.Right, otherwise Dlarfx will panic. work is not referenced if H has
    26  // order < 11.
    27  //
    28  // Dlarfx is an internal routine. It is exported for testing purposes.
    29  func (impl Implementation) Dlarfx(side blas.Side, m, n int, v []float64, tau float64, c []float64, ldc int, work []float64) {
    30  	switch {
    31  	case side != blas.Left && side != blas.Right:
    32  		panic(badSide)
    33  	case m < 0:
    34  		panic(mLT0)
    35  	case n < 0:
    36  		panic(nLT0)
    37  	case ldc < max(1, n):
    38  		panic(badLdC)
    39  	}
    40  
    41  	// Quick return if possible.
    42  	if m == 0 || n == 0 {
    43  		return
    44  	}
    45  
    46  	nh := m
    47  	lwork := n
    48  	if side == blas.Right {
    49  		nh = n
    50  		lwork = m
    51  	}
    52  	switch {
    53  	case len(v) < nh:
    54  		panic(shortV)
    55  	case len(c) < (m-1)*ldc+n:
    56  		panic(shortC)
    57  	case nh > 10 && len(work) < lwork:
    58  		panic(shortWork)
    59  	}
    60  
    61  	if tau == 0 {
    62  		return
    63  	}
    64  
    65  	if side == blas.Left {
    66  		// Form H * C, where H has order m.
    67  		switch m {
    68  		default: // Code for general m.
    69  			impl.Dlarf(side, m, n, v, 1, tau, c, ldc, work)
    70  			return
    71  
    72  		case 0: // No-op for zero size matrix.
    73  			return
    74  
    75  		case 1: // Special code for 1×1 Householder matrix.
    76  			t0 := 1 - tau*v[0]*v[0]
    77  			for j := 0; j < n; j++ {
    78  				c[j] *= t0
    79  			}
    80  			return
    81  
    82  		case 2: // Special code for 2×2 Householder matrix.
    83  			v0 := v[0]
    84  			t0 := tau * v0
    85  			v1 := v[1]
    86  			t1 := tau * v1
    87  			for j := 0; j < n; j++ {
    88  				sum := v0*c[j] + v1*c[ldc+j]
    89  				c[j] -= sum * t0
    90  				c[ldc+j] -= sum * t1
    91  			}
    92  			return
    93  
    94  		case 3: // Special code for 3×3 Householder matrix.
    95  			v0 := v[0]
    96  			t0 := tau * v0
    97  			v1 := v[1]
    98  			t1 := tau * v1
    99  			v2 := v[2]
   100  			t2 := tau * v2
   101  			for j := 0; j < n; j++ {
   102  				sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j]
   103  				c[j] -= sum * t0
   104  				c[ldc+j] -= sum * t1
   105  				c[2*ldc+j] -= sum * t2
   106  			}
   107  			return
   108  
   109  		case 4: // Special code for 4×4 Householder matrix.
   110  			v0 := v[0]
   111  			t0 := tau * v0
   112  			v1 := v[1]
   113  			t1 := tau * v1
   114  			v2 := v[2]
   115  			t2 := tau * v2
   116  			v3 := v[3]
   117  			t3 := tau * v3
   118  			for j := 0; j < n; j++ {
   119  				sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j]
   120  				c[j] -= sum * t0
   121  				c[ldc+j] -= sum * t1
   122  				c[2*ldc+j] -= sum * t2
   123  				c[3*ldc+j] -= sum * t3
   124  			}
   125  			return
   126  
   127  		case 5: // Special code for 5×5 Householder matrix.
   128  			v0 := v[0]
   129  			t0 := tau * v0
   130  			v1 := v[1]
   131  			t1 := tau * v1
   132  			v2 := v[2]
   133  			t2 := tau * v2
   134  			v3 := v[3]
   135  			t3 := tau * v3
   136  			v4 := v[4]
   137  			t4 := tau * v4
   138  			for j := 0; j < n; j++ {
   139  				sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j]
   140  				c[j] -= sum * t0
   141  				c[ldc+j] -= sum * t1
   142  				c[2*ldc+j] -= sum * t2
   143  				c[3*ldc+j] -= sum * t3
   144  				c[4*ldc+j] -= sum * t4
   145  			}
   146  			return
   147  
   148  		case 6: // Special code for 6×6 Householder matrix.
   149  			v0 := v[0]
   150  			t0 := tau * v0
   151  			v1 := v[1]
   152  			t1 := tau * v1
   153  			v2 := v[2]
   154  			t2 := tau * v2
   155  			v3 := v[3]
   156  			t3 := tau * v3
   157  			v4 := v[4]
   158  			t4 := tau * v4
   159  			v5 := v[5]
   160  			t5 := tau * v5
   161  			for j := 0; j < n; j++ {
   162  				sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] +
   163  					v5*c[5*ldc+j]
   164  				c[j] -= sum * t0
   165  				c[ldc+j] -= sum * t1
   166  				c[2*ldc+j] -= sum * t2
   167  				c[3*ldc+j] -= sum * t3
   168  				c[4*ldc+j] -= sum * t4
   169  				c[5*ldc+j] -= sum * t5
   170  			}
   171  			return
   172  
   173  		case 7: // Special code for 7×7 Householder matrix.
   174  			v0 := v[0]
   175  			t0 := tau * v0
   176  			v1 := v[1]
   177  			t1 := tau * v1
   178  			v2 := v[2]
   179  			t2 := tau * v2
   180  			v3 := v[3]
   181  			t3 := tau * v3
   182  			v4 := v[4]
   183  			t4 := tau * v4
   184  			v5 := v[5]
   185  			t5 := tau * v5
   186  			v6 := v[6]
   187  			t6 := tau * v6
   188  			for j := 0; j < n; j++ {
   189  				sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] +
   190  					v5*c[5*ldc+j] + v6*c[6*ldc+j]
   191  				c[j] -= sum * t0
   192  				c[ldc+j] -= sum * t1
   193  				c[2*ldc+j] -= sum * t2
   194  				c[3*ldc+j] -= sum * t3
   195  				c[4*ldc+j] -= sum * t4
   196  				c[5*ldc+j] -= sum * t5
   197  				c[6*ldc+j] -= sum * t6
   198  			}
   199  			return
   200  
   201  		case 8: // Special code for 8×8 Householder matrix.
   202  			v0 := v[0]
   203  			t0 := tau * v0
   204  			v1 := v[1]
   205  			t1 := tau * v1
   206  			v2 := v[2]
   207  			t2 := tau * v2
   208  			v3 := v[3]
   209  			t3 := tau * v3
   210  			v4 := v[4]
   211  			t4 := tau * v4
   212  			v5 := v[5]
   213  			t5 := tau * v5
   214  			v6 := v[6]
   215  			t6 := tau * v6
   216  			v7 := v[7]
   217  			t7 := tau * v7
   218  			for j := 0; j < n; j++ {
   219  				sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] +
   220  					v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j]
   221  				c[j] -= sum * t0
   222  				c[ldc+j] -= sum * t1
   223  				c[2*ldc+j] -= sum * t2
   224  				c[3*ldc+j] -= sum * t3
   225  				c[4*ldc+j] -= sum * t4
   226  				c[5*ldc+j] -= sum * t5
   227  				c[6*ldc+j] -= sum * t6
   228  				c[7*ldc+j] -= sum * t7
   229  			}
   230  			return
   231  
   232  		case 9: // Special code for 9×9 Householder matrix.
   233  			v0 := v[0]
   234  			t0 := tau * v0
   235  			v1 := v[1]
   236  			t1 := tau * v1
   237  			v2 := v[2]
   238  			t2 := tau * v2
   239  			v3 := v[3]
   240  			t3 := tau * v3
   241  			v4 := v[4]
   242  			t4 := tau * v4
   243  			v5 := v[5]
   244  			t5 := tau * v5
   245  			v6 := v[6]
   246  			t6 := tau * v6
   247  			v7 := v[7]
   248  			t7 := tau * v7
   249  			v8 := v[8]
   250  			t8 := tau * v8
   251  			for j := 0; j < n; j++ {
   252  				sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] +
   253  					v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] + v8*c[8*ldc+j]
   254  				c[j] -= sum * t0
   255  				c[ldc+j] -= sum * t1
   256  				c[2*ldc+j] -= sum * t2
   257  				c[3*ldc+j] -= sum * t3
   258  				c[4*ldc+j] -= sum * t4
   259  				c[5*ldc+j] -= sum * t5
   260  				c[6*ldc+j] -= sum * t6
   261  				c[7*ldc+j] -= sum * t7
   262  				c[8*ldc+j] -= sum * t8
   263  			}
   264  			return
   265  
   266  		case 10: // Special code for 10×10 Householder matrix.
   267  			v0 := v[0]
   268  			t0 := tau * v0
   269  			v1 := v[1]
   270  			t1 := tau * v1
   271  			v2 := v[2]
   272  			t2 := tau * v2
   273  			v3 := v[3]
   274  			t3 := tau * v3
   275  			v4 := v[4]
   276  			t4 := tau * v4
   277  			v5 := v[5]
   278  			t5 := tau * v5
   279  			v6 := v[6]
   280  			t6 := tau * v6
   281  			v7 := v[7]
   282  			t7 := tau * v7
   283  			v8 := v[8]
   284  			t8 := tau * v8
   285  			v9 := v[9]
   286  			t9 := tau * v9
   287  			for j := 0; j < n; j++ {
   288  				sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] +
   289  					v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] + v8*c[8*ldc+j] + v9*c[9*ldc+j]
   290  				c[j] -= sum * t0
   291  				c[ldc+j] -= sum * t1
   292  				c[2*ldc+j] -= sum * t2
   293  				c[3*ldc+j] -= sum * t3
   294  				c[4*ldc+j] -= sum * t4
   295  				c[5*ldc+j] -= sum * t5
   296  				c[6*ldc+j] -= sum * t6
   297  				c[7*ldc+j] -= sum * t7
   298  				c[8*ldc+j] -= sum * t8
   299  				c[9*ldc+j] -= sum * t9
   300  			}
   301  			return
   302  		}
   303  	}
   304  
   305  	// Form C * H, where H has order n.
   306  	switch n {
   307  	default: // Code for general n.
   308  		impl.Dlarf(side, m, n, v, 1, tau, c, ldc, work)
   309  		return
   310  
   311  	case 0: // No-op for zero size matrix.
   312  		return
   313  
   314  	case 1: // Special code for 1×1 Householder matrix.
   315  		t0 := 1 - tau*v[0]*v[0]
   316  		for j := 0; j < m; j++ {
   317  			c[j*ldc] *= t0
   318  		}
   319  		return
   320  
   321  	case 2: // Special code for 2×2 Householder matrix.
   322  		v0 := v[0]
   323  		t0 := tau * v0
   324  		v1 := v[1]
   325  		t1 := tau * v1
   326  		for j := 0; j < m; j++ {
   327  			cs := c[j*ldc:]
   328  			sum := v0*cs[0] + v1*cs[1]
   329  			cs[0] -= sum * t0
   330  			cs[1] -= sum * t1
   331  		}
   332  		return
   333  
   334  	case 3: // Special code for 3×3 Householder matrix.
   335  		v0 := v[0]
   336  		t0 := tau * v0
   337  		v1 := v[1]
   338  		t1 := tau * v1
   339  		v2 := v[2]
   340  		t2 := tau * v2
   341  		for j := 0; j < m; j++ {
   342  			cs := c[j*ldc:]
   343  			sum := v0*cs[0] + v1*cs[1] + v2*cs[2]
   344  			cs[0] -= sum * t0
   345  			cs[1] -= sum * t1
   346  			cs[2] -= sum * t2
   347  		}
   348  		return
   349  
   350  	case 4: // Special code for 4×4 Householder matrix.
   351  		v0 := v[0]
   352  		t0 := tau * v0
   353  		v1 := v[1]
   354  		t1 := tau * v1
   355  		v2 := v[2]
   356  		t2 := tau * v2
   357  		v3 := v[3]
   358  		t3 := tau * v3
   359  		for j := 0; j < m; j++ {
   360  			cs := c[j*ldc:]
   361  			sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3]
   362  			cs[0] -= sum * t0
   363  			cs[1] -= sum * t1
   364  			cs[2] -= sum * t2
   365  			cs[3] -= sum * t3
   366  		}
   367  		return
   368  
   369  	case 5: // Special code for 5×5 Householder matrix.
   370  		v0 := v[0]
   371  		t0 := tau * v0
   372  		v1 := v[1]
   373  		t1 := tau * v1
   374  		v2 := v[2]
   375  		t2 := tau * v2
   376  		v3 := v[3]
   377  		t3 := tau * v3
   378  		v4 := v[4]
   379  		t4 := tau * v4
   380  		for j := 0; j < m; j++ {
   381  			cs := c[j*ldc:]
   382  			sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4]
   383  			cs[0] -= sum * t0
   384  			cs[1] -= sum * t1
   385  			cs[2] -= sum * t2
   386  			cs[3] -= sum * t3
   387  			cs[4] -= sum * t4
   388  		}
   389  		return
   390  
   391  	case 6: // Special code for 6×6 Householder matrix.
   392  		v0 := v[0]
   393  		t0 := tau * v0
   394  		v1 := v[1]
   395  		t1 := tau * v1
   396  		v2 := v[2]
   397  		t2 := tau * v2
   398  		v3 := v[3]
   399  		t3 := tau * v3
   400  		v4 := v[4]
   401  		t4 := tau * v4
   402  		v5 := v[5]
   403  		t5 := tau * v5
   404  		for j := 0; j < m; j++ {
   405  			cs := c[j*ldc:]
   406  			sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + v5*cs[5]
   407  			cs[0] -= sum * t0
   408  			cs[1] -= sum * t1
   409  			cs[2] -= sum * t2
   410  			cs[3] -= sum * t3
   411  			cs[4] -= sum * t4
   412  			cs[5] -= sum * t5
   413  		}
   414  		return
   415  
   416  	case 7: // Special code for 7×7 Householder matrix.
   417  		v0 := v[0]
   418  		t0 := tau * v0
   419  		v1 := v[1]
   420  		t1 := tau * v1
   421  		v2 := v[2]
   422  		t2 := tau * v2
   423  		v3 := v[3]
   424  		t3 := tau * v3
   425  		v4 := v[4]
   426  		t4 := tau * v4
   427  		v5 := v[5]
   428  		t5 := tau * v5
   429  		v6 := v[6]
   430  		t6 := tau * v6
   431  		for j := 0; j < m; j++ {
   432  			cs := c[j*ldc:]
   433  			sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] +
   434  				v5*cs[5] + v6*cs[6]
   435  			cs[0] -= sum * t0
   436  			cs[1] -= sum * t1
   437  			cs[2] -= sum * t2
   438  			cs[3] -= sum * t3
   439  			cs[4] -= sum * t4
   440  			cs[5] -= sum * t5
   441  			cs[6] -= sum * t6
   442  		}
   443  		return
   444  
   445  	case 8: // Special code for 8×8 Householder matrix.
   446  		v0 := v[0]
   447  		t0 := tau * v0
   448  		v1 := v[1]
   449  		t1 := tau * v1
   450  		v2 := v[2]
   451  		t2 := tau * v2
   452  		v3 := v[3]
   453  		t3 := tau * v3
   454  		v4 := v[4]
   455  		t4 := tau * v4
   456  		v5 := v[5]
   457  		t5 := tau * v5
   458  		v6 := v[6]
   459  		t6 := tau * v6
   460  		v7 := v[7]
   461  		t7 := tau * v7
   462  		for j := 0; j < m; j++ {
   463  			cs := c[j*ldc:]
   464  			sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] +
   465  				v5*cs[5] + v6*cs[6] + v7*cs[7]
   466  			cs[0] -= sum * t0
   467  			cs[1] -= sum * t1
   468  			cs[2] -= sum * t2
   469  			cs[3] -= sum * t3
   470  			cs[4] -= sum * t4
   471  			cs[5] -= sum * t5
   472  			cs[6] -= sum * t6
   473  			cs[7] -= sum * t7
   474  		}
   475  		return
   476  
   477  	case 9: // Special code for 9×9 Householder matrix.
   478  		v0 := v[0]
   479  		t0 := tau * v0
   480  		v1 := v[1]
   481  		t1 := tau * v1
   482  		v2 := v[2]
   483  		t2 := tau * v2
   484  		v3 := v[3]
   485  		t3 := tau * v3
   486  		v4 := v[4]
   487  		t4 := tau * v4
   488  		v5 := v[5]
   489  		t5 := tau * v5
   490  		v6 := v[6]
   491  		t6 := tau * v6
   492  		v7 := v[7]
   493  		t7 := tau * v7
   494  		v8 := v[8]
   495  		t8 := tau * v8
   496  		for j := 0; j < m; j++ {
   497  			cs := c[j*ldc:]
   498  			sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] +
   499  				v5*cs[5] + v6*cs[6] + v7*cs[7] + v8*cs[8]
   500  			cs[0] -= sum * t0
   501  			cs[1] -= sum * t1
   502  			cs[2] -= sum * t2
   503  			cs[3] -= sum * t3
   504  			cs[4] -= sum * t4
   505  			cs[5] -= sum * t5
   506  			cs[6] -= sum * t6
   507  			cs[7] -= sum * t7
   508  			cs[8] -= sum * t8
   509  		}
   510  		return
   511  
   512  	case 10: // Special code for 10×10 Householder matrix.
   513  		v0 := v[0]
   514  		t0 := tau * v0
   515  		v1 := v[1]
   516  		t1 := tau * v1
   517  		v2 := v[2]
   518  		t2 := tau * v2
   519  		v3 := v[3]
   520  		t3 := tau * v3
   521  		v4 := v[4]
   522  		t4 := tau * v4
   523  		v5 := v[5]
   524  		t5 := tau * v5
   525  		v6 := v[6]
   526  		t6 := tau * v6
   527  		v7 := v[7]
   528  		t7 := tau * v7
   529  		v8 := v[8]
   530  		t8 := tau * v8
   531  		v9 := v[9]
   532  		t9 := tau * v9
   533  		for j := 0; j < m; j++ {
   534  			cs := c[j*ldc:]
   535  			sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] +
   536  				v5*cs[5] + v6*cs[6] + v7*cs[7] + v8*cs[8] + v9*cs[9]
   537  			cs[0] -= sum * t0
   538  			cs[1] -= sum * t1
   539  			cs[2] -= sum * t2
   540  			cs[3] -= sum * t3
   541  			cs[4] -= sum * t4
   542  			cs[5] -= sum * t5
   543  			cs[6] -= sum * t6
   544  			cs[7] -= sum * t7
   545  			cs[8] -= sum * t8
   546  			cs[9] -= sum * t9
   547  		}
   548  		return
   549  	}
   550  }