Page 2 of 5
Re: Absolute Val for Integers?
Posted: Mon Jan 21, 2019 2:25 pm
by Olliv
@Little John
No problem. Your research allows me to discover several details, like most of researching which are shared.
Finally this subject becomes a small mine of datas, just from a simple missing feature...
Re: Absolute Val for Integers?
Posted: Mon Jan 21, 2019 5:10 pm
by mk-soft
Simple way
Code: Select all
Import ""
Abs64(quad.q) As "_abs64"
Abs32(long.l) As "labs"
EndImport
var1.i = -1
Debug Abs64(var1)
var2.l = -10
Debug Abs32(var2)
Re: Absolute Val for Integers?
Posted: Mon Jan 21, 2019 5:14 pm
by wilbert
mk-soft wrote:Simple way
Code: Select all
Import ""
Abs64(quad.q) As "_abs64"
Abs32(long.l) As "labs"
EndImport
var1.i = -1
Debug Abs64(var1)
var2.l = -10
Debug Abs32(var2)
For MacOS and Linux you would need
llabs instead of _abs64 .
Re: Absolute Val for Integers?
Posted: Mon Jan 21, 2019 5:28 pm
by mk-soft
Is ImportC right?
Code: Select all
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Import ""
Abs64(quad.q) As "_abs64"
Abs32(long.l) As "labs"
EndImport
CompilerCase #PB_OS_Linux
ImportC ""
Abs64(quad.q) As "llabs"
Abs32(long.l) As "labs"
EndImport
CompilerCase #PB_OS_MacOS
ImportC ""
Abs64(quad.q) As "_llabs"
Abs32(long.l) As "_labs"
EndImport
CompilerEndSelect
var1.i = -1
Debug Abs64(var1)
var2.l = -10
Debug Abs32(var2)
Re: Absolute Val for Integers?
Posted: Mon Jan 21, 2019 6:05 pm
by wilbert
mk-soft wrote:Is ImportC right?
For MacOS and Linux it is working fine for PB x64.
Unfortunately I can't test for PB x86.
Re: Absolute Val for Integers?
Posted: Tue Jan 22, 2019 8:25 am
by Lord
May I ask a question?
Why does Helle's Abs(64) return wrong a result:
Code: Select all
;Windows x64
If OpenLibrary(0, "msvcrt.dll")
Prototype.q Abs64(V1.q)
Abs64.Abs64 = GetFunction(0, "_abs64")
CloseLibrary(0)
Else
;Error
EndIf
1105645676897669811
1105645676897669711
mk-soft's Abs64() gives the correct result:
Code: Select all
Import ""
Abs64(quad.q) As "_abs64"
EndImport
var1.i = 1105645676897669811
Debug var1
Debug Abs64(var1)
1105645676897669811
1105645676897669811
At least on my machine.
Re: Absolute Val for Integers?
Posted: Tue Jan 22, 2019 9:06 am
by djes
Helle wrote:
y1.q = 100
z1.q = 110564567689766987
x1.q = y1 - z1
Debug Abs64(x1)

Re: Absolute Val for Integers?
Posted: Tue Jan 22, 2019 9:53 am
by wilbert
As a macro ...
Code: Select all
Macro _Abs(n)
((n)*(Bool((n)>0)*2-1))
EndMacro
Debug _Abs(100 - 110564567689766987)
Debug _Abs(-2.75)
Re: Absolute Val for Integers?
Posted: Tue Jan 22, 2019 10:30 am
by NicTheQuick
But remember it will not work for the lowest number. In fact you can turn a seemingly positive value into a negative one. Normally there should be an exception but unforrtunality there is no such option for Purebasic.
Code: Select all
var1.i = 9223372036854775808
Debug Abs64(var1)
Re: Absolute Val for Integers?
Posted: Tue Jan 22, 2019 2:42 pm
by Josh
infratec wrote:Josh wrote:And why doesn't do Pb this by itself? Shouldn't be so complicated that Abs () automatically detects whether it is an integer or a float.
Does PB offer you the posibility to have one procedure parameter which can reperesent different types?
Even if you use a structure with Union, how can you decide if it is a float or an integer value?
It is not so easy as you think.
- You can't compare Pb functions with a user procedure. In some cases Pb functions do more, than you can do with procedures.
- You can't execute the function Abs() on a structure but only on an element of the structure. So it is clear what type it is.
Re: Absolute Val for Integers?
Posted: Tue Jan 22, 2019 4:44 pm
by Lord
That's strange:
Lord wrote:May I ask a question?
Why does Helle's Abs(64) return wrong a result:
Code: Select all
;Windows x64
If OpenLibrary(0, "msvcrt.dll")
Prototype.q Abs64(V1.q)
Abs64.Abs64 = GetFunction(0, "_abs64")
CloseLibrary(0)
Else
;Error
EndIf
1105645676897669811
1105645676897669711
mk-soft's Abs64() gives the correct result:
Code: Select all
Import ""
Abs64(quad.q) As "_abs64"
EndImport
var1.i = 1105645676897669811
Debug var1
Debug Abs64(var1)
1105645676897669811
1105645676897669811
At least on my machine.
I did a Copy&Paste of both, codes and results from IDE and debugger output, to this forum.
Now I copied both snippets from forum back to my IDE and now I get from both codes the same results.
Magic?
Re: Absolute Val for Integers?
Posted: Tue Jan 22, 2019 9:31 pm
by idle
just tried this out of curiosity
Code: Select all
Macro IABS(v) ;in line with out branching
((v) ! ((v)>>((SizeOf(integer)<<3)-1))) - ((v)>>((SizeOf(integer)<<3)-1))
EndMacro
a = -123
a = IAbs(a)
Debug a
and with the courtesy of the peep hole optimizer results in
MOV r15,qword [v_a]
MOV r14,qword [v_a]
SAR r14,63
XOR r15,r14
MOV r14,qword [v_a]
SAR r14,63
SUB r15,r14
MOV qword [v_a],r15
Re: Absolute Val for Integers?
Posted: Wed Jan 23, 2019 12:39 am
by Olliv
This is clever (very), but it does not solve an exception problem.
First, branch prevents the CPU to process with a sign flag random state as we can see above.
Second, branch must be used to manage an exception, and show us, we must give a procedure address to treat it.
Code: Select all
Procedure IntegerAbsoluteException()
MessageRequester("Error", "Domain overflow")
EndProcedure
Procedure IntegerAbs(A.Q, *exceptionaddr)
! mov rbx, 0x8000000000000000 ; THE problem
! xor rax, rax
! add rax, [p.v_A]
! Jns positive
! cmp rax, rbx
! jz exception
! xor rax, 0xffffffffffffffff
! add rax, 1
! positive:
ProcedureReturn
! exception:
! call qword [p.p_exceptionaddr]
EndProcedure
Debug IntegerAbsolute(-5, @IntegerAbsoluteException() )
Floats float, but integers do not float.
Re: Absolute Val for Integers?
Posted: Wed Jan 23, 2019 1:23 am
by jack
@idle
that's very compact code, just for fun I tried the following in the compiler explorer C++
https://godbolt.org
Code: Select all
long long int iabs(long long int v)
{
return (v<0) ? -v:v;
}
resulting asm, (rdi holds the argument)
Code: Select all
mov rdx, rdi
mov rax, rdi
sar rdx, 63
xor rax, rdx
sub rax, rdx
ret
except for different registers, it's practically identical
Re: Absolute Val for Integers?
Posted: Wed Jan 23, 2019 1:34 am
by idle
jack wrote:@idle
that's very compact code, just for fun I tried the following in the compiler explorer C++
https://godbolt.org
Code: Select all
long long int iabs(long long int v)
{
return (v<0) ? -v:v;
}
resulting asm, (rdi holds the argument)
Code: Select all
mov rdx, rdi
mov rax, rdi
sar rdx, 63
xor rax, rdx
sub rax, rdx
ret
I'm mystified how it transforms a ternary if into that, yes that's pretty much the optimal
pity cant do that as an inline macro though.
Olliv raised an important point, there is a need to check for overflow $8000000000000000
though I'm not sure if it should raise and exception
@Olliv
could wrap the overflow to 0 so it can be tested ?
you'd still have to check anyway if you were going to do a divide
Code: Select all
Macro IABS(v) ;in place no branching peep hole optimizer works
(((v) ! ((v)>>((SizeOf(integer)<<3)-1))) - ((v)>>((SizeOf(integer)<<3)-1))) & ($8000000000000000-1)
EndMacro
a = $8000000000000000;-1
b = IAbs(a)
If b
Debug "valid abs " + b
Else
Debug "invalid abs 0 or overflow"
EndIf