Skip to content

Commit c474fa8

Browse files
committed
Fix: YT_*_DOUBLE wrong results on large numbers
1 parent 87790e2 commit c474fa8

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

yukti.h

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include <stdbool.h>
3737
#include <stdarg.h>
3838
#include <sys/time.h>
39+
#include <float.h>
40+
#include <math.h>
3941

4042
/*
4143
* ========================================================================================
@@ -846,18 +848,27 @@ static int YT__equal_string (const char* a, const char* b, int* i);
846848
#define AUTOTYPE __auto_type
847849
#endif /* __cplusplus */
848850

849-
#define YT__TEST_DOUBLE(e, a, o, b, op) \
850-
do { \
851-
AUTOTYPE ut_a = (a); \
852-
AUTOTYPE ut_b = (b); \
853-
YT__current_testrecord->total_exp_count++; \
854-
if (ut_a > ut_b) { \
855-
if (!(ut_a - ut_b o (e))) \
856-
YT__FAILED (a op b, "[%f !" #op " %f]", ut_a, ut_b); \
857-
} else { \
858-
if (!(ut_b - ut_a o (e))) \
859-
YT__FAILED (a op b, "[%f !" #op " %f]", ut_a, ut_b); \
860-
} \
851+
static bool yt__approxeq (double a, double b, double epsilon)
852+
{
853+
double ut_a = fabs (a);
854+
double ut_b = fabs (b);
855+
856+
if ((isfinite (a) && isfinite (b)) || (ut_a == 0.0 && ut_b == 0.0) || (isnan (a) && isnan (b)))
857+
return true;
858+
if ((isfinite (a) && !isfinite (b)) || (!isfinite (a) && isfinite (b)))
859+
return false;
860+
861+
// Source: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
862+
double ut_diff = fabs (a - b);
863+
double ut_largest = (ut_a > ut_b) ? ut_a : ut_b;
864+
return (ut_diff <= ut_largest * epsilon);
865+
}
866+
867+
#define YT__TEST_DOUBLE(e, a, o, b) \
868+
do { \
869+
if (!(yt__approxeq (a, b, e) o true)) { \
870+
YT__FAILED (a o b, "[%f !" #o " %f]", a, b); \
871+
} \
861872
} while (0)
862873

863874
#define YT__TEST_SCALAR(a, o, b) \
@@ -889,8 +900,8 @@ static int YT__equal_string (const char* a, const char* b, int* i);
889900
YT__FAILED (a o b, "[Idx: %d, '%c' !" #o " '%c']", i, ut_a[i], ut_b[i]); \
890901
} while (0)
891902

892-
#define YT_EQ_DOUBLE(a, b, e) YT__TEST_DOUBLE (e, a, <=, b, ==)
893-
#define YT_NEQ_DOUBLE(a, b, e) YT__TEST_DOUBLE (e, a, >, b, !=)
903+
#define YT_EQ_DOUBLE(a, b, e) YT__TEST_DOUBLE (e, a, ==, b)
904+
#define YT_NEQ_DOUBLE(a, b, e) YT__TEST_DOUBLE (e, a, !=, b)
894905
#define YT_EQ_SCALAR(a, b) YT__TEST_SCALAR (a, ==, b)
895906
#define YT_NEQ_SCALAR(a, b) YT__TEST_SCALAR (a, !=, b)
896907
#define YT_GEQ_SCALAR(a, b) YT__TEST_SCALAR (a, >=, b)

0 commit comments

Comments
 (0)