Recent

Author Topic: ABS truncates a Variant float ?  (Read 8432 times)

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: ABS truncates a Variant float ?
« Reply #15 on: February 25, 2018, 03:42:04 pm »
it not only truncates it, it changes the Type over to a  Vinteger;

 as you will note with the test reports Molly did, after the ABS(V), the V is no longer a DOUBLE, but if you
cast it to a single, then its ok.

 I've looked in the Variants unit and I can't find where this is being done so it must be where the system unit
hooks in for the Variant manager and is just doing type resolving via the Variant code and resolving the ASB like
it would for non-variants.

 That is just my thoughts on it.
The only true wisdom is knowing you know nothing

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: ABS truncates a Variant float ?
« Reply #16 on: February 25, 2018, 04:20:50 pm »
From the fpc-devel list (MvC):
Quote
The abs() function is overloaded for different types.

The compiler does not know at compile time what type the variant is, how can you expect it to choose the "right" overloaded version ?

It probably takes the first fit for possible values in a Variant, which is most likely an integer version.

Don't use variants if you want type safety :)

Note: this is the explanation of why it works like it currently does.
Pleas don't start arguing with me that this is wrong.

Bart

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: ABS truncates a Variant float ?
« Reply #17 on: February 25, 2018, 04:22:32 pm »
From the fpc-devel list (MvC):
Quote
The abs() function is overloaded for different types.

The compiler does not know at compile time what type the variant is, how can you expect it to choose the "right" overloaded version ?

It probably takes the first fit for possible values in a Variant, which is most likely an integer version.

Don't use variants if you want type safety :)

Note: this is the explanation of why it works like it currently does.
Pleas don't start arguing with me that this is wrong.

Bart
What did they said about delphi compatibility?
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: ABS truncates a Variant float ?
« Reply #18 on: February 25, 2018, 04:33:53 pm »
Delphi docs state that Abs() only is overloaded for float, int64 and integer.
But as we all know, Delphi tends to not quite behave like their docs...

Quote from JM:
Quote
No, because variant can be implicitly converted to all of those types and there are different (undocumented by Embarcadero) overload selection priorities for each of those types.

Bart

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: ABS truncates a Variant float ?
« Reply #19 on: February 25, 2018, 04:48:12 pm »
Delphi handles the Variant for ABS as expected, there is no fraction stripping, there is no changing of
types after the fact, it works as it should..
 
  This could explain why I can't get some of my automation software to work with fpc which uses the
ole and variant interface and there is no way around not using it. I suppose I can take another crack at it
and put the overloaded ABS in there again to remove those bugs and move on to the next one's.

 I wrote a major HMI app that links lots of COMS and Variants within using old Delphi 3, D3 is considered now
to be very old but I still have it loaded to maintain that app, would love for it to work with lazarus but I see this is
going to be a hard road ahead.

 I understand these task are hard to deal with, I am sure some of the DEV may think of themselves as coding gods,
well that's fine, I understand that, I've been doing this myself for 45+ years.

 But even GOD can make a mistake, I run into many of them almost everyday! :D

The only true wisdom is knowing you know nothing

ASerge

  • Hero Member
  • *****
  • Posts: 2248
Re: ABS truncates a Variant float ?
« Reply #20 on: February 25, 2018, 04:51:33 pm »
What did they said about delphi compatibility?
According Delphi docs "In these cases, when it is possible to do so without ambiguity, the compiler invokes the routine whose parameters are of the type with the smallest range that accommodates the actual parameters in the call."
But... This code display
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$APPTYPE CONSOLE}
  3. {$IFDEF FPC}{$MODE OBJFPC}{$ENDIF}
  4.  
  5. uses Variants;
  6.  
  7. procedure Test(P: Double); overload;
  8. begin
  9.   Writeln('Double: ', P:0:2);
  10. end;
  11.  
  12. procedure Test(P: Integer); overload;
  13. begin
  14.   Writeln('Integer: ', P);
  15. end;
  16.  
  17. var
  18.   V: Variant;
  19. begin
  20.   V := -34.5;
  21.   Test(V);
  22.   Test(Abs(V));
  23.   Readln;
  24. end.

FPC: Integer and Integer.
Delphi 7: Integer and Double.
Delphi 10.2: Double and Double.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: ABS truncates a Variant float ?
« Reply #21 on: February 25, 2018, 04:58:32 pm »
Delphi 7: Integer and Double.
Which seems to suggest there is an ABS overload for variants, when compared with your results with Delphi 10.x


Thaddy

  • Hero Member
  • *****
  • Posts: 14381
  • Sensorship about opinions does not belong here.
Re: ABS truncates a Variant float ?
« Reply #22 on: February 25, 2018, 05:12:03 pm »
Quote
FPC: Integer and Integer.
Delphi 7: Integer and Double.
Delphi 10.2: Double and Double.
I can reproduce this for d5 upto 2007 ,d10.1. Seems modern Delphi looks at the "result" first and assumes the result type for further calculations. Also note:"without ambiguity"
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: ABS truncates a Variant float ?
« Reply #23 on: February 25, 2018, 05:13:51 pm »
Quote from JM:
Quote
As Michael said, overloads are selected at compile time. This is true for both FPC and Delphi. We even have over a 100 unit tests that we ran under Delphi to reverse engineer their selection priorities in case of variants: https://svn.freepascal.org/svn/fpc/trunk/tests/test/cg/variants/

Abs(), however, gets a forced conversion to float in Delphi: https://bugs.freepascal.org/view.php?id=20551

Bart

rvk

  • Hero Member
  • *****
  • Posts: 6169
Re: ABS truncates a Variant float ?
« Reply #24 on: February 25, 2018, 05:21:21 pm »
Looking at the CPU watch at the moment of X := -1 (X = Variant) in Delphi, there is a VarToReal done, fabs opcode and a VarFromReal. So it seems like the Abs() on a Variant is always done on a Real.

Quote from JM:
Quote
Abs(), however, gets a forced conversion to float in Delphi: https://bugs.freepascal.org/view.php?id=20551
Ah, yes, that's got the same snippet.

Mmm, Date Submitted: 2011-10-24 13:04 and status still new.
You would have thought this would have gotten attention earlier :D

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: ABS truncates a Variant float ?
« Reply #25 on: February 25, 2018, 05:24:50 pm »
I can understand the compiler having an issue at compile time, since this type is a RUN TIME type in which
case the coder needs to help the compiler a little, fully understandable..

 But as you also not, the Write/writeln seems to know what it is(RunTime) and since the "ABS" also is one of those same type of functions, it too should also behave the same, it does not in fpc but does in all versions of D.

 The mere fact that I wrote and overloaded version in local code using a VARIANT as the input type solves my
issue, but for some reason the system unit does not do this?

My old D3 does not have overload functions so my code didn't have any issues there with that..

Maybe as for user overloads the coder should be forced to indicate the type for functions that do not accept a variant directly?

example
 mylocalOverLoadFunction(V.AsInteger) etc..

 to me that is safer..

« Last Edit: February 25, 2018, 05:29:53 pm by jamie »
The only true wisdom is knowing you know nothing

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: ABS truncates a Variant float ?
« Reply #26 on: February 25, 2018, 05:37:53 pm »
The mere fact that I wrote and overloaded version in local code using a VARIANT as the input type solves my
issue, but for some reason the system unit does not do this?
As can been seen from ASerge's output it seems to differ between delphi versions. D7 seems to suggest that there is actually an overload while D10.2 seems to add additional code (or make another general approach for dealing with variants at runtime).

Quote
Maybe as for user overloads the coder should be forced to indicate the type for functions that do not accept a variant directly?
Which is also inconsistent. As you wrote yourself that write and friends knows how to deal with the actual type of the variant (unless you want to force your proposed 'restriction' for those functions as well ofc).

Not to mention the compatibility issues.
« Last Edit: February 25, 2018, 05:39:52 pm by molly »

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: ABS truncates a Variant float ?
« Reply #27 on: February 25, 2018, 05:55:35 pm »
Function ABS(V:Variant):Variant; Overload; inline;
Begin
  result := v;
  If VarIsNumeric(V) Then
    if V< 0 Then result := -v;
end;   [/code] :D

This will also allow code like this to compile:
Code: Pascal  [Select][+][-]
  1. var
  2.   S : String;
  3.  
  4. begin
  5.   S:='My very nice string';
  6.   S:=Abs(S);
  7. end;
  8.  

That would be bad.

Bart

rvk

  • Hero Member
  • *****
  • Posts: 6169
Re: ABS truncates a Variant float ?
« Reply #28 on: February 25, 2018, 05:57:16 pm »
I see in the examples here that they are concentrating on negative numbers but of course this is also false for positive numbers.

Code: Pascal  [Select][+][-]
  1. var
  2.   X: Variant;
  3. begin
  4.   X := 5.5;
  5.   writeln('X = ',Abs(X)); // <-- gives 6

Maybe just forcing real in case of variant (like Delphi seems to do) is the best fix. Because there, even for an integer assigned to a Variant it seems that Abs() always results in a Real.

Quote
X = -1
VarIsFloat  : FALSE // <-- no real assigned
VarIsNumeric: TRUE
VarIsOrdinal: TRUE
After Abs()
X = 1
VarIsFloat  : TRUE // <-- converted to real
VarIsNumeric: TRUE
VarIsOrdinal: FALSE
« Last Edit: February 25, 2018, 06:00:25 pm by rvk »

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: ABS truncates a Variant float ?
« Reply #29 on: February 25, 2018, 06:04:51 pm »
My point was to have at least a compiler WARNING so the coder can type case it for local overloads!

 Or:
   Do as the 64bit port does when it decides to change the type (MyWORD+1) to a integer, if two or more
overloads are present, It can't decide which one to call and the compiler will ERROR out, this isn't D compliant
but worked around via a WORD(MyWORD+1), but this is where it would really work well if Variants were in
play, Force a cast so the compiler knows which local overload to select at compile time..
 
 But this does not solve the ABS issue, this in it self should know at runtime what to do.

 The overloaded ABS(V:Variant):Variant seems to work well, I was wondering if putting it inside the
"Variants" unit so its only present when using Variants would work?
   
 I've done some test and the compiler seems to know the difference between using that one over the system.Abs for
non variant types.
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018