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

     1  // Copyright ©2013 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 mat
     6  
     7  import (
     8  	"github.com/jingcheng-WU/gonum/blas"
     9  	"github.com/jingcheng-WU/gonum/blas/blas64"
    10  	"github.com/jingcheng-WU/gonum/internal/asm/f64"
    11  )
    12  
    13  var (
    14  	vector *VecDense
    15  
    16  	_ Matrix        = vector
    17  	_ allMatrix     = vector
    18  	_ Vector        = vector
    19  	_ Reseter       = vector
    20  	_ MutableVector = vector
    21  )
    22  
    23  // Vector is a vector.
    24  type Vector interface {
    25  	Matrix
    26  	AtVec(int) float64
    27  	Len() int
    28  }
    29  
    30  // A MutableVector can set elements of a vector.
    31  type MutableVector interface {
    32  	Vector
    33  	SetVec(i int, v float64)
    34  }
    35  
    36  // TransposeVec is a type for performing an implicit transpose of a Vector.
    37  // It implements the Vector interface, returning values from the transpose
    38  // of the vector within.
    39  type TransposeVec struct {
    40  	Vector Vector
    41  }
    42  
    43  // At returns the value of the element at row i and column j of the transposed
    44  // matrix, that is, row j and column i of the Vector field.
    45  func (t TransposeVec) At(i, j int) float64 {
    46  	return t.Vector.At(j, i)
    47  }
    48  
    49  // AtVec returns the element at position i. It panics if i is out of bounds.
    50  func (t TransposeVec) AtVec(i int) float64 {
    51  	return t.Vector.AtVec(i)
    52  }
    53  
    54  // Dims returns the dimensions of the transposed vector.
    55  func (t TransposeVec) Dims() (r, c int) {
    56  	c, r = t.Vector.Dims()
    57  	return r, c
    58  }
    59  
    60  // T performs an implicit transpose by returning the Vector field.
    61  func (t TransposeVec) T() Matrix {
    62  	return t.Vector
    63  }
    64  
    65  // Len returns the number of columns in the vector.
    66  func (t TransposeVec) Len() int {
    67  	return t.Vector.Len()
    68  }
    69  
    70  // TVec performs an implicit transpose by returning the Vector field.
    71  func (t TransposeVec) TVec() Vector {
    72  	return t.Vector
    73  }
    74  
    75  // Untranspose returns the Vector field.
    76  func (t TransposeVec) Untranspose() Matrix {
    77  	return t.Vector
    78  }
    79  
    80  func (t TransposeVec) UntransposeVec() Vector {
    81  	return t.Vector
    82  }
    83  
    84  // VecDense represents a column vector.
    85  type VecDense struct {
    86  	mat blas64.Vector
    87  	// A BLAS vector can have a negative increment, but allowing this
    88  	// in the mat type complicates a lot of code, and doesn't gain anything.
    89  	// VecDense must have positive increment in this package.
    90  }
    91  
    92  // NewVecDense creates a new VecDense of length n. If data == nil,
    93  // a new slice is allocated for the backing slice. If len(data) == n, data is
    94  // used as the backing slice, and changes to the elements of the returned VecDense
    95  // will be reflected in data. If neither of these is true, NewVecDense will panic.
    96  // NewVecDense will panic if n is zero.
    97  func NewVecDense(n int, data []float64) *VecDense {
    98  	if n <= 0 {
    99  		if n == 0 {
   100  			panic(ErrZeroLength)
   101  		}
   102  		panic("mat: negative dimension")
   103  	}
   104  	if len(data) != n && data != nil {
   105  		panic(ErrShape)
   106  	}
   107  	if data == nil {
   108  		data = make([]float64, n)
   109  	}
   110  	return &VecDense{
   111  		mat: blas64.Vector{
   112  			N:    n,
   113  			Inc:  1,
   114  			Data: data,
   115  		},
   116  	}
   117  }
   118  
   119  // SliceVec returns a new Vector that shares backing data with the receiver.
   120  // The returned matrix starts at i of the receiver and extends k-i elements.
   121  // SliceVec panics with ErrIndexOutOfRange if the slice is outside the capacity
   122  // of the receiver.
   123  func (v *VecDense) SliceVec(i, k int) Vector {
   124  	return v.sliceVec(i, k)
   125  }
   126  
   127  func (v *VecDense) sliceVec(i, k int) *VecDense {
   128  	if i < 0 || k <= i || v.Cap() < k {
   129  		panic(ErrIndexOutOfRange)
   130  	}
   131  	return &VecDense{
   132  		mat: blas64.Vector{
   133  			N:    k - i,
   134  			Inc:  v.mat.Inc,
   135  			Data: v.mat.Data[i*v.mat.Inc : (k-1)*v.mat.Inc+1],
   136  		},
   137  	}
   138  }
   139  
   140  // Dims returns the number of rows and columns in the matrix. Columns is always 1
   141  // for a non-Reset vector.
   142  func (v *VecDense) Dims() (r, c int) {
   143  	if v.IsEmpty() {
   144  		return 0, 0
   145  	}
   146  	return v.mat.N, 1
   147  }
   148  
   149  // Caps returns the number of rows and columns in the backing matrix. Columns is always 1
   150  // for a non-Reset vector.
   151  func (v *VecDense) Caps() (r, c int) {
   152  	if v.IsEmpty() {
   153  		return 0, 0
   154  	}
   155  	return v.Cap(), 1
   156  }
   157  
   158  // Len returns the length of the vector.
   159  func (v *VecDense) Len() int {
   160  	return v.mat.N
   161  }
   162  
   163  // Cap returns the capacity of the vector.
   164  func (v *VecDense) Cap() int {
   165  	if v.IsEmpty() {
   166  		return 0
   167  	}
   168  	return (cap(v.mat.Data)-1)/v.mat.Inc + 1
   169  }
   170  
   171  // T performs an implicit transpose by returning the receiver inside a Transpose.
   172  func (v *VecDense) T() Matrix {
   173  	return Transpose{v}
   174  }
   175  
   176  // TVec performs an implicit transpose by returning the receiver inside a TransposeVec.
   177  func (v *VecDense) TVec() Vector {
   178  	return TransposeVec{v}
   179  }
   180  
   181  // Reset empties the matrix so that it can be reused as the
   182  // receiver of a dimensionally restricted operation.
   183  //
   184  // Reset should not be used when the matrix shares backing data.
   185  // See the Reseter interface for more information.
   186  func (v *VecDense) Reset() {
   187  	// No change of Inc or N to 0 may be
   188  	// made unless both are set to 0.
   189  	v.mat.Inc = 0
   190  	v.mat.N = 0
   191  	v.mat.Data = v.mat.Data[:0]
   192  }
   193  
   194  // Zero sets all of the matrix elements to zero.
   195  func (v *VecDense) Zero() {
   196  	for i := 0; i < v.mat.N; i++ {
   197  		v.mat.Data[v.mat.Inc*i] = 0
   198  	}
   199  }
   200  
   201  // CloneFromVec makes a copy of a into the receiver, overwriting the previous value
   202  // of the receiver.
   203  func (v *VecDense) CloneFromVec(a Vector) {
   204  	if v == a {
   205  		return
   206  	}
   207  	n := a.Len()
   208  	v.mat = blas64.Vector{
   209  		N:    n,
   210  		Inc:  1,
   211  		Data: use(v.mat.Data, n),
   212  	}
   213  	if r, ok := a.(RawVectorer); ok {
   214  		blas64.Copy(r.RawVector(), v.mat)
   215  		return
   216  	}
   217  	for i := 0; i < a.Len(); i++ {
   218  		v.setVec(i, a.AtVec(i))
   219  	}
   220  }
   221  
   222  // VecDenseCopyOf returns a newly allocated copy of the elements of a.
   223  func VecDenseCopyOf(a Vector) *VecDense {
   224  	v := &VecDense{}
   225  	v.CloneFromVec(a)
   226  	return v
   227  }
   228  
   229  // RawVector returns the underlying blas64.Vector used by the receiver.
   230  // Changes to elements in the receiver following the call will be reflected
   231  // in returned blas64.Vector.
   232  func (v *VecDense) RawVector() blas64.Vector {
   233  	return v.mat
   234  }
   235  
   236  // SetRawVector sets the underlying blas64.Vector used by the receiver.
   237  // Changes to elements in the receiver following the call will be reflected
   238  // in the input.
   239  func (v *VecDense) SetRawVector(a blas64.Vector) {
   240  	v.mat = a
   241  }
   242  
   243  // CopyVec makes a copy of elements of a into the receiver. It is similar to the
   244  // built-in copy; it copies as much as the overlap between the two vectors and
   245  // returns the number of elements it copied.
   246  func (v *VecDense) CopyVec(a Vector) int {
   247  	n := min(v.Len(), a.Len())
   248  	if v == a {
   249  		return n
   250  	}
   251  	if r, ok := a.(RawVectorer); ok {
   252  		src := r.RawVector()
   253  		src.N = n
   254  		dst := v.mat
   255  		dst.N = n
   256  		blas64.Copy(src, dst)
   257  		return n
   258  	}
   259  	for i := 0; i < n; i++ {
   260  		v.setVec(i, a.AtVec(i))
   261  	}
   262  	return n
   263  }
   264  
   265  // ScaleVec scales the vector a by alpha, placing the result in the receiver.
   266  func (v *VecDense) ScaleVec(alpha float64, a Vector) {
   267  	n := a.Len()
   268  
   269  	if v == a {
   270  		if v.mat.Inc == 1 {
   271  			f64.ScalUnitary(alpha, v.mat.Data)
   272  			return
   273  		}
   274  		f64.ScalInc(alpha, v.mat.Data, uintptr(n), uintptr(v.mat.Inc))
   275  		return
   276  	}
   277  
   278  	v.reuseAsNonZeroed(n)
   279  
   280  	if rv, ok := a.(RawVectorer); ok {
   281  		mat := rv.RawVector()
   282  		v.checkOverlap(mat)
   283  		if v.mat.Inc == 1 && mat.Inc == 1 {
   284  			f64.ScalUnitaryTo(v.mat.Data, alpha, mat.Data)
   285  			return
   286  		}
   287  		f64.ScalIncTo(v.mat.Data, uintptr(v.mat.Inc),
   288  			alpha, mat.Data, uintptr(n), uintptr(mat.Inc))
   289  		return
   290  	}
   291  
   292  	for i := 0; i < n; i++ {
   293  		v.setVec(i, alpha*a.AtVec(i))
   294  	}
   295  }
   296  
   297  // AddScaledVec adds the vectors a and alpha*b, placing the result in the receiver.
   298  func (v *VecDense) AddScaledVec(a Vector, alpha float64, b Vector) {
   299  	if alpha == 1 {
   300  		v.AddVec(a, b)
   301  		return
   302  	}
   303  	if alpha == -1 {
   304  		v.SubVec(a, b)
   305  		return
   306  	}
   307  
   308  	ar := a.Len()
   309  	br := b.Len()
   310  
   311  	if ar != br {
   312  		panic(ErrShape)
   313  	}
   314  
   315  	var amat, bmat blas64.Vector
   316  	fast := true
   317  	aU, _ := untransposeExtract(a)
   318  	if rv, ok := aU.(*VecDense); ok {
   319  		amat = rv.mat
   320  		if v != a {
   321  			v.checkOverlap(amat)
   322  		}
   323  	} else {
   324  		fast = false
   325  	}
   326  	bU, _ := untransposeExtract(b)
   327  	if rv, ok := bU.(*VecDense); ok {
   328  		bmat = rv.mat
   329  		if v != b {
   330  			v.checkOverlap(bmat)
   331  		}
   332  	} else {
   333  		fast = false
   334  	}
   335  
   336  	v.reuseAsNonZeroed(ar)
   337  
   338  	switch {
   339  	case alpha == 0: // v <- a
   340  		if v == a {
   341  			return
   342  		}
   343  		v.CopyVec(a)
   344  	case v == a && v == b: // v <- v + alpha * v = (alpha + 1) * v
   345  		blas64.Scal(alpha+1, v.mat)
   346  	case !fast: // v <- a + alpha * b without blas64 support.
   347  		for i := 0; i < ar; i++ {
   348  			v.setVec(i, a.AtVec(i)+alpha*b.AtVec(i))
   349  		}
   350  	case v == a && v != b: // v <- v + alpha * b
   351  		if v.mat.Inc == 1 && bmat.Inc == 1 {
   352  			// Fast path for a common case.
   353  			f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data)
   354  		} else {
   355  			f64.AxpyInc(alpha, bmat.Data, v.mat.Data,
   356  				uintptr(ar), uintptr(bmat.Inc), uintptr(v.mat.Inc), 0, 0)
   357  		}
   358  	default: // v <- a + alpha * b or v <- a + alpha * v
   359  		if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
   360  			// Fast path for a common case.
   361  			f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data)
   362  		} else {
   363  			f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0,
   364  				alpha, bmat.Data, amat.Data,
   365  				uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0)
   366  		}
   367  	}
   368  }
   369  
   370  // AddVec adds the vectors a and b, placing the result in the receiver.
   371  func (v *VecDense) AddVec(a, b Vector) {
   372  	ar := a.Len()
   373  	br := b.Len()
   374  
   375  	if ar != br {
   376  		panic(ErrShape)
   377  	}
   378  
   379  	v.reuseAsNonZeroed(ar)
   380  
   381  	aU, _ := untransposeExtract(a)
   382  	bU, _ := untransposeExtract(b)
   383  
   384  	if arv, ok := aU.(*VecDense); ok {
   385  		if brv, ok := bU.(*VecDense); ok {
   386  			amat := arv.mat
   387  			bmat := brv.mat
   388  
   389  			if v != a {
   390  				v.checkOverlap(amat)
   391  			}
   392  			if v != b {
   393  				v.checkOverlap(bmat)
   394  			}
   395  
   396  			if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
   397  				// Fast path for a common case.
   398  				f64.AxpyUnitaryTo(v.mat.Data, 1, bmat.Data, amat.Data)
   399  				return
   400  			}
   401  			f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0,
   402  				1, bmat.Data, amat.Data,
   403  				uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0)
   404  			return
   405  		}
   406  	}
   407  
   408  	for i := 0; i < ar; i++ {
   409  		v.setVec(i, a.AtVec(i)+b.AtVec(i))
   410  	}
   411  }
   412  
   413  // SubVec subtracts the vector b from a, placing the result in the receiver.
   414  func (v *VecDense) SubVec(a, b Vector) {
   415  	ar := a.Len()
   416  	br := b.Len()
   417  
   418  	if ar != br {
   419  		panic(ErrShape)
   420  	}
   421  
   422  	v.reuseAsNonZeroed(ar)
   423  
   424  	aU, _ := untransposeExtract(a)
   425  	bU, _ := untransposeExtract(b)
   426  
   427  	if arv, ok := aU.(*VecDense); ok {
   428  		if brv, ok := bU.(*VecDense); ok {
   429  			amat := arv.mat
   430  			bmat := brv.mat
   431  
   432  			if v != a {
   433  				v.checkOverlap(amat)
   434  			}
   435  			if v != b {
   436  				v.checkOverlap(bmat)
   437  			}
   438  
   439  			if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
   440  				// Fast path for a common case.
   441  				f64.AxpyUnitaryTo(v.mat.Data, -1, bmat.Data, amat.Data)
   442  				return
   443  			}
   444  			f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0,
   445  				-1, bmat.Data, amat.Data,
   446  				uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0)
   447  			return
   448  		}
   449  	}
   450  
   451  	for i := 0; i < ar; i++ {
   452  		v.setVec(i, a.AtVec(i)-b.AtVec(i))
   453  	}
   454  }
   455  
   456  // MulElemVec performs element-wise multiplication of a and b, placing the result
   457  // in the receiver.
   458  func (v *VecDense) MulElemVec(a, b Vector) {
   459  	ar := a.Len()
   460  	br := b.Len()
   461  
   462  	if ar != br {
   463  		panic(ErrShape)
   464  	}
   465  
   466  	v.reuseAsNonZeroed(ar)
   467  
   468  	aU, _ := untransposeExtract(a)
   469  	bU, _ := untransposeExtract(b)
   470  
   471  	if arv, ok := aU.(*VecDense); ok {
   472  		if brv, ok := bU.(*VecDense); ok {
   473  			amat := arv.mat
   474  			bmat := brv.mat
   475  
   476  			if v != a {
   477  				v.checkOverlap(amat)
   478  			}
   479  			if v != b {
   480  				v.checkOverlap(bmat)
   481  			}
   482  
   483  			if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
   484  				// Fast path for a common case.
   485  				for i, a := range amat.Data {
   486  					v.mat.Data[i] = a * bmat.Data[i]
   487  				}
   488  				return
   489  			}
   490  			var ia, ib int
   491  			for i := 0; i < ar; i++ {
   492  				v.setVec(i, amat.Data[ia]*bmat.Data[ib])
   493  				ia += amat.Inc
   494  				ib += bmat.Inc
   495  			}
   496  			return
   497  		}
   498  	}
   499  
   500  	for i := 0; i < ar; i++ {
   501  		v.setVec(i, a.AtVec(i)*b.AtVec(i))
   502  	}
   503  }
   504  
   505  // DivElemVec performs element-wise division of a by b, placing the result
   506  // in the receiver.
   507  func (v *VecDense) DivElemVec(a, b Vector) {
   508  	ar := a.Len()
   509  	br := b.Len()
   510  
   511  	if ar != br {
   512  		panic(ErrShape)
   513  	}
   514  
   515  	v.reuseAsNonZeroed(ar)
   516  
   517  	aU, _ := untransposeExtract(a)
   518  	bU, _ := untransposeExtract(b)
   519  
   520  	if arv, ok := aU.(*VecDense); ok {
   521  		if brv, ok := bU.(*VecDense); ok {
   522  			amat := arv.mat
   523  			bmat := brv.mat
   524  
   525  			if v != a {
   526  				v.checkOverlap(amat)
   527  			}
   528  			if v != b {
   529  				v.checkOverlap(bmat)
   530  			}
   531  
   532  			if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
   533  				// Fast path for a common case.
   534  				for i, a := range amat.Data {
   535  					v.setVec(i, a/bmat.Data[i])
   536  				}
   537  				return
   538  			}
   539  			var ia, ib int
   540  			for i := 0; i < ar; i++ {
   541  				v.setVec(i, amat.Data[ia]/bmat.Data[ib])
   542  				ia += amat.Inc
   543  				ib += bmat.Inc
   544  			}
   545  		}
   546  	}
   547  
   548  	for i := 0; i < ar; i++ {
   549  		v.setVec(i, a.AtVec(i)/b.AtVec(i))
   550  	}
   551  }
   552  
   553  // MulVec computes a * b. The result is stored into the receiver.
   554  // MulVec panics if the number of columns in a does not equal the number of rows in b
   555  // or if the number of columns in b does not equal 1.
   556  func (v *VecDense) MulVec(a Matrix, b Vector) {
   557  	r, c := a.Dims()
   558  	br, bc := b.Dims()
   559  	if c != br || bc != 1 {
   560  		panic(ErrShape)
   561  	}
   562  
   563  	aU, trans := untransposeExtract(a)
   564  	var bmat blas64.Vector
   565  	fast := true
   566  	bU, _ := untransposeExtract(b)
   567  	if rv, ok := bU.(*VecDense); ok {
   568  		bmat = rv.mat
   569  		if v != b {
   570  			v.checkOverlap(bmat)
   571  		}
   572  	} else {
   573  		fast = false
   574  	}
   575  
   576  	v.reuseAsNonZeroed(r)
   577  	var restore func()
   578  	if v == aU {
   579  		v, restore = v.isolatedWorkspace(aU.(*VecDense))
   580  		defer restore()
   581  	} else if v == b {
   582  		v, restore = v.isolatedWorkspace(b)
   583  		defer restore()
   584  	}
   585  
   586  	// TODO(kortschak): Improve the non-fast paths.
   587  	switch aU := aU.(type) {
   588  	case Vector:
   589  		if b.Len() == 1 {
   590  			// {n,1} x {1,1}
   591  			v.ScaleVec(b.AtVec(0), aU)
   592  			return
   593  		}
   594  
   595  		// {1,n} x {n,1}
   596  		if fast {
   597  			if rv, ok := aU.(*VecDense); ok {
   598  				amat := rv.mat
   599  				if v != aU {
   600  					v.checkOverlap(amat)
   601  				}
   602  
   603  				if amat.Inc == 1 && bmat.Inc == 1 {
   604  					// Fast path for a common case.
   605  					v.setVec(0, f64.DotUnitary(amat.Data, bmat.Data))
   606  					return
   607  				}
   608  				v.setVec(0, f64.DotInc(amat.Data, bmat.Data,
   609  					uintptr(c), uintptr(amat.Inc), uintptr(bmat.Inc), 0, 0))
   610  				return
   611  			}
   612  		}
   613  		var sum float64
   614  		for i := 0; i < c; i++ {
   615  			sum += aU.AtVec(i) * b.AtVec(i)
   616  		}
   617  		v.setVec(0, sum)
   618  		return
   619  	case *SymBandDense:
   620  		if fast {
   621  			aU.checkOverlap(v.asGeneral())
   622  			blas64.Sbmv(1, aU.mat, bmat, 0, v.mat)
   623  			return
   624  		}
   625  	case *SymDense:
   626  		if fast {
   627  			aU.checkOverlap(v.asGeneral())
   628  			blas64.Symv(1, aU.mat, bmat, 0, v.mat)
   629  			return
   630  		}
   631  	case *TriDense:
   632  		if fast {
   633  			v.CopyVec(b)
   634  			aU.checkOverlap(v.asGeneral())
   635  			ta := blas.NoTrans
   636  			if trans {
   637  				ta = blas.Trans
   638  			}
   639  			blas64.Trmv(ta, aU.mat, v.mat)
   640  			return
   641  		}
   642  	case *Dense:
   643  		if fast {
   644  			aU.checkOverlap(v.asGeneral())
   645  			t := blas.NoTrans
   646  			if trans {
   647  				t = blas.Trans
   648  			}
   649  			blas64.Gemv(t, 1, aU.mat, bmat, 0, v.mat)
   650  			return
   651  		}
   652  	default:
   653  		if fast {
   654  			for i := 0; i < r; i++ {
   655  				var f float64
   656  				for j := 0; j < c; j++ {
   657  					f += a.At(i, j) * bmat.Data[j*bmat.Inc]
   658  				}
   659  				v.setVec(i, f)
   660  			}
   661  			return
   662  		}
   663  	}
   664  
   665  	for i := 0; i < r; i++ {
   666  		var f float64
   667  		for j := 0; j < c; j++ {
   668  			f += a.At(i, j) * b.AtVec(j)
   669  		}
   670  		v.setVec(i, f)
   671  	}
   672  }
   673  
   674  // ReuseAsVec changes the receiver if it IsEmpty() to be of size n×1.
   675  //
   676  // ReuseAsVec re-uses the backing data slice if it has sufficient capacity,
   677  // otherwise a new slice is allocated. The backing data is zero on return.
   678  //
   679  // ReuseAsVec panics if the receiver is not empty, and panics if
   680  // the input size is less than one. To empty the receiver for re-use,
   681  // Reset should be used.
   682  func (v *VecDense) ReuseAsVec(n int) {
   683  	if n <= 0 {
   684  		if n == 0 {
   685  			panic(ErrZeroLength)
   686  		}
   687  		panic(ErrNegativeDimension)
   688  	}
   689  	if !v.IsEmpty() {
   690  		panic(ErrReuseNonEmpty)
   691  	}
   692  	v.reuseAsZeroed(n)
   693  }
   694  
   695  // reuseAsNonZeroed resizes an empty vector to a r×1 vector,
   696  // or checks that a non-empty matrix is r×1.
   697  func (v *VecDense) reuseAsNonZeroed(r int) {
   698  	// reuseAsNonZeroed must be kept in sync with reuseAsZeroed.
   699  	if r == 0 {
   700  		panic(ErrZeroLength)
   701  	}
   702  	if v.IsEmpty() {
   703  		v.mat = blas64.Vector{
   704  			N:    r,
   705  			Inc:  1,
   706  			Data: use(v.mat.Data, r),
   707  		}
   708  		return
   709  	}
   710  	if r != v.mat.N {
   711  		panic(ErrShape)
   712  	}
   713  }
   714  
   715  // reuseAsZeroed resizes an empty vector to a r×1 vector,
   716  // or checks that a non-empty matrix is r×1.
   717  func (v *VecDense) reuseAsZeroed(r int) {
   718  	// reuseAsZeroed must be kept in sync with reuseAsNonZeroed.
   719  	if r == 0 {
   720  		panic(ErrZeroLength)
   721  	}
   722  	if v.IsEmpty() {
   723  		v.mat = blas64.Vector{
   724  			N:    r,
   725  			Inc:  1,
   726  			Data: useZeroed(v.mat.Data, r),
   727  		}
   728  		return
   729  	}
   730  	if r != v.mat.N {
   731  		panic(ErrShape)
   732  	}
   733  	v.Zero()
   734  }
   735  
   736  // IsEmpty returns whether the receiver is empty. Empty matrices can be the
   737  // receiver for size-restricted operations. The receiver can be emptied using
   738  // Reset.
   739  func (v *VecDense) IsEmpty() bool {
   740  	// It must be the case that v.Dims() returns
   741  	// zeros in this case. See comment in Reset().
   742  	return v.mat.Inc == 0
   743  }
   744  
   745  func (v *VecDense) isolatedWorkspace(a Vector) (n *VecDense, restore func()) {
   746  	l := a.Len()
   747  	if l == 0 {
   748  		panic(ErrZeroLength)
   749  	}
   750  	n = getWorkspaceVec(l, false)
   751  	return n, func() {
   752  		v.CopyVec(n)
   753  		putWorkspaceVec(n)
   754  	}
   755  }
   756  
   757  // asDense returns a Dense representation of the receiver with the same
   758  // underlying data.
   759  func (v *VecDense) asDense() *Dense {
   760  	return &Dense{
   761  		mat:     v.asGeneral(),
   762  		capRows: v.mat.N,
   763  		capCols: 1,
   764  	}
   765  }
   766  
   767  // asGeneral returns a blas64.General representation of the receiver with the
   768  // same underlying data.
   769  func (v *VecDense) asGeneral() blas64.General {
   770  	return blas64.General{
   771  		Rows:   v.mat.N,
   772  		Cols:   1,
   773  		Stride: v.mat.Inc,
   774  		Data:   v.mat.Data,
   775  	}
   776  }
   777  
   778  // ColViewOf reflects the column j of the RawMatrixer m, into the receiver
   779  // backed by the same underlying data. The receiver must either be empty
   780  // have length equal to the number of rows of m.
   781  func (v *VecDense) ColViewOf(m RawMatrixer, j int) {
   782  	rm := m.RawMatrix()
   783  
   784  	if j >= rm.Cols || j < 0 {
   785  		panic(ErrColAccess)
   786  	}
   787  	if !v.IsEmpty() && v.mat.N != rm.Rows {
   788  		panic(ErrShape)
   789  	}
   790  
   791  	v.mat.Inc = rm.Stride
   792  	v.mat.Data = rm.Data[j : (rm.Rows-1)*rm.Stride+j+1]
   793  	v.mat.N = rm.Rows
   794  }
   795  
   796  // RowViewOf reflects the row i of the RawMatrixer m, into the receiver
   797  // backed by the same underlying data. The receiver must either be
   798  // empty or have length equal to the number of columns of m.
   799  func (v *VecDense) RowViewOf(m RawMatrixer, i int) {
   800  	rm := m.RawMatrix()
   801  
   802  	if i >= rm.Rows || i < 0 {
   803  		panic(ErrRowAccess)
   804  	}
   805  	if !v.IsEmpty() && v.mat.N != rm.Cols {
   806  		panic(ErrShape)
   807  	}
   808  
   809  	v.mat.Inc = 1
   810  	v.mat.Data = rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols]
   811  	v.mat.N = rm.Cols
   812  }