(j3.2006) Interval arithmetic

Van Snyder Van.Snyder
Fri Mar 13 21:30:55 EDT 2009

On Thu, 2009-03-12 at 17:36 -0700, Malcolm Cohen wrote:
> Van Snyder wrote:
> > As a consequence of my involvement with P1788, I have concluded that it
> > is impossible in general to provide reliable interval arithmetic with
> > other than an intrinsic type.
> >   
> You might have concluded that, but that doesn't mean that it's true.  
> And you're conflating "intrinsic type" with "type the compiler knows 
> about".  A Fortran 2003 compiler of necessity knows about types other 
> than intrinsic type, viz C_PTR and C_FUNPTR.

Of course Malcolm knows I intended to conflate these things instead of
engaging in the hair splitting necessary in the standard.

> > The killer is register spill.
> This is an implementation detail.  With all due respects, you are not an 
> implementor and even implementors get these things wrong ... especially 
> frequently when they are using words like "impossible".
> >   When a compiler has a value in a register
> > that is wider than the memory representation of that variable,
> Why should that happen?  Most hardware does not require that.

The only FP registers in Intel chips are the old x87 FP stack with
80-bit registers, and the XMM and MMX registers which contain one (MMX)
or two (XXM) 64-bit floating-point values.  Intel provides instructions
to round 64-bit floating-point values to 32 bits with the result in an
MMX register, but the answer to interp F95/000104 says the processor can
keep intermediate results in whatever representation it pleases, for as
long as it pleases.  The argument Bill advanced in support of that
answer is that performance would be crippled if a REAL intrinsic with a
double precision argument and default real result actually forced the
processor to emit a CVTPD2PS or CVTSD2SS instruction.

> >  and needs
> > the register for other purposes, it generates spill code.  Storing from
> > registers to memory rounds (or, worse, truncates).
> That is just *SO* not true.  It's a compiler decision how to spill.  
> It's perfectly easy to generate spill code that preserves values.  The 
> only widespread decision otherwise in recent times was (as Bill said) 
> the x87 where preserving the value costs performance (well, memory anyway).

Preserving the value is irrelevant to this discussion.

The answer to interp f95/000104 says that a processor is permitted to
compute an intermediate result in higher precision than implied by the
kind specified by 7.1.9, and to keep it in that representation for as
long as it likes.  If it needs to be spilled, maybe it's rounded when
it's spilled, and maybe it's spilled to a temp of the higher precision.
No matter whether the processor spills it to default real, or spills it
to double precision and brings it back as double-precision and drags it
around for a week, there is nothing in the standard that requires a
processor to keep track of the rounding mode in effect when the value
was produced as the result of an operation and use that rounding mode
when it finally needs to convert it to the kind specified by 7.1.9.

I didn't see anything in the standard that says a default real function
result value can't be returned in a double precision register.  Interp
f95/000104 says a processor doesn't have to round the result to default
real before returning it in a double precision register, or when it gets
used after the function returns.  97-007:14.4 says the a priori rounding
mode has to be restored when a procedure returns, so the caller has no
idea how the value was rounded when it was produced, and therefore no
idea how to round the result when converting it to the kind specified by

The question isn't "is a processor able to spill a high-precision value
to from a register to a temp and bring it back accurately," but rather
"when is a value rounded to the kind specified by 7.1.9, and what
rounding mode should be used at that instant."  The answer to interp
f95/000104 says "whenever the processor pleases to do it" and the
standard is entirely silent about what rounding mode to be used at that
instant, unless you interpret 14.4, 14.11.21 and the answer to interp
f95/000104 to mean "the rounding mode in effect when the processor gets
around to converting to the kind specified by 7.1.9."

> So you are saying that John Reid's IEEE modules are totally useless 
> because the compiler can just ignore what the user writes and spill 
> anywhere violating the IEEE standard? That's news to everyone who 
> implemented them.

This isn't a problem for the IEEE modules or IEEE standard.  It's a
problem arising from the answer to interp f95/000104, which says "7.1.9
can be ignored, and therefore what the user writes ***can be ignored***,
concerning intermediate values."

This doesn't mean the IEEE modules are "totally useless, especially
since IEEE_SET_ROUNDING MODE is just one procedure out of 37.  All 14.4
and 14.11.21 say, however, is that results have to be rounded in a
certain direction, not to what precision they have to be rounded, and
the answer to interp f95/000104 says the processor, not 7.1.9, gets to
choose that.  One might be able to force the processor to round to the
desired precision before it loses track of the rounding mode in effect
at the instant a value is computed by passing intermediate results
(including function result values) through volatile variables of the
desired kind, but that seems like an awfully big hammer -- and it's not
mentioned in Clause 14, so maybe it doesn't work anyway.

Since the answer to interp f95/000104 allows a processor to leave a real
result in a representation that might be different from that of the kind
specified by 7.1.9 as long as it likes, when it does get around to
converting it to the kind specified by 7.1.9, it isn't required to use
the rounding mode in effect at the time the value was originally
computed: that only affects the direction of rounding when the result
was computed.  It is free to use the rounding mode in effect when it
spills, or apparently any rounding mode it pleases, since the
relationship between rounding mode and conversion from whatever
precision the processor chooses to use for intermediate results to the
one specified by 7.1.9 is not addressed by the standard.

To make computations with specified rounding reliable, it is necessary
either to require the processor to round to the kind of the result as
specified in 7.1.9 immediately when the value is computed (which
contradicts the answer to interp f95/000104), or round results to the
kind specified by 7.1.9 whenever the rounding mode is changed (including
when a procedure is invoked and returns, which compromises the
usefulness of passing arguments or function results in registers), or do
enough (global) dataflow analysis to track the rounding mode (which is
impossible if IEEE_SET_ROUNDING_MODE is invoked with an argument that's
not an initialization expression).  Subclause 14.4 is so vague that it
doesn't require any of these.  Maybe the DWIM clause takes
precedence....  Let me see, where is that...?

If, however, an object is of a type known to the compiler (sorry to use
the long-winded term, but it appears to be necessary to avoid Malcolm's
hair-splitting), and the compiler knows how to round values of the type
(or components of it if it's a composite type) both when it's produced
and when it's rounded to lower precision, then it's OK (even desirable)
for the processor to keep its values in higher precision as long as it
wants to, since the type tells it how to round correctly without either
having to round preemptively or to do datalfow analysis to track the
rounding mode from the point of the value's calculation to the point of
its rounding to a lower precision.

I wasn't around when 15580 got started, but it's my understanding it was
a compromise reached after block-structured exception handlers (into
which John had put a lot of work) were rejected.  Then it was used as an
excuse not to do interval arithmetic (that nobody actually did any work
on interval arithmetic contributed to it not being done).  Independently
of whether interval arithmetic ever had (or has) a chance to be
incorporated into a Fortran standard, it appears that rounding mode
should have been specified by a variable's attribute, and by punctuation
of operators (e.g. +>).  The latter would be helpful to processors that
specify rounding in each instruction instead of a processor status word.
The former would reduce (perhaps remove) most of the problems ascribed
above to the answer to interp f95/000104.

Van Snyder                    |  What fraction of Americans believe 
Van.Snyder at jpl.nasa.gov       |  Wrestling is real and NASA is fake?
Any alleged opinions are my own and have not been approved or
disapproved by JPL, CalTech, NASA, the President, or anybody else.

More information about the J3 mailing list