Thread: FPN math

  1. #61
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    Was just going through my code just now and added a print for the values received and turned out the only reason exponent had no wrong results was because I accidently gave it the wrong starting exponent, with the 210 fixed values disabled and the limit variable set to 2 I get this:
    Code:
    gcc -Wall -o "test_fpn" "test_fpn.c" && "./test_fpn"
    negative 0
    gcc = 00000000000000000000000000000000000000000000000000000000000000000011111111110000000000000000000000000000000000000000000000000000
    mcc = 00000000000000000000000000000000000000000000000000000000000000000100000000100100000000000000000000000000000000000000000000000000
    fpn t = 1.000000e+00 m = 1.000000e+01
    read as 1.0e+1
    value '1e+1'
    Tried = 2, Wrong = 1
    Total Tried = 6, Total Wrong = 1
    negative 0
    gcc = 00000000000000000000000000000000000000000000000000000000000000000011111111110000000000000000000000000000000000000000000000000000
    mcc = 00000000000000000000000000000000000000000000000000000000000000000100000001011001000000000000000000000000000000000000000000000000
    fpn t = 1.000000e+00 m = 1.000000e+02
    read as 1.0e+2
    value '1e+2'
    Tried = 2, Wrong = 1
    Total Tried = 6, Total Wrong = 1
    Compilation finished successfully.

  2. #62
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    Turned out I had accidentally used the wrong text when reading in the values, recitified and now am sure I'm using it mostly correct, just need to fiddle with final position when the resulting pos value is greater than pos_max, see GDB online Debugger | Code, Compile, Run, Debug online C, C++ to understand what I mean (look in 'fpn_make()')

  3. #63
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    Well been doing some more experiments, haven't been able to correct that off by 1 thing so have filtered that output in favour of really wrong results that can't be ignored, just now tried with bigmath involved:
    GDB online Debugger | Code, Compile, Run, Debug online C, C++
    Online it runs fine but offline it enters an infinite loop (or at least takes way longer), got things to do now so hoping someone can at least fix the infinite loop while I'm doing them.

  4. #64
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    Fixed it, I forgot to change a variable name when I copy - pasted AND forgot to convert the orginal hard comparison to soft comparison at the break condition of a loop, the former resulted in a number going back and forth in magnitude while the later would've always proved to be true instead of eventually being false, here's the converted snippet:
    Code:
    while ( pos > 0 && gth__mcc_int( &one, &tmp ) ) {
    		mul__mcc_int( &num, &base );
    		div__mcc_int( &one, &base, &cpy );
    I'm sure you don't need me to specifically state where it should've been since it's easy enough to look for the matching pattern in fpn_make()

  5. #65
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    Haven't been able to fix the function yet but thought I'd share something interesting, I was finding there was a lot of output where inifinity should or should not have been set and so to filter out those results to see if the were any others that were also wrong and just not noticed under the barrage of infinity and off by 1 results and then set the limit for both the exp and the number to transform into a float to 1000 and here is the result:
    Code:
    gcc -Wall -o "test_fpn" "test_fpn.c" && "./test_fpn"
    FLT_DIG 6
    FLT_EXP_BIT 8
    FLT_EPSILON 1.192093e-07
    FLT_MAX_EXP 128
    FLT_MIN_EXP -125
    FLT_MAX_10_EXP 38
    FLT_MIN_10_EXP -37
    FLT_MANT_DIG 24
    FLT_MAN_BIT 23
    FLT_RADIX 2
    FLT_ROUNDS 1
    Total Tried = 6012006, Total Wrong = 13956
    Compilation finished successfully.
    So by the looks of it I only have 2 types of problem left in this to fix and it will ready for use in my compiler project,
    btw while the number wrong is indeed spot on (returned that value from exponent()) the number tried I calculated like this:
    Code:
    i * (i * ((1 + TEST_FPN + TEST_BOTH) * (1 + TEST_NEG)))
    Lemme know if you see a problem with that calculation

  6. #66
    Registered User
    Join Date
    Aug 2019
    Location
    Inside a Singularity
    Posts
    169
    Checked GitHub after quite a few days and saw that you've made the DEV_NEWS.txt file mentioning someone who's Starred/Watched it for notifications. That someone's me btw
    I've been looking at some code (I downloaded them the last time I was on your page) and there's a tonne of stuff that I don't understand but it's opened up so many things for me to learn and google and read about. I've also been reading "Handbook of Floating-Point Arithmetic" (read about 80 pages or so) suggested by @flp in one of the above posts. Great stuff, although there is math involved that I'm not familiar with. Again, googling all of it up made the most sense which taught me quite a lot of stuff in math too! I also like how they start off by mentioning a few famous bugs which I searched about and also learnt about how they were fixed.

    Of the code I've made sense of till now, you've made quite a lot of progress. Great work.

  7. #67
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    Well I half fixed the infinity issue, there's no more values becoming infinite when they shouldn't but the reverse still needs to be fixed for values that should become infinite, gonna catch some shut eye, any ideas on catching the final overflows are welcome:
    Code:
    ...
    	/* Use exponent */
    	pos = temp.exp;
    	temp.raw = 0;
    	temp.raw = ~(temp.raw);
    	temp.raw <<= temp.max_exp - 1;
    	temp.raw = ~(temp.raw);
    	while ( pos > 0 && temp.one > 1 ) {
    		NUM = temp.num;
    		temp.num *= temp.base;
    		if ( temp.num <= NUM ) goto fpn_inf;
    		temp.one /= temp.base;
    		if ( temp.fpn >= temp.one ) {
    			NUM = temp.fpn / temp.one;
    			temp.num += NUM;
    			temp.fpn -= NUM * temp.one;
    		}
    		--pos;
    	}
    	while ( pos > 0 ) {
    		NUM = temp.num;
    		temp.num *= temp.base;
    		if ( temp.num <= NUM ) goto fpn_inf;
    		--pos;
    	}
    	while ( pos < 0 && temp.num ) {
    		NUM = temp.num % temp.base;
    		temp.fpn += NUM * temp.one;
    		NUM = temp.one;
    		temp.one *= temp.base;
    		if ( temp.one <= NUM ) goto fpn_inf;
    		temp.num /= temp.base;
    		pos++;
    	}
    	while ( pos < 0 ) {
    		NUM = temp.one;
    		temp.one *= temp.base;
    		if ( temp.one <= NUM ) goto fpn_inf;
    		pos++;
    	}
    ...

  8. #68
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    Quote Originally Posted by Zeus_ View Post
    Checked GitHub after quite a few days and saw that you've made the DEV_NEWS.txt file mentioning someone who's Starred/Watched it for notifications. That someone's me btw
    I've been looking at some code (I downloaded them the last time I was on your page) and there's a tonne of stuff that I don't understand but it's opened up so many things for me to learn and google and read about. I've also been reading "Handbook of Floating-Point Arithmetic" (read about 80 pages or so) suggested by @flp in one of the above posts. Great stuff, although there is math involved that I'm not familiar with. Again, googling all of it up made the most sense which taught me quite a lot of stuff in math too! I also like how they start off by mentioning a few famous bugs which I searched about and also learnt about how they were fixed.

    Of the code I've made sense of till now, you've made quite a lot of progress. Great work.
    Didn't have a reply for this when I 1st read it but now I do soo...
    It's great to know the user who took enough interest to star mitsy is also using the same forum, if all users/devs that took an interest used the same forum then I wouldn't even need that DEV_NEWS.txt file, but alas life in this world is not perfect. I must've missed that handbook note, anyways I downloaded now to see if it could give me any hints to fixing the final 2 errors of handling

  9. #69
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650

  10. #70
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    I've finally managed to fix some underlying issues with my bignum core functions and big_make() managed to actually produce all (aside from off by 1) correct on the #.0 side of things, now I'm trying to figure out why it won't work on 0.# numbers despite using the same surface logic as fpn_make(), anyways here's another upload: GDB online Debugger | Code, Compile, Run, Debug online C, C++
    Incidentally where fpn_make() fails to set infinity on #.0 values big_make() succeeds so I'm guessing my main issue there was lack of a big enough integer to detect the right condition.

  11. #71
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    I GOT IT!
    Turned out in big_make() I had forgotten to change how I check if there was a whole number or not when I duplicated fpn_make() to transform the logic from hard numbers to soft numbers. So I changed this:
    Code:
    	/* Set exponent */
    	pos = 0;
    	if ( temp.num ) {
    To this:
    Code:
    	/* Set exponent */
    	pos = 0;
    	if ( !mcc__int_is_nil( &num ) ) {
    Currently running it for a double now

  12. #72
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    Seems something about the size caused an infinite loop, either that or it takes too long, either way I'm doing some more checks on the math, switched back to float and did the test for the text and got this (after modifying check() to report infinity mis-match):
    Code:
    gcc -Wall -o "test_fpn" "test_fpn.c" && "./test_fpn"
    one = 1, given 1.0e-100, value 1e-100
    one = 10, given 0.1e-100, value .1e-100
    one = 10, given 1.1e-100, value 1.1e-100
    one = 100, given 3.14e-100, value 3.14e-100
    one = 1, given -1.0e-100, value -1e-100
    one = 10, given -0.1e-100, value -0.1e-100
    one = 10, given -1.1e-100, value -1.1e-100
    one = 100, given -3.14e-100, value -3.14e-100
    Strings = 210
    Text Tried = 210, Text Wrong = 8, Text Off By 1 = 0, Text Not Inf = 0, Text Was Inf = 8
    Compilation finished successfully.
    At the very least this means I only need one function for any base, next is finding that infinite loop (assuming there is one), gonna update the online file now in the hopes someone else can spot why that particular exponent is giving me trouble while I look for why doubles seem to go infinitely.

    Edit:
    GDB online Debugger | Code, Compile, Run, Debug online C, C++
    Fingers are starting to hurt so gonna quit for today.
    Last edited by awsdert; 4 Days Ago at 02:19 PM.

  13. #73
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    Got a bit further with the negative exponent problem, as I suspected it wasn't just -100 causing it, I had tor remove a check for beyond min_exp and put it elsewhere
    GDB online Debugger | Code, Compile, Run, Debug online C, C++
    Code:
    ...
    		if ( pos < temp.min_exp ) {
    			pos -= temp.min_exp;
    			pos = -pos;
    			printf("pos = %ld\n", pos );
    			mcc___int_op_shr( &fpn, pos );
    			mcc___int_op_shr( &one, pos );
    			pos = temp.min_exp;
    		}
    		for ( ; pos < pos_max; ++pos)
    ...
    Output:
    Code:
    gcc -Wall -o "test_fpn" "test_fpn.c" && "./test_fpn"
    flex.exp_bias = 128
    flex.exp_bits = 8
    flex.max_exp_digits = 38
    flex.min_exp_digits = -37
    flex.max_exp = 128
    flex.min_exp = -125
    flex.man_bits = 23
    pos = 2
    gcc = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011011001110001111101110
    mcc = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    gcc.exp = 0000000000000000
    mcc.exp = 0000000000000000
    fpn t = 9.999999e-39 m = 0.000000e+00
    pos = 1
    gcc = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110110011100011111011101
    mcc = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111011001110001111101110
    gcc.exp = 0000000000000001
    mcc.exp = 0000000000000001
    fpn t = 2.000000e-38 m = 2.175494e-38
    Tried = 1521, Wrong = 2, Off By 1 = 0, Not Inf = 0, Was Inf = 0
    scenario = 0
    Compilation finished successfully.
    Edit 1: I fixed it I was doing too much there, only needed to clamp it dow- er up
    Code:
    ...
    		if ( pos < temp.min_exp )
    			pos = temp.min_exp - 1;
    		for ( ; pos < pos_max; ++pos)
    ...
    Currently testing with the limit set to FPN_MAX_EXP
    Edit 2: Seems there's another point where I incorrectly set infinity, looking for that now
    Last edited by awsdert; 3 Days Ago at 05:03 AM.

  14. #74
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    Turned out I was calculating pos wrong from the outset, I now have a variant of this in big_make()
    Code:
    	else {
    		for ( NUM = temp.one; NUM > temp.fpn; --pos, NUM >>= 1 );
    		if ( NUM == temp.fpn ) --pos;
    		if ( pos < temp.min_exp ) goto fpn_inf;
    #if 1
    		if ( pos == -2 ) {
    			printb("fpn = ", &temp.fpn, 16 );
    			putchar('\n');
    			printb("one = ", &temp.one, 16 );
    			putchar('\n');
    			printf("pos = %ld\n", pos );
    		}
    #endif
    	}
    With this output:
    Code:
    gcc -Wall -o "test_fpn" "test_fpn.c" && "./test_fpn"
    flex.exp_bias = 128
    flex.exp_bits = 8
    flex.max_exp_digits = 38
    flex.min_exp_digits = -37
    flex.max_exp = 128
    flex.min_exp = -125
    flex.man_bits = 23
    limit for #.0e+/-#, 0.#e+/-#, #.#e+/-# is 5
    fpn = 0000000000000011
    one = 0000000000001010
    pos = -2
    fpn = 0000000000000100
    one = 0000000000001010
    pos = -2
    fpn = 0000000000000101
    one = 0000000000001010
    pos = -2
    gcc = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111000000000000000000000000
    mcc = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111110100000000000000000000000
    gcc.exp = 0000000001111110
    mcc.exp = 0000000001111101
    fpn t = 5.000000e-01 m = 2.500000e-01
    one = 1, given 5.0e-1, value 5.0e-1
    Tried = 36, Wrong = 1, Off By 1 = 0, Not Inf = 0, Was Inf = 0, Too Soon = 0, Too Late = 0
    scenario = 0
    Compilation finished successfully.

  15. #75
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    650
    While I was looking for understandable docs on reading negative exponents I found this:
    String To Floating Point Number Conversion
    So I'm gonna make use of that in my free time to start again using the current code as a reference point to get me started, hopefully that will get me past this issue and finally started on the expression handler part of my compiler

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ and Math
    By darren78 in forum C++ Programming
    Replies: 2
    Last Post: 07-08-2010, 09:19 AM
  2. hex math
    By kroiz in forum C Programming
    Replies: 25
    Last Post: 01-20-2009, 03:46 PM
  3. Basic Math Problem. Undefined Math Functions
    By gsoft in forum C Programming
    Replies: 1
    Last Post: 12-28-2004, 03:14 AM
  4. math.h
    By sweets in forum C++ Programming
    Replies: 2
    Last Post: 05-05-2003, 01:27 PM
  5. Math Help
    By CAP in forum C Programming
    Replies: 2
    Last Post: 08-19-2002, 12:03 AM

Tags for this Thread