%% /u/sy/beebe/src/elefunt/c/README, Tue May 28 15:04:28 2002
%% Edit by Nelson H. F. Beebe <beebe@math.utah.edu>

            **********************************************
            **********************************************
            **  Extended C Version of the Code & Waite	**
            ** ELEFUNT Elementary Function Test Package	**
            **              [28-May-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


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

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


============
Introduction
============

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
also 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).


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

Details of the changes can be found in the companion ChangeLog file,
but can be briefly summarized as follows:

	* Support for float (./sp) and long double (./qp) as well as
	  the normal double (./dp) tests.

	  Although the float type existed in old-style K&R C, and in
	  1989 Standard C, it was not a first-class data type, in that
	  there were no library functions to support it, and float
	  arguments were coerced to double.

	  In 1999 Standard C (ISO/IEC 9899:1999(E) Programming
	  languages -- C), float and long double are finally
	  first-class primitive data types, with full library function
	  support, and, in the presence of suitable function
	  prototypes, with no promotion of float arguments to double.
	  Some pre-C99 compilers already support these extensions, and
	  the test results in the distributions show how well they do.

  	  At the time of writing (May 2002), none of my 50+ C
	  compilers yet conforms to the 1999 ISO Standard, nor do any
	  of my 35+ C++ compilers yet conform to C++98 (ISO/IEC
	  14882:1998(E) Programming languages -- C++).

	* Changes to the environmental inquiry routines, macharf(),
          machar(), and macharl(), and some of the test programs, to
          support IEEE 754 arithmetic, including those systems with
          registers that are wider than memory words.

	* Source code can be compiled with old-style K&R C compilers,
	  1989 Standard C compilers, and C++ compilers.

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

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

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

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

	* Support for compile-time and run-time setting of initial
          pseudo-random number 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.


============================
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 only the double-precision tests: change the target names to
all2 and elefunt2 for single- and double-precision tests, and to all3
and elefunt3 for single-, double-, and quadruple-precision tests.

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 (XCFLAGS=...),
	* compile-time definitions (XDEFINES=...),
	* compiler include directives (XINCLUDES=...),
	* additional linker flags (XLDFLAGS=...),
	* additional load libraries (XLIBS=...),
	* 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

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

               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.
