namespace ParasitemiaCore.Tests open Xunit open Xunit.Abstractions open ParasitemiaCore.KdTree type Point (x : float32, y : float32) = interface I2DCoords with member this.X = x member this.Y = y override this.ToString () = sprintf "(%.1f, %.1f)" x y type KdTreeTests (output : ITestOutputHelper) = // TODO: test with identical X or Y coords [] member this.``Test`` () = let pts = [ Point (1.0f, 1.0f) Point (2.0f, 2.0f) Point (1.5f, 3.6f) Point (3.0f, 3.2f) Point (4.0f, 4.0f) Point (3.5f, 1.5f) Point (2.5f, 0.5f) ] let tree = Tree.BuildTree pts output.WriteLine (sprintf "Tree: %A" tree) let s1 = tree.Search { minX = 0.0f; maxX = 5.0f; minY = 0.0f; maxY = 5.0f } // All points. output.WriteLine (sprintf "s1: %A" s1) let s2 = tree.Search { minX = 2.8f; maxX = 4.5f; minY = 3.0f; maxY = 4.5f } output.WriteLine (sprintf "s2: %A" s2) let s3 = tree.Search { minX = 2.0f; maxX = 2.0f; minY = 2.0f; maxY = 2.0f } output.WriteLine (sprintf "s3: %A" s3) [] member this.``Test 2`` () = let pts = [ Point (1.0f, 1.0f) Point (1.0f, 2.0f) Point (1.0f, 3.0f) ] let tree = Tree.BuildTree pts output.WriteLine (sprintf "Tree: %A" tree) let s1 = tree.Search { minX = 1.0f; maxX = 1.0f; minY = 1.0f; maxY = 1.0f } output.WriteLine (sprintf "s1: %A" s1) let s2 = tree.Search { minX = 1.0f; maxX = 1.0f; minY = 2.0f; maxY = 2.0f } output.WriteLine (sprintf "s2: %A" s2) // This case result is wrong: FIXME let s3 = tree.Search { minX = 1.0f; maxX = 1.0f; minY = 3.0f; maxY = 3.0f } output.WriteLine (sprintf "s3: %A" s3) let s4 = tree.Search { minX = 0.0f; maxX = 2.0f; minY = 0.0f; maxY = 4.0f } output.WriteLine (sprintf "s4: %A" s4) [] member this.``Benchmark`` () = let min = -1_000. let max = +1_000. let windowSize = 10. let nbPoints = 500_000 let n = 1_000 let rng = System.Random 42 let nextNumber (min : float) (max : float) = (rng.NextDouble () * (max + abs min)) + min |> float32 let points = [ for i = 1 to nbPoints do let x = nextNumber min max let y = nextNumber min max Point (x, y) ] let sw = System.Diagnostics.Stopwatch () sw.Start () let tree = Tree.BuildTree points sw.Stop () output.WriteLine (sprintf "Time to build = %A ms" sw.ElapsedMilliseconds) sw.Restart () let mutable nbFound = 0 for i = 1 to n do let minX = nextNumber min (max - windowSize) let minY = nextNumber min (max - windowSize) nbFound <- nbFound + (tree.Search { minX = minX; maxX = minX + float32 windowSize; minY = minY; maxY = minY + float32 windowSize } |> List.length) sw.Stop () output.WriteLine (sprintf "nb found: %i. Time to search = %A ms" nbFound sw.ElapsedMilliseconds)