[offtopic] FreePascal

General discussion for topics related to the FreeBASIC project or its community.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: [offtopic] FreePascal

Post by dodicat »

Thanks for testing Roland.
freepascal doesn't have easy to use graphics (as far as I can see)
I have forgotten how to use wingraph.
And the graph unit seems tricky to use.

I have just tested the 32 bit graph code with a 64 bit dll and a 64 bit compiler.
Seems OK.
I notice that beep with 32 bits sounds different.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: [offtopic] FreePascal

Post by srvaldez »

dodicat, if you are interested,here's the fpc-32-bit
let me know if or when you have downloaded so I can remove the link, if not, I will remove the link after one day
Last edited by srvaldez on Oct 30, 2018 3:15, edited 1 time in total.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: [offtopic] FreePascal

Post by srvaldez »

Carlos Herrera wrote: Speed is one factor, another is accuracy. Please consider the following program

Code: Select all

(*-----------------------------------------------------------------------*)
(* EPSMACH computes the machine accuracy u (1.0+u>1.0,1.0+u/2=1.0)       *)
(*-----------------------------------------------------------------------*)
VAR II: INTEGER;
VAR ONE,TWO,U,EPSMACH: double;
BEGIN
	II:= 0;
	ONE:=1.0; TWO:=2.0; U:=1.0;
    REPEAT
      U:=U/TWO;
      II:=II+1;
    UNTIL ( (ONE+U)=ONE );
    EPSMACH := TWO*U;
    writeln (II, EPSMACH);
    readln;
END.
which is adopted from O. Montenbruck, T. Pfleger, Astronomy on the Personal Computer (Springer, 1998).

Free Pascal (3.0.4) results are:
53, 2.2204460...E-16.
Exactly the same results are obtained for FB64, however, FB32 (1.05.0) gives
64, 1.0842921..E-19.

So, apparently FB32 uses x87 instruction set, which is more accurate but slower...
if you want to use the FPU when compiling with FB x64 then pass the following flag on the compile command -Wc -mfpmath=387 ,for example
G:\FreeBASIC-1.06.0-win64\fbc -w all -asm intel -gen gcc -Wc -O2,-mfpmath=387 -v epsmach.bas
in my opinion the result of 64, 1.0842921..E-19 for double is wrong
Last edited by srvaldez on Oct 30, 2018 3:18, edited 1 time in total.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: [offtopic] FreePascal

Post by dodicat »

Thanks srvaldez, I have downloaded the file.
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: [offtopic] FreePascal

Post by marcov »

srvaldez wrote:in my opinion the result of 64, 1.0842921..E-19 for double is wrong
The result is never wrong. The code, and the whole principle of it is then wrong (and it has been wrong as long as the x87 CPU exists, quite a time), as it doesn't factor into the equation that a FPU might implement double with larger registers, and that inbetween results are not rounded to storage size (double in this case)

In C you could maybe solve it by making the variable volatile.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: [offtopic] FreePascal

Post by srvaldez »

hello marcov, the code obviously is designed to give the bits of precision and epsilon of the type double which it doesn't when using the FPU, which suggest to me that the FPU precision flag is not set properly and therefore gives the wrong result
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: [offtopic] FreePascal

Post by marcov »

srvaldez wrote:hello marcov, the code obviously is designed to give the bits of precision and epsilon of the type double
That was probably the intention, but the approach is incomplete and simply wrong if you are honest, and naive if you want to sugar coat it. At the very least the variable should be volatile, so that a read and write are always synchronized with the variable.

It looks something like a ported code fragment from some eighties compiler or interpreter that happened to work on those systems, because as ancient as they are, they didn't have any form of hardware floating point or optimization for floating point. Or from C but skipping the volatile modifier.

As usual, code that seems to work at first glance is not necessarily correct.
which it doesn't when using the FPU,
As I said in the original mail, IF you have some minimal optimization (like keeping results in registers), AND your floating point implementation uses larger registers than the variable type (also e.g. softfloat that often doesn't implement all sizes), this is the expected result. Also per IEEE standard afaik.
which suggest to me that the FPU precision flag is not set properly and therefore gives the wrong result
This has nothing to do with precision. If you enable FPU exceptions, you'd get an over/underflow on the conversion of the extended back to double, but the result doesn't change. But since everything are local variables that only live till the end of the procedure (or with optimization even less, last use), that store might even get eliminated, so that is no guarantee either.
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: [offtopic] FreePascal

Post by marcov »

I checked with a compiler dev, and writes to volatile vars are not necessarily serialized with reads, so that makes the volatile suggestion uncertain too.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: [offtopic] FreePascal

Post by jj2007 »

I made a quick test in assembler:

Code: Select all

    REPEAT
      U:=U/TWO;
      II:=II+1;
    UNTIL ( (ONE+U)=ONE );
    EPSMACH := TWO*U;
becomes

Code: Select all

include \masm32\MasmBasic\MasmBasic.inc
  SetGlobals II, double Two=2.0, U=1.0, REAL10 tmpvar, EpsMach
  Init
  .Repeat
	fld U
	fld Two
	fdiv
	fstp U	; U:=U/TWO
	Print Str$("U=%Jf\n", U)
	inc II
	fld1		; One
	fld U
	fadd ST, ST(1)
	fstp tmpvar
	Fcmp tmpvar, ST, top	; comparing tmpvar with U+1, top precision
	fstp st
  .Until Zero?
  fld U
  fld st
  faddp
  fstp EpsMach
  Inkey Str$("E=%Jf\n", EpsMach)
EndOfCode
Output:

Code: Select all

U=0.5000000000000000000
U=0.2500000000000000000
U=0.1250000000000000000
U=0.06250000000000000000
U=0.03125000000000000000
...
U=1.734723475976807094e-18
U=8.673617379884035472e-19
U=4.336808689942017736e-19
U=2.168404344971008868e-19
U=1.084202172485504434e-19
E=2.168404344971008868e-19
What's the purpose the last value here? Equality is reached at 1.084e-19.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: [offtopic] FreePascal

Post by srvaldez »

@marcov
you make good points, the code is ancient probably from before floating point hardware

@jj2007
the code is supposed to simulate a mantissa right-shift to determine the number of significant bits of the type double
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: [offtopic] FreePascal

Post by marcov »

jj2007: if you don't print, you don't need to get the value of the stack. It remains in a x87 register. That is what causes the problem.

From what I see you forcedly pop and fld the value again, so that will probably work and give the low number. At least if you type it 8-byte instead of 10.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: [offtopic] FreePascal

Post by jj2007 »

marcov wrote:jj2007: if you don't print, you don't need to get the value of the stack. It remains in a x87 register. That is what causes the problem.
No problem, tmpVar is REAL10. What I forgot is that top precision still leaves one LSB of tolerance; there is xtra precision, and that one produces exactly the same as FPC32.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: [offtopic] FreePascal

Post by srvaldez »

@marcov
here's the point I was trying to make, this code works correctly
to compile with FB x64 do: fbc -w all -asm intel -gen gcc -Wc -O2,-mfpmath=387 epsmach.bas
to compile with FB x86 do: fbc -w all epsmach.bas
the result for both is: 53, 2.220446049250313e-016

Code: Select all

/'-----------------------------------------------------------------------'/
/' EPSMACH computes the machine accuracy u (1.0+u>1.0,1.0+u/2=1.0)       '/
/'-----------------------------------------------------------------------'/
dim as integer II
dim as double ONE,TWO,U,EPSMACH
dim as ushort oldcw, cw=&h27F

asm
	fstcw word ptr [oldcw]
	fldcw word ptr [cw] 'set FPU precision to double
end asm
II= 0
ONE=1.0 : TWO=2.0 : U=1.0
do
	U=U/TWO
	II=II+1
loop UNTIL ( (ONE+U)=ONE )
EPSMACH = TWO*U
asm
	fldcw word ptr [oldcw] 'restore control word
end asm
print II, EPSMACH
sleep

srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: [offtopic] FreePascal

Post by srvaldez »

here's a nice introduction to Object Pascal http://newpascal.org/assets/modern_pasc ... ction.html
Post Reply