|
36 | 36 | #include <stdbool.h> |
37 | 37 | #include <stdarg.h> |
38 | 38 | #include <sys/time.h> |
| 39 | +#include <float.h> |
| 40 | +#include <math.h> |
39 | 41 |
|
40 | 42 | /* |
41 | 43 | * ======================================================================================== |
@@ -846,18 +848,27 @@ static int YT__equal_string (const char* a, const char* b, int* i); |
846 | 848 | #define AUTOTYPE __auto_type |
847 | 849 | #endif /* __cplusplus */ |
848 | 850 |
|
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 | + } \ |
861 | 872 | } while (0) |
862 | 873 |
|
863 | 874 | #define YT__TEST_SCALAR(a, o, b) \ |
@@ -889,8 +900,8 @@ static int YT__equal_string (const char* a, const char* b, int* i); |
889 | 900 | YT__FAILED (a o b, "[Idx: %d, '%c' !" #o " '%c']", i, ut_a[i], ut_b[i]); \ |
890 | 901 | } while (0) |
891 | 902 |
|
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) |
894 | 905 | #define YT_EQ_SCALAR(a, b) YT__TEST_SCALAR (a, ==, b) |
895 | 906 | #define YT_NEQ_SCALAR(a, b) YT__TEST_SCALAR (a, !=, b) |
896 | 907 | #define YT_GEQ_SCALAR(a, b) YT__TEST_SCALAR (a, >=, b) |
|
0 commit comments