# "Shifting" floating point numbers

Discussion in 'C Programming' started by woessner@gmail.com, Mar 21, 2006.

1. ### Guest

Does anyone know of a fast way to multiply floating point numbers by
powers of two? Conceptually, all you need to do is add to the
mantissa. But can I write C code (or x86 assembly) to accomplish this
without a full-blown multiply?

For example, I'd like to be able to do the following very quickly:

double x;
double y;

x = 42.13;
y = (1 << 9) * x;

Bill

, Mar 21, 2006

2. ### santoshGuest

wrote:
> Does anyone know of a fast way to multiply floating point numbers by
> powers of two? Conceptually, all you need to do is add to the
> mantissa. But can I write C code (or x86 assembly) to accomplish this
> without a full-blown multiply?
>
> For example, I'd like to be able to do the following very quickly:
>
> double x;
> double y;
>
> x = 42.13;
> y = (1 << 9) * x;

If you know the floating point representation of your implementation
and underlying hardware, you can copy the float value to an unsiged
long variable, shift the appropriate bits and copy the value back to
the float variable. All this implies that you'll have to know details

These days, FPU's are quite fast, so a direct multiply on the float
should be efficient enough unless you're code is time critical.

santosh, Mar 21, 2006

3. ### SkarmanderGuest

wrote:
> Does anyone know of a fast way to multiply floating point numbers by
> powers of two? Conceptually, all you need to do is add to the
> mantissa. But can I write C code (or x86 assembly) to accomplish this
> without a full-blown multiply?
>

My advice: don't bother. The chance that you'll beat the combination of FPU
and compiler is small, and a trick like this tends to break down when you
least expect it.

For example, if you want to do this the right way, you have to deal with the
infinities, denormalized numbers, NaNs and last but not least, zero. But of
course you can't, since that would make your code far too slow.

> For example, I'd like to be able to do the following very quickly:
>
> double x;
> double y;
>
> x = 42.13;
> y = (1 << 9) * x;
>

Verify that you really need to do this faster than you're doing it now
first. Then see if there's some way to avoid doing the multiplication
altogether (at least in tight loops) by changing the way you handle your
data. Finally, if all these options are exhausted, you'd best go with x86
assembler and read up on the format of double precision numbers. Try
comp.lang.asm.x86. When you're at this point, C (even nonportable C) is

S.

Skarmander, Mar 21, 2006
4. ### Eric SosmanGuest

wrote On 03/21/06 13:45,:
> Does anyone know of a fast way to multiply floating point numbers by
> powers of two? Conceptually, all you need to do is add to the
> mantissa.

> But can I write C code (or x86 assembly) to accomplish this
> without a full-blown multiply?
>
> For example, I'd like to be able to do the following very quickly:
>
> double x;
> double y;
>
> x = 42.13;
> y = (1 << 9) * x;

#include <math.h>
...
y = ldexp(x, 9);

No guarantees about relative speed, though: You'll
need to measure on the platform(s) of interest.

--

Eric Sosman, Mar 21, 2006
5. ### Pierre MauretteGuest

, le 21/03/2006 a écrit :
> Does anyone know of a fast way to multiply floating point numbers by
> powers of two? Conceptually, all you need to do is add to the
> mantissa.

Mantissa ? Exponent, no ?

> But can I write C code (or x86 assembly) to accomplish this
> without a full-blown multiply?

[I consider Intel FPU, double / real8]
A problem is in the position of the exponent in the double. From bit 52
to bit 62. You can't use this way in order to have faster code, just
for fun.

In assembly, you have two ways:

- FIMUL, multiply a FP data by an integer.

- FSCALE, that do just what you want, multiply very quickly by a power
of 2 ;-) You need just to have the power (9, not 2^9 !) in ST(1) and do
FSCALE.

--
Pierre Maurette

Pierre Maurette, Mar 21, 2006
6. ### Keith ThompsonGuest

Pierre Maurette <> writes:
> , le 21/03/2006 a écrit :
>> Does anyone know of a fast way to multiply floating point numbers by
>> powers of two? Conceptually, all you need to do is add to the
>> mantissa.

> Mantissa ? Exponent, no ?
>
>> But can I write C code (or x86 assembly) to accomplish this
>> without a full-blown multiply?

> [I consider Intel FPU, double / real8]
> A problem is in the position of the exponent in the double. From bit
> 52 to bit 62. You can't use this way in order to have faster code,
> just for fun.
>
> In assembly, you have two ways:
>
> - FIMUL, multiply a FP data by an integer.
>
> - FSCALE, that do just what you want, multiply very quickly by a power
> of 2 ;-) You need just to have the power (9, not 2^9 !) in ST(1) and
> do FSCALE.

have no way of knowing whether your description is accurate. I make
mistakes every now and then; when I make them in a forum full of
experts on what I'm talking about, they'll be corrected.

And, of course, it's off-topic. There are newsgroups where such
things are topical; comp.lang.asm.x86 is probably one of them.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Keith Thompson, Mar 21, 2006
7. ### Pierre MauretteGuest

Keith Thompson, le 21/03/2006 a écrit :
[...]
> And, of course, it's off-topic. There are newsgroups where such
> things are topical; comp.lang.asm.x86 is probably one of them.

I agree your remark. But its was an answer to an off-topic question.

--
Pierre Maurette

Pierre Maurette, Mar 21, 2006
8. ### Keith ThompsonGuest

writes:
> Does anyone know of a fast way to multiply floating point numbers by
> powers of two? Conceptually, all you need to do is add to the
> mantissa. But can I write C code (or x86 assembly) to accomplish this
> without a full-blown multiply?
>
> For example, I'd like to be able to do the following very quickly:
>
> double x;
> double y;
>
> x = 42.13;
> y = (1 << 9) * x;

Compile the code with whatever optimization options are appropriate,
and look at the assembly language. If your compiler generates code
that uses something other than (and presumably faster than) a
floating-point multiply, then you're all set; there's no need to do
source-level optimization if the compiler will do it for you. If the
compiler emits an ordinary floating-point multiply instruction, then
it may mean that that's the best way to do the multiplication.

It's also possible that you can optimize this better than your
compiler can, but that's not the way to bet (unless you've actually
measured it).

And always remember the Rules of Optimization:

Rule 1: Don't do it.
Rule 2 (for experts only): Don't do it yet.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Keith Thompson, Mar 21, 2006
9. ### Jordan AbelGuest

On 2006-03-21, Pierre Maurette <> wrote:
> - FSCALE, that do just what you want, multiply very quickly by a power
> of 2 ;-) You need just to have the power (9, not 2^9 !) in ST(1) and do
> FSCALE.

This instruction may be available to C as the "scalbn" function (and if
not, scalbn will be a software implementation that does the same thing),
and I suspect this is exactly what he wants.

C99 only, of course.

Here's my system's implementation of it for i387

RCSID("\$FreeBSD: src/lib/msun/i387/s_scalbn.S,v 1.7 1999/08/28 00:06:13 peter Exp \$")

ENTRY(scalbn)
fildl 12(%esp)
fldl 4(%esp)
fscale
fstp %st(1)
ret

Jordan Abel, Mar 21, 2006
10. ### Jordan AbelGuest

On 2006-03-21, Pierre Maurette <> wrote:
> Keith Thompson, le 21/03/2006 a écrit :
> [...]
>> And, of course, it's off-topic. There are newsgroups where such
>> things are topical; comp.lang.asm.x86 is probably one of them.

> I agree your remark. But its was an answer to an off-topic question.

Not really. scalbn() [and its friends] are the on-topic answer.

Jordan Abel, Mar 21, 2006
11. ### Jordan AbelGuest

On 2006-03-21, <> wrote:
> Does anyone know of a fast way to multiply floating point numbers by
> powers of two? Conceptually, all you need to do is add to the
> mantissa. But can I write C code (or x86 assembly) to accomplish this
> without a full-blown multiply?
>
> For example, I'd like to be able to do the following very quickly:
>
> double x;
> double y;
>
> x = 42.13;
> y = (1 << 9) * x;
>
> Bill

y = scalbn(x,9);

Everyone else thinks you're off-topic because no-one else knows about
this function, apparently.

Jordan Abel, Mar 21, 2006
12. ### Eric SosmanGuest

Jordan Abel wrote On 03/21/06 15:51,:
> On 2006-03-21, <> wrote:
>
>>Does anyone know of a fast way to multiply floating point numbers by
>>powers of two? Conceptually, all you need to do is add to the
>>mantissa. But can I write C code (or x86 assembly) to accomplish this
>>without a full-blown multiply?
>>
>>For example, I'd like to be able to do the following very quickly:
>>
>>double x;
>>double y;
>>
>>x = 42.13;
>>y = (1 << 9) * x;
>>
>>Bill

>
>
> y = scalbn(x,9);

ITYM:

y = scalbn(x, 9);
#else
y = ???;
#endif

I've already posted a candidate for "???", one that
eliminates the dependency on C99 and perhaps even
obviates the preprocessor gunk ...

--

Eric Sosman, Mar 21, 2006
13. ### Keith ThompsonGuest

Pierre Maurette <> writes:
> Keith Thompson, le 21/03/2006 a écrit :
> [...]
>> And, of course, it's off-topic. There are newsgroups where such
>> things are topical; comp.lang.asm.x86 is probably one of them.

> I agree your remark. But its was an answer to an off-topic question.

The question was partly off-topic. But the solution is simple: don't
appropriate forum. (I sometimes offer a small system-specific hint
while doing so, but it's usually no more than a pointer to the

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Keith Thompson, Mar 21, 2006
14. ### P.J. PlaugerGuest

"Eric Sosman" <> wrote in message
news:dvpk84\$9cg\$...

> wrote On 03/21/06 13:45,:
>> Does anyone know of a fast way to multiply floating point numbers by
>> powers of two? Conceptually, all you need to do is add to the
>> mantissa.

>
>
>> But can I write C code (or x86 assembly) to accomplish this
>> without a full-blown multiply?
>>
>> For example, I'd like to be able to do the following very quickly:
>>
>> double x;
>> double y;
>>
>> x = 42.13;
>> y = (1 << 9) * x;

>
> #include <math.h>
> ...
> y = ldexp(x, 9);
>
> No guarantees about relative speed, though: You'll
> need to measure on the platform(s) of interest.

Before it gets lost in all the noise, this is the right answer.
And it's been in the C Standard since C89.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

P.J. Plauger, Mar 21, 2006
15. ### Jordan AbelGuest

On 2006-03-21, P.J. Plauger <> wrote:
> "Eric Sosman" <> wrote in message
> news:dvpk84\$9cg\$...
>
>> wrote On 03/21/06 13:45,:
>>> Does anyone know of a fast way to multiply floating point numbers by
>>> powers of two? Conceptually, all you need to do is add to the
>>> mantissa.

>>
>>
>>> But can I write C code (or x86 assembly) to accomplish this
>>> without a full-blown multiply?
>>>
>>> For example, I'd like to be able to do the following very quickly:
>>>
>>> double x;
>>> double y;
>>>
>>> x = 42.13;
>>> y = (1 << 9) * x;

>>
>> #include <math.h>
>> ...
>> y = ldexp(x, 9);
>>
>> No guarantees about relative speed, though: You'll
>> need to measure on the platform(s) of interest.

>
> Before it gets lost in all the noise, this is the right answer.
> And it's been in the C Standard since C89.

I thought that ldexp set the exponent to the number given, i.e. the new
exponent would be 9 regardless of the current exponent (i.e. 42.13's
exponent is already six) - why is it called "ldexp" (i thought it stood
for "load exponent", which only makes sense with my version, not the
actual function)

Jordan Abel, Mar 21, 2006
16. ### Keith ThompsonGuest

Jordan Abel <> writes:
> On 2006-03-21, P.J. Plauger <> wrote:
>> "Eric Sosman" <> wrote in message
>> news:dvpk84\$9cg\$...

[...]
>>> #include <math.h>
>>> ...
>>> y = ldexp(x, 9);
>>>
>>> No guarantees about relative speed, though: You'll
>>> need to measure on the platform(s) of interest.

>>
>> Before it gets lost in all the noise, this is the right answer.
>> And it's been in the C Standard since C89.

>
> I thought that ldexp set the exponent to the number given, i.e. the new
> exponent would be 9 regardless of the current exponent (i.e. 42.13's
> exponent is already six) - why is it called "ldexp" (i thought it stood
> for "load exponent", which only makes sense with my version, not the
> actual function)

The standard's description is:

The ldexp functions multiply a floating-point number by an
integral power of 2. A range error may occur.

Returns
The ldexp functions return x * 2**exp.

(equation translated to ASCII).

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Keith Thompson, Mar 22, 2006
17. ### Dik T. WinterGuest

In article <> writes:
> Does anyone know of a fast way to multiply floating point numbers by
> powers of two? Conceptually, all you need to do is add to the
> mantissa. But can I write C code (or x86 assembly) to accomplish this
> without a full-blown multiply?
>
> For example, I'd like to be able to do the following very quickly:
>
> double x;
> double y;
>
> x = 42.13;
> y = (1 << 9) * x;

With IEEE floating point shifting the mantissa will not accomplish what
you want. For instance, shifting the mantissa of 1.0 by any number of
bits will leave the value 1.0 because the mantissa (as a stored value)
is 0; there is an hidden (not stored) bit. When you want to multiply
by 2 you need to increment the exponent by 1.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

Dik T. Winter, Mar 22, 2006
18. ### Robin HaighGuest

<> wrote in message
news:...
> Does anyone know of a fast way to multiply floating point numbers by
> powers of two? Conceptually, all you need to do is add to the
> mantissa. But can I write C code (or x86 assembly) to accomplish this
> without a full-blown multiply?
>
> For example, I'd like to be able to do the following very quickly:
>
> double x;
> double y;
>
> x = 42.13;
> y = (1 << 9) * x;

Not disagreeing with the wise words of others, but just for interest's sake
this non-portable one-liner seems to work if you stay away from the edges

#include <stdio.h>
int main (void) {

double x = 42.13;
double y;
int power = 9;

/* assuming 4-byte longs */

y = x;
((unsigned long *)&y)[1] += power << 20; /* IEEE little-endian */

/* (change [1] to [0] for big-endian) */

printf("%f\n", y);
return 0;
}

(For language lawyers, there are some questions about whether this code is
undefined behaviour, whether it still is in the equivalent using a union, or
if y is declared volatile (answers may be different in C89 and C99))

Robin Haigh, Mar 22, 2006
19. ### Jordan AbelGuest

On 2006-03-22, Robin Haigh <> wrote:
>
> <> wrote in message
> news:...
>> Does anyone know of a fast way to multiply floating point numbers by
>> powers of two? Conceptually, all you need to do is add to the
>> mantissa. But can I write C code (or x86 assembly) to accomplish this
>> without a full-blown multiply?
>>
>> For example, I'd like to be able to do the following very quickly:
>>
>> double x;
>> double y;
>>
>> x = 42.13;
>> y = (1 << 9) * x;

>
>
> Not disagreeing with the wise words of others, but just for interest's sake
> this non-portable one-liner seems to work if you stay away from the edges
>
>
> #include <stdio.h>
> int main (void) {
>
> double x = 42.13;
> double y;
> int power = 9;
>
> /* assuming 4-byte longs */
>
> y = x;
> ((unsigned long *)&y)[1] += power << 20; /* IEEE little-endian */
>
> /* (change [1] to [0] for big-endian) */
>
> printf("%f\n", y);
> return 0;
>}
>
>
> (For language lawyers, there are some questions about whether this code is
> undefined behaviour,

yes.

> whether it still is in the equivalent using a union,

yes.

> or if y is declared volatile

and yes.

>(answers may be different in C89 and
> C99))

no.

Jordan Abel, Mar 22, 2006