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