"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;

    Thanks in advance,
    Bill
    , Mar 21, 2006
    #1
    1. Advertising

  2. santosh Guest

    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
    about your implementation and thus risk losing some portability.

    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
    #2
    1. Advertising

  3. Skarmander Guest

    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
    unlikely to help you enough.

    S.
    Skarmander, Mar 21, 2006
    #3
  4. Eric Sosman Guest

    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.


    ITYM "add the exponent."

    > 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
    #4
  5. , 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
    #5
  6. 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.


    Please don't post system-specific answers like this here. Most of us
    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
    #6
  7. 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
    #7
  8. 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
    #8
  9. Jordan Abel Guest

    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
    #9
  10. Jordan Abel Guest

    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
    #10
  11. Jordan Abel Guest

    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;
    >
    > Thanks in advance,
    > 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
    #11
  12. Eric Sosman Guest

    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;
    >>
    >>Thanks in advance,
    >>Bill

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


    ITYM:

    #if FLT_RADIX == 2
    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
    #12
  13. 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
    try to answer off-topic questions; instead, redirect the poster to an
    appropriate forum. (I sometimes offer a small system-specific hint
    while doing so, but it's usually no more than a pointer to the
    answer.)

    --
    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
    #13
  14. P.J. Plauger Guest

    "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.

    >
    > ITYM "add the exponent."
    >
    >> 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
    #14
  15. Jordan Abel Guest

    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.

    >>
    >> ITYM "add the exponent."
    >>
    >>> 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
    #15
  16. 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
    #16
  17. 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
    #17
  18. Robin Haigh Guest

    <> 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
    #18
  19. Jordan Abel Guest

    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
    #19
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. H aka N
    Replies:
    15
    Views:
    15,612
    Ben Jones
    Mar 2, 2006
  2. Motaz Saad
    Replies:
    7
    Views:
    6,458
  3. Replies:
    4
    Views:
    1,270
    Default User
    Feb 22, 2006
  4. Saraswati lakki
    Replies:
    0
    Views:
    1,287
    Saraswati lakki
    Jan 6, 2012
  5. teeshift
    Replies:
    2
    Views:
    240
    Chris Pearl
    Dec 1, 2006
Loading...

Share This Page