From 3108aba5c7541cc107f404202c2720439d2cbd15 Mon Sep 17 00:00:00 2001 From: jsalling Date: Tue, 23 Aug 2016 22:36:02 -0500 Subject: [PATCH 1/5] If two floats happen to be equal, return right away Covers the cases where infinity == infinity --- src/unity.c | 4 ++++ test/tests/testunity.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/unity.c b/src/unity.c index 159e0d9..496183a 100644 --- a/src/unity.c +++ b/src/unity.c @@ -683,6 +683,8 @@ void UnityAssertFloatsWithin(const _UF delta, UNITY_SKIP_EXECUTION; + if (expected == actual) return; + if (diff < 0.0f) { diff = 0.0f - diff; @@ -844,6 +846,8 @@ void UnityAssertDoublesWithin(const _UD delta, UNITY_SKIP_EXECUTION; + if (expected == actual) return; + if (diff < 0.0) { diff = 0.0 - diff; diff --git a/test/tests/testunity.c b/test/tests/testunity.c index 830dc57..f922b28 100644 --- a/test/tests/testunity.c +++ b/test/tests/testunity.c @@ -2838,9 +2838,7 @@ void testFloatsNotEqualBothInf(void) #ifdef UNITY_EXCLUDE_FLOAT TEST_IGNORE(); #else - EXPECT_ABORT_BEGIN TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 1.0f / f_zero); - VERIFY_FAILS_END #endif } @@ -3370,9 +3368,7 @@ void testDoublesNotEqualBothInf(void) #ifdef UNITY_EXCLUDE_DOUBLE TEST_IGNORE(); #else - EXPECT_ABORT_BEGIN TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 1.0 / d_zero); - VERIFY_FAILS_END #endif } From 028ca953d75d9664bc0b6eda5ad3db2cd7cb26b2 Mon Sep 17 00:00:00 2001 From: jsalling Date: Sat, 27 Aug 2016 15:12:45 -0500 Subject: [PATCH 2/5] Finish checking for equal floats in Arrays functions Refactor to use the same code everywhere for FloatWithin check Rename and fix a few tests for new behavior, infinity == infinity --- src/unity.c | 76 ++++++++++++++---------------------------- test/tests/testunity.c | 14 +++----- 2 files changed, 30 insertions(+), 60 deletions(-) diff --git a/src/unity.c b/src/unity.c index 496183a..17ad7cc 100644 --- a/src/unity.c +++ b/src/unity.c @@ -618,7 +618,22 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, } /*-----------------------------------------------*/ +/* Wrap this define in a function with variable types as float or double */ +#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \ + if (expected == actual) return 1; \ + diff = actual - expected; \ + if (diff < 0.0f) diff = 0.0f - diff; \ + if (delta < 0.0f) delta = 0.0f - delta; \ + return !(isnan(diff) || isinf(diff) || (delta < diff)); + /* This first part of this condition will catch any NaN or Infinite values */ + #ifndef UNITY_EXCLUDE_FLOAT +static int UnityFloatsWithin(_UF delta, _UF expected, _UF actual) +{ + _UF diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const _UF* expected, UNITY_PTR_ATTRIBUTE const _UF* actual, const _UU32 num_elements, @@ -628,7 +643,6 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const _UF* expected, _UU32 elements = num_elements; UNITY_PTR_ATTRIBUTE const _UF* ptr_expected = expected; UNITY_PTR_ATTRIBUTE const _UF* ptr_actual = actual; - _UF diff, tol; UNITY_SKIP_EXECUTION; @@ -642,15 +656,7 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const _UF* expected, while (elements--) { - diff = *ptr_expected - *ptr_actual; - if (diff < 0.0f) - diff = 0.0f - diff; - tol = UNITY_FLOAT_PRECISION * *ptr_expected; - if (tol < 0.0f) - tol = 0.0f - tol; - - /* This first part of this condition will catch any NaN or Infinite values */ - if (isnan(diff) || isinf(diff) || (diff > tol)) + if (!UnityFloatsWithin(*ptr_expected * UNITY_FLOAT_PRECISION, *ptr_expected, *ptr_actual)) { UnityTestResultsFailBegin(lineNumber); UnityPrint(UnityStrElement); @@ -678,24 +684,10 @@ void UnityAssertFloatsWithin(const _UF delta, const char* msg, const UNITY_LINE_TYPE lineNumber) { - _UF diff = actual - expected; - _UF pos_delta = delta; - UNITY_SKIP_EXECUTION; - if (expected == actual) return; - if (diff < 0.0f) - { - diff = 0.0f - diff; - } - if (pos_delta < 0.0f) - { - pos_delta = 0.0f - pos_delta; - } - - /* This first part of this condition will catch any NaN or Infinite values */ - if (isnan(diff) || isinf(diff) || (pos_delta < diff)) + if (!UnityFloatsWithin(delta, expected, actual)) { UnityTestResultsFailBegin(lineNumber); #ifdef UNITY_FLOAT_VERBOSE @@ -782,6 +774,12 @@ void UnityAssertFloatSpecial(const _UF actual, /*-----------------------------------------------*/ #ifndef UNITY_EXCLUDE_DOUBLE +static int UnityDoublesWithin(_UD delta, _UD expected, _UD actual) +{ + _UD diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const _UD* expected, UNITY_PTR_ATTRIBUTE const _UD* actual, const _UU32 num_elements, @@ -791,7 +789,6 @@ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const _UD* expected, _UU32 elements = num_elements; UNITY_PTR_ATTRIBUTE const _UD* ptr_expected = expected; UNITY_PTR_ATTRIBUTE const _UD* ptr_actual = actual; - _UD diff, tol; UNITY_SKIP_EXECUTION; @@ -805,15 +802,7 @@ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const _UD* expected, while (elements--) { - diff = *ptr_expected - *ptr_actual; - if (diff < 0.0) - diff = 0.0 - diff; - tol = UNITY_DOUBLE_PRECISION * *ptr_expected; - if (tol < 0.0) - tol = 0.0 - tol; - - /* This first part of this condition will catch any NaN or Infinite values */ - if (isnan(diff) || isinf(diff) || (diff > tol)) + if (!UnityDoublesWithin(*ptr_expected * UNITY_DOUBLE_PRECISION, *ptr_expected, *ptr_actual)) { UnityTestResultsFailBegin(lineNumber); UnityPrint(UnityStrElement); @@ -841,24 +830,9 @@ void UnityAssertDoublesWithin(const _UD delta, const char* msg, const UNITY_LINE_TYPE lineNumber) { - _UD diff = actual - expected; - _UD pos_delta = delta; - UNITY_SKIP_EXECUTION; - if (expected == actual) return; - - if (diff < 0.0) - { - diff = 0.0 - diff; - } - if (pos_delta < 0.0) - { - pos_delta = 0.0 - pos_delta; - } - - /* This first part of this condition will catch any NaN or Infinite values */ - if (isnan(diff) || isinf(diff) || (pos_delta < diff)) + if (!UnityDoublesWithin(delta, expected, actual)) { UnityTestResultsFailBegin(lineNumber); #ifdef UNITY_DOUBLE_VERBOSE diff --git a/test/tests/testunity.c b/test/tests/testunity.c index f922b28..fdfa2a8 100644 --- a/test/tests/testunity.c +++ b/test/tests/testunity.c @@ -4,8 +4,8 @@ [Released under MIT License. Please refer to license.txt for details] ========================================== */ -#include #include "unity.h" +#include #include // Dividing by these constants produces +/- infinity. @@ -2833,7 +2833,7 @@ void testFloatsNotEqualExpectedInf(void) #endif } -void testFloatsNotEqualBothInf(void) +void testFloatsEqualBothInf(void) { #ifdef UNITY_EXCLUDE_FLOAT TEST_IGNORE(); @@ -3187,7 +3187,7 @@ void testNotEqualFloatArraysNaN(void) #endif } -void testNotEqualFloatArraysInf(void) +void testEqualFloatArraysInf(void) { #ifdef UNITY_EXCLUDE_FLOAT TEST_IGNORE(); @@ -3195,9 +3195,7 @@ void testNotEqualFloatArraysInf(void) float p0[] = {1.0f, 1.0f / f_zero, 25.4f, 0.253f}; float p1[] = {1.0f, 1.0f / f_zero, 25.4f, 0.253f}; - EXPECT_ABORT_BEGIN TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END #endif } @@ -3363,7 +3361,7 @@ void testDoublesNotEqualExpectedInf(void) #endif } -void testDoublesNotEqualBothInf(void) +void testDoublesEqualBothInf(void) { #ifdef UNITY_EXCLUDE_DOUBLE TEST_IGNORE(); @@ -3716,7 +3714,7 @@ void testNotEqualDoubleArraysNaN(void) #endif } -void testNotEqualDoubleArraysInf(void) +void testEqualDoubleArraysInf(void) { #ifdef UNITY_EXCLUDE_DOUBLE TEST_IGNORE(); @@ -3724,9 +3722,7 @@ void testNotEqualDoubleArraysInf(void) double p0[] = {1.0, 1.0 / d_zero, 25.4, 0.253}; double p1[] = {1.0, 1.0 / d_zero, 25.4, 0.253}; - EXPECT_ABORT_BEGIN TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); - VERIFY_FAILS_END #endif } From 54aa838c8ad5c6a22d6c1d07ad69dd663876c9eb Mon Sep 17 00:00:00 2001 From: jsalling Date: Sat, 27 Aug 2016 15:27:52 -0500 Subject: [PATCH 3/5] Change the fallback isinf() macro to NOT need f_zero defined Delete old comments from before math.h was the default isinf() method --- src/unity.c | 12 ------------ src/unity_internals.h | 6 ++++-- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/unity.c b/src/unity.c index 17ad7cc..1195858 100644 --- a/src/unity.c +++ b/src/unity.c @@ -52,12 +52,6 @@ static const char UnityStrResultsIgnored[] = " Ignored "; static const char UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; static const char UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; -#ifdef UNITY_FLOAT_NEEDS_ZERO -/* Dividing by these constants produces +/- infinity. - * The rationale is given in UnityAssertFloatIsInf's body. */ -static const _UF f_zero = 0.0f; -#endif - /* compiler-generic print formatting masks */ static const _U_UINT UnitySizeMask[] = { @@ -718,8 +712,6 @@ void UnityAssertFloatSpecial(const _UF actual, switch(style) { - /* To determine Inf / Neg Inf, we compare to an Inf / Neg Inf value we create on the fly - * We are using a variable to hold the zero value because some compilers complain about dividing by zero otherwise */ case UNITY_FLOAT_IS_INF: case UNITY_FLOAT_IS_NOT_INF: is_trait = isinf(actual) & ispos(actual); @@ -729,7 +721,6 @@ void UnityAssertFloatSpecial(const _UF actual, is_trait = isinf(actual) & isneg(actual); break; - /* NaN is the only floating point value that does NOT equal itself. Therefore if Actual == Actual, then it is NOT NaN. */ case UNITY_FLOAT_IS_NAN: case UNITY_FLOAT_IS_NOT_NAN: is_trait = isnan(actual); @@ -864,8 +855,6 @@ void UnityAssertDoubleSpecial(const _UD actual, switch(style) { - /* To determine Inf / Neg Inf, we compare to an Inf / Neg Inf value we create on the fly - * We are using a variable to hold the zero value because some compilers complain about dividing by zero otherwise */ case UNITY_FLOAT_IS_INF: case UNITY_FLOAT_IS_NOT_INF: is_trait = isinf(actual) & ispos(actual); @@ -875,7 +864,6 @@ void UnityAssertDoubleSpecial(const _UD actual, is_trait = isinf(actual) & isneg(actual); break; - /* NaN is the only floating point value that does NOT equal itself. Therefore if Actual == Actual, then it is NOT NaN. */ case UNITY_FLOAT_IS_NAN: case UNITY_FLOAT_IS_NOT_NAN: is_trait = isnan(actual); diff --git a/src/unity_internals.h b/src/unity_internals.h index 032e2a4..b2e296a 100644 --- a/src/unity_internals.h +++ b/src/unity_internals.h @@ -225,11 +225,13 @@ typedef _US64 _U_SINT; typedef UNITY_FLOAT_TYPE _UF; #ifndef isinf -#define isinf(n) (((1.0f / f_zero) == n) ? 1 : 0) || (((-1.0f / f_zero) == n) ? 1 : 0) -#define UNITY_FLOAT_NEEDS_ZERO +/* The value of Inf - Inf is NaN */ +#define isinf(n) (isnan((n) - (n)) && !isnan(n)) #endif #ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ #define isnan(n) ((n != n) ? 1 : 0) #endif From 6d54ec2ff716818e3229fa63a55895a1b5833c96 Mon Sep 17 00:00:00 2001 From: jsalling Date: Sat, 27 Aug 2016 15:34:10 -0500 Subject: [PATCH 4/5] Get rid of conversion warning when using UNITY_FLOAT_VERBOSE with doubles Change the parameter of UnityPrintFloat from float to double (_UD) The call to snprintf uses implict default promotion to a double anyway --- src/unity.c | 2 +- src/unity_internals.h | 44 ++++++++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/unity.c b/src/unity.c index 1195858..32c1880 100644 --- a/src/unity.c +++ b/src/unity.c @@ -257,7 +257,7 @@ void UnityPrintMask(const _U_UINT mask, const _U_UINT number) # endif #endif -void UnityPrintFloat(_UF number) +void UnityPrintFloat(_UD number) { char TempBuffer[UNITY_VERBOSE_NUMBER_MAX_LENGTH + 1]; snprintf(TempBuffer, sizeof(TempBuffer), "%.6f", number); diff --git a/src/unity_internals.h b/src/unity_internals.h index b2e296a..557b6a4 100644 --- a/src/unity_internals.h +++ b/src/unity_internals.h @@ -251,32 +251,38 @@ typedef UNITY_FLOAT_TYPE _UF; /* unlike FLOAT, we DON'T include by default */ #ifndef UNITY_EXCLUDE_DOUBLE -#ifndef UNITY_INCLUDE_DOUBLE -#define UNITY_EXCLUDE_DOUBLE -#endif + #ifndef UNITY_INCLUDE_DOUBLE + #define UNITY_EXCLUDE_DOUBLE + #endif #endif #ifdef UNITY_EXCLUDE_DOUBLE -/* No Floating Point Support */ -#undef UNITY_DOUBLE_PRECISION -#undef UNITY_DOUBLE_TYPE -#undef UNITY_DOUBLE_VERBOSE + /* No Floating Point Support */ + #undef UNITY_DOUBLE_PRECISION + #undef UNITY_DOUBLE_TYPE + #undef UNITY_DOUBLE_VERBOSE -#ifdef UNITY_INCLUDE_DOUBLE -#undef UNITY_INCLUDE_DOUBLE -#endif + #ifdef UNITY_INCLUDE_DOUBLE + #undef UNITY_INCLUDE_DOUBLE + #endif + + #ifdef UNITY_FLOAT_VERBOSE + typedef _UF _UD; + /* For parameter in UnityPrintFloat, double promotion required */ + #endif #else -/* Double Floating Point Support */ -#ifndef UNITY_DOUBLE_PRECISION -#define UNITY_DOUBLE_PRECISION (1e-12f) -#endif -#ifndef UNITY_DOUBLE_TYPE -#define UNITY_DOUBLE_TYPE double -#endif -typedef UNITY_DOUBLE_TYPE _UD; + /* Double Floating Point Support */ + #ifndef UNITY_DOUBLE_PRECISION + #define UNITY_DOUBLE_PRECISION (1e-12f) + #endif + + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_DOUBLE_TYPE _UD; #endif @@ -484,7 +490,7 @@ void UnityPrintNumberUnsigned(const _U_UINT number); void UnityPrintNumberHex(const _U_UINT number, const char nibbles); #ifdef UNITY_FLOAT_VERBOSE -void UnityPrintFloat(const _UF number); +void UnityPrintFloat(const _UD number); #endif /*------------------------------------------------------- From 41c2e5889bdaff55769bf888773beed43a1e57ad Mon Sep 17 00:00:00 2001 From: jsalling Date: Tue, 30 Aug 2016 21:51:38 -0500 Subject: [PATCH 5/5] Bump the version Floats now pass Infinity == Infinity assertions --- release/version.info | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/version.info b/release/version.info index abb84c2..0ba9f86 100644 --- a/release/version.info +++ b/release/version.info @@ -1,2 +1,2 @@ -2.3.2 +2.3.3