From f678a5048fdbec946efd501f5b6ce45ea2cbc1f5 Mon Sep 17 00:00:00 2001 From: gsv Date: Wed, 4 Feb 2026 15:43:35 +0300 Subject: [PATCH 1/2] Synchronize storages size in VxM. --- QuadTree.Tests/Tests.LinearAlgebra.fs | 111 ++++++++++++++++++++++++++ QuadTree/LinearAlgebra.fs | 18 ++++- 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/QuadTree.Tests/Tests.LinearAlgebra.fs b/QuadTree.Tests/Tests.LinearAlgebra.fs index f29b2a2..3517d91 100644 --- a/QuadTree.Tests/Tests.LinearAlgebra.fs +++ b/QuadTree.Tests/Tests.LinearAlgebra.fs @@ -229,3 +229,114 @@ let ``Simple vxm. 4 * (4x3).`` () = let actual = LinearAlgebra.vxm op_add op_mult v m Assert.Equal(expected, actual) + + +(* +2,2,2,D +* +N,1,1,N,N,D,D,D +3,2,2,3,1,D,D,D +N,N,1,2,N,D,D,D +D,D,D,D,D,D,D,D +D,D,D,D,D,D,D,D +D,D,D,D,D,D,D,D +D,D,D,D,D,D,D,D +D,D,D,D,D,D,D,D += +6,6,8,10,2,D,D,D +*) +[] +let ``Simple vxm. 3 * (3x5)`` () = + let m = + 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( + 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.Leaf(Dummy), + Matrix.qtree.Leaf(Dummy) + ) + + let store = Matrix.Storage(8UL, 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 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) + ) + ) + + let store = Vector.Storage(8UL, tree) + Result.Success(SparseVector(5UL, 5UL, store)) + + let actual = LinearAlgebra.vxm op_add op_mult v m + + Assert.Equal(expected, actual) diff --git a/QuadTree/LinearAlgebra.fs b/QuadTree/LinearAlgebra.fs index db5aada..e1a6886 100644 --- a/QuadTree/LinearAlgebra.fs +++ b/QuadTree/LinearAlgebra.fs @@ -72,7 +72,23 @@ let vxm op_add op_mult (vector: Vector.SparseVector<'a>) (matrix: Matrix.SparseM | (x, y) -> Result.Failure <| Error.InconsistentStructureOfStorages(x, y) if uint64 vector.length = uint64 matrix.nrows then - match inner vector.storage.size vector.storage.data matrix.storage.data with + let vector_storage = + if uint64 vector.storage.size < uint64 matrix.storage.hSize then + let rec increaseStorage storage_data (current_size: uint64) bound = + if current_size = bound then + storage_data + else + increaseStorage + (Vector.btree.Node(storage_data, Vector.btree.Leaf(Dummy))) + (current_size * 2UL) + bound + + let target_size = uint64 matrix.storage.hSize * 1UL + Vector.Storage(target_size, increaseStorage vector.storage.data vector.storage.size target_size) + else + vector.storage + + match inner vector_storage.size vector_storage.data matrix.storage.data with | Result.Failure x -> Result.Failure x | Result.Success(storage, nvals) -> (Vector.SparseVector( From 76f924256268e5e7d7eed38d079d619f898c858b Mon Sep 17 00:00:00 2001 From: gsv Date: Wed, 4 Feb 2026 17:11:26 +0300 Subject: [PATCH 2/2] Storage for matrix is always square. --- QuadTree.Tests/Tests.BFS.fs | 2 +- QuadTree.Tests/Tests.LinearAlgebra.fs | 8 +-- QuadTree.Tests/Tests.Matrix.fs | 19 ++++--- QuadTree/Common.fs | 3 ++ QuadTree/LinearAlgebra.fs | 10 ++-- QuadTree/Matrix.fs | 74 +++++---------------------- QuadTree/Vector.fs | 3 -- 7 files changed, 34 insertions(+), 85 deletions(-) diff --git a/QuadTree.Tests/Tests.BFS.fs b/QuadTree.Tests/Tests.BFS.fs index cf652d0..6c40600 100644 --- a/QuadTree.Tests/Tests.BFS.fs +++ b/QuadTree.Tests/Tests.BFS.fs @@ -43,7 +43,7 @@ let ``Simple level bfs.`` () = ) ) - let store = Matrix.Storage(4UL, 4UL, tree) + let store = Matrix.Storage(4UL, tree) SparseMatrix(4UL, 4UL, 9UL, store) let startVertices = diff --git a/QuadTree.Tests/Tests.LinearAlgebra.fs b/QuadTree.Tests/Tests.LinearAlgebra.fs index 3517d91..e285644 100644 --- a/QuadTree.Tests/Tests.LinearAlgebra.fs +++ b/QuadTree.Tests/Tests.LinearAlgebra.fs @@ -43,7 +43,7 @@ let ``Simple vxm. All sizes are power of two.`` () = ) ) - let store = Matrix.Storage(4UL, 4UL, tree) + let store = Matrix.Storage(4UL, tree) SparseMatrix(4UL, 4UL, 9UL, store) let v = @@ -119,7 +119,7 @@ let ``Simple vxm. 3 * (3x4)`` () = ) ) - let store = Matrix.Storage(4UL, 4UL, tree) + let store = Matrix.Storage(4UL, tree) SparseMatrix(3UL, 4UL, 8UL, store) let v = @@ -195,7 +195,7 @@ let ``Simple vxm. 4 * (4x3).`` () = ) ) - let store = Matrix.Storage(4UL, 4UL, tree) + let store = Matrix.Storage(4UL, tree) SparseMatrix(4UL, 3UL, 7UL, store) let v = @@ -296,7 +296,7 @@ let ``Simple vxm. 3 * (3x5)`` () = Matrix.qtree.Leaf(Dummy) ) - let store = Matrix.Storage(8UL, 8UL, tree) + let store = Matrix.Storage(8UL, tree) SparseMatrix(3UL, 5UL, 9UL, store) let v = diff --git a/QuadTree.Tests/Tests.Matrix.fs b/QuadTree.Tests/Tests.Matrix.fs index 80f642b..bb382a1 100644 --- a/QuadTree.Tests/Tests.Matrix.fs +++ b/QuadTree.Tests/Tests.Matrix.fs @@ -12,8 +12,7 @@ let printMatrix (matrix: SparseMatrix<_>) = 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 " size: %A" matrix.storage.size printfn " Data: %A" matrix.storage.data @@ -59,7 +58,7 @@ let ``Simple Matrix.map2. Square where number of cols and rows are power of two. ) ) - let store = Storage(4UL, 4UL, tree) + let store = Storage(4UL, tree) SparseMatrix(4UL, 4UL, 9UL, store) let m2 = @@ -71,7 +70,7 @@ let ``Simple Matrix.map2. Square where number of cols and rows are power of two. Matrix.qtree.Leaf(UserValue(None)) ) - let store = Storage(4UL, 4UL, tree) + let store = Storage(4UL, tree) SparseMatrix(4UL, 4UL, 12UL, store) let f x y = @@ -98,7 +97,7 @@ let ``Simple Matrix.map2. Square where number of cols and rows are power of two. Matrix.qtree.Leaf(UserValue(None)) ) - let store = Storage(4UL, 4UL, tree) + let store = Storage(4UL, tree) Result.Success(SparseMatrix(4UL, 4UL, 6UL, store)) let actual = Matrix.map2 m1 m2 f @@ -152,7 +151,7 @@ let ``Simple Matrix.map2. Square where number of cols and rows are not power of ) ) - let store = Storage(4UL, 4UL, tree) + let store = Storage(4UL, tree) SparseMatrix(3UL, 3UL, 6UL, store) let m2 = @@ -179,7 +178,7 @@ let ``Simple Matrix.map2. Square where number of cols and rows are not power of ) ) - let store = Storage(4UL, 4UL, tree) + let store = Storage(4UL, tree) SparseMatrix(3UL, 3UL, 8UL, store) let f x y = @@ -216,7 +215,7 @@ let ``Simple Matrix.map2. Square where number of cols and rows are not power of ) ) - let store = Storage(4UL, 4UL, tree) + let store = Storage(4UL, tree) Result.Success(SparseMatrix(3UL, 3UL, 5UL, store)) let actual = Matrix.map2 m1 m2 f @@ -312,7 +311,7 @@ let ``Condensation of empty`` () = ) let expected = - SparseMatrix(2UL, 3UL, 0UL, Storage(4UL, 4UL, tree)) + SparseMatrix(2UL, 3UL, 0UL, Storage(4UL, tree)) Assert.Equal(expected.storage.data, actual.storage.data) @@ -347,6 +346,6 @@ let ``Condensation of sparse`` () = ) let expected = - SparseMatrix(4UL, 3UL, 0UL, Storage(4UL, 4UL, tree)) + SparseMatrix(4UL, 3UL, 0UL, Storage(4UL, tree)) Assert.Equal(expected.storage.data, actual.storage.data) diff --git a/QuadTree/Common.fs b/QuadTree/Common.fs index 0d57192..61a3572 100644 --- a/QuadTree/Common.fs +++ b/QuadTree/Common.fs @@ -3,6 +3,9 @@ module Common [] type nvals +[] +type storageSize + type 'value treeValue = | Dummy | UserValue of 'value diff --git a/QuadTree/LinearAlgebra.fs b/QuadTree/LinearAlgebra.fs index e1a6886..618ef52 100644 --- a/QuadTree/LinearAlgebra.fs +++ b/QuadTree/LinearAlgebra.fs @@ -18,7 +18,7 @@ let rec multScalar op_add (x: uint64) y = let vxm op_add op_mult (vector: Vector.SparseVector<'a>) (matrix: Matrix.SparseMatrix<'b>) = - let rec inner (size: uint64) vector matrix = + let rec inner (size: uint64) vector matrix = let _do x1 x2 y1 y2 y3 y4 = let new_size = size / 2UL @@ -73,8 +73,8 @@ let vxm op_add op_mult (vector: Vector.SparseVector<'a>) (matrix: Matrix.SparseM if uint64 vector.length = uint64 matrix.nrows then let vector_storage = - if uint64 vector.storage.size < uint64 matrix.storage.hSize then - let rec increaseStorage storage_data (current_size: uint64) bound = + if uint64 vector.storage.size < uint64 matrix.storage.size then + let rec increaseStorage storage_data (current_size: uint64) bound = if current_size = bound then storage_data else @@ -83,7 +83,7 @@ let vxm op_add op_mult (vector: Vector.SparseVector<'a>) (matrix: Matrix.SparseM (current_size * 2UL) bound - let target_size = uint64 matrix.storage.hSize * 1UL + let target_size = matrix.storage.size Vector.Storage(target_size, increaseStorage vector.storage.data vector.storage.size target_size) else vector.storage @@ -94,7 +94,7 @@ let vxm op_add op_mult (vector: Vector.SparseVector<'a>) (matrix: Matrix.SparseM (Vector.SparseVector( (uint64 matrix.ncols) * 1UL, nvals, - (Vector.Storage((uint64 matrix.storage.hSize) * 1UL, storage)) + (Vector.Storage(matrix.storage.size, storage)) )) |> Result.Success else diff --git a/QuadTree/Matrix.fs b/QuadTree/Matrix.fs index 057b0c8..467ee10 100644 --- a/QuadTree/Matrix.fs +++ b/QuadTree/Matrix.fs @@ -17,22 +17,13 @@ type ncols [] type nrows -[] -type storageVSize - -[] -type storageHSize - [] type Storage<'value> = - val vSize: uint64 - val hSize: uint64 + // Storage is always size-x-size square. + val size: uint64 val data: qtree<'value> - new(_vSize, _hSize, _data) = - { vSize = _vSize - hSize = _hSize - data = _data } + new(_size, _data) = { size = _size; data = _data } [] type SparseMatrix<'value> = @@ -119,7 +110,7 @@ let fromCoordinateList (coo: CoordinateList<'a>) = let tree = traverse coo.list (0UL, 0UL) storageSize - SparseMatrix(nrows, ncols, nvals, Storage(storageSize * 1UL, storageSize * 1UL, tree)) + SparseMatrix(nrows, ncols, nvals, Storage(storageSize * 1UL, tree)) let toCoordinateList (matrix: SparseMatrix<'a>) = let nrows = matrix.nrows @@ -142,25 +133,16 @@ let toCoordinateList (matrix: SparseMatrix<'a>) = @ traverse se sep halfSize let coo = - traverse - matrix.storage.data - (0UL, 0UL) - (max (uint64 matrix.storage.hSize) (uint64 matrix.storage.vSize)) + traverse matrix.storage.data (0UL, 0UL) (uint64 matrix.storage.size) CoordinateList(nrows, ncols, coo) let map2 (matrix1: SparseMatrix<_>) (matrix2: SparseMatrix<_>) f = - let rec inner (vSize: uint64) (hSize: uint64) matrix1 matrix2 = + let rec inner (size: uint64) matrix1 matrix2 = let _do x1 x2 x3 x4 y1 y2 y3 y4 = - let new_vSize = vSize / 2UL - let new_hSize = hSize / 2UL - - match - (inner new_vSize new_hSize x1 y1), - (inner new_vSize new_hSize x2 y2), - (inner new_vSize new_hSize x3 y3), - (inner new_vSize new_hSize x4 y4) - with + let new_size = size / 2UL + + match (inner new_size x1 y1), (inner new_size x2 y2), (inner new_size x3 y3), (inner new_size x4 y4) with | Result.Success((new_t1, nvals1)), Result.Success((new_t2, nvals2)), Result.Success((new_t3, nvals3)), @@ -180,7 +162,7 @@ let map2 (matrix1: SparseMatrix<_>) (matrix2: SparseMatrix<_>) f = let nnz = match res with | None -> 0UL - | _ -> (uint64 vSize) * (uint64 hSize) * 1UL + | _ -> (uint64 size) * (uint64 size) * 1UL (Leaf(UserValue(res)), nnz) |> Result.Success @@ -190,15 +172,10 @@ let map2 (matrix1: SparseMatrix<_>) (matrix2: SparseMatrix<_>) f = | (x, y) -> Result.Failure <| Error.InconsistentStructureOfStorages(x, y) if matrix1.nrows = matrix2.nrows && matrix1.ncols = matrix2.ncols then - match inner matrix1.storage.vSize matrix1.storage.hSize matrix1.storage.data matrix2.storage.data with + match inner matrix1.storage.size matrix1.storage.data matrix2.storage.data with | Result.Failure x -> Result.Failure x | Result.Success(storage, nvals) -> - (SparseMatrix( - matrix1.nrows, - matrix1.ncols, - nvals, - (Storage(matrix1.storage.vSize, matrix1.storage.hSize, storage)) - )) + (SparseMatrix(matrix1.nrows, matrix1.ncols, nvals, (Storage(matrix1.storage.size, storage)))) |> Result.Success else (Error.InconsistentSizeOfArguments(matrix1, matrix2)) |> Result.Failure @@ -248,30 +225,3 @@ let compose opAdd (opMult: 'TCell1 -> 'TCell2 -> 'TCell3) (m1:Matrix<'TCell1>) ( else failwith $"Matrices should be of equals size, but m1.Size = {m1.Size} and m2.Size = {m2.Size}" *) - -(* -module UserCode = -open MyLibrary - -type CellOfMyMatrix<'TVal> = - | EmptyCell - | FilledCell of 'TVal - -let veryUsefulFunction m1 m2 m3 = - let op1 x y = - match (x,y) with - | EmptyCell, EmptyCell -> true - | _ -> false - let op2 x y = - match (x,y) with - | true, FilledCell x -> FilledCell (x + 1) - | false, FilledCell x -> - let res = x - 1 - if res = 0 then EmptyCell else FilledCell res - | _ -> EmptyCell - map2 op2 (map2 op1 m1 m2) m3 - -let veryUsefulFunction2 m1 m2 m3 = - let op1 = (+) - let op2 = (*) - map2 op2 (map2 op1 m1 m2) m3*) diff --git a/QuadTree/Vector.fs b/QuadTree/Vector.fs index 99396da..0bf187d 100644 --- a/QuadTree/Vector.fs +++ b/QuadTree/Vector.fs @@ -9,9 +9,6 @@ type 'value btree = [] type dataLength -[] -type storageSize - [] type Storage<'value> = val size: uint64