diff --git a/src/unity.c b/src/unity.c index 483e484..c755ebb 100644 --- a/src/unity.c +++ b/src/unity.c @@ -250,24 +250,94 @@ void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) } /*-----------------------------------------------*/ -#ifdef UNITY_FLOAT_VERBOSE -#include - -#ifndef UNITY_VERBOSE_NUMBER_MAX_LENGTH -# ifdef UNITY_DOUBLE_VERBOSE -# define UNITY_VERBOSE_NUMBER_MAX_LENGTH 317 -# else -# define UNITY_VERBOSE_NUMBER_MAX_LENGTH 47 -# endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +static void UnityPrintDecimalAndNumberWithLeadingZeros(UNITY_INT32 fraction_part, UNITY_INT32 divisor) +{ + UNITY_OUTPUT_CHAR('.'); + while (divisor > 0) + { + UNITY_OUTPUT_CHAR('0' + fraction_part / divisor); + fraction_part %= divisor; + divisor /= 10; + if (fraction_part == 0) break; /* Truncate trailing 0's */ + } +} +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO +/* If rounds up && remainder 0.5 && result odd && below cutoff for double precision issues */ + #define ROUND_TIES_TO_EVEN(orig, num_int, num) \ + if (num_int > (num) && (num) - (num_int-1) <= 0.5 && (num_int & 1) == 1 && orig < 1e22) \ + num_int -= 1 /* => a tie to round down to even */ +#else + #define ROUND_TIES_TO_EVEN(orig, num_int, num) /* Remove macro */ #endif +/* Printing floating point numbers is hard. Some goals of this implementation: works for embedded + * systems, floats or doubles, and has a reasonable format. The key paper in this area, + * 'How to Print Floating-Point Numbers Accurately' by Steele & White, shows an approximation by + * scaling called Dragon 2. This code uses a similar idea. The other core algorithm uses casts and + * floating subtraction to give exact remainders after the decimal, to be scaled into an integer. + * Extra trailing 0's are excluded. The output defaults to rounding to nearest, ties to even. You + * can enable rounding ties away from zero. Note: UNITY_DOUBLE param can typedef to float or double + + * The old version required compiling in snprintf. For reference, with a similar format as now: + * char buf[19]; + * if (number > 4294967296.0 || -number > 4294967296.0) snprintf(buf, sizeof buf, "%.8e", number); + * else snprintf(buf, sizeof buf, "%.6f", number); + * UnityPrint(buf); + */ void UnityPrintFloat(UNITY_DOUBLE number) { - char TempBuffer[UNITY_VERBOSE_NUMBER_MAX_LENGTH + 1]; - snprintf(TempBuffer, sizeof(TempBuffer), "%.6f", number); - UnityPrint(TempBuffer); + if (number < 0) + { + UNITY_OUTPUT_CHAR('-'); + number = -number; + } + + if (isnan(number)) UnityPrint(UnityStrNaN); + else if (isinf(number)) UnityPrintLen(UnityStrInf, 3); + else if (number <= 0.0000005 && number > 0) UnityPrint("0.000000..."); /* Small number */ + else if (number < 4294967295.9999995) /* Rounded result fits in 32 bits, "%.6f" format */ + { + const UNITY_INT32 divisor = 1000000/10; + UNITY_UINT32 integer_part = (UNITY_UINT32)number; + UNITY_INT32 fraction_part = (UNITY_INT32)((number - (UNITY_DOUBLE)integer_part)*1000000.0 + 0.5); + /* Double precision calculation gives best performance for six rounded decimal places */ + ROUND_TIES_TO_EVEN(number, fraction_part, (number - (UNITY_DOUBLE)integer_part)*1000000.0); + + if (fraction_part == 1000000) /* Carry across the decimal point */ + { + fraction_part = 0; + integer_part += 1; + } + + UnityPrintNumberUnsigned(integer_part); + UnityPrintDecimalAndNumberWithLeadingZeros(fraction_part, divisor); + } + else /* Number is larger, use exponential format of 9 digits, "%.8e" */ + { + const UNITY_INT32 divisor = 1000000000/10; + UNITY_INT32 integer_part; + UNITY_DOUBLE_TYPE divide = 10.0; + int exponent = 9; + + while (number / divide >= 1000000000.0 - 0.5) + { + divide *= 10; + exponent++; + } + integer_part = (UNITY_INT32)(number / divide + 0.5); + /* Double precision calculation required for float, to produce 9 rounded digits */ + ROUND_TIES_TO_EVEN(number, integer_part, number / divide); + + UNITY_OUTPUT_CHAR('0' + integer_part / divisor); + UnityPrintDecimalAndNumberWithLeadingZeros(integer_part % divisor, divisor / 10); + UNITY_OUTPUT_CHAR('e'); + UNITY_OUTPUT_CHAR('+'); + if (exponent < 10) UNITY_OUTPUT_CHAR('0'); + UnityPrintNumber(exponent); + } } -#endif +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ /*-----------------------------------------------*/ @@ -631,6 +701,19 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, #define UNITY_NAN_CHECK 0 #endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + do { \ + UnityPrint(UnityStrExpected); \ + UnityPrintFloat(expected); \ + UnityPrint(UnityStrWas); \ + UnityPrintFloat(actual); \ + } while(0) +#else + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + UnityPrint(UnityStrDelta) +#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ + #ifndef UNITY_EXCLUDE_FLOAT static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) { @@ -665,14 +748,7 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, UnityTestResultsFailBegin(lineNumber); UnityPrint(UnityStrElement); UnityPrintNumberUnsigned(num_elements - elements - 1); -#ifdef UNITY_FLOAT_VERBOSE - UnityPrint(UnityStrExpected); - UnityPrintFloat(*ptr_expected); - UnityPrint(UnityStrWas); - UnityPrintFloat(*ptr_actual); -#else - UnityPrint(UnityStrDelta); -#endif + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); UnityAddMsgIfSpecified(msg); UNITY_FAIL_AND_BAIL; } @@ -694,14 +770,7 @@ void UnityAssertFloatsWithin(const UNITY_FLOAT delta, if (!UnityFloatsWithin(delta, expected, actual)) { UnityTestResultsFailBegin(lineNumber); -#ifdef UNITY_FLOAT_VERBOSE - UnityPrint(UnityStrExpected); - UnityPrintFloat(expected); - UnityPrint(UnityStrWas); - UnityPrintFloat(actual); -#else - UnityPrint(UnityStrDelta); -#endif + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); UnityAddMsgIfSpecified(msg); UNITY_FAIL_AND_BAIL; } @@ -759,7 +828,7 @@ void UnityAssertFloatSpecial(const UNITY_FLOAT actual, UnityPrint(UnityStrNot); UnityPrint(trait_names[trait_index]); UnityPrint(UnityStrWas); -#ifdef UNITY_FLOAT_VERBOSE +#ifndef UNITY_EXCLUDE_FLOAT_PRINT UnityPrintFloat(actual); #else if (should_be_trait) @@ -808,14 +877,7 @@ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expecte UnityTestResultsFailBegin(lineNumber); UnityPrint(UnityStrElement); UnityPrintNumberUnsigned(num_elements - elements - 1); -#ifdef UNITY_DOUBLE_VERBOSE - UnityPrint(UnityStrExpected); - UnityPrintFloat((float)(*ptr_expected)); - UnityPrint(UnityStrWas); - UnityPrintFloat((float)(*ptr_actual)); -#else - UnityPrint(UnityStrDelta); -#endif + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); UnityAddMsgIfSpecified(msg); UNITY_FAIL_AND_BAIL; } @@ -836,14 +898,7 @@ void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, if (!UnityDoublesWithin(delta, expected, actual)) { UnityTestResultsFailBegin(lineNumber); -#ifdef UNITY_DOUBLE_VERBOSE - UnityPrint(UnityStrExpected); - UnityPrintFloat((float)expected); - UnityPrint(UnityStrWas); - UnityPrintFloat((float)actual); -#else - UnityPrint(UnityStrDelta); -#endif + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); UnityAddMsgIfSpecified(msg); UNITY_FAIL_AND_BAIL; } @@ -902,7 +957,7 @@ void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, UnityPrint(UnityStrNot); UnityPrint(trait_names[trait_index]); UnityPrint(UnityStrWas); -#ifdef UNITY_DOUBLE_VERBOSE +#ifndef UNITY_EXCLUDE_FLOAT_PRINT UnityPrintFloat(actual); #else if (should_be_trait) diff --git a/src/unity.h b/src/unity.h index df59683..a544bb2 100644 --- a/src/unity.h +++ b/src/unity.h @@ -37,13 +37,11 @@ void tearDown(void); * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats - * - define UNITY_FLOAT_VERBOSE to print floating point values in errors (uses sprintf) * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE * - define UNITY_DOUBLE_TYPE to specify something other than double - * - define UNITY_DOUBLE_VERBOSE to print floating point values in errors (uses sprintf) - * - define UNITY_VERBOSE_NUMBER_MAX_LENGTH to change maximum length of printed numbers (used by sprintf) + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors * Output * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired diff --git a/src/unity_internals.h b/src/unity_internals.h index a49be92..34f0bd3 100644 --- a/src/unity_internals.h +++ b/src/unity_internals.h @@ -171,7 +171,6 @@ #undef UNITY_INCLUDE_FLOAT #undef UNITY_FLOAT_PRECISION #undef UNITY_FLOAT_TYPE -#undef UNITY_FLOAT_VERBOSE #else @@ -225,15 +224,19 @@ typedef UNITY_FLOAT_TYPE UNITY_FLOAT; /* 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_FLOAT_VERBOSE - typedef UNITY_FLOAT UNITY_DOUBLE; - /* For parameter in UnityPrintFloat, double promotion required */ + #ifdef UNITY_EXCLUDE_FLOAT + #define UNITY_EXCLUDE_FLOAT_PRINT + #else + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_FLOAT UNITY_DOUBLE; + /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ #endif #else @@ -250,12 +253,6 @@ typedef UNITY_FLOAT_TYPE UNITY_FLOAT; #endif -#ifdef UNITY_DOUBLE_VERBOSE -#ifndef UNITY_FLOAT_VERBOSE -#define UNITY_FLOAT_VERBOSE -#endif -#endif - /*------------------------------------------------------- * Output Method: stdout (DEFAULT) *-------------------------------------------------------*/ @@ -443,7 +440,7 @@ void UnityPrintNumber(const UNITY_INT number); void UnityPrintNumberUnsigned(const UNITY_UINT number); void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles); -#ifdef UNITY_FLOAT_VERBOSE +#ifndef UNITY_EXCLUDE_FLOAT_PRINT void UnityPrintFloat(const UNITY_DOUBLE number); #endif diff --git a/test/tests/testunity.c b/test/tests/testunity.c index 36465b7..08c621a 100644 --- a/test/tests/testunity.c +++ b/test/tests/testunity.c @@ -5,8 +5,8 @@ ========================================== */ #include "unity.h" -#include #include +#include // Dividing by these constants produces +/- infinity. // The rationale is given in UnityAssertFloatIsInf's body. @@ -59,19 +59,20 @@ static int SetToOneMeanWeAlreadyCheckedThisGuy; void setUp(void) { - SetToOneToFailInTearDown = 0; - SetToOneMeanWeAlreadyCheckedThisGuy = 0; + SetToOneToFailInTearDown = 0; + SetToOneMeanWeAlreadyCheckedThisGuy = 0; } void tearDown(void) { - if (SetToOneToFailInTearDown == 1) - TEST_FAIL_MESSAGE("<= Failed in tearDown"); - if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) - { - UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); - UNITY_OUTPUT_CHAR('\n'); - } + endPutcharSpy(); /* Stop suppressing test output */ + if (SetToOneToFailInTearDown == 1) + TEST_FAIL_MESSAGE("<= Failed in tearDown"); + if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) + { + UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); + UNITY_OUTPUT_CHAR('\n'); + } } void testUnitySizeInitializationReminder(void) @@ -2265,7 +2266,7 @@ void putcharSpy(int c) if (indexSpyBuffer < SPY_BUFFER_MAX - 1) putcharSpyBuffer[indexSpyBuffer++] = (char)c; } else - c = putchar(c); + putchar((char)c); #endif } @@ -2284,10 +2285,14 @@ void testFailureCountIncrementsAndIsReturnedAtEnd(void) void testCstringsEscapeSequence(void) { +#ifndef USING_OUTPUT_SPY + TEST_IGNORE(); +#else startPutcharSpy(); UnityPrint("\x16\x10"); endPutcharSpy(); TEST_ASSERT_EQUAL_STRING("\\x16\\x10", getBufferPutcharSpy()); +#endif } #define TEST_ASSERT_EQUAL_PRINT_NUMBERS(expected, actual) { \ @@ -3227,6 +3232,180 @@ void testNotEqualFloatArraysLengthZero(void) #endif } +#define TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, actual) { \ + startPutcharSpy(); UnityPrintFloat((actual)); endPutcharSpy(); \ + TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \ + } + +void testFloatPrinting(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0", 0.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.000000...", 0.000000499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.000001", 0.00000050000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.100469499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0", 0.9999995f); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0", 1.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.25", 1.25f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("7.999999", 7.999999f); /*Not rounding*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.000002", 16.000002f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.000004", 16.000004f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.000006", 16.000006f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4294967040.0", 4294967040.0f); /*Last full print integer*/ + + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0", -0.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.000000...",-0.000000499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.000001", -0.00000050000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.100469499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.0", -0.9999995f); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.0", -1.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.25", -1.25f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.999999", -7.999999f); /*Not rounding*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.000002", -16.000002f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.000004", -16.000004f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.000006", -16.000006f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4294967040.0",-4294967040.0f); /*Last full print integer*/ + + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967296.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5.0e+09", 5000000000.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("8.0e+09", 8.0e+09f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("8.3099991e+09", 8309999104.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 1.0e+10f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 10000000000.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00005499e+10", 1.000055e+10f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.10000006e+38", 1.10000005e+38f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.63529943e+10", 1.63529943e+10f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("3.40282347e+38", 3.40282346638e38f); + + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.0e+10", -1.0e+10f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.40282347e+38",-3.40282346638e38f); +#endif +} + +void testFloatPrintingRoundTiesToEven(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + #ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.007813", 0.0078125f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.976563", 0.9765625f); + #else /* Default to Round ties to even */ + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.007182", 0.0071825f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.976562", 0.9765625f); + #endif +#endif +} + +void testFloatPrintingInfinityAndNaN(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_PRINT_FLOATING("Inf", 1.0f / f_zero); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-Inf", -1.0f / f_zero); + + TEST_ASSERT_EQUAL_PRINT_FLOATING("NaN", 0.0f / f_zero); +#endif +} + +#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY) +static void AllFloatPrinting_LessThan32Bits(void) +{ + char expected[18]; + union { float f_value; int32_t int_value; } u; + /* Float representations are laid out in integer order, walk up the list */ + for (u.f_value = 0.00000050000005f; u.f_value <= 4294967040.0f; u.int_value += 1) + { + startPutcharSpy(); + + UnityPrintFloat(u.f_value); /*1.5x as fast as sprintf 5e-7f - 0.01f, 20s vs 30s*/ + int len = sprintf(expected, "%.6f", u.f_value); + + while (expected[len - 1] == '0' && expected[len - 2] != '.') { len--; } + expected[len] = '\0'; /* delete trailing 0's */ + + if (strcmp(expected, getBufferPutcharSpy()) != 0) + { + double six_digits = ((double)u.f_value - (uint32_t)u.f_value)*1000000.0; + /* Not a tie (remainder != 0.5) => Can't explain the different strings */ + if (six_digits - (uint32_t)six_digits != 0.5) + { + /* Fail with diagnostic printing */ + TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, u.f_value); + } + } + } +} + +/* Compared to perfect, floats are occasionally rounded wrong. It doesn't affect + * correctness, though. Two examples (of 13 total found during testing): + * Printed: 6.19256349e+20, Exact: 619256348499999981568.0f <= Eliminated by ROUND_TIES_TO_EVEN + * Printed: 2.19012272e+35, Exact: 219012271499999993621766990196637696.0f */ +static void AllFloatPrinting_Larger(const float start, const float end) +{ + unsigned int wrong = 0; + char expected[18]; + union { float f_value; int32_t int_value; } u; + for (u.f_value = start; u.f_value <= end; u.int_value += 1) + { + startPutcharSpy(); + + UnityPrintFloat(u.f_value); /*Twice as fast as sprintf 2**32-1e12, 10s vs 21s*/ + sprintf(expected, "%.8e", u.f_value); + + int len = 11 - 1; /* 11th char is 'e' in exponential format */ + while (expected[len - 1] == '0' && expected[len - 2] != '.') { len --; } + if (expected[14] != '\0') memmove(&expected[12], &expected[13], 3); /* Two char exponent */ + memmove(&expected[len], &expected[11 - 1], sizeof "e+09"); /* 5 char length */ + + if (strcmp(expected, getBufferPutcharSpy()) != 0) + { + wrong++; + /* endPutcharSpy(); UnityPrint("Expected "); UnityPrint(expected); + UnityPrint(" Was "); UnityPrint(getBufferPutcharSpy()); UNITY_OUTPUT_CHAR('\n'); */ + + if (wrong > 10 || (wrong > 3 && end <= 1e25f)) + TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, u.f_value); + /* Empirical values from the current routine, don't be worse when making changes */ + } + } +} +#endif + +/* Exhaustive testing of all float values we differentiate when printing. Doubles + * are not explored here -- too many. These tests confirm that the routine works + * for all floats > 5e-7, positives only. Off by default due to test time. + * Compares Unity's routine to your sprintf() C lib, tested to pass on 3 platforms. + * Part1 takes a long time, around 3 minutes compiled with -O2 + * Runs through all floats from 0.000001 - 2**32, ~300 million values */ +void testAllFloatPrintingPart1_LessThan32Bits(void) +{ +#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY) + AllFloatPrinting_LessThan32Bits(); +#else + TEST_IGNORE(); /* Ignore one of three */ +#endif +} + +/* Test takes a long time, around 3.5 minutes compiled with -O2, try ~500 million values */ +void testAllFloatPrintingPart2_Larger(void) +{ +#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY) + AllFloatPrinting_Larger(4294967296.0f, 1e25f); +#endif +} + +/* Test takes a long time, around 3.5 minutes compiled with -O2, try ~500 million values */ +void testAllFloatPrintingPart3_LargerStill(void) +{ +#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY) + AllFloatPrinting_Larger(1e25f, 3.40282347e+38f); +#endif +} + // ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DOUBLE SUPPORT ================== void testDoublesWithinDelta(void) @@ -3750,6 +3929,55 @@ void testNotEqualDoubleArraysLengthZero(void) #endif } +void testDoublePrinting(void) +{ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.10046949999999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4294967295.999999", 4294967295.999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967295.9999995); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967296.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 9999999995.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719925e+15", 9007199254740990.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("7.0e+100", 7.0e+100); + TEST_ASSERT_EQUAL_PRINT_FLOATING("3.0e+200", 3.0e+200); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.23456789e+300", 9.23456789e+300); + + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.10046949999999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4294967295.999999", -4294967295.999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.2949673e+09", -4294967295.9999995); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.0e+100", -7.0e+100); +#endif +} + +void testDoublePrintingRoundTiesToEven(void) +{ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + #ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00000001e+10", 10000000050.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719925e+15", 9007199245000000.0); + #else /* Default to Round ties to even */ + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 10000000050.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719924e+15", 9007199245000000.0); + #endif +#endif +} + +void testDoublePrintingInfinityAndNaN(void) +{ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_PRINT_FLOATING("Inf", 1.0 / d_zero); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-Inf", -1.0 / d_zero); + + TEST_ASSERT_EQUAL_PRINT_FLOATING("NaN", 0.0 / d_zero); +#endif +} + // ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DETAIL SUPPORT ================== void testThatDetailsCanBeHandleOneDetail(void)