By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,491 Members | 1,212 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,491 IT Pros & Developers. It's quick & easy.

Multiply float by -1: fast or slow?

P: n/a

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

Jan 25 '07 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Chris Stankevitz wrote:
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;
}
Jan 25 '07 #2

P: n/a
Chris Stankevitz wrote:
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.

--
Ian Collins.
Jan 25 '07 #3

P: n/a
"Chris Stankevitz" <ch*************@yahoo.comwrote in message
news:11*********************@k78g2000cwa.googlegro ups.com
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.

--
John Carson
Jan 25 '07 #4

P: n/a
Roman S. wrote:
Chris Stankevitz wrote:
>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;
}
inline void Invert(float& f)
// ^^^^

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jan 25 '07 #5

P: n/a
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
Jan 25 '07 #6

P: n/a
"John Carson" <jc****************@netspace.net.auwrote in message
news:45***********************@uv-55king-reader-01.melbourne.pipenetworks.com.au
>
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
return 0;
}

--
John Carson
Jan 25 '07 #7

P: n/a


On Jan 24, 11:07 pm, Michael DOUBEZ <michael.dou...@free.frwrote:
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.

Jan 25 '07 #8

P: n/a
Michael DOUBEZ wrote:
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.

--
Ian Collins.
Jan 25 '07 #9

P: n/a
ro***********@yahoo.com a écrit :
>
On Jan 24, 11:07 pm, Michael DOUBEZ <michael.dou...@free.frwrote:
>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
Jan 25 '07 #10

P: n/a
Michael DOUBEZ a écrit :
ro***********@yahoo.com a écrit :
>>
On Jan 24, 11:07 pm, Michael DOUBEZ <michael.dou...@free.frwrote:
>>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
Jan 25 '07 #11

This discussion thread is closed

Replies have been disabled for this discussion.