Page 1 of 1

Temporary Double

Posted: Sun Aug 31, 2025 7:11 am
by Piero
I use a "Temporary Double" (IIFn –—> priifn) for all non-string types
Excluding if I exceed type range by some very weird multi-type expression (almost impossible) can it still generate a problem in some case?

Code: Select all

Procedure.d priifn(e,t.d,f.d)
   If e : ProcedureReturn t : EndIf : ProcedureReturn f
EndProcedure

Macro IIFn(e,t,f) ; IIFn(true?, trueNumber, falseNumber)
   priifn(Bool(e),t,f)
EndMacro

Macro IIF(e,s,delim="|") ; IIF(true?, "trueString|falseString")
   StringField(s,Bool(Not(e))+1,delim) ; delimiter can be multi-characters
EndMacro

CompilerIf #PB_Compiler_Debugger
   Macro dq : "
   EndMacro
   Macro diifexpr(e,s,i="is") ; "non-blocking assert" (no CallDebugger)
      Debug ~"File: \""+#PB_Compiler_Filename+
         ~"\"\nLine "+ #PB_Compiler_Line + ~": \""+ dq#e#dq +~"\" "+i+" "+ IIF(e,s)
   EndMacro
CompilerElse
   Macro diifexpr(e,s,i=""):EndMacro
CompilerEndIf

Debug ~"--- IIF ---\n"

x=10 : Debug "x = "+x
Debug ""+x+" Point"+ IIF(Not(x=1), "s") ; also IIF(x<>1,"s")
Debug ""+x+" is "+ IIF(x&1, "Odd|Even")
diifexpr(1&#False Or x/(x-8)=5, "true|not true!")
Debug ""
x=1 : Debug "x = "+x
Debug ""+x+" Point"+ IIF(x=1, "|s") ; empty StringField

Debug ~"\n--- IIFn ---\n"

Debug    IIFn(1=0, 11, 10)
Debug ""+IIFn(1=0, 11, 10)
x = IIFn(1=0, %1011, $F-4-x)
Debug x
Edit: reworded the question while my Idol mk-soft tries (I hope in vain) to debug me :)

Re: Temporary Double

Posted: Sun Aug 31, 2025 1:43 pm
by mk-soft
Could lead to a conversion error with very large integer values.
integer -> Double -> Double -> Integer

I would always include the return type.

Code: Select all

;-TOP

Procedure.i _IIF_integer(expr, rTrue.i, rFalse.i)
  If expr : ProcedureReturn rTrue : Else : ProcedureReturn rFalse : EndIf
EndProcedure

Procedure.l _IIF_long(expr, rTrue.l, rFalse.l)
  If expr : ProcedureReturn rTrue : Else : ProcedureReturn rFalse : EndIf
EndProcedure

Procedure.f _IIF_float(expr, rTrue.f, rFalse.f)
  If expr : ProcedureReturn rTrue : Else : ProcedureReturn rFalse : EndIf
EndProcedure

Procedure.d _IIF_double(expr, rTrue.d, rFalse.d)
  If expr : ProcedureReturn rTrue : Else : ProcedureReturn rFalse : EndIf
EndProcedure

Macro IIF_integer(expr, rTrue, rFalse)
  _IIF_integer(Bool(expr), rTrue, rFalse)
EndMacro

Macro IIF_long(expr, rTrue, rFalse)
  _IIF_long(Bool(expr), rTrue, rFalse)
EndMacro

Macro IIF_float(expr, rTrue, rFalse)
  _IIF_float(Bool(expr), rTrue, rFalse)
EndMacro

Macro IIF_double(expr, rTrue, rFalse)
  _IIF_double(Bool(expr), rTrue, rFalse)
EndMacro

Macro IIF_string(expr, rTrue, rFalse)
  PeekS(_IIF_integer(Bool(expr), @rTrue, @rFalse))
EndMacro

;-Test

x = 1
a = IIF_integer(x=1, 10, 20)
Debug a

b.f = IIF_float(x=1, 1.0, 2.0)
Debug b

c.s = IIF_string(x=1, "True", "False")
Debug c

Re: Temporary Double

Posted: Sun Aug 31, 2025 1:50 pm
by Piero
mk-soft wrote: Sun Aug 31, 2025 1:43 pm Could lead to a conversion error with very large integer values.
Can you post an example error? (without exceeding integer range)
I'm very curious!
Thanks!

Edit: I mean, if you start with an integer, how can you get out of range? (hope I was clear)
Edit 2: I was more worried of possible quirks happening when converting .f to .d and back :?

Re: Temporary Double

Posted: Sun Aug 31, 2025 5:10 pm
by Skipper
Piero,

creating a ternary operator this way will indeed make our sources somewhat more compact, but in the end, the compiler will generate similar binaries - this is especially valid for the optimising C-backend?

Cheers,
Skipper

Re: Temporary Double

Posted: Sun Aug 31, 2025 6:13 pm
by Piero
Skipper wrote: Sun Aug 31, 2025 5:10 pm Piero,
C-backend?
My C is even more rusty than my JS (what a shame… I had GREAT teachers…) anyway I think that, with a bit of practice, you will easily spot if a macro (expansion) will bloat your source instead of helping you code "better"…

PS about "macros" etc.: I'm tempted to celebrate Fred, but my duty is to criticize… so Form Designer! :evil:

Re: Temporary Double

Posted: Sun Aug 31, 2025 6:18 pm
by Skipper
I hope you understood my reference to the PB -C-compiler backend? No need to learn C, really...

Re: Temporary Double

Posted: Sun Aug 31, 2025 8:09 pm
by Piero
Skipper wrote: Sun Aug 31, 2025 6:18 pm I hope you understood my reference to the PB -C-compiler backend? No need to learn C, really...
Yes I think I understood; It's just I'm not into making ultra-super-fast stuff, and that made me remember of C (you can compile libraries and use with PB…) it also seems to me that with all this "AI" around, compilers are still often dumb (not talking only about PB (gcc?) but again about "optimization for extreme speed")
:)

Edit: here's an example, but I dunno if I misunderstood something (as I said, I'm not into ultrafast coding stuff):
viewtopic.php?p=644508#p644508

Re: Temporary Double

Posted: Mon Sep 01, 2025 8:11 pm
by SMaag
here a collection of different IIF Macros

Code: Select all

 
  
  ; IIF : similar to the VB IIf Function
  ; use it : IIf(varReturn, A>1000, "large", "small")
  Macro IIF(varReturn, _Expression_, valTrue, valFalse)
    If Bool(_Expression_)
      varReturn = valTrue
    Else
      varReturn = valFalse  
    EndIf
  EndMacro
  
  ;IIFe operating an Expression -> run True/False Expression
  ; use it: IIFe(a=b, c+d, c*d)
  ;         IIFe(a=b, x=1, x=0)
  Macro IIFe(_Expression_, _TrueExpression_, _FalseExpression_)
    If _Expression_
      _TrueExpression_
    Else
      _FalseExpression_
    EndIf   
  EndMacro
   
  ; IIFn with Numeric retrurn 
  ; use it: numericVar = IIF(a=b, 1, 2)
  Macro IIFn(_Expression_, _TruePart_, _FalsePart_)
    Bool(_Expression_)*_TruePart_ + Bool(Not(_Expression_))*_FalsePart_     
  EndMacro

  ; IIFs with String return from True/False Stringfield
  ; use it: IIFs(A>1000, "large|small")
  Macro IIFs(_Expression_, _TrueStr_FalseStr_, sepStr="|")
    StringField(_TrueStr_FalseStr_, 2-Bool(_Expression_), sepStr)
  EndMacro
  
  ; IIFss  with String return from True/False String 
  ; use it: IIFs(A>1000, large, small)
  Macro IIFss(_Expression_, _TrueString_, _FalseString_)
    PeekS(@_TrueString_,-Bool(_Expression_)) + PeekS(@_FalseString_,-Bool(Not(_Expression_)))
  EndMacro
  
  Define res
  
  Debug "IIF returning the True/False Part"
  IIF(res, 1=0, 1, 0)
  Debug res
  IIF(res, 1=1, 1, 0)
  Debug res

  Debug "IIFe with running the True/False Expression"
  IIFe(1=0, res=1, res=0)
  Debug res
  IIFe(1=1, res=1, res=0)
  Debug res
  
  Debug "IIFn with numeric return"
  Debug IIFn(1=0, 1, 0)
  Debug IIFn(1=1, 1, 0)
  
  Debug "IIFs with retruning True/False Part from a StringField"
  Debug IIFs(1=0, "True|False")
  Debug IIFs(1=1, "True|False")
  
  Debug "IIFss with True/False String and PeekS()"
  Debug IIFss(1=0, "True", "False")  
  Debug IIFss(1=1, "True", "False")

Re: Temporary Double

Posted: Tue Sep 02, 2025 9:23 am
by Piero
SMaag wrote: Mon Sep 01, 2025 8:11 pm here a collection of different IIF Macros
I wonder if

Code: Select all

Macro IIF(e,s,delim="|") ; IIF(true?, "trueString|falseString")
   StringField(s,~Bool(e)&1+1,delim) ; delimiter can be multi-characters
EndMacro
would be faster :)

Edit:

Code: Select all

Macro IIFn(_Expression_, _TruePart_, _FalsePart_)
   Bool(_Expression_)*_TruePart_ + Bool(Not(_Expression_))*_FalsePart_     
EndMacro
Debug IIFn(1=0, 11.1, 10) ; should be 10, gives 0.0!

I prefer my version because it can be used directly with debug and generates/needs less code :)

Code: Select all

Procedure.d priifn(e,t.d,f.d) ; "temporary Double" for non-String types
   If e : ProcedureReturn t : EndIf : ProcedureReturn f
EndProcedure

Procedure.s priifs(e,s.s,d.s)
   ProcedureReturn StringField(s,Bool(Not(e))+1,d)
EndProcedure

Macro IIFn(e,t,f) ; IIFn(true?, trueNumber, falseNumber)
   priifn(Bool(e),t,f)
EndMacro

#iifsdelim="|"
Macro IIFs(e,s,delim=#iifsdelim) ; IIFs(true?, "trueString|falseString")
   priifs(Bool(e),s,delim) ; delimiter can be multi-characters
EndMacro

Macro IIF(e,t,f) ; IIF(a=b?, x=1, s="y")
   If Bool(e) : t : Else : f : EndIf ; Bool just in case
EndMacro

CompilerIf #PB_Compiler_Debugger
   Macro dq : "
   EndMacro
   Macro diifexpr(e,s,i="is") ; "non-blocking assert" (no CallDebugger)
      Debug ~"File: \""+#PB_Compiler_Filename+
         ~"\"\nLine "+ #PB_Compiler_Line + ~": \""+ dq#e#dq +~"\" "+i+" "+ IIFs(e,s)
   EndMacro
   Macro BadAssert(e,t="") ; blocking if true
      If e
         Debug ~"File: \""+#PB_Compiler_Filename+
            ~"\"\nLine "+ #PB_Compiler_Line + ~": \""+ dq#e#dq +~"\" is true! "+t
         CallDebugger
      EndIf
   EndMacro
CompilerElse
   Macro diifexpr(e,s,i=""):EndMacro
   Macro BadAssert(e,t=""):EndMacro
CompilerEndIf

BadAssert(x<>0,x) ; x should be 0 (and is also integer) by default
Debug ~"--- IIFs ---\n"

x=10 : Debug "x = "+x
Debug ""+x+" Point"+ IIFs(Not(x=1), "s") ; also IIFs(x<>1,"s")
Debug ""+x+" is "+ IIFs(x&1, "Odd|Even")
diifexpr(1&#False Or x/(x-8)=5, "true|not true!")
Debug ""
x=1 : Debug "x = "+x
Debug ""+x+" Point"+ IIFs(x=1, "|s") ; empty StringField

Debug ~"\n--- IIFn ---\n"

Debug    IIFn(1=0, 11, 10) ; it's Double, but…
Debug ""+IIFn(1=0, 11, 10) ; becomes Integer on a "string"
x = IIFn(1=0, %1011, $F-4-x) ; becomes type of x (Integer in this case)
Debug x
Edit: added #iifsdelim and made IIFs use a procedure; should generate less code (but lose some nanosecond :) )
Suggestions welcome!

Re: Temporary Double

Posted: Tue Sep 02, 2025 5:12 pm
by SMaag
Macro IIFn(_Expression_, _TruePart_, _FalsePart_)
Bool(_Expression_)*_TruePart_ + Bool(Not(_Expression_))*_FalsePart_
EndMacro
Debug IIFn(1=0, 11.1, 10) ; should be 10, gives 0.0!
seems to be a PB-Bug!
If I change the to statements it works

Code: Select all

EnableExplicit

Macro IIFn(_Expression_, _TruePart_, _FalsePart_)
  ; Bool(Not _Expression_) * _FalsePart_ + Bool(_Expression_) * _TruePart_
   Bool(_Expression_) * _TruePart_ + Bool(Not _Expression_) * _FalsePart_
 EndMacro
 
 Debug IIFn(1=0, 11.1, 10) ; should be 10, gives 0.0!
 
 Define res.d
 
 res = IIFn(1=0, 11.1, 10) ; should be 10, gives 0.0!
Debug res

Re: Temporary Double

Posted: Tue Sep 02, 2025 6:21 pm
by Piero
SMaag wrote: Tue Sep 02, 2025 5:12 pmseems to be a PB-Bug!
If I change the to statements it works
(In case, please forgive my dumbness :D) What "to statements"? Here your examples always give 0.0 :(

Re: Temporary Double

Posted: Tue Sep 02, 2025 7:16 pm
by SMaag
(In case, please forgive my dumbness :D) What "to statements"? Here your examples always give 0.0 :(
Top

Code: Select all


; this 2 lines in the Macro return different values - but should be the same
Macro IIFn(_Expression_, _TruePart_, _FalsePart_)
  Bool(Not _Expression_) * _FalsePart_ + Bool(_Expression_) * _TruePart_
  ;Bool(_Expression_) * _TruePart_ + Bool(Not _Expression_) * _FalsePart_
 EndMacro
it is a bug of the compilers precalculation!

viewtopic.php?t=87478

Re: Temporary Double

Posted: Tue Sep 02, 2025 7:41 pm
by Piero
SMaag wrote: Tue Sep 02, 2025 7:16 pmthis 2 lines in the Macro return different values - but should be the same

Code: Select all

Macro IIFn(_Expression_, _TruePart_, _FalsePart_)
  Debug Bool(Not _Expression_) * _FalsePart_ + Bool(_Expression_) * _TruePart_
  Debug Bool(_Expression_) * _TruePart_ + Bool(Not _Expression_) * _FalsePart_
EndMacro

IIFn(1=1, 11.1,10)
; 11.0999999999999996
; 21.1000000000000014
viewtopic.php?t=87478

Fred! Help! :mrgreen: