Is it really necessary to use non-standard headers like uchar.h and non-standard types like ssize_t ?
Printable View
Is it really necessary to use non-standard headers like uchar.h and non-standard types like ssize_t ?
It has nothing to do with MS. Neither MinGW nor cygwin have these
ssize_t is part of the POSIX standard, not the C standard. And uchar.h is only in C11 and later (which MS doesn't support).
C11 is still a standard so my statement stands true there, also MS DOES support ssize_t in the form of think it was SSIZE_T, I forgot about it until the recent posts, as soon as I get round to it I will adapt the unic headers to include that part, as for the uchar.h, I'll look into the work around (this is why I want to create the unic library, b****y MS and its private crap)
MSVC now supports C11 and C17, though only very recently with one of their updates to Visual Studio 2019.Quote:
Originally Posted by christop
Found another FPN multiplication bug:
I've tried everything I can think of, now I'm fishing for ideasCode:make check.run
...
Running suite(s): ALU
../src/alup.c:1524: alup__mul() 'MUL 2.1'
...
../src/alup.c:1535: alup__mul() 'MUL 2.2'
../tests/check_alu.c:842: test_alup__math_floating_absolute_fn() exp_dig = 11, man_dig = 52, 1397677567.000000 * 797987423.000000 = 1115329119875239808.000000, got 579400764218150784.000000
../tests/check_alu.c:855: test_alup__math_floating_absolute_fn() _EXPECT = 0 +0059 10000111010 1110111101001110001111011001101110111010000000011111
../tests/check_alu.c:856: test_alup__math_floating_absolute_fn() _RESULT = 0 +0059 10000111010 0000000101001110001111011001101110111010000000011111
99%: Checks: 1532, Failures: 1, Errors: 0
...
Compilation finished successfully.
Code:int_t alup__mul( alup_t _NUM, alup_t _VAL, void *_cpy, void *_tmp )
{
if ( alup_floating( _NUM ) || alup_floating( _VAL ) )
{
int_t ret;
alup_t _DST, _SRC, _DMAN, _SMAN;
ssize_t exp, dexp, sexp, dbias, sbias, dbits, sbits, bits, size;
bool_t dneg, sneg;
ssize_t ddiff = 0, sdiff = 0;
size_t man_upto;
alub_t final, prior;
/* Ensure dealing with just floats, impossible for both to take _tmp
* given the above if statment */
if ( alup_floating( _NUM ) )
{
_DST = _NUM;
}
else
{
bits = _NUM.upto - _NUM.from;
size = BITS2SIZE( bits );
alup_init_floating( _DST, _tmp, size );
alup_mov( _DST, _NUM );
}
if ( alup_floating( _VAL ) )
{
_SRC = _VAL;
}
else
{
bits = _VAL.upto - _VAL.from;
size = BITS2SIZE( bits );
alup_init_floating( _SRC, _tmp, size );
alup_mov( _SRC, _VAL );
}
dneg = alup_below0( _DST );
sneg = alup_below0( _SRC );
dexp = alup_get_exponent( _DST );
sexp = alup_get_exponent( _SRC );
if ( !dexp || !sexp )
{
_NUM.upto--;
alup_set( _NUM, 0 );
alub_set( _DST.data, _DST.upto - 1, dneg != sneg );
return 0;
}
dbias = alup_get_exponent_bias( _DST );
dexp -= dbias;
sbias = alup_get_exponent_bias( _DST );
sexp -= sbias;
exp = dexp + sexp;
alup_init_mantissa( _DST, _DMAN );
alup_init_mantissa( _SRC, _SMAN );
dbits = _DMAN.upto - _DMAN.from;
sbits = _SMAN.upto - _SMAN.from;
bits = LOWEST( dbits, sbits );
ddiff = EITHER( dexp >= 0 && dexp < dbits, dexp, dbits );
sdiff = EITHER( sexp >= 0 && sexp < sbits, sexp, sbits );
prior = alub( _DST.data, _DST.upto - 1 );
*(prior.ptr) &= ~(prior.mask);
alub_set( _DST.data, _DST.upto - 1, 0 );
alup_set_exponent( _DST, 0 );
alub_set( _DST.data, _DMAN.upto, 1 );
alub_set( _SRC.data, _SMAN.upto, 1 );
man_upto = _DMAN.upto;
_SMAN.from = _SMAN.upto - sdiff;
_DMAN.upto = _DST.upto;
_SMAN.upto++;
alup__shr( _DMAN, dbits - ddiff );
prior = alup_final_one( _DMAN );
ret = alup__mul_int2int( _DMAN, _SMAN, _cpy );
/* We mangled this so restore it now */
alup_set_exponent( _SRC, sexp + sbias );
if ( exp >= dbias )
{
alu_puts("MUL 1");
/* Set infinity */
alup_init_mantissa( _DST, _DMAN );
alup_set( _DMAN, 0 );
alup_set_exponent( _DST, (dbias << 1) | 1 );
}
else
{
final = alup_final_one( _DMAN );
_DMAN.upto = man_upto;
if ( final.bit < man_upto - 1 )
{
/* Normalise */
size_t mov = man_upto - final.bit;
size_t add = final.bit - prior.bit;
alu_puts("MUL 2.1");
exp = dexp + add;
alup__shl( _DMAN, mov );
}
else if ( final.bit >= man_upto )
{
/* Normalise */
size_t mov = final.bit - man_upto;
size_t add = final.bit - prior.bit;
alu_puts("MUL 2.2");
exp = dexp + add;
alup__shr( _DMAN, mov );
}
else if ( ret == EOVERFLOW )
{
alu_puts("MUL 2.3");
exp++;
alup__shr( _DMAN, 1 );
alub_set( _DMAN.data, man_upto - 1, 1 );
}
alup_set_exponent( _DST, exp + dbias );
}
alub_set( _DST.data, _DST.upto - 1, dneg != sneg );
if ( alup_floating( _NUM ) )
return 0;
return alup_mov( _NUM, _DST );
}
return alup__mul_int2int( _NUM, _VAL, _cpy );
}
Fixed it, turned out it was because I shortened the length of _DMAN before it needed to be, or rather it didn't need to be at all, now the division shows a bug on the same values, got a funeral to go to soon so will just
post the output and code before trying to fix it myself in the little time I have left before I leave:
Code:make check.run
...
Running suite(s): ALU
../src/alup.c:1745: alup__div() 'Route 2.1'
../tests/check_alu.c:841: test_alup__math_floating_absolute_fn() exp_dig = 11, man_dig = 52, 1397677567.000000 / 797987423.000000 = 1.751503, got 576460753243754624.000000
../tests/check_alu.c:854: test_alup__math_floating_absolute_fn() _EXPECT = 0 +0000 01111111111 1100000001100010100001000110010100110001101000001110
../tests/check_alu.c:855: test_alup__math_floating_absolute_fn() _RESULT = 0 +0059 10000111010 0000000000000000000000000000011100000001100010100001
99%: Checks: 1532, Failures: 1, Errors: 0
...
Compilation finished successfully.
Code:int_t alup__div( alup_t _NUM, alup_t _VAL, void *_rem, void *_tmp )
{
if ( alup_floating( _NUM ) || alup_floating( _VAL ) )
{
alup_t _DST, _SRC, _DMAN, _SMAN;
size_t exp_len;
ssize_t exp, dexp, sexp, dbias, sbias, dbits, sbits, bits, size;
bool_t dneg, sneg;
alub_t prior;
/* Ensure dealing with just floats, impossible for both to take _tmp
* given the above if statment */
if ( alup_floating( _NUM ) )
{
_DST = _NUM;
}
else
{
bits = _NUM.upto - _NUM.from;
size = BITS2SIZE( bits );
alup_init_floating( _DST, _tmp, size );
alup_mov( _DST, _NUM );
}
if ( alup_floating( _VAL ) )
{
_SRC = _VAL;
}
else
{
bits = _VAL.upto - _VAL.from;
size = BITS2SIZE( bits );
alup_init_floating( _SRC, _tmp, size );
alup_mov( _SRC, _VAL );
}
dneg = alup_below0( _DST );
sneg = alup_below0( _SRC );
alub_set( _DST.data, _DST.upto - 1, dneg != sneg );
dexp = alup_get_exponent( _DST );
sexp = alup_get_exponent( _SRC );
if ( !dexp || !sexp )
{
_NUM.upto--;
alup_set( _NUM, 0 );
return 0;
}
dbias = alup_get_exponent_bias( _DST );
dexp -= dbias;
sbias = alup_get_exponent_bias( _DST );
sexp -= sbias;
alup_init_mantissa( _DST, _DMAN );
alup_init_mantissa( _SRC, _SMAN );
dbits = _DMAN.upto - _DMAN.from;
sbits = _SMAN.upto - _SMAN.from;
bits = LOWEST( dbits, sbits );
exp_len = (_DST.upto - _DMAN.upto) - 1;
_SMAN.from = _SMAN.upto - EITHER( sexp >= 0 && sexp < bits, sexp, bits );
alub_set( _SMAN.data, _SMAN.upto, 1 );
_DMAN.upto = _DST.upto - 1;
_SMAN.upto++;
alup__shl( _DMAN, exp_len - 1 );
alub_set( _DMAN.data, _DMAN.upto - 1, 1 );
prior = alup_final_one( _DMAN );
(void)alup__div_int2int( _DMAN, _SMAN, _rem );
/* We mangled this so restore it now */
alup_set_exponent( _SRC, sexp + sbias );
exp = dexp + sexp;
if ( exp > dbias )
{
alu_puts("Route 1");
/* Set infinity */
_DMAN.upto = (_DST.upto - exp_len) - 1;
alup_set( _DMAN, 0 );
alup_set_exponent( _DST, (dbias << 1) | 1 );
}
else if ( exp <= (ssize_t)(_DMAN.upto - _DMAN.from) )
{
/* Normalise */
alub_t first = alup_first_one( _DMAN ), final = alup_final_one( _DMAN );
size_t rel2prv = prior.bit - final.bit
, rel2cap = _DMAN.upto - final.bit;
bool_t round = (first.bit - _DST.from) < exp_len;
if ( rel2prv >= (exp_len-1) )
{
alu_puts("Route 2.1");
alup__shr( _DMAN, (exp_len - 1) );
//alup__shr( _DMAN, ((_DMAN.upto - _DST.from) - pos) );
}
else
{
//alu_puts("Route 2.2");
alup__shr( _DMAN, (exp_len - rel2cap) - 1 );
exp = dexp - rel2prv;
if ( round )
{
alup_inc( _DMAN );
}
alup__shr( _DMAN, 1 );
}
alup_set_exponent( _DST, exp + dbias );
}
else
{
//alu_puts("Route 3");
alup__shr( _DMAN, (exp_len - 1) );
alup_set_exponent( _DST, exp + dbias );
}
if ( alup_floating( _NUM ) )
return 0;
return alup_mov( _NUM, _DST );
}
return alup__div_int2int( _NUM, _VAL, _rem );
}
Still no luck with MinGW:
Alu_demo\alu\_.h|4|fatal error: unic/limits.h: No such file or directory|
That's strange, have you checked that unic downloaded properly? I know my code there could probably use some work but I need the help of someone used to using git in shell rather than GUI.
There's no easily discernible reason for it to not find the header when I used -I $(UNIC_INC_DIR) to include the right directory in the search path.
Fixed the issue, ended up having to dedicate _tmp to _DST, _NUM for _SRC, move _NUM to _DST, _VAL to _SRC afterwards (since have to make sure is a float anyways) and remove the check for _NUM being a float to ensure _DST is moved into _NUM at the end, still get a rounding error however:
Current code (not cleaned up)Code:make check.run
...
Running suite(s): ALU
...
../src/alup.c:1732: alup__div() Route 2.1, mov = 7
../src/alup.c:1736: alup__div() _DST = 0 -0771 00011111100 01001110110001001110110001001110110001001110110001001110110001001110110001001110110001001110110001001110110001001110
../src/alup.c:1740: alup__div() _DST = 0 -1022 00000000001 11111000100111011000100111011000100111011000100111011000100111011000100111011000100111011000100111011000100111011001
../tests/check_alu.c:739: test_alup__math_floating_incremental_fn() exp_dig = 11, man_dig = 52, _i = 205, 205.000000 / 13.000000 = 15.769231, got 15.769231
../tests/check_alu.c:752: test_alup__math_floating_incremental_fn() _EXPECT = 0 +0003 10000000010 1111100010011101100010011101100010011101100010011110
../tests/check_alu.c:753: test_alup__math_floating_incremental_fn() _RESULT = 0 +0003 10000000010 1111100010011101100010011101100010011101100010011101
99%: Checks: 1532, Failures: 1, Errors: 0
...
Compilation finished successfully.
If anyone has any ideas for fixing the rounding error it would be much appreciated if you post themCode:int_t alup__div( alup_t _NUM, alup_t _VAL, void *_rem, void *_tmp )
{
if ( alup_floating( _NUM ) || alup_floating( _VAL ) )
{
alup_t _DST, _SRC, _DMAN, _SMAN;
size_t exp_len, man_upto;
ssize_t exp, dexp, sexp, dbias, sbias, dbits, sbits, bits, size;
bool_t dneg, sneg;
alub_t prior;
/* Ensure dealing with just floats, impossible for both to take _tmp
* given the above if statment */
bits = (_NUM.upto - _NUM.from) * 2;
size = BITS2SIZE( bits );
alup_init_floating( _DST, _tmp, size );
alup_mov( _DST, _NUM );
size /= 2;
_SRC.data = _NUM.data;
_SRC.info = ALU_INFO_FLOAT | ALU_INFO__SIGN;
_SRC.from = _NUM.from;
_SRC.upto = _NUM.upto;
alup_mov( _SRC, _VAL );
dneg = alup_below0( _DST );
sneg = alup_below0( _SRC );
dexp = alup_get_exponent( _DST );
sexp = alup_get_exponent( _SRC );
if ( !dexp || !sexp )
{
_NUM.upto--;
alup_set( _NUM, 0 );
alub_set( _DST.data, _DST.upto - 1, dneg != sneg );
return 0;
}
dbias = alup_get_exponent_bias( _DST );
sbias = alup_get_exponent_bias( _DST );
dexp -= dbias;
sexp -= sbias;
alup_init_mantissa( _DST, _DMAN );
alup_init_mantissa( _SRC, _SMAN );
dbits = _DMAN.upto - _DMAN.from;
sbits = _SMAN.upto - _SMAN.from;
bits = LOWEST( dbits, sbits );
exp_len = (_DST.upto - _DMAN.upto) - 1;
_SMAN.from = _SMAN.upto - EITHER( sexp >= 0 && sexp < sbits, sexp, sbits );
alub_set( _DST.data, _DMAN.upto, 1 );
alub_set( _SRC.data, _SMAN.upto, 1 );
man_upto = _DMAN.upto;
_DMAN.upto = _DST.upto;
_SMAN.upto++;
alup__shl( _DMAN, exp_len );
prior = alup_final_one( _DMAN );
(void)alup__div_int2int( _DMAN, _SMAN, _rem );
exp = dexp + sexp;
if ( exp > dbias )
{
alu_puts("Route 1");
/* Set infinity */
_DMAN.upto = man_upto;
alup_set( _DMAN, 0 );
alup_set_exponent( _DST, (dbias << 1) | 1 );
}
else if ( exp <= (ssize_t)(_DMAN.upto - _DMAN.from) )
{
/* Normalise */
alub_t first = alup_first_one( _DMAN ), final = alup_final_one( _DMAN );
size_t rel2prv = prior.bit - final.bit
, rel2cap = _DMAN.upto - final.bit, mov, sub;
bool_t round = (first.bit - _DST.from) < exp_len;
exp = dexp - rel2prv;
if ( final.bit > man_upto )
{
mov = final.bit - man_upto;
alu_printf( "Route 2.1, mov = %zu", mov );
if ( mov )
{
alup_print( _DST, 0, 1 );
alup__shr( _DMAN, mov - 1 );
alup_inc( _DMAN );
alup__shr( _DMAN, 1 );
alup_print( _DST, 0, 1 );
}
else
{
alu_puts("No rounding");
alup__shr( _DMAN, mov );
}
}
else if ( final.bit < man_upto )
{
mov = man_upto - final.bit;
alu_puts("Route 2.2");
alup__shl( _DMAN, mov - 1 );
//exp = dexp - rel2prv;
if ( round )
{
alup_inc( _DMAN );
}
alup__shr( _DMAN, 1 );
}
alup_set_exponent( _DST, exp + dbias );
}
else
{
//alu_puts("Route 3");
alup__shr( _DMAN, (exp_len - 1) );
alup_set_exponent( _DST, exp + dbias );
}
alub_set( _DST.data, _DST.upto - 1, dneg != sneg );
return alup_mov( _NUM, _DST );
}
return alup__div_int2int( _NUM, _VAL, _rem );
}
Haven't managed to fix that rounding error as yet but found an example of the FPN subtraction bug I discovered earlier but had the wrong info displayed at the time. Got overtime today, early start tomorrow, gospel after that and possibly overtime for 4 weeks on one of my days off so is unlikely I will feel like looking into this bug until after that so will just post here and see if anyone thinks of something.
Edited Output:
Subtraction Function:Code:make check.run
...
Running suite(s): ALU
... (17 Off by 1 errors from FPN division)
../tests/check_alu.c:1031: test_alup__math_floating_absolute_fn() exp_dig = 11, man_dig = 52, 1327753883.000000 - 1770012269.000000 = -442258386.000000, got 631483438.000000
../tests/check_alu.c:1044: test_alup__math_floating_absolute_fn() _EXPECT = 1 +0028 10000011011 1010010111000101001111010010000000000000000000000000
../tests/check_alu.c:1045: test_alup__math_floating_absolute_fn() _RESULT = 0 +0029 10000011100 0010110100011101011000010111000000000000000000000000
99%: Checks: 2560, Failures: 18, Errors: 0
...
Compilation finished successfully.
Exponent matching Function:Code:int_t alup__sub( alup_t _NUM, alup_t _VAL, void *_cpy, void *_tmp )
{
if ( alup_floating( _NUM ) || alup_floating( _VAL ) )
{
int_t ret;
alup_t _CPY, _TMP, _CMAN, _TMAN;
size_t exp, cexp, texp;
size_t
bits = HIGHEST( _NUM.upto - _NUM.from, _VAL.upto - _VAL.from )
, size = (bits / UNIC_CHAR_BIT) + !!(bits % UNIC_CHAR_BIT);
bool_t truncated = false;
alup_init_floating( _CPY, _cpy, size );
alup_init_floating( _TMP, _tmp, size );
alup_init_mantissa( _CPY, _CMAN );
alup_init_mantissa( _TMP, _TMAN );
alup_mov( _CPY, _NUM );
alup_mov( _TMP, _VAL );
cexp = alup_get_exponent( _CPY );
texp = alup_get_exponent( _TMP );
ret = alup_match_exponents( _CPY.data, _TMP.data, size );
truncated = (ret == ERANGE);
exp = alup_get_exponent( _CPY );
ret = alup__sub_int2int( _CMAN, _TMAN );
if ( cexp || texp )
{
size_t bias = alup_get_exponent_bias( _CPY );
if ( ret == EOVERFLOW || cexp == texp )
{
//size_t both = 1 + (ret == EOVERFLOW && cexp == texp);
//alub_t c = alub( _CMAN.data, _CMAN.upto - 1 );
--exp;
alup__shl( _CMAN, 1 );
//*(c.ptr) &= ~(c.mask);
//*(c.ptr) |= IFTRUE( both == 2, c.mask );
}
if ( cexp == texp )
{
alup_set( _TMP, 0 );
_TMP.info = 0;
if ( alup_cmp_int2int( _CMAN, _TMP ) == 0 )
{
if ( ret != EOVERFLOW )
exp = 0;
}
}
alub_set
(
_CPY.data
, _CPY.upto - 1
, (cexp >= bias && cexp < texp) || (!cexp && texp >= bias)
);
}
(void)alup_set_exponent( _CPY, exp );
ret = alup_mov( _NUM, _CPY );
return IFTRUE( truncated || ret == ERANGE, ERANGE );
}
return alup__sub_int2int( _NUM, _VAL );
}
Addition uses the same exponent matcher on the same values so I doubt it's that, included just in case thoughCode:int_t alup_match_exponents( void *_num, void *_val, size_t size )
{
int_t ret;
alup_t _NUM, _VAL, _DST, _MAN = {0};
size_t exp = 0, nexp, vexp, diff = 0;
bool truncated = false;
alup_init_floating( _NUM, _num, size );
alup_init_floating( _VAL, _val, size );
nexp = alup_get_exponent( _NUM );
vexp = alup_get_exponent( _VAL );
if ( nexp > vexp )
{
exp = nexp;
diff = nexp - vexp;
_DST = _VAL;
}
else if ( vexp > nexp )
{
exp = vexp;
diff = vexp - nexp;
_DST = _NUM;
}
if ( diff )
{
alup_init_mantissa( _DST, _MAN );
/* Match exponent and align mantissa */
(void)alup_set_exponent( _DST, exp );
ret = alup__shr( _MAN, diff );
truncated = (ret == ERANGE);
/* Insert assumed bit back into position */
if ( diff < _MAN.upto )
{
alub_t m = alub( _MAN.data, _MAN.upto - diff );
*(m.ptr) |= m.mask;
}
}
return IFTRUE( truncated, ERANGE );
}
Didn't have overtime today and when I finally felt like programming I decided to spend the past few hours changing how certain information is recorded in the API, took a while to fix all the superficial errors that popped up as a result, anyways since I couldn't think of how to fix the other bugs I mentioned just yet I decided to check the floating point comparisons are correct, turns out either my comparisons are more accurate or I've misunderstood something critical, 1st of here's the code for the check:
Edited output:Code:START_TEST( test_alup__cmp_floating_incremental )
{
ck_assert( alu_upto(alu) > 0 );
if ( !stop_checks )
{
int expect, result, _j = _i % per_func;
double value1 = _i, value2 = _j;
alup_t _VALUE1, _VALUE2;
alup_init_floating( _VALUE1, &value1, bitsof(double) );
alup_init_floating( _VALUE2, &value2, bitsof(double) );
expect = (value1 > value2) - (value1 < value2);
result = alup_cmp( &_VALUE1, &_VALUE2 );
if ( expect != result )
{
alu_printf
(
"%f <> %f = %i (source: %i <> %i), got %i"
, value2
, value2
, expect
, _i
, _j
, result
);
alup_print( &_VALUE1, 0, 1 );
alup_print( &_VALUE2, 0, 1 );
stop_checks = true;
}
ck_assert( expect == result );
}
}
END_TEST
Putting aside the higher level alur tests apparently failing (will look into that later) can anyone tell me why the floating comparison seems to ignore the sign bit?Code:make check.run
...
Running suite(s): ALU
../tests/check_alu.c:653: test_alup__cmp_floating_incremental_fn() 0.000000 <> 0.000000 = 1 (source: 64 <> 0), got -1
../tests/check_alu.c:664: test_alup__cmp_floating_incremental_fn() &_VALUE1 = 1 -1018 0000000101 0000000000000000000000000000000000000000000000000000
../tests/check_alu.c:665: test_alup__cmp_floating_incremental_fn() &_VALUE2 = 0 -2047 0000000000 0000000000000000000000000000000000000000000000000000
97%: Checks: 2560, Failures: 54, Errors: 0
../tests/check_alu.c:424:F:Core:test_alur_set_floating:0: Assertion 'memcmp( V, &src_val, sizeof(double) ) == 0' failed
...
Compilation finished successfully.