sys/fmt: use also positive scaling for s32_dfp

This commit is contained in:
Hauke Petersen 2018-01-22 17:09:56 +01:00
parent a19cb8431d
commit 78df885fc7
2 changed files with 50 additions and 59 deletions

View File

@ -263,48 +263,56 @@ 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, unsigned fp_digits) size_t fmt_s16_dfp(char *out, int16_t val, int fp_digits)
{ {
return fmt_s32_dfp(out, val, fp_digits); return fmt_s32_dfp(out, val, fp_digits);
} }
size_t fmt_s32_dfp(char *out, int32_t val, unsigned fp_digits) size_t fmt_s32_dfp(char *out, int32_t val, int fp_digits)
{ {
assert(fp_digits < TENMAP_SIZE); assert(fp_digits > -(int)TENMAP_SIZE);
int32_t absolute, divider; unsigned pos = 0;
unsigned div_len, len, pos = 0;
char tmp[9];
if (fp_digits == 0) { if (fp_digits == 0) {
return fmt_s32_dec(out, val); pos = fmt_s32_dec(out, val);
} }
if (val < 0) { else if (fp_digits > 0) {
pos = fmt_s32_dec(out, val);
if (out) { if (out) {
out[pos++] = '-'; memset(&out[pos], '0', fp_digits);
} }
val = -val; pos += fp_digits;
} }
else {
fp_digits *= -1;
uint32_t e = _tenmap[fp_digits];
int32_t abs = (val / (int32_t)e);
int32_t div = val - (abs * e);
uint32_t e = _tenmap[fp_digits]; /* the divisor should never be negative */
absolute = (val / e); if (div < 0) {
divider = val - (absolute * e); div *= -1;
}
/* handle special case for negative number with zero as absolute value */
if ((abs == 0) && (val < 0)) {
if (out) {
out[pos] = '-';
}
pos++;
}
pos += fmt_s32_dec(&out[pos], absolute); if (!out) {
/* compensate for the decimal point character... */
if (!out) { pos += fmt_s32_dec(NULL, abs) + 1;
return pos + 1 + fp_digits; /* abs len + decimal point + divider */ }
} else {
pos += fmt_s32_dec(&out[pos], abs);
out[pos++] = '.'; out[pos++] = '.';
len = pos + fp_digits; unsigned div_len = fmt_s32_dec(&out[pos], div);
div_len = fmt_s32_dec(tmp, divider); fmt_lpad(&out[pos], div_len, (size_t)fp_digits, '0');
}
while (pos < (len - div_len)) { pos += fp_digits;
out[pos++] = '0';
}
for (size_t i = 0; i < div_len; i++) {
out[pos++] = tmp[i];
} }
return pos; return pos;

View File

@ -225,60 +225,43 @@ size_t fmt_s16_dec(char *out, int16_t val);
/** /**
* @brief Convert 16-bit fixed point number to a decimal string * @brief Convert 16-bit fixed point number to a decimal string
* *
* The input for this function is a signed 16-bit integer holding the fixed * See fmt_s32_dfp() for more details
* 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.
*
* 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". For @p val := 12010 and @p fp_digits := 3 the result will
* be "12.010".
*
* Will add a leading "-" if @p val is negative.
*
* If @p out is NULL, will only return the number of bytes that would have
* been written.
*
* @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 * @param[in] fp_digits Number of digits after the decimal point, MUST be
* >= -7
* *
* @return Length of the resulting string * @return Length of the resulting string
*/ */
size_t fmt_s16_dfp(char *out, int16_t val, unsigned fp_digits); size_t fmt_s16_dfp(char *out, int16_t val, int fp_digits);
/** /**
* @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 * 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 * point value as well as an integer defining the position of the decimal point.
* decimal point, so this value defines the number of decimal digits after the * This value is used to shift the decimal point to the right (positive value
* decimal point. * of @p fp_digits) or to the left (negative value of @p fp_digits).
* *
* Will add a leading "-" if @p val is negative. * Will add a leading "-" if @p val is negative.
* *
* The resulting string will always be patted 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 -314159 and @p fp_digits is 5, the resulting string * For example: if @p val is -3548 and @p fp_digits is -2, the resulting string
* will be "-3.14159". For @p val := 16777215 and @p fp_digits := 6 the result * will be "-35.48". The same value for @p val with @p fp_digits of 2 will
* will be "16.777215". * result in "-354800".
* *
* If @p out is NULL, will only return the number of bytes that would have * @pre fp_digits > -8 (TENMAP_SIZE)
* been written.
*
* @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 * @param[in] fp_digits Number of digits after the decimal point, MUST be
* >= -7
* *
* @return Length of the resulting string * @return Length of the resulting string
*/ */
size_t fmt_s32_dfp(char *out, int32_t val, unsigned fp_digits); size_t fmt_s32_dfp(char *out, int32_t val, int fp_digits);
/** /**
* @brief Format float to string * @brief Format float to string