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