I guess you already know that 98932 (the answer you get) is half 131264 (the answer you expect)Code:../tests/test_alu.c:199: modify() 0x00000000DEADC0DE / 0x0000000000000BAD, Expected 0x0000000000131264, Got 0x0000000000098932, op = '/'
I guess you already know that 98932 (the answer you get) is half 131264 (the answer you expect)Code:../tests/test_alu.c:199: modify() 0x00000000DEADC0DE / 0x0000000000000BAD, Expected 0x0000000000131264, Got 0x0000000000098932, op = '/'
Here's a bit of a bug in your division code:
Note how you clear 'num' with "alu_reg_clr( alu, num )" and the you test to see if num is below zero. It will always be zero.Code:if ( ret == 0 ) { (void)alu_reg_clr( alu, num ); <<<< A num.node %= alu_used( alu ); val.node %= alu_used( alu ); rem.node %= alu_used( alu ); tmp.node %= alu_used( alu ); nNeg = alu_reg_below0( alu, num ); <<< B vNeg = alu_reg_below0( alu, val );
Instead you want to clear out num after you have checked if it is below zero:
I also think thatCode:if ( ret == 0 ) { num.node %= alu_used( alu ); val.node %= alu_used( alu ); rem.node %= alu_used( alu ); tmp.node %= alu_used( alu ); nNeg = alu_reg_below0( alu, num ); vNeg = alu_reg_below0( alu, val ); (void)alu_reg_clr( alu, num ); <<<< THIS CHANGE
might need to beCode:if ( vNeg ) alu_reg_neg( alu, val );
[code]Code:if ( nNeg ^ nNeg) alu_reg_neg( alu, val );
As a negative number divided by a negative number is a positive result.
Also in alu_math.h
it works on the following process..Code:int_t alu_reg_not( alu_t *alu, alu_reg_t num ) { alu_bit_t n, e; void *part; size_t i, stop, mask, mask_init, mask_last; if ( alu ) { num.node %= alu_used( alu ); part = alu_reg_data( alu, num ); n = alu_bit_set_bit( part, num.from ); e = alu_bit_set_bit( part, num.upto - 1 ); mask = 0; mask = mask_init = mask_last = ~mask; mask_init <<= n.pos; mask_last <<= (bitsof(uintmax_t) - e.pos) - 1; stop = e.seg - n.seg; *(n.ptr) ^= SET2IF( stop, mask_init, mask_init & mask_last ); for ( i = 1; i < stop; ++i ) n.ptr[i] = ~(n.ptr[i]); *(e.ptr) ^= SET1IF( stop, mask_last ); return 0; } return alu_err_null_ptr( "alu" ); }
- flip bits up to the next word boundary.
- flip words while we still can flip a full word's worth of bits.
- flip the remaining bits in the last work.
I'm not sure this will work if you are only flipping a few bits - it needs to span at least one word boundary. It doesn't seem intuitively right - you might want to look at it more closely.
Wow, either you burning the midnight oil or we live in vastly different timezones, GMT+0 (London) here, anyways I'll start with this post
Nice catch, it also means there's another bug in which rem receives negative numbers, so I'll fix that before I try to respond to any more posts
In this case you're wrong, val is number being divide by, I only flip it to positive to make division behave correctly, I flip it back after so that it is left the same as we got it, num is where that rule you stated applies
Edit: done
Last edited by awsdert; 09-25-2020 at 01:49 AM.
I added that to the tests but I've seen no failures in it despite the test iterating through every bit each segment would have, however I have just noticed a subtle bug there so I will rectify that now
Edit: Forgot to pay attention to the macro, there was no subtle bug
Last edited by awsdert; 09-25-2020 at 02:26 AM.
That... I honestly have no idea why it is happening, at 1st I though it was a missing #endif but then that would cause my compiles to fail as well, it would even cause that different compile command you gave to fail, only thing I think of is maybe the order of the flags?
My updated output:
Fixes - after the loop in the divide function, you need to shift any leftover bits:Code:../tests/test_alu.c:921: main() Pre-allocating 64 ALU registers... ../tests/test_alu.c:371: bitwise() 'Checking Bitwise Operations...' ../tests/test_alu.c:372: bitwise() '===========================================' ../tests/test_alu.c:388: bitwise() 'Shifting values...' ../tests/test_alu.c:389: bitwise() '===========================================' ../tests/test_alu.c:405: bitwise() 'Rotating values...' ../tests/test_alu.c:406: bitwise() '===========================================' ../tests/test_alu.c:431: mathmatical() 'Checking Mathematic Operations...' ../tests/test_alu.c:432: mathmatical() '===========================================' ../tests/test_alu.c:812: print_value() 'Printing values...' ../tests/test_alu.c:813: print_value() '===========================================' ../tests/test_alu.c:566: reg_print_value() 'Testing alu_lit2reg() & alu_reg2str()' ../tests/test_alu.c:567: reg_print_value() '-------------------------------------' ../tests/test_alu.c:603: reg_print_value() Expected = '123', Got = '123' ../tests/test_alu.c:626: uint_print_value() 'Testing alu_str2uint() & alu_uint2str()' ../tests/test_alu.c:627: uint_print_value() '---------------------------------------' ../tests/test_alu.c:640: uint_print_value() Error 0xFFFFFFFF -1 'Unknown error -1' ../tests/test_alu.c:858: print_value() Error 0xFFFFFFFF -1 'Unknown error -1' ../tests/test_alu.c:964: main() Error 0xFFFFFFFF -1 'Unknown error -1'
Fix for the sign being wrong on the result of division:Code:alu_reg__shl( alu, num, tmp, bits ); *(n.ptr) |= n.mask; bits = 0; } } + if(bits != 0) + alu_reg__shl( alu, num, tmp, bits ); if ( seg.from > rem.from ) alu_reg__shl( alu, num, tmp, bits );
in alu_reg_rem, the wrong thing is moved into the result:Code:if ( nNeg ) alu_reg_neg( alu, rem ); + if ( vNeg ^ nNeg) alu_reg_neg( alu, val ); return ret;
Oh, I'm in GMT+12... so we are 12 hours apart...Code:alu_reg_init( alu, REM, nodes[0], 0 ); alu_reg_init( alu, TMP, nodes[1], 0 ); ret = alu_reg_divide( alu, NUM, VAL, REM, TMP ); + (void)alu_reg_mov( alu, NUM, REM ); alu_rem_reg_nodes( alu, nodes, 2 ); return ret; }
Last edited by hamster_nz; 09-25-2020 at 03:44 AM.
Ah so that'll be why we end up with lot's a posts before we get communication, btw again you're assuming val is the result, val is NOT the result, num is the result, switched out my seg.from > rem.from for bits but I'm not adding another if statement for the same task like you did. Nice catch on the alu_reg_rem() bug, anyways I'm currently hitting a strange bug with alu_reg__shift() in that somehow during the retrieval of VAL into by the value of VAL is filled into NUM
Tried following the call chain of alu_uint_get_raw() but didn't spot anything that would cause the node of VAL to suddenly change to NUM's nodeCode:int_t alu_reg__shift ( alu_t *alu , alu_reg_t NUM , alu_reg_t VAL , alu_reg_t TMP , func_alu_reg__shift_t _shift ) { int ret, cmp; uintmax_t by; if ( alu ) { by = NUM.upto - NUM.from; NUM.node %= alu_used( alu ); VAL.node %= alu_used( alu ); TMP.node %= alu_used( alu ); alu_uint_set_raw( alu, TMP.node, by ); cmp = alu_reg_cmp( alu, VAL, TMP ); if ( cmp < 0 ) { alu_print_reg( "NUM#1", alu, NUM, 0, 1 ); alu_print_reg( "VAL#1", alu, VAL, 0, 1 ); alu_uint_get_raw( alu, VAL.node, &by ); alu_print_reg( "NUM#2", alu, NUM, 0, 1 ); ret = _shift( alu, NUM, TMP, by ); } else { ret = _shift( alu, NUM, TMP, -1 ); } return ret; } return alu_err_null_ptr("alu"); }
Edit: Found out that somehow tmp in alu_reg_get_raw() gets the same node index as NUM.node of alu_reg__shift(), not been able to identify why, nor why it only shows up in test_alu.c and not check_alu.c
Edit: Gotta go to work, assuming you respond in your morning I'll probably be responding in my morning rather than my tonight
Last edited by awsdert; 09-25-2020 at 05:28 AM.
Found the source of the error, seems when I added a node in modify() for TMP I forgot to tell alu_get_reg_nodes() the new array size so TMP was initiated with the value 0, rectified along with a bug I spotted while hunting for the problem
Gonna go to bed, thought I'd post my current problem to see if any suggestions or fixes are posted by the time I get up in the morning. All math functions seem to be working fine, added some checks for node value of 0 to prevent corruption of active nodes flags, the current problem however is converting plain integers to string, here's the relevant output:
And here's the function:Code:make check cd ../ && make --no-print-directory check #MAKECMDGOALS=check cd mak && make -j 1 --no-print-directory -f main.mak check PRJ_LIB_NAME=alu Checking 3rd Party libraries are upto date cd '../cloned/unic' && git fetch && git pull Finished checking PRJ_DST_BIN=check_alu.AppImage PRJ_DST_LIB=libalu.so cc -D NDEBUG -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK -o ../src/alu_bit.o -c ../src/alu_bit.c cc -D NDEBUG -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK -o ../src/alu_fpn.o -c ../src/alu_fpn.c cc -D NDEBUG -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK -o ../src/alu_int.o -c ../src/alu_int.c cc -D NDEBUG -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK -o ../src/alu_main.o -c ../src/alu_main.c cc -D NDEBUG -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK -o ../src/alu_math.o -c ../src/alu_math.c cc -D NDEBUG -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK -o ../src/alu_mem.o -c ../src/alu_mem.c cc -D NDEBUG -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK -o ../src/alu_uint.o -c ../src/alu_uint.c cc -D NDEBUG -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK -o ../src/alu_vec.o -c ../src/alu_vec.c cc -D NDEBUG -fPIC -shared -o ../lib/libalu.so ../src/alu_bit.o ../src/alu_fpn.o ../src/alu_int.o ../src/alu_main.o ../src/alu_math.o ../src/alu_mem.o ../src/alu_uint.o ../src/alu_vec.o -Wl,-rpath,../lib cc -D NDEBUG -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK -o ../tests/check_alu.o -c ../tests/check_alu.c cc -D NDEBUG -fPIE -L ../lib -o ../bin/check_alu.AppImage ../tests/check_alu.o -Wl,-rpath,../lib -l alu -l check ../bin/check_alu.AppImage Running unit tests under 'check' test suite Running suite(s): ALU ../tests/check_alu.c:12: wrChar() wrChar('3',0x7ffd2e28dd70) ../tests/check_alu.c:12: wrChar() wrChar('6',0x7ffd2e28dd70) ../tests/check_alu.c:30: flip() alustr = '6', taken = 1 0%: Checks: 1, Failures: 1, Errors: 0 ../tests/check_alu.c:534:F:Core:test_alu_create:0: Expected '64', Got '6' rm ../src/alu_math.o ../src/alu_main.o ../src/alu_uint.o ../src/alu_mem.o ../src/alu_int.o ../src/alu_bit.o ../src/alu_vec.o ../src/alu_fpn.o ../tests/check_alu.o make[2]: *** [main.mak:99: check] Error 1 make[1]: *** [makefile:10: check] Error 2 make: *** [makefile:4: check] Error 2 Compilation failed.
If I get lucky and someone spotted the source of the bug by morning, that's great, if not then too bad but no biggy, not particularly banking on it to begin with. And with that, good night allCode:int_t alu_reg2str( alu_t *alu, alu_dst_t dst, alu_reg_t src, alu_base_t base ) { alu_reg_t NUM, VAL, REM, TMP; int ret; size_t digit = 0, b; uint_t nodes[ALU_BASE_COUNT] = {0}; bool neg; char *base_str = base.lowercase ? ALU_BASE_STR_0toztoZ : ALU_BASE_STR_0toZtoz; src.upto = LOWEST( alu_bits_perN( alu ), src.upto ); if ( !(dst.next) || !(dst.flip) ) { ret = EADDRNOTAVAIL; alu_error(ret); return ret; } if ( !base.base ) base.base = 10; if ( base.base > strlen(base_str) ) { ret = ERANGE; alu_error(ret); return ret; } ret = alu_get_reg_nodes( alu, nodes, ALU_BASE_COUNT, 0 ); if ( ret != 0 ) { alu_error( ret ); return ret; } alu_reg_init( alu, NUM, nodes[ALU_BASE_NUM], 0 ); alu_reg_init( alu, VAL, nodes[ALU_BASE_VAL], 0 ); alu_reg_init( alu, REM, nodes[ALU_BASE_REM], 0 ); alu_reg_init( alu, TMP, nodes[ALU_BASE_TMP], 0 ); neg = alu_reg_below0( alu, src ); alu_reg_mov( alu, NUM, src ); alu_set_raw( alu, VAL.node, base.base, 0 ); if ( neg ) (void)alu_reg_neg( alu, NUM ); while ( alu_reg_cmp( alu, NUM, VAL ) >= 0 ) { ret = alu_reg_divide( alu, NUM, VAL, REM, TMP ); if ( ret == ENODATA ) { alu_error( ret ); goto fail; } if ( digit == 3 ) { switch ( base.digsep ) { case '\'': case '_': case ',': ret = dst.next( base.digsep, dst.dst ); if ( ret != 0 ) goto fail; } digit = 0; } alu_reg_get_raw( alu, TMP, &b, sizeof(size_t) ); ret = dst.next( base_str[b], dst.dst ); if ( ret != 0 ) { alu_error(ret); goto fail; } ++digit; } alu_reg_get_raw( alu, NUM, &b, sizeof(size_t) ); ret = dst.next( base_str[b], dst.dst ); if ( ret != 0 ) { alu_error(ret); goto fail; } dst.flip( dst.dst ); fail: alu_rem_reg_nodes( alu, nodes, ALU_BASE_COUNT ); return ret; }
Welp, resolved that error just now, I don't have any serious ideas regarding hamster_nz's compile issues so I'll leave that on the back burner, time to go back to alu_reg_mov() and finish the float to integer and vise versa stuff
Gonna get ready for work then start working on integer to float conversion, in the meantime if anyone feels like looking for bugs in my float to integer conversion, here's the function:
Code:int alu_reg_mov ( alu_t *alu, alu_reg_t DST, alu_reg_t SRC ) { int ret; void *D, *S; uint_t tmp = 0; alu_bit_t d, s; size_t ndiff, vdiff, upto, exp, bias; bool neg, Inf = false; alu_reg_t DEXP, DMAN, SEXP, SMAN, TMP; ret = alu_reg_clr( alu, DST ); if ( ret == 0 ) { DST.node %= alu_used( alu ); SRC.node %= alu_used( alu ); /* Check for +/- */ neg = alu_reg_below0( alu, SRC ); if ( alu_reg_floating( SRC ) ) { alu_reg_init( alu, SEXP, SRC.node, 0 ); alu_reg_init( alu, SMAN, SRC.node, 0 ); SEXP.upto = SRC.upto - 1; SEXP.from = SRC.from + SRC.mant; SMAN.upto = SRC.from + SRC.mant; SMAN.from = SRC.from; bias = -1; bias <<= (SEXP.upto - SEXP.from); bias = ~bias; ret = alu_reg_get_raw( alu, SEXP, &exp, sizeof(size_t) ); if ( ret != 0 ) { alu_error(ret); return ret; } Inf = (exp == bias); if ( alu_reg_floating( DST ) ) { alu_reg_init( alu, DEXP, DST.node, 0 ); DEXP.upto = DST.upto - 1; DEXP.from = DST.from + DST.mant; DMAN.upto = DST.from + DST.mant; DMAN.from = DST.from; D = alu_reg_data( alu, DST ); /* Set +/- */ d = alu_bit_set_bit( D, DEXP.upto ); *(d.ptr) &= ~(d.mask); *(d.ptr) |= (neg * d.mask); /* Simplify code and pass on duties to another instance, added * bonus of setting Infinity if >= Exponent limit */ alu_reg_mov( alu, DEXP, SEXP ); ndiff = DMAN.upto - DMAN.from; vdiff = SMAN.upto - SMAN.from; /* Make sure we copy the upper bits of the src mantissa */ SMAN.from = SMAN.upto - LOWEST( ndiff, vdiff ); /* Whether it is NaN or a fittable number copying the mantissa * is fine as long as we make sure it was not Infinity to begin * with */ return Inf ? alu_reg_clr( alu, DMAN ) : alu_reg_mov( alu, DMAN, SMAN ); } else if ( Inf ) { s = alu_reg_end_bit( alu, SMAN ); /* NaN cannot be recorded by an integer, use 0 instead */ if ( *(s.ptr) & s.mask ) return alu_reg_clr( alu, DST ); /* Infinity cannot be recorded by an integer, * use min/max instead */ (void)alu_reg_set_max( alu, DST ); return neg ? alu_reg_not( alu, DST ) : 0; } /* Check if exponent is negative - meaning the number is between * 0 & 1, if it is then just set the integer to 0 */ bias >>= 1; if ( exp < bias ) return alu_reg_clr( alu, DST ); exp -= bias; ndiff = DST.upto - DST.from; /* Check if number is to big to fit in the integer */ if ( (exp + SMAN.mant + 1) > ndiff ) { (void)alu_reg_set_max( alu, DST ); return neg ? alu_reg_not( alu, DST ) : 0; } /* alu_reg_get_raw() will have retrieved and released a register, * since that succeeded will end up with that register here as the * register was not released from memory, only usage */ /* Mantissas have an assumed bit, * in this case it's value can only be 1 */ vdiff = 1; (void)alu_reg_set_raw( alu, DST, &vdiff, 1, 0 ); (void)alu_get_reg_node( alu, &tmp, 0 ); alu_reg_init( alu, TMP, tmp, 0 ); /* These cannot possibly fail at this point */ (void)alu_reg__shl( alu, DST, TMP, SRC.mant ); (void)alu_reg__or( alu, DST, SMAN ); (void)alu_reg__shl( alu, DST, TMP, exp - bias ); alu_rem_reg_node( alu, &tmp ); return 0; } ndiff = DST.upto - DST.from; vdiff = SRC.upto - SRC.from; D = alu_reg_data( alu, DST ); S = alu_reg_data( alu, SRC ); d = alu_bit_set_bit( D, DST.from ); s = alu_bit_set_bit( S, SRC.from ); upto = DST.from + LOWEST( ndiff, vdiff ); for ( ; d.bit < upto; alu_bit_inc(&d), alu_bit_inc(&s) ) { *(d.ptr) &= ~(d.mask); *(d.ptr) |= SET1IF( *(s.ptr) & s.mask, d.mask ); } for ( ; d.bit < DST.upto; alu_bit_inc(&d) ) { *(d.ptr) &= ~(d.mask); *(d.ptr) |= SET1IF( neg, d.mask ); } return 0; } alu_error( ret ); return ret; }
K, there was a bug but I've fixed that now, I gotta head off to work now, I also have work 2mw so won't be doing any fixes or searching for bugs until after work 2mw. In the off chance someone feels like looking through here's the function with a spot I think is buggy marked with a comment
Code:int alu_reg_mov ( alu_t *alu, alu_reg_t DST, alu_reg_t SRC ) { int ret; void *D, *S; uint_t tmp = 0; alu_bit_t d, s; size_t ndiff, vdiff, nman_dig, vman_dig, upto, exp, bias; bool neg, Inf = false; alu_reg_t DEXP, DMAN, SEXP, SMAN, TMP; ret = alu_reg_clr( alu, DST ); if ( ret == 0 ) { DST.node %= alu_used( alu ); SRC.node %= alu_used( alu ); ndiff = DST.upto - DST.from; vdiff = SRC.upto - SRC.from; /* Check for +/- */ neg = alu_reg_below0( alu, SRC ); if ( alu_reg_floating( SRC ) ) { alu_reg_init( alu, SEXP, SRC.node, 0 ); alu_reg_init( alu, SMAN, SRC.node, 0 ); vman_dig = alu_man_dig(vdiff); SEXP.upto = SRC.upto - 1; SMAN.upto = SEXP.from = SRC.from + vman_dig; SMAN.from = SRC.from; bias = -1; bias <<= (SEXP.upto - SEXP.from); bias = ~bias; ret = alu_reg_get_raw( alu, SEXP, &exp, sizeof(size_t) ); if ( ret != 0 ) { alu_error(ret); return ret; } Inf = (exp == bias); if ( alu_reg_floating( DST ) ) { alu_reg_init( alu, DEXP, DST.node, 0 ); alu_reg_init( alu, DMAN, DST.node, 0 ); nman_dig = alu_man_dig( ndiff ); DEXP.upto = DST.upto - 1; DMAN.upto = DEXP.from = DST.from + nman_dig; DMAN.from = DST.from; D = alu_reg_data( alu, DST ); /* Set +/- */ d = alu_bit_set_bit( D, DEXP.upto ); *(d.ptr) &= ~(d.mask); *(d.ptr) |= (neg * d.mask); /* Simplify code and pass on duties to another instance, added * bonus of setting Infinity if >= Exponent limit */ alu_reg_mov( alu, DEXP, SEXP ); ndiff = DMAN.upto - DMAN.from; vdiff = SMAN.upto - SMAN.from; /* Make sure we copy the upper bits of the src mantissa */ SMAN.from = SMAN.upto - LOWEST( ndiff, vdiff ); /* Whether it is NaN or a fittable number copying the mantissa * is fine as long as we make sure it was not Infinity to begin * with */ return Inf ? alu_reg_clr( alu, DMAN ) : alu_reg_mov( alu, DMAN, SMAN ); } if ( Inf ) { s = alu_reg_end_bit( alu, SMAN ); /* NaN cannot be recorded by an integer, use 0 instead */ if ( *(s.ptr) & s.mask ) return alu_reg_clr( alu, DST ); /* Infinity cannot be recorded by an integer, * use min/max instead */ (void)alu_reg_set_max( alu, DST ); return neg ? alu_reg_not( alu, DST ) : 0; } /* Check if exponent is negative - meaning the number is between * 0 & 1, if it is then just set the integer to 0 */ bias >>= 1; if ( exp < bias ) return alu_reg_clr( alu, DST ); exp -= bias; /* Check if number is to big to fit in the integer */ if ( (exp + vman_dig + 1) > ndiff ) { (void)alu_reg_set_max( alu, DST ); return neg ? alu_reg_not( alu, DST ) : 0; } /* alu_reg_get_raw() will have retrieved and released a register, * since that succeeded will end up with that register here as the * register was not released from memory, only usage */ /* Mantissas have an assumed bit, * in this case it's value can only be 1 */ ndiff = 1; (void)alu_reg_set_raw( alu, DST, &ndiff, 1, 0 ); (void)alu_get_reg_node( alu, &tmp, 0 ); alu_reg_init( alu, TMP, tmp, 0 ); /* These cannot possibly fail at this point */ (void)alu_reg__shl( alu, DST, TMP, vman_dig ); (void)alu_reg__or( alu, DST, SMAN ); (void)alu_reg__shl( alu, DST, TMP, exp ); alu_rem_reg_node( alu, &tmp ); return 0; } if ( alu_reg_floating( DST ) ) { alu_reg_init( alu, DEXP, DST.node, 0 ); alu_reg_init( alu, DMAN, DST.node, 0 ); nman_dig = alu_man_dig(ndiff); DEXP.upto = DST.upto - 1; DMAN.upto = DEXP.from = DST.from + nman_dig; DMAN.from = DST.from; bias = -1; bias <<= (DEXP.upto - DEXP.from); bias = ~bias; bias >>= 1; s = alu_reg_end_bit( alu, SRC ); if ( s.bit >= bias ) { D = alu_reg_data( alu, DST ); d = alu_bit_set_bit( D, DEXP.upto ); /* Set +/- */ *(d.ptr) &= ~(d.mask); *(d.ptr) |= SET1IF( neg, d.mask ); /* Set Infinity */ alu_reg_set_max( alu, DEXP ); /* Clear mantissa so not treated as NaN */ return alu_reg_clr( alu, DMAN ); } /* FIXME: I think there is a bug here */ exp = bias + s.bit; ret = alu_reg_set_raw( alu, DEXP, &exp, sizeof(size_t), 0 ); return alu_reg_mov( alu, DMAN, SRC ); } D = alu_reg_data( alu, DST ); S = alu_reg_data( alu, SRC ); d = alu_bit_set_bit( D, DST.from ); s = alu_bit_set_bit( S, SRC.from ); upto = DST.from + LOWEST( ndiff, vdiff ); for ( ; d.bit < upto; alu_bit_inc(&d), alu_bit_inc(&s) ) { *(d.ptr) &= ~(d.mask); *(d.ptr) |= SET1IF( *(s.ptr) & s.mask, d.mask ); } for ( ; d.bit < DST.upto; alu_bit_inc(&d) ) { *(d.ptr) &= ~(d.mask); *(d.ptr) |= SET1IF( neg, d.mask ); } return 0; } alu_error( ret ); return ret; }
I've been trying an trying to figure this one out myself but have not found the source of the issue as yet, basically sometimes when acquiring new registers the ALU just overwrites the boolean that states if an allocated register is in use or not, I've even resorted to using a dedicated function for setting and getting that boolean yet still no avail, I've checked that function thoroughly with this:
The function itself looks like this:Code:START_TEST( test_alu_set_bit ) { ck_assert( alu_upto(alu) > 0 ); uintmax_t num[] = {0,0}, val[] = {0,0}, i = _i; if ( i >= bitsof(uintmax_t) ) num[1] = 1uLL << _i % bitsof(uintmax_t); else num[0] = 1uLL << _i; alu_set_bit( val, _i, 1 ); ck_assert_msg ( memcmp( num, val, sizeof(uintmax_t) * 2 ) == 0 , "Expected 0x%016jX%016jX, Got 0x%016jX%016jX" , num[0], num[1] , val[0], val[1] ); } END_TEST
The function I tracked the loss of state to is this one so far:Code:alu_bit_t alu_bit( uintmax_t *ptr, size_t bit ) { alu_bit_t alu_bit = {0}; alu_bit.bit = bit; alu_bit.pos = bit % bitsof(uintmax_t); alu_bit.seg = bit / bitsof(uintmax_t); alu_bit.ptr = ptr + (alu_bit.seg); alu_bit.mask = UNIC_SIZE_C(1) << alu_bit.pos; return alu_bit; } bool alu_get_bit( uintmax_t *ptr, size_t bit ) { alu_bit_t b = alu_bit( ptr, bit ); return !!(*(b.ptr) & b.mask); } void alu_set_bit( uintmax_t *ptr, size_t bit, bool val ) { alu_bit_t b = alu_bit( ptr, bit ); *(b.ptr) &= ~(b.mask); *(b.ptr) |= SET1IF( val, b.mask ); }
At this point I'm seriously considering adding a temporary parameter to this function just to track the boolean until it clears inappropriately like in my tests. Before I do that does anyone have any ideas what might be happening? As a reminder the link to current code is in my signature.Code:#define alu_get_active( alu, reg ) alu_get_bit( (void*)alu_valid(alu), reg ) #define alu_clr_active( alu, reg ) alu_set_bit( (void*)alu_valid(alu), reg, 0 ) #define alu_set_active( alu, reg ) alu_set_bit( (void*)alu_valid(alu), reg, 1 ) ... uint_t alu_get_reg_node( alu_t *alu, size_t Nsize ) { uint_t count = 0, index, reg; if ( alu ) { index = ALU_REG_ID_NEED; count = alu_used( alu ); for ( reg = index; index < count; ++index ) { reg = index; count = SET1IF( alu_get_active( alu, index ), count ); } index = HIGHEST( count, reg ); count = HIGHEST( index + 1, alu_used(alu) ); Nsize = HIGHEST( Nsize, alu_Nsize( alu ) ); reg = HIGHEST( count, alu_upto( alu ) ); alu_errno(alu) = alu_setup_reg( alu, reg, Nsize ); if ( alu_errno(alu) ) { alu_error( alu_errno(alu) ); return 0; } alu_used( alu ) = count; (void)memset( alu_data( alu, index ), 0, Nsize ); alu_set_active( alu, index ); return index; } (void)alu_err_null_ptr( "alu" ); return 0; }
Found the problem, when I switched to using the 1st register for storing active state booleans I forgot to change the starting index for alu_set_constants(), fixed and now getting behavior I expect