github.com/gopherd/gonum@v0.0.4/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  	"github.com/gopherd/gonum/blas"
    11  	"github.com/gopherd/gonum/blas/blas64"
    12  	"github.com/gopherd/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  //  1 - The sum of the element magnitudes
   269  //  2 - The Euclidean norm, the square root of the sum of the squares of the elements
   270  //  Inf - The maximum element magnitude
   271  //
   272  // Norm will panic with ErrNormOrder if an illegal norm is specified and with
   273  // ErrZeroLength if the vector has zero size.
   274  func (v *VecDense) Norm(norm float64) float64 {
   275  	if v.IsEmpty() {
   276  		panic(ErrZeroLength)
   277  	}
   278  	switch norm {
   279  	default:
   280  		panic(ErrNormOrder)
   281  	case 1:
   282  		return blas64.Asum(v.mat)
   283  	case 2:
   284  		return blas64.Nrm2(v.mat)
   285  	case math.Inf(1):
   286  		imax := blas64.Iamax(v.mat)
   287  		return math.Abs(v.at(imax))
   288  	}
   289  }
   290  
   291  // ScaleVec scales the vector a by alpha, placing the result in the receiver.
   292  func (v *VecDense) ScaleVec(alpha float64, a Vector) {
   293  	n := a.Len()
   294  
   295  	if v == a {
   296  		if v.mat.Inc == 1 {
   297  			f64.ScalUnitary(alpha, v.mat.Data)
   298  			return
   299  		}
   300  		f64.ScalInc(alpha, v.mat.Data, uintptr(n), uintptr(v.mat.Inc))
   301  		return
   302  	}
   303  
   304  	v.reuseAsNonZeroed(n)
   305  
   306  	if rv, ok := a.(RawVectorer); ok {
   307  		mat := rv.RawVector()
   308  		v.checkOverlap(mat)
   309  		if v.mat.Inc == 1 && mat.Inc == 1 {
   310  			f64.ScalUnitaryTo(v.mat.Data, alpha, mat.Data)
   311  			return
   312  		}
   313  		f64.ScalIncTo(v.mat.Data, uintptr(v.mat.Inc),
   314  			alpha, mat.Data, uintptr(n), uintptr(mat.Inc))
   315  		return
   316  	}
   317  
   318  	for i := 0; i < n; i++ {
   319  		v.setVec(i, alpha*a.AtVec(i))
   320  	}
   321  }
   322  
   323  // AddScaledVec adds the vectors a and alpha*b, placing the result in the receiver.
   324  func (v *VecDense) AddScaledVec(a Vector, alpha float64, b Vector) {
   325  	if alpha == 1 {
   326  		v.AddVec(a, b)
   327  		return
   328  	}
   329  	if alpha == -1 {
   330  		v.SubVec(a, b)
   331  		return
   332  	}
   333  
   334  	ar := a.Len()
   335  	br := b.Len()
   336  
   337  	if ar != br {
   338  		panic(ErrShape)
   339  	}
   340  
   341  	var amat, bmat blas64.Vector
   342  	fast := true
   343  	aU, _ := untransposeExtract(a)
   344  	if rv, ok := aU.(*VecDense); ok {
   345  		amat = rv.mat
   346  		if v != a {
   347  			v.checkOverlap(amat)
   348  		}
   349  	} else {
   350  		fast = false
   351  	}
   352  	bU, _ := untransposeExtract(b)
   353  	if rv, ok := bU.(*VecDense); ok {
   354  		bmat = rv.mat
   355  		if v != b {
   356  			v.checkOverlap(bmat)
   357  		}
   358  	} else {
   359  		fast = false
   360  	}
   361  
   362  	v.reuseAsNonZeroed(ar)
   363  
   364  	switch {
   365  	case alpha == 0: // v <- a
   366  		if v == a {
   367  			return
   368  		}
   369  		v.CopyVec(a)
   370  	case v == a && v == b: // v <- v + alpha * v = (alpha + 1) * v
   371  		blas64.Scal(alpha+1, v.mat)
   372  	case !fast: // v <- a + alpha * b without blas64 support.
   373  		for i := 0; i < ar; i++ {
   374  			v.setVec(i, a.AtVec(i)+alpha*b.AtVec(i))
   375  		}
   376  	case v == a && v != b: // v <- v + alpha * b
   377  		if v.mat.Inc == 1 && bmat.Inc == 1 {
   378  			// Fast path for a common case.
   379  			f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data)
   380  		} else {
   381  			f64.AxpyInc(alpha, bmat.Data, v.mat.Data,
   382  				uintptr(ar), uintptr(bmat.Inc), uintptr(v.mat.Inc), 0, 0)
   383  		}
   384  	default: // v <- a + alpha * b or v <- a + alpha * v
   385  		if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
   386  			// Fast path for a common case.
   387  			f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data)
   388  		} else {
   389  			f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0,
   390  				alpha, bmat.Data, amat.Data,
   391  				uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0)
   392  		}
   393  	}
   394  }
   395  
   396  // AddVec adds the vectors a and b, placing the result in the receiver.
   397  func (v *VecDense) AddVec(a, b Vector) {
   398  	ar := a.Len()
   399  	br := b.Len()
   400  
   401  	if ar != br {
   402  		panic(ErrShape)
   403  	}
   404  
   405  	v.reuseAsNonZeroed(ar)
   406  
   407  	aU, _ := untransposeExtract(a)
   408  	bU, _ := untransposeExtract(b)
   409  
   410  	if arv, ok := aU.(*VecDense); ok {
   411  		if brv, ok := bU.(*VecDense); ok {
   412  			amat := arv.mat
   413  			bmat := brv.mat
   414  
   415  			if v != a {
   416  				v.checkOverlap(amat)
   417  			}
   418  			if v != b {
   419  				v.checkOverlap(bmat)
   420  			}
   421  
   422  			if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
   423  				// Fast path for a common case.
   424  				f64.AxpyUnitaryTo(v.mat.Data, 1, bmat.Data, amat.Data)
   425  				return
   426  			}
   427  			f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0,
   428  				1, bmat.Data, amat.Data,
   429  				uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0)
   430  			return
   431  		}
   432  	}
   433  
   434  	for i := 0; i < ar; i++ {
   435  		v.setVec(i, a.AtVec(i)+b.AtVec(i))
   436  	}
   437  }
   438  
   439  // SubVec subtracts the vector b from a, placing the result in the receiver.
   440  func (v *VecDense) SubVec(a, b Vector) {
   441  	ar := a.Len()
   442  	br := b.Len()
   443  
   444  	if ar != br {
   445  		panic(ErrShape)
   446  	}
   447  
   448  	v.reuseAsNonZeroed(ar)
   449  
   450  	aU, _ := untransposeExtract(a)
   451  	bU, _ := untransposeExtract(b)
   452  
   453  	if arv, ok := aU.(*VecDense); ok {
   454  		if brv, ok := bU.(*VecDense); ok {
   455  			amat := arv.mat
   456  			bmat := brv.mat
   457  
   458  			if v != a {
   459  				v.checkOverlap(amat)
   460  			}
   461  			if v != b {
   462  				v.checkOverlap(bmat)
   463  			}
   464  
   465  			if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
   466  				// Fast path for a common case.
   467  				f64.AxpyUnitaryTo(v.mat.Data, -1, bmat.Data, amat.Data)
   468  				return
   469  			}
   470  			f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0,
   471  				-1, bmat.Data, amat.Data,
   472  				uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0)
   473  			return
   474  		}
   475  	}
   476  
   477  	for i := 0; i < ar; i++ {
   478  		v.setVec(i, a.AtVec(i)-b.AtVec(i))
   479  	}
   480  }
   481  
   482  // MulElemVec performs element-wise multiplication of a and b, placing the result
   483  // in the receiver.
   484  func (v *VecDense) MulElemVec(a, b Vector) {
   485  	ar := a.Len()
   486  	br := b.Len()
   487  
   488  	if ar != br {
   489  		panic(ErrShape)
   490  	}
   491  
   492  	v.reuseAsNonZeroed(ar)
   493  
   494  	aU, _ := untransposeExtract(a)
   495  	bU, _ := untransposeExtract(b)
   496  
   497  	if arv, ok := aU.(*VecDense); ok {
   498  		if brv, ok := bU.(*VecDense); ok {
   499  			amat := arv.mat
   500  			bmat := brv.mat
   501  
   502  			if v != a {
   503  				v.checkOverlap(amat)
   504  			}
   505  			if v != b {
   506  				v.checkOverlap(bmat)
   507  			}
   508  
   509  			if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
   510  				// Fast path for a common case.
   511  				for i, a := range amat.Data {
   512  					v.mat.Data[i] = a * bmat.Data[i]
   513  				}
   514  				return
   515  			}
   516  			var ia, ib int
   517  			for i := 0; i < ar; i++ {
   518  				v.setVec(i, amat.Data[ia]*bmat.Data[ib])
   519  				ia += amat.Inc
   520  				ib += bmat.Inc
   521  			}
   522  			return
   523  		}
   524  	}
   525  
   526  	for i := 0; i < ar; i++ {
   527  		v.setVec(i, a.AtVec(i)*b.AtVec(i))
   528  	}
   529  }
   530  
   531  // DivElemVec performs element-wise division of a by b, placing the result
   532  // in the receiver.
   533  func (v *VecDense) DivElemVec(a, b Vector) {
   534  	ar := a.Len()
   535  	br := b.Len()
   536  
   537  	if ar != br {
   538  		panic(ErrShape)
   539  	}
   540  
   541  	v.reuseAsNonZeroed(ar)
   542  
   543  	aU, _ := untransposeExtract(a)
   544  	bU, _ := untransposeExtract(b)
   545  
   546  	if arv, ok := aU.(*VecDense); ok {
   547  		if brv, ok := bU.(*VecDense); ok {
   548  			amat := arv.mat
   549  			bmat := brv.mat
   550  
   551  			if v != a {
   552  				v.checkOverlap(amat)
   553  			}
   554  			if v != b {
   555  				v.checkOverlap(bmat)
   556  			}
   557  
   558  			if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
   559  				// Fast path for a common case.
   560  				for i, a := range amat.Data {
   561  					v.setVec(i, a/bmat.Data[i])
   562  				}
   563  				return
   564  			}
   565  			var ia, ib int
   566  			for i := 0; i < ar; i++ {
   567  				v.setVec(i, amat.Data[ia]/bmat.Data[ib])
   568  				ia += amat.Inc
   569  				ib += bmat.Inc
   570  			}
   571  		}
   572  	}
   573  
   574  	for i := 0; i < ar; i++ {
   575  		v.setVec(i, a.AtVec(i)/b.AtVec(i))
   576  	}
   577  }
   578  
   579  // MulVec computes a * b. The result is stored into the receiver.
   580  // MulVec panics if the number of columns in a does not equal the number of rows in b
   581  // or if the number of columns in b does not equal 1.
   582  func (v *VecDense) MulVec(a Matrix, b Vector) {
   583  	r, c := a.Dims()
   584  	br, bc := b.Dims()
   585  	if c != br || bc != 1 {
   586  		panic(ErrShape)
   587  	}
   588  
   589  	aU, trans := untransposeExtract(a)
   590  	var bmat blas64.Vector
   591  	fast := true
   592  	bU, _ := untransposeExtract(b)
   593  	if rv, ok := bU.(*VecDense); ok {
   594  		bmat = rv.mat
   595  		if v != b {
   596  			v.checkOverlap(bmat)
   597  		}
   598  	} else {
   599  		fast = false
   600  	}
   601  
   602  	v.reuseAsNonZeroed(r)
   603  	var restore func()
   604  	if v == aU {
   605  		v, restore = v.isolatedWorkspace(aU.(*VecDense))
   606  		defer restore()
   607  	} else if v == b {
   608  		v, restore = v.isolatedWorkspace(b)
   609  		defer restore()
   610  	}
   611  
   612  	// TODO(kortschak): Improve the non-fast paths.
   613  	switch aU := aU.(type) {
   614  	case Vector:
   615  		if b.Len() == 1 {
   616  			// {n,1} x {1,1}
   617  			v.ScaleVec(b.AtVec(0), aU)
   618  			return
   619  		}
   620  
   621  		// {1,n} x {n,1}
   622  		if fast {
   623  			if rv, ok := aU.(*VecDense); ok {
   624  				amat := rv.mat
   625  				if v != aU {
   626  					v.checkOverlap(amat)
   627  				}
   628  
   629  				if amat.Inc == 1 && bmat.Inc == 1 {
   630  					// Fast path for a common case.
   631  					v.setVec(0, f64.DotUnitary(amat.Data, bmat.Data))
   632  					return
   633  				}
   634  				v.setVec(0, f64.DotInc(amat.Data, bmat.Data,
   635  					uintptr(c), uintptr(amat.Inc), uintptr(bmat.Inc), 0, 0))
   636  				return
   637  			}
   638  		}
   639  		var sum float64
   640  		for i := 0; i < c; i++ {
   641  			sum += aU.AtVec(i) * b.AtVec(i)
   642  		}
   643  		v.setVec(0, sum)
   644  		return
   645  	case *SymBandDense:
   646  		if fast {
   647  			aU.checkOverlap(v.asGeneral())
   648  			blas64.Sbmv(1, aU.mat, bmat, 0, v.mat)
   649  			return
   650  		}
   651  	case *SymDense:
   652  		if fast {
   653  			aU.checkOverlap(v.asGeneral())
   654  			blas64.Symv(1, aU.mat, bmat, 0, v.mat)
   655  			return
   656  		}
   657  	case *TriDense:
   658  		if fast {
   659  			v.CopyVec(b)
   660  			aU.checkOverlap(v.asGeneral())
   661  			ta := blas.NoTrans
   662  			if trans {
   663  				ta = blas.Trans
   664  			}
   665  			blas64.Trmv(ta, aU.mat, v.mat)
   666  			return
   667  		}
   668  	case *Dense:
   669  		if fast {
   670  			aU.checkOverlap(v.asGeneral())
   671  			t := blas.NoTrans
   672  			if trans {
   673  				t = blas.Trans
   674  			}
   675  			blas64.Gemv(t, 1, aU.mat, bmat, 0, v.mat)
   676  			return
   677  		}
   678  	default:
   679  		if fast {
   680  			for i := 0; i < r; i++ {
   681  				var f float64
   682  				for j := 0; j < c; j++ {
   683  					f += a.At(i, j) * bmat.Data[j*bmat.Inc]
   684  				}
   685  				v.setVec(i, f)
   686  			}
   687  			return
   688  		}
   689  	}
   690  
   691  	for i := 0; i < r; i++ {
   692  		var f float64
   693  		for j := 0; j < c; j++ {
   694  			f += a.At(i, j) * b.AtVec(j)
   695  		}
   696  		v.setVec(i, f)
   697  	}
   698  }
   699  
   700  // ReuseAsVec changes the receiver if it IsEmpty() to be of size n×1.
   701  //
   702  // ReuseAsVec re-uses the backing data slice if it has sufficient capacity,
   703  // otherwise a new slice is allocated. The backing data is zero on return.
   704  //
   705  // ReuseAsVec panics if the receiver is not empty, and panics if
   706  // the input size is less than one. To empty the receiver for re-use,
   707  // Reset should be used.
   708  func (v *VecDense) ReuseAsVec(n int) {
   709  	if n <= 0 {
   710  		if n == 0 {
   711  			panic(ErrZeroLength)
   712  		}
   713  		panic(ErrNegativeDimension)
   714  	}
   715  	if !v.IsEmpty() {
   716  		panic(ErrReuseNonEmpty)
   717  	}
   718  	v.reuseAsZeroed(n)
   719  }
   720  
   721  // reuseAsNonZeroed resizes an empty vector to a r×1 vector,
   722  // or checks that a non-empty matrix is r×1.
   723  func (v *VecDense) reuseAsNonZeroed(r int) {
   724  	// reuseAsNonZeroed must be kept in sync with reuseAsZeroed.
   725  	if r == 0 {
   726  		panic(ErrZeroLength)
   727  	}
   728  	if v.IsEmpty() {
   729  		v.mat = blas64.Vector{
   730  			N:    r,
   731  			Inc:  1,
   732  			Data: use(v.mat.Data, r),
   733  		}
   734  		return
   735  	}
   736  	if r != v.mat.N {
   737  		panic(ErrShape)
   738  	}
   739  }
   740  
   741  // reuseAsZeroed resizes an empty vector to a r×1 vector,
   742  // or checks that a non-empty matrix is r×1.
   743  func (v *VecDense) reuseAsZeroed(r int) {
   744  	// reuseAsZeroed must be kept in sync with reuseAsNonZeroed.
   745  	if r == 0 {
   746  		panic(ErrZeroLength)
   747  	}
   748  	if v.IsEmpty() {
   749  		v.mat = blas64.Vector{
   750  			N:    r,
   751  			Inc:  1,
   752  			Data: useZeroed(v.mat.Data, r),
   753  		}
   754  		return
   755  	}
   756  	if r != v.mat.N {
   757  		panic(ErrShape)
   758  	}
   759  	v.Zero()
   760  }
   761  
   762  // IsEmpty returns whether the receiver is empty. Empty matrices can be the
   763  // receiver for size-restricted operations. The receiver can be emptied using
   764  // Reset.
   765  func (v *VecDense) IsEmpty() bool {
   766  	// It must be the case that v.Dims() returns
   767  	// zeros in this case. See comment in Reset().
   768  	return v.mat.Inc == 0
   769  }
   770  
   771  func (v *VecDense) isolatedWorkspace(a Vector) (n *VecDense, restore func()) {
   772  	l := a.Len()
   773  	if l == 0 {
   774  		panic(ErrZeroLength)
   775  	}
   776  	n = getVecDenseWorkspace(l, false)
   777  	return n, func() {
   778  		v.CopyVec(n)
   779  		putVecDenseWorkspace(n)
   780  	}
   781  }
   782  
   783  // asDense returns a Dense representation of the receiver with the same
   784  // underlying data.
   785  func (v *VecDense) asDense() *Dense {
   786  	return &Dense{
   787  		mat:     v.asGeneral(),
   788  		capRows: v.mat.N,
   789  		capCols: 1,
   790  	}
   791  }
   792  
   793  // asGeneral returns a blas64.General representation of the receiver with the
   794  // same underlying data.
   795  func (v *VecDense) asGeneral() blas64.General {
   796  	return blas64.General{
   797  		Rows:   v.mat.N,
   798  		Cols:   1,
   799  		Stride: v.mat.Inc,
   800  		Data:   v.mat.Data,
   801  	}
   802  }
   803  
   804  // ColViewOf reflects the column j of the RawMatrixer m, into the receiver
   805  // backed by the same underlying data. The receiver must either be empty
   806  // have length equal to the number of rows of m.
   807  func (v *VecDense) ColViewOf(m RawMatrixer, j int) {
   808  	rm := m.RawMatrix()
   809  
   810  	if j >= rm.Cols || j < 0 {
   811  		panic(ErrColAccess)
   812  	}
   813  	if !v.IsEmpty() && v.mat.N != rm.Rows {
   814  		panic(ErrShape)
   815  	}
   816  
   817  	v.mat.Inc = rm.Stride
   818  	v.mat.Data = rm.Data[j : (rm.Rows-1)*rm.Stride+j+1]
   819  	v.mat.N = rm.Rows
   820  }
   821  
   822  // RowViewOf reflects the row i of the RawMatrixer m, into the receiver
   823  // backed by the same underlying data. The receiver must either be
   824  // empty or have length equal to the number of columns of m.
   825  func (v *VecDense) RowViewOf(m RawMatrixer, i int) {
   826  	rm := m.RawMatrix()
   827  
   828  	if i >= rm.Rows || i < 0 {
   829  		panic(ErrRowAccess)
   830  	}
   831  	if !v.IsEmpty() && v.mat.N != rm.Cols {
   832  		panic(ErrShape)
   833  	}
   834  
   835  	v.mat.Inc = 1
   836  	v.mat.Data = rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols]
   837  	v.mat.N = rm.Cols
   838  }