💾 Archived View for nox.im › posts › 2022 › 0328 › matrix-and-vector-arithmetic-with-gonum captured on 2024-08-18 at 18:21:36. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-09-28)

-=-=-=-=-=-=-

Matrix and Vector Arithmetic With Gonum

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[1] 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.

1: Gonum/mat

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...