OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / gonum.org / v1 / gonum / mat / dense_arithmetic.go
diff --git a/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go b/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go
deleted file mode 100644 (file)
index 98de718..0000000
+++ /dev/null
@@ -1,777 +0,0 @@
-// 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 (
-       "math"
-
-       "gonum.org/v1/gonum/blas"
-       "gonum.org/v1/gonum/blas/blas64"
-       "gonum.org/v1/gonum/lapack/lapack64"
-)
-
-// Add adds a and b element-wise, placing the result in the receiver. Add
-// will panic if the two matrices do not have the same shape.
-func (m *Dense) Add(a, b Matrix) {
-       ar, ac := a.Dims()
-       br, bc := b.Dims()
-       if ar != br || ac != bc {
-               panic(ErrShape)
-       }
-
-       aU, _ := untranspose(a)
-       bU, _ := untranspose(b)
-       m.reuseAs(ar, ac)
-
-       if arm, ok := a.(RawMatrixer); ok {
-               if brm, ok := b.(RawMatrixer); ok {
-                       amat, bmat := arm.RawMatrix(), brm.RawMatrix()
-                       if m != aU {
-                               m.checkOverlap(amat)
-                       }
-                       if m != bU {
-                               m.checkOverlap(bmat)
-                       }
-                       for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride {
-                               for i, v := range amat.Data[ja : ja+ac] {
-                                       m.mat.Data[i+jm] = v + bmat.Data[i+jb]
-                               }
-                       }
-                       return
-               }
-       }
-
-       var restore func()
-       if m == aU {
-               m, restore = m.isolatedWorkspace(aU)
-               defer restore()
-       } else if m == bU {
-               m, restore = m.isolatedWorkspace(bU)
-               defer restore()
-       }
-
-       for r := 0; r < ar; r++ {
-               for c := 0; c < ac; c++ {
-                       m.set(r, c, a.At(r, c)+b.At(r, c))
-               }
-       }
-}
-
-// Sub subtracts the matrix b from a, placing the result in the receiver. Sub
-// will panic if the two matrices do not have the same shape.
-func (m *Dense) Sub(a, b Matrix) {
-       ar, ac := a.Dims()
-       br, bc := b.Dims()
-       if ar != br || ac != bc {
-               panic(ErrShape)
-       }
-
-       aU, _ := untranspose(a)
-       bU, _ := untranspose(b)
-       m.reuseAs(ar, ac)
-
-       if arm, ok := a.(RawMatrixer); ok {
-               if brm, ok := b.(RawMatrixer); ok {
-                       amat, bmat := arm.RawMatrix(), brm.RawMatrix()
-                       if m != aU {
-                               m.checkOverlap(amat)
-                       }
-                       if m != bU {
-                               m.checkOverlap(bmat)
-                       }
-                       for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride {
-                               for i, v := range amat.Data[ja : ja+ac] {
-                                       m.mat.Data[i+jm] = v - bmat.Data[i+jb]
-                               }
-                       }
-                       return
-               }
-       }
-
-       var restore func()
-       if m == aU {
-               m, restore = m.isolatedWorkspace(aU)
-               defer restore()
-       } else if m == bU {
-               m, restore = m.isolatedWorkspace(bU)
-               defer restore()
-       }
-
-       for r := 0; r < ar; r++ {
-               for c := 0; c < ac; c++ {
-                       m.set(r, c, a.At(r, c)-b.At(r, c))
-               }
-       }
-}
-
-// MulElem performs element-wise multiplication of a and b, placing the result
-// in the receiver. MulElem will panic if the two matrices do not have the same
-// shape.
-func (m *Dense) MulElem(a, b Matrix) {
-       ar, ac := a.Dims()
-       br, bc := b.Dims()
-       if ar != br || ac != bc {
-               panic(ErrShape)
-       }
-
-       aU, _ := untranspose(a)
-       bU, _ := untranspose(b)
-       m.reuseAs(ar, ac)
-
-       if arm, ok := a.(RawMatrixer); ok {
-               if brm, ok := b.(RawMatrixer); ok {
-                       amat, bmat := arm.RawMatrix(), brm.RawMatrix()
-                       if m != aU {
-                               m.checkOverlap(amat)
-                       }
-                       if m != bU {
-                               m.checkOverlap(bmat)
-                       }
-                       for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride {
-                               for i, v := range amat.Data[ja : ja+ac] {
-                                       m.mat.Data[i+jm] = v * bmat.Data[i+jb]
-                               }
-                       }
-                       return
-               }
-       }
-
-       var restore func()
-       if m == aU {
-               m, restore = m.isolatedWorkspace(aU)
-               defer restore()
-       } else if m == bU {
-               m, restore = m.isolatedWorkspace(bU)
-               defer restore()
-       }
-
-       for r := 0; r < ar; r++ {
-               for c := 0; c < ac; c++ {
-                       m.set(r, c, a.At(r, c)*b.At(r, c))
-               }
-       }
-}
-
-// DivElem performs element-wise division of a by b, placing the result
-// in the receiver. DivElem will panic if the two matrices do not have the same
-// shape.
-func (m *Dense) DivElem(a, b Matrix) {
-       ar, ac := a.Dims()
-       br, bc := b.Dims()
-       if ar != br || ac != bc {
-               panic(ErrShape)
-       }
-
-       aU, _ := untranspose(a)
-       bU, _ := untranspose(b)
-       m.reuseAs(ar, ac)
-
-       if arm, ok := a.(RawMatrixer); ok {
-               if brm, ok := b.(RawMatrixer); ok {
-                       amat, bmat := arm.RawMatrix(), brm.RawMatrix()
-                       if m != aU {
-                               m.checkOverlap(amat)
-                       }
-                       if m != bU {
-                               m.checkOverlap(bmat)
-                       }
-                       for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride {
-                               for i, v := range amat.Data[ja : ja+ac] {
-                                       m.mat.Data[i+jm] = v / bmat.Data[i+jb]
-                               }
-                       }
-                       return
-               }
-       }
-
-       var restore func()
-       if m == aU {
-               m, restore = m.isolatedWorkspace(aU)
-               defer restore()
-       } else if m == bU {
-               m, restore = m.isolatedWorkspace(bU)
-               defer restore()
-       }
-
-       for r := 0; r < ar; r++ {
-               for c := 0; c < ac; c++ {
-                       m.set(r, c, a.At(r, c)/b.At(r, c))
-               }
-       }
-}
-
-// Inverse computes the inverse of the matrix a, storing the result into the
-// receiver. If a is ill-conditioned, a Condition error will be returned.
-// Note that matrix inversion is numerically unstable, and should generally
-// be avoided where possible, for example by using the Solve routines.
-func (m *Dense) Inverse(a Matrix) error {
-       // TODO(btracey): Special case for RawTriangular, etc.
-       r, c := a.Dims()
-       if r != c {
-               panic(ErrSquare)
-       }
-       m.reuseAs(a.Dims())
-       aU, aTrans := untranspose(a)
-       switch rm := aU.(type) {
-       case RawMatrixer:
-               if m != aU || aTrans {
-                       if m == aU || m.checkOverlap(rm.RawMatrix()) {
-                               tmp := getWorkspace(r, c, false)
-                               tmp.Copy(a)
-                               m.Copy(tmp)
-                               putWorkspace(tmp)
-                               break
-                       }
-                       m.Copy(a)
-               }
-       default:
-               m.Copy(a)
-       }
-       ipiv := getInts(r, false)
-       defer putInts(ipiv)
-       ok := lapack64.Getrf(m.mat, ipiv)
-       if !ok {
-               return Condition(math.Inf(1))
-       }
-       work := getFloats(4*r, false) // must be at least 4*r for cond.
-       lapack64.Getri(m.mat, ipiv, work, -1)
-       if int(work[0]) > 4*r {
-               l := int(work[0])
-               putFloats(work)
-               work = getFloats(l, false)
-       } else {
-               work = work[:4*r]
-       }
-       defer putFloats(work)
-       lapack64.Getri(m.mat, ipiv, work, len(work))
-       norm := lapack64.Lange(CondNorm, m.mat, work)
-       rcond := lapack64.Gecon(CondNorm, m.mat, norm, work, ipiv) // reuse ipiv
-       if rcond == 0 {
-               return Condition(math.Inf(1))
-       }
-       cond := 1 / rcond
-       if cond > ConditionTolerance {
-               return Condition(cond)
-       }
-       return nil
-}
-
-// Mul takes the matrix product of a and b, placing the result in the receiver.
-// If the number of columns in a does not equal the number of rows in b, Mul will panic.
-func (m *Dense) Mul(a, b Matrix) {
-       ar, ac := a.Dims()
-       br, bc := b.Dims()
-
-       if ac != br {
-               panic(ErrShape)
-       }
-
-       aU, aTrans := untranspose(a)
-       bU, bTrans := untranspose(b)
-       m.reuseAs(ar, bc)
-       var restore func()
-       if m == aU {
-               m, restore = m.isolatedWorkspace(aU)
-               defer restore()
-       } else if m == bU {
-               m, restore = m.isolatedWorkspace(bU)
-               defer restore()
-       }
-       aT := blas.NoTrans
-       if aTrans {
-               aT = blas.Trans
-       }
-       bT := blas.NoTrans
-       if bTrans {
-               bT = blas.Trans
-       }
-
-       // Some of the cases do not have a transpose option, so create
-       // temporary memory.
-       // C = A^T * B = (B^T * A)^T
-       // C^T = B^T * A.
-       if aUrm, ok := aU.(RawMatrixer); ok {
-               amat := aUrm.RawMatrix()
-               if restore == nil {
-                       m.checkOverlap(amat)
-               }
-               if bUrm, ok := bU.(RawMatrixer); ok {
-                       bmat := bUrm.RawMatrix()
-                       if restore == nil {
-                               m.checkOverlap(bmat)
-                       }
-                       blas64.Gemm(aT, bT, 1, amat, bmat, 0, m.mat)
-                       return
-               }
-               if bU, ok := bU.(RawSymmetricer); ok {
-                       bmat := bU.RawSymmetric()
-                       if aTrans {
-                               c := getWorkspace(ac, ar, false)
-                               blas64.Symm(blas.Left, 1, bmat, amat, 0, c.mat)
-                               strictCopy(m, c.T())
-                               putWorkspace(c)
-                               return
-                       }
-                       blas64.Symm(blas.Right, 1, bmat, amat, 0, m.mat)
-                       return
-               }
-               if bU, ok := bU.(RawTriangular); ok {
-                       // Trmm updates in place, so copy aU first.
-                       bmat := bU.RawTriangular()
-                       if aTrans {
-                               c := getWorkspace(ac, ar, false)
-                               var tmp Dense
-                               tmp.SetRawMatrix(amat)
-                               c.Copy(&tmp)
-                               bT := blas.Trans
-                               if bTrans {
-                                       bT = blas.NoTrans
-                               }
-                               blas64.Trmm(blas.Left, bT, 1, bmat, c.mat)
-                               strictCopy(m, c.T())
-                               putWorkspace(c)
-                               return
-                       }
-                       m.Copy(a)
-                       blas64.Trmm(blas.Right, bT, 1, bmat, m.mat)
-                       return
-               }
-               if bU, ok := bU.(*VecDense); ok {
-                       m.checkOverlap(bU.asGeneral())
-                       bvec := bU.RawVector()
-                       if bTrans {
-                               // {ar,1} x {1,bc}, which is not a vector.
-                               // Instead, construct B as a General.
-                               bmat := blas64.General{
-                                       Rows:   bc,
-                                       Cols:   1,
-                                       Stride: bvec.Inc,
-                                       Data:   bvec.Data,
-                               }
-                               blas64.Gemm(aT, bT, 1, amat, bmat, 0, m.mat)
-                               return
-                       }
-                       cvec := blas64.Vector{
-                               Inc:  m.mat.Stride,
-                               Data: m.mat.Data,
-                       }
-                       blas64.Gemv(aT, 1, amat, bvec, 0, cvec)
-                       return
-               }
-       }
-       if bUrm, ok := bU.(RawMatrixer); ok {
-               bmat := bUrm.RawMatrix()
-               if restore == nil {
-                       m.checkOverlap(bmat)
-               }
-               if aU, ok := aU.(RawSymmetricer); ok {
-                       amat := aU.RawSymmetric()
-                       if bTrans {
-                               c := getWorkspace(bc, br, false)
-                               blas64.Symm(blas.Right, 1, amat, bmat, 0, c.mat)
-                               strictCopy(m, c.T())
-                               putWorkspace(c)
-                               return
-                       }
-                       blas64.Symm(blas.Left, 1, amat, bmat, 0, m.mat)
-                       return
-               }
-               if aU, ok := aU.(RawTriangular); ok {
-                       // Trmm updates in place, so copy bU first.
-                       amat := aU.RawTriangular()
-                       if bTrans {
-                               c := getWorkspace(bc, br, false)
-                               var tmp Dense
-                               tmp.SetRawMatrix(bmat)
-                               c.Copy(&tmp)
-                               aT := blas.Trans
-                               if aTrans {
-                                       aT = blas.NoTrans
-                               }
-                               blas64.Trmm(blas.Right, aT, 1, amat, c.mat)
-                               strictCopy(m, c.T())
-                               putWorkspace(c)
-                               return
-                       }
-                       m.Copy(b)
-                       blas64.Trmm(blas.Left, aT, 1, amat, m.mat)
-                       return
-               }
-               if aU, ok := aU.(*VecDense); ok {
-                       m.checkOverlap(aU.asGeneral())
-                       avec := aU.RawVector()
-                       if aTrans {
-                               // {1,ac} x {ac, bc}
-                               // Transpose B so that the vector is on the right.
-                               cvec := blas64.Vector{
-                                       Inc:  1,
-                                       Data: m.mat.Data,
-                               }
-                               bT := blas.Trans
-                               if bTrans {
-                                       bT = blas.NoTrans
-                               }
-                               blas64.Gemv(bT, 1, bmat, avec, 0, cvec)
-                               return
-                       }
-                       // {ar,1} x {1,bc} which is not a vector result.
-                       // Instead, construct A as a General.
-                       amat := blas64.General{
-                               Rows:   ar,
-                               Cols:   1,
-                               Stride: avec.Inc,
-                               Data:   avec.Data,
-                       }
-                       blas64.Gemm(aT, bT, 1, amat, bmat, 0, m.mat)
-                       return
-               }
-       }
-
-       row := getFloats(ac, false)
-       defer putFloats(row)
-       for r := 0; r < ar; r++ {
-               for i := range row {
-                       row[i] = a.At(r, i)
-               }
-               for c := 0; c < bc; c++ {
-                       var v float64
-                       for i, e := range row {
-                               v += e * b.At(i, c)
-                       }
-                       m.mat.Data[r*m.mat.Stride+c] = v
-               }
-       }
-}
-
-// strictCopy copies a into m panicking if the shape of a and m differ.
-func strictCopy(m *Dense, a Matrix) {
-       r, c := m.Copy(a)
-       if r != m.mat.Rows || c != m.mat.Cols {
-               // Panic with a string since this
-               // is not a user-facing panic.
-               panic(ErrShape.Error())
-       }
-}
-
-// Exp calculates the exponential of the matrix a, e^a, placing the result
-// in the receiver. Exp will panic with matrix.ErrShape if a is not square.
-//
-// Exp uses the scaling and squaring method described in section 3 of
-// http://www.cs.cornell.edu/cv/researchpdf/19ways+.pdf.
-func (m *Dense) Exp(a Matrix) {
-       r, c := a.Dims()
-       if r != c {
-               panic(ErrShape)
-       }
-
-       var w *Dense
-       if m.IsZero() {
-               m.reuseAsZeroed(r, r)
-               w = m
-       } else {
-               w = getWorkspace(r, r, true)
-       }
-       for i := 0; i < r*r; i += r + 1 {
-               w.mat.Data[i] = 1
-       }
-
-       const (
-               terms   = 10
-               scaling = 4
-       )
-
-       small := getWorkspace(r, r, false)
-       small.Scale(math.Pow(2, -scaling), a)
-       power := getWorkspace(r, r, false)
-       power.Copy(small)
-
-       var (
-               tmp   = getWorkspace(r, r, false)
-               factI = 1.
-       )
-       for i := 1.; i < terms; i++ {
-               factI *= i
-
-               // This is OK to do because power and tmp are
-               // new Dense values so all rows are contiguous.
-               // TODO(kortschak) Make this explicit in the NewDense doc comment.
-               for j, v := range power.mat.Data {
-                       tmp.mat.Data[j] = v / factI
-               }
-
-               w.Add(w, tmp)
-               if i < terms-1 {
-                       tmp.Mul(power, small)
-                       tmp, power = power, tmp
-               }
-       }
-       putWorkspace(small)
-       putWorkspace(power)
-       for i := 0; i < scaling; i++ {
-               tmp.Mul(w, w)
-               tmp, w = w, tmp
-       }
-       putWorkspace(tmp)
-
-       if w != m {
-               m.Copy(w)
-               putWorkspace(w)
-       }
-}
-
-// Pow calculates the integral power of the matrix a to n, placing the result
-// in the receiver. Pow will panic if n is negative or if a is not square.
-func (m *Dense) Pow(a Matrix, n int) {
-       if n < 0 {
-               panic("matrix: illegal power")
-       }
-       r, c := a.Dims()
-       if r != c {
-               panic(ErrShape)
-       }
-
-       m.reuseAs(r, c)
-
-       // Take possible fast paths.
-       switch n {
-       case 0:
-               for i := 0; i < r; i++ {
-                       zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c])
-                       m.mat.Data[i*m.mat.Stride+i] = 1
-               }
-               return
-       case 1:
-               m.Copy(a)
-               return
-       case 2:
-               m.Mul(a, a)
-               return
-       }
-
-       // Perform iterative exponentiation by squaring in work space.
-       w := getWorkspace(r, r, false)
-       w.Copy(a)
-       s := getWorkspace(r, r, false)
-       s.Copy(a)
-       x := getWorkspace(r, r, false)
-       for n--; n > 0; n >>= 1 {
-               if n&1 != 0 {
-                       x.Mul(w, s)
-                       w, x = x, w
-               }
-               if n != 1 {
-                       x.Mul(s, s)
-                       s, x = x, s
-               }
-       }
-       m.Copy(w)
-       putWorkspace(w)
-       putWorkspace(s)
-       putWorkspace(x)
-}
-
-// Scale multiplies the elements of a by f, placing the result in the receiver.
-//
-// See the Scaler interface for more information.
-func (m *Dense) Scale(f float64, a Matrix) {
-       ar, ac := a.Dims()
-
-       m.reuseAs(ar, ac)
-
-       aU, aTrans := untranspose(a)
-       if rm, ok := aU.(RawMatrixer); ok {
-               amat := rm.RawMatrix()
-               if m == aU || m.checkOverlap(amat) {
-                       var restore func()
-                       m, restore = m.isolatedWorkspace(a)
-                       defer restore()
-               }
-               if !aTrans {
-                       for ja, jm := 0, 0; ja < ar*amat.Stride; ja, jm = ja+amat.Stride, jm+m.mat.Stride {
-                               for i, v := range amat.Data[ja : ja+ac] {
-                                       m.mat.Data[i+jm] = v * f
-                               }
-                       }
-               } else {
-                       for ja, jm := 0, 0; ja < ac*amat.Stride; ja, jm = ja+amat.Stride, jm+1 {
-                               for i, v := range amat.Data[ja : ja+ar] {
-                                       m.mat.Data[i*m.mat.Stride+jm] = v * f
-                               }
-                       }
-               }
-               return
-       }
-
-       for r := 0; r < ar; r++ {
-               for c := 0; c < ac; c++ {
-                       m.set(r, c, f*a.At(r, c))
-               }
-       }
-}
-
-// Apply applies the function fn to each of the elements of a, placing the
-// resulting matrix in the receiver. The function fn takes a row/column
-// index and element value and returns some function of that tuple.
-func (m *Dense) Apply(fn func(i, j int, v float64) float64, a Matrix) {
-       ar, ac := a.Dims()
-
-       m.reuseAs(ar, ac)
-
-       aU, aTrans := untranspose(a)
-       if rm, ok := aU.(RawMatrixer); ok {
-               amat := rm.RawMatrix()
-               if m == aU || m.checkOverlap(amat) {
-                       var restore func()
-                       m, restore = m.isolatedWorkspace(a)
-                       defer restore()
-               }
-               if !aTrans {
-                       for j, ja, jm := 0, 0, 0; ja < ar*amat.Stride; j, ja, jm = j+1, ja+amat.Stride, jm+m.mat.Stride {
-                               for i, v := range amat.Data[ja : ja+ac] {
-                                       m.mat.Data[i+jm] = fn(j, i, v)
-                               }
-                       }
-               } else {
-                       for j, ja, jm := 0, 0, 0; ja < ac*amat.Stride; j, ja, jm = j+1, ja+amat.Stride, jm+1 {
-                               for i, v := range amat.Data[ja : ja+ar] {
-                                       m.mat.Data[i*m.mat.Stride+jm] = fn(i, j, v)
-                               }
-                       }
-               }
-               return
-       }
-
-       for r := 0; r < ar; r++ {
-               for c := 0; c < ac; c++ {
-                       m.set(r, c, fn(r, c, a.At(r, c)))
-               }
-       }
-}
-
-// RankOne performs a rank-one update to the matrix a and stores the result
-// in the receiver. If a is zero, see Outer.
-//  m = a + alpha * x * y'
-func (m *Dense) RankOne(a Matrix, alpha float64, x, y Vector) {
-       ar, ac := a.Dims()
-       xr, xc := x.Dims()
-       if xr != ar || xc != 1 {
-               panic(ErrShape)
-       }
-       yr, yc := y.Dims()
-       if yr != ac || yc != 1 {
-               panic(ErrShape)
-       }
-
-       if a != m {
-               aU, _ := untranspose(a)
-               if rm, ok := aU.(RawMatrixer); ok {
-                       m.checkOverlap(rm.RawMatrix())
-               }
-       }
-
-       var xmat, ymat blas64.Vector
-       fast := true
-       xU, _ := untranspose(x)
-       if rv, ok := xU.(RawVectorer); ok {
-               xmat = rv.RawVector()
-               m.checkOverlap((&VecDense{mat: xmat, n: x.Len()}).asGeneral())
-       } else {
-               fast = false
-       }
-       yU, _ := untranspose(y)
-       if rv, ok := yU.(RawVectorer); ok {
-               ymat = rv.RawVector()
-               m.checkOverlap((&VecDense{mat: ymat, n: y.Len()}).asGeneral())
-       } else {
-               fast = false
-       }
-
-       if fast {
-               if m != a {
-                       m.reuseAs(ar, ac)
-                       m.Copy(a)
-               }
-               blas64.Ger(alpha, xmat, ymat, m.mat)
-               return
-       }
-
-       m.reuseAs(ar, ac)
-       for i := 0; i < ar; i++ {
-               for j := 0; j < ac; j++ {
-                       m.set(i, j, a.At(i, j)+alpha*x.AtVec(i)*y.AtVec(j))
-               }
-       }
-}
-
-// Outer calculates the outer product of the column vectors x and y,
-// and stores the result in the receiver.
-//  m = alpha * x * y'
-// In order to update an existing matrix, see RankOne.
-func (m *Dense) Outer(alpha float64, x, y Vector) {
-       xr, xc := x.Dims()
-       if xc != 1 {
-               panic(ErrShape)
-       }
-       yr, yc := y.Dims()
-       if yc != 1 {
-               panic(ErrShape)
-       }
-
-       r := xr
-       c := yr
-
-       // Copied from reuseAs with use replaced by useZeroed
-       // and a final zero of the matrix elements if we pass
-       // the shape checks.
-       // TODO(kortschak): Factor out into reuseZeroedAs if
-       // we find another case that needs it.
-       if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols {
-               // Panic as a string, not a mat.Error.
-               panic("mat: caps not correctly set")
-       }
-       if m.IsZero() {
-               m.mat = blas64.General{
-                       Rows:   r,
-                       Cols:   c,
-                       Stride: c,
-                       Data:   useZeroed(m.mat.Data, r*c),
-               }
-               m.capRows = r
-               m.capCols = c
-       } else if r != m.mat.Rows || c != m.mat.Cols {
-               panic(ErrShape)
-       }
-
-       var xmat, ymat blas64.Vector
-       fast := true
-       xU, _ := untranspose(x)
-       if rv, ok := xU.(RawVectorer); ok {
-               xmat = rv.RawVector()
-               m.checkOverlap((&VecDense{mat: xmat, n: x.Len()}).asGeneral())
-       } else {
-               fast = false
-       }
-       yU, _ := untranspose(y)
-       if rv, ok := yU.(RawVectorer); ok {
-               ymat = rv.RawVector()
-               m.checkOverlap((&VecDense{mat: ymat, n: y.Len()}).asGeneral())
-       } else {
-               fast = false
-       }
-
-       if fast {
-               for i := 0; i < r; i++ {
-                       zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c])
-               }
-               blas64.Ger(alpha, xmat, ymat, m.mat)
-               return
-       }
-
-       for i := 0; i < r; i++ {
-               for j := 0; j < c; j++ {
-                       m.set(i, j, alpha*x.AtVec(i)*y.AtVec(j))
-               }
-       }
-}