From ceb30ae46f1151c09b67f65d43fc746ca5bb5957 Mon Sep 17 00:00:00 2001 From: Simon Parten Date: Wed, 4 Oct 2023 09:33:16 +0200 Subject: [PATCH] Some simple scala ops --- build.sbt | 2 +- .../ai/dragonfly/math/vector/package.scala | 44 ++++++++++++- tests/shared/src/test/scala/SimpleStats.scala | 8 +-- .../src/test/scala/helpers.forTests.scala | 10 +++ .../src/test/scala/simple.vec.ops.scala | 65 +++++++++++++++++++ 5 files changed, 120 insertions(+), 9 deletions(-) create mode 100644 tests/shared/src/test/scala/helpers.forTests.scala create mode 100644 tests/shared/src/test/scala/simple.vec.ops.scala diff --git a/build.sbt b/build.sbt index f7ee715..77d9b95 100644 --- a/build.sbt +++ b/build.sbt @@ -11,7 +11,7 @@ import laika.markdown.github.GitHubFlavor import laika.parse.code.SyntaxHighlighting val appVersion:String = "0.101" -val globalScalaVersion = "3.3.0" +val globalScalaVersion = "3.3.1" ThisBuild / organization := "ai.dragonfly" ThisBuild / organizationName := "dragonfly.ai" diff --git a/slash/shared/src/main/scala/ai/dragonfly/math/vector/package.scala b/slash/shared/src/main/scala/ai/dragonfly/math/vector/package.scala index 5999737..885c8dc 100644 --- a/slash/shared/src/main/scala/ai/dragonfly/math/vector/package.scala +++ b/slash/shared/src/main/scala/ai/dragonfly/math/vector/package.scala @@ -25,10 +25,34 @@ import scala.language.implicitConversions import scala.compiletime.ops.any.== import scala.compiletime.ops.int.* +import ai.dragonfly.math.vector.Vec.copy package object vector { opaque type Vec[N <: Int] = NArray[Double] + + + inline def min[N <: Int](inline v: Vec[N], lt: Double) : Vec[N] = { + import Vec.dimension + val vOut = v.copy + var i = 0 + while (i < v.dimension) { + if (v(i) > lt) vOut(i) = lt + i = i + 1 + } + vOut + } + + inline def max[N <: Int](v: Vec[N], gt: Double) : Vec[N] = { + import Vec.dimension + val vOut = v.copy + var i = 0 + while (i < v.dimension) { + if (v(i) < gt) vOut(i) = gt + i = i + 1 + } + vOut + } object Vec { export narr.Extensions.given @@ -299,7 +323,25 @@ package object vector { inline def euclideanDistanceTo(v0: Vec[N]): Double = Math.sqrt(euclideanDistanceSquaredTo(v0)) - inline def + (v0: Vec[N]): Vec[N] = copy.add(v0) + inline def + (inline v0: Vec[N]): Vec[N] = copy.add(v0) + + inline def + (inline scalar: Double): Vec[N] = + val vOut = copy + var i = 0 + while (i < dimension) { + vOut(i) = vOut(i) + scalar + i = i + 1 + } + vOut + + inline def - (inline scalar: Double): Vec[N] = + val vOut = copy + var i = 0 + while (i < dimension) { + vOut(i) = vOut(i) - scalar + i = i + 1 + } + vOut inline def += (v0: Vec[N]): Vec[N] = add(v0) diff --git a/tests/shared/src/test/scala/SimpleStats.scala b/tests/shared/src/test/scala/SimpleStats.scala index 93bafec..32e196b 100644 --- a/tests/shared/src/test/scala/SimpleStats.scala +++ b/tests/shared/src/test/scala/SimpleStats.scala @@ -59,13 +59,7 @@ class SimpleStats extends munit.FunSuite: } test("elementRanks") { - def assertVecEquals[N <: Int](v1: Vec[N], v2: Vec[N]): Unit = { - var i: Int = 0; - while (i < v1.dimension) { - assertEquals(v1(i), v2(i)) - i += 1 - } - } + assertVecEquals( Vec.tabulate[10]( (i:Int) => 11.0 - i ).elementRanks, Vec[10](10,9,8,7,6,5,4,3,2,1) diff --git a/tests/shared/src/test/scala/helpers.forTests.scala b/tests/shared/src/test/scala/helpers.forTests.scala new file mode 100644 index 0000000..78955e2 --- /dev/null +++ b/tests/shared/src/test/scala/helpers.forTests.scala @@ -0,0 +1,10 @@ +import ai.dragonfly.math.vector.Vec + + +inline def assertVecEquals[N <: Int](inline v1: Vec[N], inline v2: Vec[N])(implicit loc: munit.Location): Unit = { + var i: Int = 0; + while (i < v1.dimension) { + munit.Assertions.assertEquals(v1(i), v2(i)) + i += 1 + } +} \ No newline at end of file diff --git a/tests/shared/src/test/scala/simple.vec.ops.scala b/tests/shared/src/test/scala/simple.vec.ops.scala new file mode 100644 index 0000000..137982a --- /dev/null +++ b/tests/shared/src/test/scala/simple.vec.ops.scala @@ -0,0 +1,65 @@ +import ai.dragonfly.math.vector.* +import narr.* + + + +class SimpleOps extends munit.FunSuite: + + test("vector addition") { + val v1 = Vec[2](1.5, 2.5) + val v2 = Vec[2](2.5, 3.5) + val vResult = Vec[2](4.0, 6.0) + assertVecEquals(v1 + v2, vResult ) + } + test("vector subtraction") { + val v1 = Vec[2](1.5, 2.5) + val v2 = Vec[2](2.5, 3.5) + + val vResult = Vec[2](-1.0, -1.0) + assertVecEquals(v1 - v2, vResult ) + } + + + test("scalar addition") { + val v1 = Vec[3](1.5, 2.5, 3.5) + val vResult = Vec[3](2.5, 3.5, 4.5) + + assertVecEquals( v1 + 1, vResult ) + } + + test("scalar negation") { + val v1 = Vec[3](1.5, 2.5, 3.5) + val vResult = Vec[3](0.5, 1.5, 2.5) + + assertVecEquals( v1 - 1.0, vResult ) + } + + test("scalar multiplication") { + val v1 = Vec[3](1.5, 2.5, 3.5) + val vResult = Vec[3](3.0, 5.0, 7.0) + + assertVecEquals( v1 * 2.0, vResult ) + } + + test("scalar division") { + val v1 = Vec[3](1.5, 2.5, 3.5) + val vResult = Vec[3](0.75, 1.25, 1.75 ) + + assertVecEquals( v1 / 2.0, vResult ) + } + + test("scalar min") { + val v1 = Vec[3](1.5, 2.5, 3.5) + val vResult = Vec[3](1.5, 2.0, 2.0 ) + println( min(v1 , 2.0).csv() ) + assertVecEquals( min(v1 , 2.0), vResult ) + } + + test("scalar max") { + val v1 = Vec[3](1.5, 2.5, 3.5) + val vResult = Vec[3](2.0, 2.5, 3.5 ) + assertVecEquals( max(v1 , 2.0), vResult ) + } + +end SimpleOps +