Absolute Val for Integers?
Re: Absolute Val for Integers?
@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...
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?
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)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Absolute Val for Integers?
For MacOS and Linux you would need llabs instead of _abs64 .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)
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Absolute Val for Integers?
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)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Absolute Val for Integers?
For MacOS and Linux it is working fine for PB x64.mk-soft wrote:Is ImportC right?

Unfortunately I can't test for PB x86.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Absolute Val for Integers?
May I ask a question?
Why does Helle's Abs(64) return wrong a result:
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
mk-soft's Abs64() gives the correct result:1105645676897669811
1105645676897669711
Code: Select all
Import ""
Abs64(quad.q) As "_abs64"
EndImport
var1.i = 1105645676897669811
Debug var1
Debug Abs64(var1)
At least on my machine.1105645676897669811
1105645676897669811

Re: Absolute Val for Integers?
Helle wrote: y1.q = 100
z1.q = 110564567689766987
x1.q = y1 - z1
Debug Abs64(x1)

Re: Absolute Val for Integers?
As a macro ...

Code: Select all
Macro _Abs(n)
((n)*(Bool((n)>0)*2-1))
EndMacro
Debug _Abs(100 - 110564567689766987)
Debug _Abs(-2.75)
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
- NicTheQuick
- Addict
- Posts: 1504
- Joined: Sun Jun 22, 2003 7:43 pm
- Location: Germany, Saarbrücken
- Contact:
Re: Absolute Val for Integers?
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)
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.
Re: Absolute Val for Integers?
infratec wrote:Does PB offer you the posibility to have one procedure parameter which can reperesent different types?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.
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.
sorry for my bad english
Re: Absolute Val for Integers?
That's strange:
Now I copied both snippets from forum back to my IDE and now I get from both codes the same results.
Magic?
I did a Copy&Paste of both, codes and results from IDE and debugger output, to this forum.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
mk-soft's Abs64() gives the correct result:1105645676897669811
1105645676897669711Code: Select all
Import "" Abs64(quad.q) As "_abs64" EndImport var1.i = 1105645676897669811 Debug var1 Debug Abs64(var1)
At least on my machine.1105645676897669811
1105645676897669811
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?
just tried this out of curiosity
and with the courtesy of the peep hole optimizer results in
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
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
Windows 11, Manjaro, Raspberry Pi OS


Re: Absolute Val for Integers?
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.
Floats float, but integers do not float.
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() )
Re: Absolute Val for Integers?
@idle
that's very compact code, just for fun I tried the following in the compiler explorer C++ https://godbolt.org
resulting asm, (rdi holds the argument)
except for different registers, it's practically identical
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;
}
Code: Select all
mov rdx, rdi
mov rax, rdi
sar rdx, 63
xor rax, rdx
sub rax, rdx
ret
Re: Absolute Val for Integers?
I'm mystified how it transforms a ternary if into that, yes that's pretty much the optimaljack wrote:@idle
that's very compact code, just for fun I tried the following in the compiler explorer C++ https://godbolt.orgresulting asm, (rdi holds the argument)Code: Select all
long long int iabs(long long int v) { return (v<0) ? -v:v; }
Code: Select all
mov rdx, rdi mov rax, rdi sar rdx, 63 xor rax, rdx sub rax, rdx ret
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
Windows 11, Manjaro, Raspberry Pi OS

