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

107 lines
2.6 KiB
C

/* *****************************************************************************
* bcd/to_ascii.c -- make an ASCII-encoded string out of a BCD-encoded number.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
#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 = 1000;
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));
}