Is it really necessary to use non-standard headers like uchar.h and non-standard types like ssize_t ?
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.Originally Posted by christop
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
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.