# Thread: I can't spot my mistake...

1. 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)

2. Here's a bit of a bug in your division code:

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 );```
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.

Instead you want to clear out num after you have checked if it is below zero:

Code:
```        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```
I also think that

Code:
```                if ( vNeg )
alu_reg_neg( alu, val );```
might need to be

Code:
```                if ( nNeg ^ nNeg)
alu_reg_neg( alu, val );```
[code]

As a negative number divided by a negative number is a positive result.

3. Also in alu_math.h

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" );
}```
it works on the following process..

- 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.

4. 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
Originally Posted by hamster_nz
Here's a bit of a bug in your division code:

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 );```
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.

Instead you want to clear out num after you have checked if it is below zero:

Code:
```        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```
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

Originally Posted by hamster_nz
I also think that

Code:
```                if ( vNeg )
alu_reg_neg( alu, val );```
might need to be

Code:
```                if ( nNeg ^ nNeg)
alu_reg_neg( alu, val );```
[code]

As a negative number divided by a negative number is a positive result.
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

5. Originally Posted by hamster_nz
Also in alu_math.h

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" );
}```
it works on the following process..

- 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.
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

6. Originally Posted by hamster_nz
A clean clone still doesn't work for me:

Code:
```\$ git clone GitHub - awsdert/alu: Library modeled after the Arithmetic Logic Unit built into CPUs
Cloning into 'alu'...
remote: Enumerating objects: 396, done.
remote: Counting objects: 100% (396/396), done.
remote: Compressing objects: 100% (377/377), done.
remote: Total 396 (delta 277), reused 126 (delta 15), pack-reused 0
Receiving objects: 100% (396/396), 138.31 KiB | 362.00 KiB/s, done.
Resolving deltas: 100% (277/277), done.
\$ cd alu/
\$ make build
#MAKECMDGOALS=build
cd mak && make -j 1 --no-print-directory -f main.mak build
PRJ_LIB_NAME=alu

Cloning into 'unic'...
remote: Enumerating objects: 193, done.
remote: Counting objects: 100% (193/193), done.
remote: Compressing objects: 100% (157/157), done.
remote: Total 193 (delta 105), reused 112 (delta 26), pack-reused 0
Receiving objects: 100% (193/193), 60.84 KiB | 293.00 KiB/s, done.
Resolving deltas: 100% (105/105), done.

Checking 3rd Party libraries are upto date
cd '../cloned/unic' && git fetch && git pull
Finished checking
PRJ_DST_BIN=test_alu.AppImage
PRJ_DST_LIB=libalu.so
mkdir ../bin
mkdir ../lib
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
In file included from /usr/include/stdio.h:41:0,
from ../include/alu.h:11,
from ../src/alu_vec.c:1:
/usr/include/x86_64-linux-gnu/bits/libio.h:466:58: error: expected declaration specifiers or ‘...’ before ‘)’ token
extern _IO_ssize_t _IO_padn (_IO_FILE *, int, _IO_ssize_t);
^
main.mak:147: recipe for target '../src/alu_vec.o' failed
make[1]: *** [../src/alu_vec.o] Error 1
makefile:9: recipe for target 'build' failed
make: *** [build] Error 2```
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?

7. My updated output:

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'```
Fixes - after the loop in the divide function, you need to shift any leftover bits:

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 );```
Fix for the sign being wrong on the result of division:
Code:
```                if ( nNeg )
alu_reg_neg( alu, rem );

+              if ( vNeg ^ nNeg)
alu_reg_neg( alu, val );

return ret;```
in alu_reg_rem, the wrong thing is moved into the result:

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;
}```
Oh, I'm in GMT+12... so we are 12 hours apart...

8. Originally Posted by hamster_nz
My updated output:

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'```
Fixes - after the loop in the divide function, you need to shift any leftover bits:

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 );```
Fix for the sign being wrong on the result of division:
Code:
```                if ( nNeg )
alu_reg_neg( alu, rem );

+              if ( vNeg ^ nNeg)
alu_reg_neg( alu, val );

return ret;```
in alu_reg_rem, the wrong thing is moved into the result:

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;
}```
Oh, I'm in GMT+12... so we are 12 hours apart...
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
Code:
```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");
}```
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 node

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

9. 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

10. 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:
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.```
And here's the function:
Code:
```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;
}```
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 all

11. 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

12. 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;
}```

13. 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;
}```

14. 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:
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 itself looks like this:
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 );
}```
The function I tracked the loss of state to is this one so far:
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;
}```
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.

15. 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

Popular pages Recent additions