Boost logo

Boost :

From: scleary_at_[hidden]
Date: 1999-12-14 13:29:33


> From: Moore, Paul [mailto:Paul.Moore_at_[hidden]]
> I'm just putting this into practice, and I wanted to check:
>
> Is it *required* for a compiler to implement
>
> (n/g) * x
>
> by dividing n/g first, before multiplying by x? If compilers are allowed
to
> reorder calculations, and do (n*x)/g, then we can't be sure that this
> formulation avoids overflow, and we *need* to introduce explicit
> temporaries. I'm not 100% sure what the (C as well as C++, presumably)
> standard says on this matter.
>
> I'd rather avoid explicit temporaries, as they would obscure
> the code. But do I need them?
>

Explicit temporaries are not necessary. Technically, neither are the
parenthesis, but it might help some brain-damaged compilers, as Bill pointed
out.

Do compilers really reorder calculations? In order to do so, they would
require some fairly good knowledge about the range of possible values of the
variables involved, and the payoff at runtime would be marginal at best. . .
You don't have any restrictions on the values of these variables in your
code, so I don't think the compiler would be _able_ to reorder this
particular statement.

In any case, the ANSI spec (see below) only permits reordering if the
results would be EXACTLY the same as the original, including overflow
side-effects and/or exceptions.

ANSI 1.9p15:
[Note: operators can be regrouped according to the usual mathematical rules
only where the operators really are associative or commutative (9). For
example, in the following fragment

        int a, b;
        /* ... */
        a = a + 32760 + b + 5;

the expression statement behaves exactly the same as

        a = (((a + 32760) + b) + 5);

due to the associativity and precedence of these operators. Thus, the
result of the sum (a + 32760) is next added to b, and that result is then
added to 5 which results in the value assigned to a. On a machine in which
overflows produce an exception and in which the range of values
representable by an int is [-32768, +32767], the implementation cannot
rewrite this expression as

        a = ((a + b) + 32765);

since if the values for a and b were, respectively, -32754 and -15, the sum
a + b would produce an exception while the original expression would not;
nor can the expression be rewritten either as

        a = ((a + 32765) + b);

or

        a = (a + (b + 32765));

since the values for a and b might have been, respectively, 4 and -8 or -17
and 12. However on a machine in which overflows do not produce an exception
and in which the results of overflows are reversible, the above expression
statement can be rewritten by the implementation in any of the above ways
because the same result will occur. ]

(9) Overloaded operators are never assumed to be associative or commutative.

        -Steve


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk