Subject: rounding direction

From: "Timothy Ritchey" <[email-masked]>
Date: Thu, 27 Feb 1997 12:45:32 -0000

I may expose my ignorance about directed rounding, but isn't that what the
Math class provides in Java?:

double ceil(double a)
Returns the smallest (closest to negative infinity) double value that is
not less than the argument and is equal to a mathematical integer.

double floor(double a)
Returns the largest (closest to positive infinity) double value that is not
greater than the argument and is equal to a mathematical integer.

(note: this is in response to a mail message; however, I am not sure where
it came from. I assumed from the nature of it that it came from this list.)

---

From: "Russell L. Carter" <[email-masked]>
Date: Thu, 27 Feb 1997 08:58:21 -0700

> greater than the argument and is equal to a mathematical integer.

These are function calls.  Other languages let you set a bit in the
control word of the cpu so that directed rounded computations perform with
no performance degradation.  There is a large difference in performance, and
it is impractical to "postprocess" every floating point result if the number
of flops is large.

Note: this approach is even worse in effect than the 53bit mantissa length
requirement, and it is uniform across architectures.  The mitigating factor
is that number of people who want to do this is small.

Russell

---

From: Arch Robison <[email-masked]>
Date: Thu, 27 Feb 1997 11:51:55 -0600 (CST)

Just to be devil's advocate, here are some reasons to *not* put
C-style control of rounding direction into Java:

    1.  The C-style rounding-control affects global state.
	This raises three related objections:

	1.a This opens up room for an untrusted piece of software to set 
	    the rounding direction to something unexpected by the caller, 
	    at a minimum causing strange bugs.   And at a maximum, it might 
	    introduce a security hole.  I don't see an obvious hole, but 
	    letting untrusted software change the meaning of +, -, *, etc. 
	    seems to be asking for trouble.
		
	1b. Affecting ubiquitous global state is anti-OOP.
	
	1c. The philosophy of Java seems to be that code should be
	    understandable by looking at it locally.  Changing the 
	    meaning of +, -, *, etc. undermines this.

    2.  Simplicity.  The great majority of software does *not* need
	rounding control.  I realize this is a terrible thing to say
	to people whose software needs rounding control.  But Java
	also throws out a lot of other features considered "essential"
	by some groups of programmers.  E.g., "const", "templates",
	"virtual base classes" are not in Java.
      
	If every little feature is added, you soon end up with a language
	that no one can understand completely.  (E.g. I cannot claim
	to fully understand C++, and I'm the lead developer of a
	state-of-the-art C++ product!)

Okay, to be fair, the numerical analyst in me likes rounding control.
But I think that it should be done in an OO way in Java.  Here's a suggestion.
Define a class (e.g. "FPU") that represents a floating-point unit and its 
associated rounding direction.  Give it methods add, subtract, multiply, 
divide etc. that perform the necessary operations.  This makes code
using it a bit verbose, but explicit.  E.g., w = x*y+z would look like this:
[Please pardon the C++ accent if there is one.]

	FPU f( FPU.towards_zero );
	w = f.add( f.multiply( x,y ), z );

The obvious objection is that I can't simply write w=x*y+z.
But allowing the latter would be against the Java philosophy of
make code understandable locally.  Using the "FPU" class makes it
clear that special arithmetic is being done, does not depend upon
global state, and only those who use the library have to pay the
price of the complexity that it adds.

Furthermore, my impression from a little use of rounding control is that 
the desired direction is often different for each operation anyway
(covariance vs. contravariance) so the added verbosity is not as bad as 
it seems.  E.g., by not using global state, one can control each operation 
in an obvious fashion:

	FPU up( FPU.towards_infinity );
	FPU down( FPU.towards_negative_infinity );
	w = up.add( down.multiply( x,y ), z );

The other obvious objection is that this would be slower.
But if you give it a little thought, it is not hard to see how
a native-code-generating optimizer could remove the overhead
if it understood the semantics of the FPU class.

Arch D. Robison			    Kuck & Associates Inc.
[email-masked] 		    1906 Fox Drive
217-356-2288 			    Champaign IL 61820
Lead Developer for KAI C++	    http://www.kai.com/C_plus_plus/index.html