Skip to content

Commit

Permalink
doc
Browse files Browse the repository at this point in the history
  • Loading branch information
Quafadas committed Sep 13, 2024
1 parent 0fe75b8 commit f19bc20
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 78 deletions.
3 changes: 3 additions & 0 deletions site/docs/_docs/examples.mdoc.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
---
title: Vector Examples
---
# Vector Examples

Some basic exampeles.
Expand Down
48 changes: 45 additions & 3 deletions site/docs/_docs/matrix.mdoc.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,54 @@
---
title: Matrix Examples
---
# Matrix Examples

Some basic exampeles.
Some basic examples. Mdoc calls `toString()` on each line, which actually, we don't want, but can't prevent for an opaque type. It is an annoyance which I believe to be justified - to be clear, you shouldn't use `toString()` to find out about matricies.

```scala mdoc
import vecxt.*
```scala mdoc:to-string

import vecxt.Matrix.*
import vecxt.BoundsCheck.DoBoundsCheck.yes
import narr.*

val nestedArr = NArray(
NArray[Double](1.0, 2.0, 3.5),
NArray[Double](3.0, 4.0, 5.0),
NArray[Double](6.0, 7.0, 8.0)
)

private val matrix = Matrix.fromRows(nestedArr)
private val matrix = Matrix.fromColumns(nestedArr)

println(matrix.shape)

println(matrix.print)

println(matrix.col(1).print)

println(matrix.row(2).print)

println(matrix.elementAt(1, 2))

```
There are only a small number of operations currently supported on matricies, but this sets out a paradigm. If it holds up, then adding more is a detail grind, rather than a risky time investment...

```scala mdoc:to-string

import vecxt.Matrix.*
import vecxt.BoundsCheck.DoBoundsCheck.yes
import narr.*
import vecxt.extensions.*

val mat1 = Matrix(NArray(1.0, 4.0, 2.0, 5.0, 3.0, 6.0), (2, 3))
val mat2 = Matrix(NArray(7.0, 9.0, 11.0, 8.0, 10, 12.0), (3, 2))
val result = mat1.matmul(mat2)

println(result.print)

// @ is a reserved character, so we can't just copy numpy syntax... experimental
val result2 = mat1 :@ mat2

println(result2.print)

```
3 changes: 2 additions & 1 deletion vecxt/js/src/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ package vecxt
import scala.scalajs.js
import scala.scalajs.js.typedarray.Float64Array
import scala.util.chaining.*
import vecxt.Tensors.Matrix
import vecxt.Matrix.*
import vecxt.extensions.matmul

export extensions.*
export vecxt.rpt.Retentions.Retention
Expand Down
2 changes: 1 addition & 1 deletion vecxt/jvm-native/src/dimCheck.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package vecxt

import vecxt.Tensors.Matrix
import vecxt.Matrix.*

protected[vecxt] object dimCheck:
inline def apply[A, B](a: Array[A], b: Array[B])(using inline doCheck: BoundsCheck) =
Expand Down
3 changes: 2 additions & 1 deletion vecxt/jvm/src/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ package vecxt

import dev.ludovic.netlib.blas.JavaBLAS.getInstance as blas
import scala.util.chaining.*
import vecxt.Tensors.Matrix
import vecxt.Matrix.*

export extensions.*
// export vecxt.Matrix.*
export vecxt.rpt.{Retentions, Limits, LossCalc}
export vecxt.rpt.LossCalc.{Agg, Occ}
export vecxt.rpt.Retentions.Retention
Expand Down
2 changes: 1 addition & 1 deletion vecxt/src/dimMatCheck.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package vecxt

import vecxt.Tensors.Matrix
import vecxt.Matrix.*
import narr.*

protected[vecxt] object dimMatCheck:
Expand Down
65 changes: 33 additions & 32 deletions vecxt/src/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@ package vecxt

import narr.*

object Tensors:
object Matrix:

type TupleOfInts[T <: Tuple] <: Boolean = T match
case EmptyTuple => true // Base case: Empty tuple is valid
case Int *: tail => TupleOfInts[tail] // Recursive case: Head is Int, check the tail
case _ => false // If any element is not an Int, return false

opaque type Tensor = (NArray[Double], Tuple)
object Tensor:
def apply[T <: Tuple](a: NArray[Double], b: T)(using ev: TupleOfInts[T] =:= true): Tensor = (a, b)
end Tensor
// opaque type Tensor = (NArray[Double], Tuple)
// object Tensor:
// def apply[T <: Tuple](a: NArray[Double], b: T)(using ev: TupleOfInts[T] =:= true): Tensor = (a, b)
// end Tensor

opaque type Vector1 = (NArray[Double], Tuple1[Int])
type Vector = Vector1 & Tensor
// opaque type Vector = (NArray[Double], Tuple1[Int])
// type Vector = Vector1 & Tensor

object Vector:
def apply(a: NArray[Double]): Vector = (a, Tuple1(a.size))
end Vector
// object Vector:
// def apply(a: NArray[Double]): Vector = (a, Tuple1(a.size))
// end Vector

opaque type Matrix1 = (NArray[Double], Tuple2[Int, Int])
opaque type Matrix = (NArray[Double], Tuple2[Int, Int])

type Matrix = Matrix1 & Tensor
// type Matrix = Matrix1 & Tensor

object Matrix:
inline def apply[T <: Tuple2[Int, Int]](raw: NArray[Double], dim: T)(using inline boundsCheck: BoundsCheck)(using
Expand Down Expand Up @@ -84,26 +84,29 @@ object Tensors:

end Matrix

opaque type StrictMatrix1[M <: Int, N <: Int] = (NArray[Double], Tuple2[M, N]) & Matrix
// opaque type StrictMatrix1[M <: Int, N <: Int] = (NArray[Double], Tuple2[M, N]) & Matrix

type StrictMatrix[M <: Int, N <: Int] = StrictMatrix1[M, N] & Tensor
object StrictMatrix:
def apply[M <: Int, N <: Int](
a: NArray[Double]
)(using ev: TupleOfInts[Tuple2[M, N]] =:= true, m: ValueOf[M], n: ValueOf[N]): StrictMatrix[M, N] =
val tup = (m.value, n.value)
(a, tup)
end apply
end StrictMatrix
// type StrictMatrix[M <: Int, N <: Int] = StrictMatrix1[M, N]
// object StrictMatrix:
// def apply[M <: Int, N <: Int](
// a: NArray[Double]
// )(using ev: TupleOfInts[Tuple2[M, N]] =:= true, m: ValueOf[M], n: ValueOf[N]): StrictMatrix[M, N] =
// val tup = (m.value, n.value)
// (a, tup)
// end apply
// end StrictMatrix

extension (d: Array[Double]) def print: String = d.mkString("[", ",", "],")

extension (m: Matrix)

extension (t: Tensor)
def raw: NArray[Double] = t._1
inline def raw: NArray[Double] = m._1

/** Zero indexed element retrieval
*/
def elementAt[T <: Tuple](b: T)(using ev: TupleOfInts[T] =:= true) =
inline def elementAt[T <: Tuple](b: T)(using ev: TupleOfInts[T] =:= true) =
val indexes = b.toList.asInstanceOf[List[Int]]
val dimensions = t._2.toList.asInstanceOf[List[Int]]
val dimensions = m._2.toList.asInstanceOf[List[Int]]

assert(indexes.length == dimensions.length)

Expand All @@ -114,13 +117,9 @@ object Tensors:
}
.sum

t._1(linearIndex)
m._1(linearIndex)
end elementAt
end extension

extension (d: Array[Double]) def arrPrint: String = d.mkString("[", ",", "],")

extension (m: Matrix)
inline def :@(b: Matrix)(using inline boundsCheck: BoundsCheck): Matrix = m.matmul(b)

inline def scale(d: Double): Unit = m._1 *= d
Expand All @@ -129,6 +128,8 @@ object Tensors:

inline def cols: Int = m._2._2

inline def shape: String = s"${m.rows} x ${m.cols}"

inline def row(i: Int): NArray[Double] =
val result = new NArray[Double](m.cols)
val cols = m.cols
Expand Down Expand Up @@ -177,4 +178,4 @@ object Tensors:
end transpose
end extension

end Tensors
end Matrix
68 changes: 29 additions & 39 deletions vecxt/test/src/TensorExt.test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package vecxt

import munit.FunSuite
import narr.*
import vecxt.Tensors.*
import vecxt.Matrix.*
import vecxt.extensions.*
import vecxt.BoundsCheck.DoBoundsCheck.yes

Expand Down Expand Up @@ -69,21 +69,11 @@ class TensorExtensionSuite extends FunSuite:
}

test("Tensor raw array retrieval") {
val vec = Vector(NArray[Double](1.0, 2.0, 3.0))
assertVecEquals(vec.raw, NArray(1.0, 2.0, 3.0))

val mat = Matrix(NArray[Double](1.0, 2.0, 3.0, 4.0), (2, 2))
assertVecEquals(mat.raw, NArray(1.0, 2.0, 3.0, 4.0))

}

test("Tensor elementAt retrieval for 1D tensor") {
val tensor = Vector(NArray[Double](1.0, 2.0, 3.0))
assertEquals(tensor.elementAt(Tuple1(0)), 1.0)
assertEquals(tensor.elementAt(Tuple1(1)), 2.0)
assertEquals(tensor.elementAt(Tuple1(2)), 3.0)
}

test("Tensor elementAt retrieval for 2D tensor") {
val tensor = Matrix(NArray[Double](1.0, 2.0, 3.0, 4.0), (2, 2))
assertEquals(tensor.elementAt((0, 0)), 1.0)
Expand All @@ -92,46 +82,46 @@ class TensorExtensionSuite extends FunSuite:
assertEquals(tensor.elementAt((1, 1)), 4.0)
}

test("Tensor elementAt retrieval for 3D tensor") {
val tensor = Tensors.Tensor(NArray[Double](1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0), (2, 2, 2))
assertEquals(tensor.elementAt((0, 0, 0)), 1.0)
assertEquals(tensor.elementAt((0, 0, 1)), 2.0)
assertEquals(tensor.elementAt((0, 1, 0)), 3.0)
assertEquals(tensor.elementAt((0, 1, 1)), 4.0)
assertEquals(tensor.elementAt((1, 0, 0)), 5.0)
assertEquals(tensor.elementAt((1, 0, 1)), 6.0)
assertEquals(tensor.elementAt((1, 1, 0)), 7.0)
assertEquals(tensor.elementAt((1, 1, 1)), 8.0)
}

test("Tensor creation") {
val array = NArray[Double](1.0, 2.0, 3.0, 4.0)
val tensor = Tensors.Tensor(array, (2, 2))
assertEquals(tensor.raw, array)
}

test("Vector creation") {
val array = NArray[Double](1.0, 2.0, 3.0)
val vector = Tensors.Vector(array)
assertEquals(vector.raw, array)
}
// test("Tensor elementAt retrieval for 3D tensor") {
// val tensor = Matrix(NArray[Double](1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0), (2, 2, 2))
// assertEquals(tensor.elementAt((0, 0, 0)), 1.0)
// assertEquals(tensor.elementAt((0, 0, 1)), 2.0)
// assertEquals(tensor.elementAt((0, 1, 0)), 3.0)
// assertEquals(tensor.elementAt((0, 1, 1)), 4.0)
// assertEquals(tensor.elementAt((1, 0, 0)), 5.0)
// assertEquals(tensor.elementAt((1, 0, 1)), 6.0)
// assertEquals(tensor.elementAt((1, 1, 0)), 7.0)
// assertEquals(tensor.elementAt((1, 1, 1)), 8.0)
// }

// test("Tensor creation") {
// val array = NArray[Double](1.0, 2.0, 3.0, 4.0)
// val tensor = Tensor(array, (2, 2))
// assertEquals(tensor.raw, array)
// }

// test("Vector creation") {
// val array = NArray[Double](1.0, 2.0, 3.0)
// val vector = Vector(array)
// assertEquals(vector.raw, array)
// }

test("Matrix creation") {
val array = NArray[Double](1.0, 2.0, 3.0, 4.0)
val matrix = Tensors.Matrix(array, (2, 2))
val matrix = Matrix(array, (2, 2))
assertEquals(matrix.raw, array)
}

test("Matrix rows and cols") {
val array = NArray[Double](1.0, 2.0, 3.0, 4.0)
val matrix = Tensors.Matrix(array, (2, 2))
val matrix = Matrix(array, (2, 2))
assertEquals(matrix.rows, 2)
assertEquals(matrix.cols, 2)
}

test("Matrix row extraction") {
val array = NArray[Double](1.0, 2.0, 3.0, 4.0)
val matrix = Tensors.Matrix(array, (2, 2))
val matrix = Matrix(array, (2, 2))
val row = matrix.row(0)
assertVecEquals(row, NArray[Double](1.0, 3.0))

Expand All @@ -141,7 +131,7 @@ class TensorExtensionSuite extends FunSuite:

test("Matrix column extraction") {
val array = NArray[Double](1.0, 2.0, 3.0, 4.0)
val matrix = Tensors.Matrix(array, (2, 2))
val matrix = Matrix(array, (2, 2))
val col1 = matrix.col(0)
assertVecEquals(col1, NArray[Double](1.0, 2.0))

Expand All @@ -160,7 +150,7 @@ class TensorExtensionSuite extends FunSuite:

test("matrix scale") {
val array = NArray[Double](1.0, 2.0, 3.0, 4.0)
val matrix = Tensors.Matrix(array, (2, 2))
val matrix = Matrix(array, (2, 2))
val col1 = matrix.scale(2)
assertVecEquals(matrix.raw, NArray[Double](2.0, 4.0, 6.0, 8.0))
}
Expand Down

0 comments on commit f19bc20

Please sign in to comment.