diff --git a/QuadTree.Tests/QuadTree.Tests.fsproj b/QuadTree.Tests/QuadTree.Tests.fsproj
index 8697b9a..dd3c1ad 100644
--- a/QuadTree.Tests/QuadTree.Tests.fsproj
+++ b/QuadTree.Tests/QuadTree.Tests.fsproj
@@ -11,6 +11,7 @@
+
diff --git a/QuadTree.Tests/Tests.LinearAlgebra.fs b/QuadTree.Tests/Tests.LinearAlgebra.fs
index e285644..8e3dd45 100644
--- a/QuadTree.Tests/Tests.LinearAlgebra.fs
+++ b/QuadTree.Tests/Tests.LinearAlgebra.fs
@@ -17,59 +17,51 @@ N,N,3,N
=
6,6,14,10
*)
+
+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 leaf_v v = qtree.Leaf << UserValue <| Some v
+let leaf_n () = qtree.Leaf << UserValue <| None
+let leaf_d () = qtree.Leaf Dummy
+
+let vleaf_v v =
+ Vector.btree.Leaf << UserValue <| Some v
+
+let vleaf_n () = Vector.btree.Leaf << UserValue <| None
+let vleaf_d () = Vector.btree.Leaf Dummy
+
[]
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))
- )
+ Matrix.qtree.Node(leaf_n (), leaf_v 1, leaf_v 3, leaf_v 2),
+ Matrix.qtree.Node(leaf_v 1, leaf_n (), leaf_v 2, leaf_v 3),
+ leaf_n (),
+ Matrix.qtree.Node(leaf_v 1, leaf_v 2, leaf_v 3, leaf_n ())
)
let store = Matrix.Storage(4UL, tree)
SparseMatrix(4UL, 4UL, 9UL, store)
let v =
- let tree = Vector.btree.Leaf(UserValue(Some(2)))
+ let tree = vleaf_v 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 tree = Vector.btree.Node(vleaf_v 6, Vector.btree.Node(vleaf_v 14, vleaf_v 10))
let store = Vector.Storage(4UL, tree)
Result.Success(SparseVector(4UL, 4UL, store))
@@ -93,63 +85,23 @@ 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)
- )
+ Matrix.qtree.Node(leaf_n (), leaf_v 1, leaf_v 3, leaf_v 2),
+ Matrix.qtree.Node(leaf_v 1, leaf_n (), leaf_v 2, leaf_v 3),
+ Matrix.qtree.Node(leaf_n (), leaf_n (), leaf_d (), leaf_d ()),
+ Matrix.qtree.Node(leaf_v 1, leaf_v 2, leaf_d (), leaf_d ())
)
let store = Matrix.Storage(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 tree = Vector.btree.Node(vleaf_v 2, Vector.btree.Node(vleaf_v 2, vleaf_d ()))
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 tree = Vector.btree.Node(vleaf_v 6, Vector.btree.Node(vleaf_v 8, vleaf_v 10))
let store = Vector.Storage(4UL, tree)
Result.Success(SparseVector(4UL, 4UL, store))
@@ -174,54 +126,24 @@ 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)
- )
+ Matrix.qtree.Node(leaf_n (), leaf_v 1, leaf_v 3, leaf_v 2),
+ Matrix.qtree.Node(leaf_v 1, leaf_d (), leaf_v 2, leaf_d ()),
+ leaf_n (),
+ Matrix.qtree.Node(leaf_v 1, leaf_d (), leaf_v 3, leaf_d ())
)
let store = Matrix.Storage(4UL, tree)
SparseMatrix(4UL, 3UL, 7UL, store)
let v =
- let tree = Vector.btree.Leaf(UserValue(Some(2)))
+ let tree = vleaf_v 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 tree = Vector.btree.Node(vleaf_v 6, Vector.btree.Node(vleaf_v 14, vleaf_d ()))
let store = Vector.Storage(4UL, tree)
Result.Success(SparseVector(3UL, 3UL, store))
@@ -251,87 +173,35 @@ let ``Simple vxm. 3 * (3x5)`` () =
let tree =
Matrix.qtree.Node(
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)
- )
+ Matrix.qtree.Node(leaf_n (), leaf_v 1, leaf_v 3, leaf_v 2),
+ Matrix.qtree.Node(leaf_v 1, leaf_n (), leaf_v 2, leaf_v 3),
+ Matrix.qtree.Node(leaf_n (), leaf_n (), leaf_d (), leaf_d ()),
+ Matrix.qtree.Node(leaf_v 1, leaf_v 2, leaf_d (), leaf_d ())
),
Matrix.qtree.Node(
- Matrix.qtree.Node(
- Matrix.qtree.Leaf(UserValue(None)),
- Matrix.qtree.Leaf(Dummy),
- Matrix.qtree.Leaf(UserValue(Some(1))),
- 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)
- ),
- Matrix.qtree.Leaf(Dummy)
+ Matrix.qtree.Node(leaf_n (), leaf_d (), leaf_v 1, leaf_d ()),
+ leaf_d (),
+ Matrix.qtree.Node(leaf_n (), leaf_d (), leaf_d (), leaf_d ()),
+ leaf_d ()
),
- Matrix.qtree.Leaf(Dummy),
- Matrix.qtree.Leaf(Dummy)
+ leaf_d (),
+ leaf_d ()
)
let store = Matrix.Storage(8UL, tree)
SparseMatrix(3UL, 5UL, 9UL, 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 tree = Vector.btree.Node(vleaf_v 2, Vector.btree.Node(vleaf_v 2, vleaf_d ()))
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.Node(
- Vector.btree.Leaf(UserValue(Some(6))),
- Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(8))), Vector.btree.Leaf(UserValue(Some(10))))
- ),
- Vector.btree.Node(
- Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(2))), Vector.btree.Leaf(Dummy)),
- Vector.btree.Leaf(Dummy)
- )
+ Vector.btree.Node(vleaf_v 6, Vector.btree.Node(vleaf_v 8, vleaf_v 10)),
+ Vector.btree.Node(Vector.btree.Node(vleaf_v 2, vleaf_d ()), vleaf_d ())
)
let store = Vector.Storage(8UL, tree)
@@ -340,3 +210,171 @@ let ``Simple vxm. 3 * (3x5)`` () =
let actual = LinearAlgebra.vxm op_add op_mult v m
Assert.Equal(expected, actual)
+
+[]
+let ``Simple mxm`` () =
+ // 222D
+ // 222D
+ // 222D
+ // DDDD
+ let tree =
+ qtree.Node(
+ leaf_v 2,
+ qtree.Node(leaf_v 2, leaf_d (), leaf_v 2, leaf_d ()),
+ qtree.Node(leaf_v 2, leaf_v 2, leaf_d (), leaf_d ()),
+ qtree.Node(leaf_v 2, leaf_d (), leaf_d (), leaf_d ())
+ )
+
+ let tree_expected =
+ qtree.Node(
+ leaf_v 12,
+ qtree.Node(leaf_v 12, leaf_d (), leaf_v 12, leaf_d ()),
+ qtree.Node(leaf_v 12, leaf_v 12, leaf_d (), leaf_d ()),
+ qtree.Node(leaf_v 12, leaf_d (), leaf_d (), leaf_d ())
+ )
+
+ let m1 =
+ SparseMatrix(3UL, 3UL, 9UL, Matrix.Storage(4UL, tree))
+
+ let m2 = m1
+
+ let expected =
+ SparseMatrix(3UL, 3UL, 9UL, Matrix.Storage(4UL, tree_expected))
+
+ let actual =
+ match LinearAlgebra.mxm op_add op_mult m1 m2 with
+ | Result.Success m -> m
+ | _ -> failwith "Unreachable"
+
+ Assert.Equal(expected.storage.data, actual.storage.data)
+
+[]
+let ``Sparse mxm`` () =
+ let m1 =
+ let d =
+ [ 0UL, 0UL, 1
+ 1UL, 1UL, 2
+ 2UL, 2UL, 3 ]
+
+ let clist = Matrix.CoordinateList(3UL, 3UL, d)
+ Matrix.fromCoordinateList clist
+
+ let m2 =
+ let d =
+ [ 0UL, 0UL, 3
+ 1UL, 1UL, 2
+ 2UL, 2UL, 1 ]
+
+ let clist = Matrix.CoordinateList(3UL, 3UL, d)
+ Matrix.fromCoordinateList clist
+
+ let expected =
+ let d =
+ [ 0UL, 0UL, 3
+ 1UL, 1UL, 4
+ 2UL, 2UL, 3 ]
+
+ let clist = Matrix.CoordinateList(3UL, 3UL, d)
+ Matrix.fromCoordinateList clist
+
+ let actual =
+ match LinearAlgebra.mxm op_add op_mult m1 m2 with
+ | Result.Success m -> m
+ | Result.Failure e -> failwith (e.ToString())
+
+ Assert.Equal(expected, actual)
+
+[]
+let ``Shrinking mxm`` () =
+ // 2 x 3
+ // 1 0 2
+ // 0 3 0
+ let m1 =
+ let d =
+ [ 0UL, 0UL, 1
+ 0UL, 2UL, 2
+ 1UL, 1UL, 3 ]
+
+ let clist = Matrix.CoordinateList(2UL, 3UL, d)
+ Matrix.fromCoordinateList clist
+
+ // 3 x 2
+ // 0 4
+ // 5 0
+ // 6 0
+ let m2 =
+ let d =
+ [ 0UL, 1UL, 4
+ 1UL, 0UL, 5
+ 2UL, 0UL, 6 ]
+
+ let clist = Matrix.CoordinateList(3UL, 2UL, d)
+ Matrix.fromCoordinateList clist
+
+ // 2 x 2
+ // 12 4
+ // 15 0
+ let expected =
+ let d =
+ [ 0UL, 0UL, 12
+ 0UL, 1UL, 4
+ 1UL, 0UL, 15 ]
+
+ let clist = Matrix.CoordinateList(2UL, 2UL, d)
+ Matrix.fromCoordinateList clist
+
+ let actual =
+ match LinearAlgebra.mxm op_add op_mult m1 m2 with
+ | Result.Success m -> m
+ | Result.Failure e -> failwith (e.ToString())
+
+ Assert.Equal(expected, actual)
+
+[]
+let ``Expanding mxm`` () =
+ // 3 x 2
+ // 1 0
+ // 0 2
+ // 3 0
+ let m1 =
+ let d =
+ [ 0UL, 0UL, 1
+ 1UL, 1UL, 2
+ 2UL, 0UL, 3 ]
+
+ let clist = Matrix.CoordinateList(3UL, 2UL, d)
+ Matrix.fromCoordinateList clist
+ // 2 x 3
+ // 4 5 6
+ // 0 0 0
+ let m2 =
+ let d =
+ [ 0UL, 0UL, 4
+ 0UL, 1UL, 5
+ 0UL, 2UL, 6 ]
+
+ let clist = Matrix.CoordinateList(2UL, 3UL, d)
+ Matrix.fromCoordinateList clist
+
+ // 3 x 3
+ // 4 5 6
+ // 0 0 0
+ // 12 15 18
+ let expected =
+ let d =
+ [ 0UL, 0UL, 4
+ 0UL, 1UL, 5
+ 0UL, 2UL, 6
+ 2UL, 0UL, 12
+ 2UL, 1UL, 15
+ 2UL, 2UL, 18 ]
+
+ let clist = Matrix.CoordinateList(3UL, 3UL, d)
+ Matrix.fromCoordinateList clist
+
+ let actual =
+ match LinearAlgebra.mxm op_add op_mult m1 m2 with
+ | Result.Success m -> m
+ | Result.Failure e -> failwith (e.ToString())
+
+ Assert.Equal(expected, actual)
diff --git a/QuadTree.Tests/Tests.Matrix.fs b/QuadTree.Tests/Tests.Matrix.fs
index bb382a1..a7f4553 100644
--- a/QuadTree.Tests/Tests.Matrix.fs
+++ b/QuadTree.Tests/Tests.Matrix.fs
@@ -15,7 +15,21 @@ let printMatrix (matrix: SparseMatrix<_>) =
printfn " size: %A" matrix.storage.size
printfn " Data: %A" matrix.storage.data
-
+let leaf_v v = qtree.Leaf << UserValue <| Some v
+let leaf_n () = qtree.Leaf << UserValue <| None
+let leaf_d () = qtree.Leaf Dummy
+
+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
(*
N,1,1,N
3,2,2,3
@@ -37,38 +51,17 @@ 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))
- )
+ Matrix.qtree.Node(leaf_n (), leaf_v 1, leaf_v 3, leaf_v 2),
+ Matrix.qtree.Node(leaf_v 1, leaf_n (), leaf_v 2, leaf_v 3),
+ leaf_n (),
+ Matrix.qtree.Node(leaf_v 1, leaf_v 2, leaf_v 3, leaf_n ())
)
let store = Storage(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 tree = Matrix.qtree.Node(leaf_v 1, leaf_v 2, leaf_v 3, leaf_n ())
let store = Storage(4UL, tree)
SparseMatrix(4UL, 4UL, 12UL, store)
@@ -81,20 +74,10 @@ let ``Simple Matrix.map2. Square where number of cols and rows are power of two.
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))
+ Matrix.qtree.Node(leaf_n (), leaf_v 2, leaf_v 4, leaf_v 3),
+ Matrix.qtree.Node(leaf_v 3, leaf_n (), leaf_v 4, leaf_v 5),
+ leaf_n (),
+ leaf_n ()
)
let store = Storage(4UL, tree)
@@ -125,30 +108,10 @@ let ``Simple Matrix.map2. Square where number of cols and rows are not power of
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)
- )
+ Matrix.qtree.Node(leaf_n (), leaf_v 1, leaf_v 3, leaf_v 2),
+ Matrix.qtree.Node(leaf_v 1, leaf_d (), leaf_v 2, leaf_d ()),
+ Matrix.qtree.Node(leaf_n (), leaf_n (), leaf_d (), leaf_d ()),
+ Matrix.qtree.Node(leaf_v 1, leaf_d (), leaf_d (), leaf_d ())
)
let store = Storage(4UL, tree)
@@ -157,25 +120,10 @@ let ``Simple Matrix.map2. Square where number of cols and rows are not power of
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)
- )
+ leaf_v 1,
+ Matrix.qtree.Node(leaf_v 2, leaf_d (), leaf_v 2, leaf_d ()),
+ Matrix.qtree.Node(leaf_v 3, leaf_v 3, leaf_d (), leaf_d ()),
+ Matrix.qtree.Node(leaf_n (), leaf_d (), leaf_d (), leaf_d ())
)
let store = Storage(4UL, tree)
@@ -189,30 +137,10 @@ let ``Simple Matrix.map2. Square where number of cols and rows are not power of
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)
- )
+ Matrix.qtree.Node(leaf_n (), leaf_v 2, leaf_v 4, leaf_v 3),
+ Matrix.qtree.Node(leaf_v 3, leaf_d (), leaf_v 4, leaf_d ()),
+ Matrix.qtree.Node(leaf_n (), leaf_n (), leaf_d (), leaf_d ()),
+ Matrix.qtree.Node(leaf_n (), leaf_d (), leaf_d (), leaf_d ())
)
let store = Storage(4UL, tree)
@@ -303,12 +231,7 @@ let ``Condensation of empty`` () =
// DDDD
// DDDD
let tree =
- qtree.Node(
- qtree.Leaf <| UserValue None,
- qtree.Node(qtree.Leaf <| UserValue None, qtree.Leaf Dummy, qtree.Leaf <| UserValue None, qtree.Leaf Dummy),
- qtree.Leaf Dummy,
- qtree.Leaf Dummy
- )
+ qtree.Node(leaf_n (), qtree.Node(leaf_n (), leaf_d (), leaf_n (), leaf_d ()), leaf_d (), leaf_d ())
let expected =
SparseMatrix(2UL, 3UL, 0UL, Storage(4UL, tree))
@@ -329,23 +252,166 @@ let ``Condensation of sparse`` () =
let tree =
qtree.Node(
- qtree.Leaf <| UserValue None,
- qtree.Node(
- qtree.Leaf << UserValue <| Some 2,
- qtree.Leaf Dummy,
- qtree.Leaf <| UserValue None,
- qtree.Leaf Dummy
- ),
- qtree.Leaf <| UserValue None,
- qtree.Node(
- qtree.Leaf <| UserValue None,
- qtree.Leaf Dummy,
- qtree.Leaf << UserValue <| Some 4,
- qtree.Leaf Dummy
- )
+ leaf_n (),
+ qtree.Node(leaf_v 2, leaf_d (), leaf_n (), leaf_d ()),
+ leaf_n (),
+ qtree.Node(leaf_n (), leaf_d (), leaf_v 4, leaf_d ())
)
let expected =
SparseMatrix(4UL, 3UL, 0UL, Storage(4UL, tree))
Assert.Equal(expected.storage.data, actual.storage.data)
+
+[]
+let ``fold -> sum`` () =
+ // 222D
+ // 222D
+ // 222D
+ // DDDD
+ let tree =
+ qtree.Node(
+ leaf_v 2,
+ qtree.Node(leaf_v 2, leaf_d (), leaf_v 2, leaf_d ()),
+ qtree.Node(leaf_v 2, leaf_v 2, leaf_d (), leaf_d ()),
+ qtree.Node(leaf_v 2, leaf_d (), leaf_d (), leaf_d ())
+ )
+
+ let m1 =
+ SparseMatrix(3UL, 3UL, 9UL, Matrix.Storage(4UL, tree))
+
+ let expected = 18
+
+ let actual = Option.get <| Matrix.foldAssociative op_add None m1
+
+ Assert.Equal(expected, actual)
+
+[]
+let ``4x4 lower triangle`` () =
+ // 2222
+ // 2222
+ // 2222
+ // 2222
+ let tree = leaf_v 2
+
+ // 2NNN
+ // 22NN
+ // 222N
+ // 2222
+ let tree_expected =
+ qtree.Node(
+ qtree.Node(leaf_v 2, leaf_n (), leaf_v 2, leaf_v 2),
+ leaf_n (),
+ leaf_v 2,
+ qtree.Node(leaf_v 2, leaf_n (), leaf_v 2, leaf_v 2)
+ )
+
+ let m1 =
+ SparseMatrix(4UL, 4UL, 16UL, Matrix.Storage(4UL, tree))
+
+ let expected =
+ SparseMatrix(4UL, 4UL, 10UL, Matrix.Storage(4UL, tree_expected))
+
+ let actual = getLowerTriangle m1
+
+ Assert.Equal(expected, actual)
+
+
+[]
+let ``3x3 lower triangle`` () =
+ // 222 D
+ // N22 D
+ // NN2 D
+
+ // DDD D
+ let tree =
+ qtree.Node(
+ qtree.Node(leaf_v 2, leaf_v 2, leaf_n (), leaf_v 2),
+ qtree.Node(leaf_v 2, leaf_d (), leaf_v 2, leaf_d ()),
+ qtree.Node(leaf_n (), leaf_n (), leaf_d (), leaf_d ()),
+ qtree.Node(leaf_v 2, leaf_d (), leaf_d (), leaf_d ())
+ )
+
+
+ // 2NN D
+ // N2N D
+ // NN2 D
+
+ // DDD D
+ let tree_expected =
+ qtree.Node(
+ qtree.Node(leaf_v 2, leaf_n (), leaf_n (), leaf_v 2),
+ qtree.Node(leaf_n (), leaf_d (), leaf_n (), leaf_d ()),
+ qtree.Node(leaf_n (), leaf_n (), leaf_d (), leaf_d ()),
+ qtree.Node(leaf_v 2, leaf_d (), leaf_d (), leaf_d ())
+ )
+
+ let m1 =
+ SparseMatrix(3UL, 3UL, 6UL, Matrix.Storage(4UL, tree))
+
+ let expected =
+ SparseMatrix(3UL, 3UL, 3UL, Matrix.Storage(4UL, tree_expected))
+
+ let actual = getLowerTriangle m1
+
+ Assert.Equal(expected, actual)
+
+[]
+let ``2x3 transposition`` () =
+ // 2N2D
+ // N2ND
+ // DDDD
+ // DDDD
+ let tree =
+ qtree.Node(
+ qtree.Node(leaf_v 2, leaf_n (), leaf_n (), leaf_v 2),
+ qtree.Node(leaf_v 2, leaf_d (), leaf_n (), leaf_d ()),
+ leaf_d (),
+ leaf_d ()
+ )
+
+
+ // 2NDD
+ // N2DD
+ // 2NDD
+ // DDDD
+ let tree_expected =
+ qtree.Node(
+ qtree.Node(leaf_v 2, leaf_n (), leaf_n (), leaf_v 2),
+ leaf_d (),
+ qtree.Node(leaf_v 2, leaf_n (), leaf_d (), leaf_d ()),
+ leaf_d ()
+ )
+
+ let m1 =
+ SparseMatrix(2UL, 3UL, 3UL, Matrix.Storage(4UL, tree))
+
+ let expected =
+ SparseMatrix(3UL, 2UL, 3UL, Matrix.Storage(4UL, tree_expected))
+
+ let actual = transpose m1
+
+ Assert.Equal(expected, actual)
+
+[]
+let ``Fold sum`` () =
+ // 2N2D
+ // N2ND
+ // DDDD
+ // DDDD
+ let tree =
+ qtree.Node(
+ qtree.Node(leaf_v 2, leaf_n (), leaf_n (), leaf_v 2),
+ qtree.Node(leaf_v 2, leaf_d (), leaf_n (), leaf_d ()),
+ leaf_d (),
+ leaf_d ()
+ )
+
+ let m1 =
+ SparseMatrix(2UL, 3UL, 3UL, Matrix.Storage(4UL, tree))
+
+ let expected = 6
+
+ let actual = foldAssociative op_add None m1 |> Option.get
+
+ Assert.Equal(expected, actual)
diff --git a/QuadTree.Tests/Tests.TriangleCount.fs b/QuadTree.Tests/Tests.TriangleCount.fs
new file mode 100644
index 0000000..357be7c
--- /dev/null
+++ b/QuadTree.Tests/Tests.TriangleCount.fs
@@ -0,0 +1,60 @@
+module Graph.TriangleCount.Tests
+
+open System
+open Xunit
+
+open Common
+open Matrix
+open Graph.TriangleCount
+
+[]
+let ``7V Triangle count`` () =
+
+ // 0 1 2 3 4 5 6
+ //
+ // 0 0 1 0 1 0 0 0
+ // 1 1 0 0 1 1 0 1
+ // 2 0 0 0 1 0 1 1
+ // 3 1 1 1 0 0 1 1
+ // 4 0 1 0 0 0 1 1
+ // 5 0 0 1 1 1 0 0
+ // 6 0 1 1 1 1 0 0
+
+ let g =
+ let d =
+ [ 1UL, 0UL, ()
+ 3UL, 0UL, ()
+ 3UL, 1UL, ()
+ 3UL, 2UL, ()
+ 4UL, 1UL, ()
+ 5UL, 2UL, ()
+ 5UL, 3UL, ()
+ 5UL, 4UL, ()
+ 6UL, 1UL, ()
+ 6UL, 2UL, ()
+ 6UL, 3UL, ()
+ 6UL, 4UL, ()
+
+ 0UL, 1UL, ()
+ 0UL, 3UL, ()
+ 1UL, 3UL, ()
+ 2UL, 3UL, ()
+ 1UL, 4UL, ()
+ 2UL, 5UL, ()
+ 3UL, 5UL, ()
+ 4UL, 5UL, ()
+ 1UL, 6UL, ()
+ 2UL, 6UL, ()
+ 3UL, 6UL, ()
+ 4UL, 6UL, () ]
+
+ fromCoordinateList (CoordinateList(7UL, 7UL, d))
+
+ let expected = 5UL
+
+ let actual =
+ match triangle_count g with
+ | Result.Success(Some x) -> x
+ | _ -> failwith "Unreachable"
+
+ Assert.Equal(expected, actual)
diff --git a/QuadTree/LinearAlgebra.fs b/QuadTree/LinearAlgebra.fs
index 618ef52..16a3479 100644
--- a/QuadTree/LinearAlgebra.fs
+++ b/QuadTree/LinearAlgebra.fs
@@ -7,6 +7,7 @@ type Error<'value1, 'value2, 'value3> =
| InconsistentSizeOfArguments of Vector.SparseVector<'value1> * Matrix.SparseMatrix<'value2>
| VectorAdditionProblem of Vector.Error<'value3, 'value3>
+
let rec multScalar op_add (x: uint64) y =
if x = 1UL then
y
@@ -99,3 +100,153 @@ let vxm op_add op_mult (vector: Vector.SparseVector<'a>) (matrix: Matrix.SparseM
|> Result.Success
else
(Error.InconsistentSizeOfArguments(vector, matrix)) |> Result.Failure
+
+
+type MXMError<'value1, 'value2, 'value3> =
+ | InconsistentSizeOfArguments of Matrix.SparseMatrix<'value1> * Matrix.SparseMatrix<'value2>
+ | MatrixAdditionProblem of Matrix.Error<'value3, 'value3>
+
+
+let mxm
+ (op_add: 'c option -> 'c option -> 'c option)
+ (op_mult: 'a option -> 'b option -> 'c option)
+ (m1: Matrix.SparseMatrix<'a>)
+ (m2: Matrix.SparseMatrix<'b>)
+ =
+
+ let rec shrink tree (size: uint64) =
+ match tree with
+ | Matrix.qtree.Node(nw, ne, sw, _) when ne = sw && ne = Matrix.qtree.Leaf Dummy -> shrink nw (size / 2UL)
+ | _ -> tree, size
+
+ let rec expand tree expandRatio =
+ match expandRatio with
+ | 1UL -> tree
+ | _ ->
+ expand
+ (Matrix.mkNode tree (Matrix.qtree.Leaf Dummy) (Matrix.qtree.Leaf Dummy) (Matrix.qtree.Leaf Dummy))
+ (expandRatio / 2UL)
+
+ let rec multiply (size: uint64) m1 m2 =
+ let divided (nw1, ne1, sw1, se1) (nw2, ne2, sw2, se2) =
+ let halfSize = size / 2UL
+
+ // Double check this code
+ let nw1_x_nw2, ne1_x_sw2, nw1_x_ne2, ne1_x_se2, sw1_x_nw2, se1_x_sw2, sw1_x_ne2, se1_x_se2 =
+ (multiply halfSize nw1 nw2),
+ (multiply halfSize ne1 sw2),
+ (multiply halfSize nw1 ne2),
+ (multiply halfSize ne1 se2),
+ (multiply halfSize sw1 nw2),
+ (multiply halfSize se1 sw2),
+ (multiply halfSize sw1 ne2),
+ (multiply halfSize se1 se2)
+
+ match nw1_x_nw2, ne1_x_sw2, nw1_x_ne2, ne1_x_se2, sw1_x_nw2, se1_x_sw2, sw1_x_ne2, se1_x_se2 with
+ | Result.Success(tnw1_x_nw2, nvals_nw1_x_nw2),
+ Result.Success(tne1_x_sw2, nvals_ne1_x_sw2),
+ Result.Success(tnw1_x_ne2, nvals_nw1_x_ne2),
+ Result.Success(tne1_x_se2, nvals_ne1_x_se2),
+ Result.Success(tsw1_x_nw2, nvals_sw1_x_nw2),
+ Result.Success(tse1_x_sw2, nvals_se1_x_sw2),
+ Result.Success(tsw1_x_ne2, nvals_sw1_x_ne2),
+ Result.Success(tse1_x_se2, nvals_se1_x_se2) ->
+ let nrows = (uint64 halfSize) * 1UL
+ let ncols = (uint64 halfSize) * 1UL
+ let storageSize = halfSize
+
+ let nw1_x_nw2 =
+ Matrix.SparseMatrix(nrows, ncols, nvals_nw1_x_nw2, Matrix.Storage(storageSize, tnw1_x_nw2))
+
+ let ne1_x_sw2 =
+ Matrix.SparseMatrix(nrows, ncols, nvals_ne1_x_sw2, Matrix.Storage(storageSize, tne1_x_sw2))
+
+ let nw1_x_ne2 =
+ Matrix.SparseMatrix(nrows, ncols, nvals_nw1_x_ne2, Matrix.Storage(storageSize, tnw1_x_ne2))
+
+ let ne1_x_se2 =
+ Matrix.SparseMatrix(nrows, ncols, nvals_ne1_x_se2, Matrix.Storage(storageSize, tne1_x_se2))
+
+ let sw1_x_nw2 =
+ Matrix.SparseMatrix(nrows, ncols, nvals_sw1_x_nw2, Matrix.Storage(storageSize, tsw1_x_nw2))
+
+ let se1_x_sw2 =
+ Matrix.SparseMatrix(nrows, ncols, nvals_se1_x_sw2, Matrix.Storage(storageSize, tse1_x_sw2))
+
+ let sw1_x_ne2 =
+ Matrix.SparseMatrix(nrows, ncols, nvals_sw1_x_ne2, Matrix.Storage(storageSize, tsw1_x_ne2))
+
+ let se1_x_se2 =
+ Matrix.SparseMatrix(nrows, ncols, nvals_se1_x_se2, Matrix.Storage(storageSize, tse1_x_se2))
+
+ let mAdd m1 (m2: Matrix.SparseMatrix<_>) =
+ match m2.storage.data with
+ | Matrix.qtree.Leaf Dummy -> Result.Success m1
+ | _ -> Matrix.map2 m1 m2 op_add
+
+ let rnw = mAdd nw1_x_nw2 ne1_x_sw2
+ let rne = mAdd nw1_x_ne2 ne1_x_se2
+ let rsw = mAdd sw1_x_nw2 se1_x_sw2
+ let rse = mAdd sw1_x_ne2 se1_x_se2
+
+ match rnw, rne, rsw, rse with
+ | Result.Success(nw), Result.Success(ne), Result.Success(sw), Result.Success(se) ->
+ Result.Success(
+ Matrix.mkNode nw.storage.data ne.storage.data sw.storage.data se.storage.data,
+ nw.nvals + ne.nvals + sw.nvals + se.nvals
+ )
+ | Result.Failure(e), _, _, _
+ | _, Result.Failure(e), _, _
+ | _, _, Result.Failure(e), _
+ | _, _, _, Result.Failure(e) -> Result.Failure(MXMError.MatrixAdditionProblem(e))
+
+ | Result.Failure(e), _, _, _, _, _, _, _
+ | _, Result.Failure(e), _, _, _, _, _, _
+ | _, _, Result.Failure(e), _, _, _, _, _
+ | _, _, _, Result.Failure(e), _, _, _, _
+ | _, _, _, _, Result.Failure(e), _, _, _
+ | _, _, _, _, _, Result.Failure(e), _, _
+ | _, _, _, _, _, _, Result.Failure(e), _
+ | _, _, _, _, _, _, _, Result.Failure(e) -> Result.Failure(e)
+
+ match m1, m2 with
+ | Matrix.qtree.Leaf(UserValue v1), Matrix.qtree.Leaf(UserValue v2) ->
+ let res = multScalar op_add (uint64 size) (op_mult v1 v2)
+
+ let nnz =
+ match res with
+ | None -> 0UL
+ | _ -> (uint64 <| size * size) * 1UL
+
+ Result.Success(Matrix.qtree.Leaf(UserValue res), nnz)
+ | Matrix.qtree.Leaf(UserValue(_)), Matrix.qtree.Node(nw2, ne2, sw2, se2) ->
+ divided (m1, m1, m1, m1) (nw2, ne2, sw2, se2)
+ | Matrix.qtree.Node(nw1, ne1, sw1, se1), Matrix.qtree.Leaf(UserValue(_)) ->
+ divided (nw1, ne1, sw1, se1) (m2, m2, m2, m2)
+ | Matrix.qtree.Node(nw1, ne1, sw1, se1), Matrix.qtree.Node(nw2, ne2, sw2, se2) ->
+ divided (nw1, ne1, sw1, se1) (nw2, ne2, sw2, se2)
+ | Matrix.qtree.Leaf Dummy, _
+ | _, Matrix.qtree.Leaf Dummy -> Result.Success(Matrix.qtree.Leaf Dummy, 0UL)
+
+ if uint64 m1.ncols = uint64 m2.nrows then
+ let nrows = m1.nrows
+ let ncols = m2.ncols
+ let storageSize = max m1.storage.size m2.storage.size
+
+ let m1_tree, m2_tree =
+ if m1.storage.size < m2.storage.size then
+ expand (m1.storage.data) (m2.storage.size / (uint64 m1.storage.size)), m2.storage.data
+ elif m1.storage.size > m2.storage.size then
+ m1.storage.data, expand (m2.storage.data) (m1.storage.size / (uint64 m2.storage.size))
+ else
+ m1.storage.data, m2.storage.data
+
+ match multiply storageSize m1_tree m2_tree with
+ | Result.Success(tree, nvals) ->
+ // in case the resulting storageSize can be smaller
+ // e.g. (2x3) * (3x2) matrices
+ let tree, storageSize = shrink tree storageSize
+ Result.Success(Matrix.SparseMatrix(nrows, ncols, nvals, Matrix.Storage(storageSize, tree)))
+ | Result.Failure(e) -> Result.Failure(e)
+ else
+ MXMError.InconsistentSizeOfArguments(m1, m2) |> Result.Failure
diff --git a/QuadTree/Matrix.fs b/QuadTree/Matrix.fs
index 467ee10..7697762 100644
--- a/QuadTree/Matrix.fs
+++ b/QuadTree/Matrix.fs
@@ -180,48 +180,102 @@ let map2 (matrix1: SparseMatrix<_>) (matrix2: SparseMatrix<_>) f =
else
(Error.InconsistentSizeOfArguments(matrix1, matrix2)) |> Result.Failure
+let foldAssociative (folder: 'T option -> 'T option -> 'T option) (state: 'T option) (matrix: SparseMatrix<'T>) =
+ let rec traverse tree (size: uint64) (state: 'T option) =
+ match tree with
+ | Leaf Dummy -> state
+ | Leaf(UserValue v) ->
+ let area = (uint64 size) * (uint64 size)
-(*
-let rec map (op: 'TCell1 -> 'TCell2) (m1:Matrix<'TCell1>) =
- match m1 with
- | Leaf(s,v1) ->
- Leaf (s, op v1)
- | Node (s,x1,x2,x3,x4) ->
- mkNode s (map op x1) (map op x2) (map op x3) (map op x4)
+ let rec foldValue size accum =
+ if size = 1UL then
+ accum
+ else
+ let halfSize = size / 2UL
+ foldValue halfSize (folder accum accum)
-let multScalar opAdd (x:uint) y =
- if x = 1u
- then y
- else
- List.init (int x) (fun _ -> y)
- |> List.reduce opAdd
-
-let compose opAdd (opMult: 'TCell1 -> 'TCell2 -> 'TCell3) (m1:Matrix<'TCell1>) (m2:Matrix<'TCell2>) =
-
- let rec go m1 m2 =
- match (m1, m2) with
- | Leaf(s,v1), Leaf(_,v2) ->
- Leaf (s, multScalar opAdd s (opMult v1 v2))
- | Node (s,x1,x2,x3,x4), Node (_,y1,y2,y3,y4) ->
- let z1 = map2 opAdd (go x1 y1) (go x2 y3)
- let z2 = map2 opAdd (go x1 y2) (go x2 y4)
- let z3 = map2 opAdd (go x3 y1) (go x4 y3)
- let z4 = map2 opAdd (go x3 y2) (go x4 y4)
- mkNode s z1 z2 z3 z4
- | Node (s,x1,x2,x3,x4), Leaf (_,v) ->
- let l = Leaf(s / 2u,v)
- let z1 = map2 opAdd (go x1 l) (go x2 l)
- let z3 = map2 opAdd (go x3 l) (go x4 l)
- mkNode s z1 z1 z3 z3
- | Leaf (_,v), Node (s,x1,x2,x3,x4) ->
- let l = Leaf(s / 2u,v)
- let z1 = map2 opAdd (go l x1) (go l x3)
- let z2 = map2 opAdd (go l x2) (go l x4)
- mkNode s z1 z2 z1 z2
-
- if m1.Size = m2.Size
- then go m1 m2
- else failwith $"Matrices should be of equals size, but m1.Size = {m1.Size} and m2.Size = {m2.Size}"
+ folder state (foldValue area v)
+ | Node(nw, ne, sw, se) ->
+ let halfSize = size / 2UL
-*)
+ let nwState = traverse nw halfSize state
+ let neState = traverse ne halfSize nwState
+ let swState = traverse sw halfSize neState
+ let seState = traverse se halfSize swState
+
+ seState
+
+ let storageSize = matrix.storage.size
+
+ let tree = matrix.storage.data
+ traverse tree storageSize state
+
+
+let getLowerTriangle (matrix: SparseMatrix<_>) =
+
+ // returns tree, removed_nvals
+ let rec makeNone tree (size: uint64) =
+ match tree with
+ | Leaf Dummy
+ | Leaf(UserValue None) -> tree, 0UL
+ | Leaf(UserValue(Some _)) -> Leaf(UserValue None), (uint64 <| size * size) * 1UL
+ | Node(nw, ne, sw, se) ->
+ let halfSize = size / 2UL
+ let nw_new, nw_removed = makeNone nw halfSize
+ let ne_new, ne_removed = makeNone ne halfSize
+ let sw_new, sw_removed = makeNone sw halfSize
+ let se_new, se_removed = makeNone se halfSize
+
+ (mkNode nw_new ne_new sw_new se_new), nw_removed + ne_removed + sw_removed + se_removed
+
+ let rec traverse tree size =
+ match tree with
+ | Leaf _ when size = 1UL -> tree, 0UL
+ | Leaf Dummy -> Leaf Dummy, 0UL
+ | Leaf _ ->
+ let halfSize = size / 2UL
+
+ let nw, nw_removed = traverse tree halfSize
+
+ let ne, ne_removed =
+ Leaf <| UserValue None, (uint64 <| halfSize * halfSize) * 1UL
+
+ let sw, sw_removed = tree, 0UL