mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
Merge pull request #7416 from smlng/sys/fmt/fmt_s32_dfp
fmt: add signed 32 bit fixed point formatting
This commit is contained in:
commit
e5c8652496
@ -35,6 +35,17 @@ ssize_t write(int fildes, const void *buf, size_t nbyte);
|
||||
|
||||
static const char _hex_chars[16] = "0123456789ABCDEF";
|
||||
|
||||
static const uint32_t _tenmap[] = {
|
||||
0,
|
||||
10LU,
|
||||
100LU,
|
||||
1000LU,
|
||||
10000LU,
|
||||
100000LU,
|
||||
1000000LU,
|
||||
10000000LU,
|
||||
};
|
||||
|
||||
static inline int _is_digit(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9');
|
||||
@ -243,16 +254,48 @@ size_t fmt_s16_dfp(char *out, int16_t val, unsigned fp_digits)
|
||||
return pos;
|
||||
}
|
||||
|
||||
static const uint32_t _tenmap[] = {
|
||||
0,
|
||||
10LU,
|
||||
100LU,
|
||||
1000LU,
|
||||
10000LU,
|
||||
100000LU,
|
||||
1000000LU,
|
||||
10000000LU,
|
||||
};
|
||||
size_t fmt_s32_dfp(char *out, int32_t val, unsigned fp_digits)
|
||||
{
|
||||
int32_t absolute, divider;
|
||||
unsigned div_len, len, pos = 0;
|
||||
char tmp[9];
|
||||
|
||||
if (fp_digits > 9) {
|
||||
return 0;
|
||||
}
|
||||
if (fp_digits == 0) {
|
||||
return fmt_s32_dec(out, val);
|
||||
}
|
||||
if (val < 0) {
|
||||
if (out) {
|
||||
out[pos++] = '-';
|
||||
}
|
||||
val = -val;
|
||||
}
|
||||
|
||||
uint32_t e = _tenmap[fp_digits];
|
||||
absolute = (val / e);
|
||||
divider = val - (absolute * e);
|
||||
|
||||
pos += fmt_s32_dec(&out[pos], absolute);
|
||||
|
||||
if (!out) {
|
||||
return pos + 1 + fp_digits; /* abs len + decimal point + divider */
|
||||
}
|
||||
|
||||
out[pos++] = '.';
|
||||
len = pos + fp_digits;
|
||||
div_len = fmt_s32_dec(tmp, divider);
|
||||
|
||||
while (pos < (len - div_len)) {
|
||||
out[pos++] = '0';
|
||||
}
|
||||
for (size_t i = 0; i < div_len; i++) {
|
||||
out[pos++] = tmp[i];
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* this is very probably not the most efficient implementation, as it at least
|
||||
* pulls in floating point math. But it works, and it's always nice to have
|
||||
|
@ -203,6 +203,34 @@ size_t fmt_s16_dec(char *out, int16_t val);
|
||||
*/
|
||||
size_t fmt_s16_dfp(char *out, int16_t val, unsigned fp_digits);
|
||||
|
||||
/**
|
||||
* @brief Convert 32-bit fixed point number to a decimal string
|
||||
*
|
||||
* The input for this function is a signed 32-bit integer holding the fixed
|
||||
* point value as well as an unsigned integer defining the position of the
|
||||
* decimal point, so this value defines the number of decimal digits after the
|
||||
* decimal point.
|
||||
*
|
||||
* Will add a leading "-" if @p val is negative.
|
||||
*
|
||||
* The resulting string will always be patted with zeros after the decimal point.
|
||||
*
|
||||
* For example: if @p val is -314159 and @p fp_digits is 5, the resulting string
|
||||
* will be "-3.14159". For @p val := 16777215 and @p fp_digits := 6 the result
|
||||
* will be "16.777215".
|
||||
*
|
||||
* If @p out is NULL, will only return the number of bytes that would have
|
||||
* been written.
|
||||
*
|
||||
* @param[out] out Pointer to the output buffer, or NULL
|
||||
* @param[in] val Fixed point value
|
||||
* @param[in] fp_digits Number of digits after the decimal point, MUST be <= 9
|
||||
*
|
||||
* @return Length of the resulting string
|
||||
* @return 0 if @p fp_digits is > 9
|
||||
*/
|
||||
size_t fmt_s32_dfp(char *out, int32_t val, unsigned fp_digits);
|
||||
|
||||
/**
|
||||
* @brief Format float to string
|
||||
*
|
||||
|
@ -157,7 +157,7 @@ static void test_fmt_u64_dec_c(void)
|
||||
TEST_ASSERT_EQUAL_STRING("1234567890123456789", (char *) out);
|
||||
}
|
||||
|
||||
static void test_rmt_s16_dec(void)
|
||||
static void test_fmt_s16_dec(void)
|
||||
{
|
||||
char out[7] = "-------";
|
||||
int16_t val;
|
||||
@ -182,7 +182,7 @@ static void test_rmt_s16_dec(void)
|
||||
TEST_ASSERT_EQUAL_STRING("12345", (char *)out);
|
||||
}
|
||||
|
||||
static void test_rmt_s16_dfp(void)
|
||||
static void test_fmt_s16_dfp(void)
|
||||
{
|
||||
char out[8] = "--------";
|
||||
int16_t val;
|
||||
@ -246,6 +246,70 @@ static void test_rmt_s16_dfp(void)
|
||||
TEST_ASSERT_EQUAL_STRING("", (char *)out);
|
||||
}
|
||||
|
||||
static void test_fmt_s32_dfp(void)
|
||||
{
|
||||
char out[13] = "-------------";
|
||||
int32_t val;
|
||||
unsigned fpp;
|
||||
size_t len;
|
||||
|
||||
val = 0;
|
||||
fpp = 8;
|
||||
len = fmt_s32_dfp(out, val, fpp);
|
||||
out[len] = '\0';
|
||||
TEST_ASSERT_EQUAL_INT(10, len);
|
||||
TEST_ASSERT_EQUAL_STRING("0.00000000", (char *)out);
|
||||
|
||||
val = 123456789;
|
||||
fpp = 7;
|
||||
len = fmt_s32_dfp(out, val, fpp);
|
||||
out[len] = '\0';
|
||||
TEST_ASSERT_EQUAL_INT(10, len);
|
||||
TEST_ASSERT_EQUAL_STRING("12.3456789", (char *)out);
|
||||
|
||||
val = 120030;
|
||||
fpp = 3;
|
||||
len = fmt_s32_dfp(out, val, fpp);
|
||||
out[len] = '\0';
|
||||
TEST_ASSERT_EQUAL_INT(7, len);
|
||||
TEST_ASSERT_EQUAL_STRING("120.030", (char *)out);
|
||||
|
||||
val = -314159;
|
||||
fpp = 5;
|
||||
len = fmt_s32_dfp(out, val, fpp);
|
||||
out[len] = '\0';
|
||||
TEST_ASSERT_EQUAL_INT(8, len);
|
||||
TEST_ASSERT_EQUAL_STRING("-3.14159", (char *)out);
|
||||
|
||||
val = -23;
|
||||
fpp = 9;
|
||||
len = fmt_s32_dfp(out, val, fpp);
|
||||
out[len] = '\0';
|
||||
TEST_ASSERT_EQUAL_INT(12, len);
|
||||
TEST_ASSERT_EQUAL_STRING("-0.000000023", (char *)out);
|
||||
|
||||
val = 50;
|
||||
fpp = 6;
|
||||
len = fmt_s32_dfp(out, val, fpp);
|
||||
out[len] = '\0';
|
||||
TEST_ASSERT_EQUAL_INT(8, len);
|
||||
TEST_ASSERT_EQUAL_STRING("0.000050", (char *)out);
|
||||
|
||||
val = -123456789;
|
||||
fpp = 0;
|
||||
len = fmt_s32_dfp(out, val, fpp);
|
||||
out[len] = '\0';
|
||||
TEST_ASSERT_EQUAL_INT(10, len);
|
||||
TEST_ASSERT_EQUAL_STRING("-123456789", (char *)out);
|
||||
|
||||
val = 31987;
|
||||
fpp = 10;
|
||||
len = fmt_s32_dfp(out, val, fpp);
|
||||
out[len] = '\0';
|
||||
TEST_ASSERT_EQUAL_INT(0, len);
|
||||
TEST_ASSERT_EQUAL_STRING("", (char *)out);
|
||||
}
|
||||
|
||||
static void test_fmt_strlen(void)
|
||||
{
|
||||
const char *empty_str = "";
|
||||
@ -321,8 +385,9 @@ Test *tests_fmt_tests(void)
|
||||
new_TestFixture(test_fmt_u64_dec_c),
|
||||
new_TestFixture(test_fmt_u16_dec),
|
||||
new_TestFixture(test_fmt_s32_dec),
|
||||
new_TestFixture(test_rmt_s16_dec),
|
||||
new_TestFixture(test_rmt_s16_dfp),
|
||||
new_TestFixture(test_fmt_s16_dec),
|
||||
new_TestFixture(test_fmt_s16_dfp),
|
||||
new_TestFixture(test_fmt_s32_dfp),
|
||||
new_TestFixture(test_fmt_strlen),
|
||||
new_TestFixture(test_fmt_str),
|
||||
new_TestFixture(test_scn_u32_dec),
|
||||
|
Loading…
Reference in New Issue
Block a user