### Author Topic: fpu example  (Read 36012 times)

#### jcfuller

• Member
• Posts: 195
##### fpu example
« on: March 26, 2013, 11:10:51 PM »
Sorry if this is the wrong place for this.
My fpu coding is horrid at best.
How would you code this "c" example in this post of mine.(jwasm or masm)
http://cboard.cprogramming.com/c-programming/155373-verify-mingw-issue.html
Do you feel it is unrealistic to expect 1267?
It is beginning to appear only gcc and BCc 5.5 return 1266.

James

#### jj2007

• Member
• Posts: 13657
• Assembly is fun ;-)
##### Re: fpu example
« Reply #1 on: March 26, 2013, 11:49:49 PM »
The result depends only on the FPU rounding mode. If it's "down", then 1266.9999999999997730 becomes indeed 1266...

include \masm32\include\masm32rt.inc
.code
start:
fld FP8(12.67)
push 100
fild dword ptr [esp]
fmul
fistp dword ptr [esp]
pop eax
inkey str\$(eax)
exit
end start

#### MichaelW

• Global Moderator
• Member
• Posts: 1196
##### Re: fpu example
« Reply #2 on: March 26, 2013, 11:57:44 PM »
Yes, using the FPU directly, and with everything at the defaults I get 1267, but by changing the rounding mode I can get 1266.
Code: [Select]
`;==============================================================================    include \masm32\include\masm32rt.inc;==============================================================================FRC_NEAREST   equ  0     ; or to even if equidistant (initialized state)FRC_DOWN      equ 400h   ; toward -infinityFRC_UP        equ 800h   ; toward +inifinityFRC_TRUNCATE  equ 0c00h  ; toward zeroSETRC MACRO rc    IFNDEF __fpu__cw__        .data?            __fpu__cw__ dw ?        .code    ENDIF    fstcw __fpu__cw__    and __fpu__cw__, NOT 0c00h    or  __fpu__cw__, rc    fldcw __fpu__cw__ENDM;==============================================================================    .data    .code;==============================================================================foo proc d:REAL8    printf("%.15G\n", d)    fld8 100.0    fld d    fmul    push eax    fistp DWORD PTR [esp]    pop eax    retfoo endp;==============================================================================start:;==============================================================================    invoke foo, FP8(12.67)    printf("%d\n",eax)    SETRC FRC_DOWN    invoke foo, FP8(12.67)    printf("%d\n",eax)    SETRC FRC_UP    invoke foo, FP8(12.67)    printf("%d\n",eax)    SETRC FRC_TRUNCATE    invoke foo, FP8(12.67)    printf("%d\n\n",eax)    inkey    exit;==============================================================================end start`
Code: [Select]
`12.67126712.67126612.67126712.671266`
In the C code you should be able to display the current FPU rounding mode, but then there is the possibility that one is using SSE2 instead of the FPU, and I can’t conveniently test the effects of that ATM.
Well Microsoft, here’s another nice mess you’ve gotten us into.

#### qWord

• Member
• Posts: 1475
• The base type of a type is the type itself
##### Re: fpu example
« Reply #3 on: March 27, 2013, 12:14:14 AM »
this "c" example
According to the C (ISO) standard, floating point values are truncated when they are converted to integer values (return d*100). Therefore 1266 is conform result.

EDIT: the same applies for c++
MREAL macros - when you need floating point arithmetic while assembling!

#### jcfuller

• Member
• Posts: 195
##### Re: fpu example
« Reply #4 on: March 27, 2013, 12:39:20 AM »
I checked the rounding mode with fegetround() and gcc (MinGW),  gcc(MinGwTDM) and PellesC all return zero but as stated
only gcc (MinGW) displays 1266 so it appears something else is causing the difference?

James

#### qWord

• Member
• Posts: 1475
• The base type of a type is the type itself
##### Re: fpu example
« Reply #5 on: March 27, 2013, 01:27:41 AM »
I can reproduce that by setting the precision to REAL10, rounding mode = nearest, doing the calculation and then change the rounding mode to truncate (round to zero).  When storing the integer result, I get also 1266. If the precision is REAL8, 1267 is the result.
You might try to check the constant FLT_EVAL_METHOD.
MREAL macros - when you need floating point arithmetic while assembling!

#### dedndave

• Member
• Posts: 8828
• Still using Abacus 2.0
##### Re: fpu example
« Reply #6 on: March 27, 2013, 01:53:12 AM »
the only place i see "finit" on this page is where Michael mentions infinity

#### jcfuller

• Member
• Posts: 195
##### Re: fpu example
« Reply #7 on: March 27, 2013, 01:55:31 AM »
Thanks everyone.
As I never do any thing in moderation and can become obsessed at the drop of a ... I persisted to see why the difference?

This is my latest test piece. When compiled with the newest 32bit gcc 4.8.0 only the first one displays 1266

James

Code: [Select]
`#include <stdio.h>#include <math.h>int     foo (double);int     main (int,char**);int foo (double d){  printf("%s% .15G\n","d = ",(double)d);return (d*100);      // 1266//return ceil(d*100);  // 1267//return floor(d*100); // 1267//return trunc(d*100); // 1267//return round(d*100);   // 1267}int main (int argc,char** argv){  int      rv={0};  double d =12.67;  rv= foo( d);  printf("%s% d\n","rv = ",(int)rv);  return 0;}`

#### jj2007

• Member
• Posts: 13657
• Assembly is fun ;-)
##### Re: fpu example
« Reply #8 on: March 27, 2013, 02:33:36 AM »
the only place i see "finit" on this page is where Michael mentions infinity

On program entry the FPU setting is NEAR, 53 bits. Here is an extended example.

Code: [Select]
`include \masm32\include\masm32rt.inc.codestart:   fld FP8(12.67)   push 100   fild dword ptr [esp]   fmul   fistp dword ptr [esp]   pop eax   print str\$(eax), 13, 10 ; default setting is NEAR, 53 ->1267  push 847Fh ; DOWN, 24 ->1266   fldcw word ptr [esp]   pop eax   fld FP8(12.67)   push 100   fild dword ptr [esp]   fmul   fistp dword ptr [esp]   pop eax   print str\$(eax), 13, 10  push 807Fh ; NEAR, 24 ->1267   fldcw word ptr [esp]   pop eax   fld FP8(12.67)   push 100   fild dword ptr [esp]   fmul   fistp dword ptr [esp]   pop eax   inkey str\$(eax)   exitend start`

#### qWord

• Member
• Posts: 1475
• The base type of a type is the type itself
##### Re: fpu example
« Reply #9 on: March 27, 2013, 02:34:15 AM »
As it has already said, there are two problem: one is the different evaluation precision of the compilers and the other is the truncation on double->int conversion.
If you get 1266 or 1267, depends of the result of d*100: if the result is a bit larger or equal than 1267, it will be truncate to this number, otherwise it will get 1266.
Many C/C++ compiler use 53 Bit precision for evaluation, where the calculation's result seems to be  a bit larger (or equal) than 1267 (due rounding of the result). GCC (32Bit) does use 64 Bit precision and the result is below 1267. Therefore GCC truncate the result to 1266 whereas the other compilers shows the intuitive result. For the other function (ceil, floor,...) it is that they have a double argument, thus GCC will do a conversion from 64 to 53 bit precision -> the value gets 1267 before the actual function is called.
MREAL macros - when you need floating point arithmetic while assembling!

#### dedndave

• Member
• Posts: 8828
• Still using Abacus 2.0
##### Re: fpu example
« Reply #10 on: March 27, 2013, 02:44:26 AM »
Jochen, yes - that's how the windows os sets it up for us
but, the C compiler init code may set it up differently

• Member
• Posts: 249
##### Re: fpu example
« Reply #11 on: March 27, 2013, 03:30:11 AM »
I could remark that in all cases got 1267, so my opinion that it's gone from differ bitwise 12.67 constant inputing of differ runtimes. So basically in this topic need hex dump of mentioned values, so we'll never get clear answer.

#### jcfuller

• Member
• Posts: 195
##### Re: fpu example
« Reply #12 on: March 27, 2013, 04:37:30 AM »
As I said before MingwTDM,tcc,PellesC,FreeBASIC,PowerBASIC,VC all display 1267.

I am trying to figure out why gcc would or want to be different?

I guess I need to find out how to communicate with the builders.

James

Edit: gcc on 32bit linux displays 1266 also.

#### Gunther

• Member
• Posts: 4159
• Forgive your enemies, but never forget their names
##### Re: fpu example
« Reply #13 on: March 27, 2013, 07:06:50 AM »
Hi James,

As I said before MingwTDM,tcc,PellesC,FreeBASIC,PowerBASIC,VC all display 1267.

I am trying to figure out why gcc would or want to be different?

I guess I need to find out how to communicate with the builders.

James

Edit: gcc on 32bit linux displays 1266 also.

yes, and that's all right, because it has to do with the C standard. Qword did explain it very well. The answer to your question is in reply #3 and #9 of this thread.

Gunther
You have to know the facts before you can distort them.

#### jcfuller

• Member
• Posts: 195
##### Re: fpu example
« Reply #14 on: March 27, 2013, 09:16:28 AM »
Gunther,
Yes I did read that a little fast and it does answer the what (thanks Qword) but it still does not answer the why when it appears almost all (clang on 32bit linux returns 1267 too) other compilers use 53 bit??

James