diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index e8ae5120..4c7f7b1b 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"paket": {
- "version": "8.0.3",
+ "version": "9.0.2",
"commands": [
"paket"
]
diff --git a/.paket/Paket.Restore.targets b/.paket/Paket.Restore.targets
index c66062b2..712cd771 100644
--- a/.paket/Paket.Restore.targets
+++ b/.paket/Paket.Restore.targets
@@ -235,14 +235,15 @@
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length)
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0])
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1])
+ $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[2])
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4])
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5])
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[6])
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[7])
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[8])
-
- %(PaketReferencesFileLinesInfo.PackageVersion)
+
+ %(PaketReferencesFileLinesInfo.PackageVersion)
All
runtime
$(ExcludeAssets);contentFiles
@@ -252,6 +253,10 @@
true
+
+
+ %(PaketReferencesFileLinesInfo.PackageVersion)
+
diff --git a/Expecto.Tests/Tests.fs b/Expecto.Tests/Tests.fs
index 48ea2336..2e85884b 100644
--- a/Expecto.Tests/Tests.fs
+++ b/Expecto.Tests/Tests.fs
@@ -6,6 +6,8 @@ open System.Text.RegularExpressions
open System.Threading
open System.IO
open System.Reflection
+open FSharp.Core.LanguagePrimitives
+open FSharp.Data.UnitSystems.SI.UnitSymbols
open Expecto
open Expecto.Impl
open Expecto.Logging
@@ -921,42 +923,207 @@ let expecto =
]
- testList "double" [
- testList "nan testing" [
- testCase "is not 'NaN'" <| fun _ ->
- Expect.isNotNaN 4.0 "should pass because it's not 'Nan'"
- testCase "is 'NaN'" (fun _ ->
- Expect.isNotNaN Double.NaN "should fail because it's 'NaN'"
- ) |> assertTestFails
+ testList "float" [
+ testList "float" [
+ testList "nan testing" [
+ testList "is 'NaN'" [
+ testCase "pass" <| fun _ ->
+ Expect.isNaN nan "should pass because it's 'NaN'"
+ testCase "fail" (fun _ ->
+ Expect.isNaN 4.0 "should fail because it's not 'NaN'"
+ ) |> assertTestFails
+ ]
+ testList "is not 'NaN'" [
+ testCase "pass" <| fun _ ->
+ Expect.isNotNaN 4.0 "should pass because it's not 'NaN'"
+ testCase "fail" (fun _ ->
+ Expect.isNotNaN nan "should fail because it's 'NaN'"
+ ) |> assertTestFails
+ ]
+ ]
+
+ testList "negative infinity testing" [
+ testList "is a negative infinity" [
+ testCase "pass" <| fun _ ->
+ Expect.isNegativeInfinity -infinity "should pass because it's a negative infinity"
+ testCase "fail infinity" (fun _ ->
+ Expect.isNegativeInfinity infinity "should fail because it's a not a negative infinity"
+ ) |> assertTestFails
+ testCase "fail 4.0" (fun _ ->
+ Expect.isNegativeInfinity 4.0 "should fail because it's not a negative infinity"
+ ) |> assertTestFails
+ ]
+ testList "is not a negative infinity" [
+ testCase "pass infinity" <| fun _ ->
+ Expect.isNotNegativeInfinity infinity "should pass because it's not a negative infinity"
+ testCase "pass 4.0" <| fun _ ->
+ Expect.isNotNegativeInfinity 4.0 "should pass because it's not a negative infinity"
+ testCase "fail" (fun _ ->
+ Expect.isNotNegativeInfinity -infinity "should fail because it's negative infinity"
+ ) |> assertTestFails
+ ]
+ ]
+
+ testList "infinity testing" [
+ testList "is an infinity" [
+ testCase "pass - negative infinity" <| fun _ ->
+ Expect.isInfinity infinity "should fail because it's negative infinity"
+ testCase "pass - positive infinity" <| fun _ ->
+ Expect.isInfinity infinity "should fail because it's positive infinity"
+ testCase "fail - 4.0" (fun _ ->
+ Expect.isInfinity 4.0 "should pass because it's not an negative infinity nor positive"
+ ) |> assertTestFails
+ ]
+ testList "is not an infinity" [
+ testCase "pass - 4.0" <| fun _ ->
+ Expect.isNotInfinity 4.0 "should pass because it's not an negative infinity nor positive"
+ testCase "fail - negative infinity" (fun _ ->
+ Expect.isNotInfinity -infinity "should fail because it's negative infinity"
+ ) |> assertTestFails
+ testCase "fail - positive infinity" (fun _ ->
+ Expect.isNotInfinity infinity "should fail because it's positive infinity"
+ ) |> assertTestFails
+ ]
+ ]
]
+ testList "float" [
+ testList "nan testing" [
+ testList "is 'NaN'" [
+ testCase "pass" <| fun _ ->
+ Expect.isNaN (FloatWithMeasure nan) "should pass because it's 'NaN'"
+ testCase "fail" (fun _ ->
+ Expect.isNaN 4.0 "should fail because it's not 'NaN'"
+ ) |> assertTestFails
+ ]
+ testList "is not 'NaN'" [
+ testCase "pass" <| fun _ ->
+ Expect.isNotNaN 4.0 "should pass because it's not 'NaN'"
+ testCase "fail" (fun _ ->
+ Expect.isNotNaN nan "should fail because it's 'NaN'"
+ ) |> assertTestFails
+ ]
+ ]
+
+ testList "negative infinity testing" [
+ testList "is a negative infinity" [
+ testCase "pass" <| fun _ ->
+ Expect.isNegativeInfinity (FloatWithMeasure -infinity) "should pass because it's a negative infinity"
+ testCase "fail infinity" (fun _ ->
+ Expect.isNegativeInfinity (FloatWithMeasure infinity) "should fail because it's a not a negative infinity"
+ ) |> assertTestFails
+ testCase "fail 4.0" (fun _ ->
+ Expect.isNegativeInfinity 4.0 "should fail because it's not a negative infinity"
+ ) |> assertTestFails
+ ]
+ testList "is not a negative infinity" [
+ testCase "pass infinity" <| fun _ ->
+ Expect.isNotNegativeInfinity (FloatWithMeasure infinity) "should pass because it's not a negative infinity"
+ testCase "pass 4.0" <| fun _ ->
+ Expect.isNotNegativeInfinity 4.0 "should pass because it's not a negative infinity"
+ testCase "fail" (fun _ ->
+ Expect.isNotNegativeInfinity (FloatWithMeasure -infinity) "should fail because it's negative infinity"
+ ) |> assertTestFails
+ ]
+ ]
- testList "positive infinity testing" [
- testCase "is not a positive infinity" <| fun _ ->
- Expect.isNotPositiveInfinity 4.0 "should pass because it's not positive infinity"
- testCase "is a positive infinity" (fun _ ->
- Expect.isNotPositiveInfinity Double.PositiveInfinity "should fail because it's a positive infinity"
- ) |> assertTestFails
+ testList "infinity testing" [
+ testList "is an infinity" [
+ testCase "pass - negative infinity" <| fun _ ->
+ Expect.isInfinity infinity "should fail because it's negative infinity"
+ testCase "pass - positive infinity" <| fun _ ->
+ Expect.isInfinity infinity "should fail because it's positive infinity"
+ testCase "fail - 4.0" (fun _ ->
+ Expect.isInfinity 4.0 "should pass because it's not an negative infinity nor positive"
+ ) |> assertTestFails
+ ]
+ testList "is not an infinity" [
+ testCase "pass - 4.0" <| fun _ ->
+ Expect.isNotInfinity 4.0 "should pass because it's not an negative infinity nor positive"
+ testCase "fail - negative infinity" (fun _ ->
+ Expect.isNotInfinity -infinity "should fail because it's negative infinity"
+ ) |> assertTestFails
+ testCase "fail - positive infinity" (fun _ ->
+ Expect.isNotInfinity infinity "should fail because it's positive infinity"
+ ) |> assertTestFails
+ ]
+ ]
]
- testList "negative infinity testing" [
- testCase "is not a negative infinity" <| fun _ ->
- Expect.isNotNegativeInfinity 4.0 "should pass because it's not a negative infinity"
- testCase "is a negative infinity" (fun _ ->
- Expect.isNotNegativeInfinity Double.NegativeInfinity "should fail because it's negative infinity"
- ) |> assertTestFails
+ testList "float32" [
+ testList "nan testing" [
+ testCase "is not 'NaN'" <| fun _ ->
+ Expect.isNotNaNf 4.0f "should pass because it's not 'NaNf'"
+ testCase "is 'NaN'" (fun _ ->
+ Expect.isNotNaNf Single.NaN "should fail because it's 'NaNf'"
+ ) |> assertTestFails
+ ]
+
+ testList "positive infinity testing" [
+ testCase "is not a positive infinity" <| fun _ ->
+ Expect.isNotPositiveInfinityf 4.0f "should pass because it's not positive infinity"
+ testCase "is a positive infinity" (fun _ ->
+ Expect.isNotPositiveInfinityf Single.PositiveInfinity "should fail because it's a positive infinityf"
+ ) |> assertTestFails
+ ]
+
+ testList "negative infinity testing" [
+ testCase "is not a negative infinity" <| fun _ ->
+ Expect.isNotNegativeInfinityf 4.0f "should pass because it's not a negative infinity"
+ testCase "is a negative infinity" (fun _ ->
+ Expect.isNotNegativeInfinityf Single.NegativeInfinity "should fail because it's negative infinityf"
+ ) |> assertTestFails
+ ]
+
+ testList "infinity testing" [
+ testCase "is not an infinity" <| fun _ ->
+ Expect.isNotInfinityf 4.0f "should pass because it's not an negative infinityf nor positive"
+
+ testCase "is a negative infinity" (fun _ ->
+ Expect.isNotInfinityf Single.NegativeInfinity "should fail because it's negative infinityf"
+ ) |> assertTestFails
+
+ testCase "is a positive infinity" (fun _ ->
+ Expect.isNotInfinityf Single.PositiveInfinity "should fail because it's positive infinityf"
+ ) |> assertTestFails
+ ]
]
+ testList "float32" [
+ testList "nan testing" [
+ testCase "is not 'NaN'" <| fun _ ->
+ Expect.isNotNaNf 4.0f "should pass because it's not 'NaNf'"
+ testCase "is 'NaN'" (fun _ ->
+ Expect.isNotNaNf (Float32WithMeasure Single.NaN) "should fail because it's 'NaNf'"
+ ) |> assertTestFails
+ ]
+
+ testList "positive infinity testing" [
+ testCase "is not a positive infinity" <| fun _ ->
+ Expect.isNotPositiveInfinityf 4.0f "should pass because it's not positive infinity"
+ testCase "is a positive infinity" (fun _ ->
+ Expect.isNotPositiveInfinityf (Float32WithMeasure Single.PositiveInfinity) "should fail because it's a positive infinityf"
+ ) |> assertTestFails
+ ]
- testList "infinity testing" [
- testCase "is not an infinity" <| fun _ ->
- Expect.isNotInfinity 4.0 "should pass because it's not an negative infinity nor positive"
+ testList "negative infinity testing" [
+ testCase "is not a negative infinity" <| fun _ ->
+ Expect.isNotNegativeInfinityf 4.0f "should pass because it's not a negative infinity"
+ testCase "is a negative infinity" (fun _ ->
+ Expect.isNotNegativeInfinityf (Float32WithMeasure Single.NegativeInfinity) "should fail because it's negative infinityf"
+ ) |> assertTestFails
+ ]
+
+ testList "infinity testing" [
+ testCase "is not an infinity" <| fun _ ->
+ Expect.isNotInfinityf 4.0f "should pass because it's not an negative infinityf nor positive"
- testCase "is a negative infinity" (fun _ ->
- Expect.isNotInfinity Double.NegativeInfinity "should fail because it's negative infinity"
- ) |> assertTestFails
+ testCase "is a negative infinity" (fun _ ->
+ Expect.isNotInfinityf (Float32WithMeasure Single.NegativeInfinity) "should fail because it's negative infinityf"
+ ) |> assertTestFails
- testCase "is a positive infinity" (fun _ ->
- Expect.isNotInfinity Double.PositiveInfinity "should fail because it's positive infinity"
- ) |> assertTestFails
+ testCase "is a positive infinity" (fun _ ->
+ Expect.isNotInfinityf (Float32WithMeasure Single.PositiveInfinity) "should fail because it's positive infinityf"
+ ) |> assertTestFails
+ ]
]
]
@@ -1560,52 +1727,190 @@ let performance =
[]
let close =
testList "close" [
+ testList "float" [
+ testCase "zero" <| fun _ ->
+ Expect.floatClose Accuracy.veryHigh 0.0 0.0 "zero"
+
+ testCase "small" <| fun _ ->
+ Expect.floatClose Accuracy.low 0.000001 0.0 "small"
+
+ testCase "large" <| fun _ ->
+ Expect.floatClose Accuracy.low 10004.0 10000.0 "large"
+
+ testCase "user" <| fun _ ->
+ Expect.floatClose {absolute=0.0; relative=1e-3}
+ 10004.0 10000.0 "user"
+
+ testCase "can fail" (fun _ ->
+ Expect.floatClose Accuracy.low 1004.0 1000.0 "can fail"
+ ) |> assertTestFails
+
+ testCase "nan fails" (fun _ ->
+ Expect.floatClose Accuracy.low nan 1.0 "nan fails"
+ ) |> assertTestFails
+
+ testCase "inf fails" (fun _ ->
+ Expect.floatClose Accuracy.low infinity 1.0 "inf fails"
+ ) |> assertTestFails
+
+ testCase "less than easy" <| fun _ ->
+ Expect.floatLessThanOrClose Accuracy.low -1.0 0.0 "less"
+
+ testCase "not less than but close" <| fun _ ->
+ Expect.floatLessThanOrClose Accuracy.low 0.000001 0.0 "close"
- testCase "zero" <| fun _ ->
- Expect.floatClose Accuracy.veryHigh 0.0 0.0 "zero"
+ testCase "not less than fails" (fun _ ->
+ Expect.floatLessThanOrClose Accuracy.low 1.0 0.0 "fail"
+ ) |> assertTestFails
+
+ testCase "greater than easy" <| fun _ ->
+ Expect.floatGreaterThanOrClose Accuracy.low 1.0 0.0 "greater"
+
+ testCase "not greater than but close" <| fun _ ->
+ Expect.floatGreaterThanOrClose Accuracy.low -0.000001 0.0 "close"
+
+ testCase "not greater than fails" (fun _ ->
+ Expect.floatGreaterThanOrClose Accuracy.low -1.0 0.0 "fail"
+ ) |> assertTestFails
+ ]
+ testList "float" [
+ testCase "zero" <| fun _ ->
+ Expect.floatClose Accuracy.veryHigh 0.0 0.0 "zero"
+
+ testCase "small" <| fun _ ->
+ Expect.floatClose Accuracy.low 0.000001 0.0 "small"
+
+ testCase "large" <| fun _ ->
+ Expect.floatClose Accuracy.low 10004.0 10000.0 "large"
+
+ testCase "user" <| fun _ ->
+ Expect.floatClose {absolute=0.0; relative=1e-3}
+ 10004.0 10000.0 "user"
+
+ testCase "can fail" (fun _ ->
+ Expect.floatClose Accuracy.low 1004.0 1000.0 "can fail"
+ ) |> assertTestFails
+
+ testCase "nan fails" (fun _ ->
+ Expect.floatClose Accuracy.low (FloatWithMeasure nan) 1.0 "nan fails"
+ ) |> assertTestFails
+
+ testCase "inf fails" (fun _ ->
+ Expect.floatClose Accuracy.low (FloatWithMeasure infinity) 1.0 "inf fails"
+ ) |> assertTestFails
- testCase "small" <| fun _ ->
- Expect.floatClose Accuracy.low 0.000001 0.0 "small"
+ testCase "less than easy" <| fun _ ->
+ Expect.floatLessThanOrClose Accuracy.low -1.0 0.0 "less"
+
+ testCase "not less than but close" <| fun _ ->
+ Expect.floatLessThanOrClose Accuracy.low 0.000001 0.0 "close"
+
+ testCase "not less than fails" (fun _ ->
+ Expect.floatLessThanOrClose Accuracy.low 1.0 0.0 "fail"
+ ) |> assertTestFails
- testCase "large" <| fun _ ->
- Expect.floatClose Accuracy.low 10004.0 10000.0 "large"
+ testCase "greater than easy" <| fun _ ->
+ Expect.floatGreaterThanOrClose Accuracy.low 1.0 0.0 "greater"
- testCase "user" <| fun _ ->
- Expect.floatClose {absolute=0.0; relative=1e-3}
- 10004.0 10000.0 "user"
+ testCase "not greater than but close" <| fun _ ->
+ Expect.floatGreaterThanOrClose Accuracy.low -0.000001 0.0 "close"
- testCase "can fail" (fun _ ->
- Expect.floatClose Accuracy.low 1004.0 1000.0 "can fail"
- ) |> assertTestFails
+ testCase "not greater than fails" (fun _ ->
+ Expect.floatGreaterThanOrClose Accuracy.low -1.0 0.0 "fail"
+ ) |> assertTestFails
+ ]
+ testList "float32" [
+ testCase "zero" <| fun _ ->
+ Expect.float32Close Accuracy32.veryHigh 0.0f 0.0f "zero"
- testCase "nan fails" (fun _ ->
- Expect.floatClose Accuracy.low nan 1.0 "nan fails"
- ) |> assertTestFails
+ testCase "small" <| fun _ ->
+ Expect.float32Close Accuracy32.low 0.000001f 0.0f "small"
- testCase "inf fails" (fun _ ->
- Expect.floatClose Accuracy.low infinity 1.0 "inf fails"
- ) |> assertTestFails
+ testCase "large" <| fun _ ->
+ Expect.float32Close Accuracy32.low 10004.0f 10000.0f "large"
- testCase "less than easy" <| fun _ ->
- Expect.floatLessThanOrClose Accuracy.low -1.0 0.0 "less"
+ testCase "user" <| fun _ ->
+ Expect.float32Close {absolute=0.0f; relative=1e-3f}
+ 10004.0f 10000.0f "user"
- testCase "not less than but close" <| fun _ ->
- Expect.floatLessThanOrClose Accuracy.low 0.000001 0.0 "close"
+ testCase "can fail" (fun _ ->
+ Expect.float32Close Accuracy32.low 1004.0f 1000.0f "can fail"
+ ) |> assertTestFails
- testCase "not less than fails" (fun _ ->
- Expect.floatLessThanOrClose Accuracy.low 1.0 0.0 "fail"
- ) |> assertTestFails
+ testCase "nan fails" (fun _ ->
+ Expect.float32Close Accuracy32.low nanf 1.0f "nanf fails"
+ ) |> assertTestFails
- testCase "greater than easy" <| fun _ ->
- Expect.floatGreaterThanOrClose Accuracy.low 1.0 0.0 "greater"
+ testCase "inf fails" (fun _ ->
+ Expect.float32Close Accuracy32.low infinityf 1.0f "infinityf fails"
+ ) |> assertTestFails
- testCase "not greater than but close" <| fun _ ->
- Expect.floatGreaterThanOrClose Accuracy.low -0.000001 0.0 "close"
+ testCase "less than easy" <| fun _ ->
+ Expect.float32LessThanOrClose Accuracy32.low -1.0f 0.0f "less"
- testCase "not greater than fails" (fun _ ->
- Expect.floatGreaterThanOrClose Accuracy.low -1.0 0.0 "fail"
- ) |> assertTestFails
+ testCase "not less than but close" <| fun _ ->
+ Expect.float32LessThanOrClose Accuracy32.low 0.000001f 0.0f "close"
+ testCase "not less than fails" (fun _ ->
+ Expect.float32LessThanOrClose Accuracy32.low 1.0f 0.0f "fail"
+ ) |> assertTestFails
+
+ testCase "greater than easy" <| fun _ ->
+ Expect.float32GreaterThanOrClose Accuracy32.low 1.0f 0.0f "greater"
+
+ testCase "not greater than but close" <| fun _ ->
+ Expect.float32GreaterThanOrClose Accuracy32.low -0.000001f 0.0f "close"
+
+ testCase "not greater than fails" (fun _ ->
+ Expect.float32GreaterThanOrClose Accuracy32.low -1.0f 0.0f "fail"
+ ) |> assertTestFails
+ ]
+ testList "float32" [
+ testCase "zero" <| fun _ ->
+ Expect.float32Close Accuracy32.veryHigh 0.0f 0.0f "zero"
+
+ testCase "small" <| fun _ ->
+ Expect.float32Close Accuracy32.low 0.000001f 0.0f "small"
+
+ testCase "large" <| fun _ ->
+ Expect.float32Close Accuracy32.low 10004.0f 10000.0f "large"
+
+ testCase "user" <| fun _ ->
+ Expect.float32Close {absolute=0.0f; relative=1e-3f}
+ 10004.0f 10000.0f "user"
+
+ testCase "can fail" (fun _ ->
+ Expect.float32Close Accuracy32.low 1004.0f 1000.0f "can fail"
+ ) |> assertTestFails
+
+ testCase "nan fails" (fun _ ->
+ Expect.float32Close Accuracy32.low (Float32WithMeasure nanf) 1.0f "nanf fails"
+ ) |> assertTestFails
+
+ testCase "inf fails" (fun _ ->
+ Expect.float32Close Accuracy32.low (Float32WithMeasure infinityf) 1.0f "infinityf fails"
+ ) |> assertTestFails
+
+ testCase "less than easy" <| fun _ ->
+ Expect.float32LessThanOrClose Accuracy32.low -1.0f 0.0f "less"
+
+ testCase "not less than but close" <| fun _ ->
+ Expect.float32LessThanOrClose Accuracy32.low 0.000001f 0.0f "close"
+
+ testCase "not less than fails" (fun _ ->
+ Expect.float32LessThanOrClose Accuracy32.low 1.0f 0.0f "fail"
+ ) |> assertTestFails
+
+ testCase "greater than easy" <| fun _ ->
+ Expect.float32GreaterThanOrClose Accuracy32.low 1.0f 0.0f "greater"
+
+ testCase "not greater than but close" <| fun _ ->
+ Expect.float32GreaterThanOrClose Accuracy32.low -0.000001f 0.0f "close"
+
+ testCase "not greater than fails" (fun _ ->
+ Expect.float32GreaterThanOrClose Accuracy32.low -1.0f 0.0f "fail"
+ ) |> assertTestFails
+ ]
]
[]
diff --git a/Expecto/Expect.fs b/Expecto/Expect.fs
index 2177ddc3..6abc092a 100644
--- a/Expecto/Expect.fs
+++ b/Expecto/Expect.fs
@@ -276,10 +276,24 @@ let floatEqual actual expected epsilon message =
/// Expects `actual` and `expected` (that are both floats) to be within a
/// given `accuracy`.
-let floatClose accuracy actual expected message =
- if Double.IsInfinity actual then
+let floatClose (accuracy: Accuracy<'u>) (actual: float<'u>) (expected: float<'u>) (message: string) : unit =
+ if Double.IsInfinity (float actual) then
failtestf "%s. Expected actual to not be infinity, but it was." message
- elif Double.IsInfinity expected then
+ elif Double.IsInfinity (float expected) then
+ failtestf "%s. Expected expected to not be infinity, but it was." message
+ elif Accuracy.areClose accuracy actual expected |> not then
+ failtestf
+ "%s. Expected difference to be less than %.20g for accuracy {absolute=%.20g; relative=%.20g}, but was %.20g. actual=%.20g expected=%.20g"
+ message (Accuracy.areCloseRhs accuracy actual expected)
+ accuracy.absolute accuracy.relative
+ (Accuracy.areCloseLhs actual expected)
+ actual expected
+/// Expects `actual` and `expected` (that are both float32s) to be within a
+/// given `accuracy`.
+let float32Close (accuracy: Accuracy32<'u>) (actual: float32<'u>) (expected: float32<'u>) message =
+ if Single.IsInfinity (float32 actual) then
+ failtestf "%s. Expected actual to not be infinity, but it was." message
+ elif Single.IsInfinity (float32 expected) then
failtestf "%s. Expected expected to not be infinity, but it was." message
elif Accuracy.areClose accuracy actual expected |> not then
failtestf
@@ -292,22 +306,75 @@ let floatClose accuracy actual expected message =
/// given `accuracy`.
let floatLessThanOrClose accuracy actual expected message =
if actual>expected then floatClose accuracy actual expected message
+/// Expects `actual` to be less than `expected` or to be within a
+/// given `accuracy`.
+let float32LessThanOrClose accuracy actual expected message =
+ if actual>expected then float32Close accuracy actual expected message
/// Expects `actual` to be greater than `expected` or to be within a
/// given `accuracy`.
let floatGreaterThanOrClose accuracy actual expected message =
if actual) message =
+ if not (Double.IsNaN (float f)) then failtestf "%s. Float should be a NaN (not a number) value." message
+
+/// Expect the passed float to not be a number.
+let isNaNf (f: float32<'u>) message =
+ if not (Single.IsNaN (float32 f)) then failtestf "%s. Float should be a NaN (not a number) value." message
+
+/// Expect the passed float to be a number.
+let isNotNaN (f: float<'u>) message =
+ if Double.IsNaN (float f) then failtestf "%s. Float was the NaN (not a number) value." message
/// Expect the passed float to be a number.
-let isNotNaN f message =
- if Double.IsNaN f then failtestf "%s. Float was the NaN (not a number) value." message
+let isNotNaNf (f: float32<'u>) message =
+ if Single.IsNaN (float32 f) then failtestf "%s. Float was the NaN (not a number) value." message
+
/// Expect the passed float not to be positive infinity.
-let isNotPositiveInfinity actual message =
- if Double.IsPositiveInfinity actual then failtestf "%s. Float was positive infinity." message
+let isPositiveInfinity (actual: float<'u>) message =
+ if not (Double.IsPositiveInfinity (float actual)) then failtestf "%s. Float should be positive infinity." message
+
+/// Expect the passed float not to be positive infinity.
+let isPositiveInfinityf (actual: float32<'u>) message =
+ if not (Single.IsPositiveInfinity (float32 actual)) then failtestf "%s. Float should be positive infinity." message
/// Expect the passed float not to be negative infinity.
-let isNotNegativeInfinity actual message =
- if Double.IsNegativeInfinity actual then failtestf "%s. Float was negative infinity." message
+let isNegativeInfinity (actual: float<'u>) message =
+ if not (Double.IsNegativeInfinity (float actual)) then failtestf "%s. Float should be negative infinity." message
+
+/// Expect the passed float not to be negative infinity.
+let isNegativeInfinityf (actual: float32<'u>) message =
+ if not (Single.IsNegativeInfinity (float32 actual)) then failtestf "%s. Float should be negative infinity." message
+
+/// Expect the passed float not to be infinity.
+let isInfinity (actual: float<'u>) message =
+ if not (Double.IsInfinity (float actual)) then failtestf "%s. Float should be infinity." message
+
+/// Expect the passed float not to be infinity.
+let isInfinityf (actual: float32<'u>) message =
+ if not (Single.IsInfinity (float32 actual)) then failtestf "%s. Float should be infinity." message
+
+/// Expect the passed float not to be positive infinity.
+let isNotPositiveInfinity (actual: float<'u>) message =
+ if Double.IsPositiveInfinity (float actual) then failtestf "%s. Float was positive infinity." message
+
+/// Expect the passed float not to be positive infinity.
+let isNotPositiveInfinityf (actual: float32<'u>) message =
+ if Single.IsPositiveInfinity (float32 actual) then failtestf "%s. Float was positive infinity." message
+
+/// Expect the passed float not to be negative infinity.
+let isNotNegativeInfinity (actual: float<'u>) message =
+ if Double.IsNegativeInfinity (float actual) then failtestf "%s. Float was negative infinity." message
+
+/// Expect the passed float not to be negative infinity.
+let isNotNegativeInfinityf (actual: float32<'u>) message =
+ if Single.IsNegativeInfinity (float32 actual) then failtestf "%s. Float was negative infinity." message
/// Expect the passed float not to be infinity.
let isNotInfinity actual message =
@@ -315,6 +382,12 @@ let isNotInfinity actual message =
isNotPositiveInfinity actual message
// passed via excluded middle
+/// Expect the passed float not to be infinity.
+let isNotInfinityf actual message =
+ isNotNegativeInfinityf actual message
+ isNotPositiveInfinityf actual message
+ // passed via excluded middle
+
/// Expect the passed string not to be empty.
let isNotEmpty (actual : string) message =
isNotNull actual message
diff --git a/Expecto/Flip.Expect.fs b/Expecto/Flip.Expect.fs
index 1e33a17f..019d61cf 100644
--- a/Expecto/Flip.Expect.fs
+++ b/Expecto/Flip.Expect.fs
@@ -72,26 +72,50 @@ let inline isGreaterThanOrEqual message (a, b) = Expecto.Expect.isGreaterThanOrE
/// given `accuracy`.
let inline floatClose message accuracy expected actual = Expecto.Expect.floatClose accuracy actual expected message
+/// Expects `actual` and `expected` (that are both floats) to be within a
+/// given `accuracy`.
+let inline float32Close message accuracy expected actual = Expecto.Expect.float32Close accuracy actual expected message
+
/// Expects `actual` to be less than `expected` or to be within a
/// given `accuracy`.
let inline floatLessThanOrClose message accuracy expected actual = Expecto.Expect.floatLessThanOrClose accuracy actual expected message
+/// Expects `actual` to be less than `expected` or to be within a
+/// given `accuracy`.
+let inline float32LessThanOrClose message accuracy expected actual = Expecto.Expect.float32LessThanOrClose accuracy actual expected message
+
/// Expects `actual` to be greater than `expected` or to be within a
/// given `accuracy`.
let inline floatGreaterThanOrClose message accuracy expected actual = Expecto.Expect.floatGreaterThanOrClose accuracy actual expected message
+/// Expects `actual` to be greater than `expected` or to be within a
+/// given `accuracy`.
+let inline float32GreaterThanOrClose message accuracy expected actual = Expecto.Expect.float32GreaterThanOrClose accuracy actual expected message
+
/// Expect the passed float to be a number.
let inline isNotNaN message f = Expecto.Expect.isNotNaN f message
+/// Expect the passed float to be a number.
+let inline isNotNaNf message f = Expecto.Expect.isNotNaNf f message
+
/// Expect the passed float not to be positive infinity.
let inline isNotPositiveInfinity message f = Expecto.Expect.isNotPositiveInfinity f message
+/// Expect the passed float not to be positive infinity.
+let inline isNotPositiveInfinityf message f = Expecto.Expect.isNotPositiveInfinityf f message
+
/// Expect the passed float not to be negative infinity.
let inline isNotNegativeInfinity message f = Expecto.Expect.isNotNegativeInfinity f message
+/// Expect the passed float not to be negative infinity.
+let inline isNotNegativeInfinityf message f = Expecto.Expect.isNotNegativeInfinityf f message
+
/// Expect the passed float not to be infinity.
let inline isNotInfinity message f = Expecto.Expect.isNotInfinity f message
+/// Expect the passed float not to be infinity.
+let inline isNotInfinityf message f = Expecto.Expect.isNotInfinityf f message
+
/// Expect the passed string not to be empty.
let inline isNotEmpty message actual = Expecto.Expect.isNotEmpty actual message
diff --git a/Expecto/Performance.fs b/Expecto/Performance.fs
index f640c351..db1f6803 100644
--- a/Expecto/Performance.fs
+++ b/Expecto/Performance.fs
@@ -3,17 +3,35 @@ namespace Expecto
open System
open Expecto.Logging
open Expecto.Logging.Message
+open FSharp.Core.LanguagePrimitives
-type Accuracy = { absolute: float; relative: float }
+type Accuracy<'abs, 'rel> = { absolute: 'abs; relative: 'rel }
+
+type Accuracy<[] 'u> = Accuracy, float>
+type Accuracy = Accuracy<1>
+type Accuracy32<[] 'u> = Accuracy, float32>
+type Accuracy32 = Accuracy32<1>
module Accuracy =
- let inline areCloseLhs a b = abs(a-b)
- let inline areCloseRhs m a b = m.absolute + m.relative * max (abs a) (abs b)
- let inline areClose m a b = areCloseLhs a b <= areCloseRhs m a b
- let low = {absolute=1e-6; relative=1e-3}
- let medium = {absolute=1e-8; relative=1e-5}
- let high = {absolute=1e-10; relative=1e-7}
- let veryHigh = {absolute=1e-12; relative=1e-9}
+ let inline areCloseLhs a b : ^a = abs(a-b)
+ let inline areCloseRhs (m: Accuracy<'a,_>) (a: 'a) (b: 'a) : 'a = m.absolute + m.relative * max (abs a) (abs b)
+ let inline areClose (m: Accuracy<'a,_>) (a: 'a) (b: 'a) : bool = areCloseLhs a b <= areCloseRhs m a b
+
+ let low<[] 'u> : Accuracy<'u> = { absolute = FloatWithMeasure 1e-6; relative = 1e-3 }
+ let medium<[] 'u> : Accuracy<'u> = { absolute = FloatWithMeasure 1e-8; relative = 1e-5 }
+ let mediumf<[] 'u> : Accuracy32<'u> = { absolute = Float32WithMeasure 1e-8f; relative = 1e-5f }
+ let high<[] 'u> : Accuracy<'u> = { absolute = FloatWithMeasure 1e-10; relative = 1e-7 }
+ let highf<[] 'u> : Accuracy32<'u> = { absolute = Float32WithMeasure 1e-10f; relative = 1e-7f }
+ let veryHigh<[] 'u> : Accuracy<'u> = { absolute = FloatWithMeasure 1e-12; relative = 1e-9 }
+ let veryHighf<[] 'u> : Accuracy32<'u> = { absolute = Float32WithMeasure 1e-12f; relative = 1e-9f }
+
+module Accuracy32 =
+ open Accuracy
+
+ let low<[] 'u> : Accuracy32<'u> = { absolute = Float32WithMeasure 1e-6f; relative = 1e-3f }
+ let medium<[] 'u> : Accuracy32<'u> = { absolute = Float32WithMeasure 1e-8f; relative = 1e-5f }
+ let high<[] 'u> : Accuracy32<'u> = { absolute = Float32WithMeasure 1e-10f; relative = 1e-7f }
+ let veryHigh<[] 'u> : Accuracy32<'u> = { absolute = Float32WithMeasure 1e-12f; relative = 1e-9f }
module Performance =
open Statistics