Vecxt matrix is a higher kinded thing with no bounds. Vecxt tries to squeeze the best performance out of Double
, but doesn't try to impose restrictions on what you can do with it.
Here we offer a matrix multiplication extension method based on Spires typeclasses.
import spire.implicits.*
import spire.algebra.Ring
import scala.reflect.ClassTag
import vecxt.*
import vecxt.all.*
import vecxt.BoundsCheck.BoundsCheck
import narr.*
import BoundsCheck.DoBoundsCheck.yes
object SpireExt:
extension [A: ClassTag: Ring](m1: Matrix[A])
inline def @@@(
m2: Matrix[A]
)(using inline boundsCheck: BoundsCheck): Matrix[A] =
dimMatCheck(m1, m2)
val (r1, c1) = m1.shape
val (r2, c2) = m2.shape
val nar = NArray.ofSize[A](r1 * c2)
val res = Matrix(nar, (r1, c2))
for i <- 0 until r1 do
for j <- 0 until c2 do
res((i, j)) = (0 until c1)
.map { k =>
val i1 = m1((i: Row, k: Col))
val i2 = m2((k: Row, j: Col))
i1 * i2
}
.reduce(_ + _)
end for
res
end @@@
inline def showMat: String =
val (r, c) = m1.shape
val sb = new StringBuilder
for i <- 0 until r do
for j <- 0 until c do
sb.append(m1((i: Row, j: Col))(using BoundsCheck.DoBoundsCheck.no))
sb.append(" ")
end for
sb.append("\n")
end for
sb.toString
end showMat
end extension
end SpireExt
import SpireExt.*
// example from tests
val mat1 = Matrix.fromRows[Complex[Double]](
NArray[Complex[Double]](Complex(1.0, -1.0), Complex(0.0, 2.0), Complex(-2.0, 1.0)),
NArray[Complex[Double]](Complex(0.0, -3.0), Complex(3.0, -2.0), Complex(-1.0, -1.0))
)
val mat2 = Matrix.fromRows[Complex[Double]](
NArray[Complex[Double]](Complex(0.0, -2.0), Complex(1.0, -4.0)),
NArray[Complex[Double]](Complex(-1.0, 3.0), Complex(2.0, -3.0)),
NArray[Complex[Double]](Complex(-2.0, 1.0), Complex(-4.0, 1.0))
)
mat1 @@@ mat2