diff --git a/QuadTree.Tests/QuadTree.Tests.fsproj b/QuadTree.Tests/QuadTree.Tests.fsproj
index e0cd2e3..9d6d3aa 100644
--- a/QuadTree.Tests/QuadTree.Tests.fsproj
+++ b/QuadTree.Tests/QuadTree.Tests.fsproj
@@ -8,6 +8,8 @@
+
+
diff --git a/QuadTree.Tests/Tests.LinearAlgebra.fs b/QuadTree.Tests/Tests.LinearAlgebra.fs
new file mode 100644
index 0000000..7b6196c
--- /dev/null
+++ b/QuadTree.Tests/Tests.LinearAlgebra.fs
@@ -0,0 +1,237 @@
+module LinearAlgebra.Tests
+
+open System
+open Xunit
+
+open Matrix
+open Vector
+open Common
+
+(*
+2,2,2,2
+*
+N,1,1,N
+3,2,2,3
+N,N,1,2
+N,N,3,N
+=
+6,6,14,10
+*)
+[]
+let ``Simple vxm. All sizes are power of two.`` () =
+ let m =
+ let tree =
+ Matrix.qtree.Node(
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(UserValue(Some(2)))
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(UserValue(Some(3)))
+ ),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(UserValue(None))
+ )
+ )
+
+ let store = Matrix.Storage(4UL, 4UL, tree)
+ SparseMatrix(4UL, 4UL, 9UL, store)
+
+ let v =
+ let tree = Vector.btree.Leaf(UserValue(Some(2)))
+
+ let store = Vector.Storage(4UL, tree)
+ SparseVector(4UL, 4UL, store)
+
+ let op_add x y =
+ match (x, y) with
+ | Some(a), Some(b) -> Some(a + b)
+ | Some(a), _
+ | _, Some(a) -> Some(a)
+ | _ -> None
+
+ let op_mult x y =
+ match (x, y) with
+ | Some(a), Some(b) -> Some(a * b)
+ | _ -> None
+
+ let expected =
+ let tree =
+ Vector.btree.Node(
+ Vector.btree.Leaf(UserValue(Some(6))),
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(14))), Vector.btree.Leaf(UserValue(Some(10))))
+ )
+
+ let store = Vector.Storage(4UL, tree)
+ Result.Success(SparseVector(4UL, 4UL, store))
+
+ let actual = LinearAlgebra.vxm op_add op_mult v m
+
+ let eq = actual = expected
+
+ Assert.True(eq)
+
+(*
+2,2,2,D
+*
+N,1,1,N
+3,2,2,3
+N,N,1,2
+D,D,D,D
+=
+6,6,8,10
+*)
+[]
+let ``Simple vxm. 3 * (3x4)`` () =
+ let m =
+ let tree =
+ Matrix.qtree.Node(
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(UserValue(Some(2)))
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(UserValue(Some(3)))
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy)
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy)
+ )
+ )
+
+ let store = Matrix.Storage(4UL, 4UL, tree)
+ SparseMatrix(3UL, 4UL, 8UL, store)
+
+ let v =
+ let tree =
+ Vector.btree.Node(
+ Vector.btree.Leaf(UserValue(Some(2))),
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(2))), Vector.btree.Leaf(Dummy))
+ )
+
+ let store = Vector.Storage(4UL, tree)
+ SparseVector(3UL, 3UL, store)
+
+ let op_add x y =
+ match (x, y) with
+ | Some(a), Some(b) -> Some(a + b)
+ | Some(a), _
+ | _, Some(a) -> Some(a)
+ | _ -> None
+
+ let op_mult x y =
+ match (x, y) with
+ | Some(a), Some(b) -> Some(a * b)
+ | _ -> None
+
+ let expected =
+ let tree =
+ Vector.btree.Node(
+ Vector.btree.Leaf(UserValue(Some(6))),
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(8))), Vector.btree.Leaf(UserValue(Some(10))))
+ )
+
+ let store = Vector.Storage(4UL, tree)
+ Result.Success(SparseVector(4UL, 4UL, store))
+
+ let actual = LinearAlgebra.vxm op_add op_mult v m
+
+ let eq = actual = expected
+
+ Assert.True(eq)
+
+
+(*
+2,2,2,2
+*
+N,1,1,D
+3,2,2,D
+N,N,1,D
+N,N,3,D
+=
+6,6,14,D
+*)
+[]
+let ``Simple vxm. 4 * (4x3).`` () =
+ let m =
+ let tree =
+ Matrix.qtree.Node(
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(UserValue(Some(2)))
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(Dummy)
+ ),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(Dummy)
+ )
+ )
+
+ let store = Matrix.Storage(4UL, 4UL, tree)
+ SparseMatrix(4UL, 3UL, 7UL, store)
+
+ let v =
+ let tree = Vector.btree.Leaf(UserValue(Some(2)))
+
+ let store = Vector.Storage(4UL, tree)
+ SparseVector(4UL, 4UL, store)
+
+ let op_add x y =
+ match (x, y) with
+ | Some(a), Some(b) -> Some(a + b)
+ | Some(a), _
+ | _, Some(a) -> Some(a)
+ | _ -> None
+
+ let op_mult x y =
+ match (x, y) with
+ | Some(a), Some(b) -> Some(a * b)
+ | _ -> None
+
+ let expected =
+ let tree =
+ Vector.btree.Node(
+ Vector.btree.Leaf(UserValue(Some(6))),
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(14))), Vector.btree.Leaf(Dummy))
+ )
+
+ let store = Vector.Storage(4UL, tree)
+ Result.Success(SparseVector(3UL, 3UL, store))
+
+ let actual = LinearAlgebra.vxm op_add op_mult v m
+
+ let eq = actual = expected
+
+ Assert.True(eq)
diff --git a/QuadTree.Tests/Tests.Matrix.fs b/QuadTree.Tests/Tests.Matrix.fs
new file mode 100644
index 0000000..90b678d
--- /dev/null
+++ b/QuadTree.Tests/Tests.Matrix.fs
@@ -0,0 +1,228 @@
+module Matrix.Tests
+
+open System
+open Xunit
+
+open Matrix
+open Common
+
+let printMatrix (matrix: SparseMatrix<_>) =
+ printfn "Matrix:"
+ printfn " Rows: %A" matrix.nrows
+ printfn " Columns: %A" matrix.ncols
+ printfn " Nvals: %A" matrix.nvals
+ printfn " Storage:"
+ printfn " vSize: %A" matrix.storage.vSize
+ printfn " hSize: %A" matrix.storage.hSize
+ printfn " Data: %A" matrix.storage.data
+
+
+(*
+N,1,1,N
+3,2,2,3
+N,N,1,2
+N,N,3,N
++
+1,1,2,2
+1,1,2,2
+3,3,N,N
+3,3,N,N
+=
+N,2,3,N
+4,3,4,5
+N,N,N,N
+N,N,N,N
+*)
+[]
+let ``Simple Matrix.map2. Square where number of cols and rows are power of two.`` () =
+ let m1 =
+ let tree =
+ Matrix.qtree.Node(
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(UserValue(Some(2)))
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(UserValue(Some(3)))
+ ),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(UserValue(None))
+ )
+ )
+
+ let store = Storage(4UL, 4UL, tree)
+ SparseMatrix(4UL, 4UL, 9UL, store)
+
+ let m2 =
+ let tree =
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(UserValue(None))
+ )
+
+ let store = Storage(4UL, 4UL, tree)
+ SparseMatrix(4UL, 4UL, 12UL, store)
+
+ let f x y =
+ match (x, y) with
+ | Some(a), Some(b) -> Some(a + b)
+ | _ -> None
+
+ let expected =
+ let tree =
+ Matrix.qtree.Node(
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(UserValue(Some(4))),
+ Matrix.qtree.Leaf(UserValue(Some(3)))
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(4))),
+ Matrix.qtree.Leaf(UserValue(Some(5)))
+ ),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(None))
+ )
+
+ let store = Storage(4UL, 4UL, tree)
+ Result.Success(SparseMatrix(4UL, 4UL, 6UL, store))
+
+ let actual = Matrix.map2 m1 m2 f
+
+ let eq = actual = expected
+
+ Assert.True(eq)
+
+(*
+N,1,1,D
+3,2,2,D
+N,N,1,D
+D,D,D,D
++
+1,1,2,D
+1,1,2,D
+3,3,N,D
+D,D,D,D
+=
+N,2,3,D
+4,3,4,D
+N,N,N,D
+D,D,D,D
+*)
+[]
+let ``Simple Matrix.map2. Square where number of cols and rows are not power of two.`` () =
+ let m1 =
+ let tree =
+ Matrix.qtree.Node(
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(UserValue(Some(2)))
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(Dummy)
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy)
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy)
+ )
+ )
+
+ let store = Storage(4UL, 4UL, tree)
+ SparseMatrix(3UL, 3UL, 6UL, store)
+
+ let m2 =
+ let tree =
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(1))),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(Dummy)
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy)
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy)
+ )
+ )
+
+ let store = Storage(4UL, 4UL, tree)
+ SparseMatrix(3UL, 3UL, 8UL, store)
+
+ let f x y =
+ match (x, y) with
+ | Some(a), Some(b) -> Some(a + b)
+ | _ -> None
+
+ let expected =
+ let tree =
+ Matrix.qtree.Node(
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(Some(2))),
+ Matrix.qtree.Leaf(UserValue(Some(4))),
+ Matrix.qtree.Leaf(UserValue(Some(3)))
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(Some(3))),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(UserValue(Some(4))),
+ Matrix.qtree.Leaf(Dummy)
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy)
+ ),
+ Matrix.qtree.Node(
+ Matrix.qtree.Leaf(UserValue(None)),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy),
+ Matrix.qtree.Leaf(Dummy)
+ )
+ )
+
+ let store = Storage(4UL, 4UL, tree)
+ Result.Success(SparseMatrix(3UL, 3UL, 5UL, store))
+
+ let actual = Matrix.map2 m1 m2 f
+
+ let eq = actual = expected
+
+ Assert.True(eq)
diff --git a/QuadTree.Tests/Tests.Vector.fs b/QuadTree.Tests/Tests.Vector.fs
index 55f3b77..1f3f32f 100644
--- a/QuadTree.Tests/Tests.Vector.fs
+++ b/QuadTree.Tests/Tests.Vector.fs
@@ -15,12 +15,12 @@ let printVector (vector: SparseVector<_>) =
printfn " Data: %A" vector.storage.data
[]
-let ``Simple map2`` () =
+let ``Simple Vector.map2. Length is power of two.`` () =
let v1 =
let tree =
Vector.btree.Node(
- Vector.btree.Node(Vector.btree.Leaf(Some(1)), Vector.btree.Leaf(None)),
- Vector.btree.Leaf(Some(2))
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(1))), Vector.btree.Leaf(UserValue(None))),
+ Vector.btree.Leaf(UserValue(Some(2)))
)
let store = Storage(8UL, tree)
@@ -29,8 +29,8 @@ let ``Simple map2`` () =
let v2 =
let tree =
Vector.btree.Node(
- Vector.btree.Node(Vector.btree.Leaf(Some(2)), Vector.btree.Leaf(None)),
- Vector.btree.Node(Vector.btree.Leaf(None), Vector.btree.Leaf(Some(1)))
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(2))), Vector.btree.Leaf(UserValue(None))),
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(None)), Vector.btree.Leaf(UserValue(Some(1))))
)
let store = Storage(8UL, tree)
@@ -44,8 +44,8 @@ let ``Simple map2`` () =
let expected =
let tree =
Vector.btree.Node(
- Vector.btree.Node(Vector.btree.Leaf(Some(3)), Vector.btree.Leaf(None)),
- Vector.btree.Node(Vector.btree.Leaf(None), Vector.btree.Leaf(Some(3)))
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(3))), Vector.btree.Leaf(UserValue(None))),
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(None)), Vector.btree.Leaf(UserValue(Some(3))))
)
let store = Storage(8UL, tree)
@@ -56,3 +56,47 @@ let ``Simple map2`` () =
let eq = actual = expected
Assert.True(eq)
+
+
+[]
+let ``Simple Vector.map2. Length is not power of two.`` () =
+ let v1 =
+ let tree =
+ Vector.btree.Node(
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(1))), Vector.btree.Leaf(UserValue(None))),
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(None)), Vector.btree.Leaf(Dummy))
+ )
+
+ let store = Storage(8UL, tree)
+ SparseVector(6UL, 2UL, store)
+
+ let v2 =
+ let tree =
+ Vector.btree.Node(
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(2))), Vector.btree.Leaf(UserValue(None))),
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(None)), Vector.btree.Leaf(Dummy))
+ )
+
+ let store = Storage(8UL, tree)
+ SparseVector(6UL, 2UL, store)
+
+ let f x y =
+ match (x, y) with
+ | Some(a), Some(b) -> Some(a + b)
+ | _ -> None
+
+ let expected =
+ let tree =
+ Vector.btree.Node(
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(3))), Vector.btree.Leaf(UserValue(None))),
+ Vector.btree.Node(Vector.btree.Leaf(UserValue(None)), Vector.btree.Leaf(Dummy))
+ )
+
+ let store = Storage(8UL, tree)
+ Result.Success(SparseVector(6UL, 2UL, store))
+
+ let actual = Vector.map2 v1 v2 f
+
+ let eq = actual = expected
+
+ Assert.True(eq)
diff --git a/QuadTree/Common.fs b/QuadTree/Common.fs
index 0cbc45f..0d57192 100644
--- a/QuadTree/Common.fs
+++ b/QuadTree/Common.fs
@@ -3,6 +3,10 @@ module Common
[]
type nvals
+type 'value treeValue =
+ | Dummy
+ | UserValue of 'value
+
type BinSearchTree<'value> =
| Leaf of 'value
diff --git a/QuadTree/LinearAlgebra.fs b/QuadTree/LinearAlgebra.fs
index ac4d176..db5aada 100644
--- a/QuadTree/LinearAlgebra.fs
+++ b/QuadTree/LinearAlgebra.fs
@@ -1,27 +1,85 @@
module LinearAlgebra
-open Vector
-open Matrix
+open Common
-let rec multScalar op_add (x: uint) y =
- if x = 1u then
+type Error<'value1, 'value2, 'value3> =
+ | InconsistentStructureOfStorages of Vector.btree