Skip to content

Commit

Permalink
lib: sfloat: Fix conversion to special values
Browse files Browse the repository at this point in the history
The conversion function returns special values
even when the input is valid number.
This commit makes sure that no special value
is returned if input is valid.

Signed-off-by: Dominik Kilian <[email protected]>
  • Loading branch information
doki-nordic authored and nordicjm committed Jan 24, 2023
1 parent 8ce1a91 commit 855cc65
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
12 changes: 12 additions & 0 deletions lib/sfloat/sfloat.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
#define SFLOAT_EXP_BIT_POS (12)
/* Exponent mask in the SFLOAT encoding. */
#define SFLOAT_EXP_MASK (0xF000)
/* Value of the exponent that is in SFLOAT special values. */
#define SFLOAT_SPECIAL_EXP 0
/* Minimum value of mantissa in SFLOAT special values. */
#define SFLOAT_SPECIAL_MANTISSA_MIN 2046

/* Size in bits of the float sign encoding. */
#define FLOAT_SIGN_BIT_SIZE 1
Expand All @@ -46,6 +50,8 @@

/* Helper macro for getting absolute value. */
#define ABS(a) ((a < 0) ? (-a) : (a))
/* Helper macro for dividing two integers with rounding upwards (ceiling). */
#define DIV_AND_CEIL(a, b) (((a) + ((b) - 1)) / (b))

/* Float type should use binary32 notation from the IEEE 754-2008 specification. */
BUILD_ASSERT(sizeof(float) == sizeof(uint32_t));
Expand Down Expand Up @@ -140,6 +146,12 @@ static struct sfloat_desc sfloat_desc_from_float(float float_num)
sfloat.exponent = (~sfloat.exponent & 0x0F) + 1;
}

/* Make sure that special sfloat values are not returned */
if ((sfloat.exponent == SFLOAT_SPECIAL_EXP) && (mantissa >= SFLOAT_SPECIAL_MANTISSA_MIN)) {
sfloat.exponent++;
mantissa = DIV_AND_CEIL(SFLOAT_SPECIAL_MANTISSA_MIN, 10);
}

sfloat.mantissa = mantissa & SFLOAT_MANTISSA_MASK;
if (float_enc.sign) {
sfloat.mantissa = (~sfloat.mantissa & SFLOAT_MANTISSA_MASK) + 1;
Expand Down
30 changes: 21 additions & 9 deletions tests/lib/sfloat/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,26 @@ ZTEST(sfloat_suite, test_sfloat_from_float)
{-20479000000.0, {0x7800}}, /* - 10^(7) * 2048 = -20480000000.00000 */

/* Mantisssa - edge cases */
{2047.0, {0x07FF}}, /* 10^(0) * 2047 = 2047.00000 */
{2048.0, {0x10CD}}, /* 10^(1) * 205 = 2050.00000 */
{-2047.0, {0x0801}}, /* - 10^(0) * 2047 = -2047.00000 */
{-2048.0, {0x0800}}, /* - 10^(0) * 2048 = -2048.00000 */
{2047.5, {0x10CD}}, /* 10^(1) * 205 = 2050.00000 */
{2048.5, {0x10CD}}, /* 10^(1) * 205 = 2050.00000 */
{-2047.5, {0x0800}}, /* - 10^(0) * 2048 = -2048.00000 */
{-2048.5, {0x1F33}}, /* - 10^(1) * 205 = -2050.00000 */
{20470.0, {0x17FF}}, /* 10^(1) * 2047 = 20470.0000 */
{20480.0, {0x20CD}}, /* 10^(2) * 205 = 20500.0000 */
{-20470.0, {0x1801}}, /* - 10^(1) * 2047 = -20470.0000 */
{-20480.0, {0x1800}}, /* - 10^(1) * 2048 = -20480.0000 */
{20475.0, {0x20CD}}, /* 10^(2) * 205 = 20500.0000 */
{20485.0, {0x20CD}}, /* 10^(2) * 205 = 20500.0000 */
{-20475.0, {0x1800}}, /* - 10^(1) * 2048 = -20480.0000 */
{-20485.0, {0x2F33}}, /* - 10^(2) * 205 = -20500.0000 */

/* Avoiding special values */
{2045.0, {0x07FD}}, /* 10^(0) * 2045 = 2045.0000 */
{2046.0, {0x10CD}}, /* 10^(1) * 205 = 2050.0000 (0x07FE is special) */
{2047.0, {0x10CD}}, /* 10^(1) * 205 = 2050.0000 (0x07FF is special) */
{2048.0, {0x10CD}}, /* 10^(1) * 205 = 2050.0000 (0x07FF is special) */
{2049.0, {0x10CD}}, /* 10^(1) * 205 = 2050.0000 */
{-2045.0, {0x0803}}, /* - 10^(0) * 2045 = 2045.0000 */
{-2046.0, {0x1F33}}, /* - 10^(1) * 205 = 2050.0000 (0x0802 is special) */
{-2047.0, {0x1F33}}, /* - 10^(1) * 205 = 2050.0000 (0x0801 is special) */
{-2048.0, {0x1F33}}, /* - 10^(1) * 205 = 2050.0000 (0x0800 is special) */
{-2049.0, {0x1F33}}, /* - 10^(1) * 205 = 2050.0000 */

/* Special values */
{(0.0 / 0.0), {SFLOAT_NAN}}, /* SFLOAT NaN */
Expand All @@ -95,7 +107,7 @@ ZTEST(sfloat_suite, test_sfloat_from_float)
float in_float = test_vector[i].in_float;

res = sfloat_from_float(in_float);
zassume_true(res.val == out_sfloat.val,
zassert_true(res.val == out_sfloat.val,
"comparison failed for the sample[%d] equal to %f: 0x%04X != 0x%04X",
i, in_float, res.val, out_sfloat.val);
}
Expand Down

0 comments on commit 855cc65

Please sign in to comment.