diff --git a/QuadTree.Benchmark/Exists.fs b/QuadTree.Benchmark/Exists.fs new file mode 100644 index 0000000..6278303 --- /dev/null +++ b/QuadTree.Benchmark/Exists.fs @@ -0,0 +1,71 @@ +namespace QuadTree.Benchmarks.Exists + + +open BenchmarkDotNet.Attributes +open QuadTree.Benchmarks.Utils + +[)>] +type Benchmark() = + + let mutable denseVec = Unchecked.defaultof> + let mutable sparseVec = Unchecked.defaultof> + let mutable denseMat = Unchecked.defaultof> + let mutable sparseMat = Unchecked.defaultof> + + [] + member val N = 0 with get, set + + [] + member this.Setup() = + let denseData = + [ for i in 0UL .. uint64 this.N - 1UL -> (i * 1UL, int i % 100) ] + + denseVec <- Vector.fromCoordinateList (Vector.CoordinateList(uint64 this.N * 1UL, denseData)) + + let sparseData = + [ for i in 0UL .. 10UL .. uint64 this.N - 1UL -> (i * 1UL, int i % 100) ] + + sparseVec <- + Vector.fromCoordinateList (Vector.CoordinateList(uint64 this.N * 1UL, sparseData)) + + let denseMatData = + [ for r in 0UL .. uint64 this.N - 1UL do + for c in 0UL .. uint64 this.N - 1UL do + (r * 1UL, c * 1UL, int (r + c) % 100) ] + + denseMat <- + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + uint64 this.N * 1UL, + uint64 this.N * 1UL, + denseMatData + ) + ) + + let sparseMatData = + [ for r in 0UL .. 10UL .. uint64 this.N - 1UL do + for c in 0UL .. 10UL .. uint64 this.N - 1UL do + (r * 1UL, c * 1UL, int (r + c) % 100) ] + + sparseMat <- + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + uint64 this.N * 1UL, + uint64 this.N * 1UL, + sparseMatData + ) + ) + + [] + member this.VectorExistsDense() = Vector.exists denseVec (fun x -> x < 0) + + [] + member this.VectorExistsSparse() = + Vector.exists sparseVec (fun x -> x < 0) + + [] + member this.MatrixExistsDense() = Matrix.exists denseMat (fun x -> x < 0) + + [] + member this.MatrixExistsSparse() = + Matrix.exists sparseMat (fun x -> x < 0) diff --git a/QuadTree.Benchmark/Filters.fs b/QuadTree.Benchmark/Filters.fs new file mode 100644 index 0000000..b733fa4 --- /dev/null +++ b/QuadTree.Benchmark/Filters.fs @@ -0,0 +1,72 @@ +namespace QuadTree.Benchmarks.Filters + +open BenchmarkDotNet.Attributes +open QuadTree.Benchmarks.Utils + +[)>] +type Benchmark() = + + let mutable denseVec = Unchecked.defaultof> + let mutable sparseVec = Unchecked.defaultof> + let mutable denseMat = Unchecked.defaultof> + let mutable sparseMat = Unchecked.defaultof> + + [] + member val N = 0 with get, set + + [] + member this.Setup() = + let denseData = + [ for i in 0UL .. uint64 this.N - 1UL -> (i * 1UL, int i % 100) ] + + denseVec <- Vector.fromCoordinateList (Vector.CoordinateList(uint64 this.N * 1UL, denseData)) + + let sparseData = + [ for i in 0UL .. 10UL .. uint64 this.N - 1UL -> (i * 1UL, int i % 100) ] + + sparseVec <- + Vector.fromCoordinateList (Vector.CoordinateList(uint64 this.N * 1UL, sparseData)) + + let denseMatData = + [ for r in 0UL .. uint64 this.N - 1UL do + for c in 0UL .. uint64 this.N - 1UL do + (r * 1UL, c * 1UL, int (r + c) % 100) ] + + denseMat <- + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + uint64 this.N * 1UL, + uint64 this.N * 1UL, + denseMatData + ) + ) + + let sparseMatData = + [ for r in 0UL .. 10UL .. uint64 this.N - 1UL do + for c in 0UL .. 10UL .. uint64 this.N - 1UL do + (r * 1UL, c * 1UL, int (r + c) % 100) ] + + sparseMat <- + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + uint64 this.N * 1UL, + uint64 this.N * 1UL, + sparseMatData + ) + ) + + [] + member this.VectorFilterDense() = + Vector.filter denseVec (fun x -> x % 2 = 0) + + [] + member this.VectorFilterSparse() = + Vector.filter sparseVec (fun x -> x % 2 = 0) + + [] + member this.MatrixFilterDense() = + Matrix.filter denseMat (fun x -> x % 2 = 0) + + [] + member this.MatrixFilterSparse() = + Matrix.filter sparseMat (fun x -> x % 2 = 0) diff --git a/QuadTree.Benchmark/Forall.fs b/QuadTree.Benchmark/Forall.fs new file mode 100644 index 0000000..af40d24 --- /dev/null +++ b/QuadTree.Benchmark/Forall.fs @@ -0,0 +1,73 @@ +namespace QuadTree.Benchmarks.Forall + + +open BenchmarkDotNet.Attributes +open QuadTree.Benchmarks.Utils + +[)>] +type Benchmark() = + + let mutable denseVec = Unchecked.defaultof> + let mutable sparseVec = Unchecked.defaultof> + let mutable denseMat = Unchecked.defaultof> + let mutable sparseMat = Unchecked.defaultof> + + [] + member val N = 0 with get, set + + [] + member this.Setup() = + let denseData = + [ for i in 0UL .. uint64 this.N - 1UL -> (i * 1UL, int i % 100) ] + + denseVec <- Vector.fromCoordinateList (Vector.CoordinateList(uint64 this.N * 1UL, denseData)) + + let sparseData = + [ for i in 0UL .. 10UL .. uint64 this.N - 1UL -> (i * 1UL, int i % 100) ] + + sparseVec <- + Vector.fromCoordinateList (Vector.CoordinateList(uint64 this.N * 1UL, sparseData)) + + let denseMatData = + [ for r in 0UL .. uint64 this.N - 1UL do + for c in 0UL .. uint64 this.N - 1UL do + (r * 1UL, c * 1UL, int (r + c) % 100) ] + + denseMat <- + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + uint64 this.N * 1UL, + uint64 this.N * 1UL, + denseMatData + ) + ) + + let sparseMatData = + [ for r in 0UL .. 10UL .. uint64 this.N - 1UL do + for c in 0UL .. 10UL .. uint64 this.N - 1UL do + (r * 1UL, c * 1UL, int (r + c) % 100) ] + + sparseMat <- + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + uint64 this.N * 1UL, + uint64 this.N * 1UL, + sparseMatData + ) + ) + + [] + member this.VectorForallDense() = + Vector.forall denseVec (fun x -> x >= 0) + + [] + member this.VectorForallSparse() = + Vector.forall sparseVec (fun x -> x >= 0) + + [] + member this.MatrixForallDense() = + Matrix.forall denseMat (fun x -> x >= 0) + + [] + member this.MatrixForallSparse() = + Matrix.forall sparseMat (fun x -> x >= 0) diff --git a/QuadTree.Benchmark/Main.fs b/QuadTree.Benchmark/Main.fs index 61394af..3fb2bf4 100644 --- a/QuadTree.Benchmark/Main.fs +++ b/QuadTree.Benchmark/Main.fs @@ -4,7 +4,10 @@ open BenchmarkDotNet.Running let main argv = let benchmarks = BenchmarkSwitcher - [| typeof + [| typeof + typeof + typeof + typeof typeof typeof |] diff --git a/QuadTree.Benchmark/QuadTree.Benchmark.fsproj b/QuadTree.Benchmark/QuadTree.Benchmark.fsproj index 4edb362..ba98b9d 100644 --- a/QuadTree.Benchmark/QuadTree.Benchmark.fsproj +++ b/QuadTree.Benchmark/QuadTree.Benchmark.fsproj @@ -8,6 +8,9 @@ + + + diff --git a/QuadTree.Tests/Tests.Matrix.fs b/QuadTree.Tests/Tests.Matrix.fs index 816b4a2..e0192a8 100644 --- a/QuadTree.Tests/Tests.Matrix.fs +++ b/QuadTree.Tests/Tests.Matrix.fs @@ -642,3 +642,495 @@ let ``Fold sum`` () = let actual = foldAssociative op_add None m1 |> Option.get Assert.Equal(expected, actual) + +[] +let ``Matrix.filter all pass, none changed`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (1UL, 0UL, 3) + (1UL, 1UL, 4) ] + ) + ) + + let actual = Matrix.filter m (fun x -> x > 0) + Assert.Equal(m, actual) + +[] +let ``Matrix.filter none pass, all reset to zero`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (1UL, 0UL, 3) + (1UL, 1UL, 4) ] + ) + ) + + let expected = + Matrix.fromCoordinateList (CoordinateList(4UL, 4UL, [])) + + let actual = Matrix.filter m (fun x -> x < 0) + + Assert.Equal(expected, actual) + +[] +let ``Matrix.filter length is not a power of 2, all reset to zero`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (1UL, 0UL, 4) + (1UL, 1UL, 5) + (1UL, 2UL, 6) + (2UL, 0UL, 7) + (2UL, 1UL, 8) + (2UL, 2UL, 9) ] + ) + ) + + let expected = + Matrix.fromCoordinateList (CoordinateList(3UL, 3UL, [])) + + let actual = Matrix.filter m (fun x -> x < 0) + + Assert.Equal(expected, actual) + +[] +let ``Matrix.filter some pass, odd set to zero`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (0UL, 3UL, 4) + (1UL, 0UL, 5) + (1UL, 1UL, 6) + (1UL, 2UL, 7) + (1UL, 3UL, 8) + (2UL, 0UL, 9) + (2UL, 1UL, 10) + (2UL, 2UL, 11) + (2UL, 3UL, 12) + (3UL, 0UL, 13) + (3UL, 1UL, 14) + (3UL, 2UL, 15) + (3UL, 3UL, 16) ] + ) + ) + + let expected = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 1UL, 2) + (0UL, 3UL, 4) + (1UL, 1UL, 6) + (1UL, 3UL, 8) + (2UL, 1UL, 10) + (2UL, 3UL, 12) + (3UL, 1UL, 14) + (3UL, 3UL, 16) ] + ) + ) + + let actual = Matrix.filter m (fun x -> x % 2 = 0) + + Assert.Equal(expected, actual) + +[] +let ``Matrix.filter length is not a power of 2, not all reset to zero`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (1UL, 0UL, 4) + (1UL, 1UL, 5) + (1UL, 2UL, 6) + (2UL, 0UL, 7) + (2UL, 1UL, 8) + (2UL, 2UL, 9) ] + ) + ) + + let expected = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 1UL, 2) + (1UL, 0UL, 4) + (1UL, 2UL, 6) + (2UL, 1UL, 8) ] + ) + ) + + let actual = Matrix.filter m (fun x -> x % 2 = 0) + + Assert.Equal(expected, actual) + +[] +let ``Matrix.filter none pass, length is not a power of 2, none changed`` () = + let m = Matrix.fromCoordinateList (CoordinateList(3UL, 3UL, [])) + let actual = Matrix.filter m (fun x -> x > 0) + Assert.Equal(m, actual) + +[] +let ``Matrix.filter none pass, length is a power of 2, none changed`` () = + let m = Matrix.fromCoordinateList (CoordinateList(4UL, 4UL, [])) + let actual = Matrix.filter m (fun x -> x > 0) + Assert.Equal(m, actual) + +[] +let ``Matrix.filter single element, passes`` () = + let m = + Matrix.fromCoordinateList (CoordinateList(1UL, 1UL, [ (0UL, 0UL, 1) ])) + + let expected = + Matrix.fromCoordinateList (CoordinateList(1UL, 1UL, [ (0UL, 0UL, 1) ])) + + let actual = Matrix.filter m (fun x -> x > 0) + + Assert.Equal(expected, actual) + +[] +let ``Matrix.filter single element, fails`` () = + let m = + Matrix.fromCoordinateList (CoordinateList(1UL, 1UL, [ (0UL, 0UL, 1) ])) + + let expected = + Matrix.fromCoordinateList (CoordinateList(1UL, 1UL, [])) + + let actual = Matrix.filter m (fun x -> x < 0) + + Assert.Equal(expected, actual) + +[] +let ``Matrix.exists the first element fits, length is a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (1UL, 0UL, 3) + (1UL, 1UL, 4) ] + ) + ) + + Assert.True(Matrix.exists m (fun x -> x = 1)) + Assert.False(Matrix.exists m (fun x -> x = 10)) + +[] +let ``Matrix.exists the first element fits, length is not a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (1UL, 0UL, 4) + (1UL, 1UL, 5) + (1UL, 2UL, 6) ] + ) + ) + + Assert.True(Matrix.exists m (fun x -> x = 1)) + +[] +let ``Matrix.exists no element fits, length is a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (1UL, 0UL, 3) + (1UL, 1UL, 4) ] + ) + ) + + Assert.False(Matrix.exists m (fun x -> x = 10)) + +[] +let ``Matrix.exists no element fits, length is not a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (1UL, 0UL, 4) + (1UL, 1UL, 5) + (1UL, 2UL, 6) ] + ) + ) + + Assert.False(Matrix.exists m (fun x -> x = 10)) + +[] +let ``Matrix.exists empty matrix`` () = + let m = Matrix.fromCoordinateList (CoordinateList(3UL, 3UL, [])) + Assert.False(Matrix.exists m (fun x -> x = 1)) + +[] +let ``Matrix.exists single element, fits`` () = + let m = + Matrix.fromCoordinateList (CoordinateList(1UL, 1UL, [ (0UL, 0UL, 1) ])) + + Assert.True(Matrix.exists m (fun x -> x = 1)) + +[] +let ``Matrix.exists single element, does not fit`` () = + let m = + Matrix.fromCoordinateList (CoordinateList(1UL, 1UL, [ (0UL, 0UL, 1) ])) + + Assert.False(Matrix.exists m (fun x -> x = 10)) + +[] +let ``Matrix.exists all elements fit,length is a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (1UL, 0UL, 3) + (1UL, 1UL, 4) ] + ) + ) + + Assert.True(Matrix.exists m (fun x -> x > 0)) + +[] +let ``Matrix.exists all elements fit,length is not a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (1UL, 0UL, 4) + (1UL, 1UL, 5) + (1UL, 2UL, 6) ] + ) + ) + + Assert.True(Matrix.exists m (fun x -> x > 0)) + +[] +let ``Matrix.exists some elements fit, length is a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (1UL, 0UL, 3) + (1UL, 1UL, 4) ] + ) + ) + + Assert.True(Matrix.exists m (fun x -> x = 2 || x = 10)) + +[] +let ``Matrix.exists some elements fit, length is not a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (1UL, 0UL, 4) + (1UL, 1UL, 5) + (1UL, 2UL, 6) ] + ) + ) + + Assert.True(Matrix.exists m (fun x -> x = 2 || x = 10)) + +[] +let ``Matrix.forall the first element fits, length is a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (1UL, 0UL, 3) + (1UL, 1UL, 4) ] + ) + ) + + Assert.True(Matrix.forall m (fun x -> x > 0)) + +[] +let ``Matrix.forall the first element fits, length is not a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (1UL, 0UL, 4) + (1UL, 1UL, 5) + (1UL, 2UL, 6) ] + ) + ) + + Assert.True(Matrix.forall m (fun x -> x > 0)) + +[] +let ``Matrix.forall no element fits, length is a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (1UL, 0UL, 3) + (1UL, 1UL, 4) ] + ) + ) + + Assert.False(Matrix.forall m (fun x -> x > 10)) + +[] +let ``Matrix.forall no element fits, length is not a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (1UL, 0UL, 4) + (1UL, 1UL, 5) + (1UL, 2UL, 6) ] + ) + ) + + Assert.False(Matrix.forall m (fun x -> x > 10)) + +[] +let ``Matrix.forall all elements fit,length is a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (1UL, 0UL, 3) + (1UL, 1UL, 4) ] + ) + ) + + Assert.True(Matrix.forall m (fun x -> x > 0)) + +[] +let ``Matrix.forall all elements fit,length is not a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (1UL, 0UL, 4) + (1UL, 1UL, 5) + (1UL, 2UL, 6) ] + ) + ) + + Assert.True(Matrix.forall m (fun x -> x > 0)) + +[] +let ``Matrix.forall some elements fit, length is a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 4UL, + 4UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (1UL, 0UL, 3) + (1UL, 1UL, 4) ] + ) + ) + + Assert.False(Matrix.forall m (fun x -> x = 2 || x = 10)) + +[] +let ``Matrix.forall some elements fit, length is not a power of 2`` () = + let m = + Matrix.fromCoordinateList ( + CoordinateList( + 3UL, + 3UL, + [ (0UL, 0UL, 1) + (0UL, 1UL, 2) + (0UL, 2UL, 3) + (1UL, 0UL, 4) + (1UL, 1UL, 5) + (1UL, 2UL, 6) ] + ) + ) + + Assert.False(Matrix.forall m (fun x -> x = 2 || x = 10)) + +[] +let ``Matrix.forall empty matrix`` () = + let m = Matrix.fromCoordinateList (CoordinateList(3UL, 3UL, [])) + Assert.True(Matrix.forall m (fun x -> x = 1)) + +[] +let ``Matrix.forall single element, fits`` () = + let m = + Matrix.fromCoordinateList (CoordinateList(1UL, 1UL, [ (0UL, 0UL, 1) ])) + + Assert.True(Matrix.forall m (fun x -> x = 1)) + +[] +let ``Matrix.forall single element, does not fit`` () = + let m = + Matrix.fromCoordinateList (CoordinateList(1UL, 1UL, [ (0UL, 0UL, 1) ])) + + Assert.False(Matrix.forall m (fun x -> x = 10)) diff --git a/QuadTree.Tests/Tests.Vector.fs b/QuadTree.Tests/Tests.Vector.fs index 4eb1af9..9349656 100644 --- a/QuadTree.Tests/Tests.Vector.fs +++ b/QuadTree.Tests/Tests.Vector.fs @@ -903,3 +903,476 @@ let ``Init vector`` () = let actual = Vector.init 3UL (fun i -> Some(int i)) Assert.Equal(expected, actual) + + +[] +let ``Vector.filter all pass, none changed`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + let actual = Vector.filter v (fun x -> x > 0) + Assert.Equal(v, actual) + +[] +let ``Vector.filter none pass, all reset to zero`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + let expected = Vector.empty 8UL + let actual = Vector.filter v (fun x -> x < 0) + + Assert.Equal(expected, actual) + +[] +let ``Vector.filter length is not a power of 2, all reset to zero`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 6UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) ] + ) + ) + + let expected = Vector.empty 6UL + let actual = Vector.filter v (fun x -> x < 0) + + Assert.Equal(expected, actual) + +[] +let ``Vector.filter some pass, odd set to zero`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + let expected = + Vector.fromCoordinateList ( + CoordinateList(8UL, [ (1UL, 2); (3UL, 4); (5UL, 6); (7UL, 8) ]) + ) + + let actual = Vector.filter v (fun x -> ((x % 2) = 0)) + + Assert.Equal(expected, actual) + +[] +let ``Vector.filter length is not a power of 2, not all reset to zero`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 6UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) ] + ) + ) + + let expected = + Vector.fromCoordinateList ( + CoordinateList(6UL, [ (1UL, 2); (3UL, 4); (5UL, 6) ]) + ) + + let actual = Vector.filter v (fun x -> ((x % 2) = 0)) + + Assert.Equal(expected, actual) + +[] +let ``Vector.filter none pass, length is not a power of 2, none changed`` () = + let v = Vector.fromCoordinateList (CoordinateList(6UL, [])) + let actual = Vector.filter v (fun x -> x > 0) + Assert.Equal(v, actual) + +[] +let ``Vector.filter none pass, length is a power of 2, none changed`` () = + let v = Vector.fromCoordinateList (CoordinateList(8UL, [])) + let actual = Vector.filter v (fun x -> x > 0) + Assert.Equal(v, actual) + +[] +let ``Vector.filter single element, passes`` () = + let v = + Vector.fromCoordinateList (CoordinateList(1UL, [ (0UL, 1) ])) + + let expected = + Vector.fromCoordinateList (CoordinateList(1UL, [ (0UL, 1) ])) + + let actual = Vector.filter v (fun x -> x > 0) + + Assert.Equal(expected, actual) + +[] +let ``Vector.filter single element, fails`` () = + let v = + Vector.fromCoordinateList (CoordinateList(1UL, [ (0UL, 1) ])) + + let expected = Vector.empty 1UL + let actual = Vector.filter v (fun x -> x < 0) + + Assert.Equal(expected, actual) + +[] +let ``Vector.exists the first element fits, length is a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + Assert.True(Vector.exists v (fun x -> x > 0)) + +[] +let ``Vector.exists the first element fits, length is not a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 6UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) ] + ) + ) + + Assert.True(Vector.exists v (fun x -> x > 0)) + +[] +let ``Vector.exists the last item fits, length is a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + Assert.True(Vector.exists v (fun x -> x > 7)) + +[] +let ``Vector.exists the last item fits, length is not a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 6UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) ] + ) + ) + + Assert.True(Vector.exists v (fun x -> x > 5)) + +[] +let ``Vector.exists empty list`` () = + let v = Vector.fromCoordinateList (CoordinateList(8UL, [])) + Assert.False(Vector.exists v (fun x -> x > 0)) + +[] +let ``Vector.exists no matching elements, length is a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + Assert.False(Vector.exists v (fun x -> x > 8)) + +[] +let ``Vector.exists no matching elements, length is not a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 6UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) ] + ) + ) + + Assert.False(Vector.exists v (fun x -> x > 6)) + +[] +let ``Vector.exists single element matches`` () = + let v = + Vector.fromCoordinateList (CoordinateList(1UL, [ (0UL, 1) ])) + + Assert.True(Vector.exists v (fun x -> x = 1)) + +[] +let ``Vector.exists single element does not match`` () = + let v = + Vector.fromCoordinateList (CoordinateList(1UL, [ (0UL, 1) ])) + + Assert.False(Vector.exists v (fun x -> x = 2)) + +[] +let ``Vector.exists all elements match, length is a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + Assert.True(Vector.exists v (fun x -> x > 0)) + +[] +let ``Vector.exists all elements match, length is not a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 6UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) ] + ) + ) + + Assert.True(Vector.exists v (fun x -> x > 0)) + +[] +let ``Vector.forall the first element not fits, length is a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + Assert.False(Vector.forall v (fun x -> x > 1)) + +[] +let ``Vector.forall the first element not fits, length is not a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 6UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) ] + ) + ) + + Assert.False(Vector.forall v (fun x -> x > 1)) + +[] +let ``Vector.forall the last item not fits, length is a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + Assert.False(Vector.forall v (fun x -> x < 8)) + +[] +let ``Vector.forall the last item not fits, length is not a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 6UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) ] + ) + ) + + Assert.False(Vector.forall v (fun x -> x < 6)) + +[] +let ``Vector.forall empty list`` () = + let v = Vector.fromCoordinateList (CoordinateList(8UL, [])) + Assert.True(Vector.forall v (fun x -> x > 0)) + +[] +let ``Vector.forall no matching elements, length is a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + Assert.False(Vector.forall v (fun x -> x > 8)) + +[] +let ``Vector.forall no matching elements, length is not a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 6UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) ] + ) + ) + + Assert.False(Vector.forall v (fun x -> x > 6)) + +[] +let ``Vector.forall single element matches`` () = + let v = + Vector.fromCoordinateList (CoordinateList(1UL, [ (0UL, 1) ])) + + Assert.True(Vector.forall v (fun x -> x = 1)) + +[] +let ``Vector.forall single element does not match`` () = + let v = + Vector.fromCoordinateList (CoordinateList(1UL, [ (0UL, 1) ])) + + Assert.False(Vector.forall v (fun x -> x = 2)) + +[] +let ``Vector.forall all elements match, length is a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 8UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) + (6UL, 7) + (7UL, 8) ] + ) + ) + + Assert.True(Vector.forall v (fun x -> x > 0)) + +[] +let ``Vector.forall all elements match, length is not a power of 2`` () = + let v = + Vector.fromCoordinateList ( + CoordinateList( + 6UL, + [ (0UL, 1) + (1UL, 2) + (2UL, 3) + (3UL, 4) + (4UL, 5) + (5UL, 6) ] + ) + ) + + Assert.True(Vector.forall v (fun x -> x > 0)) diff --git a/QuadTree/Matrix.fs b/QuadTree/Matrix.fs index 68ea7d7..e78adf7 100644 --- a/QuadTree/Matrix.fs +++ b/QuadTree/Matrix.fs @@ -394,3 +394,51 @@ let transpose (matrix: SparseMatrix<_>) = let mask (m1: SparseMatrix<'a>) (m2: SparseMatrix<'b>) f = map2 m1 m2 (fun m1 m2 -> if f m2 then m1 else None) + + +let filter (matrix: SparseMatrix<'a>) (predicate: 'a -> bool) : SparseMatrix<'a> = + let rec inner (prow: uint64) (pcol: uint64) (size: uint64) matrix = + match matrix with + | Node(x1, x2, x3, x4) -> + let halfSize = size / 2UL + + let (nwR, nwC), (neR, neC), (swR, swC), (seR, seC) = + getQuadrantCoords (prow, pcol) (uint64 halfSize) + + let t1, nvals1 = inner nwR nwC halfSize x1 + let t2, nvals2 = inner neR neC halfSize x2 + let t3, nvals3 = inner swR swC halfSize x3 + let t4, nvals4 = inner seR seC halfSize x4 + (mkNode t1 t2 t3 t4), nvals1 + nvals2 + nvals3 + nvals4 + | Leaf(Dummy) -> Leaf(Dummy), 0UL + | Leaf(UserValue(None)) -> Leaf(UserValue(None)), 0UL + | Leaf(UserValue(Some(v))) -> + if predicate v then + Leaf(UserValue(Some v)), (uint64 size) * (uint64 size) * 1UL + else + Leaf(UserValue(None)), 0UL + + let storage, nvals = + inner 0UL 0UL matrix.storage.size matrix.storage.data + + SparseMatrix(matrix.nrows, matrix.ncols, nvals, (Storage(matrix.storage.size, storage))) + +let exists (matrix: SparseMatrix<'a>) (predicate: 'a -> bool) : bool = + let rec inner tree = + match tree with + | Leaf(Dummy) -> false + | Leaf(UserValue(None)) -> false + | Leaf(UserValue(Some(v))) -> predicate v + | Node(nw, ne, sw, se) -> inner nw || inner ne || inner sw || inner se + + inner matrix.storage.data + +let forall (matrix: SparseMatrix<'a>) (predicate: 'a -> bool) : bool = + let rec inner tree = + match tree with + | Leaf(Dummy) -> true + | Leaf(UserValue(None)) -> true + | Leaf(UserValue(Some(v))) -> predicate v + | Node(nw, ne, sw, se) -> inner nw && inner ne && inner sw && inner se + + inner matrix.storage.data diff --git a/QuadTree/Vector.fs b/QuadTree/Vector.fs index b7bcb44..00e7f2a 100644 --- a/QuadTree/Vector.fs +++ b/QuadTree/Vector.fs @@ -353,7 +353,7 @@ let toCoordinateList (vector: SparseVector<'a>) = CoordinateList(length, lst) -let empty length = +let empty (length: uint64) = fromCoordinateList (CoordinateList(length, [])) let foldValues (vector: SparseVector<'a>) (f: 'b -> 'a -> 'b) (state: 'b) = @@ -561,3 +561,41 @@ let scatter | Error x -> Error x) (Ok w) | Error x -> Error Error.InconsistentStructureOfStorages + +let filter (vector: SparseVector<'a>) (predicate: 'a -> bool) : SparseVector<'a> = + let rec inner (size: uint64) vector = + match vector with + | Node(x1, x2) -> + let t1, nvals1 = inner (size / 2UL) x1 + let t2, nvals2 = inner (size / 2UL) x2 + (mkNode t1 t2), nvals1 + nvals2 + | Leaf(Dummy) -> Leaf(Dummy), 0UL + | Leaf(UserValue(None)) -> Leaf(UserValue(None)), 0UL + | Leaf(UserValue(Some(v))) -> + if predicate v then + Leaf(UserValue(Some(v))), (uint64 size) * 1UL + else + Leaf(UserValue(None)), 0UL + + let storage, nvals = inner vector.storage.size vector.storage.data + SparseVector(vector.length, nvals, Storage(vector.storage.size, storage)) + +let exists (vector: SparseVector<'a>) (predicate: 'a -> bool) : bool = + let rec inner vector = + match vector with + | Leaf(Dummy) -> false + | Leaf(UserValue(None)) -> false + | Leaf(UserValue(Some(v))) -> predicate v + | Node(x1, x2) -> inner x1 || inner x2 + + inner vector.storage.data + +let forall (vector: SparseVector<'a>) (predicate: 'a -> bool) : bool = + let rec inner vector = + match vector with + | Leaf(Dummy) -> true + | Leaf(UserValue(None)) -> true + | Leaf(UserValue(Some(v))) -> predicate v + | Node(x1, x2) -> inner x1 && inner x2 + + inner vector.storage.data