If I disturb nobody, I take the Josh's benchmark, I adjust his benchmark, I take the slowest algo and I add my thing about exception...
Magic wand... The slowest seems to become the quickest.
This thread is very interesting because sometimes quick integer handling is really a must.
Anyhow it seems that macros will be much faster than the trickiest assembler procedures (see below)...
...so could it be possible to extend Purebasic somewhen allowing to create special macros using assembler code?
If it is quicker or near equal, yes : you just use only one register too. I cannot edit a benchmark. What does it give ?
@Michael Vogel
Yes, but the complete function should be included. Just comparing two ways, or comparing forgetting measuring parameters, drive to bad surprising things.
Even if exception overflow seems to be the 0.0000000000000000001% of the domain, it is the same ratio for a carry ! Exception can be treated by a macro but to branch it from a math macro, I do not know if MacroExpandedCount could be concatenated in an assembly label. If yes, macro will be better.
Last edited by Olliv on Fri Jan 25, 2019 9:30 am, edited 1 time in total.
I experimented a bit with the x86 code.
On my computer, test seems to be faster as bt .
It also looks like you can do the inversion with three instructions instead of four.
Wilbert wrote:On my computer, test seems to be faster as bt .
BT instruction is a strange UFO. It is slow for this use (and I do not mention this, above), but I am sure it can gain time and register use in others ways...
Procedure Min(a,b)
If a And a<b
ProcedureReturn a
ElseIf b
ProcedureReturn b
ElseIf a
ProcedureReturn a
Else
ProcedureReturn b
EndIf
EndProcedure
s.s=""
Debug "m|0 1 2 3"
Debug "-+-------"
For a=0 To 3
s=""+a+"|"
For b=0 To 3
m=min(a,b)
s+m+" "
Next b
Debug s
Next a
Michael Vogel wrote:As some of you found brilliant macros fot the abs function I have a new puzzle for you: calculate the minimum non zero value of two integers:
Here's a procedure doing so, but would there be a simple math expression to get the same results?
If you want a macro, this seems to do it but it's not a really simple expression
Macro Min(a, b)
((b) + ((a)-(b)) & -Bool(((a)<(b) And (a)) Or (b)=0))
EndMacro
s.s=""
Debug "m|0 1 2 3"
Debug "-+-------"
For a=0 To 3
s=""+a+"|"
For b=0 To 3
m=min(a,b)
s+m+" "
Next b
Debug s
Next a
There might be an easier way.
If speed is your goal, an asm procedure might be faster.
It might have been better to open a new topic since this has little to do with absolute values
Last edited by wilbert on Mon Feb 04, 2019 9:19 am, edited 1 time in total.
Macro Min(a,b)
b + ((a - b) & ((a - b) >> (SizeOf(integer)<<3 -1)))
EndMacro
Macro Max(a,b)
a - ((a - b) & ((a - b) >> (SizeOf(integer)<<3 - 1)));
EndMacro
s.s=""
Debug "m|0 1 2 3"
Debug "-+-------"
For a=0 To 3
s=""+a+"|"
For b=0 To 3
m=min(a,b)
s+m+" "
Next b
Debug s
Next a
Not very efficient if you feed something else than pure variables or constants to that macro, but it works. I just converted your If-Condition to one line.
Macro Min(a, b)
((b) - Bool(((a) And (a) < (b)) Or (Not (b) And (a))) * ((b) - (a)))
EndMacro
s.s = ""
Debug " m | 0 1 2 3"
Debug "----+------------"
For a = 0 To 3
s = RSet(Str(a), 3) + " | "
For b = 0 To 3
m = Min(a, b)
s + RSet(Str(m), 2) + " "
Next
Debug s
Next
But in principle your If-condition is best practice because there will never be more evaluated than needed, provided that the most common case is the first one.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
Macro Is(relation,result)
(Bool(relation)*(result))
EndMacro
Macro mMin(a,b)
(a)+(b) - (Bool(a*b) * (Bool((a)<(b))*(b) + Bool((b)<=(a))*(a))); works fine, but not very easy to read
;(a)+(b) - Is(a*b,Is(a<b,b) + Is(b<=a,a)); easier to undesrtand, but does't work
EndMacro
s.s=""
Debug "m|0 1 2 3" : Debug "-+-------"
For a=0 To 3
s=""+a+"|"
For b=0 To 3 : m=mMin(a,b) : s+m+" " : Next b
Debug s
Next a
Macro Is(relation,result)
(Bool(relation)*(result))
EndMacro
Macro Is2(relation,result)
(Bool(relation)*(result))
EndMacro
Macro mMin(a,b)
;(a)+(b) - (Bool(a*b) * (Bool((a)<(b))*(b) + Bool((b)<=(a))*(a))); works fine, but not very easy to read
(a)+(b) - Is(a*b,Is2(a<b,b) + Is2(b<=a,a)); easier to undesrtand, but does't work
EndMacro
s.s=""
Debug "m|0 1 2 3" : Debug "-+-------"
For a=0 To 3
s=""+a+"|"
For b=0 To 3 : m=mMin(a,b) : s+m+" " : Next b
Debug s
Next a
I think the problem is that Macros have a higher precedence than anything else. So after replacing the outer "Is" the first time with the content of the Macro it sees that it has to replace Is again and shows the recursion error. If brackets would have a higher precedence it would first replace the two "Is" in the middle and after expanding it could then expand the outer one.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.