Absolute Val for Integers?
Re: Absolute Val for Integers?
I don't see a reason for a $8000000000000000 exception as the problem is not really with the abs function.
If you look at the input value as a signed integer (which it is) and the output value as an unsigned integer (which it is) the returned value is fine.
The main problem is that PB doesn't support unsigned integers.
If you format the output as an unsigned integer, it will show 9223372036854775808.
If you look at the input value as a signed integer (which it is) and the output value as an unsigned integer (which it is) the returned value is fine.
The main problem is that PB doesn't support unsigned integers.
If you format the output as an unsigned integer, it will show 9223372036854775808.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Absolute Val for Integers?
I don't think it's an exception either but it just means you need to check the result is > 0wilbert wrote:I don't see a reason for a $8000000000000000 exception as the problem is not really with the abs function.
If you look at the input value as a signed integer (which it is) and the output value as an unsigned integer (which it is) the returned value is fine.
The main problem is that PB doesn't support unsigned integers.
If you format the output as an unsigned integer, it will show 9223372036854775808.
it's still a valid point though and if you wanted to do a bool comparison with it wrapping it to 0 makes sense
even so it's still not ideal but as an inline macro it's not to far from the optimal solution.
Code: Select all
Macro IABS(v) ;in place no branching and gets peep hole optimized with overflow to 0
(((v) ! ((v)>>((SizeOf(integer)<<3)-1))) - ((v)>>((SizeOf(integer)<<3)-1))) ;& ($8000000000000000-1)
EndMacro
Re: Absolute Val for Integers?
Why should AbsI check for an exception? You already have the same problem with basic arithmetical operation:
To 99.99%, a program will not come into this range and if a programmer believes that this is a critical area for him, he must check the value by himself.
@Idle
That doesn't run at x86:
Code: Select all
z.q = -9223372036854775808
Debug z
Debug 0 - z
Debug z - 1
@Idle
That doesn't run at x86:
Code: Select all
Macro IABS(v) ;in place no branching and gets peep hole optimized with overflow to 0
(((v) ! ((v)>>((SizeOf(integer)<<3)-1))) - ((v)>>((SizeOf(integer)<<3)-1))) ;& ($8000000000000000-1)
EndMacro
; x86 x64
Debug $8000000000000000-1 ; 9223372036854775807 9223372036854775807
Debug Iabs ($8000000000000000-1) ; 9223372028264841217 9223372036854775807
sorry for my bad english
Re: Absolute Val for Integers?
Good luck
Re: Absolute Val for Integers?
@josh
The macro will work fine for integers but it won't work for quads on x86 and you can ignore the code after the comment.
that was for discussion on what to do on the range limit.
The macro will work fine for integers but it won't work for quads on x86 and you can ignore the code after the comment.
that was for discussion on what to do on the range limit.
Windows 11, Manjaro, Raspberry Pi OS


-
- Addict
- Posts: 4777
- Joined: Thu Jun 07, 2007 3:25 pm
- Location: Berlin, Germany
Re: Absolute Val for Integers?
Cool.wilbert wrote:As a macro ...![]()
Code: Select all
Macro _Abs(n) ((n)*(Bool((n)>0)*2-1)) EndMacro Debug _Abs(100 - 110564567689766987) Debug _Abs(-2.75)

And pretty fast. Thank you!
I wonder why the built-in Abs() function is not implemented this way.
- NicTheQuick
- Addict
- Posts: 1504
- Joined: Sun Jun 22, 2003 7:43 pm
- Location: Germany, Saarbrücken
- Contact:
Re: Absolute Val for Integers?
Because there are way too many operations taking place: one comparison, two multiplications and one substraction. Also the paramater gets called twice which is a terrible idea when the parameter is a function call. There is a single ASM instruction which can convert a value to its absolute value. That would be the correct way for a built-in function.Little John wrote:Cool.wilbert wrote:As a macro ...![]()
Code: Select all
Macro _Abs(n) ((n)*(Bool((n)>0)*2-1)) EndMacro Debug _Abs(100 - 110564567689766987) Debug _Abs(-2.75)
![]()
And pretty fast. Thank you!
I wonder why the built-in Abs() function is not implemented this way.
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?
That is the way the built-in function works but that single ASM instruction (fabs) operates on floating point values, not integer values.NicTheQuick wrote:There is a single ASM instruction which can convert a value to its absolute value. That would be the correct way for a built-in function.
For 32 bit integers it is accurate enough but for 64 bit integers it isn't. That is what is made clear in the first post from this thread.
A single ASM instruction to get the absolute value of a 64 bit integer value doesn't exist.
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?
Making a float value positive is easy because you only have to clear one single bit.
But I didn't expect that there is no ASM instruction to make an integer positive.
Was this method already mentioned here? But the problem remains that v is called twice.
Shitty IDE doesn't let me work anymore.
But I didn't expect that there is no ASM instruction to make an integer positive.

Was this method already mentioned here? But the problem remains that v is called twice.
Code: Select all
Macro Abs_(v)
((((v) >> 62) | 1) * (v))
EndMacro
a = -1876543
a = Abs_(a)
Debug a
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?
Only Integers
Update
Update
Code: Select all
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
Procedure AbsI(value.i)
! mov rax, qword[p.v_value]
! bt rax, 63
! jnb __absi_no
! not rax
! add rax, 1
! __absi_no:
ProcedureReturn
EndProcedure
CompilerElse
Procedure AbsI(value.i)
! mov eax, dword[p.v_value]
! bt eax, 31
! jnb __absi_no
! not eax
! add eax, 1
! __absi_no:
ProcedureReturn
EndProcedure
CompilerEndIf
qVal.i = -2100
Debug AbsI(qVal)
lVal.l = -2200
Debug AbsI(lVal)
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?
A small comparison between different ASM methods (x64).
On my computer there's very little difference in speed.
On my computer there's very little difference in speed.
Code: Select all
Procedure AbsI(value.i)
! mov rax, qword[p.v_value]
! bt rax, 63
! jnb __absi_no
! not rax
! add rax, 1
! __absi_no:
ProcedureReturn
EndProcedure
Procedure AbsI_2(value.i)
!mov rax, [p.v_value]
!cqo
!add rax, rdx
!xor rax, rdx
ProcedureReturn
EndProcedure
Procedure AbsI_3(value.i)
!mov rax, [p.v_value]
!neg rax
!cmovs rax, [p.v_value]
ProcedureReturn
EndProcedure
n = 12345678
t1 = ElapsedMilliseconds()
For i=1 To 200000000
r = AbsI(n)
Next
t2 = ElapsedMilliseconds()
For i=1 To 200000000
r = AbsI_2(n)
Next
t3 = ElapsedMilliseconds()
For i=1 To 200000000
r = AbsI_3(n)
Next
t4 = ElapsedMilliseconds()
MessageRequester("Results", Str(t2-t1)+" vs "+Str(t3-t2)+" vs "+Str(t4-t3))
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
-
- Addict
- Posts: 4777
- Joined: Thu Jun 07, 2007 3:25 pm
- Location: Berlin, Germany
Re: Absolute Val for Integers?
I agree. However, this is only because that macro is written in a way so that it can be called like a function. A built-in function doesn't have to work exactly like this, but could copy the value of the parameter to a variable.NicTheQuick wrote:Also the paramater gets called twice which is a terrible idea when the parameter is a function call.Little John wrote:I wonder why the built-in Abs() function is not implemented this way.
Same here on my computer.wilbert wrote:A small comparison between different ASM methods (x64).
On my computer there's very little difference in speed.
And even a bit faster than any of these three procedures (using the same test code as you did) is
Code: Select all
Macro _Abs(n)
((n)*(Bool((n)>0)*2-1))
EndMacro

Re: Absolute Val for Integers?
I don't know if I completely misunderstand something here, but what about a simple 0-x?
Code: Select all
Procedure AbsI(value.i)
! mov rax, qword[p.v_value]
! bt rax, 63
! jnb __absi_no
! not rax
! add rax, 1
! __absi_no:
ProcedureReturn
EndProcedure
Procedure AbsI_2(value.i)
!mov rax, [p.v_value]
!cqo
!add rax, rdx
!xor rax, rdx
ProcedureReturn
EndProcedure
Procedure AbsI_3(value.i)
!mov rax, [p.v_value]
!neg rax
!cmovs rax, [p.v_value]
ProcedureReturn
EndProcedure
n = 12345678
t1 = ElapsedMilliseconds()
For i=1 To 200000000
r = AbsI(n)
Next
t2 = ElapsedMilliseconds()
For i=1 To 200000000
r = AbsI_2(n)
Next
t3 = ElapsedMilliseconds()
For i=1 To 200000000
r = AbsI_3(n)
Next
t4 = ElapsedMilliseconds()
For i=1 To 200000000
If n < 0
n = 0 - n
EndIf
Next
t5 = ElapsedMilliseconds()
MessageRequester("Results", Str(t2-t1)+" vs "+Str(t3-t2)+" vs "+Str(t4-t3)+" vs "+Str(t5-t4))
sorry for my bad english
Re: Absolute Val for Integers?
I added AbsQ(Value)
Update
- Added wilberts code
Update
- Added wilberts code
Code: Select all
;-TOP
; AbsI and AbsQ
; By mk-soft and wilbert from 24.01.2019
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
Procedure AbsI(value.i)
!mov rax, [p.v_value]
!neg rax
!cmovs rax, [p.v_value]
ProcedureReturn
EndProcedure
CompilerElse
Procedure AbsI(value.i)
!mov eax, [p.v_value]
!neg eax
!cmovs eax, [p.v_value]
ProcedureReturn
EndProcedure
CompilerEndIf
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
Procedure.q AbsQ(value.q)
!mov rax, [p.v_value]
!neg rax
!cmovs rax, [p.v_value]
ProcedureReturn
EndProcedure
CompilerElse
Procedure.q AbsQ(value.q)
! lea eax,dword[p.v_value]
! mov edx,dword[eax+4]
! mov eax,dword[eax]
! bt edx, 31
! jnb __absq_no
! not eax
! not edx
! add eax,1
! adc edx,0
! __absq_no:
ProcedureReturn
EndProcedure
CompilerEndIf
;-
Define iVal.i = $80000001
Debug AbsI(iVal)
Define qVal.q = $8000000000000001
r1.q = AbsQ(qVal)
Debug r1
Debug Hex(r1)
Last edited by mk-soft on Thu Jan 24, 2019 10:05 pm, edited 2 times in total.
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?
P.S.
The third method by Wilbert is the fastest . The fourth method cannot return a return value and is therefore invalid.
The third method by Wilbert is the fastest . The fourth method cannot return a return value and is therefore invalid.
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