Page 1 of 1
Getting the sign of a number
Posted: Sun Oct 02, 2005 12:18 am
by Dr. Dri
Code updated For 5.20+ (As PB supported)
since pb doesn't fully support boolean expressions, i have to write this annoying code
Code: Select all
Procedure Sgn(x.l)
ProcedureReturn Bool((x > 0 Or #False) - (x < 0 Or #False))
EndProcedure
Procedure SgnF(x.f)
ProcedureReturn Bool((x > 0 Or #False) - (x < 0 Or #False))
EndProcedure
Debug Sgn(-5)
Debug Sgn(-0)
Debug Sgn( 5)
Debug SgnF(-5.0)
Debug SgnF(-0.0)
Debug SgnF( 5.0)
Dri

Posted: Sun Oct 02, 2005 12:53 am
by Xombie
How about...
Code: Select all
Procedure Sgn(a.l)
ProcedureReturn a >> 31 & 1
EndProcedure
Procedure SgnF(a.f)
ProcedureReturn Int(a) >> 31 & 1
EndProcedure
Not sure if the SgnF is all that fast because of the Int()
Posted: Sun Oct 02, 2005 12:55 am
by Dr. Dri
doesn't work
Code: Select all
Procedure Sgn(a.l)
ProcedureReturn a >> 31 & 1
EndProcedure
Debug Sgn(-5)
Debug Sgn(-0)
Debug Sgn( 5)
Dri
Posted: Sun Oct 02, 2005 1:04 am
by Xombie
It's always been my understanding that 0 can neither be positive or negative. So zero has no sign. Some math majors want to help me out on this one?
However that fudges my SgnF function for numbers less than one >_>
Posted: Sun Oct 02, 2005 9:00 am
by Psychophanta
But those function are not valid for .b or .w
Here i made one:
viewtopic.php?t=8121
But here are 2 different functions for it in which it is improved in size and speed:
Code: Select all
Procedure.b Sgn(n.f)
!fld dword[esp] ;push FPU stack, and load value to st0
!fstp st1 ;leaves popped FPU stack while maintaining value in st0
!ftst ;test value for update FPU flags.
!fnstsw ax ;transfers FPU status word to ax
!fwait
!sahf ;transfers ah to CPU flags.
!seta al ;if positive al=1, else al=0
!jnc near @f;if negative jump, else:
!dec al
!@@:movsx eax,al ;return and finish
ProcedureReturn
EndProcedure
;Prove it:
r.f=7
Debug Sgn(0.000094)
Debug Sgn(-v.b)
Debug Sgn(-r.f)
Debug ""
For t.w=-20 To 20
Debug Sgn(t.w)
Next
Posted: Sun Oct 02, 2005 11:03 am
by Dr. Dri
Psychophanta wrote:But those function are not valid for .b or .w
I agree, it's like using a byte or a word with hex(). You need & $FF or $FFFF...
Dri
Posted: Sun Oct 02, 2005 11:17 am
by Psychophanta
Nope, i was wrong!
Your functions works for .b and .w too.
But not needed 2 separate functions; you can resume it in one only function for all PB native types:
Code: Select all
Procedure Sgn(x.f)
ProcedureReturn (x > 0 Or #False) - (x < 0 Or #False)
EndProcedure
However, even it seems to work, that code is not correct for PB specifications

Posted: Sun Oct 02, 2005 2:23 pm
by Pupil
If you want something a bit faster, that only works for integers you can use this:
Code: Select all
Procedure Sgn(a.l)
MOV eax, [esp]
XOR ebx, ebx
AND eax, eax
SETNZ bl
SAR eax, 31
OR eax, ebx
ProcedureReturn
EndProcedure
Posted: Sun Oct 02, 2005 5:05 pm
by Killswitch
0 can't be postive or negative, but 1-0 and 1+0 are equal so it doesn't matter. x^0 = 1, including 0^0=1 - I've always found that weird. Just don't ever divide anything by zero - things get horribly complex then.
Posted: Sun Oct 02, 2005 6:40 pm
by va!n
what about this way?
Code: Select all
Procedure Sgn(x.l)
If x.l < 0
result = #True
Else
result = #False
EndIf
ProcedureReturn result
EndProcedure
Procedure SgnF(x.f)
If x.f < 0
result = #True
Else
result = #False
EndIf
ProcedureReturn result
EndProcedure
Debug Sgn(-5)
Debug Sgn(-0)
Debug Sgn( 5)
Debug SgnF(-5.0)
Debug SgnF(-0.0)
Debug SgnF( 5.0)
Btw, Debug SgnF(-0.0) returns #FALSE, because 0 cant be negative or positive!
Posted: Sun Oct 02, 2005 7:47 pm
by Dr. Dri
@Pupil
Nice example but i'm an ASM begginer so i don't understand

but it works very well ^^
@va!n
My idea was to return a -1|0|1 which would mean neg|nul|pos
Dri
Posted: Mon Oct 03, 2005 10:16 pm
by MikeB
Psychophanta gave us two routines, as far as I can see the first one works but the second one is wrong for -0.xxxx. Or at least it is wrong for -1/7 which is what I used.
MikeB
Posted: Mon Oct 03, 2005 11:27 pm
by Psychophanta
MikeB wrote:Psychophanta gave us two routines, as far as I can see the first one works but the second one is wrong for -0.xxxx. Or at least it is wrong for -1/7 which is what I used.
MikeB
Oopps!
You're right. Thanx to correct me. I was at the point to add it to my 'tested' collection.
Well, then i gave you only the first one

But here is one much faster, and smaller.
It is tricky, and it has an only problem: if you give it a '-0' value, it will result as '-1'. But apart of that, it works wonderfully:
Code: Select all
Procedure.b Sgn(n.f)
!mov eax,dword[esp]
!test eax,eax
!jz @f
!sar eax,31
!bts eax,0
!@@:
ProcedureReturn
EndProcedure
Posted: Mon Oct 03, 2005 11:58 pm
by va!n
@Psychophanta
Respect! Very nice! Works fine here! Keep it on!
