Recent

Author Topic: Problem with round function  (Read 2086 times)

VTwin

  • Hero Member
  • *****
  • Posts: 775
  • Former Turbo Pascal 3 user
Re: Problem with round function
« Reply #30 on: August 31, 2019, 08:08:50 pm »
Thanks Thaddy, but I already knew it was a stupid mistake. :D I neglected to check the implementation, my fault. I have used C and C++ fairly extensively in the past, and, as you point out, implementations are not standard. They don't even agree on the return type.

In my case the mistakes were restricted to graphics-related code, and the damage limited to a displaced pixel. No statistical or monetary functions were harmed.

I learned Pascal using Turbo Pascal in the 1980s, and neglected to check if the FPC and TP Round functions were the same. They are not. I don't follow your point about "clear and strict reference for the ISO" though, it seems FPC does not follow ISO here.
« Last Edit: August 31, 2019, 08:19:35 pm by VTwin »
“Talk is cheap. Show me the code.” -Linus Torvalds

macOS 10.13.6: Lazarus 2.0 fixes svn 61930 (64 bit Cocoa)
Ubuntu 18.04.3: Lazarus 2.0.4 (64 bit on VBox)
Windows 7 Pro SP1: Lazarus 2.0.4 (64 bit on VBox)
fpc 3.0.4

Steven Pietrobon

  • New Member
  • *
  • Posts: 13
Re: Problem with round function
« Reply #31 on: September 01, 2019, 09:21:02 am »
Here is output with {$N-} switch.

Not sure why it is not working. For some reason, ppc386 says that the $N switch does not exist!

Free Pascal Compiler version 3.0.4 [2017/10/06] for i386
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling qroot.pas
qroot.pas(5,2) Warning: Unsupported switch "$N"


Try outputting the real value like so:

Function NthRoot(b, n: Longint): Longint;
Begin
  writeln(Exp((1/n)*Ln(b)));
  NthRoot := Trunc(Exp((1/n)*Ln(b)));
End;


Here is the result I get (Windows XP 32-bit)

 2.00000000000000000000E+0000
ta[v] = 8, ir = 2
 3.00000000000000000022E+0000
ta[v] = 27, ir = 3
 4.00000000000000000000E+0000
ta[v] = 64, ir = 4
 5.00000000000000000000E+0000
ta[v] = 125, ir = 5
« Last Edit: September 01, 2019, 09:47:05 am by Steven Pietrobon »

Thaddy

  • Hero Member
  • *****
  • Posts: 8967
Re: Problem with round function
« Reply #32 on: September 01, 2019, 10:04:25 am »
The N switch is simply not supported. File a report.
Most people that want to use threading should learn to patch their jeans first: use a needle.

BrunoK

  • Full Member
  • ***
  • Posts: 181
  • Retired programmer
Re: Problem with round function
« Reply #33 on: September 01, 2019, 12:26:38 pm »
As previously written, anybody using CEIL, TRUNC, ROUND must understand what the intent of the used function is and know the kind of numbers that would be processed.
This is due to small differences in mathematical / arithmetic operations on double.
Not being aware of that fact may mean you can have horribly wrong results.
AND no, it is NOT a BUG.

Example program :
Code: Pascal  [Select]
  1. program NthRoot;
  2.  
  3. function NThRoot(b, n : integer):double;
  4. begin
  5.   Result := Exp((1/n)*Ln(b));
  6. end;
  7.  
  8. var
  9.   dbl : double;
  10.   b, n : integer;
  11. begin {NThRoot test}
  12.   {$ifdef cpu32}
  13.   WriteLn('cpu32');
  14.   {$ELSE}
  15.     {$ifdef cpu64}
  16.     WriteLn('cpu64');
  17.     {$ELSE}
  18.     WriteLn('cpu ???');
  19.     {$ENDIF}
  20.   {$ENDIF}
  21.   for b in [8,27,64,125] do begin
  22.     dbl := nThRoot(b ,3);
  23.     writeln('nThRoot(',b,', 3) = ',dbl,' trunc(nThRoot) = ', trunc(dbl));
  24.   end;
  25.   readln;
  26. end.  {NThRoot test}        
  27.  
Results :
Code: Pascal  [Select]
  1. cpu32
  2. nThRoot(8, 3) =  2.0000000000000000E+000 trunc(nThRoot) = 2
  3. nThRoot(27, 3) =  3.0000000000000000E+000 trunc(nThRoot) = 3
  4. nThRoot(64, 3) =  4.0000000000000000E+000 trunc(nThRoot) = 4
  5. nThRoot(125, 3) =  5.0000000000000000E+000 trunc(nThRoot) = 5
  6.  
Code: Pascal  [Select]
  1. cpu64
  2. nThRoot(8, 3) =  1.9999999999999998E+000 trunc(nThRoot) = 1
  3. nThRoot(27, 3) =  2.9999999999999996E+000 trunc(nThRoot) = 2
  4. nThRoot(64, 3) =  3.9999999999999991E+000 trunc(nThRoot) = 3
  5. nThRoot(125, 3) =  5.0000000000000009E+000 trunc(nThRoot) = 5
  6.  
Lazarus trunk r. 59978/03.01.2019 (+/- patches regarding enabled, TScrollBar, TCursorImage). FPC 3.0.4 32 bits. (+heaptrc with leaked ClassName+Revisited TList) , Windows 10 Pro x64 (v. 1903)

Thaddy

  • Hero Member
  • *****
  • Posts: 8967
Re: Problem with round function
« Reply #34 on: September 01, 2019, 12:34:31 pm »
Well, the non-conformation to ISO in any ISO mode IS a bug.... How would you argue against it? <bemused, not worth a  >:D  grumpy>
Most people that want to use threading should learn to patch their jeans first: use a needle.

Kays

  • Full Member
  • ***
  • Posts: 182
  • Whasup!?
    • KaiBurghardt.de
Re: Problem with round function
« Reply #35 on: September 02, 2019, 01:37:44 am »
[…] Rounding is not influenced by the modes.
Huh? Well, then issue #35626 has to be closed right away.
My answer explained the current state of affairs which is that the modes don't influence the rounding. […]
Alright, I see.

[…]
Not sure why it is not working. For some reason, ppc386 says that the $N switch does not exist! […]

qroot.pas(5,2) Warning: Unsupported switch "$N"
[…]
It doesn’t say, it doesn’t exist, but it’s ignored, since it’s unsupported.

The N switch is simply not supported. File a report.
No, don’t. It’s documented, that it’s recognized for compatibility only.
Yours Sincerely
Kai Burghardt

Steven Pietrobon

  • New Member
  • *
  • Posts: 13
Re: Problem with round function
« Reply #36 on: September 02, 2019, 01:56:46 am »
As previously written, anybody using CEIL, TRUNC, ROUND must understand what the intent of the used function is and know the kind of numbers that would be processed.
This is due to small differences in mathematical / arithmetic operations on double.
Not being aware of that fact may mean you can have horribly wrong results.
AND no, it is NOT a BUG.

Are you sure? The trunc function is working correctly, but the 64 bit CPU real calculation is giving less accurate results than the 32 bit CPU real calculation!!!
« Last Edit: September 02, 2019, 02:00:51 am by Steven Pietrobon »

Thaddy

  • Hero Member
  • *****
  • Posts: 8967
Re: Problem with round function
« Reply #37 on: September 02, 2019, 06:22:15 am »
Are you sure? The trunc function is working correctly, but the 64 bit CPU real calculation is giving less accurate results than the 32 bit CPU real calculation!!!
Well, that's only on windows... as documented...
Most people that want to use threading should learn to patch their jeans first: use a needle.

PascalDragon

  • Hero Member
  • *****
  • Posts: 636
  • Compiler Developer
Re: Problem with round function
« Reply #38 on: September 02, 2019, 10:10:50 am »
The N switch is simply not supported. File a report.
No, don’t. It’s documented, that it’s recognized for compatibility only.
Though that could change depending on the outcome of bug report #35626.

As previously written, anybody using CEIL, TRUNC, ROUND must understand what the intent of the used function is and know the kind of numbers that would be processed.
This is due to small differences in mathematical / arithmetic operations on double.
Not being aware of that fact may mean you can have horribly wrong results.
AND no, it is NOT a BUG.

Are you sure? The trunc function is working correctly, but the 64 bit CPU real calculation is giving less accurate results than the 32 bit CPU real calculation!!!
Only the i386 and i8086 targets as well as the x86_64 ones with the exception of Win64 have a separate Extended (10-bit floating point) type. All other targets have Extended as an alias to Double, because their FPUs do not support 10-bit floating point numbers. As the compiler always calculates with the highest available precision there will be differences between the platforms.

Steven Pietrobon

  • New Member
  • *
  • Posts: 13
Re: Problem with round function
« Reply #39 on: September 03, 2019, 06:56:32 am »
Thanks for that explanation PascalDragon. I'm a bit puzzled why x86_64 win32 supports extended (10 byte real), while x86_64 win64 only supports double (8 byte real). Is this something Intel did to increase speed?

Thaddy

  • Hero Member
  • *****
  • Posts: 8967
Re: Problem with round function
« Reply #40 on: September 03, 2019, 09:15:20 am »
No, it is simply that Microsoft changed their ABI for Windows64 to only support double. There are ways - undocumented and not supported - to compile FPC to support 80 bit precision under Windows 64 but you would loose MS ABI compatibility for 64 bit Windows. I seem to remember Florian himself wrote here on how to do that...(about 1-2 years ago? )
Microsoft made the choice to only support double (or multiples of double) and it has nothing to do with Intel. The hardware still supports it, hence you CAN compile FPC x86_64-win64 to use the 80 bit precision. If you know what you are doing... MS decided to only support SSE and AVX families...
« Last Edit: September 03, 2019, 09:31:50 am by Thaddy »
Most people that want to use threading should learn to patch their jeans first: use a needle.

Steven Pietrobon

  • New Member
  • *
  • Posts: 13
Re: Problem with round function
« Reply #41 on: September 04, 2019, 06:38:59 am »
Thanks Thaddy. Seems like a dumb decision by Microsoft. This means that if you want more precision than 8 bytes, you need to do your calculations in software!

Perhaps Free Pascal needs to add these software floating point options, so that extended is true extended (10 bytes), as well as adding triple and quadruple for 12 and 16 byte precision.
« Last Edit: September 04, 2019, 06:45:55 am by Steven Pietrobon »

Thaddy

  • Hero Member
  • *****
  • Posts: 8967
Re: Problem with round function
« Reply #42 on: September 04, 2019, 08:32:14 am »
This means that if you want more precision than 8 bytes, you need to do your calculations in software!
Well, not quite, but it - as it stands - requires some usually simple assembler routines and all the required instructions are supported up to even 512 bits ( if the processor supports it ).
(MS C(++) achieves the same with intrinsics for 128,256 and 512 bits)
I would not be surprised if FPC supports similar on a high language level in the future.  There are already rudimentary signs of this in the compiler code,
« Last Edit: September 04, 2019, 08:35:30 am by Thaddy »
Most people that want to use threading should learn to patch their jeans first: use a needle.

PascalDragon

  • Hero Member
  • *****
  • Posts: 636
  • Compiler Developer
Re: Problem with round function
« Reply #43 on: September 09, 2019, 10:14:31 am »
Perhaps Free Pascal needs to add these software floating point options, so that extended is true extended (10 bytes), as well as adding triple and quadruple for 12 and 16 byte precision.
It is indeed planned to at least support 10-Byte floating point in software, cause currently it's not trivially possible to cross compile the compiler from x86_64-win64 to i386-win32 (or any other platform without Extended support to i386).