From a8bd7b5af2f83ba42afcd43c377fe36d437bff67 Mon Sep 17 00:00:00 2001 From: Mark VanderVoord Date: Mon, 21 Jul 2014 14:38:25 -0400 Subject: [PATCH] continue to streamline floating point support --- src/unity.c | 103 ++++++++++++------------------------------ src/unity_internals.h | 35 +++++++++++--- 2 files changed, 59 insertions(+), 79 deletions(-) diff --git a/src/unity.c b/src/unity.c index b0e409a..affb018 100644 --- a/src/unity.c +++ b/src/unity.c @@ -614,95 +614,52 @@ void UnityAssertFloatsWithin(const _UF delta, } //----------------------------------------------- -void UnityAssertFloatIsInf(const _UF actual, - const _U_SINT should_be, - const char* msg, - const UNITY_LINE_TYPE lineNumber) +void UnityAssertFloatSpecial(const _UF actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_STYLE_T style) { UNITY_SKIP_EXECUTION; - // In Microsoft Visual C++ Express Edition 2008, - // if ((1.0f / f_zero) != actual) - // produces - // error C2124: divide or mod by zero - // As a workaround, place 0 into a variable. - _U_SINT is_inf = ((1.0f / f_zero) == actual) ? 1 : 0; - if (is_inf != should_be) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrExpected); - if (!should_be) - UnityPrint(UnityStrNot); - UnityPrint(UnityStrInf); - UnityPrint(UnityStrWas); -#ifdef UNITY_FLOAT_VERBOSE - UnityPrintFloat(actual); -#else - if (should_be) - UnityPrint(UnityStrNot); - UnityPrint(UnityStrInf); -#endif - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -//----------------------------------------------- -void UnityAssertFloatIsNegInf(const _UF actual, - const _U_SINT should_be, - const char* msg, - const UNITY_LINE_TYPE lineNumber) -{ - UNITY_SKIP_EXECUTION; + const char* trait_names[] = { UnityStrInf, UnityStrNegInf, UnityStrNaN }; + _U_SINT should_be_trait = ((_U_SINT)style & 1); + _U_SINT is_trait = !should_be_trait; + _U_SINT trait_index = style >> 1; - // The rationale for not using 1.0f/0.0f is given in UnityAssertFloatIsInf's body. - _U_SINT is_inf = ((-1.0f / f_zero) == actual) ? 1 : 0; - if (is_inf != should_be) + switch(style) { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrExpected); - if (!should_be) - UnityPrint(UnityStrNot); - UnityPrint(UnityStrNegInf); - UnityPrint(UnityStrWas); -#ifdef UNITY_FLOAT_VERBOSE - UnityPrintFloat(actual); -#else - if (should_be) - UnityPrint(UnityStrNot); - UnityPrint(UnityStrNegInf); -#endif - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} + //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 = ((1.0f / f_zero) == actual) ? 1 : 0; + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = ((-1.0f / f_zero) == actual) ? 1 : 0; + break; -//----------------------------------------------- -void UnityAssertFloatIsNaN(const _UF actual, - const _U_SINT should_be, - const char* msg, - const UNITY_LINE_TYPE lineNumber) -{ - UNITY_SKIP_EXECUTION; + //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 = (actual == actual) ? 0 : 1; + break; + } - //NaN is the only floating point value that does NOT - //equal itself. Therefore if Actual == Actual, then it - //is NOT NaN. - _U_SINT is_nan = (actual == actual) ? 0 : 1; - if (is_nan != should_be) + if (is_trait != should_be_trait) { UnityTestResultsFailBegin(lineNumber); UnityPrint(UnityStrExpected); - if (!should_be) + if (!should_be_trait) UnityPrint(UnityStrNot); - UnityPrint(UnityStrNaN); + UnityPrint(trait_names[trait_index]); UnityPrint(UnityStrWas); #ifdef UNITY_FLOAT_VERBOSE UnityPrintFloat(actual); #else - if (should_be) + if (should_be_trait) UnityPrint(UnityStrNot); - UnityPrint(UnityStrNaN); + UnityPrint(trait_names[trait_index]); #endif UnityAddMsgIfSpecified(msg); UNITY_FAIL_AND_BAIL; diff --git a/src/unity_internals.h b/src/unity_internals.h index 7224ce8..839e14e 100644 --- a/src/unity_internals.h +++ b/src/unity_internals.h @@ -329,6 +329,18 @@ typedef enum UNITY_DISPLAY_STYLE_UNKNOWN } UNITY_DISPLAY_STYLE_T; +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum _UNITY_FLOAT_STYLE_T +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, +} UNITY_FLOAT_STYLE_T; +#endif + struct _Unity { const char* TestFile; @@ -437,6 +449,11 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const _UF* expected, const char* msg, const UNITY_LINE_TYPE lineNumber); +void UnityAssertFloatSpecial(const _UF actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_STYLE_T style); + void UnityAssertFloatIsInf(const _UF actual, const _U_SINT should_be, const char* msg, @@ -552,16 +569,19 @@ void UnityAssertDoubleIsNaN(const _UD actual, #define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Floating Point Disabled") #define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Floating Point Disabled") #define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Floating Point Disabled") +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Floating Point Disabled") +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Floating Point Disabled") +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Floating Point Disabled") #else #define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((_UF)(delta), (_UF)(expected), (_UF)(actual), (message), (UNITY_LINE_TYPE)line) #define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((_UF)(expected) * (_UF)UNITY_FLOAT_PRECISION, (_UF)expected, (_UF)actual, (UNITY_LINE_TYPE)line, message) #define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((_UF*)(expected), (_UF*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)line) -#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatIsInf((_UF)(actual), 1, (message), (UNITY_LINE_TYPE)line) -#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatIsNegInf((_UF)(actual), 1, (message), (UNITY_LINE_TYPE)line) -#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatIsNaN((_UF)(actual), 1, (message), (UNITY_LINE_TYPE)line) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatIsInf((_UF)(actual), 0, (message), (UNITY_LINE_TYPE)line) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatIsNegInf((_UF)(actual), 0, (message), (UNITY_LINE_TYPE)line) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatIsNaN((_UF)(actual), 0, (message), (UNITY_LINE_TYPE)line) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_FLOAT_IS_NOT_NAN) #endif #ifdef UNITY_EXCLUDE_DOUBLE @@ -571,6 +591,9 @@ void UnityAssertDoubleIsNaN(const _UD actual, #define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Double Precision Disabled") #define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Double Precision Disabled") #define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Double Precision Disabled") +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Double Precision Disabled") +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Double Precision Disabled") +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Double Precision Disabled") #else #define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((_UD)(delta), (_UD)(expected), (_UD)(actual), (message), (UNITY_LINE_TYPE)line) #define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((_UD)(expected) * (_UD)UNITY_DOUBLE_PRECISION, (_UD)expected, (_UD)actual, (UNITY_LINE_TYPE)line, message) -- GitLab