Some (Types.Ellipse (float32 cx, float32 cy, float32 majorAxis, float32 minorAxis, float32 phi'))
+
+// Optimized version of 'ellipse': TODO
+let ellipse' (p1x : float) (p1y : float) (m1 : float) (p2x : float) (p2y : float) (m2 : float) (p3x : float) (p3y : float) : Types.Ellipse option =
+ ellipse p1x p1y m1 p2x p2y m2 p3x p3y
+
let inline private vectorRotation (px : float32) (py : float32) (vx : float32) (vy : float32) (p0x : float32) (p0y : float32) : float32 =
if py > p0y then
if vx > 0.f then -1.f else 1.f
PI * (3.f * (this.A + this.B) - sqrt ((3.f * this.A + this.B) * (this.A + 3.f * this.B)))
override this.ToString () =
- sprintf "{Ellipse: cx = %f, cy = %f, a = %f, b = %f, alpha = %f}" this.Cx this.Cy this.A this.B this.Alpha
+ $"{{Ellipse: cx = %f{this.Cx}, cy = %f{this.Cy}, a = %f{this.A}, b = %f{this.B}, alpha = %f{this.Alpha}}}"
+
+ override this.Equals (other : obj) =
+ match other with
+ | :? Ellipse as otherEllipse ->
+ otherEllipse.Cx = this.Cx &&
+ otherEllipse.Cy = this.Cy &&
+ otherEllipse.A = this.A &&
+ otherEllipse.B = this.B &&
+ otherEllipse.Alpha = this.Alpha
+ | _ -> false
+
+ override this.GetHashCode () = HashCode.Combine (this.Cx, this.Cy, this.A, this.B, this.Alpha)
[<Struct>]
type CellClass = HealthyRBC | InfectedRBC | Peculiar
--- /dev/null
+module ParasitemiaUI.Constants
</PropertyGroup>
<ItemGroup>
+ <Compile Include="Constants.fs" />
<Compile Include="Types.fs" />
<Compile Include="Utils.fs" />
<Compile Include="SourceImage.fs" />
--- /dev/null
+module ParasitemiaCore.EllipsesBench
+
+open System
+open System.Diagnostics
+open type System.Console
+
+open ParasitemiaCore.Ellipse
+
+let rng = System.Random (42)
+
+let generateParameters () : float * float * float * float * float * float * float * float =
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble ()
+
+let benchOld () =
+ let sw = Stopwatch ()
+ sw.Start ()
+
+ for i in 1 .. 500_000 do
+ let p1x, p1y, m1, p2x, p2y, m2, p3x, p3y = generateParameters ()
+ ellipse p1x p1y m1 p2x p2y m2 p3x p3y |> ignore
+
+ sw.Stop ()
+ WriteLine (sprintf "Old: time = %A ms" sw.ElapsedMilliseconds)
+
+
+let benchNew () =
+ let sw = Stopwatch ()
+ sw.Start ()
+
+ for i in 1 .. 500_000 do
+ let p1x, p1y, m1, p2x, p2y, m2, p3x, p3y = generateParameters ()
+ ellipse' p1x p1y m1 p2x p2y m2 p3x p3y |> ignore
+
+ sw.Stop ()
+ WriteLine (sprintf "New: time = %A ms" sw.ElapsedMilliseconds)
\ No newline at end of file
--- /dev/null
+module ParasitemiaCore.KdTreeBench
+
+open System
+open type System.Console
+
+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
+
+let bench1 () =
+ let min = -1_000.
+ let max = +1_000.
+ let windowSize = 10.
+ let nbPoints = 1_000_000
+ let n = 1_000_000
+
+ let rng = Random 42
+ let nextNumber (min : float) (max : float) (rng : Random) =
+ (rng.NextDouble () * (max + abs min)) + min |> float32
+
+ let points =
+ [
+ for i = 1 to nbPoints do
+ let x = nextNumber min max rng
+ let y = nextNumber min max rng
+ Point (x, y)
+ ]
+
+ let sw = System.Diagnostics.Stopwatch ()
+ sw.Start ()
+
+ let tree = Tree.BuildTree points
+
+ sw.Stop ()
+ WriteLine (sprintf "Time to build = %A ms" sw.ElapsedMilliseconds)
+
+ let rng = Random 42
+ sw.Restart ()
+
+ let mutable nbFound = 0
+ for i = 1 to n do
+ let minX = nextNumber min (max - windowSize) rng
+ let minY = nextNumber min (max - windowSize) rng
+ nbFound <- nbFound + (tree.SearchOld { minX = minX; maxX = minX + float32 windowSize; minY = minY; maxY = minY + float32 windowSize } |> List.length)
+
+ sw.Stop ()
+ WriteLine (sprintf "New: nb found: %i. Time to search = %A ms" nbFound sw.ElapsedMilliseconds)
+
+ let rng = Random 42
+ sw.Restart ()
+
+ let mutable nbFound = 0
+ for i = 1 to n do
+ let minX = nextNumber min (max - windowSize) rng
+ let minY = nextNumber min (max - windowSize) rng
+ nbFound <- nbFound + (tree.Search { minX = minX; maxX = minX + float32 windowSize; minY = minY; maxY = minY + float32 windowSize }).Count
+
+ sw.Stop ()
+ WriteLine (sprintf "New: nb found: %i. Time to search = %A ms" nbFound sw.ElapsedMilliseconds)
\ No newline at end of file
</PropertyGroup>
<ItemGroup>
+ <Compile Include="EllipsesBench.fs" />
+ <Compile Include="KdTreeBench.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
// Learn more about F# at http://docs.microsoft.com/dotnet/fsharp
-open System
-open type System.Console
-
-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
-
-let kdTree () =
- let min = -1_000.
- let max = +1_000.
- let windowSize = 10.
- let nbPoints = 1_000_000
- let n = 1_000_000
-
- let rng = Random 42
- let nextNumber (min : float) (max : float) (rng : Random) =
- (rng.NextDouble () * (max + abs min)) + min |> float32
-
- let points =
- [
- for i = 1 to nbPoints do
- let x = nextNumber min max rng
- let y = nextNumber min max rng
- Point (x, y)
- ]
-
- let sw = System.Diagnostics.Stopwatch ()
- sw.Start ()
-
- let tree = Tree.BuildTree points
-
- sw.Stop ()
- WriteLine (sprintf "Time to build = %A ms" sw.ElapsedMilliseconds)
-
- let rng = Random 42
- sw.Restart ()
-
- let mutable nbFound = 0
- for i = 1 to n do
- let minX = nextNumber min (max - windowSize) rng
- let minY = nextNumber min (max - windowSize) rng
- nbFound <- nbFound + (tree.SearchOld { minX = minX; maxX = minX + float32 windowSize; minY = minY; maxY = minY + float32 windowSize } |> List.length)
-
- sw.Stop ()
- WriteLine (sprintf "New: nb found: %i. Time to search = %A ms" nbFound sw.ElapsedMilliseconds)
-
- let rng = Random 42
- sw.Restart ()
-
- let mutable nbFound = 0
- for i = 1 to n do
- let minX = nextNumber min (max - windowSize) rng
- let minY = nextNumber min (max - windowSize) rng
- nbFound <- nbFound + (tree.Search { minX = minX; maxX = minX + float32 windowSize; minY = minY; maxY = minY + float32 windowSize }).Count
-
- sw.Stop ()
- WriteLine (sprintf "New: nb found: %i. Time to search = %A ms" nbFound sw.ElapsedMilliseconds)
+module ParasitemiaCore.Main
[<EntryPoint>]
let main argv =
- kdTree ()
+ //KdTreeBench.bench1 ()
+ EllipsesBench.benchOld ()
+ EllipsesBench.benchNew ()
0
\ No newline at end of file
--- /dev/null
+namespace ParasitemiaCore.Tests
+
+open Xunit
+open Xunit.Abstractions
+
+open Swensen.Unquote
+
+open ParasitemiaCore.Ellipse
+
+type EllipsesTests (output : ITestOutputHelper) =
+
+ [<Fact>]
+ member this.``Compare the old and new ellipse construction implementations`` () =
+ let rng = System.Random (42)
+
+ let generateParameters () : float * float * float * float * float * float * float * float =
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble (),
+ rng.NextDouble ()
+
+ for i in 1 .. 100 do
+ let p1x, p1y, m1, p2x, p2y, m2, p3x, p3y = generateParameters ()
+ let e = ellipse p1x p1y m1 p2x p2y m2 p3x p3y
+ let e' = ellipse' p1x p1y m1 p2x p2y m2 p3x p3y
+
+ output.WriteLine (string e)
+
+ test <@ e = e' @>
+
+ ()
\ No newline at end of file
</PropertyGroup>
<ItemGroup>
+ <Compile Include="EllipsesTests.fs" />
<Compile Include="KdTreeTests.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
+ <PackageReference Include="Unquote" Version="5.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>