mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
Merge pull request #17106 from kaspar030/fmt_s32_dfp_tenmap_independance
sys/fmt: make fmt_s32_dfp() string based
This commit is contained in:
commit
e0b8238e79
@ -308,61 +308,62 @@ size_t fmt_s16_dec(char *out, int16_t val)
|
|||||||
return fmt_s32_dec(out, val);
|
return fmt_s32_dec(out, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t fmt_s16_dfp(char *out, int16_t val, int fp_digits)
|
size_t fmt_s16_dfp(char *out, int16_t val, int scale)
|
||||||
{
|
{
|
||||||
return fmt_s32_dfp(out, val, fp_digits);
|
return fmt_s32_dfp(out, val, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t fmt_s32_dfp(char *out, int32_t val, int fp_digits)
|
size_t fmt_s32_dfp(char *out, int32_t val, int scale)
|
||||||
{
|
{
|
||||||
assert(fp_digits > -(int)TENMAP_SIZE);
|
unsigned pos = 0;
|
||||||
|
|
||||||
unsigned pos = 0;
|
if (scale == 0) {
|
||||||
|
|
||||||
if (fp_digits == 0) {
|
|
||||||
pos = fmt_s32_dec(out, val);
|
pos = fmt_s32_dec(out, val);
|
||||||
}
|
}
|
||||||
else if (fp_digits > 0) {
|
else if (scale > 0) {
|
||||||
pos = fmt_s32_dec(out, val);
|
pos = fmt_s32_dec(out, val);
|
||||||
if (out) {
|
if (out) {
|
||||||
memset(&out[pos], '0', fp_digits);
|
memset(&out[pos], '0', scale);
|
||||||
}
|
}
|
||||||
pos += fp_digits;
|
pos += scale;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fp_digits *= -1;
|
scale = -scale;
|
||||||
uint32_t e = _tenmap[fp_digits];
|
char buf[10]; /* "2147483648" */
|
||||||
int32_t abs = (val / (int32_t)e);
|
int negative = val < 0;
|
||||||
int32_t div = val - (abs * e);
|
uint32_t uval = negative ? -val : val;
|
||||||
|
int len = fmt_u32_dec(buf, uval);
|
||||||
/* the divisor should never be negative */
|
if (negative) {
|
||||||
if (div < 0) {
|
|
||||||
div *= -1;
|
|
||||||
}
|
|
||||||
/* handle special case for negative number with zero as absolute value */
|
|
||||||
if ((abs == 0) && (val < 0)) {
|
|
||||||
if (out) {
|
if (out) {
|
||||||
out[pos] = '-';
|
out[pos] = '-';
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
if (len <= scale) {
|
||||||
|
int zeroes = scale - len + 1;
|
||||||
|
if (out) {
|
||||||
|
memset(&out[pos], '0', zeroes);
|
||||||
|
}
|
||||||
|
pos += zeroes;
|
||||||
|
}
|
||||||
|
if (out) {
|
||||||
|
memcpy(&out[pos], buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
if (!out) {
|
pos += len;
|
||||||
/* compensate for the decimal point character... */
|
|
||||||
pos += fmt_s32_dec(NULL, abs) + 1;
|
if (out) {
|
||||||
|
unsigned dot_pos = pos - scale;
|
||||||
|
for (unsigned i = pos; i >= dot_pos; i--) {
|
||||||
|
out[i] = out[i - 1];
|
||||||
|
}
|
||||||
|
out[dot_pos] = '.';
|
||||||
}
|
}
|
||||||
else {
|
pos += 1;
|
||||||
pos += fmt_s32_dec(&out[pos], abs);
|
|
||||||
out[pos++] = '.';
|
|
||||||
unsigned div_len = fmt_s32_dec(&out[pos], div);
|
|
||||||
fmt_lpad(&out[pos], div_len, (size_t)fp_digits, '0');
|
|
||||||
}
|
|
||||||
pos += fp_digits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this is very probably not the most efficient implementation, as it at least
|
/* 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
|
* pulls in floating point math. But it works, and it's always nice to have
|
||||||
* low hanging fruits when optimizing. (Kaspar)
|
* low hanging fruits when optimizing. (Kaspar)
|
||||||
|
@ -18,7 +18,14 @@
|
|||||||
* integers, even when the C library was built without support for 64 bit
|
* integers, even when the C library was built without support for 64 bit
|
||||||
* formatting (newlib-nano).
|
* formatting (newlib-nano).
|
||||||
*
|
*
|
||||||
* \note The print functions in this library do not buffer any output.
|
* @note The fmt functions expect their `out` parameter to hold the entire output.
|
||||||
|
* This *MUST* be ensured by the caller.
|
||||||
|
*
|
||||||
|
* @note Each fmt function will not write anything to `out` if it is `NULL`, but
|
||||||
|
* still return the number of bytes that would have been written.
|
||||||
|
* This can be used to ensure the `out` buffer is large enough.
|
||||||
|
*
|
||||||
|
* @note The print functions in this library do not buffer any output.
|
||||||
* Mixing calls to standard @c printf from stdio.h with the @c print_xxx
|
* Mixing calls to standard @c printf from stdio.h with the @c print_xxx
|
||||||
* functions in fmt, especially on the same output line, may cause garbled
|
* functions in fmt, especially on the same output line, may cause garbled
|
||||||
* output.
|
* output.
|
||||||
@ -287,39 +294,30 @@ size_t fmt_s16_dec(char *out, int16_t val);
|
|||||||
*
|
*
|
||||||
* @param[out] out Pointer to the output buffer, or NULL
|
* @param[out] out Pointer to the output buffer, or NULL
|
||||||
* @param[in] val Fixed point value
|
* @param[in] val Fixed point value
|
||||||
* @param[in] fp_digits Number of digits after the decimal point, MUST be
|
* @param[in] scale Scale value
|
||||||
* >= -7
|
|
||||||
*
|
*
|
||||||
* @return Length of the resulting string
|
* @return Length of the resulting string
|
||||||
*/
|
*/
|
||||||
size_t fmt_s16_dfp(char *out, int16_t val, int fp_digits);
|
size_t fmt_s16_dfp(char *out, int16_t val, int scale);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert 32-bit fixed point number to a decimal string
|
* @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
|
* This multiplies a 32bit signed number by 10^(scale) before formatting.
|
||||||
* point value as well as an integer defining the position of the decimal point.
|
|
||||||
* This value is used to shift the decimal point to the right (positive value
|
|
||||||
* of @p fp_digits) or to the left (negative value of @p fp_digits).
|
|
||||||
*
|
*
|
||||||
* Will add a leading "-" if @p val is negative.
|
* The resulting string will always be padded with zeros after the decimal point.
|
||||||
*
|
*
|
||||||
* The resulting string will always be patted with zeros after the decimal point.
|
* For example: if @p val is -35648 and @p scale is -2, the resulting
|
||||||
*
|
* string will be "-352.48"( -35648*10^-2). The same value for @p val with
|
||||||
* For example: if @p val is -3548 and @p fp_digits is -2, the resulting string
|
* @p scale of 2 will result in "-3524800" (-35648*10^2).
|
||||||
* will be "-35.48". The same value for @p val with @p fp_digits of 2 will
|
|
||||||
* result in "-354800".
|
|
||||||
*
|
|
||||||
* @pre fp_digits > -8 (TENMAP_SIZE)
|
|
||||||
*
|
*
|
||||||
* @param[out] out Pointer to the output buffer, or NULL
|
* @param[out] out Pointer to the output buffer, or NULL
|
||||||
* @param[in] val Fixed point value
|
* @param[in] val Fixed point value
|
||||||
* @param[in] fp_digits Number of digits after the decimal point, MUST be
|
* @param[in] scale Scale value
|
||||||
* >= -7
|
|
||||||
*
|
*
|
||||||
* @return Length of the resulting string
|
* @return Length of the resulting string
|
||||||
*/
|
*/
|
||||||
size_t fmt_s32_dfp(char *out, int32_t val, int fp_digits);
|
size_t fmt_s32_dfp(char *out, int32_t val, int scale);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Format float to string
|
* @brief Format float to string
|
||||||
|
@ -738,6 +738,15 @@ static void test_fmt_s32_dfp(void)
|
|||||||
out[act_len] = '\0';
|
out[act_len] = '\0';
|
||||||
TEST_ASSERT_EQUAL_STRING("-0.0000001", (char *)out);
|
TEST_ASSERT_EQUAL_STRING("-0.0000001", (char *)out);
|
||||||
|
|
||||||
|
val = -1;
|
||||||
|
fpp = -24;
|
||||||
|
len = fmt_s32_dfp(NULL, val, fpp);
|
||||||
|
TEST_ASSERT_EQUAL_INT(3 - fpp, len);
|
||||||
|
act_len = fmt_s32_dfp(out, val, fpp);
|
||||||
|
TEST_ASSERT_EQUAL_INT(3 - fpp, act_len);
|
||||||
|
out[act_len] = '\0';
|
||||||
|
TEST_ASSERT_EQUAL_STRING("-0.000000000000000000000001", (char *)out);
|
||||||
|
|
||||||
/* check that the buffer was not overflowed */
|
/* check that the buffer was not overflowed */
|
||||||
TEST_ASSERT_EQUAL_STRING("z", &out[28]);
|
TEST_ASSERT_EQUAL_STRING("z", &out[28]);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user