cake
/
libg1m
Archived
1
0
Fork 0
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libg1m/src/bcd/to_ascii.c

97 lines
2.3 KiB
C

/* ************************************************************************** */
/* _____ _ */
/* bcd/to_ascii.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/11/21 13:54:41 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals/bcd.h>
#define VISIBLE_PRECISION 5
/**
* g1m_bcdtoa:
* Simple BCD to string function.
*
* @arg bcd The BCD number.
* @return The allocated string.
*/
char *g1m_bcdtoa(struct bcd *bcd)
{
char buf[50], *p = buf;
unsigned char *bytes = bcd->BCDval;
/* get the exponent */
int neg = 0;
int exp = g1m_bcd_get_exponent_neg(bcd, &neg);
if (neg) *p++ = '-';
/* get the mantissa */
char mant[15];
for (int i = 0; i < 15; i += 2)
mant[i] = lwr(i / 2 + 1);
for (int i = 1; i < 15; i += 2)
mant[i] = upr(i / 2 + 2);
/* calculate number of significant digits */
int signif;
for (signif = 15; signif && !mant[signif - 1]; signif--);
if (!signif) exp = 0;
/* put integer part */
int num = 0;
if (exp > 0) {
while (exp > 0 && signif) {
exp--;
signif--;
*p++ = mant[num++] + '0';
}
if (exp > 0 && exp < VISIBLE_PRECISION) while (exp) {
exp--;
*p++ = '0';
}
} else
*p++ = '0';
/* put decimal part */
if (signif) {
*p++ = '.';
/* put some zeroes */
if (exp < 0 && exp > -VISIBLE_PRECISION) while (exp) {
exp++;
*p++ = '0';
}
/* put the numbers */
while (signif--)
*p++ = mant[num++] + '0';
}
/* put exponent */
if (exp) {
*p++ = '^';
int exp_neg = exp < 0;
if (exp_neg) {
*p++ = '(';
*p++ = '-';
exp = -exp;
}
int eprec = 100;
while (exp < eprec)
eprec /= 10;
while (eprec) {
*p++ = exp / eprec + '0';
exp %= eprec;
eprec /= 10;
}
if (exp_neg) *p++ = ')';
}
/* put string end */
*p = 0;
/* duplicate and send to user */
return (strdup(buf));
}