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

  1. #151
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Fixed that segfault, turned I had poorly initialised a few variables in the process of moving core code, anyways I got closer to the correct behavior of FPN, addition, turned out I had to check the prior states of the exponents before deciding to add the assumed bit, also had to shorten the resulting mantissa length by 1 to ensure I got the overflow error upon those 2 bits being added, I used that error to detect when the final exponent should be incremented, now I've just got what appears to be an edge case and a buggy rotate right bitwise (either that or the width given to it is wrong, haven't seen possible causes of either yet)

    Code:
    make check.run
    ...
    Running suite(s): ALU
    ../tests/check_alu.c:966: test_alur_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:977: test_alur_add_floating_fn() NUM = 0 +1023 11111111110 0000000000000000000000000000000000000000000000000000
    ../tests/check_alu.c:979: test_alur_add_floating_fn() NUM = 0 +0001 10000000000 0000000000000000000000000000000000000000000000000000
    99%: Checks: 1584, Failures: 1, Errors: 0
    ../tests/check_alu.c:981:F:Core:test_alur_add_floating:1: Assertion '1 == 0' failed
    ==11026==LeakSanitizer has encountered a fatal error.
    ==11026==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
    ==11026==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
    [Inferior 1 (process 11026) 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.
    I'll post code for the right shift in a minute, forgot to make alur__ror() rely on alup__ror()

    Edit: Apparently it was the alur__ror() that was buggy, dunno what I did there but making it rely on alup__ror() instead got rid of the right shift errors so I'll ignore that one. I've replaced the above output with the fresh output, as you can see it is only 1 addition left that is resulting in the incorrect exponent, since I'm once again drawing a blank I'll leave it at that after uploading the change I just made, hopefully either I or someone else gets an idea for fixing that while I'm moving more code into the alup_* functions

  2. #152
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    I find it interesting that you don't see compile errors when using uninitialized variables, even though warnings are turned on.

    I haven't bothered investigating why that would be... can you think of any reason?

  3. #153
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by hamster_nz View Post
    I find it interesting that you don't see compile errors when using uninitialized variables, even though warnings are turned on.

    I haven't bothered investigating why that would be... can you think of any reason?
    Because I initialise them before I use them, it only kicks up a fuss when there is no sign of it being initialised at all before the attempt to use the information it has

    Here's an example:
    Code:
    int ret;
    return ret; // Error flagged here
    Code:
    int ret;
    foo(&ret);
    return ret; // No error because foo is now seen as responsible for initialisation
    Edit: Another example:
    Code:
    int ret;
    ret = foo();
    return ret; // No error because it was initialised with the result of foo()

  4. #154
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    I've managed to greatly simplify the FPN addition code, still same bug but now the code is far easier to read, it seems adding that extra variable to the shift functions was the greatest mistake I've made in the ALU project.
    A reminder of the bug:
    Code:
    make check.run
    ...
    Using host libthread_db library "/usr/lib/libthread_db.so.1".
    Running suite(s): ALU
    ../src/alur.c:366: alur_add() Error 0x00000022 34 'Numerical result out of range'
    ../tests/check_alu.c:1037: test_alur_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:1048: test_alur_add_floating_fn() NUM = 0 +0000 01111111111 0000000000000000000000000000000000000000000000000000 // Incorrect result from software
    ../tests/check_alu.c:1050: test_alur_add_floating_fn() NUM = 0 +0001 10000000000 0000000000000000000000000000000000000000000000000000 // Correct result from hardware
    99%: Checks: 1584, Failures: 1, Errors: 0
    ...
    Compilation finished successfully.
    The addition part:
    Code:
    int_t alur__add(
    	alu_t *alu
    	, alur_t NUM
    	, alur_t VAL
    	, uint_t cpy
    	, uint_t tmp
    )
    {	
    	if ( alu )
    	{
    		int ret;
    		//alub_t n, v;
    		alup_t _NUM, _VAL;
    		
    		NUM.node %= alu_used( alu );
    		VAL.node %= alu_used( alu );
    		cpy %= alu_used(alu);
    		tmp %= alu_used(alu);
    		
    		ret = IFTRUE( !NUM.node || !VAL.node || !cpy || !tmp, EINVAL );
    			
    		if ( ret )
    		{
    			alu_error( ret );
    			
    			if ( !NUM.node ) alu_puts( "NUM.node was 0!" );
    			
    			if ( !VAL.node ) alu_puts( "VAL.node was 0!" );
    			
    			if ( !cpy ) alu_puts( "cpy was 0!" );
    			
    			if ( !tmp ) alu_puts( "tmp was 0!" );
    			
    			return ret;
    		}
    		
    		alup_init_register( alu, _NUM, NUM );
    		alup_init_register( alu, _VAL, VAL );
    		
    		if ( alur_floating( NUM ) || alur_floating( VAL ) )
    		{
    			alup_t _CPY, _TMP, _CMAN, _TMAN;
    			size_t exp;//, cexp, texp;//, bias;
    			bool_t truncated = false;
    			
    			alup_init_floating( _CPY, alu_data(alu, cpy), alu_Nsize(alu) );
    			alup_init_floating( _TMP, alu_data(alu, tmp), alu_Nsize(alu) );
    			
    			alup_init_mantissa( _CPY, _CMAN );
    			alup_init_mantissa( _TMP, _TMAN );
    			
    			alup_mov( _CPY, _NUM );
    			alup_mov( _TMP, _VAL );
    			
    			//cexp = alup_get_exponent( _CPY );
    			//texp = alup_get_exponent( _TMP );
    			//bias = alup_get_exponent_bias( _CPY );
    			
    			ret = alup_match_exponents
    			(
    				_CPY.data
    				, _TMP.data
    				, alu_Nsize(alu)
    			);
    			
    			truncated = (ret == ERANGE);
    			
    			exp = alup_get_exponent( _CPY );
    			
    			ret = alup__add_int2int( _CMAN, _TMAN );
    			
    			if ( ret == EOVERFLOW ) ++exp;
    			
    			(void)alup_set_exponent( _CPY, exp );
    			
    			ret = alup_mov( _NUM, _CPY );
    			
    			return IFTRUE( truncated || ret == ERANGE, ERANGE );
    		}
    		return alup__add_int2int( _NUM, _VAL );
    	}
    	
    	return alu_err_null_ptr("alu");
    }
    Just in case anyone needs to see it, the exponent matching part:
    Code:
    int_t alup_match_exponents( void *_num, void *_val, size_t size )
    {
    	int_t ret;
    	alup_t _NUM, _VAL, _DST, _MAN = {0};
    	size_t exp = 0, nexp, vexp, diff = 0;
    	bool truncated = false;
    	
    	alup_init_floating( _NUM, _num, size );
    	alup_init_floating( _VAL, _val, size );
    	
    	nexp = alup_get_exponent( _NUM );
    	vexp = alup_get_exponent( _VAL );
    		
    	if ( nexp > vexp )
    	{
    		exp = nexp;
    		diff = nexp - vexp;
    		_DST = _VAL;
    	}
    	else if ( vexp > nexp )
    	{
    		exp = vexp;
    		diff = vexp - nexp;
    		_DST = _NUM;
    	}
    	
    	if ( diff )
    	{
    		alup_init_mantissa( _DST, _MAN );
    			
    		/* Match exponent and align mantissa */
    		(void)alup_set_exponent( _DST, exp );
    		
    		ret = alup__shr( _MAN, diff );
    		
    		truncated = (ret == ERANGE);
    	
    		/* Insert assumed bit back into position */
    		if ( diff < _MAN.upto )
    		{
    			alub_t m = alub( _MAN.data, _MAN.upto - diff );
    			*(m.ptr) |= m.mask;
    		}
    	}
    	
    	return IFTRUE( truncated, ERANGE );
    }

  5. #155
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    I FIXED IT!!!

    It always felt like I needed the original exponents somehow, now I have coded evidence:
    Code:
    int_t alur__add(
    	alu_t *alu
    	, alur_t NUM
    	, alur_t VAL
    	, uint_t cpy
    	, uint_t tmp
    )
    {	
    	if ( alu )
    	{
    		int ret;
    		//alub_t n, v;
    		alup_t _NUM, _VAL;
    		
    		NUM.node %= alu_used( alu );
    		VAL.node %= alu_used( alu );
    		cpy %= alu_used(alu);
    		tmp %= alu_used(alu);
    		
    		ret = IFTRUE( !NUM.node || !VAL.node || !cpy || !tmp, EINVAL );
    			
    		if ( ret )
    		{
    			alu_error( ret );
    			
    			if ( !NUM.node ) alu_puts( "NUM.node was 0!" );
    			
    			if ( !VAL.node ) alu_puts( "VAL.node was 0!" );
    			
    			if ( !cpy ) alu_puts( "cpy was 0!" );
    			
    			if ( !tmp ) alu_puts( "tmp was 0!" );
    			
    			return ret;
    		}
    		
    		alup_init_register( alu, _NUM, NUM );
    		alup_init_register( alu, _VAL, VAL );
    		
    		if ( alur_floating( NUM ) || alur_floating( VAL ) )
    		{
    			alup_t _CPY, _TMP, _CMAN, _TMAN;
    			size_t exp, cexp, texp;
    			bool_t truncated = false;
    			
    			alup_init_floating( _CPY, alu_data(alu, cpy), alu_Nsize(alu) );
    			alup_init_floating( _TMP, alu_data(alu, tmp), alu_Nsize(alu) );
    			
    			alup_init_mantissa( _CPY, _CMAN );
    			alup_init_mantissa( _TMP, _TMAN );
    			
    			alup_mov( _CPY, _NUM );
    			alup_mov( _TMP, _VAL );
    			
    			cexp = alup_get_exponent( _CPY );
    			texp = alup_get_exponent( _TMP );
    			
    			ret = alup_match_exponents
    			(
    				_CPY.data
    				, _TMP.data
    				, alu_Nsize(alu)
    			);
    			
    			truncated = (ret == ERANGE);
    			
    			exp = alup_get_exponent( _CPY );
    			
    			ret = alup__add_int2int( _CMAN, _TMAN );
    			
    			if ( cexp || texp )
    			{
    				if ( (cexp == texp) || ret == EOVERFLOW ) ++exp;
    			}
    			
    			(void)alup_set_exponent( _CPY, exp );
    			
    			ret = alup_mov( _NUM, _CPY );
    			
    			return IFTRUE( truncated || ret == ERANGE, ERANGE );
    		}
    		return alup__add_int2int( _NUM, _VAL );
    	}
    	
    	return alu_err_null_ptr("alu");
    }
    Gotta head to work earlier than usual today to get my nieces and nephews their xmas presents, I welcome anyone to look for edge cases with this because I need to include those in the tests as well

  6. #156
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Judging by the lack of responses I can only predict 3 scenarios:

    1. Peops lost interest (doubt this one)
    2. Peops didn't bother to try any additions they though of (suspect this one strongly)
    3. Peops didn't find any edge cases (doubt this one also)

    Assuming number 2 then that's fine, wasn't really expecting many to try, either way I'll try a bunch of additions using the results of I think it was rnd_s()? I'm sure a few of you already know what I mean and the rest probably already understand the rough purpose, assuming I don't get any fails there either then I'll move onto subtraction which uses the same process

  7. #157
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Ended up starting with the subtraction instead of the random additions, now I'm running into a segfault and I have no clue why, stops at this line:
    alu/alup.c at master * awsdert/alu * GitHub

    Edit: The segfault occurs during subtraction, both addition and subtraction are likely using the same registers so I see no reason for it to segfault after addition already succeeded

  8. #158
    Registered User
    Join Date
    Sep 2020
    Posts
    150
    Judging by the lack of responses I can only predict 3 scenarios:

    1. Peops lost interest (doubt this one)
    2. Peops didn't bother to try any additions they though of (suspect this one strongly)
    3. Peops didn't find any edge cases (doubt this one also)
    I would add 4. People don't understand the code.

    It's certainly true for me, though out of curiosity and lack of other meaningful projects I sometimes read the posts.

  9. #159
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by thmm View Post
    I would add 4. People don't understand the code.

    It's certainly true for me, though out of curiosity and lack of other meaningful projects I sometimes read the posts.
    Please clarify what parts you struggle to understand, I did after all try to make it more readable

  10. #160
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    c - What does a type followed by _t (underscore-t) represent? - Stack Overflow

    However, you should also note that POSIX defines a lot of extra type names ending in '_t', and reserves the suffix for the implementation. That means that if you are working on POSIX-related systems, defining your own type names with the convention is ill-advised. The system I work on has done it (for more than 20 years); we regularly get tripped up by systems defining types with the same name as we define.
    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  11. #161
    Registered User
    Join Date
    Sep 2020
    Posts
    150
    It's not the code itself(which is readable), but what it is doing. I know very little about the CPU.

  12. #162
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by thmm View Post
    It's not the code itself(which is readable), but what it is doing. I know very little about the CPU.
    I suggest you youtube binary math then

  13. #163
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    Quote Originally Posted by awsdert View Post
    I suggest you youtube binary math then
    ^^^ Are you trying to lose friends? Cause comments like that won't make any ^^^

    The reason I haven't had any more input are

    a) A Harry Potter movie isn't on - so I'm busy on other stuff. I'm building an Audio Distortion Meter as time allows.

    b) I know enough about floating point to know that there is a lot to know. Fixing an odd 'doing something dumb in C' is relatively easy, but I don't want to spend hours reading papers to fully inform my self to help assist you with stuff where I don't have the depth of experience.

    c) I'm more than happy to help somebody once or twice, but I'm nobody's code monkey for ever.

    c) I don't really agree with how you are going about implementing it. Seems to be a silly way to do it. But that is because I don't appreciate your aims.

    If was implementing FP addition/subtraction in software. Here's my outline of implementation:

    1. Split the FP registers into parts (sign, exponent, mantissa) maybe adding guard bits too.

    2. Handle special cases (zeros, +INF/-INF, NaN)

    3. Fix up the mantissa of both parts, and deal with 'denormalized' cases (very small numbers)

    4. work out how much to right-shift the smaller FP number, to give a common exponent as the other one.

    6. Merge the sign into the mantissa (convert it from sign+magnitude to two's complement.

    7. Finally do the addition - just simple binary addition.

    8. Handle if the exponent has increased or decreased - i.e. 're-normalize'

    9. Convert back to sign+magnitude

    10. Process rounding

    11. Convert back to IEEE format and pack into the register

    If I was doing it for implementation in hardware (e.g. an FPGA) I would be doing it very differently.

  14. #164
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by hamster_nz View Post
    ^^^ Are you trying to lose friends? Cause comments like that won't make any ^^^

    The reason I haven't had any more input are

    a) A Harry Potter movie isn't on - so I'm busy on other stuff. I'm building an Audio Distortion Meter as time allows.

    b) I know enough about floating point to know that there is a lot to know. Fixing an odd 'doing something dumb in C' is relatively easy, but I don't want to spend hours reading papers to fully inform my self to help assist you with stuff where I don't have the depth of experience.

    c) I'm more than happy to help somebody once or twice, but I'm nobody's code monkey for ever.

    c) I don't really agree with how you are going about implementing it. Seems to be a silly way to do it. But that is because I don't appreciate your aims.

    If was implementing FP addition/subtraction in software. Here's my outline of implementation:

    1. Split the FP registers into parts (sign, exponent, mantissa) maybe adding guard bits too.

    2. Handle special cases (zeros, +INF/-INF, NaN)

    3. Fix up the mantissa of both parts, and deal with 'denormalized' cases (very small numbers)

    4. work out how much to right-shift the smaller FP number, to give a common exponent as the other one.

    6. Merge the sign into the mantissa (convert it from sign+magnitude to two's complement.

    7. Finally do the addition - just simple binary addition.

    8. Handle if the exponent has increased or decreased - i.e. 're-normalize'

    9. Convert back to sign+magnitude

    10. Process rounding

    11. Convert back to IEEE format and pack into the register

    If I was doing it for implementation in hardware (e.g. an FPGA) I would be doing it very differently.
    1st: what do you mean trying to lose friends? Xey said xey didn't understand what I was going on about so I suggested a starting point for xem to understand, understanding how binary math works gives an understanding of how the CPU sees math, moving onto FPN binary math after that would be a natural course by which point xey would begin to understand what I'm on about.

    2nd: I didn't expect you to be my "code monkey", appreciate the help you've given but I only refer to a member directly when it involves something xey have already posted, otherwise I generally speak to the community at large since I'm more likely to get the help I need if I don't specifically rely on single person, take linux for example, if the founder relied on the input of only one person then the system would not be as robust as it is today

    3rd: I'm trying to implement an EXISTING and already robust standard, that means I don't have the luxury of deciding the format as you are suggesting, my only choice is to follow the decisions already made by trial and error of past implementations

    The reason I compare against hardware atm is because I no my CPU has a correct implementation for fixed size hardware floats, my implementation however is focusing on scalabilty so that it can be used in another hobby project of mine where I'm making a compiler, which means it must follow the standards first before experimenting with it's own custom types, formats and implementations

    If you don't wanna do anymore then just don't, I'm not expecting you or anyone else to help, I merely throw out these questions and invitations in the hopes that someone will be inclined to help me fix bugs faster than I would on my own

    As an aside I did get round to testing FPN addition on random numbers, there was a bug and I've fixed it, I've not seen any more errors pop up with it so I'm treating it as done until one does, in mean time I still haven't thought of a possible reason why FPN subtraction is segfaulting in my project so if anyone has actually looked or is inclined to look then I still welcome help on that

  15. #165
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    If you really want others to help; then you need to:

    1. Post which git repo has the current code you are having issues with
    2. Add a README in the repo on how to compile/build the repo.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

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