%% /u/sy/beebe/src/elefunt/java/README, Thu May 30 05:57:30 2002
%% Edit by Nelson H. F. Beebe <beebe@math.utah.edu>

	    ***********************************************
	    ***********************************************
	    ** Extended Java Version of the Code & Waite **
	    ** ELEFUNT Elementary Function Test Package  **
	    **	     [30-May-2002]--[07-Jun-2002]        **
	    ***********************************************
	    ***********************************************

				  by

			  Nelson H. F. Beebe
		   Center for Scientific Computing
			  University of Utah
		  Department of Mathematics, 110 LCB
			 155 S 1400 E RM 233
		    Salt Lake City, UT 84112-0090
				 USA

	      Email: beebe@math.utah.edu, beebe@acm.org,
	    beebe@computer.org, beebe@ieee.org (Internet)
	       WWW URL: http://www.math.utah.edu/~beebe
		      Telephone: +1 801 581 5254
		FAX: +1 801 585 1640, +1 801 581 4148

=================
Table of contents
=================

	Preface
	Introduction to the Java version
	The pros and cons of Java
	What's new
	How to run the ELEFUNT tests
	References
	Introduction to the C/C++ version


=======
Preface
=======

To get started immediately, with minimal reading, skip down to the
section ``How to run the ELEFUNT tests''.


================================
Introduction to the Java version
================================

This is a manual translation into Java of the companion C/C++ manual
translation of the Fortran ELEFUNT packages.

As with the C/C++ version, the goal is NOT to exercise all of the
bells and whistles of the newer languages, but rather to preserve the
code structure as closely as possible to the original Fortran, and in
particular, to make the output from ALL of the various language
implementations indistinguishable.  Thus, no attempt has been made to
use lowercase letters in strings.  For reference purposes, each Java
test program produces a leading one-line banner identifying the
version and last modification time of the elefunt.java support file.

The syntax of large parts of C is identical to that of Java.  Java has
a radically different I/O model, and completely lacks pointers, but
fortunately, the ELEFUNT code in C makes practically no use of
pointers. Java is object oriented, so class wrappers need to added.

The manual translation of the C/C++ test programs into Java took only
about twenty minutes each, thanks to the power of the emacs text
editor, its Lisp extension language, regular-expression support, and
keyboard macros.  The entire job was completed in just over one day,
which is not a bad investment for the production of just under 7000
lines of Java code!

I began by inserting a boilerplate class wrapper, then inserted the
entire body of the test program, indented four additional spaces, into
the corresponding Java function.

Next, I cleaned up the variable declarations, since I chose to define
several C variables as Java final constants (Java's "final int foo =
123;" is superior to the C/C++ preprocessor style "#define foo 123",
since it gives a type as well as a name, and prevents reassignment).

Then I ran the Emacs Lisp function java-convert-c-formats() to convert
format items in C printf() statements to Java function call templates:
this converted a C statement like

	(void)printf("The answers are %7.3f and %14.5e\n", result1, result2);

into a pending Java statement

	System.out.print("The answers are " + fmt.F(,7,3) + " and " + fmt.E(,14,5) + "\n", result1, result2);

I repeatedly applied a keyboard macro to the source code to change
those incomplete statements to look like this:

	System.out.print("The answers are " + fmt.F(result1,7,3) + " and " + fmt.E(result2,14,5) + "\n");

I then cleaned up the code by manually wrapping several long lines,
and finally, I applied the Emacs Lisp function
java-convert-machar-names() to convert names formerly set by the call
to machar() to package-qualified names, since in Java, machar() is not
required, and its arguments simply become named constants.

It was gratifying that in EVERY case, once a Java compilation was
successful, the programs ran correctly, and gave the expected output.

Once the double-precision Java version was completed, it was a
straightforward task to translate it to the single-precision version,
which is mostly a matter of changing "double" to "float", and adding
suitable typecasts in some expressions, and F suffixes on
floating-point constants.  Once again, all of the test programs ran
successfully and correctly after their first successful compilation.


=========================
The pros and cons of Java
=========================

The Java programming language is defined in terms of an abstract
virtual machine that functions identically on all hardware platforms.
The intent was to create a programming language environment that would
shield software developers from the variations across platforms that
must be attended to in virtually all other programming languages.

In the quest for the goal `write once, run everywhere', Java imposes a
substantial number of restrictions that most other programming
languages do not.  In particular, its evaluation order is rigidly
defined as left-to-right (subject to parentheses and operator
precedence), it does not permit mixing of single- and double-precision
arithmetic without explicit typecasts, and it does not permit
evaluation of intermediate expressions in higher precision.

Java classes must be stored in files of the same name, with extension
.java.  Compilation with javac produces a corresponding .class file,
analogous to the object files (.o on UNIX, .obj on DOS, Windows,
TOPS-20, DEC (Open)VMS, ...) of other languages.  This necessarily
forces an organizational discipline of one class == one file.

Interestingly, unlike other languages, Java programs can have multiple
main programs (though at most one per class), and some implementations
(e.g., GNU gcj) even permit Java programs to start from arbitrary
functions!  This proves very convenient: a main() program provided
with each .java file can run validation tests, e.g.,

	javac fmt.java && java fmt

Java's arithmetic is identical on all platforms: it is based on 8-bit,
16-bit, 32-bit, and 64-bit two's complement signed integers, a 16-bit
unsigned char integer type, and 32-bit and 64-bit floating-point
numbers represented in IEEE 754 format.  Java requires full support of
IEEE 754 subnormals, NaN, Infinity, and signed zero.  However, Java
omits rounding control and access to floating-point flags, and has a
number of other vagaries that prompted W. Kahan and Joseph D. Darcy to
write a scathing criticism entitled ``How Java's Floating-Point Hurts
Everyone Everywhere'' [see the references below.]

Java has attracted enormous attention: my Java bibliographies at

	http://www.math.utah.edu/pub/tex/bib/index-table-j.html#java
	http://www.math.utah.edu/pub/tex/bib/index-table-j.html#java2000

log 1918 books published from 1995 to mid-2002, nearly 300 a year,
vastly more than any other programming language in the history of
computing.  By contrast, my Fortran bibliographies record 1643 books
from 1961 to 2001, or about 40 a year.

Java's superficial resemblance to a subset of C may give an initial
impression of simplicity, but there is enormous complexity concealed
in the huge class libraries, and there are astonishingly many pitfalls
in Java, as documented in Bloch's excellent book (see references
below).

Java's core library reference manual fills three volumes of about 3600
pages (see the books by co-authored by Chan, Lee, and Kramer in the
references below), and there are many thousands of book pages on its
several other libraries (AWT, Java Beans, JNI, Jini, RMI, Swing, ...).

The source distribution in Java 1.4 (the latest version: on Sun
Solaris 2.8, available in the single archive file /usr/j2se/src.zip)
includes 1,180,000 lines of code, and that is incomplete, since some
modules are not distributed in source form, or are implemented in
native code (e.g., much of the java.lang.Math library), and neither
are the compilers, debuggers, linkers, byte-code verifiers, and Java
Virtual Machine interpreters included.

Yet, for all of that code, Java has some appalling omissions that
clearly demonstrate that its developers had virtually no concern for,
or understanding of, numeric applications.  Many of these issues have
been taken up by the Java Grande Forum (visit
http://www.javagrande.org/, and see many papers recorded in the Java
bibliographies noted above), a consortium of institutions and
individuals interested in Java for numerical computation.

For the ELEFUNT test package, three issues in particular stand out:

(1) Despite its huge library corpus, Java has almost no support
    whatever for format control of numeric output: its designers
    foolishly assume that there can be only one text representation of
    a number.  Fortran had such control back in 1956, and so does C,
    C++, and most Lisp dialects.  Even little languages like Pascal,
    awk, perl, python, ruby, ... have it.  Java does not.

(2) Like C before its second ISO Standard, in 1999, Java tries to
    squeak by with minimal floating-point library support: it offers
    remainder, absolute value, conversion to integer (truncation with
    a cast, plus ceil(), floor(), and round()), power, exponential,
    logarithm, random number, trigonometric functions (cos(), sin(),
    tan()), and the inverse trigonometric functions (acos(), asin(),
    atan(), and atan2()).  However, only double-precision versions of
    these functions are provided: there are none for single-precision
    computation.  [See http://java.sun.com/j2se/1.4/docs/api/java/lang/Math.html
    for complete documentation of class java.lang.Math.]

    Absent are log10(), cotan(), and hyperbolic functions (cosh(),
    sinh(), tanh()) included in Cody & Waite's 1980 book, Software
    Manual for the Elementary Functions, and standardly available in
    Fortran, C, and C++.  Also absent are the special functions, such
    erf(), erfc(), gamma(), psi(), and Bessel functions (J(n,x),
    I(n,x), K(n,x), and Y(n,x)), commonly provided in UNIX C
    libraries.

    These deficiencies are significant not only for numerical
    programmers, but they also impede using Java for pedagogical
    purposes: how can students learn about the issue of floating-point
    precision if there is effectively only one available for
    experimentation?

(3) There is no support whatever for quadruple precision, since that
    is not part of the Java Virtual Machine specification.

The most serious of these is (1), and to deal with it, I initially
wrote a modest package, fmt.java, to provide functions I(x,w),
E(x,w,d), and F(x,w,d), analogous to the Fortran Iw, Ew.d, and Fw.d
format items, since these are all that are required for the ELEFUNT
tests.  Although all Java objects and primitive types can be converted
to a string simply by concatenating them with another string (e.g.,
"" + x), there is no control over the representation: floating-point
numbers may or may not have an exponent, and the number of exponent
digits is always minimal.  The number of digits output is one less
than required by Matula's 1968 formula of ceil(1 + N/log2(10)) [see
references below] for N bits of precision, so reconversion of the
decimal representation to binary is not guaranteed to recover the
original value.  However, failures for random arguments in (0,1) are
unlikely: 100,000,000 binary->decimal->binary conversion tests in
bugs/bug001.java found none in the interval (0,1), and the same number
of tests in bugs/bug002.java found none in the intervals
(Float.MIN_VALUE,1) and (1,Float.MAX_VALUE) [each test took two hours
wall clock time on a 1.266GHz Intel Pentium 4.]

I therefore spent time on the four days following the first successful
Java translation of ELEFUNT, writing these notes, carrying out
additional testing on several other platforms, implementing an
enhanced version of the extmath.java package to supply standard
elementary functions that are not provided by Java, and writing a
replacement for the simple fmt.java package as the pair fmtint.java
and fmtflt.java.  The latter two were the most difficult: together
they contain nearly 5200 lines, of which half is test suite code, and
a quarter is documentation formatted according to the javadoc
conventions: running

	javadoc -author -version fmt???.java

produces the HTML documentation stored in the ./html directory.

The goal in the fmt.java package is not to achieve complete rigor (for
that, see the papers by Clinger, Gries, Knuth, Steele and White,
Burger and Dybvig, and Abbott and 15 Al's in the references below, and
note that multiple-precision arithmetic, completely lacking in Java,
is mandatory for the job), but rather, to provide a reasonably
straightforward implementation that is acceptably accurate for ELEFUNT
output.

Ultimately, Java will probably get a fancy numeric formatting package
that my fmt.java package can then interface with.  Given Sun
Microsystem's strong track record in providing high-quality
floating-point support, thanks to people like IEEE 754 committee
members David Hough and Joe Darcy, and to Guy Steele (the same one
referenced above), I have some confidence that Java will ultimately
benefit from this in-house knowledge base.

I have not retrofitted use of the fancier fmtflt.java and fmtint.java
packages into the Java version of the ELEFUNT package, but I expect to
make good use of them in future Java programming projects.

In tests of the fmtflt.java and fmtint.java packages on local systems,
I get identical output on Apple PowerPC Darwin (MacOSX), Intel x86
GNU/Linux, and Sun Solaris, covering Java 1.1, 1.2, 1.2.2, 1.3.1, and
1.4.  There are numeric differences reported on Compaq/DEC Alpha OSF/1
and SGI IRIX 6.5 systems: in every case, these differences are in the
formatting of numbers by the native Java libraries, not in those from
my own code.

Java provides object wrappers for each of its primitive data types,
with similar names (primitive "double" becomes object "Double").
These wrappers provide a few named constants (MAX_VALUE, MIN_VALUE,
NEGATIVE_INFINITY, NaN, and POSITIVE_INFINITY, but none of the other
values provided by machar()), plus a few methods for value conversion,
infinity, NaN, and object equality testing, conversion to raw bit
strings, and object hash codes.  Methods then are used with object
names: the primitive "double x; fmt.E(x,w,d)" would become
"ExtendedDouble xx; xx.E(w,d)", where ExtendedDouble is a class that
implements an extension to Double, and offers additional methods.

In ELEFUNT for C/C++, I extended the code to permit both compile-time
and run-time setting of the initial pseudo-random number generator
seed, and of the number of random arguments in the test intervals.  At
run-time, values can be set for the environment variables INITIALSEED
and MAXTEST.  Java's virtual machine environment tends to divorce it
from access to the underlying host environment, so there is no access
to shell environment variables via getenv().  However, a similar
feature can be provided at run time with Java `system properties'
accessed via the function System.getProperty():

	java -DINITIALSEED=271828182 -DMAXTEST=100000 talldp

I have yet to discover how, or if, the GNU Java implementation, gcj,
accesses such properties.  Neither environment variables nor
command-line variable assignments are visible to its
System.getProperty().


==========
What's new
==========

	* ELEFUNT is now available for Java!

	* Java code has been successful compiled with Java 1.2, 1.3,
          and 1.4, with deprecation warnings turned on.  It should
          work correctly, without changes, in ALL Java platforms.
          Actual output is expected to vary, since some vendors might
          use differing implementations of the java.lang.Math library.

	  It has also been compiled with GNU gcj 3.0.4 on GNU/Linux on
	  Intel IA-32, and gcj 3.1 on Sun SPARC Solaris 2.8: while
	  compilations are successful, runs all fail with an uncaught
	  divide-by-zero error inside the runtime library from the call
	  myFormat.format(-999.0) in fmt.java.  This was tedious to
	  track down: the gdb debugger does not yet support
	  gcj-compiled Java code, and the Runtime.traceInstructions()
	  and Runtime.traceMethodCalls functions are not supported, so
	  I had to resort to dozens of print statements sprinkled
	  through a temporary copy of the source code.

	* The extmath.java package supplies standard elementary
          functions that are missing in the definition of the standard
          java.lang.Math package.  It can be used as a complete
          replacement for the latter: simply change all instances of
          Math.X to extmath.X in your code, for all X.

	* The fmtflt.java and fmtint.java packages provide much
          enhanced numeric formatted output, with support for string
          justification (left, right, center), Ada-style based numbers
          (5#34214#), Fortran/C/C++ format items (B, I, O, Z, E, F, G,
          plus new ones R and S), and Ada-style digit separators
          (contrast 3.1415926535897932384626433832795028 with
          3.14159_26535_89793_23846_26433_83279_5028 or
          3.141_592_653_589_793_238_462_643_383_279_502_8).

	* New ELEFUNT code directory structure, with common source
	  files, shell scripts, and awk programs in ./common, and
	  precision-dependent code in ./sp (single precision) and ./dp
	  (double precision).

	* Output listings for several current systems are available in
          ./sp/logs and ./dp/logs.

	* New top-level Makefile to control building and testing.

	* New helper script (./common/elefunt.sh) to run the tests
	  with several different Java compilers, giving the output
	  listing distinctive names that identify the system,
	  compiler, and optimization level

	* (cd common; make check) will run a validation suite against
	  correct output from Java 1.2 on Sun Solaris 2.8.  In
	  particular, this does simple tests for fmt.java, and
	  extensive tests for extmath.java, fmtflt.java, and
	  fmtint.java.  The extmath.java tests are carefully chosen to
	  examine regions around the cutoffs used in my
	  implementations of the hyperbolic functions, as well as for
	  signed zero, and near the underflow and overflow limits of
	  these functions, and those that they call to do their
	  computations.  The tests also include results for alternate
	  implementations using the standard mathematical definitions,
	  and using truncated Taylor series expansions, which is also
	  handy for pedagogical demonstrations of the intricacies of
	  floating-point computation.

	  On Sun Solaris 2.8, identical results are obtained for
	  extmath.java for Java 1.1, 1.2, and 1.4.  On Apple Darwin
	  (== MacOS X), Java 1.3.1 produces identical output.  On
	  Intel IA-32 GNU/Linux (Red Hat 7.2), Java 1.2.2 produces
	  identical output.  On SGI IRIX 6.5, Java 1.3. two test
	  results (for sinh() and cosh() near the overflow limit)
	  differ by 2 ulps from the correct values.  On Compaq/DEC
	  OSF/1 4.0, the same tests as on the SGI were also 2 ulps in
	  error.  However, the tests exposed another problem: on this
	  system (long)NaN is -9223372036854775808, whereas on all of
	  the other test systems, (long)NaN is 0!  This is
	  demonstrated in the program bugs/bug002.java.

	* doc/*.pdf contain additional documentation on the
          computation of elementary functions.

	* html/*.* contains javadoc HTML documentation produced
	  automatically from the fmtflt.java and fmtint.java packages.


============================
How to run the ELEFUNT tests
============================

UNIX make is the conventional, and best, way to automate software
building and testing.

The Makefiles here are highly portable, provide all of the GNU
standard targets (notably: all, check, clean, distclean, install,
maintainer-clean, mostlyclean, and uninstall), and should not need
modification at any site.

The packages are portable enough that, so far, there has been no need
to provide for automatic configuration with the GNU autoconf package:
thus, there are no configure scripts.

There are two convenient ways to run the ELEFUNT test programs:

	make all
or
	make elefunt

These run both single- and double-precision tests, since both are
standard in Java.

The difference between "all" and "elefunt" is that with the former,
you can optionally additionally supply on the make command line

	* output filename suffix (NAME=...),
	* additional compiler flags (JAVACFLAGS=...),
	* additional make flags (XMFLAGS=...), and
	* compiler optimization level (XOPT=...)

while with the latter, the ./common/elefunt.sh script takes over,
figures out what system you have, and runs the tests with at least two
optimization levels of each compiler.

To restore the distribution tree to its original condition (but
preserving any listing files that you generated locally), do

	make distclean


==========
References
==========

@String{j-CACM                  = "Communications of the Association for
                                  Computing Machinery"}

@String{j-IBM-JRD               = "IBM Journal of Research and Development"}

@String{j-PROC-AM-MATH-SOC      = "Proceedings of the American Mathematical Society"}

@String{j-SIGPLAN               = "ACM SIGPLAN Notices"}

@String{pub-AW                  = "Ad{\-d}i{\-s}on-Wes{\-l}ey"}

@String{pub-AW:adr              = "Reading, MA, USA"}

@String{pub-SV                  = "Spring{\-}er-Ver{\-}lag"}

@String{pub-SV:adr              = "Berlin, Germany~/ Heidelberg,
                                  Germany~/ London, UK~/ etc."}

@Article{Matula:1968:BCT,
  author =       "David W. Matula",
  title =        "The Base Conversion Theorem",
  journal =      j-PROC-AM-MATH-SOC,
  volume =       "19",
  number =       "3",
  pages =        "716--723",
  month =        jun,
  year =         "1968",
  CODEN =        "PAMYAR",
  ISSN =         "0002-9939",
  bibdate =      "Fri Apr 21 07:26:39 2000",
  acknowledgement = ack-nhfb,
}

@Article{Matula:1968:IOC,
  author =       "D. W. Matula",
  title =        "In-and-Out Conversions",
  journal =      j-CACM,
  volume =       "11",
  number =       "1",
  pages =        "47--50",
  month =        jan,
  year =         "1968",
  CODEN =        "CACMA2",
  ISSN =         "0001-0782",
  bibdate =      "Thu Sep 1 10:16:10 1994",
  bibsource =    "ftp://garbo.uwasa.fi/pc/doc-soft/fpbibl18.zip",
  acknowledgement = ack-nj,
}

@Article{Clinger:1990:HRF,
  author =       "William D. Clinger",
  title =        "How to Read Floating Point Numbers Accurately",
  journal =      j-SIGPLAN,
  volume =       "25",
  number =       "6",
  pages =        "92--101",
  month =        jun,
  year =         "1990",
  CODEN =        "SINODQ",
  ISSN =         "0362-1340",
  bibdate =      "Sun May 02 09:17:14 1999",
  bibsource =    "ftp://garbo.uwasa.fi/pc/doc-soft/fpbibl18.zip",
  note =         "See also output algorithms in
                 \cite{Knuth:1990:SPW,Steele:1990:HPF,Burger:1996:PFN,Abbott:1999:ASS}.",
  abstract =     "Consider the problem of converting decimal scientific
                 notation for a number into the best binary floating
                 point approximation to that number, for some fixed
                 precision. This problem cannot be solved using
                 arithmetic of any fixed precision. Hence the IEEE
                 Standard for Binary Floating-Point Arithmetic does not
                 require the result of such a conversion to be the best
                 approximation. The author presents an efficient
                 algorithm that always finds the best approximation. The
                 algorithm uses a few extra bits of precision to compute
                 an IEEE-conforming approximation while testing an
                 intermediate result to determine whether the
                 approximation could be other than the best. If the
                 approximation might not be the best, then the best
                 approximation is determined by a few simple operations
                 on multiple-precision integers, where the precision is
                 determined by the input. When using 64 bits of
                 precision to compute IEEE double precision results, the
                 algorithm avoids higher-precision arithmetic over 99\%
                 of the time.",
  acknowledgement = ack-nhfb # " and " # ack-nj,
  affiliation =  "Oregon Univ., Eugene, OR, USA",
  classification = "C5230 (Digital arithmetic methods); C1160
                 (Combinatorial mathematics); C7310 (Mathematics)",
  confdate =     "20-22 June 1990",
  conflocation = "White Plains, NY, USA",
  confsponsor =  "ACM",
  keywords =     "Floating point numbers; Decimal scientific notation;
                 Best binary floating point approximation; Fixed
                 precision; IEEE Standard; Efficient algorithm;
                 IEEE-conforming approximation; Intermediate result;
                 Multiple-precision integers; IEEE double precision
                 results; Higher-precision arithmetic",
  language =     "English",
  pubcountry =   "USA",
  thesaurus =    "Digital arithmetic; Mathematics computing; Number
                 theory; Standards",
}

@InCollection{Gries:1990:BDO,
  author =       "David Gries",
  title =        "Binary to Decimal, One More Time",
  crossref =     "Feijen:1990:BOB",
  chapter =      "16",
  pages =        "141--148",
  year =         "1990",
  bibdate =      "Sat Sep 03 09:41:32 1994",
  note =         "This paper presents an alternate proof of Knuth's
                 algorithm \cite{Knuth:1990:SPW} for conversion between
                 decimal and fixed-point binary numbers.",
  acknowledgement = ack-nhfb,
}

@InCollection{Knuth:1990:SPW,
  author =       "Donald E. Knuth",
  title =        "A Simple Program Whose Proof Isn't",
  crossref =     "Feijen:1990:BOB",
  chapter =      "27",
  pages =        "233--242",
  year =         "1990",
  bibdate =      "Sat Sep 03 09:42:46 1994",
  note =         "This paper discusses the algorithm used in {\TeX} for
                 converting between decimal and scaled fixed-point
                 binary values, and for guaranteeing a minimum number of
                 digits in the decimal representation. See also
                 \cite{Clinger:1990:HRF} for decimal to binary
                 conversion, \cite{Steele:1990:HPF} for binary to
                 decimal conversion, and \cite{Gries:1990:BDO} for an
                 alternate proof of Knuth's algorithm.",
  acknowledgement = ack-nhfb,
}

@Article{Steele:1990:HPF,
  author =       "Guy L. {Steele Jr.} and Jon L. White",
  title =        "How to Print Floating-Point Numbers Accurately",
  journal =      j-SIGPLAN,
  volume =       "25",
  number =       "6",
  pages =        "112--126",
  month =        jun,
  year =         "1990",
  CODEN =        "SINODQ",
  ISSN =         "0362-1340",
  bibdate =      "Sat May 04 17:29:18 1996",
  note =         "See also input algorithm in \cite{Clinger:1990:HRF},
                 and a faster output algorithm in
                 \cite{Burger:1996:PFN}, and \cite{Knuth:1990:SPW}, and
                 IBM S/360 algorithms in \cite{Abbott:1999:ASS} for both
                 IEEE 754 and S/360 formats. In electronic mail dated
                 Wed, 27 Jun 90 11:55:36 EDT, Guy Steele reported that
                 an intrepid pre-SIGPLAN 90 conference implementation of
                 what is stated in the paper revealed 3 mistakes:
                 \begin{itemize} \item[1.] Table~5 (page
                 124):\par\noindent insert {\tt k <-- 0} after
                 assertion, and also delete {\tt k <-- 0} from Table~6.
                 \item[2.] Table~9 (page 125):\par\noindent
                 \begin{tabular}{ll} for & {\tt -1:USER!({"}{"});} \\
                 substitute & {\tt -1:USER!({"}0{"});}
                 \end{tabular}\par\noindent and delete the comment.
                 \item[3.] Table~10 (page 125):\par\noindent
                 \begin{tabular}{ll} for & {\tt fill(-k, {"}0{"})}\\
                 substitute & {\tt fill(-k-1, {"}0{"})} \end{tabular}
                 \end{itemize}
                 \def\EatBibTeXPeriod#1{\ifx#1.\else#1\fi}\EatBibTeXPeriod",
  abstract =     "Algorithms are presented for accurately converting
                 floating-point numbers to decimal representation. The
                 key idea is to carry along with the computation an
                 explicit representation of the required rounding
                 accuracy. The authors begin with the simpler problem of
                 converting fixed-point fractions. A modification of the
                 well-known algorithm for radix-conversion of
                 fixed-point fractions by multiplication explicitly
                 determines when to terminate the conversion process; a
                 variable number of digits are produced. They derive two
                 algorithms for free-format output of floating-point
                 numbers. Finally, they modify the free-format
                 conversion algorithm for use in fixed-format
                 applications. Information may be lost if the fixed
                 format provides too few digit positions, but the output
                 is always correctly rounded. On the other hand, no
                 `garbage digits' are ever produced, even if the fixed
                 format specifies too many digit positions (intuitively,
                 the `4/3 prints as 1.333333328366279602' problem does
                 not occur).",
  acknowledgement = ack-nhfb,
  affiliation =  "Thinking Machines Corp., Cambridge, MA, USA",
  classification = "C5230 (Digital arithmetic methods); C7310
                 (Mathematics)",
  confdate =     "20-22 June 1990",
  conflocation = "White Plains, NY, USA",
  confsponsor =  "ACM",
  keywords =     "Floating-point numbers; Decimal representation;
                 Explicit representation; Rounding accuracy; Fixed-point
                 fractions; Radix-conversion; Conversion process;
                 Free-format output; Free-format conversion algorithm;
                 Fixed-format applications; Garbage digits; Digit
                 positions",
  language =     "English",
  pubcountry =   "USA",
  thesaurus =    "Digital arithmetic; Mathematics computing",
}

@Book{Feijen:1990:BOB,
  editor =       "W. H. J. Feijen and A. J. M. {van Gasteren} and D.
                 Gries and J. Misra",
  booktitle =    "Beauty is our business: a birthday salute to {Edsger
                 W. Dijkstra}",
  title =        "Beauty is our business: a birthday salute to {Edsger
                 W. Dijkstra}",
  publisher =    pub-SV,
  address =      pub-SV:adr,
  pages =        "xix + 453",
  year =         "1990",
  ISBN =         "0-387-97299-4",
  LCCN =         "QA76 .B326 1990",
  bibdate =      "Thu Mar 24 09:27:40 1994",
  acknowledgement = ack-nhfb,
}

@Article{Burger:1996:PFN,
  author =       "Robert G. Burger and R. Kent Dybvig",
  title =        "Printing Floating-Point Numbers Quickly and
                 Accurately",
  journal =      j-SIGPLAN,
  volume =       "31",
  number =       "5",
  pages =        "108--116",
  month =        may,
  year =         "1996",
  CODEN =        "SINODQ",
  ISSN =         "0362-1340",
  bibdate =      "Sun May 02 09:16:12 1999",
  note =         "This paper offers a significantly faster algorithm
                 than that of \cite{Steele:1990:HPF}, together with a
                 correctness proof and an implementation in Scheme. See
                 also \cite{Clinger:1990:HRF,Abbott:1999:ASS}.",
  acknowledgement = ack-nhfb,
}

@Book{Chan:1998:JCLb,
  author =       "Patrick Chan and Rosanna Lee",
  title =        "The {Java} Class Libraries: java.applet, java.awt,
                 java.beans",
  volume =       "2",
  publisher =    pub-AW,
  address =      pub-AW:adr,
  edition =      "Second",
  pages =        "1712",
  year =         "1998",
  ISBN =         "0-201-31003-1",
  LCCN =         "QA76.73.J38C47 1998",
  bibdate =      "Wed May 27 07:02:55 1998",
  bibsource =    "http://www.aw.com/",
  price =        "US\$54",
  URL =          "http://cseng.aw.com/bookdetail.qry?ISBN=0-201-31003-1;
                 http://www2.awl.com/cgi-bin/htsearch?restrict=&exclude=&config=htdig&method=boolean&format=builtin%2Dlong&words=Chan%20AND%20Lee&page=2",
  acknowledgement = ack-nhfb,
  annote =       "See \cite{Chan:1999:JCLb} for vol. 1.",
}

@TechReport{Kahan:1998:HJFa,
  author =       "W. Kahan and Joseph D. Darcy",
  title =        "How {Java}'s Floating-Point Hurts Everyone
                 Everywhere",
  type =         "Technical Report",
  institution =  "Department of Mathematics and Department of Electrical
                 Engineering and Computer Science, University of
                 California, Berkeley",
  address =      "Berkeley, CA, USA",
  pages =        "80",
  day =          "18",
  month =        jun,
  year =         "1998",
  bibdate =      "Sat Sep 12 18:53:11 1998",
  URL =          "http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf;
                 http://www.cs.berkeley.edu/~wkahan/JAVAhurt.ps",
  acknowledgement = ack-nhfb,
  annote =       "The authors deliver a biting criticism of Java for its
                 failure to use the 80-bit temporary real format on
                 Intel x86 architectures, failure to use multiply-add
                 instructions when available, and failure to compute
                 float subexpressions in double precision.",
}

@Book{Chan:1999:JCLb,
  author =       "Patrick Chan and Rosanna Lee and Doug Kramer",
  title =        "The {Java} Class Libraries, Volume 1",
  publisher =    pub-AW,
  address =      pub-AW:adr,
  edition =      "Second",
  pages =        "704",
  year =         "1999",
  ISBN =         "0-201-31002-3",
  LCCN =         "QA76.73.J38 C47 1998",
  bibdate =      "Tue May 11 07:28:09 1999",
  price =        "US\$34.95",
  acknowledgement = ack-nhfb,
  annote =       "Covers java.io, java.lang., java.math, java.net,
                 java.text, java.util",
}

@Book{Chan:1999:JCLc,
  author =       "Patrick Chan and Rosanna Lee and Douglas Kramer",
  title =        "The {Java} Class Libraries, Second Edition, Volume 1:
                 Supplement for {Java 2} Platform, Standard Edition,
                 v1.2",
  publisher =    pub-AW,
  address =      pub-AW:adr,
  pages =        "xxix + 1157",
  year =         "1999",
  ISBN =         "0-201-48552-4",
  LCCN =         "QA76.73.J38 C47 1998",
  bibdate =      "Sat May 11 09:29:34 2002",
  bibsource =    "http://www1.fatbrain.com/asp/bookinfo/bookinfo.asp?theisbn=0201485524",
  price =        "US\$34.95",
  acknowledgement = ack-nhfb,
}

@Article{Abbott:1999:ASS,
  author =       "P. H. Abbott and D. G. Brush and C. W. {Clark III} and
                 C. J. Crone and J. R. Ehrman and G. W. Ewart and C. A.
                 Goodrich and M. Hack and J. S. Kapernick and B. J.
                 Minchau and W. C. Shepard and R. M. {Smith, Sr.} and
                 R. Tallman and S. Walkowiak and A. Watanabe and W. R.
                 White",
  title =        "Architecture and software support in {IBM S/390
                 Parallel Enterprise Servers} for {IEEE} Floating-Point
                 arithmetic",
  journal =      j-IBM-JRD,
  volume =       "43",
  number =       "5/6",
  pages =        "723--760",
  month =        "????",
  year =         "1999",
  CODEN =        "IBMJAE",
  ISSN =         "0018-8646",
  bibdate =      "Wed Apr 19 18:58:23 MDT 2000",
  note =         "Besides important history of the development of the
                 S/360 floating-point architecture, this paper has a
                 good description of IBM's algorithm for exact
                 decimal-to-binary conversion, complementing earlier
                 ones
                 \cite{Steele:1990:HPF,Clinger:1990:HRF,Knuth:1990:SPW,Burger:1996:PFN}.",
  URL =          "http://www.research.ibm.com/journal/rd/435/abbott.html",
  acknowledgement = ack-nhfb,
}

@Book{Bloch:2001:EJP,
  author =       "Joshua Bloch",
  title =        "Effective {Java}: Programming Language Guide",
  publisher =    pub-AW,
  address =      pub-AW:adr,
  pages =        "xvi + 252",
  year =         "2001",
  ISBN =         "0-201-31005-8",
  LCCN =         "QA76.73.J38 B57 2001",
  bibdate =      "Sat Apr 20 11:10:41 2002",
  series =       "Java series",
  acknowledgement = ack-nhfb,
  contents=      "1. Introduction -- 2. Creating and destroying objects
                 -- 3. Methods common to all objects -- 4. Classes and
                 interfaces -- 5. Substitutes for C constructs --
                 6. Methods -- 7. General programming -- 8. Exceptions
                 -- 9. Threads -- 10. Serialization",
  keywords =     "java (computer program language)",
}

------------------------------------------------------------------------


=================================
Introduction to the C/C++ version
=================================

This is a substantial update of some old (1987) work documented
below to provide a highly-portable C (and C++) translation of the
Fortran ELEFUNT packages.

At the time the translation from Fortran to C was originally carried
out, C was yet to be standardized, double was its only usable
floating-point data type, and automated Fortran-to-C translators did
not exist.  Thus, the translation was done by hand, taking great care
to ensure output that is indistinguishable from that produced by the
original Fortran code.

For this new version, ELEFUNT has been significantly extended in C and
C++, and in Fortran, to test the quadruple-precision (C/C++ long
double and Fortran REAL*16) elementary functions.  To my knowledge, no
such version of ELEFUNT has hitherto been available, although computer
vendors may well have produced in-house versions for their own testing
purposes.  [A Java version of the single- and double- precision tests is
available.]

Although a freely-available, and highly reliable, Fortran-to-C
translator, f2c, is now available, I chose to continue the tradition
of hand translation of the quadruple-precision Fortran code for two
very good reasons:

	* f2c does not recognize quadruple-precision Fortran, and thus
	  could not do the job (though the commercial Cobalt Blue
	  translator might), and

	* f2c translates Fortran I/O statements into calls to a
	  separate library which must be ported and be available, and
	  which substantially obscure the code.

The hand translation ensures that Fortran WRITE statements are
converted to more readable C printf() function calls, and that the
numerous Fortran goto statements which confuse control flow have been
almost entirely banished (just one remains in each of the three
machar*() functions).

------------------------------------------------------------------------

               C Version of the Code & Waite
          ELEFUNT Elementary Function Test Package
                       [15-Jun-1987]

This C version of the ELEFUNT test package was translated by
Ken Stoner (GU.STONER@SCIENCE.UTAH.EDU) and Nelson H.F.
Beebe (BEEBE@SCIENCE.UTAH.EDU) at the Center for Scientific
Computing, Department of Mathematics, University of Utah.
The translation was carried out by converting the original
FORTRAN code to Ratfor automatically with the Unix struct
utility, then hand editing the Ratfor to C, which resemble
one another.

Considerable care has been taken to match the output format
of the two versions, so that after the characters
+-0123456789 have been converted to blanks, the output
listings should substantially agree.  One error was
corrected in FORMAT 1030 in TPOWER--a missing right
parenthesis.  The FORTRAN version has some inconsistencies
in the number of blank lines used for spacing the output; we
have opted in favor of uniformity in the C version.

C is problematic for numerical work on several grounds:

        * Parentheses in expressions cannot be used to
          enforce evaluation order; temporary variables must
          be introduced.  This was particularly a problem in
          machar.c.

        * C has float and double data types, but an
          implementation is free to implement these
          in the same precision (PCC-20 uses only single
          precision); the run-time library is written only
          in type double.

        * The behavior of library functions with respect to
          out-of-range arguments, or arguments which would
          result in substantial accuracy loss, is not
          standardized.  Most C run-time libraries simply
          set the global error value "errno" to a non-zero
          value and return an arbitrary function result.
          Code to test errno has been added to the test
          programs.

        * The behavior of floating-point arithmetic in
          response to  underflow or overflow is not
          well-defined.

In addition, machines with IEEE arithmetic (which is
provided by most newer architectures) place additional
demands on numerical software because they have
computational units of greater precision than is stored in
memory.  For example, several implementations compute with
80-bit extended precision, but store 32-bit or 64-bit values
in memory.  Code in machar is particularly sensitive to
this, and it has been necessary to force memory stores in
intermediate expressions by calling a function
store(&memval).  Since the address of a memory location is
passed to store(), that location can potentially be
modified, and the caller of store() must then reload the
memory value upon return, rather than using a value that
might exist in a higher-precision register.

The C version has been written using type "float"; the
Makefile's for it provide an implicit "#define float double"
for those systems in which the two precisions are
implemented differently, so that the tests are carried out
at the precision of the run-time library.
