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