Hi all,

What is the fastest way to multiply four floats by 0.5 ? The floats are in a xmm register.

What is the fastest way to multiply four floats by 0.5 ? The floats are in a xmm register.

Hello,

I have never worked with floats before, but I imagine the fastest way to multiply them by 0.5 is to divide them by 2.

But this is only a thought of mine.

Regards,

Claus

I have never worked with floats before, but I imagine the fastest way to multiply them by 0.5 is to divide them by 2.

But this is only a thought of mine.

Regards,

Claus

This probably won't work for everything and is more than likely misguided but essentially you have to shift right by 1. Since floats are stored as powers of 2, you have only to subract 1 from the power in order to divide by 2.

For example with REAL8:

For REAL4 (MASM format this time):

For example with REAL8:

```
DATA SECTION
```

somefp DQ 210.244

CODE SECTION

sub D[somefp+4],00100000h ; divide REAL8 by 2

For REAL4 (MASM format this time):

```
.DATA
```

somefp REAL4 210.244

.CODE

sub DWORD PTR somefp,00800000h ; Divide REAL4 by 2

He's referring to the Exponent.

FloatingPoint values have a special binary encoding where the top handful of bits are used to keep the Exponent (and Sign bit) while the rest of the bits contain the Mantissa (also known as the Significand).

The fastest way to divide any floatingpoint value by a multiple of 2 would be to modify the Exponent, he's absolutely right, but I get the feeling you were looking for an MMX solution...

For anyone who isn't awake to this stuff,

S EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM

That's how a 32bit float is encoded under the IEEE standard.

Have a nice day :)

FloatingPoint values have a special binary encoding where the top handful of bits are used to keep the Exponent (and Sign bit) while the rest of the bits contain the Mantissa (also known as the Significand).

The fastest way to divide any floatingpoint value by a multiple of 2 would be to modify the Exponent, he's absolutely right, but I get the feeling you were looking for an MMX solution...

For anyone who isn't awake to this stuff,

S EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM

That's how a 32bit float is encoded under the IEEE standard.

Have a nice day :)

Evilhomer2k it is easy to do with SSE. You can copy the data to memory and subtract as Donkey has show below. Or if you have SSE2 you can do it in parallel. You have to have at least SSE2 to do that because you need to treat the data like integer data and SSE doesn't support that.

This probably won't work for everything and is more than likely misguided but essentially you have to shift right by 1. Since floats are stored as powers of 2, you have only to subract 1 from the power in order to divide by 2.

For example with REAL8:

For REAL4 (MASM format this time):

```
```

.data

align 16

sub_exponent dd 00800000h, 00800000h, 00800000h, 00800000h

.code

psubd xmm0,[sub_exponent]

This probably won't work for everything and is more than likely misguided but essentially you have to shift right by 1. Since floats are stored as powers of 2, you have only to subract 1 from the power in order to divide by 2.

For example with REAL8:

```
DATA SECTION
```

somefp DQ 210.244

CODE SECTION

sub D[somefp+4],00100000h ; divide REAL8 by 2

For REAL4 (MASM format this time):

```
.DATA
```

somefp REAL4 210.244

.CODE

sub DWORD PTR somefp,00800000h ; Divide REAL4 by 2

Thanks. Too bad it doesn't work for everything, 0.0 for example.

Well, you have only to make a special case for 0.0 :

MASM:

Then it seems to work in all cases.

```
DATA SECTION
```

somefp DQ 0.0

CODE SECTION

cmp D[somefp+4],0

je >

sub D[somefp+4],00100000h

:

MASM:

```
.DATA
```

somefp REAL8 0.0

.CODE

cmp DWORD PTR [somefp+4],0

je @F

sub DWORD PTR [somefp+4],00100000h

@@:

Then it seems to work in all cases.

Well, you have only to make a special case for 0.0 :

```
DATA SECTION
```

somefp DQ 0.0

CODE SECTION

cmp D[somefp+4],0

je >

sub D[somefp+4],00100000h

:

MASM:

```
.DATA
```

somefp REAL8 0.0

.CODE

cmp DWORD PTR [somefp+4],0

je @F

sub DWORD PTR [somefp+4],00100000h

@@:

Then it seems to work in all cases.

Using SSE2 that would be:

```
```

.data

align 16

four_0s real4 0.0,0.0,0.0,0.0

sub_value dd 00800000h,00800000h,00800000h,00800000h

.code

;xmm0 holds the 4 real4 values you want to multiply by 0.5

movaps xmm5,[four_0s] ;value to look for.

movaps xmm6,[sub_value] ;value to subtract from the exponentf

movaps xmm1,xmm0 ;get backup copy of data

cmpps xmm1,xmm5,0 ;xmm1 now has an FFFFFFFF in each dword location in XMM1 with a 0.0 all other locations have 0.

pandn xmm1,xmm6 ;NOTs XMM1, and then ANDs it with XMM6. So it will only subtract from the exponent if the value is non-zero

psubd xmm0,xmm1 ;only subtract the sub_value from those fields that aren't 0.0s'.