Recent

Author Topic: IfThen function  (Read 8788 times)

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
IfThen function
« on: April 28, 2022, 09:34:59 am »
Hello,
I have a problem with the IfThen function in Math (fpc 3.2.2).

function IfThen(val:boolean;const iftrue:double ; const iffalse:double =0.0):double;  inline; overload;

I am calling it like this (well not like this, but my values happen to be both zero and this is a possible case):

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.     Math;
  5.  
  6.  
  7. function Calc(n, d: double): double;
  8. begin
  9.   Result := IfThen(d > 0, n/d, 0);
  10. end;
  11.  
  12. var
  13.   x : double;
  14. begin
  15.   x := Calc(0, 0);
  16. end.    
  17.  



I got a invalid floating point op under windows, while no such error occurs under linux.

Any Ideas?
Thank you

« Last Edit: April 28, 2022, 09:45:50 am by tt »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

MarkMLl

  • Hero Member
  • *****
  • Posts: 8080
Re: IfThen function
« Reply #1 on: April 28, 2022, 09:54:59 am »
I suspect that the problem is that since IfThen() is a function your num/denom is being evaluated- unsuccessfully- despite the fact that you neither expect nor want it to be.

https://forum.lazarus.freepascal.org/index.php/topic,42225.msg426543.html#msg426543

MarkMLl
« Last Edit: April 28, 2022, 09:57:42 am by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Zvoni

  • Hero Member
  • *****
  • Posts: 2780
Re: IfThen function
« Reply #2 on: April 28, 2022, 10:07:10 am »
I'm more surprised he's not getting an error on Linux.
Different settings for compiler?

EDIT: i'll never understand people using such functions instead of doing it yourself, and catching everything that can go wrong beforehand
What's wrong with doing it yourself instead?
Code: Pascal  [Select][+][-]
  1. function Calc(n, d: double): double;
  2. begin
  3.   If d>0 Then Result:=n/d Else Result:=0;
  4.   //Result := IfThen(d > 0, n/d, 0);
  5. end;
  6.  
  7.  
« Last Edit: April 28, 2022, 10:10:11 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: IfThen function
« Reply #3 on: April 28, 2022, 10:10:00 am »
I suspect that the problem is that since IfThen() is a function your num/denom is being evaluated- unsuccessfully- despite the fact that you neither expect nor want it to be.

https://forum.lazarus.freepascal.org/index.php/topic,42225.msg426543.html#msg426543

MarkMLl

Ok correct, thank you.
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: IfThen function
« Reply #4 on: April 28, 2022, 10:11:03 am »
I'm more surprised he's not getting an error on Linux.
Different settings for compiler?

EDIT: i'll never understand people using such functions instead of doing it yourself, and catching everything that can go wrong beforehand
What's wrong with doing it yourself instead?
Code: Pascal  [Select][+][-]
  1. function Calc(n, d: double): double;
  2. begin
  3.   If d>0 Then Result:=n/d Else Result:=0;
  4.   //Result := IfThen(d > 0, n/d, 0);
  5. end;
  6.  
  7.  


I am wrong. Sorry
« Last Edit: April 28, 2022, 10:15:31 am by tt »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

MarkMLl

  • Hero Member
  • *****
  • Posts: 8080
Re: IfThen function
« Reply #5 on: April 28, 2022, 10:21:29 am »
i'll never understand people using such functions instead of doing it yourself, and catching everything that can go wrong beforehand
What's wrong with doing it yourself instead?

I'm writing this in defence of OP, lest he feel that you're accusing him of being lazy or st^H^H negligent.

Inline if-then-else was in ALGOL-60, and rather than being syntactic sugar it fills a real need /because/ it only evaluates one of the subexpressions. It's omission in Pascal was- I believe- because of the time constraints Wirth had when designing and implementing the initial implementation, and because it's in virtually every other ALGOL derivative its omission is unfortunate particularly when somebody is working from a description of an algorithm in some other language or ALGOL-based pseudolanguage.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: IfThen function
« Reply #6 on: April 28, 2022, 10:32:31 am »
I was definitiely in error.

I was just wanting to have something smart like this in C...

Code: C  [Select][+][-]
  1. #include <stdio.h>
  2.  
  3. #define IFTHEELSE(C, d, T, F) if (C) { d = T; } else { d = F; }
  4.  
  5. int main()
  6. {
  7.  
  8.     float n, d, r;
  9.  
  10.     n = 2; d = 5;    
  11.  
  12.     IFTHEELSE(d > 0, r, n/d, 0)
  13.  
  14.    
  15.     printf("Hello World");
  16.     printf("%f", r);
  17.  
  18.  
  19.     return 0;
  20. }
  21.  


Again,
apologies.
 
« Last Edit: April 28, 2022, 10:34:55 am by tt »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Zvoni

  • Hero Member
  • *****
  • Posts: 2780
Re: IfThen function
« Reply #7 on: April 28, 2022, 10:33:07 am »
i'll never understand people using such functions instead of doing it yourself, and catching everything that can go wrong beforehand
What's wrong with doing it yourself instead?

I'm writing this in defence of OP, lest he feel that you're accusing him of being lazy or st^H^H negligent.

Inline if-then-else was in ALGOL-60, and rather than being syntactic sugar it fills a real need /because/ it only evaluates one of the subexpressions. It's omission in Pascal was- I believe- because of the time constraints Wirth had when designing and implementing the initial implementation, and because it's in virtually every other ALGOL derivative its omission is unfortunate particularly when somebody is working from a description of an algorithm in some other language or ALGOL-based pseudolanguage.

MarkMLl
Mark, no offense taken, and i wasn't "accusing" the OP. It's just the way my brain ticks.
As you correctly pointed out: IfThen is a Function, thusly all Parameters get thrown on the stack, consequencing in being evaluated before pushed on the stack.
Yes, IfThen has the "inline" modifier, but do we know if that Function in OP's case really got inlined? Does he have {$inline on}? (No Idea if for math.pp it's switched on or not)

And in C i always have to read a line like "c = (d==False) ? 0 : 1;" twice.....

EDIT: I'd be more interested if this would work
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$inline on}    
  3.     uses Math;        
  4.     {function Calc(n, d: double): double;
  5.     begin
  6.       Result := IfThen(d > 0, n/d, 0);
  7.     end;}    
  8.     var
  9.       x, d, n : double;      
  10.     begin
  11.       d := 0;
  12.       n := 0;
  13.       x := IfThen(d>0, n/d, 0);
  14.       //x := Calc(0, 0);
  15.     end.    
  16.  
« Last Edit: April 28, 2022, 10:40:02 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: IfThen function
« Reply #8 on: April 28, 2022, 10:39:52 am »
i'll never understand people using such functions instead of doing it yourself, and catching everything that can go wrong beforehand
What's wrong with doing it yourself instead?

I'm writing this in defence of OP, lest he feel that you're accusing him of being lazy or st^H^H negligent.

Inline if-then-else was in ALGOL-60, and rather than being syntactic sugar it fills a real need /because/ it only evaluates one of the subexpressions. It's omission in Pascal was- I believe- because of the time constraints Wirth had when designing and implementing the initial implementation, and because it's in virtually every other ALGOL derivative its omission is unfortunate particularly when somebody is working from a description of an algorithm in some other language or ALGOL-based pseudolanguage.

MarkMLl
Mark, no offense taken, and i wasn't "accusing" the OP. It's just the way my brain ticks.
As you correctly pointed out: IfThen is a Function, thusly all Parameters get thrown on the stack, consequencing in being evaluated before pushed on the stack.
Yes, IfThen has the "inline" modifier, but do we know if that Function in OP's case really got inlined? Does he have {$inline on}? (No Idea if for math.pp it's switched on or not)

And in C i always have to read a line like "c = (d==False) ? 0 : 1;" twice.....

Just more bits, I also tried with inlining disabled, but the problem (as you guys pointed out) is that the function call requires the function parameter evaluation before the stack operation, just like doing the division, assigning to a temp var and passing to the function, it with raise the error regardless.

x := n/d; // the error is here inline or not
Ifthen( condition, x, 0);
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

dbannon

  • Hero Member
  • *****
  • Posts: 3171
    • tomboy-ng, a rewrite of the classic Tomboy
Re: IfThen function
« Reply #9 on: April 28, 2022, 11:05:29 am »
And in C i always have to read a line like "c = (d==False) ? 0 : 1;" twice.....

c = !d?0:1;

No Zvoni, your version was far too readable.

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

MarkMLl

  • Hero Member
  • *****
  • Posts: 8080
Re: IfThen function
« Reply #10 on: April 28, 2022, 11:07:46 am »
I don't think inline's relevant here, since both operands will always be evaluated in any case... with implementation-defined order so $Deity help you if they have side-effects :-)

In addition there's a constant hardwired inside the compiler and if a function is larger than that then an associated inline directive will be ignored (except for a warning message). I'm confident that the core developers had good reason for doing it that way, and I don't know what would happen if somebody recompiled his copy of the compiler with that constant changed.

FPC's macros are actually quite useful since they may extend over multiple lines and nested macros are handled reliably. However since they have no provision for parameters I don't think they really help here unless you're able to contrive that the controlling expression and parameters are actually consistently-named variables/constants/etc.

As per my original posting and- in particular- the included link at least one core developer is sympathetic to inline if-then-else. OTOH he's resolutely opposed to adding parameters to macros, so all I we can do is cling to the hope that inline conditionals eventually get added in some form.

Finally, looking at this from an historical perspective, I've seen early compilers and their documentation make very heavy going of nested if-then-else statements. Now granted that doctrine is far clearer these days but I still feel that the more that can be done to localise conditional handling the better: if something is conditional within the scope of an *expression* I see no reason to add to the complexity of a program by adding *statements*. Furthermore, if statements need to be added then that implies that an lvalue assignee must be repeated, increasing the risk that subsequent maintenance will change something in one copy but not the other.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11980
  • FPC developer.
Re: IfThen function
« Reply #11 on: April 28, 2022, 12:00:56 pm »
In addition there's a constant hardwired inside the compiler and if a function is larger than that then an associated inline directive will be ignored (except for a warning message). I'm confident that the core developers had good reason for doing it that way, and I don't know what would happen if somebody recompiled his copy of the compiler with that constant changed.

Afaik it is a kind of heuristic that tries to assess the complexity of a function. For very complex functions, the inline speed gain is zero or negative (code cache and TLB polution), and can also cause to hit the "procedure too complex" situation and/or compiler slowdown with gigantic procedures earlier.

IOW, it is only a safeguard to avoid accidental extreme cases that are not useful anyway.



MarkMLl

  • Hero Member
  • *****
  • Posts: 8080
Re: IfThen function
« Reply #12 on: April 28, 2022, 12:36:13 pm »
Afaik it is a kind of heuristic that tries to assess the complexity of a function. For very complex functions, the inline speed gain is zero or negative (code cache and TLB polution), and can also cause to hit the "procedure too complex" situation and/or compiler slowdown with gigantic procedures earlier.

IOW, it is only a safeguard to avoid accidental extreme cases that are not useful anyway.

...and in any event, it definitely doesn't affect OP's problem.

I wasn't in the least intending any criticism of the development team there. It was more a gentle acknowledgement of the fact that anybody who tinkered might risk incurring Sven's wrath :-)

I'd note that if I find myself with lots of smallish functions that might benefit from being inlined, I define a macro INLINE__ that either takes the value "inline" or is set blank. That way, I can specifically avoid generating warning messages if the compiler decides to not inline a function, or inlining is disabled at the global or unit level.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

BobDog

  • Sr. Member
  • ****
  • Posts: 394
Re: IfThen function
« Reply #13 on: April 28, 2022, 01:07:48 pm »

 IfThen--Conditional function that returns one of two values.
The whole point of these functions (or ternary operators) is that only one value is evaluated.
This would be a speed up operation with a safety check.
variable = condition ? answer1 : answer2 in C
or
variable=iif(condition,answer1, answer2) in basic.
Evaluating both answers seems pointless.

 


Zvoni

  • Hero Member
  • *****
  • Posts: 2780
Re: IfThen function
« Reply #14 on: April 28, 2022, 01:16:01 pm »

 IfThen--Conditional function that returns one of two values.
The whole point of these functions (or ternary operators) is that only one value is evaluated.
This would be a speed up operation with a safety check.
variable = condition ? answer1 : answer2 in C
or
variable=iif(condition,answer1, answer2) in basic.
Evaluating both answers seems pointless.
Yes, but how do you want to avoid evaluating all Parameters if you throw them on the stack since you're passing it to a function?
The only way i see would be to evaluate from left to right in this case (since "condition" is the first param), and depending on the result evaluate the second or the third, discarding/ignoring the "other" one...

which is exactly what "If Condition Then Result:=a Else Result:=b; does
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

 

TinyPortal © 2005-2018