From 9d9de3baaba6271e9ca3df23b4bb7e155ae1dd1f Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Sun, 29 Mar 2026 20:10:49 +0200 Subject: [PATCH 1/3] address imprecision in ivas_get_dirac_sba_max_md_bits() with -funsafe-math-optimizations --- lib_com/ivas_dirac_com.c | 13 +++++++++++++ lib_com/options.h | 1 + 2 files changed, 14 insertions(+) diff --git a/lib_com/ivas_dirac_com.c b/lib_com/ivas_dirac_com.c index 3396815be..012c6f345 100644 --- a/lib_com/ivas_dirac_com.c +++ b/lib_com/ivas_dirac_com.c @@ -385,7 +385,20 @@ void ivas_get_dirac_sba_max_md_bits( *metadata_max_bits = MAX16B; /* no limit */ } +#ifdef FIX_FLOAT_1544_SBA_META_IMPRECISION_UNSAFE_MATH + /* + The expression ceilf( (float) *metadata_max_bits * nbands / 5 ) was converted to double precision because of issues with -funsafe-math-optimizations, + where an imprecision of the division in combination with the ceilf()-operator could actually produce different results (+1) for *metadata_max_bits. + Alternative ways to address this: + 1) Pick up the corresponding code from the BASOP codebase + 2) An expression which takes care of small imprecisions of the division, e.g., ceilf( ( (float) *metadata_max_bits * nbands / 5 ) - 0.1f ) + (minimum non-zero fractional part for X / 5 is 0.2 - substract half of this, to compensate for imprecisions; the ceilf() should still return the correct integer) + For reasons of code-readability, the variant with double precision was chosen. + */ + *metadata_max_bits = (int16_t) min( (float) MAX16B, ceilf( (double) *metadata_max_bits * nbands / 5 ) ); +#else *metadata_max_bits = (int16_t) min( (float) MAX16B, ceilf( (float) *metadata_max_bits * nbands / 5 ) ); +#endif *qmetadata_max_bit_req = QMETADATA_MAXBIT_REQ_SBA >> 1; return; diff --git a/lib_com/options.h b/lib_com/options.h index 94bc26d82..96a3c3488 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -162,6 +162,7 @@ #define TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR /* FhG: Temporary workaround for incorrect implementation of decoder flush with split rendering */ #define NONBE_1122_KEEP_EVS_MODE_UNCHANGED /* FhG: Disables fix for issue 1122 in EVS mode to keep BE tests green. This switch should be removed once the 1122 fix is added to EVS via a CR. */ #define FIX_BASOP_2469_OBJ_EDIT_TD_REND_GAIN /* Eri: Basop issue 2469: TD renderer gain has wrong Q. In float this is just a synch of the cleanup done in BASOP */ +#define FIX_FLOAT_1544_SBA_META_IMPRECISION_UNSAFE_MATH /* FhG: float issue 1544: imprecision in ivas_get_dirac_sba_max_md_bits() with -funsafe-math-optimizations */ /* #################### End BE switches ################################## */ -- GitLab From b91110401a1028fe310a2ff10763114926cbc03e Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Sun, 29 Mar 2026 20:17:06 +0200 Subject: [PATCH 2/3] try to make stupid VS compiler happy --- lib_com/ivas_dirac_com.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/ivas_dirac_com.c b/lib_com/ivas_dirac_com.c index 012c6f345..5ca88ae6f 100644 --- a/lib_com/ivas_dirac_com.c +++ b/lib_com/ivas_dirac_com.c @@ -395,7 +395,7 @@ void ivas_get_dirac_sba_max_md_bits( (minimum non-zero fractional part for X / 5 is 0.2 - substract half of this, to compensate for imprecisions; the ceilf() should still return the correct integer) For reasons of code-readability, the variant with double precision was chosen. */ - *metadata_max_bits = (int16_t) min( (float) MAX16B, ceilf( (double) *metadata_max_bits * nbands / 5 ) ); + *metadata_max_bits = (int16_t) min( (float) MAX16B, ceilf( (float) ( (double) *metadata_max_bits * nbands / 5 ) ) ); #else *metadata_max_bits = (int16_t) min( (float) MAX16B, ceilf( (float) *metadata_max_bits * nbands / 5 ) ); #endif -- GitLab From 9fbfa161a22857b4a29bcfcbb092c549453dd527 Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Mon, 30 Mar 2026 09:36:40 +0200 Subject: [PATCH 3/3] alternative workaround using a multiplication instead of a division --- lib_com/ivas_dirac_com.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib_com/ivas_dirac_com.c b/lib_com/ivas_dirac_com.c index 5ca88ae6f..109437894 100644 --- a/lib_com/ivas_dirac_com.c +++ b/lib_com/ivas_dirac_com.c @@ -387,15 +387,12 @@ void ivas_get_dirac_sba_max_md_bits( #ifdef FIX_FLOAT_1544_SBA_META_IMPRECISION_UNSAFE_MATH /* - The expression ceilf( (float) *metadata_max_bits * nbands / 5 ) was converted to double precision because of issues with -funsafe-math-optimizations, - where an imprecision of the division in combination with the ceilf()-operator could actually produce different results (+1) for *metadata_max_bits. - Alternative ways to address this: - 1) Pick up the corresponding code from the BASOP codebase - 2) An expression which takes care of small imprecisions of the division, e.g., ceilf( ( (float) *metadata_max_bits * nbands / 5 ) - 0.1f ) - (minimum non-zero fractional part for X / 5 is 0.2 - substract half of this, to compensate for imprecisions; the ceilf() should still return the correct integer) - For reasons of code-readability, the variant with double precision was chosen. + original formula was: + *metadata_max_bits = (int16_t) min( (float) MAX16B, ceilf( (float) *metadata_max_bits * nbands / 5 ) ); + The division by 5 is replaced by a multiplication by 0.2f, since the division is causing problems for + certain optimizations using -funsafe-math-optimizations */ - *metadata_max_bits = (int16_t) min( (float) MAX16B, ceilf( (float) ( (double) *metadata_max_bits * nbands / 5 ) ) ); + *metadata_max_bits = (int16_t) min( (float) MAX16B, ceilf( *metadata_max_bits * nbands * 0.2f ) ); #else *metadata_max_bits = (int16_t) min( (float) MAX16B, ceilf( (float) *metadata_max_bits * nbands / 5 ) ); #endif -- GitLab