Multiply float by -1: fast or slow?

C

Chris Stankevitz

Is this a fast way to invert a float:

inline Invert(float& f)
{
f *= -1.0f;
}

I'd like the CPU to flip the sign bit (and not carry out a float-float
multiplication). Please enlighten me! I'm going be performing a lot
of these.

Thanks,

Chris
 
R

Roman S.

Chris said:
Is this a fast way to invert a float:

inline Invert(float& f)
{
f *= -1.0f;
}

I'd like the CPU to flip the sign bit (and not carry out a float-float
multiplication). Please enlighten me! I'm going be performing a lot
of these.

Thanks,

Chris

I think what you should do is:

inline Invert(float& f)
{
f = -f;
}
 
I

Ian Collins

Chris said:
Is this a fast way to invert a float:

inline Invert(float& f)

Missing return type.
{
f *= -1.0f;
}

I'd like the CPU to flip the sign bit (and not carry out a float-float
multiplication). Please enlighten me! I'm going be performing a lot
of these.
Try it, check the generated assembler. Your compiler should be able to
perform the required optimisation.
 
J

John Carson

Chris Stankevitz said:
Is this a fast way to invert a float:

inline Invert(float& f)
{
f *= -1.0f;
}

I'd like the CPU to flip the sign bit (and not carry out a float-float
multiplication). Please enlighten me! I'm going be performing a lot
of these.


The only way to know is to test it. Different compilers will handle the same
code differently and different hardware platforms will have different
abilities.

On my computer

f = -f;

is slightly faster, but my computer can perform either operation about 100
million times per second. Code for testing:

#include <iostream>
#include <ctime>
using namespace std;

const int loops = 1000000000;

int main()
{
volatile float f = 345.898f;
int start = clock();
for(size_t i=0; i<loops; ++i)
f *= -1;
cout << ((double)clock()-time)/CLOCKS_PER_SEC << endl;

start = clock();
for(size_t i=0; i<loops; ++i)
f = -f;
cout << ((double)clock()-time)/CLOCKS_PER_SEC << endl;

return 0;
}

Note that tests like the above can't tell you exactly what speed you will
get in a real application, but they give you some idea.
 
M

Michael DOUBEZ

Chris Stankevitz a écrit :
Is this a fast way to invert a float:

inline Invert(float& f)
{
f *= -1.0f;
}

I'd like the CPU to flip the sign bit (and not carry out a float-float
multiplication). Please enlighten me! I'm going be performing a lot
of these.

If you don't mind portability, you can simply flip it:
reinterpret_cast<char*>(&f)[sizeof(float)-1]^=0x80;

This is evil.

Michael
 
J

John Carson

John Carson said:
Code for testing:

#include <iostream>
#include <ctime>
using namespace std;

const int loops = 1000000000;

int main()
{
volatile float f = 345.898f;
int start = clock();
for(size_t i=0; i<loops; ++i)
f *= -1;
cout << ((double)clock()-time)/CLOCKS_PER_SEC << endl;

// change time to start in previous line
start = clock();
for(size_t i=0; i<loops; ++i)
f = -f;
cout << ((double)clock()-time)/CLOCKS_PER_SEC << endl;

// change time to start in previous line
 
R

robertwessel2

Chris Stankevitz a écrit :
Is this a fast way to invert a float:
inline Invert(float& f)
{
f *= -1.0f;
}
I'd like the CPU to flip the sign bit (and not carry out a float-float
multiplication). Please enlighten me! I'm going be performing a lot
of these.If you don't mind portability, you can simply flip it:
reinterpret_cast<char*>(&f)[sizeof(float)-1]^=0x80;

This is evil.


Not only is it not portable, it doesn't work on (probably) the majority
of architectures out there. Mind you that the OP did not specify that
he was running on x86 or another machine which has IEEE-like floats
stored little endian. Even worse, your code may be substantially
slower than just a straight multiplication by -1 or negation since it
will almost certainly force the compiler to actually store the value in
memory before flipping the bit - something that would likely be avoided
if the value was already in a register, and the function actual got (as
requested) inlined. All quite implementation dependent, of course.
 
I

Ian Collins

Michael said:
Chris Stankevitz a écrit :
Is this a fast way to invert a float:

inline Invert(float& f)
{
f *= -1.0f;
}

I'd like the CPU to flip the sign bit (and not carry out a float-float
multiplication). Please enlighten me! I'm going be performing a lot
of these.


If you don't mind portability, you can simply flip it:
reinterpret_cast<char*>(&f)[sizeof(float)-1]^=0x80;
Don't try and 2nd guess the compiler when it comes to this sort of
optimisation.
This is evil.
It sure is.
 
M

Michael DOUBEZ

(e-mail address removed) a écrit :
Chris Stankevitz a écrit :
Is this a fast way to invert a float:
inline Invert(float& f)
{
f *= -1.0f;
}
I'd like the CPU to flip the sign bit (and not carry out a float-float
multiplication). Please enlighten me! I'm going be performing a lot
of these.If you don't mind portability, you can simply flip it:
reinterpret_cast<char*>(&f)[sizeof(float)-1]^=0x80;

This is evil.


Not only is it not portable, it doesn't work on (probably) the majority
of architectures out there. Mind you that the OP did not specify that
he was running on x86 or another machine which has IEEE-like floats
stored little endian. Even worse, your code may be substantially
slower than just a straight multiplication by -1 or negation since it
will almost certainly force the compiler to actually store the value in
memory before flipping the bit - something that would likely be avoided
if the value was already in a register, and the function actual got (as
requested) inlined. All quite implementation dependent, of course.

Yes, it is evil. But, if you do something implementation dependant, well
you just do it.

And I expect this kind of trick to work on IEEE, IBM and VAX float since
they all put the sign bit on the MSB. Making a switch for litlle/big
endian is not really a big deal.

Concerning the perfs, I didn't make any bench but the truth is that bit
operations on float are forbidden so unless the compiler optimize the
operation (-() or *-1.0f) alternatives are equivalent.

Now, this is not something I would do but worth a try.

Michael
 
M

Michael DOUBEZ

Michael DOUBEZ a écrit :
(e-mail address removed) a écrit :
Chris Stankevitz a écrit :

Is this a fast way to invert a float:
inline Invert(float& f)
{
f *= -1.0f;
}
I'd like the CPU to flip the sign bit (and not carry out a float-float
multiplication). Please enlighten me! I'm going be performing a lot
of these.If you don't mind portability, you can simply flip it:
reinterpret_cast<char*>(&f)[sizeof(float)-1]^=0x80;

This is evil.


Not only is it not portable, it doesn't work on (probably) the majority
of architectures out there. Mind you that the OP did not specify that
he was running on x86 or another machine which has IEEE-like floats
stored little endian. Even worse, your code may be substantially
slower than just a straight multiplication by -1 or negation since it
will almost certainly force the compiler to actually store the value in
memory before flipping the bit - something that would likely be avoided
if the value was already in a register, and the function actual got (as
requested) inlined. All quite implementation dependent, of course.

Concerning the perfs, I didn't make any bench but the truth is that bit
operations on float are forbidden so unless the compiler optimize the
operation (-() or *-1.0f) alternatives are equivalent.

Now, this is not something I would do but worth a try.

Making a quick try, it is slower to cast.

Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top