Code:
LDBL makeFPN( ullong num, ullong fpn, long exp, long zeros ) {
LDBL dst = {0};
long base = 10, pos = 0, bit,
pos_max = FPNT_MAN_BIT,
exp_max = FPNT_EXP_MAX;
ullong one = 1, dec = 0;
dst.man = num;
for ( one = 1; one <= fpn; one *= base );
if ( num ) {
for ( ; pos < pos_max; ++pos ) {
if ( num == 1 ) break;
num >>= 1;
}
dst.exp = exp_max + pos - 1;
}
else if ( fpn ) {
for ( pos = -4; zeros < 0 && pos > -pos_max; pos -= 3, ++zeros );
dst.exp = exp_max + pos - 1;
pos = -4;
}
if ( fpn ) dec = 1;
else fpn = one / base;
while ( pos < pos_max ) {
for ( bit = 1; bit < 4 && pos < pos_max; ++bit, ++pos ) {
fpn *= 2;
dst.man <<= 1;
if ( fpn >= one ) {
dst.man |= dec;
fpn -= one;
}
}
}
if ( fpn && dec ) dst.man++;
if ( dst.man ) {
pos = 0;
for ( ; pos < exp; ++pos, dst.man *= 2 );
for ( ; pos > exp; --pos, dst.man *= 2 );
}
return dst;
}
typedef struct test_val {
ullong num;
ullong fpn;
long exp;
long zeros;
} test_val_t;
test_val_t values[] = {
{0}, {1,0}, {101,0}, {0,1,0}, {0,101,0}, {101,101,0}, {0,1,0,-1},
{1,1,10,0}, {0,1,10,0}, {1,1,10,0}, {0,101,10,0}, {1,1,10,0},
{3,14,0}, {3,14,10} };
float floats[] = {
0, 1, 101, 0.1, 0.101, 101.101, 0.01,
1.0e+10, 101.0e+10, 0.1e+10, 0.101e+10, 1.1e+10,
3.14, 3.14e+10 };
char *text[] = {
"0", "1", "101", "0.1", "0.101", "101.101", "0.01",
"1.0e+10", "101.0e+10", "0.1e+10", "0.101e+10", "1.1e+10",
"3.14", "3.14e+10"
};
int main() {
int i;
LDBL test = {0}, mine = {0};
test_val_t *val;
for ( i = 0; i < 7; ++i ) {
test.fpn = floats[i];
val = &(values[i]);
mine = makeFPN( val->num, val->fpn, val->exp, val->zeros );
//printf( "test.sig %u mine.sig %u ", test.sig, mine.sig );
printf( "test.exp %02X mine.exp %02X ", test.exp, mine.exp );
printf( "test.man %06X mine.man %06X ", test.man, mine.man );
#if 0
print( "test.hex", test );
putchar(' ');
print( "mine.hex", mine );
putchar(' ');
#endif
printf("test.fpn %e mine.fpn %e text '%s'\n", test.fpn, mine.fpn, text[i] );
}
return 0;
}