
On Apr 07, 2009 at 02:10AM, Steven D'Aprano <steve@pearwood.info> wrote:
On the other hand, I'm with Guido when he wrote "it is certainly not right to choose speed over correctness". This is especially a problem for floating point optimizations, and I urge Cesare to be conservative in any f.p. optimizations he introduces, including constant folding.
The principle that I followed on doing constant folding was: "do what Python will do without constant folding enabled". So if Python will generate LOAD_CONST 1 LOAD_CONST 2 BINARY_ADD the constant folding code will simply replace them with a single LOAD_CONST 3 When working with such kind of optimizations, the temptation is to apply them at any situation possible. For example, in other languages this a = b * 2 * 3 will be replaced by a = b * 6 In Python I can't do that, because b can be an object which overloaded the * operator, so it *must* be called two times, one for 2 and one for 3. That's the way I choose to implement constant folding. The only difference at this time is regards invalid operations, which will raise exceptions at compile time, not at running time. So if you write: a = 1 / 0 an exception will be raised at compile time. I decided to let the exception be raised immediately, because I think that it's better to detect an error at compile time than at execution time. However, this can leed to incompatibilities with existing code, so in the final implementation I will add a flag to struct compiling (in ast.c) so that this behaviour can be controlled programmatically (enabling or not the exception raising). I already introduced a flag in struct compiling to control the constant folding, that can be completely disabled, if desired.
So... +1 on the general principle of constant folding, -0.5 on any such optimizations which change the semantics of a f.p. operation. The only reason it's -0.5 rather than -1 is that (presumably) anyone who cares about floating point correctness already knows to never trust the compiler.
As Raymond stated, there's no loss in precision working with constant folding code on float datas. That's because there will be a rounding and a store of computed values each time that a result is calculated. Other languages will use FPU registers to hold results as long as possibile, keeping full 80 bit precision (16 bit exponent + 64 bit mantissa). That's not the Python case. Cesare