nox.im · All Posts · All in Go
Every once in a while we come across engineering problems that require matrix and vector calculations. While we can utilize R for experiments and it is awesome at that, for my taste, it’s simply not suitable for anything that runs under performance and memory constraints in production. If you’re familiar with R or Numpy, you dealt with a variety of data types. Since Go is statically typed, Gonum/mat provides implementations of float64 for its linear algebra operations. Go bridges the benefits of two worlds, the fast edit-compile-run cycles from interpreted languages and compile time checks as well as runtime efficiency of compiled languages.
Create a vector with mat.NewVecDense()
:
e := mat.NewVecDense(2, []float64{
1, 1,
})
Note that GoNum treats vectors as a column. To use a vector as a row, you can
transpose it with e.T()
.
e =
⎡1⎤
⎣1⎦
We can print vectors and matrices as above with a small helper function:
func Print(m mat.Matrix, name string) {
spacer := " "
r := mat.Formatted(m, mat.Prefix(spacer), mat.Squeeze())
fmt.Printf("%s = \n%s%v\n\n", name, spacer, r)
}
Create a matrix with math.NewDense()
:
a := mat.NewDense(3, 2, []float64{
1, 0,
0, 1,
0, 1,
})
a =
⎡1 0⎤
⎢0 1⎥
⎣0 1⎦
Gonum operations usually don’t return values and operates on a receiver instead, which can be in-place to allow large matrices to execute without overhead in memory. For example:
// matrix A x vector e with the result being written into matrix A
a.MulVec(a, e)
But we can also allocate a new vector for the result we’re expecting. Note that we have to match the dimensions.
r := mat.NewVecDense(3, make([]float64, 3))
r.MulVec(a, e)
If dimensions mismatch, you will see the mat.ErrShape
error.
ErrShape = Error{"mat: dimension mismatch"}
When dimensions work, you can print the result:
r =
⎡1⎤
⎢1⎥
⎣1⎦
The Hadamard product, or element wise multiplication of two equal sized Matrices can be achieved with:
r.MulElem(a, b)
more to follow soon, I’ll extend this with time…