Skip to content

Commit

Permalink
Using math.isClose instead of math.approxEqual
Browse files Browse the repository at this point in the history
  • Loading branch information
Zardoz89 committed Mar 27, 2021
1 parent 8700f8c commit 13c1e8a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 10 deletions.
48 changes: 45 additions & 3 deletions source/pijamas.d
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,49 @@ class Assertion(T)
return context;
}

// Ripped from std.math
private template CommonDefaultFor(T,U)
{
import std.traits : CommonType;
import std.algorithm.comparison : min;

alias baseT = FloatingPointBaseType!T;
alias baseU = FloatingPointBaseType!U;

enum CommonType!(baseT, baseU) CommonDefaultFor = 10.0L ^^ -((min(baseT.dig, baseU.dig) + 1) / 2 + 1);
}

private template FloatingPointBaseType(T)
{
import std.traits : isFloatingPoint;
import std.range.primitives : ElementType;
static if (isFloatingPoint!T)
{
alias FloatingPointBaseType = Unqual!T;
}
else static if (isFloatingPoint!(ElementType!(Unqual!T)))
{
alias FloatingPointBaseType = Unqual!(ElementType!(Unqual!T));
}
else
{
alias FloatingPointBaseType = real;
}
}

/**
* Asserts that a float type is aproximated equal. Returns the valued wrapped around the assertion
*
* Params:
* other = Value to compare to compare.
* maxRelDiff = Maximum allowable relative difference.
* Setting to 0.0 disables this check. Default depends on the type of
* `other` and the original valie: It is approximately half the number of decimal digits of
* precision of the smaller type.
* maxAbsDiff = Maximum absolute difference. This is mainly usefull
* for comparing values to zero. Setting to 0.0 disables this check.
* Defaults to `0.0`.
*
* Examples:
* ```
* double d = 0.1;
Expand All @@ -114,15 +154,17 @@ class Assertion(T)
* d.should.be.approxEqual(d2);
* ```
*/
T approxEqual(U = double)(U other, U maxRelDiff = 1e-2, U maxAbsDiff = 1e-05,
T approxEqual(U = double)(U other, U maxRelDiff = CommonDefaultFor!(T,U), U maxAbsDiff = 0.0,
string file = __FILE__, size_t line = __LINE__) @trusted
if (is(T : real) && __traits(isFloating, T) && is(U : real) && __traits(isFloating, U))
{
import std.math : approxEqual;
import std.math : isClose;
operator = "be approximated equal than";
this.ok(approxEqual(context, other, maxRelDiff, maxAbsDiff), this.message(other), file, line);
this.ok(isClose(context, other, maxRelDiff, maxAbsDiff), this.message(other), file, line);
return context;
}
///ditto
alias close = approxEqual;

/**
* Asserts whether a value exists - currently simply compares it with null, if it is a pointer, a class or a string.
Expand Down
24 changes: 17 additions & 7 deletions tests/pijamas_spec.d
Original file line number Diff line number Diff line change
Expand Up @@ -196,41 +196,51 @@ import pijamas;
{
float f = 0.01;
f.should.be.approxEqual(f);

f.should.be.close(f);

double d = 0.01;
d.should.be.approxEqual(d);

real r = 0.01;
r.should.be.approxEqual(r);
}

// it("handles comparing diferent float types")
{
float f = 0.01;
double d = 0.01;
real r = 0.01;
f.should.be.approxEqual(d);
f.should.be.approxEqual(r);

d.should.be.approxEqual(f);
d.should.be.approxEqual(r);

r.should.be.approxEqual(f);
r.should.be.approxEqual(d);
}

// it("asserts that two nearly identical float values are approximated equal")
{
float one = 1_000_000_000.0;
one.should.be.close(999_999_999.0);

double d = 0.1;
double d2 = d + 1e-05;
double d2 = d + 1e-10;
d.should.not.be.equal(d2);
d.should.be.approxEqual(d2);

// and("when increase the difference, it must not be approximated equals")
d2 += 1e-2;
d2 += 1e-5;
d.should.not.be.equal(d2);
d.should.not.be.approxEqual(d2);
assertThrown!Exception(d.should.be.approxEqual(d2));

// and("Different default limits for different floating point types")
float oneFloat = 1.0f;
double oneDouble = 1.0;
oneFloat.should.be.close(0.999_99f);
oneDouble.should.not.be.close(0.999_99);
}
}

Expand Down

0 comments on commit 13c1e8a

Please sign in to comment.