From 394ac84df9ecc1556b922c1161503ef74962fe6a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Nov 2021 17:55:59 +0100 Subject: [PATCH 1/2] meson: drop -ffast-math After reading https://simonbyrne.github.io/notes/fastmath/ I think we should drop -ffast-math. The JSON code actually looks for NaN, so the fact it becomes unreliable kinda sucks. Moreover, we don't do any number crunching. We use floating point fields only sporadical for trivial math. Hence the optimization is entirely unnecessary. --- meson.build | 1 - 1 file changed, 1 deletion(-) diff --git a/meson.build b/meson.build index f8b1156455..cc6981825e 100644 --- a/meson.build +++ b/meson.build @@ -409,7 +409,6 @@ possible_cc_flags = possible_common_cc_flags + [ '-Werror=missing-declarations', '-Werror=missing-prototypes', '-fdiagnostics-show-option', - '-ffast-math', '-fno-common', '-fno-strict-aliasing', '-fstack-protector', From c79aaff9d53c992ef0f2d6a24163c9972819df24 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Nov 2021 22:21:51 +0100 Subject: [PATCH 2/2] test-json: add test that makes sure floats are somewhat reasonably implemented Test that we don't loose accuracy without bounds for extreme values, and validate that nan/inf/-inf actually get converted to null properly. --- src/test/test-json.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/test/test-json.c b/src/test/test-json.c index 1d4b11945e..34ea7448a9 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include #include #include "alloc-util.h" @@ -521,6 +522,58 @@ static void test_bisect(void) { } } +static void test_float_match(JsonVariant *v) { + const long double delta = 0.0001; + + assert_se(json_variant_is_array(v)); + assert_se(json_variant_elements(v) == 9); + assert_se(fabsl((long double) 1.0 - ((long double) DBL_MIN / json_variant_real(json_variant_by_index(v, 0)))) <= delta); + assert_se(fabsl((long double) 1.0 - ((long double) DBL_MAX / json_variant_real(json_variant_by_index(v, 1)))) <= delta); + assert_se(json_variant_is_null(json_variant_by_index(v, 2))); /* nan is not supported by json → null */ + assert_se(json_variant_is_null(json_variant_by_index(v, 3))); /* +inf is not supported by json → null */ + assert_se(json_variant_is_null(json_variant_by_index(v, 4))); /* -inf is not supported by json → null */ + assert_se(json_variant_is_null(json_variant_by_index(v, 5)) || + fabsl((long double) 1.0 - ((long double) HUGE_VAL / json_variant_real(json_variant_by_index(v, 5)))) <= delta); /* HUGE_VAL might be +inf, but might also be something else */ + assert_se(json_variant_is_real(json_variant_by_index(v, 6)) && + json_variant_is_integer(json_variant_by_index(v, 6)) && + json_variant_integer(json_variant_by_index(v, 6)) == 0); + assert_se(json_variant_is_real(json_variant_by_index(v, 7)) && + json_variant_is_integer(json_variant_by_index(v, 7)) && + json_variant_integer(json_variant_by_index(v, 7)) == 10); + assert_se(json_variant_is_real(json_variant_by_index(v, 8)) && + json_variant_is_integer(json_variant_by_index(v, 8)) && + json_variant_integer(json_variant_by_index(v, 8)) == -10); +} + +static void test_float(void) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL; + _cleanup_free_ char *text = NULL; + + log_info("/* %s */", __func__); + + assert_se(json_build(&v, JSON_BUILD_ARRAY( + JSON_BUILD_REAL(DBL_MIN), + JSON_BUILD_REAL(DBL_MAX), + JSON_BUILD_REAL(NAN), + JSON_BUILD_REAL(INFINITY), + JSON_BUILD_REAL(-INFINITY), + JSON_BUILD_REAL(HUGE_VAL), + JSON_BUILD_REAL(0), + JSON_BUILD_REAL(10), + JSON_BUILD_REAL(-10))) >= 0); + + json_variant_dump(v, JSON_FORMAT_COLOR|JSON_FORMAT_PRETTY, NULL, NULL); + + test_float_match(v); + + assert_se(json_variant_format(v, 0, &text) >= 0); + assert_se(json_parse(text, 0, &w, NULL, NULL) >= 0); + + json_variant_dump(w, JSON_FORMAT_COLOR|JSON_FORMAT_PRETTY, NULL, NULL); + + test_float_match(w); +} + int main(int argc, char *argv[]) { test_setup_logging(LOG_DEBUG); @@ -573,6 +626,7 @@ int main(int argc, char *argv[]) { test_normalize(); test_bisect(); + test_float(); return 0; }