diff options
author | Janne Grunau <janne-libav@jannau.net> | 2015-12-07 18:14:46 +0300 |
---|---|---|
committer | Janne Grunau <janne-libav@jannau.net> | 2015-12-21 19:40:18 +0300 |
commit | 9d218d573f8088c606d873e80df572582e6773ef (patch) | |
tree | d46a9984d723b29be19b4a96b11b1b4ee813053c /tests | |
parent | 711781d7a1714ea4eb0217eb1ba04811978c43d1 (diff) |
checkasm: add float comparison util functions
Diffstat (limited to 'tests')
-rw-r--r-- | tests/checkasm/checkasm.c | 73 | ||||
-rw-r--r-- | tests/checkasm/checkasm.h | 11 |
2 files changed, 84 insertions, 0 deletions
diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 37bc13983d..becfe357c3 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -27,6 +27,7 @@ #include "checkasm.h" #include "libavutil/common.h" #include "libavutil/cpu.h" +#include "libavutil/intfloat.h" #include "libavutil/random_seed.h" #if HAVE_IO_H @@ -151,6 +152,78 @@ static struct { /* PRNG state */ AVLFG checkasm_lfg; +/* float compare support code */ +static int is_negative(union av_intfloat32 u) +{ + return u.i >> 31; +} + +int float_near_ulp(float a, float b, unsigned max_ulp) +{ + union av_intfloat32 x, y; + + x.f = a; + y.f = b; + + if (is_negative(x) != is_negative(y)) { + // handle -0.0 == +0.0 + return a == b; + } + + if (abs(x.i - y.i) <= max_ulp) + return 1; + + return 0; +} + +int float_near_ulp_array(const float *a, const float *b, unsigned max_ulp, + unsigned len) +{ + unsigned i; + + for (i = 0; i < len; i++) { + if (!float_near_ulp(a[i], b[i], max_ulp)) + return 0; + } + return 1; +} + +int float_near_abs_eps(float a, float b, float eps) +{ + float abs_diff = fabsf(a - b); + + return abs_diff < eps; +} + +int float_near_abs_eps_array(const float *a, const float *b, float eps, + unsigned len) +{ + unsigned i; + + for (i = 0; i < len; i++) { + if (!float_near_abs_eps(a[i], b[i], eps)) + return 0; + } + return 1; +} + +int float_near_abs_eps_ulp(float a, float b, float eps, unsigned max_ulp) +{ + return float_near_ulp(a, b, max_ulp) || float_near_abs_eps(a, b, eps); +} + +int float_near_abs_eps_array_ulp(const float *a, const float *b, float eps, + unsigned max_ulp, unsigned len) +{ + unsigned i; + + for (i = 0; i < len; i++) { + if (!float_near_abs_eps_ulp(a[i], b[i], eps, max_ulp)) + return 0; + } + return 1; +} + /* Print colored text to stderr if the terminal supports it */ static void color_printf(int color, const char *fmt, ...) { diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 6fc30ca0a2..4a4cce4286 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -42,6 +42,17 @@ void checkasm_fail_func(const char *msg, ...) av_printf_format(1, 2); void checkasm_update_bench(int iterations, uint64_t cycles); void checkasm_report(const char *name, ...) av_printf_format(1, 2); +/* float compare utilities */ +int float_near_ulp(float a, float b, unsigned max_ulp); +int float_near_abs_eps(float a, float b, float eps); +int float_near_abs_eps_ulp(float a, float b, float eps, unsigned max_ulp); +int float_near_ulp_array(const float *a, const float *b, unsigned max_ulp, + unsigned len); +int float_near_abs_eps_array(const float *a, const float *b, float eps, + unsigned len); +int float_near_abs_eps_array_ulp(const float *a, const float *b, float eps, + unsigned max_ulp, unsigned len); + extern AVLFG checkasm_lfg; #define rnd() av_lfg_get(&checkasm_lfg) |