Code:
../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 45, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 0497 00111110001 1000000000000000000000000000000000000000000000000000
../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 1028 10000000100 0111000000000000000000000000000000000000000000000000
../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 46, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 0497 00111110001 1100000000000000000000000000000000000000000000000000
../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 1028 10000000100 0111100000000000000000000000000000000000000000000000
../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 47, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 0498 00111110010 0000000000000000000000000000000000000000000000000000
../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 1028 10000000100 1000000000000000000000000000000000000000000000000000
../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 48, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 0498 00111110010 0010000000000000000000000000000000000000000000000000
../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 1028 10000000100 1000100000000000000000000000000000000000000000000000
../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 49, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 0498 00111110010 0100000000000000000000000000000000000000000000000000
../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 1028 10000000100 1001000000000000000000000000000000000000000000000000
The 4 digit value between the sign bit and the exponent bits is just the exponent in decimal prepended with 0's for alignment, as a reminder the top NUM is the result of my code while the bottom NUM is the result of
Code:
int_t alu_match_exponents
(
alu_t *alu
, uint_t num
, uint_t val
, uint_t tmp
)
{
if ( alu )
{
int_t ret;
alu_reg_t NUM, VAL, MAN, TMP;
size_t nexp;
alu_reg_init_floating( alu, NUM, num );
alu_reg_init_floating( alu, VAL, val );
alu_reg_init_unsigned( alu, TMP, tmp );
NUM.upto = alu_Nbits(alu);
VAL.upto = alu_Nbits(alu);
ret = alu_reg_get_exponent( alu, NUM, &nexp );
if ( ret == 0 )
{
size_t vexp, diff;
bool truncated = false;
(void)alu_reg_get_exponent( alu, VAL, &vexp );
if ( nexp > vexp )
{
if ( vexp )
{
diff = nexp - vexp;
alu_reg_init_mantissa( VAL, MAN );
/* Match exponent and align mantissa */
(void)alu_reg_set_exponent( alu, VAL, nexp );
alu->block.fault = 0;
alu_reg__shr( alu, MAN, TMP, diff );
truncated = (alu_errno(alu) == ERANGE);
/* Insert assumed bit back into position */
if ( diff < MAN.upto )
{
void *V = alu_reg_data( alu, VAL );
alu_bit_t v = alu_bit( V, MAN.upto - diff );
*(v.ptr) |= v.mask;
}
}
}
else if ( vexp > nexp )
{
if ( nexp )
{
diff = vexp - nexp;
alu_reg_init_mantissa( NUM, MAN );
(void)alu_reg_set_exponent( alu, NUM, vexp );
alu->block.fault = 0;
alu_reg__shr( alu, MAN, TMP, diff );
truncated = (alu_errno(alu) == ERANGE);
/* Insert assumed bit back into position */
if ( diff < MAN.upto )
{
void *N = alu_reg_data( alu, NUM );
alu_bit_t n = alu_bit( N, MAN.upto - diff );
*(n.ptr) |= n.mask;
}
}
}
alu->block.fault = IFTRUE(truncated,ERANGE);
return 0;
}
alu_error(ret);
return ret;
}
return alu_err_null_ptr("alu");
}
int_t alu_reg_addition(
alu_t *alu
, alu_reg_t NUM
, alu_reg_t VAL
, uint_t cpy
, uint_t tmp
)
{
if ( alu )
{
int ret;
bool carry = false, changed = false;
alu_bit_t n, v;
size_t pos;
void *part;
alu_reg_t CPY, CEXP, CMAN, TEXP, TMAN, TMP;
NUM.node %= alu_used( alu );
VAL.node %= alu_used( alu );
ret = IFTRUE( !NUM.node || !VAL.node, EINVAL );
if ( ret )
{
alu_error( ret );
if ( !NUM.node ) alu_puts( "NUM.node was 0!" );
if ( !VAL.node ) alu_puts( "VAL.node was 0!" );
return ret;
}
if ( alu_reg_floating( VAL ) )
{
alu_reg_init_floating( alu, TMP, tmp );
TMP.upto = alu_Nbits(alu);
/* VAL is supposed to be unchanged so use VCPY instead */
ret = alu_reg_mov( alu, TMP, VAL );
if ( ret == 0 )
{
alu_reg_init_floating( alu, CPY, cpy );
CPY.upto = alu_Nbits(alu);
/* Need NUM to be unchanged so can restore details later,
* having both floats the same size also makes math easier,
* also no chance of failure here as the previous move
* succeeded in getting the same temporary registers this
* one will be looking for */
(void)alu_reg_mov( alu, CPY, NUM );
uint_t temp = alu_get_reg_node( alu, 0 );
if ( temp )
{
ret = alu_match_exponents( alu, cpy, tmp, temp );
alu_rem_reg_node( alu, &temp );
if ( ret == 0 )
{
bool truncated = (alu_errno(alu) == ERANGE);
uint_t nodes[2];
ret = alu_get_reg_nodes( alu, nodes, 2, 0 );
if ( ret == 0 )
{
do
{
alu_reg_t _CMAN, _TMAN;
size_t bias, exp;
alu_reg_init_unsigned( alu, _CMAN, nodes[0] );
alu_reg_init_unsigned( alu, _TMAN, nodes[1] );
alu_reg_init_exponent( CPY, CEXP );
alu_reg_init_exponent( TMP, TEXP );
alu_reg_init_mantissa( CPY, CMAN );
alu_reg_init_mantissa( TMP, TMAN );
alu_reg_int2int( alu, _CMAN, CMAN );
alu_reg_int2int( alu, _TMAN, TMAN );
(void)alu_reg_get_exponent( alu, CPY, &exp );
bias = alu_reg_get_exponent_bias( CPY );
if ( exp )
{
exp -= bias;
if ( (ssize_t)exp < 0 )
{
exp = -exp;
}
n = alu_bit
(
(void*)alu_reg_data( alu, _CMAN )
, exp
);
*(n.ptr) |= n.mask;
v = alu_bit
(
(void*)alu_reg_data( alu, _TMAN )
, exp
);
*(v.ptr) |= v.mask;
}
/* Not possible to get an EOVERFLOW from these */
ret = alu_reg_add( alu, _CMAN, _TMAN );
if ( ret != 0 && ret != ENODATA )
break;
n = alu_reg_end_bit( alu, _CMAN );
if ( n.bit || *(n.ptr) & n.mask )
{
exp = n.bit + bias;
ret = alu_reg_set_exponent( alu, CPY, exp );
if ( ret )
break;
_CMAN.upto = n.bit - 1;
pos = LOWEST( CMAN.upto, _CMAN.upto );
_CMAN.from = _CMAN.upto - pos;
CMAN.from = CMAN.upto - pos;
(void)alu_reg_int2int( alu, CMAN, _CMAN );
}
ret = alu_reg_mov( alu, NUM, CPY );
if ( ret )
break;
alu_rem_reg_nodes( alu, nodes, 2 );
return EITHER( truncated, ERANGE, ret );
}
while (0);
alu_rem_reg_nodes( alu, nodes, 2 );
alu_error(ret);
return ret;
}
}
}
else
{
ret = alu_errno(alu);
}
}
alu_error(ret);
return ret;
}