[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