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 :wink:

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 :wink:

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. :shock:
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