flat assembler
Message board for the users of flat assembler.

Index > Main > How implement signum for float value ?

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
Roman



Joined: 21 Apr 2012
Posts: 2111
Roman 12 Aug 2026, 15:03
I read sign can return 0 or 1 or -1. Three values.
sign(0) = 0
sign(10)=1
sign(-3)=-1

I do this code, but not sure is correct.
Code:
macro xmSign x1,r { local l1,l2,ll
   xor r,r
   xorps xmm7,xmm7
   comiss xmm7,xmm#x1 ;if value = 0
   jz    ll

l1: comiss xmm#x1,xmm7
   ja    l2
   mov r,-2     
l2: inc r
ll:

}

mov eax,1f
movd xmm1,eax
xmSign 1,dl

    


Last edited by Roman on 12 Aug 2026, 15:10; edited 2 times in total
Post 12 Aug 2026, 15:03
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1235
Location: Russia
macomics 12 Aug 2026, 15:07
Code:
mov eax, 1f
and eax, 80000000h
jz .unsigned ; jump
; signed
; ...
.unsigned:
mov eax, -1f
and eax, 80000000h
jnz .signed ; jump
; unsigned
; ...
.signed:    
Post 12 Aug 2026, 15:07
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 21055
Location: In your JS exploiting you and your system
revolution 12 Aug 2026, 15:10
COMISS sets ZF, PF, and CF so a single comparison can use JA, JB, JZ and JP to detect all possible outcomes.

I don't recommend to use the raw binary value with integer compare, because NaN make it very complicated and worse than the internal hardware.
Post 12 Aug 2026, 15:10
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2111
Roman 12 Aug 2026, 18:35
This ok.
Code:
macro xmSign x1,r { local l2,ll
   xor r,r
   xorps xmm7,xmm7
   comiss xmm#x1,xmm7
   jz    ll
   ja    l2
   mov r,-2     ;-2
l2: inc r
ll:

} 
    
Post 12 Aug 2026, 18:35
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 21055
Location: In your JS exploiting you and your system
revolution 12 Aug 2026, 23:10
JP should be the first test in case of NaN, then test for JB/JA/JZ.
Code:
comiss ...
jp .unordered
jz .equal
ja .above
jb .below
; can't reach here.    
Post 12 Aug 2026, 23:10
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 21055
Location: In your JS exploiting you and your system
revolution 13 Aug 2026, 00:25
revolution wrote:
I don't recommend to use the raw binary value with integer compare, because NaN make it very complicated and worse than the internal hardware.
Comparing positive zero to negative zero is also a problem when reading the raw binary value.
Post 13 Aug 2026, 00:25
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 21055
Location: In your JS exploiting you and your system
revolution 13 Aug 2026, 04:05
To eliminate the branches:
Code:
        comiss  xmm0, xmm1
        jp      .error
        setc    dl
        setnz   cl
        neg     dl
        lea     edx, [edx * 2 + ecx]    ; dl = -1, 0, or +1    
Can be tested like this:
Code:
format elf executable

SYS32_exit_group = 252

        xorpd   xmm0, xmm0
        irp v, -6.0f, 0.0f, +6.0f {
                x = dword v
                mov     eax, x
                movd    xmm1, eax
                comiss  xmm0, xmm1
                jp      .error
                setc    dl
                setnz   cl
                neg     dl
                lea     edx, [edx * 2 + ecx]    ; dl = -1, 0, or +1
                if x and 0x7fffffff = 0
                        cmp     dl, 0
                        jnz     .error
                else if x shr 31 = 0
                        cmp     dl, -1
                        jnz     .error
                else
                        cmp     dl, 1
                        jnz     .error
                end if
        }
        mov     eax, SYS32_exit_group
        xor     ebx, ebx
        int     0x80

.error:
        mov     eax, SYS32_exit_group
        or      ebx, -1
        int     0x80    
Code:
$ fasm test.asm && ./test && echo passed
flat assembler  version 1.73.31  (16384 kilobytes memory)
2 passes, 200 bytes.
passed    
Post 13 Aug 2026, 04:05
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2111
Roman 13 Aug 2026, 04:13
Code:
xor edx,edx
xor ecx,ecx
comiss  xmm0, xmm1
jp      .error
setc    dl
setnz   cl
neg     dl
lea     edx, [edx * 2 + ecx]    ; dl = -1, 0, or +1 
    
Post 13 Aug 2026, 04:13
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 21055
Location: In your JS exploiting you and your system
revolution 13 Aug 2026, 04:17
The leading xor's aren't sufficient unless the NEG DL is changed to NEG EDX.

It is probably easier to use a single MOVSX EDX, DL after DL is defined.
Post 13 Aug 2026, 04:17
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4574
Location: vpcmpistri
bitRAKE 13 Aug 2026, 06:35
signum function ...
Code:
        xor eax, eax
        comiss xmm0, xmm1
        jp .unordered
        seta al
        sbb eax, 0    


Code:
movaps xmm2, xmm1
cmpltss xmm2, xmm0   ; -1 if b
cmpltss xmm0, xmm1   ; -1 if a<b
psubd xmm0, xmm2
movd eax, xmm0       ; -1 / 0 / +1, unordered -> 0    
... easy to parallelize.
Post 13 Aug 2026, 06:35
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 21055
Location: In your JS exploiting you and your system
revolution 13 Aug 2026, 06:52
bitRAKE wrote:
signum function ...
Code:
        xor eax, eax
        comiss xmm0, xmm1
        jp .unordered
        seta al
        sbb eax, 0    
Nice.

It can also be one instruction, and 3 bytes, shorter if a 32-bit value isn't needed.
Code:
        comiss xmm0, xmm1
        jp .unordered
        seta al
        sbb al, 0    
Or placing movsx on the end is the same length.
Code:
        comiss xmm0, xmm1
        jp .unordered
        seta al
        sbb al, 0
        movsx eax,al    
Post 13 Aug 2026, 06:52
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2111
Roman 13 Aug 2026, 07:08
Thanks Revolution.
I took this for my intersection 3D point with 3D tetrahedron.
Code:
;working good
macro xmSign x1,r {
        xorps xmm7,xmm7
        comiss xmm#x1,xmm7
        seta r
        sbb r, 0
} 
    
Post 13 Aug 2026, 07:08
View user's profile Send private message Reply with quote
macgub



Joined: 11 Jan 2006
Posts: 375
Location: Poland
macgub 13 Aug 2026, 14:55
What about branchless negation float value?
I tried with this:
Code:
pcmpeqd xmm7,xmm7
pslld xmm7,31
xorps xmm6,xmm7
    

xm7 = temp register
xm6 = register with float value
But it sometimes produce NaN -0 value.
Post 13 Aug 2026, 14:55
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4574
Location: vpcmpistri
bitRAKE 14 Aug 2026, 08:18
macgub wrote:
What about branchless negation float value?
Code:
pxor  xmm0, xmm0
subss xmm0, xmm6    
The VPXOR is a zero-idiom on modern processors - dependency breaking, 0-cycle.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 14 Aug 2026, 08:18
View user's profile Send private message Visit poster's website Reply with quote
macgub



Joined: 11 Jan 2006
Posts: 375
Location: Poland
macgub 14 Aug 2026, 09:28
It was so easy. I sometimes tend to complicate things. Thanks a lot bitRAKE!
Post 14 Aug 2026, 09:28
View user's profile Send private message Visit poster's website Reply with quote
macgub



Joined: 11 Jan 2006
Posts: 375
Location: Poland
macgub 14 Aug 2026, 09:46
I have following statement:
Code:
   cmp      eax,1b
   jne      @f
   addps    xmm7,xmm0
   jmp      .fix
  @@:
   subps    xmm7,xmm0
  .fix:
    

Any ideas for turn it into branchless? Possibly equal or bit greater in size? I have idea: scatter eax value into xmm reg, shift left, and negate with xorps like above. But as I wrote it sometimes produce float -0 value
Post 14 Aug 2026, 09:46
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4574
Location: vpcmpistri
bitRAKE 14 Aug 2026, 10:22
If we assume the branch is random, 50%:
(Because a well predicted branch is better than branchless.)
Code:
xor    eax, 1
neg    eax            ; CF = (eax != 1)
sbb    eax, eax       ; 0 if ==1, -1 otherwise
movd   xmm1, eax
pshufd xmm1, xmm1, 0
pslld  xmm1, 31       ; 0 or 0x80000000 per lane
xorps  xmm0, xmm1
addps  xmm7, xmm0    
No memory access.

And the modern is eye candy for many...:
Code:
xor    eax, 1
neg    eax            ; CF = (eax != 1)
sbb    eax, eax       ; 0 if ==1, -1 otherwise
vpbroadcastd xmm1, eax                   ; GPR->vec broadcast, AVX512VL
vpternlogd   xmm0, xmm1, [sign]{1to4}, 01111000b ; computes A ^ (B & C)
vaddps       xmm7, xmm7, xmm0    
... way too costly.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 14 Aug 2026, 10:22
View user's profile Send private message Visit poster's website Reply with quote
macgub



Joined: 11 Jan 2006
Posts: 375
Location: Poland
macgub 15 Aug 2026, 07:41
bitRAKE, with this I cannot avoid -0 NaN problem
Code:
...
pslld  xmm1,31
; if in xmm0 resides 0 in some place
; and in xmm1 broadcasted 0x80000000
xorps xmm0,xmm1
; bring me 0x80000000 (-0) in xmm0 in some place
    

Did I miss something?
Post 15 Aug 2026, 07:41
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4574
Location: vpcmpistri
bitRAKE 15 Aug 2026, 09:30
macgub wrote:
I cannot avoid -0 NaN problem
-0 is not NaN, What do you mean? Perhaps look earlier in calculation if you are getting NaN result because ADDPS with -0 does not produce NaN. If you need to preserve XMM0 then swap the XORPS operands and use XMM1.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 15 Aug 2026, 09:30
View user's profile Send private message Visit poster's website Reply with quote
macgub



Joined: 11 Jan 2006
Posts: 375
Location: Poland
macgub 15 Aug 2026, 13:59
Quote:

ADDPS with -0 does not produce NaN.

You are right. I have bug caused other reason. Thanks for responses.
Post 15 Aug 2026, 13:59
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2026, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.