Recent

Author Topic: val return code  (Read 4078 times)

dhatlestad

  • Newbie
  • Posts: 2
val return code
« on: May 21, 2025, 08:41:24 pm »
I am not sure what the return code from val() is supposed to be. If I try to convert a number in val() that is too large for a floating point Double, say 1e310, I do not get an error and the return code is 0. The converted Double is '+inf' in the debugger. Seems reasonable to convert to positive infinite for an overflow but it seems like throwing an overflow exception would be better. The return code from val() does not appear to have an expected meaning or value. Maybe the {$R+} directive would help? The trunc() function does not like the value 1e42, of course, because it is too large for an int64 value, that is, larger than 9,223,372,036,854,775,807. The trunc() function throws an exception, as expected, when the value is too large. Perhaps it would be better to check in your code to see if the converted real number is less than the maximum for an int64.

Tested on Lazarus version 4.0; FPC version 3.2.2; win64.

dsiders

  • Hero Member
  • *****
  • Posts: 1679
Re: val return code
« Reply #1 on: May 21, 2025, 10:43:31 pm »
I am not sure what the return code from val() is supposed to be. If I try to convert a number in val() that is too large for a floating point Double, say 1e310, I do not get an error and the return code is 0. The converted Double is '+inf' in the debugger. Seems reasonable to convert to positive infinite for an overflow but it seems like throwing an overflow exception would be better. The return code from val() does not appear to have an expected meaning or value. Maybe the {$R+} directive would help? The trunc() function does not like the value 1e42, of course, because it is too large for an int64 value, that is, larger than 9,223,372,036,854,775,807. The trunc() function throws an exception, as expected, when the value is too large. Perhaps it would be better to check in your code to see if the converted real number is less than the maximum for an int64.

Tested on Lazarus version 4.0; FPC version 3.2.2; win64.

This has nothing to do with Release 4.0 of the IDE. This is a discussion about RTL.

Start another thread.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
Re: val return code
« Reply #2 on: May 22, 2025, 12:39:50 pm »
I splitted it off

Thaddy

  • Hero Member
  • *****
  • Posts: 19623
  • Glad to be alive.
Any "programmer" that knows only one programming language is not a programmer

dhatlestad

  • Newbie
  • Posts: 2
Re: val return code
« Reply #4 on: May 22, 2025, 07:18:57 pm »
Thank you for splitting this topic to another thread. For context, my post about the val() function is in reference to https://forum.lazarus.freepascal.org/index.php/topic,71050.msg555506.html#msg555506. Perhaps that should have been the first post in this new thread.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6421
  • Compiler Developer
Re: val return code
« Reply #5 on: May 22, 2025, 08:46:06 pm »
The return code from val() does not appear to have an expected meaning or value.

No, Val does not use exceptions. And for floating point it's perfectly valid to convert it to Infinity if the value is too large (same as values that aren't exactly representable will just be converted to the next best floating point number). The result code is for parsing errors.

avk

  • Hero Member
  • *****
  • Posts: 837
Re: val return code
« Reply #6 on: July 10, 2026, 07:27:25 am »
...
No, Val does not use exceptions. And for floating point it's perfectly valid to convert it to Infinity if the value is too large ...

Let's try to check it.
Code: Pascal  [Select][+][-]
  1. program test;
  2. {$mode objfpc}
  3. uses
  4.   SysUtils;
  5.  
  6. function TryStrToDouble(const s: string; out d: Double): Boolean;
  7. var
  8.   q: QWord absolute d;
  9.   c: Integer;
  10. begin
  11.   WriteLn('Input: ', s);
  12.   Result := False;
  13.   try
  14.     Val(s, d, c);
  15.     Result := c = 0;
  16.   except
  17.     on e: Exception do begin
  18.       WriteLn(e.ClassName, ' on call Val()');
  19.       WriteLn('Code: ', c);
  20.       WriteLn('Output bits: ', q.ToHexString(16));
  21.     end;
  22.   end;
  23. end;
  24.  
  25. procedure DoTest(const s: string);
  26. var
  27.   d: Double;
  28.   q: QWord absolute d;
  29. begin
  30.   if TryStrToDouble(s, d) then begin
  31.     WriteLn('Conversion success');
  32.     WriteLn('Output bits: ', q.ToHexString(16));
  33.     try
  34.       WriteLn('Output: ', d);
  35.     except
  36.       on e: Exception do
  37.         WriteLn(e.ClassName, ' on print');
  38.     end;
  39.   end else
  40.     WriteLn('Conversion failure');
  41. end;
  42.  
  43. var
  44.   s: string;
  45. begin
  46.   WriteLn('FPC-', {$i %FPCVersion}, ' ', {$i %FPCTargetCPU}, '-', {$i %FPCTargetOs});
  47.   s := '-42e308';
  48.   DoTest(s);
  49. end.
  50.  

win64:
Code: [Select]
FPC-3.2.2 x86_64-Win64
Input: -42e308
Conversion success
Output bits: FFF0000000000000
Output:                     -Inf
So far so good.

win32:
Code: [Select]
FPC-3.2.2 i386-Win32
Input: -42e308
EOverflow on call Val()
Code: 0
Output bits: 0141FF600023B958
Conversion failure
Hmm...

Linux:
Code: [Select]
FPC-3.2.3 x86_64-Linux
Input: -42e308
Conversion success
Output bits: 0000000000000000
Output: EOverflow on print
Oops...

LeP

  • Guest
Re: val return code
« Reply #7 on: July 10, 2026, 09:17:21 am »
This is with Delphi (same code of @rvk):

Quote
Delphi ver. 37.0.59082.6021 On Linux = False ,On Win64 = False ,On Win32 = True
Input: -42e308
Conversion success
Output bits: FFF0000000000000
Output:                    -Inf

Delphi ver. 37.0.59082.6021 On Linux = False ,On Win64 = True ,On Win32 = False
Input: -42e308
Conversion success
Output bits: FFF0000000000000
Output:                    -Inf

Delphi ver. 37.0.59082.6021 On Linux = True ,On Win64 = False ,On Win32 = False
Input: -42e308
Conversion success
Output bits: FFF0000000000000
Output:                    -Inf

I think that something should be updated on RTL, simple.

I don't know if those results are right or not, but it's better to have one single behavior in all platform that 3 differents issues ....
« Last Edit: July 10, 2026, 09:19:10 am by LeP »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
Re: val return code
« Reply #8 on: July 10, 2026, 09:55:55 am »
To access the state it is smarter to first check with 3.3.1, as that is where most of the development of the last 8 years went.

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 469
  • FPC git[main] Lazarus git[main] 💪🐯💪
Re: val return code
« Reply #9 on: July 10, 2026, 12:39:46 pm »
UPD: Hmm, I think I just masked the exception generation.

Let's try to check it.
But it's true ) the exception doesn't occur in Val itself )
It happens after the call

By the way, I managed to fix it, though I don't fully understand why, since I haven't worked closely with the FPU

Add this code to the beginning of the program (target: Win32 x386):
Code: Pascal  [Select][+][-]
  1. begin
  2.   asm
  3.     finit
  4.   end;
  5. ...

Code: [Select]
FPC-3.3.1 i386-Win32
Input: -42e308
Conversion success
Output bits: FFF0000000000000
Output:                     -Inf
« Last Edit: July 10, 2026, 05:35:21 pm by ALLIGATOR »

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 469
  • FPC git[main] Lazarus git[main] 💪🐯💪
Re: val return code
« Reply #10 on: July 10, 2026, 06:49:08 pm »
I've isolated the code causing the problem.
On Win64, it works fine, but on x32, it throws an exception.

Code: Pascal  [Select][+][-]
  1. program app;
  2.  
  3. {$ifdef FPC}{$asmmode intel}{$endif}
  4. procedure test; assembler;
  5. var
  6.   r: TExtended80Rec;
  7.   e: Extended absolute r;
  8.   d: Double;
  9. asm
  10.   mov word ptr r[0], $8F6C
  11.   mov word ptr r[2], $2BBA
  12.   mov word ptr r[4], $FCFE
  13.   mov word ptr r[6], $BAE7
  14.   mov word ptr r[8], $C403
  15.   fld e
  16.   fstp d
  17.   fld d
  18. end;
  19.  
  20. begin
  21.   Set8087CW($1332);
  22.   test;
  23. end.
« Last Edit: July 10, 2026, 07:12:13 pm by ALLIGATOR »

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 469
  • FPC git[main] Lazarus git[main] 💪🐯💪
Re: val return code
« Reply #11 on: July 10, 2026, 07:43:08 pm »
Actually, it behaves the same way in both Delphi and FPC

(Delphi 12CE)

Code: Pascal  [Select][+][-]
  1. program app;
  2.  
  3. uses
  4.   SysUtils;
  5.  
  6. var
  7.   d: Double;
  8.   c: Integer;
  9.  
  10. begin
  11.   Set8087CW($1332);
  12.  
  13.   try
  14.     Val('-42e308', d, c);
  15.   except
  16.     WriteLn('hehe');
  17.   end;
  18.  
  19.   Readln;
  20. end.

LeP

  • Guest
Re: val return code
« Reply #12 on: July 10, 2026, 07:43:17 pm »
In Delphi (I cannot try in FPC 'cause I don't have 32 bit crosscompiler) is working (I change assignement 'cause TExtended80rec is little bit different):

Quote
e = -4.20000000000000E+0309
d =                    -Inf

Code: Pascal  [Select][+][-]
  1. procedure test; assembler;
  2. var
  3.   p: TExtended80Rec;
  4.   e: Extended absolute p;
  5.   d: Double;
  6.   w: word;
  7. begin
  8.   p.Words[0] := $8F6C;
  9.   p.Words[1] := $2BBA;
  10.   p.Words[2] := $FCFE;
  11.   p.Words[3] := $BAE7;
  12.   p.Words[4] := $C403;
  13.   asm
  14.     (*
  15.     mov r[0], $8F6C
  16.     mov r[2], $2BBA
  17.     mov r[4], $FCFE
  18.     mov r[6], $BAE7
  19.     mov r[8], $C403
  20.     *)
  21.     fld e
  22.     fstp d
  23.     fld d
  24.   end;
  25.   writeln('e = ',e);
  26.   writeln('d = ',d);
  27. end;
  28.  
  29. begin
  30.   try
  31.     test;
  32.     Readln;
  33.   except
  34.     on E: Exception do
  35.       Writeln(E.ClassName, ': ', E.Message);
  36.   end;
  37. end.

P.S.: and like I wrote in my first post, in Delphi works normal without change code, or use assembly or insert any other instruction.
« Last Edit: July 10, 2026, 07:46:18 pm by LeP »

LeP

  • Guest
Re: val return code
« Reply #13 on: July 10, 2026, 07:51:58 pm »
Take care that since Delphi 12.x (I don't remember wich) the floating points behave like IEE754 without exceptions. All flag are masked by default.

avk

  • Hero Member
  • *****
  • Posts: 837
Re: val return code
« Reply #14 on: July 10, 2026, 08:32:35 pm »
UPD: Hmm, I think I just masked the exception generation.
...

It is enough to mask the overflow
Code: Pascal  [Select][+][-]
  1. ...
  2. uses
  3.   SysUtils, Math;
  4. ...
  5. begin
  6.   WriteLn('FPC-', {$i %FPCVersion}, ' ', {$i %FPCTargetCPU}, '-', {$i %FPCTargetOs});
  7.   SetExceptionMask(GetExceptionMask + [exOverflow]);
  8. ...
  9.  
but what about the claim
Quote
No, Val does not use exceptions...

 

TinyPortal © 2005-2018