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

  1. #91
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    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. #92
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    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. #93
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    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. #94
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    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
    Quote Originally Posted by hamster_nz View Post
    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

    Quote Originally Posted by hamster_nz View Post
    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. #95
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by hamster_nz View Post
    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. #96
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by hamster_nz View Post
    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. #97
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    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...
    Last edited by hamster_nz; 09-25-2020 at 03:44 AM.

  8. #98
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by hamster_nz View Post
    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. #99
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    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. #100
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    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. #101
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    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. #102
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    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. #103
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    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. #104
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    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. #105
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    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 subscribe to a feed

Similar Threads

  1. can anyone help to spot mistake in the code
    By chess_queen in forum C Programming
    Replies: 1
    Last Post: 10-21-2012, 10:37 AM
  2. Can you spot my mistake?
    By Brewer in forum C Programming
    Replies: 13
    Last Post: 11-12-2006, 12:50 PM
  3. going to a certain spot in a file...
    By agerealm in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2002, 02:31 AM

Tags for this Thread