diff --git a/QuadTree.Tests/QuadTree.Tests.fsproj b/QuadTree.Tests/QuadTree.Tests.fsproj index ae6bad4..e0cd2e3 100644 --- a/QuadTree.Tests/QuadTree.Tests.fsproj +++ b/QuadTree.Tests/QuadTree.Tests.fsproj @@ -7,6 +7,7 @@ + diff --git a/QuadTree.Tests/Tests.Vector.fs b/QuadTree.Tests/Tests.Vector.fs new file mode 100644 index 0000000..55f3b77 --- /dev/null +++ b/QuadTree.Tests/Tests.Vector.fs @@ -0,0 +1,58 @@ +module Vector.Tests + +open System +open Xunit + +open Vector +open Common + +let printVector (vector: SparseVector<_>) = + printfn "Vector:" + printfn " Length: %A" vector.length + printfn " Nvals: %A" vector.nvals + printfn " Storage:" + printfn " Size: %A" vector.storage.size + printfn " Data: %A" vector.storage.data + +[] +let ``Simple map2`` () = + let v1 = + let tree = + Vector.btree.Node( + Vector.btree.Node(Vector.btree.Leaf(Some(1)), Vector.btree.Leaf(None)), + Vector.btree.Leaf(Some(2)) + ) + + let store = Storage(8UL, tree) + SparseVector(8UL, 6UL, store) + + 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))) + ) + + let store = Storage(8UL, tree) + SparseVector(8UL, 4UL, 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(Some(3)), Vector.btree.Leaf(None)), + Vector.btree.Node(Vector.btree.Leaf(None), Vector.btree.Leaf(Some(3))) + ) + + let store = Storage(8UL, tree) + Result.Success(SparseVector(8UL, 4UL, store)) + + let actual = Vector.map2 v1 v2 f + + let eq = actual = expected + + Assert.True(eq) diff --git a/QuadTree.Tests/Tests.fs b/QuadTree.Tests/Tests.fs index b4f9680..47fe055 100644 --- a/QuadTree.Tests/Tests.fs +++ b/QuadTree.Tests/Tests.fs @@ -3,5 +3,36 @@ open System open Xunit +open Common + +[] +let ``Power of two for 1`` () = + Assert.True(Common.getNearestUpperPowerOfTwo 1UL = 1UL) + +[] +let ``Power of two for 2`` () = + Assert.True(Common.getNearestUpperPowerOfTwo 2UL = 2UL) + +[] +let ``Power of two for 3`` () = + Assert.True(Common.getNearestUpperPowerOfTwo 3UL = 4UL) + +[] +let ``Power of two for 12`` () = + Assert.True(Common.getNearestUpperPowerOfTwo 12UL = 16UL) + +[] +let ``Power of two for 1025`` () = + Assert.True(Common.getNearestUpperPowerOfTwo 1025UL = 2048UL) + +[] +let ``Power of two for 524290`` () = + Assert.True(Common.getNearestUpperPowerOfTwo 524290UL = 1048576UL) + +[] +let ``Power of two for 1048576`` () = + Assert.True(Common.getNearestUpperPowerOfTwo 1048576UL = 1048576UL) + [] -let ``My test`` () = Assert.True(true) +let ``Power of two for 4611686018427388001`` () = + Assert.True(Common.getNearestUpperPowerOfTwo 4611686018427388001UL = 9223372036854776000UL) diff --git a/QuadTree/Common.fs b/QuadTree/Common.fs index d4eb2bc..0cbc45f 100644 --- a/QuadTree/Common.fs +++ b/QuadTree/Common.fs @@ -1,5 +1,9 @@ module Common +[] +type nvals + + type BinSearchTree<'value> = | Leaf of 'value | Node of BinSearchTree<'value> * 'value * BinSearchTree<'value> @@ -117,13 +121,19 @@ let treeOfPowersOfTwo = ) let getNearestUpperPowerOfTwo (x: uint64) = + let MAX = 9223372036854776000UL + let rec find tree rightBound = match tree with | BinSearchTree.Node(left, v, right) -> if x = v then v elif x < v then find left v - elif x <= rightBound then rightBound - else failwith "Unfinished" - | _ -> failwith "Unfinished" - - find treeOfPowersOfTwo 9223372036854776000UL + else find right rightBound + | BinSearchTree.Leaf(v) -> if x <= v then v else rightBound + + if x = MAX then + MAX + elif x < MAX then + find treeOfPowersOfTwo 9223372036854776000UL + else + failwithf "Argument is too large. Must be not greater then %A" MAX diff --git a/QuadTree/LinearAlgebra.fs b/QuadTree/LinearAlgebra.fs index 6e36935..ac4d176 100644 --- a/QuadTree/LinearAlgebra.fs +++ b/QuadTree/LinearAlgebra.fs @@ -12,7 +12,7 @@ let rec multScalar op_add (x: uint) y = if x % 2u = 0u then res else op_add res v let vxm op_add op_mult (vector: SparseVector<'a>) (matrix: SparseMatrix<'b>) = - if vector.length = uint matrix.nrows then + if uint64 vector.length = uint64 matrix.nrows then let inner len vector matrix = match (vector, matrix) with | btree.Leaf(v1), qtree.Leaf(v2) -> diff --git a/QuadTree/Matrix.fs b/QuadTree/Matrix.fs index 10c7873..dfb273a 100644 --- a/QuadTree/Matrix.fs +++ b/QuadTree/Matrix.fs @@ -1,5 +1,6 @@ module Matrix +open Common (* | x1 | x2 | ---------- @@ -16,8 +17,6 @@ type columnId [] type rowId -[] -type nvals [] type SparseMatrix<'value> = diff --git a/QuadTree/Vector.fs b/QuadTree/Vector.fs index cc7e726..002d54a 100644 --- a/QuadTree/Vector.fs +++ b/QuadTree/Vector.fs @@ -1,14 +1,28 @@ module Vector +open Common + type 'value btree = | Leaf of 'value | Node of 'value btree * 'value btree +[] +type dataLength + +[] +type storageSize + +[] +type Storage<'value> = + val size: uint64 + val data: btree<'value> + new(_size, _data) = { size = _size; data = _data } + [] type SparseVector<'value> = - val length: uint - val nvals: uint - val storage: btree> + val length: uint64 + val nvals: uint64 + val storage: Storage> new(_length, _nvals, _storage) = { length = _length @@ -40,24 +54,34 @@ let map2 (vector1: SparseVector<'a>) (vector2: SparseVector<'b>) f = let len1 = vector1.length if len1 = vector2.length then - let rec inner (len: uint) vector1 vector2 = + let rec inner (size: uint64) vector1 vector2 = match (vector1, vector2) with | Node(t1, t2), Leaf(_) -> - let new_t1, nvals1 = inner (len / 2u) t1 vector2 - let new_t2, nvals2 = inner (len / 2u) t2 vector2 + let new_t1, nvals1 = inner (size / 2UL) t1 vector2 + let new_t2, nvals2 = inner (size / 2UL) t2 vector2 (mkNode new_t1 new_t2), nvals1 + nvals2 | Leaf(_), Node(t1, t2) -> - let new_t1, nvals1 = inner (len / 2u) vector1 t1 - let new_t2, nvals2 = inner (len / 2u) vector1 t2 + let new_t1, nvals1 = inner (size / 2UL) vector1 t1 + let new_t2, nvals2 = inner (size / 2UL) vector1 t2 (mkNode new_t1 new_t2), nvals1 + nvals2 | Node(t1, t2), Node(t3, t4) -> - let new_t1, nvals1 = inner (len / 2u) t1 t3 - let new_t2, nvals2 = inner (len / 2u) t2 t4 + let new_t1, nvals1 = inner (size / 2UL) t1 t3 + let new_t2, nvals2 = inner (size / 2UL) t2 t4 (mkNode new_t1 new_t2), nvals1 + nvals2 - | Leaf(v1), Leaf(v2) -> Leaf(f v1 v2), len + | Leaf(v1), Leaf(v2) -> + let res = f v1 v2 + + let nnz = + match res with + | None -> 0UL + | _ -> (uint64 size) * 1UL + + Leaf(res), nnz + + let storage, nvals = + inner vector1.storage.size vector1.storage.data vector2.storage.data - let storage, nvals = inner len1 vector1.storage vector2.storage - Result.Success(SparseVector(len1, nvals, storage)) + Result.Success(SparseVector(len1, nvals, (Storage(vector1.storage.size, storage)))) else Result.Failure "The length of the vector1 must be equals to the length of the vector2."