func Row(dst []float64, i int, a Matrix) []float64 {
	r, c := a.Dims()
	if i < 0 || i >= r {
		panic(ErrColAccess)
	}
	if dst == nil {
		dst = make([]float64, c)
	} else {
		if len(dst) != c {
			panic(ErrRowLength)
		}
	}
	aU, aTrans := untranspose(a)
	if rm, ok := aU.(RawMatrixer); ok {
		m := rm.RawMatrix()
		if aTrans {
			blas64.Copy(blas64.Vector{N: c, Inc: m.Stride, Data: m.Data[i:]},
				blas64.Vector{N: c, Inc: 1, Data: dst},
			)
			return dst
		}
		copy(dst, m.Data[i*m.Stride:i*m.Stride+m.Cols])
		return dst
	}
	for j := 0; j < c; j++ {
		dst[j] = a.At(i, j)
	}
	return dst
}
Row copies the elements in the ith row of the matrix into the slice dst.
The length of the provided slice must equal the number of columns, unless the
slice is nil in which case a new slice is first allocated.
package mat
import (
	"math"
	"gonum.org/v1/gonum/blas"
	"gonum.org/v1/gonum/blas/blas64"
	"gonum.org/v1/gonum/floats"
	"gonum.org/v1/gonum/lapack"
	"gonum.org/v1/gonum/lapack/lapack64"
)
type Matrix interface {
	Dims() (r, c int)
	At(i, j int) float64
	T() Matrix
}
var (
	_ Matrix       = Transpose{}
	_ Untransposer = Transpose{}
)
type Transpose struct {
	Matrix Matrix
}
func (t Transpose) At(i, j int) float64 {
	return t.Matrix.At(j, i)
}
func (t Transpose) Dims() (r, c int) {
	c, r = t.Matrix.Dims()
	return r, c
}
func (t Transpose) T() Matrix {
	return t.Matrix
}
func (t Transpose) Untranspose() Matrix {
	return t.Matrix
}
type Untransposer interface {
	Untranspose() Matrix
}
type UntransposeBander interface {
	UntransposeBand() Banded
}
type UntransposeTrier interface {
	UntransposeTri() Triangular
}
type UntransposeTriBander interface {
	UntransposeTriBand() TriBanded
}
type Mutable interface {
	Set(i, j int, v float64)
	Matrix
}
type RowViewer interface {
	RowView(i int) Vector
}
type RawRowViewer interface {
	RawRowView(i int) []float64
}
type ColViewer interface {
	ColView(j int) Vector
}
type RawColViewer interface {
	RawColView(j int) []float64
}
type Cloner interface {
	Clone(a Matrix)
}
type Reseter interface {
	Reset()
}
type Copier interface {
	Copy(a Matrix) (r, c int)
}
type Grower interface {
	Caps() (r, c int)
	Grow(r, c int) Matrix
}
type BandWidther interface {
	BandWidth() (k1, k2 int)
}
type RawMatrixSetter interface {
	SetRawMatrix(a blas64.General)
}
type RawMatrixer interface {
	RawMatrix() blas64.General
}
type RawVectorer interface {
	RawVector() blas64.Vector
}
type NonZeroDoer interface {
	DoNonZero(func(i, j int, v float64))
}
type RowNonZeroDoer interface {
	DoRowNonZero(i int, fn func(i, j int, v float64))
}
type ColNonZeroDoer interface {
	DoColNonZero(j int, fn func(i, j int, v float64))
}
func untranspose(a Matrix) (Matrix, bool) {
	if ut, ok := a.(Untransposer); ok {
		return ut.Untranspose(), true
	}
	return a, false
}
func untransposeExtract(a Matrix) (Matrix, bool) {
	ut, trans := untranspose(a)
	switch m := ut.(type) {
	case *DiagDense, *SymBandDense, *TriBandDense, *BandDense, *TriDense, *SymDense, *Dense:
		return m, trans
	case RawSymBander:
		rsb := m.RawSymBand()
		if rsb.Uplo != blas.Upper {
			return ut, trans
		}
		var sb SymBandDense
		sb.SetRawSymBand(rsb)
		return &sb, trans
	case RawTriBander:
		rtb := m.RawTriBand()
		if rtb.Diag == blas.Unit {
			return ut, trans
		}
		var tb TriBandDense
		tb.SetRawTriBand(rtb)
		return &tb, trans
	case RawBander:
		var b BandDense
		b.SetRawBand(m.RawBand())
		return &b, trans
	case RawTriangular:
		rt := m.RawTriangular()
		if rt.Diag == blas.Unit {
			return ut, trans
		}
		var t TriDense
		t.SetRawTriangular(rt)
		return &t, trans
	case RawSymmetricer:
		rs := m.RawSymmetric()
		if rs.Uplo != blas.Upper {
			return ut, trans
		}
		var s SymDense
		s.SetRawSymmetric(rs)
		return &s, trans
	case RawMatrixer:
		var d Dense
		d.SetRawMatrix(m.RawMatrix())
		return &d, trans
	default:
		return ut, trans
	}
}
func Col(dst []float64, j int, a Matrix) []float64 {
	r, c := a.Dims()
	if j < 0 || j >= c {
		panic(ErrColAccess)
	}
	if dst == nil {
		dst = make([]float64, r)
	} else {
		if len(dst) != r {
			panic(ErrColLength)
		}
	}
	aU, aTrans := untranspose(a)
	if rm, ok := aU.(RawMatrixer); ok {
		m := rm.RawMatrix()
		if aTrans {
			copy(dst, m.Data[j*m.Stride:j*m.Stride+m.Cols])
			return dst
		}
		blas64.Copy(blas64.Vector{N: r, Inc: m.Stride, Data: m.Data[j:]},
			blas64.Vector{N: r, Inc: 1, Data: dst},
		)
		return dst
	}
	for i := 0; i < r; i++ {
		dst[i] = a.At(i, j)
	}
	return dst
}