74 lines
1.9 KiB
C
74 lines
1.9 KiB
C
|
#include "Rts.h"
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#define BYTEBUILD_DOUBLE_PRECISION 0.00000000000001
|
||
|
|
||
|
HsInt bytebuild_paste_double(char *s0, HsInt off, double n) {
|
||
|
char* s = s0 + off;
|
||
|
// handle special cases
|
||
|
if (n == 0 || isnan(n) || isinf(n)) {
|
||
|
*s = '0';
|
||
|
return 1;
|
||
|
} else {
|
||
|
int digit, m, m1;
|
||
|
char *c = s;
|
||
|
int neg = (n < 0);
|
||
|
if (neg)
|
||
|
n = -n;
|
||
|
// calculate magnitude
|
||
|
m = log10(n);
|
||
|
int useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
|
||
|
if (neg)
|
||
|
*(c++) = '-';
|
||
|
// set up for scientific notation
|
||
|
if (useExp) {
|
||
|
if (m < 0)
|
||
|
m -= 1.0;
|
||
|
n = n / pow(10.0, m);
|
||
|
m1 = m;
|
||
|
m = 0;
|
||
|
}
|
||
|
if (m < 1.0) {
|
||
|
m = 0;
|
||
|
}
|
||
|
// convert the number
|
||
|
while (n > BYTEBUILD_DOUBLE_PRECISION || m >= 0) {
|
||
|
double weight = pow(10.0, m);
|
||
|
if (weight > 0 && !isinf(weight)) {
|
||
|
digit = floor(n / weight);
|
||
|
n -= (digit * weight);
|
||
|
*(c++) = '0' + digit;
|
||
|
}
|
||
|
if (m == 0 && n > 0)
|
||
|
*(c++) = '.';
|
||
|
m--;
|
||
|
}
|
||
|
if (useExp) {
|
||
|
// convert the exponent
|
||
|
int i, j;
|
||
|
*(c++) = 'e';
|
||
|
if (m1 > 0) {
|
||
|
*(c++) = '+';
|
||
|
} else {
|
||
|
*(c++) = '-';
|
||
|
m1 = -m1;
|
||
|
}
|
||
|
m = 0;
|
||
|
while (m1 > 0) {
|
||
|
*(c++) = '0' + m1 % 10;
|
||
|
m1 /= 10;
|
||
|
m++;
|
||
|
}
|
||
|
c -= m;
|
||
|
for (i = 0, j = m-1; i<j; i++, j--) {
|
||
|
// swap without temporary
|
||
|
c[i] ^= c[j];
|
||
|
c[j] ^= c[i];
|
||
|
c[i] ^= c[j];
|
||
|
}
|
||
|
c += m;
|
||
|
}
|
||
|
return (c - s);
|
||
|
}
|
||
|
}
|