107 lines
2.6 KiB
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));
|
|
}
|