1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

sys/fmt: make fmt_s32_dfp() string based

This commit is contained in:
Kaspar Schleiser 2021-10-28 21:00:00 +02:00
parent 09e0692a85
commit 61c62c2ed6
2 changed files with 42 additions and 50 deletions

View File

@ -308,61 +308,62 @@ size_t fmt_s16_dec(char *out, int16_t 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 (fp_digits == 0) {
if (scale == 0) {
pos = fmt_s32_dec(out, val);
}
else if (fp_digits > 0) {
else if (scale > 0) {
pos = fmt_s32_dec(out, val);
if (out) {
memset(&out[pos], '0', fp_digits);
memset(&out[pos], '0', scale);
}
pos += fp_digits;
pos += scale;
}
else {
fp_digits *= -1;
uint32_t e = _tenmap[fp_digits];
int32_t abs = (val / (int32_t)e);
int32_t div = val - (abs * e);
/* the divisor should never be negative */
if (div < 0) {
div *= -1;
}
/* handle special case for negative number with zero as absolute value */
if ((abs == 0) && (val < 0)) {
scale = -scale;
char buf[10]; /* "2147483648" */
int negative = val < 0;
uint32_t uval = negative ? -val : val;
int len = fmt_u32_dec(buf, uval);
if (negative) {
if (out) {
out[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) {
/* compensate for the decimal point character... */
pos += fmt_s32_dec(NULL, abs) + 1;
pos += len;
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 += 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;
pos += 1;
}
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
* low hanging fruits when optimizing. (Kaspar)

View File

@ -287,39 +287,30 @@ size_t fmt_s16_dec(char *out, int16_t val);
*
* @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
* >= -7
* @param[in] scale Scale value
*
* @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
*
* The input for this function is a signed 32-bit integer holding the fixed
* 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).
* This multiplies a 32bit signed number by 10^(scale) before formatting.
*
* 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 -3548 and @p fp_digits is -2, the resulting string
* 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)
* 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
* @p scale of 2 will result in "-3524800" (-35648*10^2).
*
* @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
* >= -7
* @param[in] scale Scale value
*
* @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