[MLton-user] IEEEReal rounding not working
Matthew Fluet
fluet at tti-c.org
Thu Jul 26 13:22:58 PDT 2007
> I'm not sure what the correct behavior should be.
Well, given the dynamic semantics of SML and the specification of the
Basis Library, I don't believe that treating the Real<N>.* operations as
pure is correct.
> I'd hate to lose optimizations, as I switched from O'Caml because the
> floating point computations were so much faster in my application.
My guess is that it wouldn't be that bad. I suspect that floating-point
operations susceptible to CSE are rare; certainly, much rarer than
integer, array/vector, and tuple operations susceptible to CSE.
> But it would be nice to have a document somewhere specifying exactly how
> rounding modes are treated in expressions. For instance, I can imagine
> an optimization that executes Real.fromString at compile time for a
> string constant, which would kill the fix.
Well, although MLton currently treats Real<N>.* operations as pure, it
doesn't do any constant folding of Real<N>.* operations, precisely because
such computations should be done under the dynamic rounding mode, not the
static (compile-time) rounding mode.
As a curiosity, I wonder how floating-point constants should be evaluated.
Currently, MLton treats fp constants as pure expressions; hence, they can
be globalized and common constants can be combined. That is, a program
like:
val () = IEEEReal.setRoundingMode IEEEReal.TO_POSINF
val r1 = 0.1
val () = IEEEReal.setRoundingMode IEEEReal.TO_NEGINF
val r2 = 0.1
will be evaluated by the native codegen like:
val r = 0.1
val () = IEEEReal.setRoundingMode IEEEReal.TO_POSINF
val r1 = r
val () = IEEEReal.setRoundingMode IEEEReal.TO_NEGINF
val r2 = r
Furthermore, the "global" r will be evaluated by C code of the form:
double globalReal[10];
static void real_Init() {
...
double globalReal[7] = 0.1;
...
}
which in turn will be compiled by gcc into two 32-bit moves of constants;
that is, gcc will evaluate the floating point constant to its IEEE
representation, presumably using TO_NEAREST semantics. In any case, you
won't get r1 and r2 being two different floating point values.
The C codegen will actual constant-propagate the floating point
constants, but in that case, gcc will see something like:
{
double R1, R2;
...
R1 = 0.1;
...
R2 = 0.1;
...
}
and both of those will probably be compiled as floating point loads of
static data, where the static data is again the IEEE representation
computed by gcc at compile time. Again, I think you'll get r1 and r2
being the same floating point value.
Welcome to the wonderful world of IEEE floating point...
Of course, the above is ignoring the fact that after MLton globalizes the
floating point constants, there is no need to keep r1 and r2 as distinct
variables, and copy propagation will actually make every use of r1 and r2
be a use of r; so you *really* get the same floating point value.
I know that the different rounding modes are useful for performing
interval arithmetic, and, Sean, I see from your CMU homepage that you have
some background in interval arithmetic, so perhaps you know whether this
treatment of floating point constants plays havoc with that usage.
More information about the MLton-user
mailing list