123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809 |
- // Copyright ©2013 The Gonum Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package mat
- import (
- "gonum.org/v1/gonum/blas"
- "gonum.org/v1/gonum/blas/blas64"
- "gonum.org/v1/gonum/internal/asm/f64"
- )
- var (
- vector *VecDense
- _ Matrix = vector
- _ allMatrix = vector
- _ Vector = vector
- _ Reseter = vector
- _ MutableVector = vector
- )
- // Vector is a vector.
- type Vector interface {
- Matrix
- AtVec(int) float64
- Len() int
- }
- // A MutableVector can set elements of a vector.
- type MutableVector interface {
- Vector
- SetVec(i int, v float64)
- }
- // TransposeVec is a type for performing an implicit transpose of a Vector.
- // It implements the Vector interface, returning values from the transpose
- // of the vector within.
- type TransposeVec struct {
- Vector Vector
- }
- // At returns the value of the element at row i and column j of the transposed
- // matrix, that is, row j and column i of the Vector field.
- func (t TransposeVec) At(i, j int) float64 {
- return t.Vector.At(j, i)
- }
- // AtVec returns the element at position i. It panics if i is out of bounds.
- func (t TransposeVec) AtVec(i int) float64 {
- return t.Vector.AtVec(i)
- }
- // Dims returns the dimensions of the transposed vector.
- func (t TransposeVec) Dims() (r, c int) {
- c, r = t.Vector.Dims()
- return r, c
- }
- // T performs an implicit transpose by returning the Vector field.
- func (t TransposeVec) T() Matrix {
- return t.Vector
- }
- // Len returns the number of columns in the vector.
- func (t TransposeVec) Len() int {
- return t.Vector.Len()
- }
- // TVec performs an implicit transpose by returning the Vector field.
- func (t TransposeVec) TVec() Vector {
- return t.Vector
- }
- // Untranspose returns the Vector field.
- func (t TransposeVec) Untranspose() Matrix {
- return t.Vector
- }
- func (t TransposeVec) UntransposeVec() Vector {
- return t.Vector
- }
- // VecDense represents a column vector.
- type VecDense struct {
- mat blas64.Vector
- // A BLAS vector can have a negative increment, but allowing this
- // in the mat type complicates a lot of code, and doesn't gain anything.
- // VecDense must have positive increment in this package.
- }
- // NewVecDense creates a new VecDense of length n. If data == nil,
- // a new slice is allocated for the backing slice. If len(data) == n, data is
- // used as the backing slice, and changes to the elements of the returned VecDense
- // will be reflected in data. If neither of these is true, NewVecDense will panic.
- // NewVecDense will panic if n is zero.
- func NewVecDense(n int, data []float64) *VecDense {
- if n <= 0 {
- if n == 0 {
- panic(ErrZeroLength)
- }
- panic("mat: negative dimension")
- }
- if len(data) != n && data != nil {
- panic(ErrShape)
- }
- if data == nil {
- data = make([]float64, n)
- }
- return &VecDense{
- mat: blas64.Vector{
- N: n,
- Inc: 1,
- Data: data,
- },
- }
- }
- // SliceVec returns a new Vector that shares backing data with the receiver.
- // The returned matrix starts at i of the receiver and extends k-i elements.
- // SliceVec panics with ErrIndexOutOfRange if the slice is outside the capacity
- // of the receiver.
- func (v *VecDense) SliceVec(i, k int) Vector {
- return v.sliceVec(i, k)
- }
- func (v *VecDense) sliceVec(i, k int) *VecDense {
- if i < 0 || k <= i || v.Cap() < k {
- panic(ErrIndexOutOfRange)
- }
- return &VecDense{
- mat: blas64.Vector{
- N: k - i,
- Inc: v.mat.Inc,
- Data: v.mat.Data[i*v.mat.Inc : (k-1)*v.mat.Inc+1],
- },
- }
- }
- // Dims returns the number of rows and columns in the matrix. Columns is always 1
- // for a non-Reset vector.
- func (v *VecDense) Dims() (r, c int) {
- if v.IsEmpty() {
- return 0, 0
- }
- return v.mat.N, 1
- }
- // Caps returns the number of rows and columns in the backing matrix. Columns is always 1
- // for a non-Reset vector.
- func (v *VecDense) Caps() (r, c int) {
- if v.IsEmpty() {
- return 0, 0
- }
- return v.Cap(), 1
- }
- // Len returns the length of the vector.
- func (v *VecDense) Len() int {
- return v.mat.N
- }
- // Cap returns the capacity of the vector.
- func (v *VecDense) Cap() int {
- if v.IsEmpty() {
- return 0
- }
- return (cap(v.mat.Data)-1)/v.mat.Inc + 1
- }
- // T performs an implicit transpose by returning the receiver inside a Transpose.
- func (v *VecDense) T() Matrix {
- return Transpose{v}
- }
- // TVec performs an implicit transpose by returning the receiver inside a TransposeVec.
- func (v *VecDense) TVec() Vector {
- return TransposeVec{v}
- }
- // Reset empties the matrix so that it can be reused as the
- // receiver of a dimensionally restricted operation.
- //
- // Reset should not be used when the matrix shares backing data.
- // See the Reseter interface for more information.
- func (v *VecDense) Reset() {
- // No change of Inc or N to 0 may be
- // made unless both are set to 0.
- v.mat.Inc = 0
- v.mat.N = 0
- v.mat.Data = v.mat.Data[:0]
- }
- // Zero sets all of the matrix elements to zero.
- func (v *VecDense) Zero() {
- for i := 0; i < v.mat.N; i++ {
- v.mat.Data[v.mat.Inc*i] = 0
- }
- }
- // CloneFromVec makes a copy of a into the receiver, overwriting the previous value
- // of the receiver.
- func (v *VecDense) CloneFromVec(a Vector) {
- if v == a {
- return
- }
- n := a.Len()
- v.mat = blas64.Vector{
- N: n,
- Inc: 1,
- Data: use(v.mat.Data, n),
- }
- if r, ok := a.(RawVectorer); ok {
- blas64.Copy(r.RawVector(), v.mat)
- return
- }
- for i := 0; i < a.Len(); i++ {
- v.setVec(i, a.AtVec(i))
- }
- }
- // VecDenseCopyOf returns a newly allocated copy of the elements of a.
- func VecDenseCopyOf(a Vector) *VecDense {
- v := &VecDense{}
- v.CloneFromVec(a)
- return v
- }
- // RawVector returns the underlying blas64.Vector used by the receiver.
- // Changes to elements in the receiver following the call will be reflected
- // in returned blas64.Vector.
- func (v *VecDense) RawVector() blas64.Vector {
- return v.mat
- }
- // SetRawVector sets the underlying blas64.Vector used by the receiver.
- // Changes to elements in the receiver following the call will be reflected
- // in the input.
- func (v *VecDense) SetRawVector(a blas64.Vector) {
- v.mat = a
- }
- // CopyVec makes a copy of elements of a into the receiver. It is similar to the
- // built-in copy; it copies as much as the overlap between the two vectors and
- // returns the number of elements it copied.
- func (v *VecDense) CopyVec(a Vector) int {
- n := min(v.Len(), a.Len())
- if v == a {
- return n
- }
- if r, ok := a.(RawVectorer); ok {
- src := r.RawVector()
- src.N = n
- dst := v.mat
- dst.N = n
- blas64.Copy(src, dst)
- return n
- }
- for i := 0; i < n; i++ {
- v.setVec(i, a.AtVec(i))
- }
- return n
- }
- // ScaleVec scales the vector a by alpha, placing the result in the receiver.
- func (v *VecDense) ScaleVec(alpha float64, a Vector) {
- n := a.Len()
- if v == a {
- if v.mat.Inc == 1 {
- f64.ScalUnitary(alpha, v.mat.Data)
- return
- }
- f64.ScalInc(alpha, v.mat.Data, uintptr(n), uintptr(v.mat.Inc))
- return
- }
- v.reuseAsNonZeroed(n)
- if rv, ok := a.(RawVectorer); ok {
- mat := rv.RawVector()
- v.checkOverlap(mat)
- if v.mat.Inc == 1 && mat.Inc == 1 {
- f64.ScalUnitaryTo(v.mat.Data, alpha, mat.Data)
- return
- }
- f64.ScalIncTo(v.mat.Data, uintptr(v.mat.Inc),
- alpha, mat.Data, uintptr(n), uintptr(mat.Inc))
- return
- }
- for i := 0; i < n; i++ {
- v.setVec(i, alpha*a.AtVec(i))
- }
- }
- // AddScaledVec adds the vectors a and alpha*b, placing the result in the receiver.
- func (v *VecDense) AddScaledVec(a Vector, alpha float64, b Vector) {
- if alpha == 1 {
- v.AddVec(a, b)
- return
- }
- if alpha == -1 {
- v.SubVec(a, b)
- return
- }
- ar := a.Len()
- br := b.Len()
- if ar != br {
- panic(ErrShape)
- }
- var amat, bmat blas64.Vector
- fast := true
- aU, _ := untransposeExtract(a)
- if rv, ok := aU.(*VecDense); ok {
- amat = rv.mat
- if v != a {
- v.checkOverlap(amat)
- }
- } else {
- fast = false
- }
- bU, _ := untransposeExtract(b)
- if rv, ok := bU.(*VecDense); ok {
- bmat = rv.mat
- if v != b {
- v.checkOverlap(bmat)
- }
- } else {
- fast = false
- }
- v.reuseAsNonZeroed(ar)
- switch {
- case alpha == 0: // v <- a
- if v == a {
- return
- }
- v.CopyVec(a)
- case v == a && v == b: // v <- v + alpha * v = (alpha + 1) * v
- blas64.Scal(alpha+1, v.mat)
- case !fast: // v <- a + alpha * b without blas64 support.
- for i := 0; i < ar; i++ {
- v.setVec(i, a.AtVec(i)+alpha*b.AtVec(i))
- }
- case v == a && v != b: // v <- v + alpha * b
- if v.mat.Inc == 1 && bmat.Inc == 1 {
- // Fast path for a common case.
- f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data)
- } else {
- f64.AxpyInc(alpha, bmat.Data, v.mat.Data,
- uintptr(ar), uintptr(bmat.Inc), uintptr(v.mat.Inc), 0, 0)
- }
- default: // v <- a + alpha * b or v <- a + alpha * v
- if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
- // Fast path for a common case.
- f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data)
- } else {
- f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0,
- alpha, bmat.Data, amat.Data,
- uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0)
- }
- }
- }
- // AddVec adds the vectors a and b, placing the result in the receiver.
- func (v *VecDense) AddVec(a, b Vector) {
- ar := a.Len()
- br := b.Len()
- if ar != br {
- panic(ErrShape)
- }
- v.reuseAsNonZeroed(ar)
- aU, _ := untransposeExtract(a)
- bU, _ := untransposeExtract(b)
- if arv, ok := aU.(*VecDense); ok {
- if brv, ok := bU.(*VecDense); ok {
- amat := arv.mat
- bmat := brv.mat
- if v != a {
- v.checkOverlap(amat)
- }
- if v != b {
- v.checkOverlap(bmat)
- }
- if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
- // Fast path for a common case.
- f64.AxpyUnitaryTo(v.mat.Data, 1, bmat.Data, amat.Data)
- return
- }
- f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0,
- 1, bmat.Data, amat.Data,
- uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0)
- return
- }
- }
- for i := 0; i < ar; i++ {
- v.setVec(i, a.AtVec(i)+b.AtVec(i))
- }
- }
- // SubVec subtracts the vector b from a, placing the result in the receiver.
- func (v *VecDense) SubVec(a, b Vector) {
- ar := a.Len()
- br := b.Len()
- if ar != br {
- panic(ErrShape)
- }
- v.reuseAsNonZeroed(ar)
- aU, _ := untransposeExtract(a)
- bU, _ := untransposeExtract(b)
- if arv, ok := aU.(*VecDense); ok {
- if brv, ok := bU.(*VecDense); ok {
- amat := arv.mat
- bmat := brv.mat
- if v != a {
- v.checkOverlap(amat)
- }
- if v != b {
- v.checkOverlap(bmat)
- }
- if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
- // Fast path for a common case.
- f64.AxpyUnitaryTo(v.mat.Data, -1, bmat.Data, amat.Data)
- return
- }
- f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0,
- -1, bmat.Data, amat.Data,
- uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0)
- return
- }
- }
- for i := 0; i < ar; i++ {
- v.setVec(i, a.AtVec(i)-b.AtVec(i))
- }
- }
- // MulElemVec performs element-wise multiplication of a and b, placing the result
- // in the receiver.
- func (v *VecDense) MulElemVec(a, b Vector) {
- ar := a.Len()
- br := b.Len()
- if ar != br {
- panic(ErrShape)
- }
- v.reuseAsNonZeroed(ar)
- aU, _ := untransposeExtract(a)
- bU, _ := untransposeExtract(b)
- if arv, ok := aU.(*VecDense); ok {
- if brv, ok := bU.(*VecDense); ok {
- amat := arv.mat
- bmat := brv.mat
- if v != a {
- v.checkOverlap(amat)
- }
- if v != b {
- v.checkOverlap(bmat)
- }
- if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
- // Fast path for a common case.
- for i, a := range amat.Data {
- v.mat.Data[i] = a * bmat.Data[i]
- }
- return
- }
- var ia, ib int
- for i := 0; i < ar; i++ {
- v.setVec(i, amat.Data[ia]*bmat.Data[ib])
- ia += amat.Inc
- ib += bmat.Inc
- }
- return
- }
- }
- for i := 0; i < ar; i++ {
- v.setVec(i, a.AtVec(i)*b.AtVec(i))
- }
- }
- // DivElemVec performs element-wise division of a by b, placing the result
- // in the receiver.
- func (v *VecDense) DivElemVec(a, b Vector) {
- ar := a.Len()
- br := b.Len()
- if ar != br {
- panic(ErrShape)
- }
- v.reuseAsNonZeroed(ar)
- aU, _ := untransposeExtract(a)
- bU, _ := untransposeExtract(b)
- if arv, ok := aU.(*VecDense); ok {
- if brv, ok := bU.(*VecDense); ok {
- amat := arv.mat
- bmat := brv.mat
- if v != a {
- v.checkOverlap(amat)
- }
- if v != b {
- v.checkOverlap(bmat)
- }
- if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 {
- // Fast path for a common case.
- for i, a := range amat.Data {
- v.setVec(i, a/bmat.Data[i])
- }
- return
- }
- var ia, ib int
- for i := 0; i < ar; i++ {
- v.setVec(i, amat.Data[ia]/bmat.Data[ib])
- ia += amat.Inc
- ib += bmat.Inc
- }
- }
- }
- for i := 0; i < ar; i++ {
- v.setVec(i, a.AtVec(i)/b.AtVec(i))
- }
- }
- // MulVec computes a * b. The result is stored into the receiver.
- // MulVec panics if the number of columns in a does not equal the number of rows in b
- // or if the number of columns in b does not equal 1.
- func (v *VecDense) MulVec(a Matrix, b Vector) {
- r, c := a.Dims()
- br, bc := b.Dims()
- if c != br || bc != 1 {
- panic(ErrShape)
- }
- aU, trans := untransposeExtract(a)
- var bmat blas64.Vector
- fast := true
- bU, _ := untransposeExtract(b)
- if rv, ok := bU.(*VecDense); ok {
- bmat = rv.mat
- if v != b {
- v.checkOverlap(bmat)
- }
- } else {
- fast = false
- }
- v.reuseAsNonZeroed(r)
- var restore func()
- if v == aU {
- v, restore = v.isolatedWorkspace(aU.(*VecDense))
- defer restore()
- } else if v == b {
- v, restore = v.isolatedWorkspace(b)
- defer restore()
- }
- // TODO(kortschak): Improve the non-fast paths.
- switch aU := aU.(type) {
- case Vector:
- if b.Len() == 1 {
- // {n,1} x {1,1}
- v.ScaleVec(b.AtVec(0), aU)
- return
- }
- // {1,n} x {n,1}
- if fast {
- if rv, ok := aU.(*VecDense); ok {
- amat := rv.mat
- if v != aU {
- v.checkOverlap(amat)
- }
- if amat.Inc == 1 && bmat.Inc == 1 {
- // Fast path for a common case.
- v.setVec(0, f64.DotUnitary(amat.Data, bmat.Data))
- return
- }
- v.setVec(0, f64.DotInc(amat.Data, bmat.Data,
- uintptr(c), uintptr(amat.Inc), uintptr(bmat.Inc), 0, 0))
- return
- }
- }
- var sum float64
- for i := 0; i < c; i++ {
- sum += aU.AtVec(i) * b.AtVec(i)
- }
- v.setVec(0, sum)
- return
- case *SymBandDense:
- if fast {
- aU.checkOverlap(v.asGeneral())
- blas64.Sbmv(1, aU.mat, bmat, 0, v.mat)
- return
- }
- case *SymDense:
- if fast {
- aU.checkOverlap(v.asGeneral())
- blas64.Symv(1, aU.mat, bmat, 0, v.mat)
- return
- }
- case *TriDense:
- v.CopyVec(b)
- aU.checkOverlap(v.asGeneral())
- ta := blas.NoTrans
- if trans {
- ta = blas.Trans
- }
- blas64.Trmv(ta, aU.mat, v.mat)
- case *Dense:
- if fast {
- aU.checkOverlap(v.asGeneral())
- t := blas.NoTrans
- if trans {
- t = blas.Trans
- }
- blas64.Gemv(t, 1, aU.mat, bmat, 0, v.mat)
- return
- }
- default:
- if fast {
- for i := 0; i < r; i++ {
- var f float64
- for j := 0; j < c; j++ {
- f += a.At(i, j) * bmat.Data[j*bmat.Inc]
- }
- v.setVec(i, f)
- }
- return
- }
- }
- for i := 0; i < r; i++ {
- var f float64
- for j := 0; j < c; j++ {
- f += a.At(i, j) * b.AtVec(j)
- }
- v.setVec(i, f)
- }
- }
- // ReuseAsVec changes the receiver if it IsEmpty() to be of size n×1.
- //
- // ReuseAsVec re-uses the backing data slice if it has sufficient capacity,
- // otherwise a new slice is allocated. The backing data is zero on return.
- //
- // ReuseAsVec panics if the receiver is not empty, and panics if
- // the input size is less than one. To empty the receiver for re-use,
- // Reset should be used.
- func (v *VecDense) ReuseAsVec(n int) {
- if n <= 0 {
- if n == 0 {
- panic(ErrZeroLength)
- }
- panic(ErrNegativeDimension)
- }
- if !v.IsEmpty() {
- panic(ErrReuseNonEmpty)
- }
- v.reuseAsZeroed(n)
- }
- // reuseAsNonZeroed resizes an empty vector to a r×1 vector,
- // or checks that a non-empty matrix is r×1.
- func (v *VecDense) reuseAsNonZeroed(r int) {
- // reuseAsNonZeroed must be kept in sync with reuseAsZeroed.
- if r == 0 {
- panic(ErrZeroLength)
- }
- if v.IsEmpty() {
- v.mat = blas64.Vector{
- N: r,
- Inc: 1,
- Data: use(v.mat.Data, r),
- }
- return
- }
- if r != v.mat.N {
- panic(ErrShape)
- }
- }
- // reuseAsZeroed resizes an empty vector to a r×1 vector,
- // or checks that a non-empty matrix is r×1.
- func (v *VecDense) reuseAsZeroed(r int) {
- // reuseAsZeroed must be kept in sync with reuseAsNonZeroed.
- if r == 0 {
- panic(ErrZeroLength)
- }
- if v.IsEmpty() {
- v.mat = blas64.Vector{
- N: r,
- Inc: 1,
- Data: useZeroed(v.mat.Data, r),
- }
- return
- }
- if r != v.mat.N {
- panic(ErrShape)
- }
- v.Zero()
- }
- // IsEmpty returns whether the receiver is empty. Empty matrices can be the
- // receiver for size-restricted operations. The receiver can be emptied using
- // Reset.
- func (v *VecDense) IsEmpty() bool {
- // It must be the case that v.Dims() returns
- // zeros in this case. See comment in Reset().
- return v.mat.Inc == 0
- }
- func (v *VecDense) isolatedWorkspace(a Vector) (n *VecDense, restore func()) {
- l := a.Len()
- if l == 0 {
- panic(ErrZeroLength)
- }
- n = getWorkspaceVec(l, false)
- return n, func() {
- v.CopyVec(n)
- putWorkspaceVec(n)
- }
- }
- // asDense returns a Dense representation of the receiver with the same
- // underlying data.
- func (v *VecDense) asDense() *Dense {
- return &Dense{
- mat: v.asGeneral(),
- capRows: v.mat.N,
- capCols: 1,
- }
- }
- // asGeneral returns a blas64.General representation of the receiver with the
- // same underlying data.
- func (v *VecDense) asGeneral() blas64.General {
- return blas64.General{
- Rows: v.mat.N,
- Cols: 1,
- Stride: v.mat.Inc,
- Data: v.mat.Data,
- }
- }
- // ColViewOf reflects the column j of the RawMatrixer m, into the receiver
- // backed by the same underlying data. The receiver must either be empty
- // have length equal to the number of rows of m.
- func (v *VecDense) ColViewOf(m RawMatrixer, j int) {
- rm := m.RawMatrix()
- if j >= rm.Cols || j < 0 {
- panic(ErrColAccess)
- }
- if !v.IsEmpty() && v.mat.N != rm.Rows {
- panic(ErrShape)
- }
- v.mat.Inc = rm.Stride
- v.mat.Data = rm.Data[j : (rm.Rows-1)*rm.Stride+j+1]
- v.mat.N = rm.Rows
- }
- // RowViewOf reflects the row i of the RawMatrixer m, into the receiver
- // backed by the same underlying data. The receiver must either be
- // empty or have length equal to the number of columns of m.
- func (v *VecDense) RowViewOf(m RawMatrixer, i int) {
- rm := m.RawMatrix()
- if i >= rm.Rows || i < 0 {
- panic(ErrRowAccess)
- }
- if !v.IsEmpty() && v.mat.N != rm.Cols {
- panic(ErrShape)
- }
- v.mat.Inc = 1
- v.mat.Data = rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols]
- v.mat.N = rm.Cols
- }
|