Archived

This topic is now archived and is closed to further replies.

How to do fast floating-point multiplication by 1, 0, and -1?

This topic is 5535 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I have two single-percision floating-point variables, which I need to multiply as quickly as possible (this is done many times in a loop). One of the variables can potentially contain any real number, but the other is known to contain either 1, 0, or -1. I don't know in advance which of the three is contained in that variable. Given this situation, how can I optimize the multiplication? Is it perhaps possible to encode 1, 0, and -1 as some other special values and do the multiplication with bitwise operations (that would be the optimal solution, I think)? Is there some other way? EDIT: Is this supposed to go into the General Programming forum instead?.... Michael K., Co-designer and Graphics Programmer of "The Keepers"
We come in peace... surrender or die! [edited by - technobot on July 27, 2003 3:19:49 PM]

Share on other sites
if you just had -1 and 1 you could encode -1 as 0x80000000 and 1 as 0, and than you could do an integer xor.

c = a ^ b;

This will work, but I don''t think it will be faster, since fmul costs 1 clock tick on modern cpu''s, and if you want to do other floating point opts on them after this, they can be kept in the floating point registers if you use fmul. I think just using fmul, or an sse equivalent will be the best way.

My Site

Share on other sites
quasar, I''m not as skilled as you, but I know the IEEE format. How would xoring two sign bits which equal 0, give c a negative sign? Say you''re multiplying by -1 (0x80000000), alright?...so xoring that int with a positive or zero float would be bluntly:
0x800000000
XOR
0xMantissa^Exponent
0 XOR 0 is 0, when that sign bit should be 1, I think. Because + * - = negative. Something''s screwy.

Share on other sites
Um...
if (x == 0.0f)    result = 0.0f;else if (x == -1.0f)    result = -y;else    result = y;

Would that be fast enough?

The following statement is true. The previous statement is false.
Shameless promotion:
FreePop: The GPL Populous II clone.

Share on other sites
You should probably just use fmul, any tricks you pull otherwise will just eat up an integer register and probably take more cycles. You might be able to get a speedup by ordering the arguments well, but that might already be done internally.

Share on other sites
that and... NEVER TEST FLOATS FOR EQUALITY. :D

Share on other sites
Using conditions is not an option, as the multiplications are part of a more complex calculation, and there are several such multiplications per calculation. I.e. something like:

result1 = (bla1 * bla2) + (bla3 * bla4) + (bla5 * bla6);
result2 = (bla7 * bla8) + (bla9 * bla10) + (bla11 * bla12);
result3 = interpolate(result1, result2, factor);

Basically, this is part of the improved version of Ken Perlin's perlin noise, as described in this paper. One of the improvement is to use specially selected gradient vectors whose components can only be 1, 0, or -1.

Part of the algorithm is a series of dot products between those vectors and certain other vectors. In the performance section of the paper, Ken Perlin writes: "... the new algorithm runs approximately 10 percent faster than the original. The cost of the extra multiplies required to compute the three corrected interpolants is apparently outweighted by the savings from the multiplies no longer required to compute the eigth inner products . ".

What bugs me is: how are the dot (inner) products eliminated??

EDIT: Only 1 cycle for an fmul? Hmm... that's interesting...

Michael K.,
Co-designer and Graphics Programmer of "The Keepers"

We come in peace... surrender or die!

[edited by - technobot on July 28, 2003 4:09:15 PM]

Share on other sites
A couple questions:

1. Will the variables that are -1, 0, or 1 be set to the constants -1/0/1, or will mathematical calculations produce these numbers?

2. In the equations you just showed us, which are the variables that are 0/1/-1?

How appropriate. You fight like a cow.

Share on other sites
what he (perlin) talks about is actually hw implementation. THERE mults are expensive, THERE replacing it by some simple bitwise logic to "multiply" -1,0,1 together is useful. it replaces a full fpu multiplier for 32bit floats (or similar) by some and|or logic for 2bits.. or even a lookuptable for the actual product is enough..

dotproduct[(a<<4)|(b<<2)|c] where a,b,c = {0,1,2} with mapping 0 := -1.f, 1 := 0.f, 2 = 1.f

every hw implementation of what ever just LOVES to not use any floatingpoint math where needed.

just expensive processors are directly made to be fast on fpu''s.. and slow on switching between fpu and integer unit (passing values there around..).

the only place where i''d see the possible optimisation to gain performance _could_ be in SSE, where you can just and,or,xor a bitmask, and anding/xoring a bitmask is enough to multiply a float by -1,0,1 i think..

"take a look around" - limp bizkit

1. 1
2. 2
3. 3
Rutin
16
4. 4
JoeJ
13
5. 5

• 10
• 9
• 14
• 10
• 25
• Forum Statistics

• Total Topics
632646
• Total Posts
3007637
• Who's Online (See full list)

There are no registered users currently online

×