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

  1. #136
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,100
    I think I fixed it but hitting an unexpected segfault before I can check, I can't even deduce where it might be coming from because it seems some local variables relied upon at the point of the segfault have somehow been 0'd out between the call to the add function (which is right above the line the segfault occurs on) and the usage of the local variable:
    Code:
    	ret = alu_reg_add( alu, NUM, VAL ); // between this call and the next line both NUM and VAL are somehow 0'd
    	
    	N = alu_reg_data( alu, NUM );
    Code:
    make check.run
    cd ../ && make --no-print-directory check.run
    #MAKECMDGOALS=check.run
    cd mak && make -j 1 --no-print-directory -f main.mak check.run
    PRJ_GOALS=check
    PRJ_LIB_NAME=alu_d
    Checking 3rd Party libraries are upto date
    cd '../cloned/unic' && git fetch && git pull
    Finished checking
    PRJ_DST_BIN=check_alu_d.AppImage
    PRJ_DST_LIB=libalu_d.so
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_bit_d.o -c ../src/alu_bit.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_fpn_d.o -c ../src/alu_fpn.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_int_d.o -c ../src/alu_int.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_main_d.o -c ../src/alu_main.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_math_d.o -c ../src/alu_math.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_mem_d.o -c ../src/alu_mem.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_uint_d.o -c ../src/alu_uint.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_vec_d.o -c ../src/alu_vec.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -shared  -o ../lib/libalu_d.so ../src/alu_bit_d.o ../src/alu_fpn_d.o ../src/alu_int_d.o ../src/alu_main_d.o ../src/alu_math_d.o ../src/alu_mem_d.o ../src/alu_uint_d.o ../src/alu_vec_d.o -Wl,-rpath,../lib
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../tests/check_alu_d.o -c ../tests/check_alu.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIE -L ../lib  -o ../bin/check_alu_d.AppImage ../tests/check_alu_d.o -Wl,-rpath,../lib -l alu_d -l check  -l rt -l pthread -l m
    gdb -ex run  ../bin/check_alu_d.AppImage
    GNU gdb (GDB) 9.2
    Copyright (C) 2020 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    Type "show copying" and "show warranty" for details.
    This GDB was configured as "x86_64-pc-linux-gnu".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
        <http://www.gnu.org/software/gdb/documentation/>.
    For help, type "help".
    Type "apropos word" to search for commands related to "word"...
    Reading symbols from ../bin/check_alu_d.AppImage...
    Starting program: /mnt/MEDIA/HOME/github/alu/bin/check_alu_d.AppImage
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/usr/lib/libthread_db.so.1".
    Running suite(s): ALU
    Program received signal SIGSEGV, Segmentation fault.
    0x0000555555562f24 in test_alu_reg_add_floating_fn (_i=0)
        at ../tests/check_alu.c:958
    958		N = alu_reg_data( alu, NUM );
    (gdb) quit
    A debugging session is active.
    	Inferior 1 [process 14337] will be killed.
    Quit anyway? (y or n) [answered Y; input not from terminal]
    rm ../src/alu_int_d.o ../src/alu_math_d.o ../tests/check_alu_d.o ../src/alu_main_d.o ../src/alu_uint_d.o ../src/alu_fpn_d.o ../src/alu_bit_d.o ../src/alu_mem_d.o ../src/alu_vec_d.o
    Compilation finished successfully.
    I've tried debugging but I'm honestly lost on where to find the bug, if anyone has any ideas from looking at the project code I would appreciate you mentioning it even if it turns out to be a dead end.

  2. #137
    Registered User
    Join Date
    Sep 2020
    Posts
    83
    Can't debug what I can't build:

    Code:
    ...
    cc -D NDEBUG -O3  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../tests/test_alu.o -c ../tests/test_alu.c
    ../tests/test_alu.c: In function ‘reg_compare’:
    ../tests/test_alu.c:27:2: warning: implicit declaration of function ‘alu_reg_init’; did you mean ‘alu_reg_inc’? [-Wimplicit-function-declaration]
      alu_reg_init( alu, NUM, nodes[0], info );
      ^~~~~~~~~~~~
      alu_reg_inc
    ../tests/test_alu.c:32:2: warning: ‘NUM.node’ may be used uninitialized in this function [-Wmaybe-uninitialized]
      alu_int_set_raw( alu, NUM.node, _num );
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ../tests/test_alu.c:33:2: warning: ‘VAL.node’ may be used uninitialized in this function [-Wmaybe-uninitialized]
      alu_int_set_raw( alu, VAL.node, _val );
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ../tests/test_alu.c: In function ‘modify’:
    ../tests/test_alu.c:83:2: warning: ‘VAL.node’ may be used uninitialized in this function [-Wmaybe-uninitialized]
      alu_int_set_raw( alu, VAL.node, _val );
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    cc -D NDEBUG -O3  -fPIE -L ../lib  -o ../bin/test_alu.AppImage ../tests/test_alu.o -Wl,-rpath,../lib -l alu 
    ../tests/test_alu.o: In function `reg_compare':
    test_alu.c:(.text+0x173): undefined reference to `alu_reg_init'
    test_alu.c:(.text+0x1a0): undefined reference to `alu_reg_init'
    ../tests/test_alu.o: In function `modify':
    test_alu.c:(.text+0x423): undefined reference to `alu_reg_init'
    test_alu.c:(.text+0x450): undefined reference to `alu_reg_init'
    test_alu.c:(.text+0x47f): undefined reference to `alu_reg_init'
    ../tests/test_alu.o:test_alu.c:(.text+0x2271): more undefined references to `alu_reg_init' follow
    collect2: error: ld returned 1 exit status
    main.mak:122: recipe for target 'test_alu.AppImage' failed
    make[1]: *** [test_alu.AppImage] Error 1
    rm ../src/alu_math.o ../src/alu_bit.o ../src/alu_fpn.o ../tests/test_alu.o ../src/alu_uint.o ../src/alu_vec.o ../src/alu_int.o ../src/alu_mem.o ../src/alu_main.o
    makefile:9: recipe for target 'check' failed
    make: *** [check] Error 2
    (This was a fresh clone of the repo)

  3. #138
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,100
    Quote Originally Posted by hamster_nz View Post
    Can't debug what I can't build:

    Code:
    ...
    cc -D NDEBUG -O3  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../tests/test_alu.o -c ../tests/test_alu.c
    ../tests/test_alu.c: In function ‘reg_compare’:
    ../tests/test_alu.c:27:2: warning: implicit declaration of function ‘alu_reg_init’; did you mean ‘alu_reg_inc’? [-Wimplicit-function-declaration]
      alu_reg_init( alu, NUM, nodes[0], info );
      ^~~~~~~~~~~~
      alu_reg_inc
    ../tests/test_alu.c:32:2: warning: ‘NUM.node’ may be used uninitialized in this function [-Wmaybe-uninitialized]
      alu_int_set_raw( alu, NUM.node, _num );
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ../tests/test_alu.c:33:2: warning: ‘VAL.node’ may be used uninitialized in this function [-Wmaybe-uninitialized]
      alu_int_set_raw( alu, VAL.node, _val );
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ../tests/test_alu.c: In function ‘modify’:
    ../tests/test_alu.c:83:2: warning: ‘VAL.node’ may be used uninitialized in this function [-Wmaybe-uninitialized]
      alu_int_set_raw( alu, VAL.node, _val );
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    cc -D NDEBUG -O3  -fPIE -L ../lib  -o ../bin/test_alu.AppImage ../tests/test_alu.o -Wl,-rpath,../lib -l alu 
    ../tests/test_alu.o: In function `reg_compare':
    test_alu.c:(.text+0x173): undefined reference to `alu_reg_init'
    test_alu.c:(.text+0x1a0): undefined reference to `alu_reg_init'
    ../tests/test_alu.o: In function `modify':
    test_alu.c:(.text+0x423): undefined reference to `alu_reg_init'
    test_alu.c:(.text+0x450): undefined reference to `alu_reg_init'
    test_alu.c:(.text+0x47f): undefined reference to `alu_reg_init'
    ../tests/test_alu.o:test_alu.c:(.text+0x2271): more undefined references to `alu_reg_init' follow
    collect2: error: ld returned 1 exit status
    main.mak:122: recipe for target 'test_alu.AppImage' failed
    make[1]: *** [test_alu.AppImage] Error 1
    rm ../src/alu_math.o ../src/alu_bit.o ../src/alu_fpn.o ../tests/test_alu.o ../src/alu_uint.o ../src/alu_vec.o ../src/alu_int.o ../src/alu_mem.o ../src/alu_main.o
    makefile:9: recipe for target 'check' failed
    make: *** [check] Error 2
    (This was a fresh clone of the repo)
    You're building the wrong one for the bug I experienced, you have however reminded me that I need to go fix that file again after the minor API change, use "make check" or if you have gede installed then "make check.gede" My only way of stopping the repeat builds was to just append the additional targets to each other as one target

    Edit: File is fixed now, along with a few extra bugs I noticed after running it
    Last edited by awsdert; 1 Week Ago at 03:10 AM.

  4. #139
    Registered User
    Join Date
    Sep 2020
    Posts
    83
    I was making 'check' - see line 31.

  5. #140
    Registered User
    Join Date
    Sep 2020
    Posts
    83
    You're in luck - Harry Potter is on TV. Oh no, not again.... will debug while I watch.

    Got it to build using:
    Code:
    gcc -o alu *.c ../tests/check_alu.c  -Wall -pedantic -I ../include -I ../cloned/unic/include -l check -lm -lsubunit -lpthread -lrt -g
    And verified that it segfaulted.

    Spent a while looking at what is going on around line 1152 in math.c, where it dies.

    v is declared on line 1054 of alu_math.c

    Code:
    alu_bit_t n, v
    v is used on line 1152

    Code:
    *(v.ptr) |= v.mask;
    But v isn't initialised till line 1195:
    Code:
    v = alu_bit( part, VAL.from );
    It looks to me that 'v' is just holding junk from the stack. Can verify that.

    After 'v' is declared, I set it to 0xFFs with:
    Code:
                    memset(&v,255,sizeof(v));
    Then in gdb:

    Code:
    ...
    Running suite(s): ALU
    
    
    Program received signal SIGSEGV, Segmentation fault.
    0x000055555555dfec in alu_reg_addition (alu=0x7fffffffde20, NUM=..., VAL=..., cpy=10, tmp=11) at alu_math.c:1153
    1153                                *(v.ptr) |= v.mask;
    (gdb) print v
    $1 = {seg = 18446744073709551615, bit = 18446744073709551615, pos = 18446744073709551615, ptr = 0xffffffffffffffff, 
      mask = 18446744073709551615}
    (gdb) printf "%lx", v.seg
    ffffffffffffffff(gdb) printf "%lx\n", v.seg
    ffffffffffffffff
    (gdb) printf "%lx\n", v.bit
    ffffffffffffffff
    (gdb) printf "%lx\n", v.pos
    ffffffffffffffff
    (gdb) printf "%lx\n", v.ptr

    Yep - using uninitialized values.

    Not bothering to analyze the code, and just looking at context, I think

    Code:
          n = alu_bit
          (
              (void*)alu_reg_data( alu, _TMAN )
              , exp
          );
    
    
          *(v.ptr) |= v.mask;    <<<< LINE 1152
    should be:

    Code:
          n = alu_bit
          (
              (void*)alu_reg_data( alu, _TMAN )
              , exp
          );
    
    
          *(n.ptr) |= n.mask;    <<<< LINE 1152
    That's an hour of debugging... 30 minutes per character?
    Last edited by hamster_nz; 1 Week Ago at 04:02 AM.

  6. #141
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,100
    Quote Originally Posted by hamster_nz View Post
    Spent a while looking at what is going on around line 1152 in math.c, where it dies.

    v is declared on line 1054 of alu_math.c
    Still looking through your post but are you sure you've got up to date files?
    When I look at that line with what I have uploaded all I see is this:
    Code:
    				}

  7. #142
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,100
    Quote Originally Posted by hamster_nz View Post
    You're in luck - Harry Potter is on TV. Oh no, not again.... will debug while I watch.

    Got it to build using:
    Code:
    gcc -o alu *.c ../tests/check_alu.c  -Wall -pedantic -I ../include -I ../cloned/unic/include -l check -lm -lsubunit -lpthread -lrt -g
    And verified that it segfaulted.

    Spent a while looking at what is going on around line 1152 in math.c, where it dies.

    v is declared on line 1054 of alu_math.c

    Code:
    alu_bit_t n, v
    v is used on line 1152

    Code:
    *(v.ptr) |= v.mask;
    But v isn't initialised till line 1195:
    Code:
    v = alu_bit( part, VAL.from );
    It looks to me that 'v' is just holding junk from the stack. Can verify that.

    After 'v' is declared, I set it to 0xFFs with:
    Code:
                    memset(&v,255,sizeof(v));
    Then in gdb:

    Code:
    ...
    Running suite(s): ALU
    
    
    Program received signal SIGSEGV, Segmentation fault.
    0x000055555555dfec in alu_reg_addition (alu=0x7fffffffde20, NUM=..., VAL=..., cpy=10, tmp=11) at alu_math.c:1153
    1153                                *(v.ptr) |= v.mask;
    (gdb) print v
    $1 = {seg = 18446744073709551615, bit = 18446744073709551615, pos = 18446744073709551615, ptr = 0xffffffffffffffff, 
      mask = 18446744073709551615}
    (gdb) printf "%lx", v.seg
    ffffffffffffffff(gdb) printf "%lx\n", v.seg
    ffffffffffffffff
    (gdb) printf "%lx\n", v.bit
    ffffffffffffffff
    (gdb) printf "%lx\n", v.pos
    ffffffffffffffff
    (gdb) printf "%lx\n", v.ptr

    Yep - using uninitialized values.

    Not bothering to analyze the code, and just looking at context, I think

    Code:
          n = alu_bit
          (
              (void*)alu_reg_data( alu, _TMAN )
              , exp
          );
    
    
          *(v.ptr) |= v.mask;    <<<< LINE 1152
    should be:

    Code:
          n = alu_bit
          (
              (void*)alu_reg_data( alu, _TMAN )
              , exp
          );
    
    
          *(n.ptr) |= n.mask;    <<<< LINE 1152
    That's an hour of debugging... 30 minutes per character?
    Thank you Wrong fix but helped me see what was wrong, instead of v being filled n got filled, n was supposed to only refer to either NUM or CPY (depends on where it is used), likewise v is only supposed to refer to VAL or TMP, sadly FPN addition is still broken

  8. #143
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,100
    I finally spotted one of the reasons why my FPN math is failing, just can't spot the cause of that reason, basically the mantissa is not far enough to the right by the time the result is given, I've hand picked a few of the results to show what I mean:
    Code:
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 45, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 0497 00111110001 1000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 1028 10000000100 0111000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 46, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 0497 00111110001 1100000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 1028 10000000100 0111100000000000000000000000000000000000000000000000
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 47, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 0498 00111110010 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 1028 10000000100 1000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 48, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 0498 00111110010 0010000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 1028 10000000100 1000100000000000000000000000000000000000000000000000
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 49, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 0498 00111110010 0100000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 1028 10000000100 1001000000000000000000000000000000000000000000000000
    The 4 digit value between the sign bit and the exponent bits is just the exponent in decimal prepended with 0's for alignment, as a reminder the top NUM is the result of my code while the bottom NUM is the result of
    hardware addition, the code I used for those results is here, if anyone spots a potential cause I would greatly appreciate you mentioning it even if it turns out to be a wild goose chase because I may catch something else along the way
    Code:
    int_t alu_match_exponents
    (
    	alu_t *alu
    	, uint_t num
    	, uint_t val
    	, uint_t tmp
    )
    {
    	if ( alu )
    	{
    		int_t ret;
    		alu_reg_t NUM, VAL, MAN, TMP;
    		size_t nexp;
    			
    		alu_reg_init_floating( alu, NUM, num );
    		alu_reg_init_floating( alu, VAL, val );
    		alu_reg_init_unsigned( alu, TMP, tmp );
    		
    		NUM.upto = alu_Nbits(alu);
    		VAL.upto = alu_Nbits(alu);
    		
    		ret = alu_reg_get_exponent( alu, NUM, &nexp );
    		
    		if ( ret == 0 )
    		{
    			size_t vexp, diff;
    			bool truncated = false;
    			
    			(void)alu_reg_get_exponent( alu, VAL, &vexp );
    			
    			if ( nexp > vexp )
    			{
    				if ( vexp )
    				{
    					diff = nexp - vexp;
    					alu_reg_init_mantissa( VAL, MAN );
    					
    					/* Match exponent and align mantissa */
    					(void)alu_reg_set_exponent( alu, VAL, nexp );
    					alu->block.fault = 0;
    					alu_reg__shr( alu, MAN, TMP, diff );
    					truncated = (alu_errno(alu) == ERANGE);
    					
    					/* Insert assumed bit back into position */
    					if ( diff < MAN.upto )
    					{
    						void *V = alu_reg_data( alu, VAL );
    						alu_bit_t v = alu_bit( V, MAN.upto - diff );
    						*(v.ptr) |= v.mask;
    					}
    				}
    			}
    			else if ( vexp > nexp )
    			{
    				if ( nexp )
    				{
    					diff = vexp - nexp;
    					
    					alu_reg_init_mantissa( NUM, MAN );
    					
    					(void)alu_reg_set_exponent( alu, NUM, vexp );
    					alu->block.fault = 0;
    					alu_reg__shr( alu, MAN, TMP, diff );
    					truncated = (alu_errno(alu) == ERANGE);
    					
    					/* Insert assumed bit back into position */
    					if ( diff < MAN.upto )
    					{
    						void *N = alu_reg_data( alu, NUM );
    						alu_bit_t n = alu_bit( N, MAN.upto - diff );
    						*(n.ptr) |= n.mask;
    					}
    				}
    			}
    			
    			alu->block.fault = IFTRUE(truncated,ERANGE);
    			
    			return 0;
    		}
    		
    		alu_error(ret);
    		return ret;
    	}
    	
    	return alu_err_null_ptr("alu");
    }
    
    int_t alu_reg_addition(
    	alu_t *alu
    	, alu_reg_t NUM
    	, alu_reg_t VAL
    	, uint_t cpy
    	, uint_t tmp
    )
    {	
    	if ( alu )
    	{
    		int ret;
    		bool carry = false, changed = false;
    		alu_bit_t n, v;
    		size_t pos;
    		void *part;
    		alu_reg_t CPY, CEXP, CMAN, TEXP, TMAN, TMP;
    		
    		NUM.node %= alu_used( alu );
    		VAL.node %= alu_used( alu );
    		
    		ret = IFTRUE( !NUM.node || !VAL.node, EINVAL );
    			
    		if ( ret )
    		{
    			alu_error( ret );
    			
    			if ( !NUM.node ) alu_puts( "NUM.node was 0!" );
    			
    			if ( !VAL.node ) alu_puts( "VAL.node was 0!" );
    			
    			return ret;
    		}
    		
    		if ( alu_reg_floating( VAL ) )
    		{
    			alu_reg_init_floating( alu, TMP, tmp );
    			
    			TMP.upto = alu_Nbits(alu);
    			
    			/* VAL is supposed to be unchanged so use VCPY instead */
    			ret = alu_reg_mov( alu, TMP, VAL );
    			
    			if ( ret == 0 )
    			{	
    				alu_reg_init_floating( alu, CPY, cpy );
    				
    				CPY.upto = alu_Nbits(alu);
    				
    				/* Need NUM to be unchanged so can restore details later,
    				* having both floats the same size also makes math easier,
    				* also no chance of failure here as the previous move
    				* succeeded in getting the same temporary registers this
    				* one will be looking for */
    				(void)alu_reg_mov( alu, CPY, NUM );
    				
    				uint_t temp = alu_get_reg_node( alu, 0 );
    		
    				if ( temp )
    				{					
    					ret = alu_match_exponents( alu, cpy, tmp, temp );
    					alu_rem_reg_node( alu, &temp );
    					
    					if ( ret == 0 )
    					{
    						bool truncated = (alu_errno(alu) == ERANGE);
    						uint_t nodes[2];
    						
    						ret = alu_get_reg_nodes( alu, nodes, 2, 0 );
    						
    						if ( ret == 0 )
    						{
    							do
    							{
    								alu_reg_t _CMAN, _TMAN;
    								size_t bias, exp;
    								
    								alu_reg_init_unsigned( alu, _CMAN, nodes[0] );
    								alu_reg_init_unsigned( alu, _TMAN, nodes[1] );
    								
    								alu_reg_init_exponent( CPY, CEXP );
    								alu_reg_init_exponent( TMP, TEXP );
    								
    								alu_reg_init_mantissa( CPY, CMAN );
    								alu_reg_init_mantissa( TMP, TMAN );
    								
    								alu_reg_int2int( alu, _CMAN, CMAN );
    								alu_reg_int2int( alu, _TMAN, TMAN );
    								
    								(void)alu_reg_get_exponent( alu, CPY, &exp );
    								bias = alu_reg_get_exponent_bias( CPY );
    								
    								if ( exp )
    								{
    									exp -= bias;
    									if ( (ssize_t)exp < 0 )
    									{
    										exp = -exp;
    									}
    									
    									n = alu_bit
    									(
    										(void*)alu_reg_data( alu, _CMAN )
    										, exp
    									);
    									
    									*(n.ptr) |= n.mask;
    									
    									v = alu_bit
    									(
    										(void*)alu_reg_data( alu, _TMAN )
    										, exp
    									);
    									
    									*(v.ptr) |= v.mask;
    								}
    								
    								/* Not possible to get an EOVERFLOW from these */
    								ret = alu_reg_add( alu, _CMAN, _TMAN );
    								
    								if ( ret != 0 && ret != ENODATA )
    									break;
    								
    								n = alu_reg_end_bit( alu, _CMAN );
    								if ( n.bit || *(n.ptr) & n.mask )
    								{
    									exp = n.bit + bias;
    							
    									ret = alu_reg_set_exponent( alu, CPY, exp );
    								
    									if ( ret )
    										break;
    									
    									_CMAN.upto = n.bit - 1;
    									
    									pos = LOWEST( CMAN.upto, _CMAN.upto );
    									
    									_CMAN.from = _CMAN.upto - pos;
    									CMAN.from = CMAN.upto - pos;
    									(void)alu_reg_int2int( alu, CMAN, _CMAN );
    								}
    								
    								ret = alu_reg_mov( alu, NUM, CPY );
    								if ( ret )
    									break;
    								
    								alu_rem_reg_nodes( alu, nodes, 2 );
    								return EITHER( truncated, ERANGE, ret );
    							}
    							while (0);
    							
    							alu_rem_reg_nodes( alu, nodes, 2 );
    							alu_error(ret);
    							return ret;
    						}
    					}
    				}
    				else
    				{
    					ret = alu_errno(alu);
    				}
    			}
    			
    			alu_error(ret);
    			return ret;
    		}

  9. #144
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,100
    Managed to fix the mantissa, now it just the exponent that is the problem, I welcome any ideas there:
    Code:
    int_t alu_reg_addition(
    	alu_t *alu
    	, alu_reg_t NUM
    	, alu_reg_t VAL
    	, uint_t cpy
    	, uint_t tmp
    )
    {	
    	if ( alu )
    	{
    		int ret;
    		bool carry = false, changed = false;
    		alu_bit_t n, v;
    		size_t pos;
    		void *part;
    		alu_reg_t CPY, CEXP, CMAN, TEXP, TMAN, TMP;
    		
    		NUM.node %= alu_used( alu );
    		VAL.node %= alu_used( alu );
    		
    		ret = IFTRUE( !NUM.node || !VAL.node, EINVAL );
    			
    		if ( ret )
    		{
    			alu_error( ret );
    			
    			if ( !NUM.node ) alu_puts( "NUM.node was 0!" );
    			
    			if ( !VAL.node ) alu_puts( "VAL.node was 0!" );
    			
    			return ret;
    		}
    		
    		if ( alu_reg_floating( VAL ) )
    		{
    			alu_reg_init_floating( alu, TMP, tmp );
    			
    			TMP.upto = alu_Nbits(alu);
    			
    			/* VAL is supposed to be unchanged so use VCPY instead */
    			ret = alu_reg_mov( alu, TMP, VAL );
    			
    			if ( ret == 0 )
    			{	
    				alu_reg_init_floating( alu, CPY, cpy );
    				
    				CPY.upto = alu_Nbits(alu);
    				
    				/* Need NUM to be unchanged so can restore details later,
    				* having both floats the same size also makes math easier,
    				* also no chance of failure here as the previous move
    				* succeeded in getting the same temporary registers this
    				* one will be looking for */
    				(void)alu_reg_mov( alu, CPY, NUM );
    				
    				uint_t temp = alu_get_reg_node( alu, 0 );
    		
    				if ( temp )
    				{
    					alu_puts( "Addition details" );
    					alu_puts( "================" );
    #if 0
    					alu_print_reg( alu, CPY, 0, 1 );
    					alu_print_reg( alu, TMP, 0, 1 );
    #endif
    						
    					ret = alu_match_exponents( alu, cpy, tmp, temp );
    					alu_rem_reg_node( alu, &temp );
    					
    					if ( ret == 0 )
    					{
    						bool truncated = (alu_errno(alu) == ERANGE);
    						uint_t nodes[2];
    						
    						ret = alu_get_reg_nodes( alu, nodes, 2, 0 );
    						
    						if ( ret == 0 )
    						{
    							do
    							{
    								alu_reg_t _CMAN, _TMAN;
    								size_t bias, exp;
    								
    								alu_reg_init_unsigned( alu, _CMAN, nodes[0] );
    								alu_reg_init_unsigned( alu, _TMAN, nodes[1] );
    								
    								alu_reg_init_exponent( CPY, CEXP );
    								alu_reg_init_exponent( TMP, TEXP );
    								
    								alu_reg_init_mantissa( CPY, CMAN );
    								alu_reg_init_mantissa( TMP, TMAN );
    								
    								_CMAN.upto = CMAN.upto + 2;
    								_TMAN.upto = TMAN.upto + 2;
    								
    								alu_reg_int2int( alu, _CMAN, CMAN );
    								alu_reg_int2int( alu, _TMAN, TMAN );
    								
    								(void)alu_reg_get_exponent( alu, CPY, &exp );
    								bias = alu_reg_get_exponent_bias( CPY );
    								
    								if ( exp && exp != bias )
    								{
    									exp -= bias;
    									
    									n = alu_bit
    									(
    										(void*)alu_reg_data( alu, _CMAN )
    										, CMAN.upto
    									);
    									
    									*(n.ptr) |= n.mask;
    									
    									v = alu_bit
    									(
    										(void*)alu_reg_data( alu, _TMAN )
    										, TMAN.upto
    									);
    									
    									*(v.ptr) |= v.mask;
    								}
    #if 0
    								/* Not possible to get an EOVERFLOW from these */
    								alu_print_reg( alu, _CMAN, 0, 1 );
    								alu_print_reg( alu, _TMAN, 0, 1 );
    #endif
    								
    								ret = alu_reg_add( alu, _CMAN, _TMAN );
    								
    								if ( ret != 0 && ret != ENODATA )
    									break;
    								
    								n = alu_reg_end_bit( alu, _CMAN );
    								if ( n.bit || *(n.ptr) & n.mask )
    								{
    									exp = n.bit + bias;
    							
    									ret = alu_reg_set_exponent( alu, CPY, exp );
    								
    									if ( ret )
    										break;
    									
    									_CMAN.upto = n.bit - 1;
    									
    									pos = LOWEST( CMAN.upto, _CMAN.upto );
    									
    									_CMAN.from = _CMAN.upto - pos;
    									CMAN.from = CMAN.upto - pos;
    									(void)alu_reg_int2int( alu, CMAN, _CMAN );
    								}
    								
    								ret = alu_reg_mov( alu, NUM, CPY );
    								if ( ret )
    									break;
    								
    								alu_rem_reg_nodes( alu, nodes, 2 );
    								return EITHER( truncated, ERANGE, ret );
    							}
    							while (0);
    							
    							alu_rem_reg_nodes( alu, nodes, 2 );
    							alu_error(ret);
    							return ret;
    						}
    					}
    				}
    				else
    				{
    					ret = alu_errno(alu);
    				}
    			}
    			
    			alu_error(ret);
    			return ret;
    		}
    I know there are probably some edge cases but I will work on that once I have general arithmetic working properly

  10. #145
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,100
    Gotten a heck of a lot closer, realised I forgot to take the position of the mantissa bits into account
    Code:
    int_t alu_reg_addition(
    	alu_t *alu
    	, alu_reg_t NUM
    	, alu_reg_t VAL
    	, uint_t cpy
    	, uint_t tmp
    )
    {	
    	if ( alu )
    	{
    		int ret;
    		bool carry = false, changed = false;
    		alu_bit_t n, v;
    		size_t pos;
    		void *part;
    		alu_reg_t CPY, CEXP, CMAN, TEXP, TMAN, TMP;
    		
    		NUM.node %= alu_used( alu );
    		VAL.node %= alu_used( alu );
    		
    		ret = IFTRUE( !NUM.node || !VAL.node, EINVAL );
    			
    		if ( ret )
    		{
    			alu_error( ret );
    			
    			if ( !NUM.node ) alu_puts( "NUM.node was 0!" );
    			
    			if ( !VAL.node ) alu_puts( "VAL.node was 0!" );
    			
    			return ret;
    		}
    		
    		if ( alu_reg_floating( VAL ) )
    		{
    			alu_reg_init_floating( alu, TMP, tmp );
    			
    			TMP.upto = alu_Nbits(alu);
    			
    			/* VAL is supposed to be unchanged so use VCPY instead */
    			ret = alu_reg_mov( alu, TMP, VAL );
    			
    			if ( ret == 0 )
    			{	
    				alu_reg_init_floating( alu, CPY, cpy );
    				
    				CPY.upto = alu_Nbits(alu);
    				
    				/* Need NUM to be unchanged so can restore details later,
    				* having both floats the same size also makes math easier,
    				* also no chance of failure here as the previous move
    				* succeeded in getting the same temporary registers this
    				* one will be looking for */
    				(void)alu_reg_mov( alu, CPY, NUM );
    				
    				uint_t temp = alu_get_reg_node( alu, 0 );
    		
    				if ( temp )
    				{
    					ret = alu_match_exponents( alu, cpy, tmp, temp );
    					alu_rem_reg_node( alu, &temp );
    					
    					if ( ret == 0 )
    					{
    						bool truncated = (alu_errno(alu) == ERANGE);
    						uint_t nodes[2];
    						
    						ret = alu_get_reg_nodes( alu, nodes, 2, 0 );
    						
    						if ( ret == 0 )
    						{
    							do
    							{
    								alu_reg_t _CMAN, _TMAN;
    								size_t bias, _exp;
    								ssize_t exp;
    								
    								alu_reg_init_unsigned( alu, _CMAN, nodes[0] );
    								alu_reg_init_unsigned( alu, _TMAN, nodes[1] );
    								
    								alu_reg_init_exponent( CPY, CEXP );
    								alu_reg_init_exponent( TMP, TEXP );
    								
    								alu_reg_init_mantissa( CPY, CMAN );
    								alu_reg_init_mantissa( TMP, TMAN );
    								
    								_CMAN.upto = CMAN.upto + 2;
    								_TMAN.upto = TMAN.upto + 2;
    								
    								alu_reg_int2int( alu, _CMAN, CMAN );
    								alu_reg_int2int( alu, _TMAN, TMAN );
    								
    								(void)alu_reg_get_exponent( alu, CPY, &_exp );
    								bias = alu_reg_get_exponent_bias( CPY );
    								
    								if ( _exp && _exp != bias )
    								{
    									_exp -= bias;
    									
    									n = alu_bit
    									(
    										(void*)alu_reg_data( alu, _CMAN )
    										, CMAN.upto
    									);
    									
    									*(n.ptr) |= n.mask;
    									
    									v = alu_bit
    									(
    										(void*)alu_reg_data( alu, _TMAN )
    										, TMAN.upto
    									);
    									
    									*(v.ptr) |= v.mask;
    								}
    								else
    									_exp = 0;
    									
    								exp = _exp;
    								
    								ret = alu_reg_add( alu, _CMAN, _TMAN );
    								
    								if ( ret != 0 && ret != ENODATA )
    									break;
    								
    								n = alu_reg_end_bit( alu, _CMAN );
    								part = alu_reg_data( alu, _CMAN );
    								for
    								(
    									v = alu_bit( part, 0 )
    									; v.bit < n.bit && !(*(v.ptr) & v.mask)
    									; alu_bit_inc(&v)
    								);
    								
    								if ( n.bit || *(n.ptr) & n.mask )
    								{	
    									_exp = n.bit - v.bit;
    									
    									ret = alu_reg_set_exponent( alu, CPY, bias + _exp );
    								
    									if ( ret )
    										break;
    									
    									_CMAN.upto = n.bit - 1;
    									
    									pos = LOWEST( CMAN.upto, _CMAN.upto );
    									
    									_CMAN.from = _CMAN.upto - pos;
    									CMAN.from = CMAN.upto - pos;
    									(void)alu_reg_int2int( alu, CMAN, _CMAN );
    								}
    								else
    								{	
    									ret = alu_reg_set_exponent( alu, CPY, (ssize_t)bias + exp );
    								
    									if ( ret )
    										break;
    								}
    								
    								ret = alu_reg_mov( alu, NUM, CPY );
    								if ( ret )
    									break;
    								
    								alu_rem_reg_nodes( alu, nodes, 2 );
    								return EITHER( truncated, ERANGE, ret );
    							}
    							while (0);
    							
    							alu_rem_reg_nodes( alu, nodes, 2 );
    							alu_error(ret);
    							return ret;
    						}
    					}
    				}
    				else
    				{
    					ret = alu_errno(alu);
    				}
    			}
    			
    			alu_error(ret);
    			return ret;
    		}

  11. #146
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,100
    This is the closest I've gotten:
    Code:
    make check.run
    ...
    gdb -ex run  ../bin/check_alu_d.AppImage
    GNU gdb (GDB) 9.2
    ...
    Reading symbols from ../bin/check_alu_d.AppImage...
    Starting program: ~/alu/bin/check_alu_d.AppImage
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/usr/lib/libthread_db.so.1".
    Running suite(s): ALU
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 0, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 +0001 10000000000 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 +0000 01111111111 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 1, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 +1024 11111111111 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 +0001 10000000000 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 3, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 +0001 10000000000 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 +0002 10000000001 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 7, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 +0002 10000000001 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 +0003 10000000010 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 15, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 +0003 10000000010 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 +0004 10000000011 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:967: test_alu_reg_add_floating_fn() _num = 31, _val = 1, (EXP.upto = 63) - (EXP.from = 52) = 11, (MAN.upto = 52) - (MAN.from = 0) = 52
    ../tests/check_alu.c:978: test_alu_reg_add_floating_fn() NUM = 0 +0004 10000000011 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:980: test_alu_reg_add_floating_fn() NUM = 0 +0005 10000000100 0000000000000000000000000000000000000000000000000000
    99%: Checks: 1584, Failures: 6, Errors: 0
    ../tests/check_alu.c:982:F:Core:test_alu_reg_add_floating:0: Assertion '1 == 0' failed
    ...
    ../tests/check_alu.c:982:F:Core:test_alu_reg_add_floating:31: Assertion '1 == 0' failed
    ==9545==LeakSanitizer has encountered a fatal error.
    ==9545==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
    ==9545==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
    [Inferior 1 (process 9545) exited with code 01]
    (gdb) quit
    rm ../src/alu_int_d.o ../src/alu_math_d.o ../tests/check_alu_d.o ../src/alu_main_d.o ../src/alu_uint_d.o ../src/alu_fpn_d.o ../src/alu_bit_d.o ../src/alu_mem_d.o ../src/alu_vec_d.o
    Compilation finished successfully.
    With this code:
    Code:
    int_t alu_reg_addition(
    	alu_t *alu
    	, alu_reg_t NUM
    	, alu_reg_t VAL
    	, uint_t cpy
    	, uint_t tmp
    )
    {	
    	if ( alu )
    	{
    		int ret;
    		bool carry = false, changed = false;
    		alu_bit_t n, v;
    		size_t pos;
    		void *part;
    		alu_reg_t CPY, CEXP, CMAN, TEXP, TMAN, TMP;
    		
    		NUM.node %= alu_used( alu );
    		VAL.node %= alu_used( alu );
    		
    		ret = IFTRUE( !NUM.node || !VAL.node, EINVAL );
    			
    		if ( ret )
    		{
    			alu_error( ret );
    			
    			if ( !NUM.node ) alu_puts( "NUM.node was 0!" );
    			
    			if ( !VAL.node ) alu_puts( "VAL.node was 0!" );
    			
    			return ret;
    		}
    		
    		if ( alu_reg_floating( VAL ) )
    		{
    			alu_reg_init_floating( alu, TMP, tmp );
    			
    			TMP.upto = alu_Nbits(alu);
    			
    			/* VAL is supposed to be unchanged so use VCPY instead */
    			ret = alu_reg_mov( alu, TMP, VAL );
    			
    			if ( ret == 0 )
    			{	
    				alu_reg_init_floating( alu, CPY, cpy );
    				
    				CPY.upto = alu_Nbits(alu);
    				
    				/* Need NUM to be unchanged so can restore details later,
    				* having both floats the same size also makes math easier,
    				* also no chance of failure here as the previous move
    				* succeeded in getting the same temporary registers this
    				* one will be looking for */
    				(void)alu_reg_mov( alu, CPY, NUM );
    				
    				uint_t temp = alu_get_reg_node( alu, 0 );
    		
    				if ( temp )
    				{
    					ret = alu_match_exponents( alu, cpy, tmp, temp );
    					alu_rem_reg_node( alu, &temp );
    					
    					if ( ret == 0 )
    					{
    						bool truncated = (alu_errno(alu) == ERANGE);
    						uint_t nodes[2];
    						
    						ret = alu_get_reg_nodes( alu, nodes, 2, 0 );
    						
    						if ( ret == 0 )
    						{
    							do
    							{
    								alu_reg_t _CMAN, _TMAN;
    								size_t bias, _exp;
    								ssize_t exp;
    								
    								alu_reg_init_unsigned( alu, _CMAN, nodes[0] );
    								alu_reg_init_unsigned( alu, _TMAN, nodes[1] );
    								
    								alu_reg_init_exponent( CPY, CEXP );
    								alu_reg_init_exponent( TMP, TEXP );
    								
    								alu_reg_init_mantissa( CPY, CMAN );
    								alu_reg_init_mantissa( TMP, TMAN );
    								
    								_CMAN.upto = CMAN.upto + 2;
    								_TMAN.upto = TMAN.upto + 2;
    								
    								alu_reg_int2int( alu, _CMAN, CMAN );
    								alu_reg_int2int( alu, _TMAN, TMAN );
    								
    								(void)alu_reg_get_exponent( alu, CPY, &_exp );
    								bias = alu_reg_get_exponent_bias( CPY );
    								
    								if ( _exp && _exp != bias )
    								{
    									_exp -= bias;
    									
    									n = alu_bit
    									(
    										(void*)alu_reg_data( alu, _CMAN )
    										, CMAN.upto
    									);
    									
    									*(n.ptr) |= n.mask;
    									
    									v = alu_bit
    									(
    										(void*)alu_reg_data( alu, _TMAN )
    										, TMAN.upto
    									);
    									
    									*(v.ptr) |= v.mask;
    								}
    									
    								exp = _exp;
    								
    								ret = alu_reg_add( alu, _CMAN, _TMAN );
    								
    								if ( ret == ENODATA )
    								{
    									++exp;
    									ret = 0;
    								}
    								
    								if ( ret != 0 && ret != ENODATA )
    									break;
    								
    								n = alu_reg_end_bit( alu, _CMAN );
    								part = alu_reg_data( alu, _CMAN );
    								for
    								(
    									v = alu_bit( part, 0 )
    									; v.bit < n.bit && !(*(v.ptr) & v.mask)
    									; alu_bit_inc(&v)
    								);
    								
    								ret = alu_reg_set_exponent( alu, CPY, bias + exp );
    								
    								if ( ret )
    									break;
    								
    								(void)alu_reg_int2int( alu, CMAN, _CMAN );
    								
    								ret = alu_reg_mov( alu, NUM, CPY );
    								if ( ret )
    									break;
    								
    								alu_rem_reg_nodes( alu, nodes, 2 );
    								return EITHER( truncated, ERANGE, ret );
    							}
    							while (0);
    							
    							alu_rem_reg_nodes( alu, nodes, 2 );
    							alu_error(ret);
    							return ret;
    						}
    					}
    				}
    				else
    				{
    					ret = alu_errno(alu);
    				}
    			}
    			
    			alu_error(ret);
    			return ret;
    		}
    I'm gonna take a break, hopefully someone finds the fault before I get back to trying

  12. #147
    Registered User
    Join Date
    Jul 2009
    Posts
    6
    If you're periodically running into undefined behavior, valgrind might be able to identify cases you haven't noticed.

    Ruling out these cases might be helpful.

  13. #148
    Registered User
    Join Date
    Sep 2020
    Posts
    83
    If I was in your position I would really start looking how actual floating point H/W does addition. There are plenty of papers out there:

    https://www.ijert.org/research/desig...TV2IS70837.pdf

    https://core.ac.uk/download/pdf/190942867.pdf

    These sorts of problems tend to need to be written once, and rewritten twice (or 'refactored' if you don't like "rewritten" as a term).

    - The first write is to work out what needs to happen, and it usually is broken and littered with errors in corner cases.

    - The first rewrite is to make it actually work correctly, but is poorly performing and poorly structured.

    - The second rewrite uses are the things learnt along the way to write a clean and efficient implementation.

    You can sometimes jump the first couple of attempts if you read a few published papers, which will point out the corner cases and traps to you.
    Last edited by hamster_nz; 1 Week Ago at 04:15 PM.

  14. #149
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,100
    Quote Originally Posted by hamster_nz View Post
    If I was in your position I would really start looking how actual floating point H/W does addition. There are plenty of papers out there:

    https://www.ijert.org/research/desig...TV2IS70837.pdf

    https://core.ac.uk/download/pdf/190942867.pdf

    These sorts of problems tend to need to be written once, and rewritten twice (or 'refactored' if you don't like "rewritten" as a term).

    - The first write is to work out what needs to happen, and it usually is broken and littered with errors in corner cases.

    - The first rewrite is to make it actually work correctly, but is poorly performing and poorly structured.

    - The second rewrite uses are the things learnt along the way to write a clean and efficient implementation.

    You can sometimes jump the first couple of attempts if you read a few published papers, which will point out the corner cases and traps to you.
    In this case I need to first fully understand what needs to happen, I find that I tend to understand stuff like this better by actually going through the trial and error stuff, judging by the fact I'm almost there with the results I'd say I now have a mostly full understanding of FPN addition, I'll be adding to that understanding once I get the remaining results correct, anyways now that I'm here again JonA since you brought it up (and reminded me of it's existence) do you know anything about this line:
    Code:
    ==2387==ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.
    from this output?
    Code:
    make check.valgrind
    cd ../ && make --no-print-directory check.valgrind
    #MAKECMDGOALS=check.valgrind
    cd mak && make -j 1 --no-print-directory -f main.mak check.valgrind
    PRJ_GOALS=  check
    PRJ_LIB_NAME=alu_d
    Checking 3rd Party libraries are upto date
    cd '../cloned/unic' && git fetch && git pull
    Finished checking
    PRJ_DST_BIN=check_alu_d.AppImage
    PRJ_DST_LIB=libalu_d.so
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_bit_d.o -c ../src/alu_bit.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_fpn_d.o -c ../src/alu_fpn.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_int_d.o -c ../src/alu_int.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_main_d.o -c ../src/alu_main.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_math_d.o -c ../src/alu_math.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_mem_d.o -c ../src/alu_mem.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_uint_d.o -c ../src/alu_uint.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../src/alu_vec_d.o -c ../src/alu_vec.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -shared  -o ../lib/libalu_d.so ../src/alu_bit_d.o ../src/alu_fpn_d.o ../src/alu_int_d.o ../src/alu_main_d.o ../src/alu_math_d.o ../src/alu_mem_d.o ../src/alu_uint_d.o ../src/alu_vec_d.o -Wl,-rpath,../lib
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIC -Wall -Wextra -pedantic -I ../cloned/unic/include -I ../include -D UNIC_FALLBACK  -o ../tests/check_alu_d.o -c ../tests/check_alu.c
    cc -ggdb -D _DEBUG -O0 -fsanitize=address  -fPIE -L ../lib  -o ../bin/check_alu_d.AppImage ../tests/check_alu_d.o -Wl,-rpath,../lib -l alu_d -l check  -l rt -l pthread -l m
    valgrind ../bin/check_alu_d.AppImage
    ==2387== Memcheck, a memory error detector
    ==2387== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==2387== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
    ==2387== Command: ../bin/check_alu_d.AppImage
    ==2387==
    ==2387==ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.
    ==2387==
    ==2387== HEAP SUMMARY:
    ==2387==     in use at exit: 0 bytes in 0 blocks
    ==2387==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
    ==2387==
    ==2387== All heap blocks were freed -- no leaks are possible
    ==2387==
    ==2387== For lists of detected and suppressed errors, rerun with: -s
    ==2387== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    rm ../src/alu_int_d.o ../src/alu_math_d.o ../tests/check_alu_d.o ../src/alu_main_d.o ../src/alu_uint_d.o ../src/alu_fpn_d.o ../src/alu_bit_d.o ../src/alu_mem_d.o ../src/alu_vec_d.o
    make[2]: *** [main.mak:104: check.valgrind] Error 1
    make[1]: *** [makefile:10: check.valgrind] Error 2
    make: *** [makefile:4: check.valgrind] Error 2
    Compilation failed.
    I usually find that googling an acronym gives me everything but what I'm looking for so it would be helpful to be pointed in the right direction.

  15. #150
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,100
    Since I was drawing a blank on how to fix the exponent I decided to move as much core code into ptr handling variants as possible, now I've a segfault and I'm drawing a blank on the how there also, maybe some fresh eyes will help:
    Code:
    int_t alup__shr( alup_t _NUM, void *_tmp, size_t by )
    {	
    	int_t ret = 0;
    	
    	if ( by )
    	{
    		alup_t _TMP;
    		
    		/* Mantissa will use same bits but exponent will be lesser */
    		if ( alup_floating( _NUM ) )
    		{
    			alup_t _EXP;
    			
    			alup_init_exponent( _NUM, _EXP );
    			alup_init_unsigned( _TMP, &by, sizeof(size_t) );
    			
    			return alup_sub_int2int( _EXP, _TMP );
    		}
    		else
    		{
    			alub_t n, v;
    			bool_t neg = alup_below0( _NUM );
    			size_t diff = _NUM.upto - _NUM.from;
    			size_t size = (diff / UNIC_CHAR_BIT) + !!(diff % UNIC_CHAR_BIT);
    		
    			if ( by >= diff )
    			{
    				alup_set( _NUM, neg );
    				return 0;
    			}
    			
    			alup_init_unsigned( _TMP, _tmp, size );
    			
    			/* We have the ptr so might as well */
    			ret = alup_mov_int2int( _TMP, _NUM );
    			
    			if ( ret )
    			{
    				alu_error(ret);
    				return ret;
    			}
    			
    			n = alub( _NUM.data, _NUM.from );
    			v = alub( _tmp, 0 );
    			
    			while ( by )
    			{
    				--by;
    				alub_dec(&n);
    				
    				ret = EITHER( *(n.ptr) & n.mask, ERANGE, ret ); // This line is where the segfault occurs
    In meantime I'm gonna get something to eat, hopefully someone can find the root cause while I'm taking a break, in case no one's looked at the recent upload messages on the github page I've switch to shorter names for the internal stuff
    alu_bit_* to alub_*
    alu_reg_* to alur_*
    alu_ptr_* to alup_*

    In general the order of calls looks roughly like this: alu_* > alur_* > alup_* > alub_*

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