Page 1 of 1
Abs(quad.q)
Posted: Fri Jan 05, 2024 4:09 pm
by juergenkulow
Please change in
documentation Abs:
Code: Select all
@Function Result.f(.d)(.q) = Abs(Number.f(.d)(.q))
@Description
Returns the absolute value of the given value.
@Parameter "Number.f or Number.d or Number.q"
and add in pbcompilerc
See:
Strange behavior of Abs()
Re: Abs(quad.q)
Posted: Wed Jan 31, 2024 11:59 am
by SMaag
here a first solution for the ABS() Problem in C-Backend when using values with more than 53Bits
To see the Bug: Use C-Backend and set CPU to MMX/SSE Version or activate 'Optimize generated code'
Updated!
Code: Select all
; This is a test to solve tha PB's ABS() Problem at C-Backend
; because at ASM Backend the 80Bit Float unit is used for ABS() what works perfect for 64Bit INT
; In C-Backend a MMX Version is used for ABS(). This is a problem because MMX use only 64Bit Floats
; with a manitassa of 53 Bits. This will cause bugs if the ABS() is used for values with more bits
; like address calculation!
; Assembler_ShiftArithmeticRight_Bits : This is how to cacluclate the NumberOfBits to shift
; its 63 for x64 und 31 for x32
#ABS_SAR_BITS = (SizeOf(Integer)*8-1)
; This is the optimized Abs Version (translated from Assembler to PB-Code; Soure Math.asm from Linux Asm Project
; X!(X>>63)-(X>>63) ; x64
; X!(X>>31)-(X>>31) ; x32
; PB 6.04 on Ryzen 5800 the Macro is nearly same speed as PB's ABS()
; for 50Mio calls PB_ABS() = 53ms AbsI = 58ms
Macro AbsI(X)
(X!(X>>(SizeOf(Integer)*8-1))-(X>>(SizeOf(Integer)*8-1)))
EndMacro
; only for x32 we need an extra Macro for AbsQ() which shifts 63 Bit for Quads
CompilerIf #PB_Compiler_Backend =#PB_Backend_Asm
Macro AbsQ(X)
Abs(X)
EndMacro
CompilerElse ; C-Backend
Macro AbsQ(X)
(X!(X>>63)-(X>>63))
EndMacro
CompilerEndIf
Procedure procAbs(X)
CompilerIf #PB_Compiler_Backend = #PB_Backend_Asm
CompilerIf #PB_Compiler_64Bit
!MOV RDX, [p.v_X]
!MOV RAX, RDX
!SAR RDX, 63
!XOR RAX, RDX
!SUB RAX, RDX
ProcedureReturn
CompilerElse
!MOV EDX, [p.v_X]
!MOV EAX, EDX
!SAR EDX, 31
!XOR EAX, EDX
!SUB EAX, EDX
ProcedureReturn
CompilerEndIf
CompilerElse ; C-Backend
ProcedureReturn X!(X>>63)-(X>>63)
CompilerEndIf
EndProcedure
Define I, K, L, N, t1, t2, t3
CompilerIf #PB_Compiler_Debugger
; to see the Bug you have to switch on Compiler\Compiler Options\Optimze generated code
; or set CPU with MMX/SSE
N = 1234567891234567890 ; in C Backend the difference is 46
; N = 1<<54 -1 ; in C Backend the difference is 1
Debug "N = " + N
Debug "Hex(N) = " + Hex(N)
Debug #Null$
Debug "In C-Backend this is wrong! If Compiler\Compiler Options\Optimze generated code is activated or MMS/SSE CPU is selected"
K = Abs(N)
Debug "PB Abs(N) = " + K
K = Abs(-N)
Debug "PB Abs(-N) = " + K
Debug #Null$
Debug "Macro AbsI()"
K = AbsI(N)
Debug K
K = AbsI(-N)
Debug K
Debug #Null$
K = AbsI(N)
L= Abs(N)
K -L
Debug "AbsI(N) - Abs(N) = " + K
Debug "The difference should be 0 but in C-Backend it is not!"
CompilerElse
#Start = 100000000000000005
#LOOPS = 50000000 ; 50Mio
t1 = ElapsedMilliseconds()
For I = 1 To #LOOPS
K = AbsI(-I)
L = AbsI(I)
Next
t1 = ElapsedMilliseconds() - t1
t2 = ElapsedMilliseconds()
For I = 1 To #LOOPS
K = Abs(-I)
L = Abs(I)
Next
t2 = ElapsedMilliseconds() - t2
t3 = ElapsedMilliseconds()
For I = 1 To #LOOPS
K = procAbs(-I)
L = procAbs(I)
Next
t3 = ElapsedMilliseconds() - t3
MessageRequester("Time", "Macro AbsI() = " + Str(t1) + #CRLF$ + "PB Abs() = " + Str(t2)+ #CRLF$ + "ASM procAbs() = " + Str(t3))
CompilerEndIf