kompose/vendor/github.com/gonum/matrix/mat64/vector.go
Tomas Kral 1f8a0e06c9
Upgrade OpenShift and its dependencies.
OpenShift version 1.4.0-alpha.0
2016-10-18 12:04:00 +02:00

350 lines
7.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 mat64
import (
"math"
"github.com/gonum/blas"
"github.com/gonum/blas/blas64"
)
var (
vector *Vector
_ Matrix = vector
// _ Cloner = vector
// _ Viewer = vector
// _ Subvectorer = vector
// _ Adder = vector
// _ Suber = vector
// _ Muler = vector
// _ Dotter = vector
// _ ElemMuler = vector
// _ Scaler = vector
// _ Applyer = vector
// _ Normer = vector
// _ Sumer = vector
// _ Stacker = vector
// _ Augmenter = vector
// _ Equaler = vector
// _ ApproxEqualer = vector
// _ RawMatrixLoader = vector
// _ RawMatrixer = vector
)
// Vector represents a column vector.
type Vector struct {
mat blas64.Vector
n int
// A BLAS vector can have a negative increment, but allowing this
// in the mat64 type complicates a lot of code, and doesn't gain anything.
// Vector must have positive increment in this package.
}
// NewVector creates a new Vector of length n. If len(data) == n, data is used
// as the backing data slice. If data == nil, a new slice is allocated. If
// neither of these is true, NewVector will panic.
func NewVector(n int, data []float64) *Vector {
if len(data) != n && data != nil {
panic(ErrShape)
}
if data == nil {
data = make([]float64, n)
}
return &Vector{
mat: blas64.Vector{
Inc: 1,
Data: data,
},
n: n,
}
}
// ViewVec returns a sub-vector view of the receiver starting at element i and
// extending n columns. If i is out of range, or if n is zero or extend beyond the
// bounds of the Vector ViewVec will panic with ErrIndexOutOfRange. The returned
// Vector retains reference to the underlying vector.
func (v *Vector) ViewVec(i, n int) *Vector {
if i+n > v.n {
panic(ErrIndexOutOfRange)
}
return &Vector{
n: n,
mat: blas64.Vector{
Inc: v.mat.Inc,
Data: v.mat.Data[i*v.mat.Inc:],
},
}
}
func (v *Vector) Dims() (r, c int) { return v.n, 1 }
// Len returns the length of the vector.
func (v *Vector) Len() int {
return v.n
}
func (v *Vector) Reset() {
v.mat.Data = v.mat.Data[:0]
v.mat.Inc = 0
v.n = 0
}
func (v *Vector) RawVector() blas64.Vector {
return v.mat
}
// 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 matrices and
// returns the number of rows and columns it copied.
func (v *Vector) CopyVec(a *Vector) (n int) {
n = min(v.Len(), a.Len())
blas64.Copy(n, a.mat, v.mat)
return n
}
// AddVec adds a and b element-wise, placing the result in the receiver.
func (v *Vector) AddVec(a, b *Vector) {
ar := a.Len()
br := b.Len()
if ar != br {
panic(ErrShape)
}
v.reuseAs(ar)
amat, bmat := a.RawVector(), b.RawVector()
for i := 0; i < v.n; i++ {
v.mat.Data[i*v.mat.Inc] = amat.Data[i*amat.Inc] + bmat.Data[i*bmat.Inc]
}
}
// SubVec subtracts the vector b from a, placing the result in the receiver.
func (v *Vector) SubVec(a, b *Vector) {
ar := a.Len()
br := b.Len()
if ar != br {
panic(ErrShape)
}
v.reuseAs(ar)
amat, bmat := a.RawVector(), b.RawVector()
for i := 0; i < v.n; i++ {
v.mat.Data[i*v.mat.Inc] = amat.Data[i*amat.Inc] - bmat.Data[i*bmat.Inc]
}
}
// MulElemVec performs element-wise multiplication of a and b, placing the result
// in the receiver.
func (v *Vector) MulElemVec(a, b *Vector) {
ar := a.Len()
br := b.Len()
if ar != br {
panic(ErrShape)
}
v.reuseAs(ar)
amat, bmat := a.RawVector(), b.RawVector()
for i := 0; i < v.n; i++ {
v.mat.Data[i*v.mat.Inc] = amat.Data[i*amat.Inc] * bmat.Data[i*bmat.Inc]
}
}
// DivElemVec performs element-wise division of a by b, placing the result
// in the receiver.
func (v *Vector) DivElemVec(a, b *Vector) {
ar := a.Len()
br := b.Len()
if ar != br {
panic(ErrShape)
}
v.reuseAs(ar)
amat, bmat := a.RawVector(), b.RawVector()
for i := 0; i < v.n; i++ {
v.mat.Data[i*v.mat.Inc] = amat.Data[i*amat.Inc] / bmat.Data[i*bmat.Inc]
}
}
// MulVec computes a * b if trans == false and a^T * b if trans == true. 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.
func (v *Vector) MulVec(a Matrix, trans bool, b *Vector) {
ar, ac := a.Dims()
br := b.Len()
if trans {
if ar != br {
panic(ErrShape)
}
} else {
if ac != br {
panic(ErrShape)
}
}
var w Vector
if v != a && v != b {
w = *v
}
if w.n == 0 {
if trans {
w.mat.Data = use(w.mat.Data, ac)
} else {
w.mat.Data = use(w.mat.Data, ar)
}
w.mat.Inc = 1
w.n = ar
if trans {
w.n = ac
}
} else {
if trans {
if ac != w.n {
panic(ErrShape)
}
} else {
if ar != w.n {
panic(ErrShape)
}
}
}
switch a := a.(type) {
case RawSymmetricer:
amat := a.RawSymmetric()
blas64.Symv(1, amat, b.mat, 0, w.mat)
case RawTriangular:
w.CopyVec(b)
amat := a.RawTriangular()
ta := blas.NoTrans
if trans {
ta = blas.Trans
}
blas64.Trmv(ta, amat, w.mat)
case RawMatrixer:
amat := a.RawMatrix()
t := blas.NoTrans
if trans {
t = blas.Trans
}
blas64.Gemv(t, 1, amat, b.mat, 0, w.mat)
case Vectorer:
if trans {
col := make([]float64, ar)
for c := 0; c < ac; c++ {
w.mat.Data[c*w.mat.Inc] = blas64.Dot(ar,
blas64.Vector{Inc: 1, Data: a.Col(col, c)},
b.mat,
)
}
} else {
row := make([]float64, ac)
for r := 0; r < ar; r++ {
w.mat.Data[r*w.mat.Inc] = blas64.Dot(ac,
blas64.Vector{Inc: 1, Data: a.Row(row, r)},
b.mat,
)
}
}
default:
if trans {
col := make([]float64, ar)
for c := 0; c < ac; c++ {
for i := range col {
col[i] = a.At(i, c)
}
var f float64
for i, e := range col {
f += e * b.mat.Data[i*b.mat.Inc]
}
w.mat.Data[c*w.mat.Inc] = f
}
} else {
row := make([]float64, ac)
for r := 0; r < ar; r++ {
for i := range row {
row[i] = a.At(r, i)
}
var f float64
for i, e := range row {
f += e * b.mat.Data[i*b.mat.Inc]
}
w.mat.Data[r*w.mat.Inc] = f
}
}
}
*v = w
}
// Equals compares the vectors represented by b and the receiver and returns true
// if the vectors are element-wise equal.
func (v *Vector) EqualsVec(b *Vector) bool {
n := v.Len()
nb := b.Len()
if n != nb {
return false
}
for i := 0; i < n; i++ {
if v.mat.Data[i*v.mat.Inc] != b.mat.Data[i*b.mat.Inc] {
return false
}
}
return true
}
// EqualsApproxVec compares the vectors represented by b and the receiver, with
// tolerance for element-wise equality specified by epsilon.
func (v *Vector) EqualsApproxVec(b *Vector, epsilon float64) bool {
n := v.Len()
nb := b.Len()
if n != nb {
return false
}
for i := 0; i < n; i++ {
if math.Abs(v.mat.Data[i*v.mat.Inc]-b.mat.Data[i*b.mat.Inc]) > epsilon {
return false
}
}
return true
}
// reuseAs resizes an empty vector to a r×1 vector,
// or checks that a non-empty matrix is r×1.
func (v *Vector) reuseAs(r int) {
if v.isZero() {
v.mat = blas64.Vector{
Inc: 1,
Data: use(v.mat.Data, r),
}
v.n = r
return
}
if r != v.n {
panic(ErrShape)
}
}
func (v *Vector) isZero() bool {
// It must be the case that v.Dims() returns
// zeros in this case. See comment in Reset().
return v.mat.Inc == 0
}