Re: Floating point in kernel

From: Richard B. Johnson (root@chaos.analogic.com)
Date: Thu May 04 2000 - 15:19:57 EST


On Thu, 4 May 2000, Abramo Bagnara wrote:

> "Richard B. Johnson" wrote:
> >
> > On Wed, 3 May 2000, Jeff Garzik wrote:
> >
> > > "B. James Phillippe" wrote:
> > > >
> > > > Hello,
> > > >
> > > > I know this is not legal. However, I'm reviewing some kernel module code
> > > > which basically does:
> > > >
> > > > unsigned long foo = some_other_ulong * 1.234;
> > >
> > > oof :) Reminds me of some fbdev code I saw a while back IIRC
> > >
> > > When you really want fractional numbers not literally floating point,
> > > you can always multiple both numbers to make them decimal, perform the
> > > math op, and then divide back down again.
> > >
> > > Jeff
> > >
> >
> > Correct. In the cited case, the code could read:
> >
> > foo = some_other_ulong * 1234 / 1000;
> >
> > The complier sometimes optimizes the wrong stuff so 1234/1000 might
> > get optimized to 1 which is not what you want. Therefore, you can
> > force the issue by doing:
> >
> > foo = some_other_ulong * 1234;
> > ^__ sequence point
> > foo /= 1000;
> >
>
> As far as I know this is not needed at all.
> * and / have the same precedence and associativity is specified from
> left to right so this is interpreted as:
>
> foo = (some_other_ulong * 1234) / 1000
>
> It's not guaranted that some_other_ulong * 1234 is evaluated before 1000
> but we are sure that multiplication is done before division.
>
> If I'm wrong I'd like to know ASAP as I've written bogus C code for 15
> years now ;-))
>

I don't think the C standard specifies the order of evaluation of
constants. If you use the parentheses as you have shown, you
force the evaluation of whatever is inside them first. This makes sure
the code does the right thing.

The problem comes up often when constants are evaluated by the code-
generator.

main()
{
    int i = 1;

    i = i * 1234 / 1000;
    printf("%d\n", i);
}

This generates:

        .file "aaa.c"
        .version "01.01"
gcc2_compiled.:
.section .rodata
.LC0:
        .string "%d\n"
.text
        .align 4
.globl main
        .type main,@function
main:
        pushl %ebp
        movl %esp,%ebp
        pushl $1 ; <--------------- Here
        pushl $.LC0
        call printf
        leave
        ret
.Lfe1:
        .size main,.Lfe1-main
        .ident "GCC: (GNU) 2.7.2.3"

gcc just pushed the constant 1 on the stack and printed it.
Now, if you turn off optimization, you get some code-generation.

Cheers,
Dick Johnson

Penguin : Linux version 2.3.41 on an i686 machine (800.63 BogoMips).

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun May 07 2000 - 21:00:15 EST