[llvm-commits] [test-suite] r148656 - in /test-suite/trunk/MultiSource/Benchmarks: Makefile nbench/ nbench/COM.DAT nbench/Changes nbench/Makefile nbench/NNET.DAT nbench/README nbench/bdoc.txt nbench/debugbit.good.gz nbench/emfloat.c nbench/emfloat.h nbench/hardware.h nbench/misc.c nbench/misc.h nbench/nbench.reference_output nbench/nbench0.c nbench/nbench0.h nbench/nbench1.c nbench/nbench1.h nbench/nmglobal.h nbench/sysspec.c nbench/sysspec.h nbench/wordcat.h

Benjamin Kramer benny.kra at googlemail.com
Sun Jan 22 01:50:59 PST 2012


Author: d0k
Date: Sun Jan 22 03:50:58 2012
New Revision: 148656

URL: http://llvm.org/viewvc/llvm-project?rev=148656&view=rev
Log:
Add nbench to the test suite (aka the old BYTE magazine benchmark)

- Modified to run a fixed number of iterations so changes are reflected in the reports.
- Made independent of configure programs.
- Disabled output so we can use a reference output.
- Stripped most of the code we don't need.

It would be nice to report the results for the individual test but I couldn't
figure out how to do that with the current infrastructure.

Added:
    test-suite/trunk/MultiSource/Benchmarks/nbench/
    test-suite/trunk/MultiSource/Benchmarks/nbench/COM.DAT
    test-suite/trunk/MultiSource/Benchmarks/nbench/Changes
    test-suite/trunk/MultiSource/Benchmarks/nbench/Makefile
    test-suite/trunk/MultiSource/Benchmarks/nbench/NNET.DAT
    test-suite/trunk/MultiSource/Benchmarks/nbench/README
    test-suite/trunk/MultiSource/Benchmarks/nbench/bdoc.txt
    test-suite/trunk/MultiSource/Benchmarks/nbench/debugbit.good.gz   (with props)
    test-suite/trunk/MultiSource/Benchmarks/nbench/emfloat.c
    test-suite/trunk/MultiSource/Benchmarks/nbench/emfloat.h
    test-suite/trunk/MultiSource/Benchmarks/nbench/hardware.h
    test-suite/trunk/MultiSource/Benchmarks/nbench/misc.c
    test-suite/trunk/MultiSource/Benchmarks/nbench/misc.h
    test-suite/trunk/MultiSource/Benchmarks/nbench/nbench.reference_output
    test-suite/trunk/MultiSource/Benchmarks/nbench/nbench0.c
    test-suite/trunk/MultiSource/Benchmarks/nbench/nbench0.h
    test-suite/trunk/MultiSource/Benchmarks/nbench/nbench1.c
    test-suite/trunk/MultiSource/Benchmarks/nbench/nbench1.h
    test-suite/trunk/MultiSource/Benchmarks/nbench/nmglobal.h
    test-suite/trunk/MultiSource/Benchmarks/nbench/sysspec.c
    test-suite/trunk/MultiSource/Benchmarks/nbench/sysspec.h
    test-suite/trunk/MultiSource/Benchmarks/nbench/wordcat.h
Modified:
    test-suite/trunk/MultiSource/Benchmarks/Makefile

Modified: test-suite/trunk/MultiSource/Benchmarks/Makefile
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/Makefile?rev=148656&r1=148655&r2=148656&view=diff
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/Makefile (original)
+++ test-suite/trunk/MultiSource/Benchmarks/Makefile Sun Jan 22 03:50:58 2012
@@ -4,8 +4,8 @@
 # Disabled: OptimizerEval.
 PARALLEL_DIRS := Fhourstones Fhourstones-3.1 \
                  McCat Olden Ptrdist llubenchmark \
-                 sim FreeBench MallocBench Prolangs-C SciMark2-C\
-                 mediabench ASCI_Purple MiBench Trimaran VersaBench NPB-serial\
+                 sim FreeBench MallocBench Prolangs-C SciMark2-C mediabench\
+                 nbench ASCI_Purple MiBench Trimaran VersaBench NPB-serial\
                  BitBench ASC_Sequoia
 
 ifndef DISABLE_CXX

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/COM.DAT
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/COM.DAT?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/COM.DAT (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/COM.DAT Sun Jan 22 03:50:58 2012
@@ -0,0 +1,11 @@
+ALLSTATS=T
+DONUMSORT=T
+DOSTRINGSORT=T
+DOBITFIELD=T
+DOEMF=T
+DOFOUR=T
+DOASSIGN=T
+DOIDEA=T
+DOHUFF=T
+DONNET=T
+DOLU=T

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/Changes
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/Changes?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/Changes (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/Changes Sun Jan 22 03:50:58 2012
@@ -0,0 +1,42 @@
+This is about BYTE's beta version of the native-algorithm benchmark
+
+December 16, 1996:
+
+The source for DOS is obtainable at http://www.byte.com/bmark/bmark.htm
+Linux adaptation written by Uwe F. Mayer <mayer at tux.org>
+
+February 7, 1997:
+
+added -DSOLARIS flag to support solaris
+
+November 11, 1997:
+
+added index split suggested by Andrew D. Balsa
+re-baselined to a Linux machine
+added checking of CPU-type at run-time (cpuinfo.c)
+increased maximal number of loops in some tests
+removed -DSOLARIS flag, works now automatically (this also removed the
+  compiler warnings about redefined types and leads to a 20% faster
+  code for "Bitfield" if compiled with -funroll-loops!)
+
+November 13-19, 1997:
+
+changed debugging information
+changed random number generator to be always 32 bits even on 64 bit OSs
+added data resets to Bitfield and Huffman
+created this Changes file
+added debug code for Bitfield
+
+December 6, 1997:
+
+got rid of cpuinfo.c
+added a RESULTS file
+
+December 7, 1997:
+
+fixed the statistical analysis used to compute the confidence coefficient
+fixed a bug in the DEBUG routine of "Assignment"
+
+December 11, 1997
+added some entries to RESULTS
+

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/Makefile
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/Makefile?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/Makefile (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/Makefile Sun Jan 22 03:50:58 2012
@@ -0,0 +1,7 @@
+LEVEL = ../../..
+
+PROG     = nbench
+CPPFLAGS = -DBASE_ITERATIONS=50
+LDFLAGS  =
+
+include	../../Makefile.multisrc

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/NNET.DAT
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/NNET.DAT?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/NNET.DAT (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/NNET.DAT Sun Jan 22 03:50:58 2012
@@ -0,0 +1,210 @@
+5  7  8 
+26
+0  0  1  0  0
+0  1  0  1  0
+1  0  0  0  1
+1  0  0  0  1
+1  1  1  1  1
+1  0  0  0  1
+1  0  0  0  1
+0  1  0  0  0  0  0  1
+1  1  1  1  0
+1  0  0  0  1
+1  0  0  0  1
+1  1  1  1  0
+1  0  0  0  1
+1  0  0  0  1
+1  1  1  1  0
+0  1  0  0  0  0  1  0
+0  1  1  1  0
+1  0  0  0  1
+1  0  0  0  0
+1  0  0  0  0
+1  0  0  0  0
+1  0  0  0  1
+0  1  1  1  0
+0  1  0  0  0  0  1  1
+1  1  1  1  0
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  1  1  1  0
+0  1  0  0  0  1  0  0
+1  1  1  1  1
+1  0  0  0  0
+1  0  0  0  0
+1  1  1  0  0
+1  0  0  0  0
+1  0  0  0  0
+1  1  1  1  1
+0  1  0  0  0  1  0  1
+1  1  1  1  1
+1  0  0  0  0
+1  0  0  0  0
+1  1  1  0  0
+1  0  0  0  0
+1  0  0  0  0
+1  0  0  0  0
+0  1  0  0  0  1  1  0
+0  1  1  1  0
+1  0  0  0  1
+1  0  0  0  0
+1  0  0  0  0
+1  0  0  1  1
+1  0  0  0  1
+0  1  1  1  0
+0  1  0  0  0  1  1  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  1  1  1  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+0  1  0  0  1  0  0  0
+0  1  1  1  0
+0  0  1  0  0
+0  0  1  0  0
+0  0  1  0  0
+0  0  1  0  0
+0  0  1  0  0
+0  1  1  1  0
+0  1  0  0  1  0  0  1
+0  0  0  0  1
+0  0  0  0  1
+0  0  0  0  1
+0  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+0  1  1  1  0
+0  1  0  0  1  0  1  0
+1  0  0  0  1
+1  0  0  1  0
+1  0  1  0  0
+1  1  0  0  0
+1  0  1  0  0
+1  0  0  1  0
+1  0  0  0  1
+0  1  0  0  1  0  1  1
+1  0  0  0  0
+1  0  0  0  0
+1  0  0  0  0
+1  0  0  0  0
+1  0  0  0  0
+1  0  0  0  0
+1  1  1  1  1
+0  1  0  0  1  1  0  0
+1  0  0  0  1
+1  1  0  1  1
+1  0  1  0  1
+1  0  1  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+0  1  0  0  1  1  0  1
+1  0  0  0  1
+1  1  0  0  1
+1  0  1  0  1
+1  0  1  0  1
+1  0  1  0  1
+1  0  0  1  1
+1  0  0  0  1
+0  1  0  0  1  1  1  0
+0  1  1  1  0
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+0  1  1  1  0
+0  1  0  0  1  1  1  1
+1  1  1  1  0
+1  0  0  0  1
+1  0  0  0  1
+1  1  1  1  0
+1  0  0  0  0
+1  0  0  0  0
+1  0  0  0  0
+0  1  0  1  0  0  0  0
+0  1  1  1  0
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  1  0  1
+1  0  0  1  1
+0  1  1  1  1
+0  1  0  1  0  0  0  1
+1  1  1  1  0  
+1  0  0  0  1
+1  0  0  0  1
+1  1  1  1  0
+1  0  1  0  0
+1  0  0  1  0
+1  0  0  0  1
+0  1  0  1  0  0  1  0
+0  1  1  1  1
+1  0  0  0  0
+1  0  0  0  0
+0  1  1  1  0
+0  0  0  0  1
+0  0  0  0  1
+1  1  1  1  0
+0  1  0  1  0  0  1  1
+1  1  1  1  1
+0  0  1  0  0
+0  0  1  0  0
+0  0  1  0  0
+0  0  1  0  0
+0  0  1  0  0
+0  0  1  0  0
+0  1  0  1  0  1  0  0
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+0  1  1  1  0
+0  1  0  1  0  1  0  1
+1  0  0  0  1
+1  0  0  0  1
+0  1  0  1  0
+0  1  0  1  0
+0  1  0  1  0
+0  1  0  1  0
+0  0  1  0  0
+0  1  0  1  0  1  1  0
+1  0  0  0  1
+1  0  0  0  1
+1  0  0  0  1
+1  0  1  0  1
+1  0  1  0  1
+1  0  1  0  1
+0  1  0  1  0
+0  1  0  1  0  1  1  1
+1  0  0  0  1
+0  1  0  1  0
+0  1  0  1  0
+0  0  1  0  0
+0  1  0  1  0
+0  1  0  1  0
+1  0  0  0  1
+0  1  0  1  1  0  0  0
+1  0  0  0  1
+0  1  0  1  0
+0  1  0  1  0
+0  0  1  0  0
+0  0  1  0  0
+0  0  1  0  0
+0  0  1  0  0
+0  1  0  1  1  0  0  1
+1  1  1  1  1
+0  0  0  1  0
+0  0  0  1  0
+0  0  1  0  0
+0  1  0  0  0
+0  1  0  0  0
+1  1  1  1  1
+0  1  0  1  1  0  1  0

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/README
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/README?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/README (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/README Sun Jan 22 03:50:58 2012
@@ -0,0 +1,66 @@
+February 18, 2003
+-----------------
+Bug-fix release.
+
+December 9, 1997
+----------------
+This release is based on beta release 2 of BYTE Magazine's BYTEmark
+benchmark program (previously known as BYTE's Native Mode
+Benchmarks). This document covers the Native Mode (a.k.a. Algorithm
+Level) tests; benchmarks designed to expose the capabilities of a
+system's CPU, FPU, and memory system.
+
+Running a "make" will create the binary if all goes well. It is called
+"nbench" and performs a suite of 10 tests and compares the results to
+a Dell Pentium 90 with 16 MB RAM and 256 KB L2 cache running MSDOS and
+compiling with the Watcom 10.0 C/C++ compiler. If you define -DLINUX
+during compilation (the default) then you also get a comparison to an
+AMD K6/233 with 32 MB RAM and 512 KB L2-cache running Linux 2.0.32 and
+using a binary which was compiled with GNU gcc version 2.7.2.3 and GNU
+libc-5.4.38.
+
+For more verbose output specify -v as an argument.
+
+The primary web site is: http://www.tux.org/~mayer/linux/bmark.html
+
+The port to Linux/Unix was done by Uwe F. Mayer <mayer at tux.org>.
+
+The index-split was done by Andrew D. Balsa, and reflects the
+realization that memory management is important in CPU design. The
+original tests have been left alone, however, the tests NUMERIC SORT,
+FP EMULATION, IDEA, and HUFFMAN now constitute the integer-arithmetic
+focused benchmark index, while the tests STRING SORT, BITFIELD, and
+ASSIGNMENT make up the new memory index.
+
+The algorithms were not changed from the source which was obtained
+from the BYTE web site at http://www.byte.com/bmark/bmark.htm on
+December 14, 1996.  However, the source was modified to better work
+with 64-bit machines (in particular the random number generator was
+modified to always work with 32 bit, no matter what kind of hardware
+you run it on). Furthermore, for some of the algorithms additional
+resettings of the data was added to increase the consistency across
+different hardware. Some extra debugging code was added, which has no
+impact on normal runs.
+
+In case there is uneven system load due to other processes while this
+benchmark suite executes, it might take longer to run than on an
+unloaded system. This is because the benchmark does some statistical
+analysis to make sure that the reported results are statistically
+significant, and an increased variation in individual runs requires
+more runs to achieve the required statistical confidence.
+
+This is a single-threaded benchmark and is not designed to measure the
+performance gain on multi-processor machines.
+
+For details and customization read bdoc.txt.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/bdoc.txt
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/bdoc.txt?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/bdoc.txt (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/bdoc.txt Sun Jan 22 03:50:58 2012
@@ -0,0 +1,2109 @@
+http://www.byte.com/bmark/bmark.htm
+----------------------------------------------------------------------------
+
+BYTEmark
+
+----------------------------------------------------------------------------
+
+This is release 2 of BYTE Magazine's BYTEmark benchmark program (previously
+known as BYTE's Native Mode Benchmarks). This document covers the Native
+Mode (a.k.a. Algorithm Level) tests; benchmarks designed to expose the
+capabilities of a system's CPU, FPU, and memory system. Another group of
+benchmarks within the BYTEmark suite includes the Application Simulation
+Benchmarks. They are detailed in a separate document. [NOTE: The
+documentation for the Application simulation benchmarks should appear before
+the end of March, 95. -- RG].
+
+The Tests
+
+The Native Mode portion of the BYTEmark consists of a number of well-known
+algorithms; some BYTE has used before in earlier versions of the benchmark,
+others are new. The complete suite consists of 10 tests:
+
+Numeric sort - Sorts an array of 32-bit integers.
+
+String sort - Sorts an array of strings of arbitrary length.
+
+Bitfield - Executes a variety of bit manipulation functions.
+
+Emulated floating-point - A small software floating-point package.
+
+Fourier coefficients - A numerical analysis routine for calculating series
+approximations of waveforms.
+
+Assignment algorithm - A well-known task allocation algorithm.
+
+Huffman compression - A well-known text and graphics compression algorithm.
+
+IDEA encryption - A relatively new block cipher algorithm.
+
+Neural Net - A small but functional back-propagation network simulator.
+
+LU Decomposition - A robust algorithm for solving linear equations.
+
+A more complete description of each test can be found in later sections of
+this document.
+
+BYTE built the BYTEmark with the multiplatform world foremost in mind. There
+were, of course, other considerations that we kept high on the list:
+
+Real-world algorithms. The algorithms should actually do something. Previous
+benchmarks often moved gobs of bytes from one point to another, added or
+subtracted piles and piles of numbers, or (in some cases) actually executed
+NOP instructions. We should not belittle those tests of yesterday, they had
+their place. However, we think it better that tests be based on activities
+that are more complex in nature.
+
+Easy to port. All the benchmarks are written in "vanilla" ANSI C. This
+provides us with the best chance of moving them quickly and accurately to
+new processors and operating systems as they appear. It also simplifies
+maintenance.
+
+This means that as new 64-bit (and, perhaps, 128-bit) processors appear, the
+benchmarks can test them as soon as a compiler is available.
+
+Comprehensive. The algorithms were derived from a variety of sources. Some
+are routines that BYTE had been using for some time. Others are routines
+derived from well-known texts in the computer science world. Furthermore,
+the algorithms differ in structure. Some simply "walk" sequentially through
+one-dimensional arrays. Others build and manipulate two-dimensional arrays.
+Finally, some benchmarks are "integer" tests, while others exercise the
+floating-point coprocessor (if one is available).
+
+Scalable. We wanted these benchmarks to be useful across as wide a variety
+of systems as possible. We also wanted to give them a lifetime beyond the
+next wave of new processors.
+
+To that end, we incorporated "dynamic workload adjustment." A complete
+description of this appears in a later section. In a nutshell, this allows
+the tests to "expand or contract" depending on the capabilities of the
+system under test, all the while providing consistent results so that fair
+and accurate comparisons are possible.
+
+Honesty In Advertising
+
+We'd be lying if we said that the BYTEmark was all the benchmarking that
+anyone would ever need to run on a system. It would be equally inaccurate to
+suggest that the tests are completely free of inadequacies. There are many
+things the tests do not do, there are shortcomings, and there are problems.
+
+BYTE will continue to improve the BYTEmark. The source code is freely
+available, and we encourage vendors and users to examine the routines and
+provide us with their feedback. In this way, we assure fairness,
+comprehensiveness, and accuracy.
+
+Still, as we mentioned, there are some shortcomings. Here are those we
+consider the most significant. Keep them in mind as you examine the results
+of the benchmarks now and in the future.
+
+At the mercy of C compilers. Being written in ANSI C, the benchmark program
+is highly portable. This is a reflection of the "world we live in." If this
+were a one-processor world, we might stand a chance at hand-crafting a
+benchmark in assembly language. (At one time, that's exactly what BYTE did.)
+Not today, no way.
+
+The upshot is that the benchmarks must be compiled. For broadest coverage,
+we selected ANSI C. And when they're compiled, the resulting executable's
+performance can be highly dependent on the capabilities of the C compiler.
+Today's benchmark results can be blown out of the water tomorrow if someone
+new enters the scene with an optimizing strategy that outperforms existing
+competition.
+
+This concern is not easily waved off. It will require you to keep careful
+track of compiler version and optimization switches. As BYTE builds its
+database of benchmark results, version number and switch setting will become
+an integral part of that data. This will be true for published information
+as well, so that you can make comparisons fairly and accurately. BYTE will
+control the distribution of test results so that all relevant compiler
+information is attached to the data.
+
+As a faint justification -- for those who think this situation results in
+"polluted" tests -- we should point out that we are in the same boat as all
+the other developers (at least, all those using C compilers -- and that's
+quite a sizeable group). If the only C compilers for a given system happen
+to be poor ones, everyone suffers. It's a fact that a given platform's
+ultimate potential depends as much on the development software available as
+on the technical achievements of the hardware design.
+
+It's just CPU and FPU. It's very tempting to try to capture the performance
+of a machine in a single number. That has never been possible -- though it's
+been tried a lot -- and the gap between that ideal and reality will forever
+widen.
+
+These benchmarks are meant to expose the theoretical upper limit of the CPU,
+FPU, and memory architecture of a system. They cannot measure video, disk,
+or network throughput (those are the domains of a different set of
+benchmarks). You should, therefore, use the results of these tests as part,
+not all, of any evaluation of a system.
+
+Single threaded. Currently, each benchmark test uses only a single execution
+thread. It's unlikely that you'll find any modern operating system that does
+not have some multitasking component. How a system "scales" as more tasks
+are run simultaneously is an effect that the current benchmarks cannot
+explore.
+
+BYTE is working on a future version of the tests that will solve this
+problem.
+
+The tests are synthetic. This quite reasonable argument is based on the fact
+that people don't run benchmarks for a living, they run applications.
+Consequently, the only true measure of a system is how well it performs
+whatever applications you will be running. This, in fact, is the philosophy
+behind the BAPCo benchmarks.
+
+This is not a point with which we would disagree. BYTE regularly makes use
+of a variety of application benchmarks. None of this suggests, however, that
+the BYTEmark benchmarks serve no purpose.
+
+BYTEmark's results should be used as predictors. They can be moved to a new
+platform long before native applications will be ported. The BYTEmark
+benchmarks will therefore provide an early look at the potential of the
+machine. Additionally, the BYTEmark permits you to "home in" on an aspect of
+the overall architecture. How well does the system perform when executing
+floating-point computations? Does its memory architecture help or hinder the
+management of memory buffers that may fall on arbitrary address boundaries?
+How does the cache work with a program whose memory access favors moving
+randomly through memory as opposed to moving sequentially through memory?
+
+The answers to these questions can give you a good idea of how well a system
+would support a particular class of applications. Only a synthetic benchmark
+can give the narrow view necessary to find the answers.
+
+Dynamic Workloads
+
+Our long history of benchmarking has taught us one thing above all others:
+Tomorrow's system will go faster than today's by an amount exceeding your
+wildest guess -- and then some. Dealing with this can become an unending
+race.
+
+It goes like this: You design a benchmark algorithm, you specify its
+parameters (how big the array is, how many loops, etc.), you run it on
+today's latest super-microcomputer, collect your data, and go home. A new
+machine arrives the next day, you run your benchmark, and discover that the
+test executes so quickly that the resolution of the clock routine you're
+using can't keep up with it (i.e., the test is over and done before the
+system clock even has a chance to tick).
+
+If you modify your routine, the figures you collected yesterday are no good.
+If you create a better clock routine by sneaking down into the system
+hardware, you can kiss portability goodbye.
+
+The BYTEmark benchmarks solve this problem by a process we'll refer to as
+"dynamic workload adjustment." In principle, it simply means that if the
+test runs so fast that the system clock can't time it, the benchmark
+increases the test workload -- and keeps increasing it -- until enough time
+is consumed to gather reliable test results.
+
+Here's an example.
+
+The BYTEmark benchmarks perform timing using a "stopwatch" paradigm. The
+routine StartStopwatch() begins timing; StopStopwatch() ends timing and
+reports the elapsed time in clock ticks. Now, "clock ticks" is a value that
+varies from system to system. We'll presume that our test system provides
+1000 clock ticks per second. (We'll also presume that the system actually
+updates its clock 1000 times per second. Surprisingly, some systems don't do
+that. One we know of will tell you that the clock provides 100 ticks per
+second, but updates the clock in 5- or 6-tick increments. The resolution is
+no better than somewhere around 1/18th of a second.) Here, when we say
+"system" we mean not only the computer system, but the environment provided
+by the C compiler. Interestingly, different C compilers for the same system
+will report different clock ticks per second.
+
+Built into the benchmarks is a global variable called GLOBALMINTICKS. This
+variable is the minimum number of clock ticks that the benchmark will allow
+StopStopwatch() to report.
+
+Suppose you run the Numeric Sort benchmark. The benchmark program will
+construct an array filled with random numbers, call StartStopwatch(), sort
+the array, and call StopStopwatch(). If the time reported in StopStopwatch()
+is less than GLOBALMINTICKS, then the benchmark will build two arrays, and
+try again. If sorting two arrays took less time than GLOBALMINTICKS, the
+process repeats with more arrays.
+
+This goes on until the benchmark makes enough work so that an interval
+between StartStopwatch() and StopStopwatch() exceeds GLOBALMINTICKS. Once
+that happens, the test is actually run, and scores are calculated.
+
+Notice that the benchmark didn't make bigger arrays, it made more arrays.
+That's because the time taken by the sort test does not increase linearly as
+the array grows, it increases by a factor of N*log(N) (where N is the size
+of the array).
+
+This principle is applied to all the benchmark tests. A machine with a less
+accurate clock may be forced to sort more arrays at a time, but the results
+are given in arrays per second. In this way fast machines, slow machines,
+machines with accurate clocks, machines with less accurate clocks, can all
+be tested with the same code.
+
+Confidence Intervals
+
+Another built-in feature of the BYTEmark is a set of statistical-analysis
+routines. Running benchmarks is one thing; the question arises as to how
+many times should a test be run until you know you have a good sampling.
+Also, can you determine whether the test is stable (i.e., do results vary
+widely from one execution of the benchmark to the next)?
+
+The BYTEmark keeps score as follows: Each test (a test being a numeric
+sort, a string sort, etc.) is run five times. These five scores are
+averaged, the standard deviation is determined, and a 95% confidence
+half-interval for the mean is calculated (using the student t
+distribution). This tells us that the true average lies -- with a 95%
+probability -- within plus or minus the confidence half-interval of
+the calculated average. If this half-interval is within 5% of the
+calculated average, the benchmarking stops. Otherwise, a new test is
+run and the calculations are repeated with all of the runs done so
+far, including the new one. The benchmark proceeds this way up to a
+total of 30 runs. If the length of the half-interval is still bigger
+than 5% of the calculated average then a warning issued that the
+results might not be statistically certain before the average is
+displayed.
+
+** Fixed a statistical bug here. Uwe F. Mayer
+
+The upshot is that, for each benchmark test, the true average is -- with a
+95% level of confidence -- within 5% of the average reported. Here, the
+"true average" is the average we would get were we able to run the tests
+over and over again an infinite number of times.
+
+This specification ensures that the calculation of results is controlled;
+that someone running the tests in California will use the same technique for
+determining benchmark results as someone running the tests in New York.
+
+In case there is uneven system load due to other processes while this
+benchmark suite executes, it might take longer to run the benchmark suite
+as compared to a run an unloaded system. This is because the benchmark does
+some statistical analysis to make sure that the reported results are
+statistically significant (as explained above), and a high variation in
+individual runs requires more runs to achieve the required statistical
+confidence.
+
+*** added last the paragraph, Uwe F. Mayer
+
+Interpreting Results
+
+Of course, running the benchmarks can present you with a boatload of data.
+It can get mystifying, and some of the more esoteric statistical information
+is valuable only to a limited audience. The big question is: What does it
+all mean?
+
+First, we should point out that the BYTEmark reports both "raw" and indexed
+scores for each test. The raw score for a particular test amounts to the
+"iterations per second" of that test. For example, the numeric sort test
+reports as its raw score the number of arrays it was able to sort per
+second.
+
+The indexed score is the raw score of the system under test divided by the
+raw score obtained on the baseline machine. As of this release, the
+baseline machine is a DELL 90 Mhz Pentium XPS/90 with 16 MB of RAM and 256K
+of external processor cache. (The compiler used was the Watcom C/C++ 10.0
+compiler; optimizations set to "fastest possible code", 4-byte structure
+alignment, Pentium code generation with Pentium register-based calling. The
+operating system was MSDOS.) The indexed score serves to "normalize" the
+raw scores, reducing their dynamic range and making them easier to
+grasp. Simply put, if your machine has an index score of 2.0 on the numeric
+sort test, it performed that test twice as fast as this 90 Mhz Pentium.
+
+If you run all the tests (as you'll see, it is possible to perform "custom
+runs", which execute only a subset of the tests) the BYTEmark will also
+produce two overall index figures: Integer index and Floating-point index.
+The Integer index is the geometric mean of those tests that involve only
+integer processing -- numeric sort, string sort, bitfield, emulated
+floating-point, assignment, Huffman, and IDEA -- while the Floating-point
+index is the geometric mean of those tests that require the floating-point
+coprocessor -- Fourier, neural net, and LU decomposition. You can use these
+scores to get a general feel for the performance of the machine under test
+as compared to the baseline 90 Mhz Pentium.
+
+The Linux/Unix port has a second baseline machine, it is an AMD K6/233 with
+32 MB RAM and 512 KB L2-cache running Linux 2.0.32 and using GNU gcc
+version 2.7.2.3 and libc-5.4.38.  The integer index was split as suggested
+by Andrew D. Balsa <andrewbalsa at usa.net>, and reflects the realization that
+memory management is important in CPU design. The original tests have been
+left alone, however, the geometric mean of the tests NUMERIC SORT, FP
+EMULATION, IDEA, and HUFFMAN now constitutes the integer-arithmetic focused
+benchmark index, while the geometric mean of the tests STRING SORT,
+BITFIELD, and ASSIGNMENT makes up the new memory index. The floating point
+index has been left alone, it is still the geometric mean of FOURIER,
+NEURAL NET, and LU DECOMPOSITION.
+
+*** added the section on Linux, Uwe F. Mayer
+
+What follows is a list of the benchmarks and associated brief remarks that
+describe what the tests do: What they exercise; what a "good" result or a
+"bad" result means. Keep in mind that, in this expanding universe of faster
+processors, bigger caches, more elaborate memory architectures, "good" and
+"bad" are indeed relative terms. A good score on today's hot new processor
+will be a bad score on tomorrow's hot new processor.
+
+These remarks are based on empirical data and profiling that we have done to
+date. (NOTE: The profiling is limited to Intel and Motorola 68K on this
+release. As more data is gathered, we will be refining this section.
+3/14/95--RG)
+
+Benchmark                            Description
+
+Numeric sort                         Generic integer performance.  Should
+                                     exercise non-sequential performance
+                                     of cache (or memory if cache is less
+                                     than 8K).  Moves 32-bit longs at a
+                                     time, so 16-bit processors will be
+                                     at a disadvantage.
+
+
+
+String sort                          Tests memory-move performance.
+                                     Should exercise non-sequential
+                                     performance of cache, with added
+                                     burden that moves are byte-wide and
+                                     can occur on odd address boundaries.
+                                      May tax the performance of
+                                     cell-based processors that must
+                                     perform additional shift operations
+                                     to deal with bytes.
+
+
+
+Bitfield                             Exercises "bit twiddling"
+                                     performance.  Travels through memory
+                                     in a somewhat sequential fashion;
+                                     different from sorts in that data is
+                                     merely altered in place.  If
+                                     properly compiled, takes into
+                                     account 64-bit processors, which
+                                     should see a boost.
+
+
+
+Emulated F.P.                        Past experience has shown this test
+                                     to be a good measurement of overall
+                                     performance.
+
+
+
+Fourier                              Good measure of transcendental and
+                                     trigonometric performance of FPU.
+                                     Little array activity, so this test
+                                     should not be dependent of cache or
+                                     memory architecture.
+
+
+
+Assignment                           The test moves through large integer
+                                     arrays in both row-wise and
+                                     column-wise fashion.  Cache/memory
+                                     with good sequential performance
+                                     should see a boost (memory is
+                                     altered in place -- no moving as in
+                                     a sort operation).   Processing is
+                                     done in 32-bit chunks -- no
+                                     advantage given to 64-bit
+                                     processors.
+
+
+
+Huffman                              A combination of byte operations,
+                                     bit twiddling, and overall integer
+                                     manipulation.  Should be a good
+                                     general measurement.
+
+
+
+IDEA                                 Moves through data sequentially in
+                                     16-bit chunks.  Should provide a
+                                     good indication of raw speed.
+
+
+
+Neural Net                           Small-array floating-point test
+                                     heavily dependent on the exponential
+                                     function; less dependent on overall
+                                     FPU performance.  Small arrays, so
+                                     cache/memory architecture should not
+                                     come into play.
+
+
+
+LU decomposition.                           A floating-point test that moves
+                                     through arrays in both row-wise and
+                                     column-wise fashion.  Exercises only
+                                     fundamental math operations (+, -,
+                                     *, /).
+
+The Command File
+
+Purpose
+
+The BYTEmark program allows you to override many of its default parameters
+using a command file. The command file also lets you request statistical
+information, as well as specify an output file to hold the test results for
+later use.
+
+You identify the command file using a command-line argument. E.G.,
+
+C:NBENCH -cCOMFILE.DAT
+
+tells the benchmark program to read from COMFILE.DAT in the current
+directory.
+
+The content of the command file is simply a series of parameter names and
+values, each on a single line. The parameters control internal variables
+that are either global in nature (i.e., they effect all tests in the
+program) or are specific to a given benchmark test.
+
+The parameters are listed in a reference guide that follows, arranged in the
+following groups:
+
+Global Parameters
+
+Numeric Sort
+
+String Sort
+
+Bitfield
+
+Emulated floating-point
+
+Fourier coefficients
+
+Assignment algorithm
+
+IDEA encryption
+
+Huffman compression
+
+Neural net
+
+LU decomposition
+
+As mentioned above, those items listed under "Global Parameters" affect all
+tests; the rest deal with specific benchmarks. There is no required ordering
+to parameters as they appear in the command file. You can specify them in
+any sequence you wish.
+
+You should be judicious in your use of a command file. Some parameters will
+override the "dynamic workload" adjustment that each test performs. Doing
+this completely bypasses the benchmark code that is designed to produce an
+accurate reading from your system clock. Other parameters will alter default
+settings, yielding test results that cannot be compared with published
+benchmark results.
+
+A Sample Command File
+
+Suppose you built a command file that contained the following:
+
+ALLSTATS=T
+
+CUSTOMRUN=T
+
+OUTFILE=D:\DATA.DAT
+
+DONUMSORT=T
+
+DOLU=T
+
+Here's what this file tells the benchmark program:
+
+ALLSTATS=T means that you've requested a "dump" of all the statistics the
+test gathers. This includes not only the standard deviations of tests run,
+it also produces test-specific information such as the number of arrays
+built, the array size, etc.
+
+CUSTOMRUN=T tells the system that this is a custom run. Only tests
+explicitly specified will be executed.
+
+OUTFILE=D:\DATA.DAT will write the output of the benchmark to the file
+DATA.DAT on the root of the D: drive. (If DATA.DAT already exists, output
+will be appended to the file.)
+
+DONUMSORT=T tells the system to run the numeric sort benchmark. (This was
+necessary on account of the CUSTOMRUN=T line, above.)
+
+DOLU=T tells the system to run the LU decomposition benchmark.
+
+Command File Parameters Reference
+
+(NOTE: Altering some global parameters can invalidate results for comparison
+purposes. Those parameters are indicated in the following section by a bold
+asterisk (*). If you alter any parameters so indicated, you may NOT publish
+the resulting data as BYTEmark scores.)
+
+Global Parameters
+
+GLOBALMINTICKS=<n>
+
+This overrides the default global_min_ticks value (defined in NBENCH1.H).
+The global_min_ticks value is defined as the minimum number of clock ticks
+per iteration of a particular benchmark. For example, if global_min_ticks is
+set to 100 and the numeric sort benchmark is run; each iteration MUST take
+at least 100 ticks, or the system will expand the work-per-iteration.
+
+MINSECONDS=<n>
+
+Sets the minimum number of seconds any particular test will run. This has
+the effect of controlling the number of repetitions done. Default: 5.
+
+ALLSTATS=<T|F>
+
+Set this flag to T for a "dump" of all statistics. The information displayed
+varies from test to test. Default: F.
+
+OUTFILE=<path>
+
+Specifies that output should go to the specified output file. Any test
+results and statistical data displayed on-screen will also be written to the
+file. If the file does not exist, it will be created; otherwise, new output
+will be appended to an existing file. This allows you to "capture" several
+runs into a single file for later review.
+
+Note: the path should not appear in quotes. For example, something like the
+following would work: OUTFILE=C:\BENCH\DUMP.DAT
+
+CUSTOMRUN=<T|F>
+
+Set this flag to T for a custom run. A "custom run" means that the program
+will run only the benchmark tests that you explicitly specify. So, use this
+flag to run a subset of the tests. Default: F.
+
+Numeric Sort
+
+DONUMSORT=<T|F>
+
+Indicates whether to do the numeric sort. Default is T, unless this is a
+custom run (CUSTOMRUN=T), in which case default is F.
+
+NUMNUMARRAYS=<n>
+
+Indicates the number of numeric arrays the system will build. Setting this
+value will override the program's "dynamic workload" adjustment for this
+test.*
+
+NUMARRAYSIZE=<n>
+
+Indicates the number of elements in each numeric array. Default is 8001
+entries. (NOTE: Altering this value will invalidate the test for comparison
+purposes. The performance of the numeric sort test is not related to the
+array size as a linear function; i.e., an array twice as big will not take
+twice as long. The relationship involves a logarithmic function.)*
+
+NUMMINSECONDS=<n>
+
+Overrides MINSECONDS for the numeric sort test.
+
+String Sort
+
+DOSTRINGSORT=<T|F>
+
+Indicates whether to do the string sort. Default is T, unless this is a
+custom run (CUSTOMRUN=T), in which case the default is F.
+
+STRARRAYSIZE=<n>
+
+Sets the size of the string array. Default is 8111. (NOTE: Altering this
+value will invalidate the test for comparison purposes. The performance of
+the string sort test is not related to the array size as a linear function;
+i.e., an array twice as big will not take twice as long. The relationship
+involves a logarithmic function.)*
+
+NUMSTRARRAYS=<n>
+
+Sets the number of string arrays that will be created to run the test.
+Setting this value will override the program's "dynamic workload" adjustment
+for this test.*
+
+STRMINSECONDS=<n>
+
+Overrides MINSECONDS for the string sort test.
+
+Bitfield
+
+DOBITFIELD=<T|F>
+
+Indicates whether to do the bitfield test. Default is T, unless this is a
+custom run (CUSTOMRUN=T), in which case the default is F.
+
+NUMBITOPS=<n>
+
+Sets the number of bitfield operations that will be performed. Setting this
+value will override the program's "dynamic workload" adjustment for this
+test.*
+
+BITFIELDSIZE=<n>
+
+Sets the number of 32-bit elements in the bitfield arrays. The default value
+is dependent on the size of a long as defined by the current compiler. For a
+typical compiler that defines a long to be 32 bits, the default is 32768.
+(NOTE: Altering this parameter will invalidate test results for comparison
+purposes.)*
+
+BITMINSECONDS=<n>
+
+Overrides MINSECONDS for the bitfield test.
+
+Emulated floating-point
+
+DOEMF=<T|F>
+
+Indicates whether to do the emulated floating-point test. Default is T,
+unless this is a custom run (CUSTOMRUN=T), in which case the default is F.
+
+EMFARRAYSIZE=<n>
+
+Sets the size (number of elements) of the emulated floating-point benchmark.
+Default is 3000. The test builds three arrays, each of equal size. This
+parameter sets the number of elements for EACH array. (NOTE: Altering this
+parameter will invalidate test results for comparison purposes.)*
+
+EMFLOOPS=<n>
+
+Sets the number of loops per iteration of the floating-point test. Setting
+this value will override the program's "dynamic workload" adjustment for
+this test.*
+
+EMFMINSECONDS=<n>
+
+Overrides MINSECONDS for the emulated floating-point test.
+
+Fourier coefficients
+
+DOFOUR=<T|F>
+
+Indicates whether to do the Fourier test. Default is T, unless this is a
+custom run (CUSTOMRUN=T), in which case the default is F.
+
+FOURASIZE=<n>
+
+Sets the size of the array for the Fourier test. This sets the number of
+coefficients the test will derive. NOTE: Specifying this value will override
+the system's "dynamic workload" adjustment for this test, and may make the
+results invalid for comparison purposes.*
+
+FOURMINSECONDS=<n>
+
+Overrides MINSECONDS for the Fourier test.
+
+Assignment Algorithm
+
+DOASSIGN=<T|F>
+
+Indicates whether to do the assignment algorithm test. Default is T, unless
+this is a custom run (CUSTOMRUN=T), in which case the default is F.
+
+ASSIGNARRAYS=<n>
+
+Indicates the number of arrays that will be built for the test. Specifying
+this value will override the system's "dynamic workload" adjustment for this
+test. (NOTE: The size of the arrays in the assignment algorithm is fixed at
+101 x 101. Altering the array size requires adjusting global constants and
+recompiling; to do so, however, would invalidate test results.)*
+
+ASSIGNMINSECONDS=<n>
+
+Overrides MINSECONDS for the assignment algorithm test.
+
+IDEA encryption
+
+DOIDEA=<T|F>
+
+Indicates whether to do the IDEA encryption test. Default is T, unless this
+is a custom run (CUSTOMRUN=T), in which case the default is F.
+
+IDEAARRAYSIZE=<n>
+
+Sets the size of the plain-text character array that will be encrypted by the
+test. Default is 4000. The benchmark actually builds 3 arrays: 1st
+plain-text, encrypted version, and 2nd plain-text. The 2nd plain-text array is
+the destination for the decryption process [part of the test]. All arrays
+are set to the same size. (NOTE: Specifying this value will invalidate test
+results for comparison purposes.)*
+
+IDEALOOPS=<n>
+
+Indicates the number of loops in the IDEA test. Specifying this value will
+override the system's "dynamic workload" adjustment for this test.*
+
+IDEAMINSECONDS=<n>
+
+Overrides MINSECONDS for the IDEA test.
+
+Huffman compression
+
+DOHUFF=<T|F>
+
+Indicates whether to do the Huffman test. Default is T, unless this is a
+custom run (CUSTOMRUN=T), in which case the default is F.
+
+HUFFARRAYSIZE=<n>
+
+Sets the size of the string buffer that will be compressed using the Huffman
+test. The default is 5000. (NOTE: Altering this value will invalidate test
+results for comparison purposes.)*
+
+HUFFLOOPS=<n>
+
+Sets the number of loops in the Huffman test. Specifying this value will
+override the system's "dynamic workload" adjustment for this test.*
+
+HUFFMINSECONDS=<n>
+
+Overrides MINSECONDS for the Huffman test.
+
+Neural net
+
+DONNET=<T|F>
+
+Indicates whether to do the Neural Net test. Default is T, unless this is a
+custom run (CUSTOMRUN=T), in which case the default is F.
+
+NNETLOOPS=<n>
+
+Sets the number of loops in the Neural Net test. NOTE: Altering this value
+overrides the benchmark's "dynamic workload" adjustment algorithm, and may
+invalidate the results for comparison purposes.*
+
+NNETMINSECONDS=<n>
+
+Overrides MINSECONDS for the Neural Net test.
+
+LU decomposition
+
+DOLU=<T|F>
+
+Indicates whether to do the LU decomposition test. Default is T, unless this
+is a custom run (CUSTOMRUN=T), in which case the default is F.
+
+LUNUMARRAYS=<n>
+
+Sets the number of arrays in each iteration of the LU decomposition test.
+Specifying this value will override the system's "dynamic workload"
+adjustment for this test.*
+
+LUMINSECONDS=<n>
+
+Overrides MINSECONDS for the LU decomposition test.
+
+Numeric Sort
+
+Description
+
+This benchmark is designed to explore how well the system sorts a numeric
+array. In this case, a numeric array is a one-dimensional collection of
+signed, 32-bit integers. The actual sorting is performed by a heapsort
+algorithm (see the text box following for a description of the heapsort
+algorithm).
+
+It's probably unnecessary to point out (but we'll do it anyway) that sorting
+is a fundamental operation in computer application software. You'll likely
+find sorting routines nestled deep inside a variety of applications;
+everything from database systems to operating-systems kernels.
+
+The numeric sort benchmark reports the number of arrays it was able to sort
+per second. The array size is set by a global constant (it can be overridden
+by the command file -- see below).
+
+Analysis
+
+Optimized 486 code: Profiling of the numeric sort benchmark using Watcom's
+profiler (Watcom C/C++ 10.0) indicates that the algorithm spends most of its
+time in the numsift() function (specifically, about 90% of the benchmark's
+time takes place in numsift()). Within numsift(), two if statements dominate
+time spent:
+
+if(array[k]<array[k+1L]) and if(array[i]<array[k])
+
+Both statements involve indexes into arrays, so it's likely the processor is
+spending a lot of time resolving the array references. (Though both
+statements involve "less-than" comparisons, we doubt that much time is
+consumed in performing the signed compare operation.) Though the first
+statement involves array elements that are adjacent to one another, the
+second does not. In fact, the second statement will probably involve
+elements that are far apart from one another during early passes through the
+sifting process. We expect that systems whose caching system pre-fetches
+contiguous elements (often in "burst" line fills) will not have any great
+advantage of systems without pre-fetch mechanisms.
+
+Similar results were found when we profiled the numeric sort algorithm under
+the Borland C/C++ compiler.
+
+680x0 Code (Macintosh CodeWarrior): CodeWarrior's profiler is function
+based; consequently, it does not allow for line-by-line analysis as does the
+Watcom compiler's profiler.
+
+However, the CodeWarrior profiler does give us enough information to note
+that NumSift() only accounts for about 28% of the time consumed by the
+benchmark. The outer routine, NumHeapSort() accounts for around 71% of the
+time taken. It will require additional analysis to determine why the two
+compilers -- Watcom and CodeWarrior divide the workload so differently. (It
+may have something to do with compiler architecture, or the act of profiling
+the code may produce results that are significantly different than how the
+program runs under normal conditions, though that would lead one to wonder
+what use profilers would be.)
+
+Porting Considerations
+
+The numeric sort routine should represent a trivial porting exercise. It is
+not an overly large benchmark in terms of source code. Additionally, the
+only external routines it calls on are for allocating and releasing memory,
+and managing the stopwatch.
+
+The numeric sort benchmark depends on the following global definitions (note
+that these may be overridden by the command file):
+
+NUMNUMARRAYS -- Sets the upper limit on the number of arrays that the
+benchmark will attempt to build. The numeric sort benchmark creates work for
+itself by requiring the system to sort more and more arrays...not bigger and
+bigger arrays. (The latter case would skew results, because the sorting time
+for heapsort is N log2 N - e.g., doubling the array size does not double the
+sort time.) This constant sets the upper limit to the number of arrays the
+system will build before it signals an error. The default value is 100, and
+may be changed if your system exceeds this limit.
+
+NUMARRAYSIZE - Determines the size of each array built. It has been set to
+8111L and should not be tampered with. The command file entry
+NUMARRAYSIZE=<n> can be used to change this value, but results produced by
+doing this will make your results incompatible with other runs of the
+benchmark (since results will be skewed -- see preceding paragraph).
+
+To test for a correct execution of the numeric sort benchmark, #define the
+DEBUG symbol. This will enable code that verifies that arrays are properly
+sorted. You should run the benchmark program using a command file that has
+only the numeric sort test enabled. If there is an error, the program will
+display "SORT ERROR" (If this happens, it's possible that tons of "SORT
+ERROR" messages will be emitted, so it's best not to redirect output to a
+file), otherwise it will print "Numeric sort: OK" (also quite a few times).
+
+References
+
+Gonnet, G.H. 1984, Handbook of Algorithms and Data Structures (Reading, MA:
+Addison-Wesley).
+
+Knuth, Donald E. 1968, Fundamental Algorithms, vol 1 of The Art of Computer
+Programming (Reading, MA: Addison-Wesley).
+
+Press, William H., Flannery, Brian P., Teukolsky, Saul A., and Vetterling,
+William T. 1989, Numerical Recipes in Pascal (Cambridge: Cambridge
+University Press).
+
+Heapsort
+
+The heapsort algorithm is well-covered in a number of the popular
+computer-science textbooks. In fact, it gets a pat on the back in Numerical
+Recipes (Press et. al.), where the authors write:
+
+Heapsort is our favorite sorting routine. It can be recommended
+wholeheartedly for a variety of sorting applications. It is a true
+"in-place" sort, requiring no auxiliary storage.
+
+Heapsort works by building the array into a kind of a queue called a heap.
+You can imagine this heap as being a form of in-memory binary tree. The
+topmost (root) element of the tree is the element that -- were the array
+sorted -- would be the largest element in the array. Sorting takes place by
+first constructing the heap, then pulling the root off the tree, promoting
+the next largest element to the root, pulling it off, and so on. (The
+promotion process is known as "sifting up.")
+
+Heapsort executes in N log2 N time even in its worst case. Unlike some other
+sorting algorithms, it does not benefit from a partially sorted array
+(though Gonnet does refer to a variation of heapsort, called "smoothsort,"
+which does -- see references).
+
+String Sort
+
+Description
+
+This benchmark is designed to gauge how well the system moves bytes around.
+By that we mean, how well the system can copy a string of bytes from one
+location to another; source and destination being aligned to arbitrary
+addresses. (This is unlike the numeric sort array, which moves bytes
+longword-at-a-time.) The strings themselves are built so as to be of random
+length, ranging from no fewer than 4 bytes and no greater than 80 bytes. The
+mixture of random lengths means that processors will be forced to deal with
+strings that begin and end on arbitrary address boundaries.
+
+The string sort benchmark uses the heapsort algorithm; this is the same
+algorithm as is used in the numeric sort benchmark (see the sidebar on the
+heapsort for a detailed description of the algorithm).
+
+Manipulation of the strings is actually handled by two arrays. One array
+holds the strings themselves; the other is a pointers array. Each member of
+the pointers array carries an offset that points into the string array, so
+that the ith pointer carries the offset to the ith string. This allows the
+benchmark to rapidly locate the position of the ith string. (The sorting
+algorithm requires exchanges of items that might be "distant" from one
+another in the array. It's critical that the routine be able to rapidly find
+a string based on its indexed position in the array.)
+
+The string sort benchmark reports the number of string arrays it was able to
+sort per second. The size of the array is set by a global constant.
+
+Analysis
+
+Optimized 486 code (Watcom C/C++ 10.0): Profiling of the string sort
+benchmark indicates that it spends most of its time in the C library routine
+memmove(). Within that routine, most of the execution is consumed by a pair
+of instructions: rep movsw and rep movsd. These are repeated string move --
+word width and repeated string move -- doubleword width, respectively.
+
+This is precisely where we want to see the time spent. It's interesting to
+note that the memmove() of the particular compiler/profiler tested (Watcom
+C/C++ 10.0) was "smart" enough to do most of the moving on word or
+doubleword boundaries. The string sort benchmark specifically sets arbitrary
+boundaries, so we'd expect to see lots of byte-wide moves. The "smart"
+memmove() is able to move bytes only when it has to, and does the remainder
+of the work via words and doublewords (which can move more bits at a time).
+
+680x0 Code (Macintosh CodeWarrior): Because CodeWarrior's profiler is
+function based, it is impossible to get an idea of how much time the test
+spends in library routines such as memmove(). Fortunately, as an artifact of
+the early version of the benchmark, the string sort algorithm makes use of
+the MoveMemory() routine in the sysspec.c file (system specific routines).
+This call, on anything other than a 16-bit DOS system, calls memmove()
+directly. Hence, we can get a good approximation of how much time is spent
+moving bytes.
+
+The answer is that nearly 78% of the benchmark's time is consumed by
+MoveMemory(), the rest being taken up by the other routines (the
+str_is_less() routine, which performs string comparisons, takes about 7% of
+the time). As above, we can guess that most of the benchmark's time is
+dependent on the performance of the library's memmove() routine.
+
+Porting Considerations
+
+As with the numeric sort routine, the string sort benchmark should be simple
+to port. Simpler, in fact. The string sort benchmark routine is not
+dependent on any typedef that may change from machine to machine (unless a
+char type is not 8 bits).
+
+The string sort benchmark depends on the following global definitions:
+
+NUMSTRARRAYS - Sets the upper limit on the number of arrays that the
+benchmark will attempt to build. The string sort benchmark creates work for
+itself by requiring the system to sort more and more arrays, not bigger and
+bigger arrays. (See section on Numeric Sort for an explanation.) This
+constant sets the upper limit to the number of arrays the system will build
+before it signals an error. The default value is 100, and may be changed if
+your system exceeds this limit.
+
+STRARRAYSIZE - Sets the default size of the string arrays built. We say
+"arrays" because, as with the numeric sort benchmark, the system adds work
+not by expanding the size of the array, but by adding more arrays. This
+value is set to 8111, and should not be modified, since results would not be
+comparable with other runs of the same benchmark on other machines.
+
+To test for a correct execution of the string sort benchmark, #define
+the DEBUG symbol. This will enable code that verifies the arrays are
+properly sorted. Set up a command file that runs only the string sort,
+and execute the benchmark program. If the routine is operating
+properly, the benchmark will print "String sort: OK", this message is
+printed quite often. Otherwise, the program will display "SORT ERROR"
+for each pair of strings it finds out of order (which can be really
+often).
+
+References
+
+See the references for the Numeric Sort benchmark.
+
+Bitfield Operations
+
+Description
+
+The purpose of this benchmark is to explore how efficiently the system
+executes operations that deal with "twiddling bits." The test is set up to
+simulate a "bit map"; a data structure used to keep track of storage usage.
+(Don't confuse this meaning of "bitmap" with its use in describing a
+graphics data structure.)
+
+Systems often use bit maps to keep an inventory of memory blocks or (more
+frequently) disk blocks. In the case of a bit map that manages disk usage,
+an operating system will set aside a buffer in memory so that each bit in
+that buffer corresponds to a block on the disk drive. A 0 bit means that the
+corresponding block is free; a 1 bit means the block is in use. Whenever a
+file requests a new block of disk storage, the operating system searches the
+bit map for the first 0 bit, sets the bit (to indicate that the block is now
+spoken for), and returns the number of the corresponding disk block to the
+requesting file.
+
+These types of operations are precisely what this test simulates. A block of
+memory is set allocated for the bit map. Another block of memory is
+allocated, and set up to hold a series of "bit map commands". Each bitmap
+command tells the simulation to do 1 of 3 things:
+
+1) Clear a series of consecutive bits,
+
+2) Set a series of consecutive bits, or
+
+3) Complement (1->0 and 0->1) a series of consecutive bits.
+
+The bit map command block is loaded with a set of random bit map commands
+(each command covers an random number of bits), and simulation routine steps
+sequentially through the command block, grabbing a command and executing it.
+
+The bitfield benchmark reports the number of bits it was able to operate on
+per second. The size of the bit map is constant; the bitfield operations
+array is adjusted based on the capabilities of the processor. (See the
+section describing the auto-adjust feature of the benchmarks.)
+
+Analysis
+
+Optimized 486 code: Using the Watcom C/C++ 10.0 profiler, the Bitfield
+benchmark appears to spend all of its time in two routines: ToggleBitRun()
+(74% of the time) and DoBitFieldIteration() (24% of the time). We say
+"appears" because this is misleading, as we will explain.
+
+First, it is important to recall that the test performs one of three
+operations for each run of bits (see above). The routine ToggleBitRun()
+handles two of those three operations: setting a run of bits and clearing a
+run of bits. An if() statement inside ToggleBitRun() decides which of the
+two operations is performed. (Speed freaks will quite rightly point out that
+this slows the entire algorithm. ToggleBitRun() is called by a switch()
+statement which has already decided whether bits should be set or cleared;
+it's a waste of time to have ToggleBitRun() have to make that decision yet
+again.)
+
+DoBitFieldIteration() is the "outer" routine that calls ToggleBitRun().
+DoBitFieldIteration() also calls FlipBitRun(). This latter routine is the
+one that performs the third bitfield operation: complementing a run of bits.
+FlipBitRun() gets no "air time" at all (while DoBitFieldIteration() gets 24
+% of the time) simply because the compiler's optimizer recognizes that
+FlipBitRun() is only called by DoBitFieldIteration(), and is called only
+once. Consequently, the optimizer moves FlipBitRun() "inline", i.e., into
+DoBitFieldIteration(). This removes an unnecessary call/return cycle (and is
+probably part of the reason why the FlipBitRun() code gets 24% of the
+algorithm's time, instead of something closer to 30% of its time.)
+
+Within the routines, those lines of code that actually do the shifting, the
+and operations, and the or operations, consume time evenly. This should make
+for a good test of a processor's "bit twiddling" capabilities.
+
+680x0 Code (Macintosh CodeWarrior): The CodeWarrior profiler is function
+based. Consequently, it is impossible to produce a profile of machine
+instruction execution time. We can, however, get a good picture of how the
+algorithm divides its time among the various functions.
+
+Unlike the 486 compiler, the CodeWarrior compiler did not appear to collapse
+the FlipBitRun() routine into the outer DoBitFieldIteration() routine. (We
+don't know this for certain, of course. It's possible that the compiler
+would have done this had we not been profiling.)
+
+In any case, the time spent in the two "core" routines of the bitfield test
+are shown below:
+
+FlipBitRun() - 18031.2 microsecs (called 509 times)
+
+ToggleBitRun() - 50770.6 microsecs (called 1031 times)
+
+In terms of total time, FlipBitRun() takes about 35% of the time (it gets
+about 33% of the calls). Remember, ToggleBitRun() is a single routine that
+is called both to set and clear bits. Hence, ToggleBitRun() is called twice
+as often as FlipBitRun().
+
+We can conclude that time spent setting bits to 1, setting bits to 0, and
+changing the state of bits, is about equal; the load is balanced close to
+what we'd expect it to be, based on the structure of the algorithm.
+
+Porting Considerations
+
+The bitfield operations benchmark is dependent on the size of the long
+datatype. On most systems, this is 32 bits. However, on some of the newer
+RISC chips, a long can be 64 bits long. If your system does use 64-bit
+longs, you'll need to #define the symbol LONG64.
+
+If you are unsure of the size of a long in your system (some C compiler
+manuals make it difficult to discover), simply place an ALLSTATS=T line in
+the command file and run the benchmarks. This will cause the benchmark
+program to display (among other things) the size of the data types int,
+short, and long in bytes.
+
+BITFARRAYSIZE - Sets the number of longs in the bit map array. This number
+is fixed, and should not be altered. The bitfield test adjusts itself by
+adding more bitfield commands (see above), not by creating a larger bit map.
+
+Currently, there is no code added to test for correct execution. If you are
+concerned that your port was incorrect, you'll need to step through your
+favorite debugger and verify execution against the original source code.
+
+** I added a resetting of the random number generator, and a resetting
+** of the bitfield to each loop. Those operations are outside of the
+** timed loop, and should add to make the benchmark more consistent.
+** There also is now debugging information available. If you define
+** DEBUG then the program will write a file named "debugbit.dat",
+** which is the contents of the bitfield after the calibration loop of
+** 30 operations. You can compare this file with the file
+** "debugbit.good" that comes with the distribution.
+** Uwe F. Mayer <mayer at tux.edu>
+
+References
+
+None.
+
+Emulated Floating-point
+
+Description
+
+The emulated floating-point benchmark includes routines that are similar to
+those that would be executed whenever a system performs floating-point
+operations in the absence of a coprocessor. In general, this amounts to a
+mixture of integer instructions, including shift operations, integer
+addition and subtraction, and bit testing (among others).
+
+The benchmark itself is remarkably simple. The test builds three
+1-dimensional arrays and loads the first two up with random floating-point
+numbers. The arrays are then partitioned into 4 equal-sized groups, and the
+test proceeds by performing addition, subtraction, multiplication, and
+division -- one operation on each group. (For example, for the addition
+group, an element from the first array is added to the second array and the
+result is placed in the third array.)
+
+Of course, most of the work takes place inside the routines that perform the
+addition, subtraction, multiplication, and division. These routines operate
+on a special data type (referred to as an InternalFPF number) that -- though
+not strictly IEEE compliant -- carries all the necessary data fields to
+support an IEEE-compatible floating-point system. Specifically, an
+InternalFPF number is built up of the following fields:
+
+Type (indicates a NORMAL, SUBNORMAL, etc.)
+
+Mantissa sign
+
+Unbiased, signed 16-bit exponent
+
+4-word (16 bits) mantissa.
+
+The emulated floating-point test reports its results in number of loops per
+second (where a "loop" is one pass through the arrays as described above).
+
+Finally, we are aware that this test could be on its way to becoming an
+anachronism. A growing number of systems are appearing that have
+coprocessors built into the main CPU. It's possible that floating-point
+emulation will one day be a thing of the past.
+
+Analysis
+
+Optimized 486 code (Watcom C/C++ 10.0): The algorithm's time is distributed
+across a number of routines. The distribution is:
+
+ShiftMantLeft1() - 60% of the time
+
+ShiftMantRight1() - 17% of the time
+
+DivideInternalFPF() - 14% of the time
+
+MultiplyInternalFPF() - 5% of the time.
+
+The first two routines are similar to one another; both shift bits about in
+a floating-point number's mantissa. It's reasonable that ShiftMantLeft1()
+should take a larger share of the system's time; it is called as part of the
+normalization process that concludes every emulated addition, subtraction,
+mutiplication, and division.
+
+680x0 Code (Macintosh CodeWarrior): CodeWarrior's profiler is
+function-based; consequently, it isn't possible to get timing at the machine
+instruction level. However, the output to CodeWarrior's profiler has
+provided insight into the breakdown of time spent in various functions that
+forces us to rethink our 486 code analysis.
+
+Analyzing what goes on inside the emulated floating-point tests is a tough
+one to call because some of the routines that are part of the test are
+called by the function that builds the arrays. Consequently, a quick look at
+the profiler's output can be misleading; it's not obvious how much time a
+particular routine is spending in the test and how much time that same
+routine is spending setting up the test (an operation that does not get
+timed).
+
+Specifically, the routine that loads up the arrays with test data calls
+LongToInternalFPF() and DivideInternalFPF(). LongToInternalFPF() makes one
+call to normalize() if the number is not a true zero. In turn, normalize()
+makes an indeterminate number of calls to ShiftMantLeft1(), depending on the
+structure of the mantissa being normalized.
+
+What's worse, DivideInternalFPF() makes all sorts of calls to all kinds of
+important low-level routines such as Sub16Bits() and ShiftMantLeft1().
+Untangling the wiring of which routine is being called as part of the test,
+and which is being called as part of the setup could probably be done with
+the computer equivalent of detective work and spelunking, but in the
+interest of time we'll opt for approximation.
+
+Here's a breakdown of some of the important routines and their times:
+
+AddSubInternalFPF() - 1003.9 microsecs (called 9024 times)
+
+MultiplyInternalFPF() - 20143 microsecs (called 5610 times)
+
+DivideInternalFPF() - 18820.9 microsecs (called 3366 times).
+
+The 3366 calls to DivideInternalFPF() are timed calls, not setup calls --
+the profiler at least gives outputs of separate calls made to the same
+routine, so we can determine which call is being made by the benchmark, and
+which is being made by the setup routine. It turns out that the setup
+routine calls DivideInternalFPF() 30,000 times.
+
+Notice that though addition/subtraction are called most often,
+multiplication next, then finally division; the time spent in each is the
+reverse. Division takes the most time, then multiplication, finally
+addition/subtraction. (There's probably some universal truth lurking here
+somewhere, but we haven't found it yet.)
+
+Other routines, and their breakdown:
+
+Add16Bits() - 115.3 microsecs
+
+ShiftMantRight1() - 574.2 microsecs
+
+Sub16Bits() - 1762 microsecs
+
+StickySiftRightMant - 40.4 microsecs
+
+ShiftMantLeft1() - 17486.1 microsecs
+
+The times for the last three routines are suspect, since they are called by
+DivideInternalFPF(), and a large portion of their time could be part of the
+setup process. This is what leads us to question the results obtained in the
+486 analysis, since it, too, is unable to determine precisely who is calling
+whom.
+
+Porting Considerations
+
+Earlier versions of this benchmark were extremely sensitive to porting;
+particularly to the "endianism" of the target system. We have tried to
+eliminate many of these problems. The test is nonetheless more "sensitive"
+to porting than most others.
+
+Pay close attention to the following defines and typedefs. They can be found
+in the files EMFLOAT.H, NMGLOBAL.H, and NBENCH1.H:
+
+u8 - Stands for unsigned, 8-bit. Usually defined to be unsigned char.
+
+u16 - Stands for unsigned, 16-bit. Usually defined to be unsigned short.
+
+u32 - Stands for unsigned, 32-bit. Usually defined to be unsigned long.
+
+INTERNAL_FPF_PRECISION - Indicates the number of elements in the mantissa of
+an InternalFPF number. Should be set to 4.
+
+The exponent field of an InternalFPF number is of type short. It should be
+set to whatever minimal data type can hold a signed, 16-bit number.
+
+Other global definitions you will want to be aware of:
+
+CPUEMFLOATLOOPMAX - Sets the maximum number of loops the benchmark will
+attempt before flagging an error. Each execution of a loop in the emulated
+floating-point test is "non-destructive," since the test takes factors from
+two arrays, operates on the factors, and places the result in a third array.
+Consequently, the test makes more work for itself by increasing the number
+of times it passes through the arrays (# of loops). If the system exceeds
+the limit set by CPUEMFLOATLOOPMAX, it will signal an error.
+
+This value may be altered to suit your system; it will not effect the
+benchmark results (unless you reduce it so much the system can never
+generate enough loops to produce a good test run).
+
+EMFARRAYSIZE - Sets the size of the arrays to be used in the test. This
+value is the number of entries (InternalFPF numbers) per array. Currently,
+the number is fixed at 3000, and should not be altered.
+
+Currently, there is no means of testing correct execution of the benchmark
+other than via debugger. There are routines available to decode the internal
+floating point format and print out the numbers, but no formal correctness
+test has been constructed. (This should be available soon. -- 3/14/95 RG)
+
+** It now prints out the operations of 8 of the entries used in the
+** test. Assuming you leave EMFARRAYSIZE at 3000, your results should
+** look like the ones below. The number in front of the colon is the
+** index of the entry.
+**  
+**  	 2: (-1.1160E   0) + (-4.5159E   0) = -5.6320E   0
+**  	 6: (-4.4507E  -1) - (-8.2050E  -1) = +3.7543E  -1
+**  	10: (+1.2465E   0) * (+7.4667E  -1) = +9.3075E  -1
+**  	14: (-1.2781E   0) / (-1.7367E   0) = +7.3596E  -1
+**    2986: (-7.0390E   0) * (-2.0752E   0) = +1.4607E   1
+**    2990: (+8.3753E  -1) / (+2.3876E   1) = +3.5078E  -2
+**    2994: (-1.1393E   0) + (-1.6080E   1) = -1.7219E   1
+**    2998: (+7.2450E   0) - (-8.2654E  -1) = +8.0716E   0
+**
+** Uwe F. Mayer <mayer at tux.edu>
+
+References
+
+Microprocessor Programming for Computer Hobbyists, Neill Graham, Tab Books,
+Blue Ridge Summit, PA, 1977.
+
+Apple Numerica Manual, Second edition, Apple Computer, Addison-Wesley
+Publishing Co., Reading, MA, 1988.
+
+Fourier Series
+
+Description
+
+This is a floating-point benchmark designed primarily to exercise the
+trigonometric and transcendental functions of the system. It calculates the
+first n Fourier coefficients of the function (x+1)x on the interval 0,2. In
+this case, the function (x+1)x is being treated as a cyclic waveform with a
+period of 2.
+
+The Fourier coefficients, when applied as factors to a properly constructed
+series of sine and cosine functions, allow you to approximate the original
+waveform. (In fact, if you can calculate all the Fourier coefficients --
+there'll be an infinite number -- you can reconstruct the waveform exactly).
+You have to calculate the coefficients via integration, and the algorithm
+does this using a simple trapezoidal rule for its numeric integration
+function.
+
+The upshot of all this is that it provides an exercise for the
+floating-point routines that calculate sine, cosine, and raising a number to
+a power. There are also some floating-point multiplications, divisions,
+additions, and subtractions mixed in.
+
+The benchmark reports its results as the number of coefficients calculated
+per second.
+
+As an additional note, we should point out that the performance of this
+benchmark is heavily dependent on how well-built the compiler's math library
+is. We have seen at least two cases where recompilation with new (and
+improved!) math libraries have resulted in two-fold and five-fold
+performance improvements. (Apparently, when a compiler gets moved to a new
+platform, the trigonometric and transcendental functions in the math
+libraries are among the last routines to be "hand optimized" for the new
+platform.) About all we can say about this is that whenever you run this
+test, verify that you have the latest and greatest math libraries.
+
+Analysis
+
+Optimized 486 code: The benchmark partitions its time almost evenly among
+the modules pow387, exp386, and trig387; giving between 25% and 28% of its
+time to each. This is based on profiling with the Watcom compiler running
+under Windows NT. These modules hold the routines that handle raising a
+number to a power and performing trigonometric (sine and cosine)
+calculations. For example, within trig387, time was nearly equally divided
+between the routine that calculates sine and the routine that calculates
+cosine.
+
+The remaining time (between 17% and 18%) was spent in the balance of the
+test. We noticed that most of that time occurred in the routine
+thefunction(). This is at the heart of the numerical integration routine the
+benchmark uses.
+
+Consequently, this benchmark should be a good test of the exponential and
+trigonometric capabilities of a processor. (Note that we recognize that the
+performance also depends on how well the compiler's math library is built.)
+
+680x0 Code (Macintosh CodeWarrior): The CodeWarrior profiler is function
+based, therefore it is impossible to get performance results for individual
+machine instructions. The CodeWarrior compiler is also unable to tell us how
+much time is spent within a given library routine; we can't see how much
+time gets spent executing the sin(), cos(), or pow() functions (which,
+unfortunately, was the whole idea behind the benchmark).
+
+About all we can glean from the results is that thefunction() takes about
+74% of the time in the test (this is where the heavy math calculations take
+place) while trapezoidintegrate() accounts for about 26% of the time on its
+own.
+
+Porting Considerations
+
+Necessarily, this benchmark is at the mercy of the efficiency of the
+floating-point support provided by whatever compiler you are using. It is
+recommended that, if you are doing the port yourself, you contact the
+designers of the compiler, and discuss with them what optimization switches
+should be set to produce the fastest code. (This sounds simple; usually it's
+not. Some systems let you decide between speed and true IEEE compliance.)
+
+As far as global definitions go, this benchmark is happily free of them. All
+the math is done using double data types. We have noticed that, on some Unix
+systems, you must be careful to include the correct math libraries.
+Typically, you'll discover this at link time.
+
+To test for correct execution of the benchmark: It's unlikely you'll need to
+do this, since the algorithm is so cut-and-dried. Furthermore, there are no
+explicit provisions made to verify the correctness. You can, however, either
+dip into your favorite debugger, or alter the code to print out the contents
+of the abase (which holds the A[i] terms) and bbase (which holds the B[i]
+terms) arrays as they are being filled (see routine DoFPUTransIteration).
+** This is exactly what I have done, it now prints out A[i] and B[i] data.
+** Uwe F. Mayer <mayer at tux.edu>
+Run the benchmark with a command file set to execute only the Fourier test,
+and examine the contents of the arrays. The first 100 are listed below.
+
+A[i]=
+   2.84 1.05 0.274 0.0824 0.0102 -0.024 -0.0426 -0.0536 -0.0605 -0.065
+-0.0679 -0.0698 -0.0709 -0.0715 -0.0717 -0.0715 -0.0711 -0.0704
+-0.0696 -0.0685 -0.0674 -0.0661 -0.0647 -0.0632 -0.0615 -0.0598 -0.058
+-0.0561 -0.0542 -0.0521 -0.0501 -0.0479 -0.0457 -0.0434 -0.0411
+-0.0387 -0.0363 -0.0338 -0.0313 -0.0288 -0.0262 -0.0236 -0.0209
+-0.0183 -0.0156 -0.0129 -0.0102 -0.00744 -0.0047 -0.00196 0.000794
+0.00355 0.0063 0.00905 0.0118 0.0145 0.0172 0.0199 0.0226 0.0253
+0.0279 0.0305 0.0331 0.0357 0.0382 0.0407 0.0431 0.0455 0.0479 0.0502
+0.0525 0.0547 0.0569 0.059 0.061 0.063 0.0649 0.0668 0.0686 0.0703
+0.072 0.0736 0.0751 0.0765 0.0779 0.0792 0.0804 0.0816 0.0826 0.0836
+0.0845 0.0853 0.0861 0.0867 0.0873 0.0877 0.0881 0.0884 0.0887 0.0888
+
+B[i]= 
+(undefined) -1.88 -1.16 -0.806 -0.61 -0.487 -0.402 -0.34 -0.293 -0.255
+-0.224 -0.199 -0.177 -0.158 -0.141 -0.126 -0.113 -0.101 -0.0901
+-0.0802 -0.071 -0.0625 -0.0546 -0.0473 -0.0404 -0.034 -0.0279 -0.0222
+-0.0168 -0.0117 -0.00693 -0.00238 0.00193 0.00601 0.00988 0.0135 0.017
+0.0203 0.0234 0.0263 0.0291 0.0317 0.0341 0.0364 0.0385 0.0405 0.0424
+0.0441 0.0457 0.0471 0.0484 0.0496 0.0507 0.0516 0.0525 0.0532 0.0538
+0.0543 0.0546 0.0549 0.055 0.0551 0.055 0.0549 0.0546 0.0543 0.0538
+0.0533 0.0527 0.052 0.0512 0.0503 0.0493 0.0483 0.0472 0.046 0.0447
+0.0434 0.042 0.0405 0.039 0.0374 0.0358 0.0341 0.0323 0.0305 0.0287
+0.0268 0.0249 0.023 0.021 0.019 0.0169 0.0149 0.0128 0.0107 0.00857
+0.00644 0.0043 0.00215
+
+Note that there is no B[0] coefficient. If the above numbers are in the
+arrays shown, you can feel pretty confident that the benchmark it working
+properly.
+
+References
+
+Engineering and Scientific Computations in Pascal, Lawrence P. Huelsman,
+Harper & Row, New York, 1986.
+
+Assignment Algorithm
+
+Description
+
+This test is built on an algorithm with direct application to the business
+world. The assignment algorithm solves the following problem: Say you have X
+machines and Y jobs. Any of the machines can do any of the jobs; however, the
+machines are sufficiently different so that the cost of doing a particular
+job can vary depending what machine does it. Furthermore, the jobs are
+sufficiently different that the cost varies depending on which job a given
+machine does. You therefore construct a matrix; machines are the rows, jobs
+are the columns, and the [i,j] element of the array is the cost of doing the
+jth job on the ith machine. How can you assign the jobs so that the cost of
+completing them all is minimal? (This also assumes that one machine does one
+job.)
+
+Did you get that?
+
+The assignment algorithm benchmark is largely a test of how well the
+processor handles problems built around array manipulation. It is not a
+floating-point test; the "cost matrix" built by the algorithm is simply a 2D
+array of long integers. This benchmark considers an iteration to be a run of
+the assignment algorithm on a 101 x 101 - element matrix. It reports its
+results in iterations per second.
+
+Analysis
+
+Optimized 486 code (Watcom C/C++ 10.0): There are numerous loops within the
+assignment algorithm. The development system we were using (Watcom C/C++
+10.0) appears to have a fine time unrolling many of them. Consequently, it
+is difficult to pin down the execution impact of single lines (as in, for
+example, the numeric sort benchmark).
+
+On the level of functions, the benchmark spends around 70% of its time in
+the routine first_assignments(). This is where a) lone zeros in rows and
+columns are found and selected, and b) a choice is made between duplicate
+zeros. Around 23% of the time is spent in the second_assignments() routine
+where (if first_assignments() fails) the matrix is partitioned into smaller
+submatrices.
+
+Overall, we did a tally of instruction mix execution. The approximate
+breakdowns are:
+
+move - 38%
+
+conditional jump - 12%
+
+unconditional jump - 11%
+
+comparison - 14%
+
+math/logical/shift - 24%
+
+Many of the move instructions that appeared to consume the most amounts of
+time were referencing items on the local stack frame. This required an
+indirect reference through EBP, plus a constant offset to resolve the
+address.
+
+This should be a good exercise of a cache, since operations in the
+first_assignments() routine require both row-wise and column-wise movement
+through the array. Note that the routine could be made more "severe" by
+chancing the assignedtableau[][] array to an array of unsigned char --
+forcing fetches on byte boundaries.
+
+680x0 Code (CodeWarrior): The CodeWarrior profiler is function-based.
+Consequently, it's not possible to determine what's going on at the machine
+instruction level. We can, however, get a good idea of how much time the
+algorithm spends in each routine. The important routines are broken down as
+follows:
+
+calc_minimum_costs() - approximately 0.3% of the time
+
+(250 microsecs)
+
+first_assignments() - approximately 79% of the time
+
+(96284.6 microsecs)
+
+second_assignments() - approximately 19% of the time
+
+(22758 microsecs)
+
+These times are approximate; some time is spent in the Assignment() routine
+itself.
+
+These figures are reasonably close to those of the 486, at least in terms of
+the mixture of time spent in a particular routine. Hence, this should still
+be a good test of system cache (as described in the preceding section),
+given the behavior of the first_assignments() routine.
+
+Porting Considerations
+
+The assignment algorithm test is purely an integer benchmark, and requires
+no special data types that might be affected by ports to different
+architectures. There are only two global constants that affect the
+algorithm:
+
+ASSIGNROWS and ASSIGNCOLS - These set the size of the assignment array. Both
+are defined to be 101 (so, the array that is benchmarked is a 101 x 101
+-element array of longs). These values should not be altered.
+
+To test for correct execution of the benchmark: #define the symbol DEBUG,
+recompile, set up a command file that executes only the assignment
+algorithm, and run the benchmark. (You may want to pipe the output through a
+paging filter, like the more program.) The act of defining DEBUG will enable
+a section of code that displays the assigned columns on a per-row basis. If
+the benchmark is working properly, the numbers to be displayed
+should be:
+
+R000: 056 R001: 066 R002: 052 R003: 065 R004: 043 R005: 023 R006: 016
+R007: 077 R008: 095 R009: 004 R010: 064 R011: 076 R012: 078 R013: 091
+R014: 013 R015: 029 R016: 044 R017: 014 R018: 041 R019: 042 R020: 020
+R021: 071 R022: 024 R023: 017 R024: 055 R025: 040 R026: 070 R027: 025
+R028: 031 R029: 019 R030: 073 R031: 002 R032: 047 R033: 009 R034: 035
+R035: 045 R036: 005 R037: 063 R038: 081 R039: 039 R040: 087 R041: 008
+R042: 053 R043: 093 R044: 049 R045: 092 R046: 061 R047: 046 R048: 026
+R049: 034 R050: 088 R051: 000 R052: 028 R053: 018 R054: 072 R055: 021
+R056: 037 R057: 082 R058: 006 R059: 058 R060: 096 R061: 068 R062: 069
+R063: 054 R064: 057 R065: 086 R066: 097 R067: 084 R068: 099 R069: 051
+R070: 098 R071: 003 R072: 074 R073: 062 R074: 080 R075: 033 R076: 011
+R077: 094 R078: 012 R079: 050 R080: 010 R081: 038 R082: 089 R083: 059
+R084: 022 R085: 079 R086: 015 R087: 007 R088: 075 R089: 083 R090: 060
+R091: 048 R092: 032 R093: 067 R094: 001 R095: 030 R096: 027 R097: 085
+R098: 090 R099: 036 R100: 100
+
+These are the column choices for each row made by the algorithm. If
+you see these numbers displayed, the algorithm is working correctly.
+
+*** The original debugging information was incorrect, as it not only
+*** display the chosen columns, but also displayed eliminated columns.
+*** Changed to show all 101 entries. Uwe F. Mayer <mayer at tux.edu>
+
+References
+
+Quantitative Decision Making for Business, Gordon, Pressman, and Cohn,
+Prentice-Hall, Englewood Cliffs, NJ, 1990.
+
+Quantitative Decision Making, Guiseppi A. Forgionne, Wadsworth Publishing
+Co., California, 1986.
+
+Huffman Compression
+
+Description
+
+This is a compression algorithm that -- while helpful for some time as a
+text compression technique -- has since fallen out of fashion on account of
+the superior performance by algorithms such as LZW compression. It is,
+however, still used in some graphics file formats in one form or another.
+
+The benchmark consists of three parts:
+
+Building a "Huffman Tree" (explained below),
+
+Compression, and
+
+Decompression.
+
+A "Huffman Tree" is a special data structure that guides the compression and
+decompression processes. If you were to diagram one, it would look like a
+large binary tree (i.e., two branches per each node). Describing its
+function in detail is beyond the scope of this paper (see the references for
+more information). We should, however, point out that the tree is built from
+the "bottom up"; and the procedure for constructing it requires that the
+algorithm scan the uncompressed buffer, building a frequency table for all
+the characters appearing in the buffer. (This version of the Huffman
+algorithm compresses byte-at-a-time, though there's no reason why the same
+principle could not be applied to tokens larger than one byte.)
+
+Once the tree is built, text compression is relatively straightforward. The
+algorithm fetches a character from the uncompressed buffer, navigates the
+tree based on the character's value, and produces a bit stream that is
+concatenated to the compressed buffer. Decompression is the reverse of that
+process. (We recognize that we are simplifying the algorithm. Again, we
+recommend you check the references.)
+
+The Huffman Compression benchmark considers an iteration to be the three
+operations described above, performed on an uncompressed text buffer of 5000
+bytes. It reports its results in iterations per second.
+
+Analysis
+
+Optimized 486 code (Watcom C/C++ 10.0): The Huffman compression algorithm --
+tree building, compression, and decompression -- is written as a single,
+large routine: DoHuffIteration(). All the benchmark's time is spent within
+that routine.
+
+Components of DoHuffIteration() that consume the most time are those that
+perform the compression and decompression .
+
+The code for performing the compression spends most of its time (accounting
+for about 13%) constructing the bit string for a character that is being
+compressed. It does this by seeking up the tree from a leaf, emitting 1's
+and 0's in the process, until it reaches the root. The stream of 1's and 0's
+are loaded into a character array; the algorithm then walks "backward"
+through the array, setting (or clearing) bits in the compression buffer as
+it goes.
+
+Similarly, the decompression portion takes about 12% of the time as the
+algorithm pulls bits out of the compressed buffer -- using them to navigate
+the Huffman tree -- and reconstructs the original text.
+
+680x0 Code (Macintosh CodeWarrior): CodeWarrior's profiler is function
+based. Consequently, it's impossible to get performance scores for
+individual machine instructions. Furthermore, as mentioned above, the
+Huffman compression algorithm is written as a monolithic routine. This makes
+the results from the CodeWarrior profiler all the more sparse.
+
+We can at least point out that the lowmost routines (GetCompBit() and
+SetCompBit()) that read and write individual bits, though called nearly 13
+million times each, account for only 0.7% and 0.3% of the total time,
+respectively.
+
+Porting Considerations
+
+The Huffman algorithm relies on no special data types. It should port
+readily. Global constants of interest include:
+
+EXCLUDED - This is a large, positive value. Currently it is set to 32000,
+and should be left alone. Basically, this is a token that the system uses to
+indicate an excluded character (one that does not appear in the plain-text).
+It is set to a ridiculously high value that will never appear in the
+pointers of the tree during normal construction.
+
+MAXHUFFLOOPS - This is another one of those "governor" constants. The
+Huffman benchmark creates more work for itself by doing multiple
+compression/decompression loops. This constant sets the maximum number of
+loops it will attempt per iteration before it gives up. Currently, it is set
+to 50000. Though it is unlikely you'll ever need to modify this value, you
+can increase it if your machine is too fast for the adjustment algorithm. Do
+not reduce the number.
+
+HUFFARRAYSIZE - This value sets the size of the plain-text array to be
+compressed. You can override this value with the command file to see how
+well your machine performs for larger or smaller arrays. The subsequent
+results, however, are invalid for comparison with other systems.
+
+To test for correct execution of the benchmark: #define the symbol DEBUG,
+recompile, build a command file that executes only the Huffman compression
+algorithm, and run the benchmark. Defining DEBUG will enable a section of
+code that verifies the decompression as it takes place (i.e., the routine
+compares -- character at a time -- the uncompressed data with the original
+plain-text). If there's an error, the program will repeatedly display: "Error
+at textoffset xxx". 
+
+** If everything is correct it will emit quite a few "Huffman: OK" messages.
+**
+** I added a resetting of the random number generator, outside of the
+** timed loop, and a resetting of the Huffman tree, inside of the
+** timed loop. That should help to make the benchmark more consistent.
+** The program did originally only reset half of the tree, which lead
+** to runtime errors on some systems. The effect on the benchmark
+** should be negligible, and in fact comes out as being of the order
+** of less than 1% on my test system.
+** Uwe F. Mayer <mayer at tux.edu>
+
+References
+
+Data Compression: Methods and Theory, James A. Storer, Computer Science
+Press, Rockville, MD, 1988.
+
+An Introduction to Text Processing, Peter D. Smith, MIT Press, Cambridge,
+MA, 1990.
+
+IDEA Encryption
+
+Description
+
+This is another benchmark based on a "higher-level" algorithm; "higher
+-level" in the sense that it is more complex than a sort or a search
+operation.
+
+Security -- and, therefore, cryptography -- are becoming increasingly
+important issues in the computer realm. It's likely that more and more
+machines will be running routines like the IDEA encryption algorithm. (IDEA
+is an acronym for the International Data Encryption Algorithm.)
+
+A good description of the algorithm (and, in fact, the reference we used to
+create the source code for the test) can be found in Bruce Schneier's
+exhaustive exploration of encryption, "Applied Cryptography" (see
+references). To quote Mr. Schneier: "In my opinion, it [IDEA] is the best
+and most secure block algorithm available to the public at this time."
+
+IDEA is a symmetrical, block cipher algorithm. Symmetrical means that the
+same routine used to encrypt the data also decrypts the data. A block cipher
+works on the plain-text (the message to be encrypted) in fixed, discrete
+chunks. In the case of IDEA, the algorithm encrypts and decrypts 64 bits at
+a time.
+
+As pointed out in Schneier's book, there are three operations that the IDEA
+uses to do its work:
+
+XOR (exclusive-or)
+
+Addition modulo 216 (ignoring overflow)
+
+Multiplication modulo 216+1 (ignoring overflow).
+
+IDEA requires a key of 128 bits. However, keys and blocks are further
+subdivided into 16-bit chunks, so that any given operation within the IDEA
+encryption is performed on 16-bit quantities. (This is one of the many
+advantages of the algorithm, it is efficient even on 16-bit processors.)
+
+The IDEA benchmark considers an "iteration" to be an encryption and
+decryption of a buffer of 4000 bytes. The test actually builds 3 buffers:
+The first to hold the original plain-text, the second to hold the encrypted
+text, and the third to hold the decrypted text (the contents of which should
+match that of the first buffer). It reports its results in iterations per
+second.
+
+Analysis
+
+Optimized 486 code: The algorithm actually spends most of its time (nearly
+75%) within the mul() routine, which performs the multiplication modulo
+216+1. This is a super-simple routine, consisting primarily of if
+statements, shifts, and additions.
+
+The remaining time (around 24%) is spent in the balance of the cipher_idea()
+routine. (Note that cipher_idea() calls the mul() routine frequently; so,
+the 24% is comprised of the other lines of cipher_idea()). cipher_idea() is
+littered with simple pointer-fetch-and-increment operations, some addition,
+and some exclusive-or operations.
+
+Note that IDEA's exercise of system capabilities probably doesn't extend
+beyond testing simple integer math operations. Since the buffer size is set
+to 4000 bytes, the test will run entirely in processor cache on most
+systems. Even the cache won't get a heavy "internal" workout, since the
+algorithm proceeds sequentially through each buffer from lower to higher
+addresses.
+
+680x0 code (Macintosh CodeWarrior): CodeWarrior's profiler is function
+based; consequently, it is impossible to determine execution profiles for
+individual machine instructions. We can, however, get an idea of how much
+time is spent in each routine.
+
+As with Huffman compression, the IDEA algorithm is written monolithically --
+a single, large routine does most of the work. However, a special
+multiplication routine, mul(), is frequently called within each
+encryption/decryption iteration (see above).
+
+In this instance, the results for the 68K system diverges widely from those
+of the 486 system. The CodeWarrior profiler shows the mul() routine as
+taking only 4% of the total time in the benchmark, even though it is called
+over 20 million times. The outer routine is called 600,000 times, and
+accounts for about 96% of the whole program's entire time.
+
+Porting Considerations
+
+Since IDEA does its work in 16-bit units, it is particularly important that
+u16 be defined to whatever datatype provides an unsigned 16-bit integer on
+the test platform. Usually, unsigned short works for this. (You can verify
+the size of a short by running the benchmarks with a command file that
+includes ALLSTATS=T as one of the commands. This will cause the benchmark
+program to display a message that tells the size of the int, short, and long
+data-types in bytes.)
+
+Also, the mul() routine in IDEA requires the u32 datatype to define an
+unsigned 32-bit integer. In most cases, unsigned long works.
+
+To test for correct execution of the benchmark: #define the symbol DEBUG,
+recompile, build a command file that executes only the IDEA algorithm, and
+run the benchmark. Defining DEBUG will enable a section of code that
+compares the original plain-text with the output of the test. (Remember, the
+benchmark performs both encryption and decryption.) If the algorithm has
+failed, the output will not match the input, and you'll see "IDEA Error"
+messages all over your display.
+
+References
+
+Applied Cryptography: Protocols, Algorithms, and Source Code in C, Bruce
+Schneier, John Wiley & Sons, Inc., New York, 1994.
+
+Neural Net
+
+Description
+
+The Neural Net simulation benchmark is based on a simple back-propagation
+neural network presented by Maureen Caudill as part of a BYTE article that
+appeared in the October, 1991 issue (see "Expert Networks" in that issue).
+The network involved is a simple 3-layer (input neurodes, middle-layer
+neurodes, and output neurodes) network that accepts a number of 5 x 7 input
+patterns and produce a single 8-bit output pattern.
+
+The test involves sending the network an input pattern that is the 5 x 7
+"image" of a character (1's and 0's -- 1's representing lit pixels, 0's
+representing unlit pixels), and teaching it the 8-bit ASCII code for the
+character.
+
+A thorough description of how the back propagation algorithm works is beyond
+the scope of this paper. We recommend you search through the references
+given at the end of this paper, particularly Ms. Caudill's article, for
+detailed discussion. In brief, the benchmark is primarily an exercise in
+floating-point operations, with some frequent use of the exp() function. It
+also performs a great deal of array references, though the arrays in use are
+well under 300 elements each (and less than 100 in most cases).
+
+The Neural Net benchmark considers an iteration to be a single learning
+cycle. (A "learning cycle" is defined as the time it takes the network to be
+able to associate all input patterns to the correct output patterns within a
+specified tolerance.) It reports its results in iterations per second.
+
+Analysis
+
+Optimized 486 code: The forward pass of the network (i.e., calculating
+outputs from inputs) utilize a sigmoid function. This function has, at its
+heart, a call to the exp() library routine. A small but non-negligible
+amount of time is spent in that function (a little over 5% for the 486
+system we tested).
+
+The learning portion of the network benchmark depends on the derivative of
+the sigmoid function, which turns out to require only multiplications and
+subtractions. Consequently, each learning pass exercises only simple
+floating-point operations.
+
+If we divide the time spent in the test into two parts -- forward pass and
+backward pass (the latter being the learning pass) -- then the test appears
+to spend the greatest part of its time in the learning phase. In fact, most
+time is spent in the adjust_mid_wts() routine. This is the part of the
+routine that alters the weights on the middle layer neurodes. (It accounts
+for over 40% of the benchmark's time.)
+
+680x0 Code (Macintosh CodeWarrior): Though CodeWarrior's profiler is
+function based, the neural net benchmark is highly modular. We can therefore
+get a good breakdown of routine usage:
+
+worst_pass_error() - 304 microsecs (called 4680 times)
+
+adjust_mid_wts() - 83277 microsecs (called 46800 times)
+
+adjust_out_wts() - 17394 microsecs (called 46800 times)
+
+do_mid_error() - 11512 microsecs (called 46800 times)
+
+do_out_error() - 3002 microsecs (called 46800 times)
+
+do_mid_forward() - 49559 microsecs (called 46800 times)
+
+do_out_forward() - 20634 microsecs (called 46800 times)
+
+Again, most time was spent in adjust_mid_wts() (as on the 486), accounting
+for almost twice as much time as do_mid_forward().
+
+Porting Consideration
+
+The Neural Net benchmark is not dependent on any special data types. There
+are a number of global variables and arrays that should not be altered in
+any way. Most importantly, the #defines found in NBENCH1.H under the Neural
+Net section should not be changed. These control not only the number of
+neurodes in each layer; they also include constants that govern the learning
+processes.
+
+Other globals to be aware of:
+
+MAXNNETLOOPS - This constant simply sets the upper limit on the number of
+training loops the test will permit per iteration. The Neural Net benchmark
+adjusts its workload by re-teaching itself over and over (each time it
+begins a new training session, the network is "cleared" -- loaded with
+random values). It is unlikely you will ever need to modify this constant.
+
+inpath - This string pointer is set to the path from which the neural net's
+input data is read. It is currently hardwired to "NNET.DAT". You shouldn't
+have to change this name, unless your file system requires directory
+information as part of the path.
+
+Note that the Neural Net benchmark is the only test that requires an
+external data file. The contents of the file are listed in an attachment to
+this paper. You should use the attachment to reconstruct the file should it
+become lost or corrupted. Any changes to the file will invalidate the test
+results.
+
+To test for correct execution of the benchmark: #define the symbol DEBUG,
+recompile, build a command file that executes only the Neural Net test, and
+run the benchmark. Defining DEBUG will enable a section of code that
+displays how many passes through the learning process were required for the
+net to learn. It should learn in 780 passes.
+
+References
+
+"Expert Networks," Maureen Caudill, BYTE Magazine, October, 1991.
+
+Simulating Neural Networks, Norbert Hoffmann, Verlag Vieweg, Wiesbaden,
+1994.
+
+Signal and Image Processing with Neural Networks, Timothy Masters, John
+Wiley and Sons, New York, 1994.
+
+Introduction to Neural Networks, Jeannette Stanley, California Scientific
+Software, CA, 1989.
+
+LU Decomposition
+
+Description
+
+LU Decomposition is an algorithm that can be used as the heart of a program
+for solving linear equations. Suppose you have a matrix A. LU Decomposition
+determines the matrices L and U such that
+
+L . U = A
+
+where L is a lower triangular matrix and U is an upper triangular matrix. (A
+lower triangular matrix has nonzero elements only on the main diagonal and
+below. An upper triangular matrix has nonzero elements only on the main
+diagonal and above.)
+
+Without going into the mathematical details too deeply, having the L and U
+matrices makes the solution of linear equations (i.e., equations of the form
+A . x = b) quite easy. It turns out that you can also use LU decomposition
+to determine matrix inverses and determinants.
+
+The algorithm used in the benchmarks was derived from Numerical Recipes in
+Pascal (there is a C version of the book, which we did not have on hand), a
+book we heartily recommend to anyone serious about mathematical and
+scientific computing. The authors are approving of LU decomposition as a
+means of solving linear equations, pointing out that their version (which
+makes use of what we would have to call "Crout's method with partial
+implicit pivoting") is a factor of 3 better than one of their Gauss-Jordan
+routines, a factor of 1.5 better than another. They go on to demonstrate the
+use of LU decomposition for iterative improvement of linear equation
+solutions.
+
+The benchmark begins by creating a "solvable" linear system. This is easily
+done by loading up the column vector b with random integers, then
+initializing A with an identity matrix. The equations are then "scrambled"
+by either multiplying a row by a constant, or adding one row to another. The
+scrambled matrices are handed to the LU algorithm.
+
+The LU Decomposition benchmark considers a single iteration to be the
+solution of one set of equations (the size of A is fixed at 101 x 101
+elements). It reports its results in iterations per second.
+
+Analysis
+
+Optimized 486 code (Watcom C/C++ 10.0): The entire algorithm consists of two
+parts: the LU decomposition itself, and the back substitution algorithm that
+builds the solution vector. The majority of the algorithm's time takes place
+within the former; the algorithm that builds the L and U matrices (this
+takes place in routine ludcmp()).
+
+Within ludcmp(), there are two extremely tight for loops forming the heart
+of Crout's algorithm that consume the majority of the time. The loops are
+"tight" in that they each consist of only one line of code; in both cases,
+the line of code is a "multiply and accumulate" operation (actually, it's
+sort of a multiply and de-accumulate, since the result of the multiplication
+is subtracted, not added).
+
+In both cases, the items multiplied are elements from the A array; and one
+factor's row index is varying more rapidly, while another factor's column
+index is varying more rapidly.
+
+Note that this is a good overall test of floating-point operations within
+matrices. Most of the math is floating-point; primarily additions,
+subtractions, and multiplications (only a few divisions).
+
+680x0 Code (Macintosh CodeWarrior): CodeWarrior's profiler is function
+based. It is therefore impossible to determine execution profiles at the
+machine-code level. The profiler does, however, allow us to determine how
+much time the benchmark spends in each routine. This breakdown is as
+follows:
+
+lusolve() - 3.4 microsecs (about 0% of the time)
+
+lubksb() 1198 microsec (about 2% of the time)
+
+ludcmp() - 63171 microsec (about 91% of the time)
+
+The above percentages are for the whole program. Consequently, as a portion
+of actual benchmark time, the amount attributed to each will be slightly
+larger (though the proportions will remain the same).
+
+Since ludcmp() performs the actual LU decomposition, this is exactly where
+we'd want the benchmark to spend its time. The lubksb() routine calls
+ludcmp(), using the resulting matrix to "back-solve" the linear equation.
+
+Porting Considerations
+
+The LU Decomposition routine requires no special data types, and is immune
+to byte ordering. It does make use of a typedef (LUdblptr) that includes an
+embedded union; this allows the benchmark to "coerce" a pointer to double
+into a pointer to a 2D array of double. This arrangement has not caused
+problems with the compilers we have tested to date.
+
+Other constants and globals to be aware of:
+
+LUARRAYROWS and LUARRAYCOLS - These constants set the size of the
+coefficient matrix, A. They cannot be altered by command file. In fact, you
+shouldn't alter them at all, or your results will be invalid. Currently,
+they are both set to 101.
+
+MAXLUARRAYS - This is another "governor" constant. The algorithm performs
+dynamic workload adjustment by building more and more arrays to solve per
+timing round. This sets the maximum upper limit of arrays that it will
+build. Currently, it is set to 1000, which should be more than enough for
+the reasonable future (1000 arrays of 101 x 101 floating-point doubles would
+require somewhere around 80 megabytes of RAM -- and that's not counting the
+column vectors).
+
+To test for correct execution of the benchmark: Currently, there is no
+simple technique for doing this. You can, however, either use your favorite
+debugger (or embed a printf() statement) at the conclusion of the lubksb()
+routine. When this routine concludes, the array b will hold the solution
+vector. These items will be stored as floating-point doubles, and the first
+14 are (with rounding):
+
+46 20 23 22 85 86 97 95 8 89 75 67 6 86
+
+If you find these numbers as the first 14 in the array b[], then you're
+virtually guaranteed that the algorithm is working correctly.
+
+*** The above is not correct, as the initial matrix is not the identity,
+*** but a matrix with random nonzero entries on the diagonal (they have
+*** altered the algorithm since they wrote the documentation).
+*** I changed the output of the debugging routine, it now prints first
+*** what the array b should hold (as righthand side divided by diagonal
+*** entry), and then it prints what the array b does hold after the
+*** decomposition has been done to compute the solution of the system. If
+*** you get the same, then fine.
+*** And, by the way, my original right hand sides are
+***  46  23  85  97   8  75   6  81  88  76   6  84  31  53   2 ...
+*** and the diagonal entries are
+*** 520 922 186 495  89 267 786 571 175 600 738 321 897 541 859 ...
+*** You notice that one has every other number of the original sequence.
+*** This is due to BYTE's change of the algorithm, as they now also use the
+*** random number generator to generate the diagonal elements.
+*** Here is the complete set of data:
+*** 46/520=0.09  23/922=0.02  85/186=0.46   97/495=0.20  8/89=0.09
+*** 75/267=0.28  6/786=0.01   81/571=0.14   88/175=0.50  76/600=0.13
+*** 6/738=0.01   84/321=0.26  31/897=0.03   53/541=0.10  2/859=0.00
+*** 86/92=0.93   51/121=0.42  29/248=0.12   51/789=0.06  84/6=14.00
+*** 21/180=0.12  33/48=0.69   2/899=0.00    12/820=0.01  69/372=0.19
+*** 59/809=0.07  74/18=4.11   40/788=0.05   39/56=0.70   86/91=0.95
+*** 33/878=0.04  82/165=0.50  42/561=0.07   8/274=0.03   84/694=0.12
+*** 32/352=0.09  25/969=0.03  59/816=0.07   33/112=0.29  5/125=0.04
+*** 89/740=0.12  7/223=0.03   54/994=0.05   33/80=0.41   55/676=0.08
+*** 6/524=0.01   36/544=0.07  21/160=0.13   58/596=0.10  15/717=0.02
+*** 84/311=0.27  98/530=0.18  46/713=0.06   41/233=0.18  73/640=0.11
+*** 40/343=0.12  72/586=0.12  100/965=0.10  59/764=0.08  37/866=0.04
+*** 27/682=0.04  3/652=0.00   41/352=0.12   87/786=0.11  45/79=0.57
+*** 83/761=0.11  41/817=0.05  46/209=0.22   78/930=0.08  85/210=0.40
+*** 80/756=0.11  18/931=0.02  30/669=0.04   47/127=0.37  85/891=0.10
+*** 66/364=0.18  83/955=0.09  58/637=0.09   58/778=0.07  82/288=0.28
+*** 42/540=0.08  76/290=0.26  59/36=1.64    29/463=0.06  63/476=0.13
+*** 6/340=0.02   73/341=0.21  59/737=0.08   81/492=0.16  98/443=0.22
+*** 58/32=1.81   53/562=0.09  54/263=0.21   46/367=0.13  58/390=0.15
+*** 96/845=0.11  30/746=0.04  2/687=0.00    28/849=0.03  84/180=0.47
+*** 85/382=0.22
+*** Uwe F. Mayer <mayer at tux.edu>
+
+References
+
+Numerical Recipes in Pascal: The Art of Scientific Computing, Press,
+Flannery, Teukolsky, Vetterling, Cambridge University Press, New York, 1989.

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/debugbit.good.gz
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/debugbit.good.gz?rev=148656&view=auto
==============================================================================
Binary file - no diff available.

Propchange: test-suite/trunk/MultiSource/Benchmarks/nbench/debugbit.good.gz
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/emfloat.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/emfloat.c?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/emfloat.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/emfloat.c Sun Jan 22 03:50:58 2012
@@ -0,0 +1,1343 @@
+/*
+** emfloat.c
+** Source for emulated floating-point routines.
+** BYTEmark (tm)
+** BYTE's Native Mode Benchmarks
+** Rick Grehan, BYTE Magazine.
+**
+** Created:
+** Last update: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include "nmglobal.h"
+#include "emfloat.h"
+
+/*
+** Floating-point emulator.
+** These routines are only "sort of" IEEE-compliant.  All work is
+** done using an internal representation.  Also, the routines do
+** not check for many of the exceptions that might occur.
+** Still, the external formats produced are IEEE-compatible,
+** with the restriction that they presume a low-endian machine
+** (though the endianism will not effect the performance).
+**
+** Some code here was based on work done by Steve Snelgrove of
+** Orem, UT.  Other code comes from routines presented in
+** the long-ago book: "Microprocessor Programming for
+** Computer Hobbyists" by Neill Graham.
+*/
+
+/**************************
+** SetupCPUEmFloatArrays **
+***************************
+** Set up the arrays that will be used in the emulated
+** floating-point tests.
+** This is done by loading abase and bbase elements with
+** random numbers.  We use our long-to-floating point
+** routine to set them up.
+** NOTE: We really don't need the pointer to cbase...cbase
+** is overwritten in the benchmark.
+*/
+void SetupCPUEmFloatArrays(InternalFPF *abase,
+                InternalFPF *bbase,
+                InternalFPF *cbase,
+                ulong arraysize)
+{
+ulong i;
+InternalFPF locFPF1,locFPF2;
+/*
+** Reset random number generator so things repeat. Inserted by Uwe F. Mayer.
+*/
+extern int32 randnum(int32 lngval);
+randnum((int32)13);
+
+for(i=0;i<arraysize;i++)
+{/*       LongToInternalFPF(randwc(50000L),&locFPF1); */
+        Int32ToInternalFPF(randwc((int32)50000),&locFPF1);
+ /*       LongToInternalFPF(randwc(50000L)+1L,&locFPF2); */
+        Int32ToInternalFPF(randwc((int32)50000)+(int32)1,&locFPF2);
+        DivideInternalFPF(&locFPF1,&locFPF2,abase+i);
+ /*       LongToInternalFPF(randwc(50000L)+1L,&locFPF2); */
+        Int32ToInternalFPF(randwc((int32)50000)+(int32)1,&locFPF2);
+        DivideInternalFPF(&locFPF1,&locFPF2,bbase+i);
+}
+return;
+}
+
+/***********************
+** DoEmFloatIteration **
+************************
+** Perform an iteration of the emulated floating-point
+** benchmark.  Note that "an iteration" can involve multiple
+** loops through the benchmark.
+*/
+ulong DoEmFloatIteration(InternalFPF *abase,
+                InternalFPF *bbase,
+                InternalFPF *cbase,
+                ulong arraysize, ulong loops)
+{
+ulong elapsed;          /* For the stopwatch */
+static uchar jtable[16] = {0,0,0,0,1,1,1,1,2,2,2,2,2,3,3,3};
+ulong i;
+#ifdef DEBUG
+int number_of_loops;
+#endif
+/*
+** Begin timing
+*/
+elapsed=StartStopwatch();
+#ifdef DEBUG
+number_of_loops=loops-1; /* the index of the first loop we run */
+#endif
+
+/*
+** Each pass through the array performs operations in
+** the followingratios:
+**   4 adds, 4 subtracts, 5 multiplies, 3 divides
+** (adds and subtracts being nearly the same operation)
+*/
+while(loops--)
+{
+        for(i=0;i<arraysize;i++)
+                switch(jtable[i % 16])
+                {
+                        case 0: /* Add */
+                                AddSubInternalFPF(0,abase+i,
+                                  bbase+i,
+                                  cbase+i);
+                                break;
+                        case 1: /* Subtract */
+                                AddSubInternalFPF(1,abase+i,
+                                  bbase+i,
+                                  cbase+i);
+                                break;
+                        case 2: /* Multiply */
+                                MultiplyInternalFPF(abase+i,
+                                  bbase+i,
+                                  cbase+i);
+                                break;
+                        case 3: /* Divide */
+                                DivideInternalFPF(abase+i,
+                                  bbase+i,
+                                  cbase+i);
+                                break;
+                }
+#ifdef DEBUG
+{
+  ulong j[8];   /* we test 8 entries */
+  int k;
+  ulong i;
+  char buffer[1024];
+  if (number_of_loops==loops) /* the first loop */
+    {
+      j[0]=(ulong)2;
+      j[1]=(ulong)6;
+      j[2]=(ulong)10;
+      j[3]=(ulong)14;
+      j[4]=(ulong)(arraysize-14);
+      j[5]=(ulong)(arraysize-10);
+      j[6]=(ulong)(arraysize-6);
+      j[7]=(ulong)(arraysize-2);
+      for(k=0;k<8;k++){
+	i=j[k];
+	InternalFPFToString(buffer,abase+i);
+	printf("%6ld: (%s) ",i,buffer);
+	switch(jtable[i % 16])
+	  {
+	  case 0: strcpy(buffer,"+"); break;
+	  case 1: strcpy(buffer,"-"); break;
+	  case 2: strcpy(buffer,"*"); break;
+	  case 3: strcpy(buffer,"/"); break;
+	  }
+	printf("%s ",buffer);
+	InternalFPFToString(buffer,bbase+i);
+	printf("(%s) = ",buffer);
+	InternalFPFToString(buffer,cbase+i);
+	printf("%s\n",buffer);
+      }
+    }
+}
+#endif
+}
+return(StopStopwatch(elapsed));
+}
+
+/***********************
+** SetInternalFPFZero **
+************************
+** Set an internal floating-point-format number to zero.
+** sign determines the sign of the zero.
+*/
+static void SetInternalFPFZero(InternalFPF *dest,
+                        uchar sign)
+{
+int i;          /* Index */
+
+dest->type=IFPF_IS_ZERO;
+dest->sign=sign;
+dest->exp=MIN_EXP;
+for(i=0;i<INTERNAL_FPF_PRECISION;i++)
+        dest->mantissa[i]=0;
+return;
+}
+
+/***************************
+** SetInternalFPFInfinity **
+****************************
+** Set an internal floating-point-format number to infinity.
+** This can happen if the exponent exceeds MAX_EXP.
+** As above, sign picks the sign of infinity.
+*/
+static void SetInternalFPFInfinity(InternalFPF *dest,
+                        uchar sign)
+{
+int i;          /* Index */
+
+dest->type=IFPF_IS_INFINITY;
+dest->sign=sign;
+dest->exp=MIN_EXP;
+for(i=0;i<INTERNAL_FPF_PRECISION;i++)
+        dest->mantissa[i]=0;
+return;
+}
+
+/**********************
+** SetInternalFPFNaN **
+***********************
+** Set an internal floating-point-format number to Nan
+** (not a number).  Note that we "emulate" an 80x87 as far
+** as the mantissa bits go.
+*/
+static void SetInternalFPFNaN(InternalFPF *dest)
+{
+int i;          /* Index */
+
+dest->type=IFPF_IS_NAN;
+dest->exp=MAX_EXP;
+dest->sign=1;
+dest->mantissa[0]=0x4000;
+for(i=1;i<INTERNAL_FPF_PRECISION;i++)
+        dest->mantissa[i]=0;
+
+return;
+}
+
+/*******************
+** IsMantissaZero **
+********************
+** Pass this routine a pointer to an internal floating point format
+** number's mantissa.  It checks for an all-zero mantissa.
+** Returns 0 if it is NOT all zeros, !=0 otherwise.
+*/
+static int IsMantissaZero(u16 *mant)
+{
+int i;          /* Index */
+int n;          /* Return value */
+
+n=0;
+for(i=0;i<INTERNAL_FPF_PRECISION;i++)
+        n|=mant[i];
+
+return(!n);
+}
+
+/**************
+** Add16Bits **
+***************
+** Add b, c, and carry.  Retult in a.  New carry in carry.
+*/
+static void Add16Bits(u16 *carry,
+                u16 *a,
+                u16 b,
+                u16 c)
+{
+u32 accum;              /* Accumulator */
+
+/*
+** Do the work in the 32-bit accumulator so we can return
+** the carry.
+*/
+accum=(u32)b;
+accum+=(u32)c;
+accum+=(u32)*carry;
+*carry=(u16)((accum & 0x00010000) ? 1 : 0);     /* New carry */
+*a=(u16)(accum & 0xFFFF);       /* Result is lo 16 bits */
+return;
+}
+
+/**************
+** Sub16Bits **
+***************
+** Additive inverse of above.
+*/
+static void Sub16Bits(u16 *borrow,
+                u16 *a,
+                u16 b,
+                u16 c)
+{
+u32 accum;              /* Accumulator */
+
+accum=(u32)b;
+accum-=(u32)c;
+accum-=(u32)*borrow;
+*borrow=(u32)((accum & 0x00010000) ? 1 : 0);    /* New borrow */
+*a=(u16)(accum & 0xFFFF);
+return;
+}
+
+/*******************
+** ShiftMantLeft1 **
+********************
+** Shift a vector of 16-bit numbers left 1 bit.  Also provides
+** a carry bit, which is shifted in at the beginning, and
+** shifted out at the end.
+*/
+static void ShiftMantLeft1(u16 *carry,
+                        u16 *mantissa)
+{
+int i;          /* Index */
+int new_carry;
+u16 accum;      /* Temporary holding placed */
+
+for(i=INTERNAL_FPF_PRECISION-1;i>=0;i--)
+{       accum=mantissa[i];
+        new_carry=accum & 0x8000;       /* Get new carry */
+        accum=accum<<1;                 /* Do the shift */
+        if(*carry)
+                accum|=1;               /* Insert previous carry */
+        *carry=new_carry;
+        mantissa[i]=accum;              /* Return shifted value */
+}
+return;
+}
+
+/********************
+** ShiftMantRight1 **
+*********************
+** Shift a mantissa right by 1 bit.  Provides carry, as
+** above
+*/
+static void ShiftMantRight1(u16 *carry,
+                        u16 *mantissa)
+{
+int i;          /* Index */
+int new_carry;
+u16 accum;
+
+for(i=0;i<INTERNAL_FPF_PRECISION;i++)
+{       accum=mantissa[i];
+        new_carry=accum & 1;            /* Get new carry */
+        accum=accum>>1;
+        if(*carry)
+                accum|=0x8000;
+        *carry=new_carry;
+        mantissa[i]=accum;
+}
+return;
+}
+
+
+/*****************************
+** StickyShiftMantRight **
+******************************
+** This is a shift right of the mantissa with a "sticky bit".
+** I.E., if a carry of 1 is shifted out of the least significant
+** bit, the least significant bit is set to 1.
+*/
+static void StickyShiftRightMant(InternalFPF *ptr,
+                        int amount)
+{
+int i;          /* Index */
+u16 carry;      /* Self-explanatory */
+u16 *mantissa;
+
+mantissa=ptr->mantissa;
+
+if(ptr->type!=IFPF_IS_ZERO)     /* Don't bother shifting a zero */
+{
+        /*
+        ** If the amount of shifting will shift everyting
+        ** out of existence, then just clear the whole mantissa
+        ** and set the lowmost bit to 1.
+        */
+        if(amount>=INTERNAL_FPF_PRECISION * 16)
+        {
+                for(i=0;i<INTERNAL_FPF_PRECISION-1;i++)
+                        mantissa[i]=0;
+                mantissa[INTERNAL_FPF_PRECISION-1]=1;
+        }
+        else
+                for(i=0;i<amount;i++)
+                {
+                        carry=0;
+                        ShiftMantRight1(&carry,mantissa);
+                        if(carry)
+                                mantissa[INTERNAL_FPF_PRECISION-1] |= 1;
+                }
+}
+return;
+}
+
+
+/**************************************************
+**         POST ARITHMETIC PROCESSING            **
+**  (NORMALIZE, ROUND, OVERFLOW, AND UNDERFLOW)  **
+**************************************************/
+
+/**************
+** normalize **
+***************
+** Normalize an internal-representation number.  Normalization
+** discards empty most-significant bits.
+*/
+static void normalize(InternalFPF *ptr)
+{
+u16     carry;
+
+/*
+** As long as there's a highmost 0 bit, shift the significand
+** left 1 bit.  Each time you do this, though, you've
+** gotta decrement the exponent.
+*/
+while ((ptr->mantissa[0] & 0x8000) == 0)
+{
+        carry = 0;
+        ShiftMantLeft1(&carry, ptr->mantissa);
+        ptr->exp--;
+}
+return;
+}
+
+/****************
+** denormalize **
+*****************
+** Denormalize an internal-representation number.  This means
+** shifting it right until its exponent is equivalent to
+** minimum_exponent. (You have to do this often in order
+** to perform additions and subtractions).
+*/
+static void denormalize(InternalFPF *ptr,
+                int minimum_exponent)
+{
+long exponent_difference;
+
+if (IsMantissaZero(ptr->mantissa))
+{
+        printf("Error:  zero significand in denormalize\n");
+}
+
+exponent_difference = ptr->exp-minimum_exponent;
+if (exponent_difference < 0)
+{
+        /*
+        ** The number is subnormal
+        */
+        exponent_difference = -exponent_difference;
+        if (exponent_difference >= (INTERNAL_FPF_PRECISION * 16))
+        {
+                /* Underflow */
+                SetInternalFPFZero(ptr, ptr->sign);
+        }
+        else
+        {
+                ptr->exp+=exponent_difference;
+                StickyShiftRightMant(ptr, exponent_difference);
+        }
+}
+return;
+}
+
+
+/*********************
+** RoundInternalFPF **
+**********************
+** Round an internal-representation number.
+** The kind of rounding we do here is simplest...referred to as
+** "chop".  "Extraneous" rightmost bits are simply hacked off.
+*/
+void RoundInternalFPF(InternalFPF *ptr)
+{
+/* int i; */
+
+if (ptr->type == IFPF_IS_NORMAL ||
+        ptr->type == IFPF_IS_SUBNORMAL)
+{
+        denormalize(ptr, MIN_EXP);
+        if (ptr->type != IFPF_IS_ZERO)
+        {
+
+                /* clear the extraneous bits */
+                ptr->mantissa[3] &= 0xfff8;
+/*              for (i=4; i<INTERNAL_FPF_PRECISION; i++)
+                {
+                        ptr->mantissa[i] = 0;
+                }
+*/
+                /*
+                ** Check for overflow
+                */
+/*              Does not do anything as ptr->exp is a short and MAX_EXP=37268
+		if (ptr->exp > MAX_EXP)
+                {
+                        SetInternalFPFInfinity(ptr, ptr->sign);
+                }
+*/
+        }
+}
+return;
+}
+
+/*******************************************************
+**  ARITHMETIC OPERATIONS ON INTERNAL REPRESENTATION  **
+*******************************************************/
+
+/***************
+** choose_nan **
+****************
+** Called by routines that are forced to perform math on
+** a pair of NaN's.  This routine "selects" which NaN is
+** to be returned.
+*/
+static void choose_nan(InternalFPF *x,
+                InternalFPF *y,
+                InternalFPF *z,
+                int intel_flag)
+{
+int i;
+
+/*
+** Compare the two mantissas,
+** return the larger.  Note that we will be emulating
+** an 80387 in this operation.
+*/
+for (i=0; i<INTERNAL_FPF_PRECISION; i++)
+{
+        if (x->mantissa[i] > y->mantissa[i])
+        {
+                memmove((void *)x,(void *)z,sizeof(InternalFPF));
+                return;
+        }
+        if (x->mantissa[i] < y->mantissa[i])
+        {
+                memmove((void *)y,(void *)z,sizeof(InternalFPF));
+                return;
+        }
+}
+
+/*
+** They are equal
+*/
+if (!intel_flag)
+        /* if the operation is addition */
+        memmove((void *)x,(void *)z,sizeof(InternalFPF));
+else
+        /* if the operation is multiplication */
+        memmove((void *)y,(void *)z,sizeof(InternalFPF));
+return;
+}
+
+
+/**********************
+** AddSubInternalFPF **
+***********************
+** Adding or subtracting internal-representation numbers.
+** Internal-representation numbers pointed to by x and y are
+** added/subtracted and the result returned in z.
+*/
+static void AddSubInternalFPF(uchar operation,
+                InternalFPF *x,
+                InternalFPF *y,
+                InternalFPF *z)
+{
+int exponent_difference;
+u16 borrow;
+u16 carry;
+int i;
+InternalFPF locx,locy;  /* Needed since we alter them */
+
+/*
+** Following big switch statement handles the
+** various combinations of operand types.
+*/
+switch ((x->type * IFPF_TYPE_COUNT) + y->type)
+{
+case ZERO_ZERO:
+        memmove((void *)x,(void *)z,sizeof(InternalFPF));
+        if (x->sign ^ y->sign ^ operation)
+        {
+                z->sign = 0; /* positive */
+        }
+        break;
+
+case NAN_ZERO:
+case NAN_SUBNORMAL:
+case NAN_NORMAL:
+case NAN_INFINITY:
+case SUBNORMAL_ZERO:
+case NORMAL_ZERO:
+case INFINITY_ZERO:
+case INFINITY_SUBNORMAL:
+case INFINITY_NORMAL:
+        memmove((void *)x,(void *)z,sizeof(InternalFPF));
+        break;
+
+
+case ZERO_NAN:
+case SUBNORMAL_NAN:
+case NORMAL_NAN:
+case INFINITY_NAN:
+        memmove((void *)y,(void *)z,sizeof(InternalFPF));
+        break;
+
+case ZERO_SUBNORMAL:
+case ZERO_NORMAL:
+case ZERO_INFINITY:
+case SUBNORMAL_INFINITY:
+case NORMAL_INFINITY:
+        memmove((void *)y,(void *)z,sizeof(InternalFPF));
+        z->sign ^= operation;
+        break;
+
+case SUBNORMAL_SUBNORMAL:
+case SUBNORMAL_NORMAL:
+case NORMAL_SUBNORMAL:
+case NORMAL_NORMAL:
+        /*
+        ** Copy x and y to locals, since we may have
+        ** to alter them.
+        */
+        memmove((void *)&locx,(void *)x,sizeof(InternalFPF));
+        memmove((void *)&locy,(void *)y,sizeof(InternalFPF));
+
+        /* compute sum/difference */
+        exponent_difference = locx.exp-locy.exp;
+        if (exponent_difference == 0)
+        {
+                /*
+                ** locx.exp == locy.exp
+                ** so, no shifting required
+                */
+                if (locx.type == IFPF_IS_SUBNORMAL ||
+                  locy.type == IFPF_IS_SUBNORMAL)
+                        z->type = IFPF_IS_SUBNORMAL;
+                else
+                        z->type = IFPF_IS_NORMAL;
+
+                /*
+                ** Assume that locx.mantissa > locy.mantissa
+                */
+                z->sign = locx.sign;
+                z->exp= locx.exp;
+        }
+        else
+                if (exponent_difference > 0)
+                {
+                        /*
+                        ** locx.exp > locy.exp
+                        */
+                        StickyShiftRightMant(&locy,
+                                 exponent_difference);
+                        z->type = locx.type;
+                        z->sign = locx.sign;
+                        z->exp = locx.exp;
+                }
+                else    /* if (exponent_difference < 0) */
+                {
+                        /*
+                        ** locx.exp < locy.exp
+                        */
+                        StickyShiftRightMant(&locx,
+                                -exponent_difference);
+                        z->type = locy.type;
+                        z->sign = locy.sign ^ operation;
+                        z->exp = locy.exp;
+                }
+
+                if (locx.sign ^ locy.sign ^ operation)
+                {
+                        /*
+                        ** Signs are different, subtract mantissas
+                        */
+                        borrow = 0;
+                        for (i=(INTERNAL_FPF_PRECISION-1); i>=0; i--)
+                                Sub16Bits(&borrow,
+                                        &z->mantissa[i],
+                                        locx.mantissa[i],
+                                        locy.mantissa[i]);
+
+                        if (borrow)
+                        {
+                                /* The y->mantissa was larger than the
+                                ** x->mantissa leaving a negative
+                                ** result.  Change the result back to
+                                ** an unsigned number and flip the
+                                ** sign flag.
+                                */
+                                z->sign = locy.sign ^ operation;
+                                borrow = 0;
+                                for (i=(INTERNAL_FPF_PRECISION-1); i>=0; i--)
+                                {
+                                        Sub16Bits(&borrow,
+                                                &z->mantissa[i],
+                                                0,
+                                                z->mantissa[i]);
+                                }
+                        }
+                        else
+                        {
+                                /* The assumption made above
+                                ** (i.e. x->mantissa >= y->mantissa)
+                                ** was correct.  Therefore, do nothing.
+                                ** z->sign = x->sign;
+                                */
+                        }
+
+                        if (IsMantissaZero(z->mantissa))
+                        {
+                                z->type = IFPF_IS_ZERO;
+                                z->sign = 0; /* positive */
+                        }
+                        else
+                                if (locx.type == IFPF_IS_NORMAL ||
+                                         locy.type == IFPF_IS_NORMAL)
+                                {
+                                        normalize(z);
+                                }
+                }
+                else
+                {
+                        /* signs are the same, add mantissas */
+                        carry = 0;
+                        for (i=(INTERNAL_FPF_PRECISION-1); i>=0; i--)
+                        {
+                                Add16Bits(&carry,
+                                        &z->mantissa[i],
+                                        locx.mantissa[i],
+                                        locy.mantissa[i]);
+                        }
+
+                        if (carry)
+                        {
+                                z->exp++;
+                                carry=0;
+                                ShiftMantRight1(&carry,z->mantissa);
+                                z->mantissa[0] |= 0x8000;
+                                z->type = IFPF_IS_NORMAL;
+                        }
+                        else
+                                if (z->mantissa[0] & 0x8000)
+                                        z->type = IFPF_IS_NORMAL;
+        }
+        break;
+
+case INFINITY_INFINITY:
+        SetInternalFPFNaN(z);
+        break;
+
+case NAN_NAN:
+        choose_nan(x, y, z, 1);
+        break;
+}
+
+/*
+** All the math is done; time to round.
+*/
+RoundInternalFPF(z);
+return;
+}
+
+
+/************************
+** MultiplyInternalFPF **
+*************************
+** Two internal-representation numbers x and y are multiplied; the
+** result is returned in z.
+*/
+static void MultiplyInternalFPF(InternalFPF *x,
+                        InternalFPF *y,
+                        InternalFPF *z)
+{
+int i;
+int j;
+u16 carry;
+u16 extra_bits[INTERNAL_FPF_PRECISION];
+InternalFPF locy;       /* Needed since this will be altered */
+/*
+** As in the preceding function, this large switch
+** statement selects among the many combinations
+** of operands.
+*/
+switch ((x->type * IFPF_TYPE_COUNT) + y->type)
+{
+case INFINITY_SUBNORMAL:
+case INFINITY_NORMAL:
+case INFINITY_INFINITY:
+case ZERO_ZERO:
+case ZERO_SUBNORMAL:
+case ZERO_NORMAL:
+        memmove((void *)x,(void *)z,sizeof(InternalFPF));
+        z->sign ^= y->sign;
+        break;
+
+case SUBNORMAL_INFINITY:
+case NORMAL_INFINITY:
+case SUBNORMAL_ZERO:
+case NORMAL_ZERO:
+        memmove((void *)y,(void *)z,sizeof(InternalFPF));
+        z->sign ^= x->sign;
+        break;
+
+case ZERO_INFINITY:
+case INFINITY_ZERO:
+        SetInternalFPFNaN(z);
+        break;
+
+case NAN_ZERO:
+case NAN_SUBNORMAL:
+case NAN_NORMAL:
+case NAN_INFINITY:
+        memmove((void *)x,(void *)z,sizeof(InternalFPF));
+        break;
+
+case ZERO_NAN:
+case SUBNORMAL_NAN:
+case NORMAL_NAN:
+case INFINITY_NAN:
+        memmove((void *)y,(void *)z,sizeof(InternalFPF));
+        break;
+
+
+case SUBNORMAL_SUBNORMAL:
+case SUBNORMAL_NORMAL:
+case NORMAL_SUBNORMAL:
+case NORMAL_NORMAL:
+        /*
+        ** Make a local copy of the y number, since we will be
+        ** altering it in the process of multiplying.
+        */
+        memmove((void *)&locy,(void *)y,sizeof(InternalFPF));
+
+        /*
+        ** Check for unnormal zero arguments
+        */
+        if (IsMantissaZero(x->mantissa) || IsMantissaZero(y->mantissa))
+                SetInternalFPFInfinity(z, 0);
+
+        /*
+        ** Initialize the result
+        */
+        if (x->type == IFPF_IS_SUBNORMAL ||
+            y->type == IFPF_IS_SUBNORMAL)
+                z->type = IFPF_IS_SUBNORMAL;
+        else
+                z->type = IFPF_IS_NORMAL;
+
+        z->sign = x->sign ^ y->sign;
+        z->exp = x->exp + y->exp ;
+        for (i=0; i<INTERNAL_FPF_PRECISION; i++)
+        {
+                z->mantissa[i] = 0;
+                extra_bits[i] = 0;
+        }
+
+        for (i=0; i<(INTERNAL_FPF_PRECISION*16); i++)
+        {
+                /*
+                ** Get rightmost bit of the multiplier
+                */
+                carry = 0;
+                ShiftMantRight1(&carry, locy.mantissa);
+                if (carry)
+                {
+                        /*
+                        ** Add the multiplicand to the product
+                        */
+                        carry = 0;
+                        for (j=(INTERNAL_FPF_PRECISION-1); j>=0; j--)
+                                Add16Bits(&carry,
+                                        &z->mantissa[j],
+                                        z->mantissa[j],
+                                        x->mantissa[j]);
+                }
+                else
+                {
+                        carry = 0;
+                }
+
+                /*
+                ** Shift the product right.  Overflow bits get
+                ** shifted into extra_bits.  We'll use it later
+                ** to help with the "sticky" bit.
+                */
+                ShiftMantRight1(&carry, z->mantissa);
+                ShiftMantRight1(&carry, extra_bits);
+        }
+
+        /*
+        ** Normalize
+        ** Note that we use a "special" normalization routine
+        ** because we need to use the extra bits. (These are
+        ** bits that may have been shifted off the bottom that
+        ** we want to reclaim...if we can.
+        */
+        while ((z->mantissa[0] & 0x8000) == 0)
+        {
+                carry = 0;
+                ShiftMantLeft1(&carry, extra_bits);
+                ShiftMantLeft1(&carry, z->mantissa);
+                z->exp--;
+        }
+
+        /*
+        ** Set the sticky bit if any bits set in extra bits.
+        */
+        if (IsMantissaZero(extra_bits))
+        {
+                z->mantissa[INTERNAL_FPF_PRECISION-1] |= 1;
+        }
+        break;
+
+case NAN_NAN:
+        choose_nan(x, y, z, 0);
+        break;
+}
+
+/*
+** All math done...do rounding.
+*/
+RoundInternalFPF(z);
+return;
+}
+
+
+/**********************
+** DivideInternalFPF **
+***********************
+** Divide internal FPF number x by y.  Return result in z.
+*/
+static void DivideInternalFPF(InternalFPF *x,
+                        InternalFPF *y,
+                        InternalFPF *z)
+{
+int i;
+int j;
+u16 carry;
+u16 extra_bits[INTERNAL_FPF_PRECISION];
+InternalFPF locx;       /* Local for x number */
+
+/*
+** As with preceding function, the following switch
+** statement selects among the various possible
+** operands.
+*/
+switch ((x->type * IFPF_TYPE_COUNT) + y->type)
+{
+case ZERO_ZERO:
+case INFINITY_INFINITY:
+        SetInternalFPFNaN(z);
+        break;
+
+case ZERO_SUBNORMAL:
+case ZERO_NORMAL:
+        if (IsMantissaZero(y->mantissa))
+        {
+                SetInternalFPFNaN(z);
+                break;
+        }
+
+case ZERO_INFINITY:
+case SUBNORMAL_INFINITY:
+case NORMAL_INFINITY:
+        SetInternalFPFZero(z, x->sign ^ y->sign);
+        break;
+
+case SUBNORMAL_ZERO:
+case NORMAL_ZERO:
+        if (IsMantissaZero(x->mantissa))
+        {
+                SetInternalFPFNaN(z);
+                break;
+        }
+
+case INFINITY_ZERO:
+case INFINITY_SUBNORMAL:
+case INFINITY_NORMAL:
+        SetInternalFPFInfinity(z, 0);
+        z->sign = x->sign ^ y->sign;
+        break;
+
+case NAN_ZERO:
+case NAN_SUBNORMAL:
+case NAN_NORMAL:
+case NAN_INFINITY:
+        memmove((void *)x,(void *)z,sizeof(InternalFPF));
+        break;
+
+case ZERO_NAN:
+case SUBNORMAL_NAN:
+case NORMAL_NAN:
+case INFINITY_NAN:
+        memmove((void *)y,(void *)z,sizeof(InternalFPF));
+        break;
+
+case SUBNORMAL_SUBNORMAL:
+case NORMAL_SUBNORMAL:
+case SUBNORMAL_NORMAL:
+case NORMAL_NORMAL:
+        /*
+        ** Make local copy of x number, since we'll be
+        ** altering it in the process of dividing.
+        */
+        memmove((void *)&locx,(void *)x,sizeof(InternalFPF));
+
+        /*
+        ** Check for unnormal zero arguments
+        */
+        if (IsMantissaZero(locx.mantissa))
+        {
+                if (IsMantissaZero(y->mantissa))
+                        SetInternalFPFNaN(z);
+                else
+                        SetInternalFPFZero(z, 0);
+                break;
+        }
+        if (IsMantissaZero(y->mantissa))
+        {
+                SetInternalFPFInfinity(z, 0);
+                break;
+        }
+
+        /*
+        ** Initialize the result
+        */
+        z->type = x->type;
+        z->sign = x->sign ^ y->sign;
+        z->exp = x->exp - y->exp +
+                        ((INTERNAL_FPF_PRECISION * 16 * 2));
+        for (i=0; i<INTERNAL_FPF_PRECISION; i++)
+        {
+                z->mantissa[i] = 0;
+                extra_bits[i] = 0;
+        }
+
+        while ((z->mantissa[0] & 0x8000) == 0)
+        {
+                carry = 0;
+                ShiftMantLeft1(&carry, locx.mantissa);
+                ShiftMantLeft1(&carry, extra_bits);
+
+                /*
+                ** Time to subtract yet?
+                */
+                if (carry == 0)
+                        for (j=0; j<INTERNAL_FPF_PRECISION; j++)
+                        {
+                                if (y->mantissa[j] > extra_bits[j])
+                                {
+                                        carry = 0;
+                                        goto no_subtract;
+                                }
+                                if (y->mantissa[j] < extra_bits[j])
+                                        break;
+                        }
+                /*
+                ** Divisor (y) <= dividend (x), subtract
+                */
+                carry = 0;
+                for (j=(INTERNAL_FPF_PRECISION-1); j>=0; j--)
+                        Sub16Bits(&carry,
+                                &extra_bits[j],
+                                extra_bits[j],
+                                y->mantissa[j]);
+                carry = 1;      /* 1 shifted into quotient */
+        no_subtract:
+                ShiftMantLeft1(&carry, z->mantissa);
+                z->exp--;
+        }
+        break;
+
+case NAN_NAN:
+        choose_nan(x, y, z, 0);
+        break;
+}
+
+/*
+** Math complete...do rounding
+*/
+RoundInternalFPF(z);
+}
+
+/**********************
+** LongToInternalFPF **
+** Int32ToInternalFPF **
+***********************
+** Convert a signed (long) 32-bit integer into an internal FPF number.
+*/
+/* static void LongToInternalFPF(long mylong, */
+static void Int32ToInternalFPF(int32 mylong,
+                InternalFPF *dest)
+{
+int i;          /* Index */
+u16 myword;     /* Used to hold converted stuff */
+/*
+** Save the sign and get the absolute value.  This will help us
+** with 64-bit machines, since we use only the lower 32
+** bits just in case. (No longer necessary after we use int32.)
+*/
+/* if(mylong<0L) */
+if(mylong<(int32)0)
+{       dest->sign=1;
+        mylong=(int32)0-mylong;
+}
+else
+        dest->sign=0;
+/*
+** Prepare the destination floating point number
+*/
+dest->type=IFPF_IS_NORMAL;
+for(i=0;i<INTERNAL_FPF_PRECISION;i++)
+        dest->mantissa[i]=0;
+
+/*
+** See if we've got a zero.  If so, make the resultant FP
+** number a true zero and go home.
+*/
+if(mylong==0)
+{       dest->type=IFPF_IS_ZERO;
+        dest->exp=0;
+        return;
+}
+
+/*
+** Not a true zero.  Set the exponent to 32 (internal FPFs have
+** no bias) and load the low and high words into their proper
+** locations in the mantissa.  Then normalize.  The action of
+** normalizing slides the mantissa bits into place and sets
+** up the exponent properly.
+*/
+dest->exp=32;
+myword=(u16)((mylong >> 16) & 0xFFFFL);
+dest->mantissa[0]=myword;
+myword=(u16)(mylong & 0xFFFFL);
+dest->mantissa[1]=myword;
+normalize(dest);
+return;
+}
+
+#ifdef DEBUG
+/************************
+** InternalFPFToString **
+*************************
+** FOR DEBUG PURPOSES
+** This routine converts an internal floating point representation
+** number to a string.  Used in debugging the package.
+** Returns length of converted number.
+** NOTE: dest must point to a buffer big enough to hold the
+**  result.  Also, this routine does append a null (an effect
+**  of using the sprintf() function).  It also returns
+**  a length count.
+** NOTE: This routine returns 5 significant digits.  Thats
+**  about all I feel safe with, given the method of
+**  conversion.  It should be more than enough for programmers
+**  to determine whether the package is properly ported.
+*/
+static int InternalFPFToString(char *dest,
+                InternalFPF *src)
+{
+InternalFPF locFPFNum;          /* Local for src (will be altered) */
+InternalFPF IFPF10;             /* Floating-point 10 */
+InternalFPF IFPFComp;           /* For doing comparisons */
+int msign;                      /* Holding for mantissa sign */
+int expcount;                   /* Exponent counter */
+int ccount;                     /* Character counter */
+int i,j,k;                      /* Index */
+u16 carryaccum;                 /* Carry accumulator */
+u16 mycarry;                    /* Local for carry */
+
+/*
+** Check first for the simple things...Nan, Infinity, Zero.
+** If found, copy the proper string in and go home.
+*/
+switch(src->type)
+{
+        case IFPF_IS_NAN:
+                memcpy(dest,"NaN",3);
+                return(3);
+
+        case IFPF_IS_INFINITY:
+                if(src->sign==0)
+                        memcpy(dest,"+Inf",4);
+                else
+                        memcpy(dest,"-Inf",4);
+                return(4);
+
+        case IFPF_IS_ZERO:
+                if(src->sign==0)
+                        memcpy(dest,"+0",2);
+                else
+                        memcpy(dest,"-0",2);
+                return(2);
+}
+
+/*
+** Move the internal number into our local holding area, since
+** we'll be altering it to print it out.
+*/
+memcpy((void *)&locFPFNum,(void *)src,sizeof(InternalFPF));
+
+/*
+** Set up a floating-point 10...which we'll use a lot in a minute.
+*/
+/* LongToInternalFPF(10L,&IFPF10); */
+Int32ToInternalFPF((int32)10,&IFPF10);
+
+/*
+** Save the mantissa sign and make it positive.
+*/
+msign=src->sign;
+
+/* src->sign=0 */ /* bug, fixed Nov. 13, 1997 */
+(&locFPFNum)->sign=0;
+
+expcount=0;             /* Init exponent counter */
+
+/*
+** See if the number is less than 10.  If so, multiply
+** the number repeatedly by 10 until it's not.   For each
+** multiplication, decrement a counter so we can keep track
+** of the exponent.
+*/
+
+while(1)
+{       AddSubInternalFPF(1,&locFPFNum,&IFPF10,&IFPFComp);
+        if(IFPFComp.sign==0) break;
+        MultiplyInternalFPF(&locFPFNum,&IFPF10,&IFPFComp);
+        expcount--;
+        memcpy((void *)&locFPFNum,(void *)&IFPFComp,sizeof(InternalFPF));
+}
+/*
+** Do the reverse of the above.  As long as the number is
+** greater than or equal to 10, divide it by 10.  Increment the
+** exponent counter for each multiplication.
+*/
+
+while(1)
+{
+        AddSubInternalFPF(1,&locFPFNum,&IFPF10,&IFPFComp);
+        if(IFPFComp.sign!=0) break;
+        DivideInternalFPF(&locFPFNum,&IFPF10,&IFPFComp);
+        expcount++;
+        memcpy((void *)&locFPFNum,(void *)&IFPFComp,sizeof(InternalFPF));
+}
+
+/*
+** About time to start storing things.  First, store the
+** mantissa sign.
+*/
+ccount=1;               /* Init character counter */
+if(msign==0)
+        *dest++='+';
+else
+        *dest++='-';
+
+/*
+** At this point we know that the number is in the range
+** 10 > n >=1.  We need to "strip digits" out of the
+** mantissa.  We do this by treating the mantissa as
+** an integer and multiplying by 10. (Not a floating-point
+** 10, but an integer 10.  Since this is debug code and we
+** could care less about speed, we'll do it the stupid
+** way and simply add the number to itself 10 times.
+** Anything that makes it to the left of the implied binary point
+** gets stripped off and emitted.  We'll do this for
+** 5 significant digits (which should be enough to
+** verify things).
+*/
+/*
+** Re-position radix point
+*/
+carryaccum=0;
+while(locFPFNum.exp>0)
+{
+        mycarry=0;
+        ShiftMantLeft1(&mycarry,locFPFNum.mantissa);
+        carryaccum=(carryaccum<<1);
+        if(mycarry) carryaccum++;
+        locFPFNum.exp--;
+}
+
+while(locFPFNum.exp<0)
+{
+        mycarry=0;
+        ShiftMantRight1(&mycarry,locFPFNum.mantissa);
+        locFPFNum.exp++;
+}
+
+for(i=0;i<6;i++)
+        if(i==1)
+        {       /* Emit decimal point */
+                *dest++='.';
+                ccount++;
+        }
+        else
+        {       /* Emit a digit */
+                *dest++=('0'+carryaccum);
+                ccount++;
+
+                carryaccum=0;
+                memcpy((void *)&IFPF10,
+                        (void *)&locFPFNum,
+                        sizeof(InternalFPF));
+
+                /* Do multiply via repeated adds */
+                for(j=0;j<9;j++)
+                {
+                        mycarry=0;
+                        for(k=(INTERNAL_FPF_PRECISION-1);k>=0;k--)
+                                Add16Bits(&mycarry,&(IFPFComp.mantissa[k]),
+                                        locFPFNum.mantissa[k],
+                                        IFPF10.mantissa[k]);
+                        carryaccum+=mycarry ? 1 : 0;
+                        memcpy((void *)&locFPFNum,
+                                (void *)&IFPFComp,
+                                sizeof(InternalFPF));
+                }
+        }
+
+/*
+** Now move the 'E', the exponent sign, and the exponent
+** into the string.
+*/
+*dest++='E';
+
+/* sprint is supposed to return an integer, but it caused problems on SunOS
+ * with the native cc. Hence we force it.
+ * Uwe F. Mayer
+ */
+ccount+=(int)sprintf(dest,"%4d",expcount);
+
+/*
+** All done, go home.
+*/
+return(ccount);
+
+}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/emfloat.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/emfloat.h?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/emfloat.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/emfloat.h Sun Jan 22 03:50:58 2012
@@ -0,0 +1,150 @@
+
+/*
+** emfloat.h
+** Header for emfloat.c
+**
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+#include <stdio.h>
+
+/* Is this a 64 bit architecture? If so, this will define LONG64 */
+/* Uwe F. Mayer 15 November 1997                                 */
+/* #include "pointer.h" */
+
+/*
+** DEFINES
+*/
+#define u8 unsigned char
+#define u16 unsigned short
+#define u32 unsigned int
+#define uchar unsigned char
+#define ulong unsigned long
+
+#define MAX_EXP 32767L
+#define MIN_EXP (-32767L)
+
+#define IFPF_IS_ZERO 0
+#define IFPF_IS_SUBNORMAL 1
+#define IFPF_IS_NORMAL 2
+#define IFPF_IS_INFINITY 3
+#define IFPF_IS_NAN 4
+#define IFPF_TYPE_COUNT 5
+
+#define ZERO_ZERO                       0
+#define ZERO_SUBNORMAL                  1
+#define ZERO_NORMAL                     2
+#define ZERO_INFINITY                   3
+#define ZERO_NAN                        4
+
+#define SUBNORMAL_ZERO                  5
+#define SUBNORMAL_SUBNORMAL             6
+#define SUBNORMAL_NORMAL                7
+#define SUBNORMAL_INFINITY              8
+#define SUBNORMAL_NAN                   9
+
+#define NORMAL_ZERO                     10
+#define NORMAL_SUBNORMAL                11
+#define NORMAL_NORMAL                   12
+#define NORMAL_INFINITY                 13
+#define NORMAL_NAN                      14
+
+#define INFINITY_ZERO                   15
+#define INFINITY_SUBNORMAL              16
+#define INFINITY_NORMAL                 17
+#define INFINITY_INFINITY               18
+#define INFINITY_NAN                    19
+
+#define NAN_ZERO                        20
+#define NAN_SUBNORMAL                   21
+#define NAN_NORMAL                      22
+#define NAN_INFINITY                    23
+#define NAN_NAN                         24
+#define OPERAND_ZERO                    0
+#define OPERAND_SUBNORMAL               1
+#define OPERAND_NORMAL                  2
+#define OPERAND_INFINITY                3
+#define OPERAND_NAN                     4
+
+/*
+** Following already defined in NMGLOBAL.H
+**
+#define INTERNAL_FPF_PRECISION 4
+*/
+
+/*
+** TYPEDEFS
+*/
+
+typedef struct
+{
+        u8 type;        /* Indicates, NORMAL, SUBNORMAL, etc. */
+        u8 sign;        /* Mantissa sign */
+        short exp;      /* Signed exponent...no bias */
+        u16 mantissa[INTERNAL_FPF_PRECISION];
+} InternalFPF;
+
+/*
+** PROTOTYPES
+*/
+void SetupCPUEmFloatArrays(InternalFPF *abase,
+        InternalFPF *bbase, InternalFPF *cbase, ulong arraysize);
+ulong DoEmFloatIteration(InternalFPF *abase,
+        InternalFPF *bbase, InternalFPF *cbase,
+        ulong arraysize, ulong loops);
+static void SetInternalFPFZero(InternalFPF *dest,
+                        uchar sign);
+static void SetInternalFPFInfinity(InternalFPF *dest,
+                        uchar sign);
+static void SetInternalFPFNaN(InternalFPF *dest);
+static int IsMantissaZero(u16 *mant);
+static void Add16Bits(u16 *carry,u16 *a,u16 b,u16 c);
+static void Sub16Bits(u16 *borrow,u16 *a,u16 b,u16 c);
+static void ShiftMantLeft1(u16 *carry,u16 *mantissa);
+static void ShiftMantRight1(u16 *carry,u16 *mantissa);
+static void StickyShiftRightMant(InternalFPF *ptr,int amount);
+static void normalize(InternalFPF *ptr);
+static void denormalize(InternalFPF *ptr,int minimum_exponent);
+void RoundInternalFPF(InternalFPF *ptr);
+static void choose_nan(InternalFPF *x,InternalFPF *y,InternalFPF *z,
+                int intel_flag);
+static void AddSubInternalFPF(uchar operation,InternalFPF *x,
+                InternalFPF *y,InternalFPF *z);
+static void MultiplyInternalFPF(InternalFPF *x,InternalFPF *y,
+                        InternalFPF *z);
+static void DivideInternalFPF(InternalFPF *x,InternalFPF *y, 
+                        InternalFPF *z);
+/* static void LongToInternalFPF(long mylong, */
+static void Int32ToInternalFPF(int32 mylong,
+                InternalFPF *dest);
+#ifdef DEBUG
+static int InternalFPFToString(char *dest,
+                InternalFPF *src);
+#endif
+
+/*
+** EXTERNALS
+*/
+extern ulong StartStopwatch();
+extern ulong StopStopwatch(ulong elapsed);
+/* extern long randwc(long num); */
+extern int32 randwc(int32 num);

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/hardware.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/hardware.h?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/hardware.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/hardware.h Sun Jan 22 03:50:58 2012
@@ -0,0 +1,2 @@
+extern
+void hardware(const int write_to_file, FILE *global_ofile);

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/misc.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/misc.c?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/misc.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/misc.c Sun Jan 22 03:50:58 2012
@@ -0,0 +1,120 @@
+
+/*
+** misc.c
+** BYTEmark (tm)
+** BYTE's Native Mode Benchmarks
+** Rick Grehan, BYTE Magazine
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+#include <stdio.h>
+#include "misc.h"
+
+/***********************************************************
+**     MISCELLANEOUS BUT OTHERWISE NECESSARY ROUTINES     **
+***********************************************************/
+
+/****************************
+** RANDOM NUMBER GENERATOR **
+*****************************
+** This is a second-order linear congruential random number
+** generator.  Its advantage is (of course) that it can be
+** seeded and will thus produce repeatable sequences of
+** random numbers.
+*/
+
+/****************************
+*         randwc()          *
+*****************************
+** Returns signed long random modulo num.
+*/
+/*
+long randwc(long num)
+{
+	return(randnum(0L)%num);
+}
+*/
+/*
+** Returns signed 32-bit random modulo num.
+*/
+int32 randwc(int32 num)
+{
+	return(randnum((int32)0)%num);
+}
+
+/***************************
+**      abs_randwc()      **
+****************************
+** Same as randwc(), only this routine returns only
+** positive numbers.
+*/
+/*
+unsigned long abs_randwc(unsigned long num)
+{
+long temp;
+
+temp=randwc(num);
+if(temp<0) temp=0L-temp;
+
+return((unsigned long)temp);
+}
+*/
+u32 abs_randwc(u32 num)
+{
+int32 temp;		/* Temporary storage */ 
+
+temp=randwc(num);
+if(temp<0) temp=(int32)0-temp;
+
+return((u32)temp);
+}
+
+/****************************
+*        randnum()          *
+*****************************
+** Second order linear congruential generator.
+** Constants suggested by J. G. Skellam.
+** If val==0, returns next member of sequence.
+**    val!=0, restart generator.
+*/
+/*
+long randnum(long lngval)
+{
+	register long interm;
+	static long randw[2] = { 13L , 117L };
+
+	if (lngval!=0L)
+	{	randw[0]=13L; randw[1]=117L; }
+
+	interm=(randw[0]*254754L+randw[1]*529562L)%999563L;
+	randw[1]=randw[0];
+	randw[0]=interm;
+	return(interm);
+}
+*/
+int32 randnum(int32 lngval)
+{
+	register int32 interm;
+	static int32 randw[2] = { (int32)13 , (int32)117 };
+
+	if (lngval!=(int32)0)
+	{	randw[0]=(int32)13; randw[1]=(int32)117; }
+
+	interm=(randw[0]*(int32)254754+randw[1]*(int32)529562)%(int32)999563;
+	randw[1]=randw[0];
+	randw[0]=interm;
+	return(interm);
+}
+

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/misc.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/misc.h?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/misc.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/misc.h Sun Jan 22 03:50:58 2012
@@ -0,0 +1,41 @@
+/*
+** misc.h
+** Header for misc.c
+** BYTEmark (tm)
+** BYTE's Native Mode Benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Creation:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/************************
+** FUNCTION PROTOTYPES **
+************************/
+
+/*
+long randwc(long num);
+unsigned long abs_randwc(unsigned long num);
+long randnum(long lngval);
+*/
+
+#include "nmglobal.h"
+int32 randwc(int32 num);
+u32 abs_randwc(u32 num);
+int32 randnum(int32 lngval);
+
+

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/nbench.reference_output
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/nbench.reference_output?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/nbench.reference_output (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/nbench.reference_output Sun Jan 22 03:50:58 2012
@@ -0,0 +1,28 @@
+BBBBBB   YYY   Y  TTTTTTT  EEEEEEE
+BBB   B  YYY   Y    TTT    EEE
+BBB   B  YYY   Y    TTT    EEE
+BBBBBB    YYY Y     TTT    EEEEEEE
+BBB   B    YYY      TTT    EEE
+BBB   B    YYY      TTT    EEE
+BBBBBB     YYY      TTT    EEEEEEE
+
+
+BYTEmark (tm) Native Mode Benchmark ver. 2 (10/95)
+
+NOTE!!! Iteration display disabled to prevent diffs from failing!
+NUMERIC SORT        :  Iterations/sec.:          0.00  Index:   0.00
+STRING SORT         :  Iterations/sec.:          0.00  Index:   0.00
+BITFIELD            :  Iterations/sec.:          0.00  Index:   0.00
+FP EMULATION        :  Iterations/sec.:          0.00  Index:   0.00
+FOURIER             :  Iterations/sec.:          0.00  Index:   0.00
+ASSIGNMENT          :  Iterations/sec.:          0.00  Index:   0.00
+IDEA                :  Iterations/sec.:          0.00  Index:   0.00
+HUFFMAN             :  Iterations/sec.:          0.00  Index:   0.00
+NEURAL NET          :  Iterations/sec.:          0.00  Index:   0.00
+LU DECOMPOSITION    :  Iterations/sec.:          0.00  Index:   0.00
+==========================ORIGINAL BYTEMARK RESULTS==========================
+INTEGER INDEX       : 0.000
+FLOATING-POINT INDEX: 0.000
+Baseline (MSDOS*)   : Pentium* 90, 256 KB L2-cache, Watcom* compiler 10.0
+* Trademarks are property of their respective holder.
+exit 0

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/nbench0.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/nbench0.c?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/nbench0.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/nbench0.c Sun Jan 22 03:50:58 2012
@@ -0,0 +1,1175 @@
+
+/*
+** nbench0.c
+*/
+
+/*******************************************
+**             BYTEmark (tm)              **
+** BYTE MAGAZINE'S NATIVE MODE BENCHMARKS **
+**           FOR CPU/FPU                  **
+**             ver 2.0                    **
+**       Rick Grehan, BYTE Magazine       **
+********************************************
+** NOTE: These benchmarks do NOT check for the presence
+** of an FPU.  You have to find that out manually.
+**
+** REVISION HISTORY FOR BENCHMARKS
+**  9/94 -- First beta. --RG
+**  12/94 -- Bug discovered in some of the integer routines
+**    (IDEA, Huffman,...).  Routines were not accurately counting
+**    the number of loops.  Fixed. --RG (Thanks to Steve A.)
+**  12/94 -- Added routines to calculate and display index
+**    values. Indexes based on DELL XPS 90 (90 MHz Pentium).
+**  1/95 -- Added Mac time manager routines for more accurate
+**    timing on Macintosh (said to be good to 20 usecs) -- RG
+**  1/95 -- Re-did all the #defines so they made more
+**    sense.  See NMGLOBAL.H -- RG
+**  3/95 -- Fixed memory leak in LU decomposition.  Did not
+**    invalidate previous results, just made it easier to run.--RG
+**  3/95 -- Added TOOLHELP.DLL timing routine to Windows timer. --RG
+**  10/95 -- Added memory array & alignment; moved memory
+**      allocation out of LU Decomposition -- RG
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include "nmglobal.h"
+#include "nbench0.h"
+#include "hardware.h"
+
+/*************
+**** main ****
+*************/
+#ifdef MAC
+void main(void)
+#else
+int main(int argc, char *argv[])
+#endif
+{
+int i;                  /* Index */
+time_t time_and_date;   /* Self-explanatory */
+struct tm *loctime;
+double bmean;           /* Benchmark mean */
+double bstdev;          /* Benchmark stdev */
+double lx_memindex;     /* Linux memory index (mainly integer operations)*/
+double lx_intindex;     /* Linux integer index */
+double lx_fpindex;      /* Linux floating-point index */
+double intindex;        /* Integer index */
+double fpindex;         /* Floating-point index */
+ulong bnumrun;          /* # of runs */
+
+#ifdef MAC
+        MaxApplZone();
+#endif
+
+#ifdef MACTIMEMGR
+/* Set up high res timer */
+MacHSTdelay=600*1000*1000;      /* Delay is 10 minutes */
+
+memset((char *)&myTMTask,0,sizeof(TMTask));
+
+/* Prime and remove the task, calculating overhead */
+PrimeTime((QElemPtr)&myTMTask,-MacHSTdelay);
+RmvTime((QElemPtr)&myTMTask);
+MacHSTohead=MacHSTdelay+myTMTask.tmCount;
+#endif
+
+#ifdef WIN31TIMER
+/* Set up the size of the timer info structure */
+win31tinfo.dwSize=(DWORD)sizeof(TIMERINFO);
+/* Load library */
+if((hThlp=LoadLibrary("TOOLHELP.DLL"))<32)
+{       printf("Error loading TOOLHELP\n");
+        exit(0);
+}
+if(!(lpfn=GetProcAddress(hThlp,"TimerCount")))
+{       printf("TOOLHELP error\n");
+        exit(0);
+}
+#endif
+
+/*
+** Set global parameters to default.
+*/
+global_min_ticks=MINIMUM_TICKS;
+global_min_seconds=MINIMUM_SECONDS;
+global_allstats=0;
+global_custrun=0;
+global_align=8;
+write_to_file=0;
+lx_memindex=(double)1.0;        /* set for geometric mean computations */
+lx_intindex=(double)1.0;
+lx_fpindex=(double)1.0;
+intindex=(double)1.0;
+fpindex=(double)1.0;
+mem_array_ents=0;               /* Nothing in mem array */
+
+/*
+** We presume all tests will be run unless told
+** otherwise
+*/
+for(i=0;i<NUMTESTS;i++)
+        tests_to_do[i]=1;
+
+/*
+** Initialize test data structures to default
+** values.
+*/
+set_request_secs();     /* Set all request_secs fields */
+global_numsortstruct.adjust=0;
+global_numsortstruct.arraysize=NUMARRAYSIZE;
+
+global_strsortstruct.adjust=0;
+global_strsortstruct.arraysize=STRINGARRAYSIZE;
+
+global_bitopstruct.adjust=0;
+global_bitopstruct.bitfieldarraysize=BITFARRAYSIZE;
+
+global_emfloatstruct.adjust=0;
+global_emfloatstruct.arraysize=EMFARRAYSIZE;
+
+global_fourierstruct.adjust=0;
+
+global_assignstruct.adjust=0;
+
+global_ideastruct.adjust=0;
+global_ideastruct.arraysize=IDEAARRAYSIZE;
+
+global_huffstruct.adjust=0;
+global_huffstruct.arraysize=HUFFARRAYSIZE;
+
+global_nnetstruct.adjust=0;
+
+global_lustruct.adjust=0;
+
+/*
+** For Macintosh -- read the command line.
+*/
+#ifdef MAC
+UCommandLine();
+#endif
+
+/*
+** Handle any command-line arguments.
+*/
+if(argc>1)
+        for(i=1;i<argc;i++)
+                if(parse_arg(argv[i])==-1)
+                {       display_help(argv[0]);
+                        exit(0);
+                }
+/*
+** Output header
+*/
+#ifdef LINUX
+output_string("\nBYTEmark* Native Mode Benchmark ver. 2 (10/95)\n");
+output_string("Index-split by Andrew D. Balsa (11/97)\n");
+output_string("Linux/Unix* port by Uwe F. Mayer (12/96,11/97)\n");
+#else
+output_string("BBBBBB   YYY   Y  TTTTTTT  EEEEEEE\n");
+output_string("BBB   B  YYY   Y    TTT    EEE\n");
+output_string("BBB   B  YYY   Y    TTT    EEE\n");
+output_string("BBBBBB    YYY Y     TTT    EEEEEEE\n");
+output_string("BBB   B    YYY      TTT    EEE\n");
+output_string("BBB   B    YYY      TTT    EEE\n");
+output_string("BBBBBB     YYY      TTT    EEEEEEE\n\n");
+output_string("\nBYTEmark (tm) Native Mode Benchmark ver. 2 (10/95)\n");
+#endif
+/*
+** See if the user wants all stats.  Output heading info
+** if so.
+*/
+if(global_allstats)
+{
+                output_string("\n");
+                output_string("============================== ALL STATISTICS ===============================\n");
+        time(&time_and_date);
+        loctime=localtime(&time_and_date);
+        sprintf(buffer,"**Date and time of benchmark run: %s",asctime(loctime));
+        output_string(buffer);
+        sprintf(buffer,"**Sizeof: char:%u short:%u int:%u long:%u u8:%u u16:%u u32:%u int32:%u\n",
+                (unsigned int)sizeof(char),
+                (unsigned int)sizeof(short),
+                (unsigned int)sizeof(int),
+                (unsigned int)sizeof(long),
+                (unsigned int)sizeof(u8),
+                (unsigned int)sizeof(u16),
+                (unsigned int)sizeof(u32),
+                (unsigned int)sizeof(int32));
+        output_string(buffer);
+#ifdef LINUX
+#include "sysinfo.c"
+#else
+        sprintf(buffer,"**%s\n",sysname);
+        output_string(buffer);
+        sprintf(buffer,"**%s\n",compilername);
+        output_string(buffer);
+        sprintf(buffer,"**%s\n",compilerversion);
+        output_string(buffer);
+#endif
+                output_string("=============================================================================\n");
+}
+
+/*
+** Execute the tests.
+*/
+output_string("\nNOTE!!! Iteration display disabled to prevent diffs from failing!\n");
+#ifdef LINUX
+output_string("\nTEST                : Iterations/sec.  : Old Index   : New Index\n");
+output_string("                    :                  : Pentium 90* : AMD K6/233*\n");
+output_string("--------------------:------------------:-------------:------------\n");
+#endif
+
+for(i=0;i<NUMTESTS;i++)
+{
+        if(tests_to_do[i])
+        {       sprintf(buffer,"%s    :",ftestnames[i]);
+                                output_string(buffer);
+                if (0!=bench_with_confidence(i,
+                        &bmean,
+                        &bstdev,
+                        &bnumrun)){
+		  output_string("\n** WARNING: The current test result is NOT 95 % statistically certain.\n");
+		  output_string("** WARNING: The variation among the individual results is too large.\n");
+		  output_string("                    :");
+		}
+#ifdef LINUX
+                sprintf(buffer," %15.5g  :  %9.2f  :  %9.2f\n",
+                        bmean,bmean/bindex[i],bmean/lx_bindex[i]);
+#else
+		sprintf(buffer,"  Iterations/sec.: %13.2f  Index: %6.2f\n",
+                        /*bmean,bmean/bindex[i],*/ 0.0, 0.0);
+#endif
+                output_string(buffer);
+		/*
+		** Gather integer or FP indexes
+		*/
+		if((i==4)||(i==8)||(i==9)){
+		  /* FP index */
+		  fpindex=fpindex*(bmean/bindex[i]);
+		  /* Linux FP index */
+		  lx_fpindex=lx_fpindex*(bmean/lx_bindex[i]);
+		}
+		else{
+		  /* Integer index */
+		  intindex=intindex*(bmean/bindex[i]);
+		  if((i==0)||(i==3)||(i==6)||(i==7))
+		    /* Linux integer index */
+		    lx_intindex=lx_intindex*(bmean/lx_bindex[i]);
+		  else
+		    /* Linux memory index */
+		    lx_memindex=lx_memindex*(bmean/lx_bindex[i]);
+		}
+
+                if(global_allstats)
+                {
+                        sprintf(buffer,"  Absolute standard deviation: %g\n",bstdev);
+                        output_string(buffer);
+			if (bmean>(double)1e-100){
+			  /* avoid division by zero */
+			  sprintf(buffer,"  Relative standard deviation: %g %%\n",
+				  (double)100*bstdev/bmean);
+			  output_string(buffer);
+			}
+                        sprintf(buffer,"  Number of runs: %lu\n",bnumrun);
+                        output_string(buffer);
+                        show_stats(i);
+                        sprintf(buffer,"Done with %s\n\n",ftestnames[i]);
+                        output_string(buffer);
+                }
+        }
+}
+/* printf("...done...\n"); */
+
+/*
+** Output the total indexes
+*/
+if(global_custrun==0)
+{
+        output_string("==========================ORIGINAL BYTEMARK RESULTS==========================\n");
+        sprintf(buffer,"INTEGER INDEX       : %.3f\n",
+                       /*pow(intindex,(double).142857)*/ 0.0);
+        output_string(buffer);
+        sprintf(buffer,"FLOATING-POINT INDEX: %.3f\n",
+                        /*pow(fpindex,(double).33333)*/ 0.0);
+        output_string(buffer);
+        output_string("Baseline (MSDOS*)   : Pentium* 90, 256 KB L2-cache, Watcom* compiler 10.0\n");
+#ifdef LINUX
+        output_string("==============================LINUX DATA BELOW===============================\n");
+	hardware(write_to_file, global_ofile);
+#include "sysinfoc.c"
+        sprintf(buffer,"MEMORY INDEX        : %.3f\n",
+                       pow(lx_memindex,(double).3333333333));
+        output_string(buffer);
+        sprintf(buffer,"INTEGER INDEX       : %.3f\n",
+                       pow(lx_intindex,(double).25));
+        output_string(buffer);
+        sprintf(buffer,"FLOATING-POINT INDEX: %.3f\n",
+                        pow(lx_fpindex,(double).3333333333));
+        output_string(buffer);
+        output_string("Baseline (LINUX)    : AMD K6/233*, 512 KB L2-cache, gcc 2.7.2.3, libc-5.4.38\n");
+#endif
+output_string("* Trademarks are property of their respective holder.\n");
+}
+
+exit(0);
+}
+
+/**************
+** parse_arg **
+***************
+** Given a pointer to a string, we assume that's an argument.
+** Parse that argument and act accordingly.
+** Return 0 if ok, else return -1.
+*/
+static int parse_arg(char *argptr)
+{
+int i;          /* Index */
+FILE *cfile;    /* Command file identifier */
+
+/*
+** First character has got to be a hyphen.
+*/
+if(*argptr++!='-') return(-1);
+
+/*
+** Convert the rest of the argument to upper case
+** so there's little chance of confusion.
+*/
+for(i=0;i<strlen(argptr);i++)
+        argptr[i]=(char)toupper((int)argptr[i]);
+
+/*
+** Next character picks the action.
+*/
+switch(*argptr++)
+{
+        case '?':       return(-1);     /* Will display help */
+
+        case 'V': global_allstats=1; return(0); /* verbose mode */
+
+        case 'C':                       /* Command file name */
+                /*
+                ** First try to open the file for reading.
+                */
+                cfile=fopen(argptr,"r");
+                if(cfile==(FILE *)NULL)
+                {       printf("**Error opening file: %s\n",argptr);
+                        return(-1);
+                }
+                read_comfile(cfile);    /* Read commands */
+                fclose(cfile);
+                break;
+        default:
+                return(-1);
+}
+return(0);
+}
+
+/*******************
+** display_help() **
+********************
+** Display a help message showing argument requirements and such.
+** Exit when you're done...I mean, REALLY exit.
+*/
+void display_help(char *progname)
+{
+        printf("Usage: %s [-v] [-c<FILE>]\n",progname);
+        printf(" -v = verbose\n");
+        printf(" -c = input parameters thru command file <FILE>\n");
+        exit(0);
+}
+
+
+/*****************
+** read_comfile **
+******************
+** Read the command file.  Set global parameters as
+** specified.  This routine assumes that the command file
+** is already open.
+*/
+static void read_comfile(FILE *cfile)
+{
+char inbuf[40];
+char *eptr;             /* Offset to "=" sign */
+int i;                  /* Index */
+
+/*
+** Sit in a big loop, reading a line from the file at each
+** pass.  Terminate on EOF.
+*/
+while(fgets(inbuf,39,cfile)!=(char *)NULL)
+{
+        /* Overwrite the CR character */
+        if(strlen(inbuf)>0)
+                inbuf[strlen(inbuf)-1]='\0';
+
+        /*
+        ** Parse up to the "=" sign.  If we don't find an
+        ** "=", then flag an error.
+        */
+        if((eptr=strchr(inbuf,(int)'='))==(char *)NULL)
+        {       printf("**COMMAND FILE ERROR at LINE:\n %s\n",
+                        inbuf);
+                goto skipswitch;        /* A GOTO!!!! */
+        }
+
+        /*
+        ** Insert a null where the "=" was, then convert
+        ** the substring to uppercase.  That will enable
+        ** us to perform the match.
+        */
+        *eptr++='\0';
+        strtoupper((char *)&inbuf[0]);
+        i=MAXPARAM;
+        do {
+                if(strcmp(inbuf,paramnames[i])==0)
+                        break;
+        } while(--i>=0);
+
+        if(i<0)
+        {       printf("**COMMAND FILE ERROR -- UNKNOWN PARAM: %s",
+                        inbuf);
+                goto skipswitch;
+        }
+
+        /*
+        ** Advance eptr to the next field...which should be
+        ** the value assigned to the parameter.
+        */
+        switch(i)
+        {
+                case PF_GMTICKS:        /* GLOBALMINTICKS */
+                        global_min_ticks=(ulong)atol(eptr);
+                        break;
+
+                case PF_MINSECONDS:     /* MINSECONDS */
+                        global_min_seconds=(ulong)atol(eptr);
+                        set_request_secs();
+                        break;
+
+                case PF_ALLSTATS:       /* ALLSTATS */
+                        global_allstats=getflag(eptr);
+                        break;
+
+                case PF_OUTFILE:        /* OUTFILE */
+                        strcpy(global_ofile_name,eptr);
+                        global_ofile=fopen(global_ofile_name,"a");
+                        /*
+                        ** Open the output file.
+                        */
+                        if(global_ofile==(FILE *)NULL)
+                        {       printf("**Error opening output file: %s\n",
+                                        global_ofile_name);
+                                ErrorExit();
+                        }
+                        write_to_file=-1;
+                        break;
+
+                case PF_CUSTOMRUN:      /* CUSTOMRUN */
+                        global_custrun=getflag(eptr);
+                        for(i=0;i<NUMTESTS;i++)
+                                tests_to_do[i]=1-global_custrun;
+                        break;
+
+                case PF_DONUM:          /* DONUMSORT */
+                        tests_to_do[TF_NUMSORT]=getflag(eptr);
+                        break;
+
+                case PF_NUMNUMA:        /* NUMNUMARRAYS */
+                        global_numsortstruct.numarrays=
+                                (ushort)atoi(eptr);
+                        global_numsortstruct.adjust=1;
+                        break;
+
+                case PF_NUMASIZE:       /* NUMARRAYSIZE */
+                        global_numsortstruct.arraysize=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_NUMMINS:        /* NUMMINSECONDS */
+                        global_numsortstruct.request_secs=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_DOSTR:          /* DOSTRINGSORT */
+                        tests_to_do[TF_SSORT]=getflag(eptr);
+                        break;
+
+                case PF_STRASIZE:       /* STRARRAYSIZE */
+                        global_strsortstruct.arraysize=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_NUMSTRA:        /* NUMSTRARRAYS */
+                        global_strsortstruct.numarrays=
+                                (ushort)atoi(eptr);
+                        global_strsortstruct.adjust=1;
+                        break;
+
+                case PF_STRMINS:        /* STRMINSECONDS */
+                        global_strsortstruct.request_secs=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_DOBITF: /* DOBITFIELD */
+                        tests_to_do[TF_BITOP]=getflag(eptr);
+                        break;
+
+                case PF_NUMBITOPS:      /* NUMBITOPS */
+                        global_bitopstruct.bitoparraysize=
+                                (ulong)atol(eptr);
+                        global_bitopstruct.adjust=1;
+                        break;
+
+                case PF_BITFSIZE:       /* BITFIELDSIZE */
+                        global_bitopstruct.bitfieldarraysize=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_BITMINS:        /* BITMINSECONDS */
+                        global_bitopstruct.request_secs=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_DOEMF:          /* DOEMF */
+                        tests_to_do[TF_FPEMU]=getflag(eptr);
+                        break;
+
+                case PF_EMFASIZE:       /* EMFARRAYSIZE */
+                        global_emfloatstruct.arraysize=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_EMFLOOPS:       /* EMFLOOPS */
+                        global_emfloatstruct.loops=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_EMFMINS:        /* EMFMINSECOND */
+                        global_emfloatstruct.request_secs=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_DOFOUR: /* DOFOUR */
+                        tests_to_do[TF_FFPU]=getflag(eptr);
+                        break;
+
+                case PF_FOURASIZE:      /* FOURASIZE */
+                        global_fourierstruct.arraysize=
+                                (ulong)atol(eptr);
+                        global_fourierstruct.adjust=1;
+                        break;
+
+                case PF_FOURMINS:       /* FOURMINSECONDS */
+                        global_fourierstruct.request_secs=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_DOASSIGN:       /* DOASSIGN */
+                        tests_to_do[TF_ASSIGN]=getflag(eptr);
+                        break;
+
+                case PF_AARRAYS:        /* ASSIGNARRAYS */
+                        global_assignstruct.numarrays=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_ASSIGNMINS:     /* ASSIGNMINSECONDS */
+                        global_assignstruct.request_secs=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_DOIDEA: /* DOIDEA */
+                        tests_to_do[TF_IDEA]=getflag(eptr);
+                        break;
+
+                case PF_IDEAASIZE:      /* IDEAARRAYSIZE */
+                        global_ideastruct.arraysize=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_IDEALOOPS:      /* IDEALOOPS */
+                        global_ideastruct.loops=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_IDEAMINS:       /* IDEAMINSECONDS */
+                        global_ideastruct.request_secs=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_DOHUFF: /* DOHUFF */
+                        tests_to_do[TF_HUFF]=getflag(eptr);
+                        break;
+
+                case PF_HUFFASIZE:      /* HUFFARRAYSIZE */
+                        global_huffstruct.arraysize=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_HUFFLOOPS:      /* HUFFLOOPS */
+                        global_huffstruct.loops=
+                                (ulong)atol(eptr);
+                        global_huffstruct.adjust=1;
+                        break;
+
+                case PF_HUFFMINS:       /* HUFFMINSECONDS */
+                        global_huffstruct.request_secs=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_DONNET: /* DONNET */
+                        tests_to_do[TF_NNET]=getflag(eptr);
+                        break;
+
+                case PF_NNETLOOPS:      /* NNETLOOPS */
+                        global_nnetstruct.loops=
+                                (ulong)atol(eptr);
+                        global_nnetstruct.adjust=1;
+                        break;
+
+                case PF_NNETMINS:       /* NNETMINSECONDS */
+                        global_nnetstruct.request_secs=
+                                (ulong)atol(eptr);
+                        break;
+
+                case PF_DOLU:           /* DOLU */
+                        tests_to_do[TF_LU]=getflag(eptr);
+                        break;
+
+                case PF_LUNARRAYS:      /* LUNUMARRAYS */
+                        global_lustruct.numarrays=
+                                (ulong)atol(eptr);
+                        global_lustruct.adjust=1;
+                        break;
+
+                case PF_LUMINS: /* LUMINSECONDS */
+                        global_lustruct.request_secs=
+                                (ulong)atol(eptr);
+                        break;
+
+                                case PF_ALIGN:          /* ALIGN */
+                                                global_align=atoi(eptr);
+                                                break;
+        }
+skipswitch:
+        continue;
+}       /* End while */
+
+return;
+}
+
+/************
+** getflag **
+*************
+** Return 1 if cptr points to "T"; 0 otherwise.
+*/
+static int getflag(char *cptr)
+{
+        if(toupper((int)*cptr)=='T') return(1);
+return(0);
+}
+
+/***************
+** strtoupper **
+****************
+** Convert's a string to upper case.  The string is presumed
+** to consist only of alphabetic characters, and to be terminated
+** with a null.
+*/
+static void strtoupper(char *s)
+{
+
+do {
+/*
+** Oddly enough, the following line did not work under THINK C.
+** So, I modified it....hmmmm. --RG
+        *s++=(char)toupper((int)*s);
+*/
+        *s=(char)toupper((int)*s);
+        s++;
+} while(*s!=(char)'\0');
+return;
+}
+
+/*********************
+** set_request_secs **
+**********************
+** Set everyone's "request_secs" entry to whatever
+** value is in global_min_secs.  This is done
+** at the beginning, and possibly later if the
+** user redefines global_min_secs in the command file.
+*/
+static void set_request_secs(void)
+{
+
+global_numsortstruct.request_secs=global_min_seconds;
+global_strsortstruct.request_secs=global_min_seconds;
+global_bitopstruct.request_secs=global_min_seconds;
+global_emfloatstruct.request_secs=global_min_seconds;
+global_fourierstruct.request_secs=global_min_seconds;
+global_assignstruct.request_secs=global_min_seconds;
+global_ideastruct.request_secs=global_min_seconds;
+global_huffstruct.request_secs=global_min_seconds;
+global_nnetstruct.request_secs=global_min_seconds;
+global_lustruct.request_secs=global_min_seconds;
+
+return;
+}
+
+
+/**************************
+** bench_with_confidence **
+***************************
+** Given a benchmark id that indicates a function, this routine
+** repeatedly calls that benchmark, seeking to collect and replace
+** scores to get 5 that meet the confidence criteria.
+**
+** The above is mathematically questionable, as the statistical theory
+** depends on independent observations, and if we exchange data points
+** depending on what we already have then this certainly violates
+** independence of the observations. Hence I changed this so that at
+** most 30 observations are done, but none are deleted as we go
+** along. We simply do more runs and hope to get a big enough sample
+** size so that things stabilize. Uwe F. Mayer
+**
+** Return 0 if ok, -1 if failure.  Returns mean
+** and std. deviation of results if successful.
+*/
+static int bench_with_confidence(int fid,       /* Function id */
+        double *mean,                   /* Mean of scores */
+        double *stdev,                  /* Standard deviation */
+        ulong *numtries)                /* # of attempts */
+{
+double myscores[30];            /* Need at least 5 scores, use at most 30 */
+double c_half_interval;         /* Confidence half interval */
+int i;                          /* Index */
+/* double newscore; */          /* For improving confidence interval */
+
+/*
+** Get first 5 scores.  Then begin confidence testing.
+*/
+for (i=0;i<5;i++)
+{       (*funcpointer[fid])();
+        myscores[i]=getscore(fid);
+#ifdef DEBUG
+	printf("score # %d = %g\n", i, myscores[i]);
+#endif
+}
+*numtries=5;            /* Show 5 attempts */
+
+/*
+** The system allows a maximum of 30 tries before it gives
+** up.  Since we've done 5 already, we'll allow 25 more.
+*/
+
+/*
+** Enter loop to test for confidence criteria.
+*/
+while(1)
+{
+        /*
+        ** Calculate confidence. Should always return 0.
+        */
+        if (0!=calc_confidence(myscores,
+		*numtries,
+                &c_half_interval,
+                mean,
+                stdev)) return(-1);
+
+        /*
+        ** Is the length of the half interval 5% or less of mean?
+        ** If so, we can go home.  Otherwise, we have to continue.
+        */
+        if(c_half_interval/ (*mean) <= (double)0.05)
+                break;
+
+#ifdef OLDCODE
+#undef OLDCODE
+#endif
+#ifdef OLDCODE
+/* this code is no longer valid, we now do not replace but add new scores */
+/* Uwe F. Mayer */
+	      /*
+	      ** Go get a new score and see if it
+	      ** improves existing scores.
+	      */
+	      do {
+		      if(*numtries==10)
+			      return(-1);
+		      (*funcpointer[fid])();
+		      *numtries+=1;
+		      newscore=getscore(fid);
+	      } while(seek_confidence(myscores,&newscore,
+		      &c_half_interval,mean,stdev)==0);
+#endif
+	/* We now simply add a new test run and hope that the runs
+           finally stabilize, Uwe F. Mayer */
+	if(*numtries==30) return(-1);
+	(*funcpointer[fid])();
+	myscores[*numtries]=getscore(fid);
+#ifdef DEBUG
+	printf("score # %ld = %g\n", *numtries, myscores[*numtries]);
+#endif
+	*numtries+=1;
+}
+
+return(0);
+}
+
+#ifdef OLDCODE
+/* this procecdure is no longer needed, Uwe F. Mayer */
+  /********************
+  ** seek_confidence **
+  *********************
+  ** Pass this routine an array of 5 scores PLUS a new score.
+  ** This routine tries the new score in place of each of
+  ** the other five scores to determine if the new score,
+  ** when replacing one of the others, improves the confidence
+  ** half-interval.
+  ** Return 0 if failure.  Original 5 scores unchanged.
+  ** Return -1 if success.  Also returns new half-interval,
+  ** mean, and standard deviation of the sample.
+  */
+  static int seek_confidence( double scores[5],
+  		double *newscore,
+  		double *c_half_interval,
+  		double *smean,
+  		double *sdev)
+  {
+  double sdev_to_beat;    /* Original sdev to be beaten */
+  double temp;            /* For doing a swap */
+  int is_beaten;          /* Indicates original was beaten */
+  int i;                  /* Index */
+
+  /*
+  ** First calculate original standard deviation
+  */
+  calc_confidence(scores,c_half_interval,smean,sdev);
+  sdev_to_beat=*sdev;
+  is_beaten=-1;
+
+  /*
+  ** Try to beat original score.  We'll come out of this
+  ** loop with a flag.
+  */
+  for(i=0;i<5;i++)
+  {
+  	temp=scores[i];
+  	scores[i]=*newscore;
+  	calc_confidence(scores,c_half_interval,smean,sdev);
+  	scores[i]=temp;
+  	if(sdev_to_beat>*sdev)
+  	{       is_beaten=i;
+  		sdev_to_beat=*sdev;
+  	}
+  }
+
+  if(is_beaten!=-1)
+  {       scores[is_beaten]=*newscore;
+  	return(-1);
+  }
+  return(0);
+  }
+#endif
+
+/********************
+** calc_confidence **
+*********************
+** Given a set of numtries scores, calculate the confidence
+** half-interval.  We'll also return the sample mean and sample
+** standard deviation.
+** NOTE: This routines presumes a confidence of 95% and
+** a confidence coefficient of .95
+** returns 0 if there is an error, otherwise -1
+*/
+static int calc_confidence(double scores[], /* Array of scores */
+		int num_scores,             /* number of scores in array */
+                double *c_half_interval,    /* Confidence half-int */
+                double *smean,              /* Standard mean */
+                double *sdev)               /* Sample stand dev */
+{
+/* Here is a list of the student-t distribution up to 29 degrees of
+   freedom. The value at 0 is bogus, as there is no value for zero
+   degrees of freedom. */
+double student_t[30]={0.0 , 12.706 , 4.303 , 3.182 , 2.776 , 2.571 ,
+                             2.447 , 2.365 , 2.306 , 2.262 , 2.228 ,
+                             2.201 , 2.179 , 2.160 , 2.145 , 2.131 ,
+                             2.120 , 2.110 , 2.101 , 2.093 , 2.086 ,
+                             2.080 , 2.074 , 2.069 , 2.064 , 2.060 ,
+		             2.056 , 2.052 , 2.048 , 2.045 };
+int i;          /* Index */
+if ((num_scores<2) || (num_scores>30)) {
+  output_string("Internal error: calc_confidence called with an illegal number of scores\n");
+  return(-1);
+}
+/*
+** First calculate mean.
+*/
+*smean=(double)0.0;
+for(i=0;i<num_scores;i++){
+  *smean+=scores[i];
+}
+*smean/=(double)num_scores;
+
+/* Get standard deviation */
+*sdev=(double)0.0;
+for(i=0;i<num_scores;i++) {
+  *sdev+=(scores[i]-(*smean))*(scores[i]-(*smean));
+}
+*sdev/=(double)(num_scores-1);
+*sdev=sqrt(*sdev);
+
+/* Now calculate the length of the confidence half-interval.  For a
+** confidence level of 95% our confidence coefficient gives us a
+** multiplying factor of the upper .025 quartile of a t distribution
+** with num_scores-1 degrees of freedom, and dividing by sqrt(number of
+** observations). See any introduction to statistics.
+*/
+*c_half_interval=student_t[num_scores-1] * (*sdev) / sqrt((double)num_scores);
+return(0);
+}
+
+/*************
+** getscore **
+**************
+** Return the score for a particular benchmark.
+*/
+static double getscore(int fid)
+{
+
+/*
+** Fid tells us the function.  This is really a matter of
+** doing the proper coercion.
+*/
+switch(fid)
+{
+        case TF_NUMSORT:
+                return(global_numsortstruct.sortspersec);
+        case TF_SSORT:
+                return(global_strsortstruct.sortspersec);
+        case TF_BITOP:
+                return(global_bitopstruct.bitopspersec);
+        case TF_FPEMU:
+                return(global_emfloatstruct.emflops);
+        case TF_FFPU:
+                return(global_fourierstruct.fflops);
+        case TF_ASSIGN:
+                return(global_assignstruct.iterspersec);
+        case TF_IDEA:
+                return(global_ideastruct.iterspersec);
+        case TF_HUFF:
+                return(global_huffstruct.iterspersec);
+        case TF_NNET:
+                return(global_nnetstruct.iterspersec);
+        case TF_LU:
+                return(global_lustruct.iterspersec);
+}
+return((double)0.0);
+}
+
+/******************
+** output_string **
+*******************
+** Displays a string on the screen.  Also, if the flag
+** write_to_file is set, outputs the string to the output file.
+** Note, this routine presumes that you've included a carriage
+** return at the end of the buffer.
+*/
+static void output_string(char *buffer)
+{
+
+printf("%s",buffer);
+if(write_to_file!=0)
+        fprintf(global_ofile,"%s",buffer);
+return;
+}
+
+/***************
+** show_stats **
+****************
+** This routine displays statistics for a particular benchmark.
+** The benchmark is identified by its id.
+*/
+static void show_stats (int bid)
+{
+char buffer[80];        /* Display buffer */
+
+switch(bid)
+{
+        case TF_NUMSORT:                /* Numeric sort */
+                sprintf(buffer,"  Number of arrays: %d\n",
+                        global_numsortstruct.numarrays);
+                output_string(buffer);
+                sprintf(buffer,"  Array size: %ld\n",
+                        global_numsortstruct.arraysize);
+                output_string(buffer);
+                break;
+
+        case TF_SSORT:          /* String sort */
+                sprintf(buffer,"  Number of arrays: %d\n",
+                        global_strsortstruct.numarrays);
+                output_string(buffer);
+                sprintf(buffer,"  Array size: %ld\n",
+                        global_strsortstruct.arraysize);
+                output_string(buffer);
+                break;
+
+        case TF_BITOP:          /* Bitmap operation */
+                sprintf(buffer,"  Operations array size: %ld\n",
+                        global_bitopstruct.bitoparraysize);
+                output_string(buffer);
+                sprintf(buffer,"  Bitfield array size: %ld\n",
+                        global_bitopstruct.bitfieldarraysize);
+                output_string(buffer);
+                break;
+
+        case TF_FPEMU:          /* Floating-point emulation */
+                sprintf(buffer,"  Number of loops: %lu\n",
+                        global_emfloatstruct.loops);
+                output_string(buffer);
+                sprintf(buffer,"  Array size: %lu\n",
+                        global_emfloatstruct.arraysize);
+                output_string(buffer);
+                break;
+
+        case TF_FFPU:           /* Fourier test */
+                sprintf(buffer,"  Number of coefficients: %lu\n",
+                        global_fourierstruct.arraysize);
+                output_string(buffer);
+                break;
+
+        case TF_ASSIGN:
+                sprintf(buffer,"  Number of arrays: %lu\n",
+                        global_assignstruct.numarrays);
+                output_string(buffer);
+                break;
+
+        case TF_IDEA:
+                sprintf(buffer,"  Array size: %lu\n",
+                        global_ideastruct.arraysize);
+                output_string(buffer);
+                sprintf(buffer," Number of loops: %lu\n",
+                        global_ideastruct.loops);
+                output_string(buffer);
+                break;
+
+        case TF_HUFF:
+                sprintf(buffer,"  Array size: %lu\n",
+                        global_huffstruct.arraysize);
+                output_string(buffer);
+                sprintf(buffer,"  Number of loops: %lu\n",
+                        global_huffstruct.loops);
+                output_string(buffer);
+                break;
+
+        case TF_NNET:
+                sprintf(buffer,"  Number of loops: %lu\n",
+                        global_nnetstruct.loops);
+                output_string(buffer);
+                break;
+
+        case TF_LU:
+                sprintf(buffer,"  Number of arrays: %lu\n",
+                        global_lustruct.numarrays);
+                output_string(buffer);
+                break;
+}
+return;
+}
+
+/*
+** Following code added for Mac stuff, so that we can emulate command
+** lines.
+*/
+
+#ifdef MAC
+
+/*****************
+** UCommandLine **
+******************
+** Reads in a command line, and sets up argc and argv appropriately.
+** Note that this routine uses gets() to read in the line.  This means
+** you'd better not enter more than 128 characters on a command line, or
+** things will overflow, and oh boy...
+*/
+void UCommandLine(void)
+{
+printf("Enter command line\n:");
+gets((char *)Uargbuff);
+UParse();
+return;
+}
+
+/***********
+** UParse **
+************
+** Parse the pseudo command-line.  This code appeared as part of the
+** Small-C library in Dr. Dobb's ToolBook of C.
+** It expects the following globals:
+** argc = arg count
+** argv = Pointer to array of char pointers
+** Uargbuff = Character array that holds the arguments.  Should be 129 bytes long.
+** Udummy1 = This is a 2-byte buffer that holds a "*", and acts as the first
+**  argument in the argument list.  This maintains compatibility with other
+**  C's, though it does not provide access to the executable filename.
+** This routine allows for up to 20 individual command-line arguments.
+** Also note that this routine does NOT allow for redirection.
+*/
+void UParse(void)
+{
+unsigned char *ptr;
+
+argc=0;         /* Start arg count */
+Udummy[0]='*';  /* Set dummy first argument */
+Udummy[1]='\0';
+argv[argc++]=(char *)Udummy;
+
+ptr=Uargbuff;           /* Start pointer */
+while(*ptr)
+{
+        if(isspace(*ptr))
+        {       ++ptr;
+                continue;
+        }
+        if(argc<20) argv[argc++]=(char *)ptr;
+        ptr=UField(ptr);
+}
+return;
+}
+/***********
+** UField **
+************
+** Isolate the next command-line field.
+*/
+unsigned char *UField(unsigned char *ptr)
+{
+while(*ptr)
+{       if(isspace(*ptr))
+        {       *ptr=(unsigned char)NULL;
+                return(++ptr);
+        }
+        ++ptr;
+}
+return(ptr);
+}
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/nbench0.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/nbench0.h?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/nbench0.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/nbench0.h Sun Jan 22 03:50:58 2012
@@ -0,0 +1,356 @@
+/*
+** nbench0.h
+** Header for nbench0.c
+** BYTEmark (tm)
+** BYTE's Native Mode Benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Creation:
+** Revision: 3/95;10/95
+**  10/95 - Added memory array & alignment -- RG
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/*
+** Following should be modified accordingly per each
+** compilation.
+*/
+char *sysname="You can enter your system description in nbench0.h";
+char *compilername="It then will be printed here after you recompile";
+char *compilerversion="Have a nice day";
+
+/*  Parameter flags.  Must coincide with parameter names array
+** which appears below. */
+#define PF_GMTICKS 0            /* GLOBALMINTICKS */
+#define PF_MINSECONDS 1         /* MINSECONDS */
+#define PF_ALLSTATS 2           /* ALLSTATS */
+#define PF_OUTFILE 3            /* OUTFILE */
+#define PF_CUSTOMRUN 4          /* CUSTOMRUN */
+#define PF_DONUM 5              /* DONUMSORT */
+#define PF_NUMNUMA 6            /* NUMNUMARRAYS */
+#define PF_NUMASIZE 7           /* NUMARRAYSIZE */
+#define PF_NUMMINS 8            /* NUMMINSECONDS */
+#define PF_DOSTR 9              /* DOSTRINGSORT */
+#define PF_STRASIZE 10          /* STRARRAYSIZE */
+#define PF_NUMSTRA 11           /* NUMSTRARRAYS */
+#define PF_STRMINS 12           /* STRMINSECONDS */
+#define PF_DOBITF 13            /* DOBITFIELD */
+#define PF_NUMBITOPS 14         /* NUMBITOPS */
+#define PF_BITFSIZE 15          /* BITFIELDSIZE */
+#define PF_BITMINS 16           /* BITMINSECONDS */
+#define PF_DOEMF 17             /* DOEMF */
+#define PF_EMFASIZE 18          /* EMFARRAYSIZE */
+#define PF_EMFLOOPS 19          /* EMFLOOPS */
+#define PF_EMFMINS 20           /* EMFMINSECOND */
+#define PF_DOFOUR 21            /* DOFOUR */
+#define PF_FOURASIZE 22         /* FOURASIZE */
+#define PF_FOURMINS 23          /* FOURMINSECONDS */
+#define PF_DOASSIGN 24          /* DOASSIGN */
+#define PF_AARRAYS 25           /* ASSIGNARRAYS */
+#define PF_ASSIGNMINS 26        /* ASSIGNMINSECONDS */
+#define PF_DOIDEA 27            /* DOIDEA */
+#define PF_IDEAASIZE 28         /* IDEAARRAYSIZE */
+#define PF_IDEALOOPS 29         /* IDEALOOPS */
+#define PF_IDEAMINS 30          /* IDEAMINSECONDS */
+#define PF_DOHUFF 31            /* DOHUFF */
+#define PF_HUFFASIZE 32         /* HUFFARRAYSIZE */
+#define PF_HUFFLOOPS 33         /* HUFFLOOPS */
+#define PF_HUFFMINS 34          /* HUFFMINSECONDS */
+#define PF_DONNET 35            /* DONNET */
+#define PF_NNETLOOPS 36         /* NNETLOOPS */
+#define PF_NNETMINS 37          /* NNETMINSECONDS */
+#define PF_DOLU 38              /* DOLU */
+#define PF_LUNARRAYS 39         /* LUNUMARRAYS */
+#define PF_LUMINS 40            /* LUMINSECONDS */
+#define PF_ALIGN 41		        /* ALIGN */
+
+#define MAXPARAM 41
+
+/* Tests-to-do flags...must coincide with test. */
+#define TF_NUMSORT 0
+#define TF_SSORT 1
+#define TF_BITOP 2
+#define TF_FPEMU 3
+#define TF_FFPU 4
+#define TF_ASSIGN 5
+#define TF_IDEA 6
+#define TF_HUFF 7
+#define TF_NNET 8
+#define TF_LU 9
+
+#define NUMTESTS 10
+
+/*
+** GLOBALS
+*/
+
+#define BUF_SIZ 1024
+
+/*
+** Test names
+*/
+char *ftestnames[] = {
+        "NUMERIC SORT    ",
+        "STRING SORT     ",
+        "BITFIELD        ",
+        "FP EMULATION    ",
+        "FOURIER         ",
+        "ASSIGNMENT      ",
+        "IDEA            ",
+        "HUFFMAN         ",
+        "NEURAL NET      ",
+        "LU DECOMPOSITION" };
+
+/*
+** Indexes -- Baseline is DELL Pentium XP90
+** 11/28/94
+*/
+double bindex[] = {
+    38.993,                     /* Numeric sort */
+    2.238,                      /* String sort */
+    5829704,                    /* Bitfield */
+    2.084,                      /* FP Emulation */
+    879.278,                    /* Fourier */
+    .2628,                      /* Assignment */
+    65.382,                     /* IDEA */
+    36.062,                     /* Huffman */
+    .6225,                      /* Neural Net */
+    19.3031 };                  /* LU Decomposition */
+
+/*
+** Indices -- Baseline is a AMD K6-233, 32MB RAM (60ns SDRAM),512k L2 cache,
+** Linux kernel 2.0.32, libc-5.4.38, gcc-2.7.2.3)
+** Nov/30/97
+*/
+double lx_bindex[] = {
+      118.73, 	    /* Numeric sort */
+      14.459,	    /* String sort */
+    27910000,	    /* Bitfield */
+      9.0314,	    /* FP Emulation */
+      1565.5,	    /* Fourier */
+      1.0132,	    /* Assignment */
+      220.21,	    /* IDEA */
+      112.93,	    /* Huffman */
+      1.4799,	    /* Neural Net */
+      26.732};      /* LU Decomposition */
+
+/* Parameter names */
+char *paramnames[]= {
+        "GLOBALMINTICKS",
+        "MINSECONDS",
+        "ALLSTATS",
+        "OUTFILE",
+        "CUSTOMRUN",
+        "DONUMSORT",
+        "NUMNUMARRAYS",
+        "NUMARRAYSIZE",
+        "NUMMINSECONDS",
+        "DOSTRINGSORT",
+        "STRARRAYSIZE",
+        "NUMSTRARRAYS",
+        "STRMINSECONDS",
+        "DOBITFIELD",
+        "NUMBITOPS",
+        "BITFIELDSIZE",
+        "BITMINSECONDS",
+        "DOEMF",
+        "EMFARRAYSIZE",
+        "EMFLOOPS",
+        "EMFMINSECONDS",
+        "DOFOUR",
+        "FOURSIZE",
+        "FOURMINSECONDS",
+        "DOASSIGN",
+        "ASSIGNARRAYS",
+        "ASSIGNMINSECONDS",
+        "DOIDEA",
+        "IDEARRAYSIZE",
+        "IDEALOOPS",
+        "IDEAMINSECONDS",
+        "DOHUFF",
+        "HUFARRAYSIZE",
+        "HUFFLOOPS",
+        "HUFFMINSECONDS",
+        "DONNET",
+        "NNETLOOPS",
+        "NNETMINSECONDS",
+        "DOLU",
+        "LUNUMARRAYS",
+        "LUMINSECONDS",
+	"ALIGN" };
+
+/*
+** Following array is a collection of flags indicating which
+** tests to perform.
+*/
+int tests_to_do[NUMTESTS];
+
+/*
+** Buffer for holding output text.
+*/
+char buffer[BUF_SIZ];
+
+/*
+** Global parameters.
+*/
+ulong global_min_ticks;         /* Minimum ticks */
+ulong global_min_seconds;       /* Minimum seconds tests run */
+int global_allstats;            /* Statistics dump flag */
+char global_ofile_name[BUF_SIZ];/* Output file name */
+FILE *global_ofile;             /* Output file */
+int global_custrun;             /* Custom run flag */
+int write_to_file;              /* Write output to file */
+int global_align;		/* Memory alignment */
+
+/*
+** Following global is the memory array.  This is used to store
+** original and aligned (modified) memory addresses.
+*/
+ulong mem_array[2][MEM_ARRAY_SIZE];
+int mem_array_ents;		/* # of active entries */
+
+/*
+** Following are global structures, one built for
+** each of the tests.
+*/
+SortStruct global_numsortstruct;        /* For numeric sort */
+SortStruct global_strsortstruct;        /* For string sort */
+BitOpStruct global_bitopstruct;         /* For bitfield operations */
+EmFloatStruct global_emfloatstruct;     /* For emul. float. point */
+FourierStruct global_fourierstruct;     /* For fourier test */
+AssignStruct global_assignstruct;       /* For assignment algorithm */
+IDEAStruct global_ideastruct;           /* For IDEA encryption */
+HuffStruct global_huffstruct;           /* For Huffman compression */
+NNetStruct global_nnetstruct;           /* For Neural Net */
+LUStruct global_lustruct;               /* For LU decomposition */
+
+/*
+** The following array of function struct pointers lets
+** us very rapidly map a function to its controlling
+** data structure. NOTE: These must match the "TF_xxx"
+** constants above.
+*/
+void *global_fstruct[] =
+{       (void *)&global_numsortstruct,
+        (void *)&global_strsortstruct,
+        (void *)&global_bitopstruct,
+        (void *)&global_emfloatstruct,
+        (void *)&global_fourierstruct,
+        (void *)&global_assignstruct,
+        (void *)&global_ideastruct,
+        (void *)&global_huffstruct,
+        (void *)&global_nnetstruct,
+        (void *)&global_lustruct };
+
+/*
+** Following globals added to support command line emulation on
+** the Macintosh....which doesn't have command lines.
+*/
+#ifdef MAC
+int argc;                       /* Argument count */
+char *argv[20];                 /* Argument vectors */
+
+unsigned char Uargbuff[129];    /* Buffer holding arguments string */
+unsigned char Udummy[2];        /* Dummy buffer for first arg */
+
+#endif
+
+#ifdef MACTIMEMGR
+#include <Types.h>
+#include <Timer.h>
+/*
+** Timer globals for Mac
+*/
+struct TMTask myTMTask;
+long MacHSTdelay,MacHSTohead;
+
+#endif
+
+/*
+** Following globals used by Win 31 timing routines.
+** NOTE: This requires the includes of the w31timer.asm
+** file in your project!!
+*/
+#ifdef WIN31TIMER
+#include <windows.h>
+#include <toolhelp.h>
+extern TIMERINFO win31tinfo;
+extern HANDLE hThlp;
+extern FARPROC lpfn;
+#endif
+
+/*
+** PROTOTYPES
+*/
+static int parse_arg(char *argptr);
+static void display_help(char *progname);
+static void read_comfile(FILE *cfile);
+static int getflag(char *cptr);
+static void strtoupper(char *s);
+static void set_request_secs(void);
+static int bench_with_confidence(int fid,
+        double *mean, double *stdev, ulong *numtries);
+/*
+static int seek_confidence(double scores[5],
+        double *newscore, double *c_half_interval,
+        double *smean,double *sdev);
+*/
+static int calc_confidence(double scores[],
+        int num_scores,
+        double *c_half_interval,double *smean,
+        double *sdev);
+static double getscore(int fid);
+static void output_string(char *buffer);
+static void show_stats(int bid);
+
+#ifdef MAC
+void UCommandLine(void);
+void UParse(void);
+unsigned char *UField(unsigned char *ptr);
+#endif
+
+/*
+** EXTERNAL PROTOTYPES
+*/
+extern void DoNumSort(void);    /* From NBENCH1 */
+extern void DoStringSort(void);
+extern void DoBitops(void);
+extern void DoEmFloat(void);
+extern void DoFourier(void);
+extern void DoAssign(void);
+extern void DoIDEA(void);
+extern void DoHuffman(void);
+extern void DoNNET(void);
+extern void DoLU(void);
+
+extern void ErrorExit(void);    /* From SYSSPEC */
+
+/*
+** Array of pointers to the benchmark functions.
+*/
+void (*funcpointer[])(void) =
+{       DoNumSort,
+        DoStringSort,
+        DoBitops,
+        DoEmFloat,
+        DoFourier,
+        DoAssign,
+        DoIDEA,
+        DoHuffman,
+        DoNNET,
+        DoLU };
+
+

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/nbench1.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/nbench1.c?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/nbench1.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/nbench1.c Sun Jan 22 03:50:58 2012
@@ -0,0 +1,4444 @@
+
+/*
+** nbench1.c
+*/
+
+/********************************
+**       BYTEmark (tm)         **
+** BYTE NATIVE MODE BENCHMARKS **
+**       VERSION 2             **
+**                             **
+** Included in this source     **
+** file:                       **
+**  Numeric Heapsort           **
+**  String Heapsort            **
+**  Bitfield test              **
+**  Floating point emulation   **
+**  Fourier coefficients       **
+**  Assignment algorithm       **
+**  IDEA Encyption             **
+**  Huffman compression        **
+**  Back prop. neural net      **
+**  LU Decomposition           **
+**    (linear equations)       **
+** ----------                  **
+** Rick Grehan, BYTE Magazine  **
+*********************************
+**
+** BYTEmark (tm)
+** BYTE's Native Mode Benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Creation:
+** Revision: 3/95;10/95
+**  10/95 - Removed allocation that was taking place inside
+**   the LU Decomposition benchmark. Though it didn't seem to
+**   make a difference on systems we ran it on, it nonetheless
+**   removes an operating system dependency that probably should
+**   not have been there.
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/*
+** INCLUDES
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <math.h>
+#include "nmglobal.h"
+#include "nbench1.h"
+#include "wordcat.h"
+
+#ifdef DEBUG
+static int numsort_status=0;
+static int stringsort_status=0;
+#endif
+
+/*********************
+** NUMERIC HEAPSORT **
+**********************
+** This test implements a heapsort algorithm, performed on an
+** array of longs.
+*/
+
+/**************
+** DoNumSort **
+***************
+** This routine performs the CPU numeric sort test.
+** NOTE: Last version incorrectly stated that the routine
+**  returned result in # of longword sorted per second.
+**  Not so; the routine returns # of iterations per sec.
+*/
+
+void DoNumSort(void)
+{
+SortStruct *numsortstruct;      /* Local pointer to global struct */
+farlong *arraybase;     /* Base pointers of array */
+long accumtime;         /* Accumulated time */
+double iterations;      /* Iteration counter */
+char *errorcontext;     /* Error context string pointer */
+int systemerror;        /* For holding error codes */
+
+/*
+** Link to global structure
+*/
+numsortstruct=&global_numsortstruct;
+
+/*
+** Set the error context string.
+*/
+errorcontext="CPU:Numeric Sort";
+
+/*
+** See if we need to do self adjustment code.
+*/
+if(numsortstruct->adjust==0)
+{
+	/*
+	** Self-adjustment code.  The system begins by sorting 1
+	** array.  If it does that in no time, then two arrays
+	** are built and sorted.  This process continues until
+	** enough arrays are built to handle the tolerance.
+	*/
+	numsortstruct->numarrays=1;
+	while(1)
+	{
+		/*
+		** Allocate space for arrays
+		*/
+		arraybase=(farlong *)AllocateMemory(sizeof(long) *
+			numsortstruct->numarrays * numsortstruct->arraysize,
+			&systemerror);
+		if(systemerror)
+		{       ReportError(errorcontext,systemerror);
+			FreeMemory((farvoid *)arraybase,
+				  &systemerror);
+			ErrorExit();
+		}
+
+		/*
+		** Do an iteration of the numeric sort.  If the
+		** elapsed time is less than or equal to the permitted
+		** minimum, then allocate for more arrays and
+		** try again.
+		*/
+		if(DoNumSortIteration(arraybase,
+			numsortstruct->arraysize,
+			numsortstruct->numarrays)>global_min_ticks)
+			break;          /* We're ok...exit */
+
+		FreeMemory((farvoid *)arraybase,&systemerror);
+		if(numsortstruct->numarrays++>NUMNUMARRAYS)
+		{       printf("CPU:NSORT -- NUMNUMARRAYS hit.\n");
+			ErrorExit();
+		}
+	}
+}
+else
+{       /*
+	** Allocate space for arrays
+	*/
+	arraybase=(farlong *)AllocateMemory(sizeof(long) *
+		numsortstruct->numarrays * numsortstruct->arraysize,
+		&systemerror);
+	if(systemerror)
+	{       ReportError(errorcontext,systemerror);
+		FreeMemory((farvoid *)arraybase,
+			  &systemerror);
+		ErrorExit();
+	}
+
+}
+/*
+** All's well if we get here.  Repeatedly perform sorts until the
+** accumulated elapsed time is greater than # of seconds requested.
+*/
+accumtime=0L;
+iterations=(double)0.0;
+
+do {
+	accumtime+=DoNumSortIteration(arraybase,
+		numsortstruct->arraysize,
+		numsortstruct->numarrays);
+	iterations+=(double)1.0;
+} while(iterations < BASE_ITERATIONS * 15);
+
+/*
+** Clean up, calculate results, and go home.  Be sure to
+** show that we don't have to rerun adjustment code.
+*/
+FreeMemory((farvoid *)arraybase,&systemerror);
+
+numsortstruct->sortspersec=iterations *
+	(double)numsortstruct->numarrays / TicksToFracSecs(accumtime);
+
+if(numsortstruct->adjust==0)
+	numsortstruct->adjust=1;
+
+#ifdef DEBUG
+if (numsort_status==0) printf("Numeric sort: OK\n");
+numsort_status=0;
+#endif
+return;
+}
+
+/***********************
+** DoNumSortIteration **
+************************
+** This routine executes one iteration of the numeric
+** sort benchmark.  It returns the number of ticks
+** elapsed for the iteration.
+*/
+static ulong DoNumSortIteration(farlong *arraybase,
+		ulong arraysize,
+		uint numarrays)
+{
+ulong elapsed;          /* Elapsed ticks */
+ulong i;
+/*
+** Load up the array with random numbers
+*/
+LoadNumArrayWithRand(arraybase,arraysize,numarrays);
+
+/*
+** Start the stopwatch
+*/
+elapsed=StartStopwatch();
+
+/*
+** Execute a heap of heapsorts
+*/
+for(i=0;i<numarrays;i++)
+	NumHeapSort(arraybase+i*arraysize,0L,arraysize-1L);
+
+/*
+** Get elapsed time
+*/
+elapsed=StopStopwatch(elapsed);
+#ifdef DEBUG
+{
+	for(i=0;i<arraysize-1;i++)
+	{       /*
+		** Compare to check for proper
+		** sort.
+		*/
+		if(arraybase[i+1]<arraybase[i])
+		{       printf("Sort Error\n");
+			numsort_status=1;
+                        break;
+		}
+	}
+}
+#endif
+
+return(elapsed);
+}
+
+/*************************
+** LoadNumArrayWithRand **
+**************************
+** Load up an array with random longs.
+*/
+static void LoadNumArrayWithRand(farlong *array,     /* Pointer to arrays */
+		ulong arraysize,
+		uint numarrays)         /* # of elements in array */
+{
+long i;                 /* Used for index */
+farlong *darray;        /* Destination array pointer */
+/*
+** Initialize the random number generator
+*/
+/* randnum(13L); */
+randnum((int32)13);
+
+/*
+** Load up first array with randoms
+*/
+for(i=0L;i<arraysize;i++)
+        /* array[i]=randnum(0L); */
+	array[i]=randnum((int32)0);
+
+/*
+** Now, if there's more than one array to load, copy the
+** first into each of the others.
+*/
+darray=array;
+while(--numarrays)
+{       darray+=arraysize;
+	for(i=0L;i<arraysize;i++)
+		darray[i]=array[i];
+}
+
+return;
+}
+
+/****************
+** NumHeapSort **
+*****************
+** Pass this routine a pointer to an array of long
+** integers.  Also pass in minimum and maximum offsets.
+** This routine performs a heap sort on that array.
+*/
+static void NumHeapSort(farlong *array,
+	ulong bottom,           /* Lower bound */
+	ulong top)              /* Upper bound */
+{
+ulong temp;                     /* Used to exchange elements */
+ulong i;                        /* Loop index */
+
+/*
+** First, build a heap in the array
+*/
+for(i=(top/2L); i>0; --i)
+	NumSift(array,i,top);
+
+/*
+** Repeatedly extract maximum from heap and place it at the
+** end of the array.  When we get done, we'll have a sorted
+** array.
+*/
+for(i=top; i>0; --i)
+{       NumSift(array,bottom,i);
+	temp=*array;                    /* Perform exchange */
+	*array=*(array+i);
+	*(array+i)=temp;
+}
+return;
+}
+
+/************
+** NumSift **
+*************
+** Peforms the sift operation on a numeric array,
+** constructing a heap in the array.
+*/
+static void NumSift(farlong *array,     /* Array of numbers */
+	ulong i,                /* Minimum of array */
+	ulong j)                /* Maximum of array */
+{
+unsigned long k;
+long temp;                              /* Used for exchange */
+
+while((i+i)<=j)
+{
+	k=i+i;
+	if(k<j)
+		if(array[k]<array[k+1L])
+			++k;
+	if(array[i]<array[k])
+	{
+		temp=array[k];
+		array[k]=array[i];
+		array[i]=temp;
+		i=k;
+	}
+	else
+		i=j+1;
+}
+return;
+}
+
+/********************
+** STRING HEAPSORT **
+********************/
+
+/*****************
+** DoStringSort **
+******************
+** This routine performs the CPU string sort test.
+** Arguments:
+**      requested_secs = # of seconds to execute test
+**      stringspersec = # of strings per second sorted (RETURNED)
+*/
+void DoStringSort(void)
+{
+
+SortStruct *strsortstruct;      /* Local for sort structure */
+faruchar *arraybase;            /* Base pointer of char array */
+long accumtime;                 /* Accumulated time */
+double iterations;              /* # of iterations */
+char *errorcontext;             /* Error context string pointer */
+int systemerror;                /* For holding error code */
+
+/*
+** Link to global structure
+*/
+strsortstruct=&global_strsortstruct;
+
+/*
+** Set the error context
+*/
+errorcontext="CPU:String Sort";
+
+/*
+** See if we have to perform self-adjustment code
+*/
+if(strsortstruct->adjust==0)
+{
+	/*
+	** Initialize the number of arrays.
+	*/
+	strsortstruct->numarrays=1;
+	while(1)
+	{
+		/*
+		** Allocate space for array.  We'll add an extra 100
+		** bytes to protect memory as strings move around
+		** (this can happen during string adjustment)
+		*/
+		arraybase=(faruchar *)AllocateMemory((strsortstruct->arraysize+100L) *
+			(long)strsortstruct->numarrays,&systemerror);
+		if(systemerror)
+		{       ReportError(errorcontext,systemerror);
+			ErrorExit();
+		}
+
+		/*
+		** Do an iteration of the string sort.  If the
+		** elapsed time is less than or equal to the permitted
+		** minimum, then de-allocate the array, reallocate a
+		** an additional array, and try again.
+		*/
+		if(DoStringSortIteration(arraybase,
+			strsortstruct->numarrays,
+			strsortstruct->arraysize)>global_min_ticks)
+			break;          /* We're ok...exit */
+
+		FreeMemory((farvoid *)arraybase,&systemerror);
+		strsortstruct->numarrays+=1;
+	}
+}
+else
+{
+	/*
+	** We don't have to perform self adjustment code.
+	** Simply allocate the space for the array.
+	*/
+	arraybase=(faruchar *)AllocateMemory((strsortstruct->arraysize+100L) *
+		(long)strsortstruct->numarrays,&systemerror);
+	if(systemerror)
+	{       ReportError(errorcontext,systemerror);
+		ErrorExit();
+	}
+}
+/*
+** All's well if we get here.  Repeatedly perform sorts until the
+** accumulated elapsed time is greater than # of seconds requested.
+*/
+accumtime=0L;
+iterations=(double)0.0;
+
+do {
+	accumtime+=DoStringSortIteration(arraybase,
+				strsortstruct->numarrays,
+				strsortstruct->arraysize);
+	iterations+=(double)strsortstruct->numarrays;
+} while(iterations < BASE_ITERATIONS * 5);
+
+/*
+** Clean up, calculate results, and go home.
+** Set flag to show we don't need to rerun adjustment code.
+*/
+FreeMemory((farvoid *)arraybase,&systemerror);
+strsortstruct->sortspersec=iterations / (double)TicksToFracSecs(accumtime);
+if(strsortstruct->adjust==0)
+	strsortstruct->adjust=1;
+#ifdef DEBUG
+if (stringsort_status==0) printf("String sort: OK\n");
+stringsort_status=0;
+#endif
+return;
+}
+
+/**************************
+** DoStringSortIteration **
+***************************
+** This routine executes one iteration of the string
+** sort benchmark.  It returns the number of ticks
+** Note that this routine also builds the offset pointer
+** array.
+*/
+static ulong DoStringSortIteration(faruchar *arraybase,
+		uint numarrays,ulong arraysize)
+{
+farulong *optrarray;            /* Offset pointer array */
+unsigned long elapsed;          /* Elapsed ticks */
+unsigned long nstrings;         /* # of strings in array */
+int syserror;                   /* System error code */
+unsigned int i;                 /* Index */
+farulong *tempobase;            /* Temporary offset pointer base */
+faruchar *tempsbase;            /* Temporary string base pointer */
+
+/*
+** Load up the array(s) with random numbers
+*/
+optrarray=LoadStringArray(arraybase,numarrays,&nstrings,arraysize);
+
+/*
+** Set temp base pointers...they will be modified as the
+** benchmark proceeds.
+*/
+tempobase=optrarray;
+tempsbase=arraybase;
+
+/*
+** Start the stopwatch
+*/
+elapsed=StartStopwatch();
+
+/*
+** Execute heapsorts
+*/
+for(i=0;i<numarrays;i++)
+{       StrHeapSort(tempobase,tempsbase,nstrings,0L,nstrings-1);
+	tempobase+=nstrings;    /* Advance base pointers */
+	tempsbase+=arraysize+100;
+}
+
+/*
+** Record elapsed time
+*/
+elapsed=StopStopwatch(elapsed);
+
+#ifdef DEBUG
+{
+	unsigned long i;
+	for(i=0;i<nstrings-1;i++)
+	{       /*
+		** Compare strings to check for proper
+		** sort.
+		*/
+		if(str_is_less(optrarray,arraybase,nstrings,i+1,i))
+		{       printf("Sort Error\n");
+			stringsort_status=1;
+                        break;
+		}
+	}
+}
+#endif
+
+/*
+** Release the offset pointer array built by
+** LoadStringArray()
+*/
+FreeMemory((farvoid *)optrarray,&syserror);
+
+/*
+** Return elapsed ticks.
+*/
+return(elapsed);
+}
+
+/********************
+** LoadStringArray **
+*********************
+** Initialize the string array with random strings of
+** varying sizes.
+** Returns the pointer to the offset pointer array.
+** Note that since we're creating a number of arrays, this
+** routine builds one array, then copies it into the others.
+*/
+static farulong *LoadStringArray(faruchar *strarray, /* String array */
+	uint numarrays,                 /* # of arrays */
+	ulong *nstrings,                /* # of strings */
+	ulong arraysize)                /* Size of array */
+{
+faruchar *tempsbase;            /* Temporary string base pointer */
+farulong *optrarray;            /* Local for pointer */
+farulong *tempobase;            /* Temporary offset pointer base pointer */
+unsigned long curroffset;       /* Current offset */
+int fullflag;                   /* Indicates full array */
+unsigned char stringlength;     /* Length of string */
+unsigned char i;                /* Index */
+unsigned long j;                /* Another index */
+unsigned int k;                 /* Yet another index */
+unsigned int l;                 /* Ans still one more index */
+int systemerror;                /* For holding error code */
+
+/*
+** Initialize random number generator.
+*/
+/* randnum(13L); */
+randnum((int32)13);
+
+/*
+** Start with no strings.  Initialize our current offset pointer
+** to 0.
+*/
+*nstrings=0L;
+curroffset=0L;
+fullflag=0;
+
+do
+{
+	/*
+	** Allocate a string with a random length no
+	** shorter than 4 bytes and no longer than
+	** 80 bytes.  Note we have to also make sure
+	** there's room in the array.
+	*/
+        /* stringlength=(unsigned char)((1+abs_randwc(76L)) & 0xFFL);*/
+	stringlength=(unsigned char)((1+abs_randwc((int32)76)) & 0xFFL);
+	if((unsigned long)stringlength+curroffset+1L>=arraysize)
+	{       stringlength=(unsigned char)((arraysize-curroffset-1L) &
+				0xFF);
+		fullflag=1;     /* Indicates a full */
+	}
+
+	/*
+	** Store length at curroffset and advance current offset.
+	*/
+	*(strarray+curroffset)=stringlength;
+	curroffset++;
+
+	/*
+	** Fill up the rest of the string with random bytes.
+	*/
+	for(i=0;i<stringlength;i++)
+	{       *(strarray+curroffset)=
+		        /* (unsigned char)(abs_randwc((long)0xFE)); */
+			(unsigned char)(abs_randwc((int32)0xFE));
+		curroffset++;
+	}
+
+	/*
+	** Increment the # of strings counter.
+	*/
+	*nstrings+=1L;
+
+} while(fullflag==0);
+
+/*
+** We now have initialized a single full array.  If there
+** is more than one array, copy the original into the
+** others.
+*/
+k=1;
+tempsbase=strarray;
+while(k<numarrays)
+{       tempsbase+=arraysize+100;         /* Set base */
+	for(l=0;l<arraysize;l++)
+		tempsbase[l]=strarray[l];
+	k++;
+}
+
+/*
+** Now the array is full, allocate enough space for an
+** offset pointer array.
+*/
+optrarray=(farulong *)AllocateMemory(*nstrings * sizeof(unsigned long) *
+		numarrays,
+		&systemerror);
+if(systemerror)
+{       ReportError("CPU:Stringsort",systemerror);
+	FreeMemory((void *)strarray,&systemerror);
+	ErrorExit();
+}
+
+/*
+** Go through the newly-built string array, building
+** offsets and putting them into the offset pointer
+** array.
+*/
+curroffset=0;
+for(j=0;j<*nstrings;j++)
+{       *(optrarray+j)=curroffset;
+	curroffset+=(unsigned long)(*(strarray+curroffset))+1L;
+}
+
+/*
+** As above, we've made one copy of the offset pointers,
+** so duplicate this array in the remaining ones.
+*/
+k=1;
+tempobase=optrarray;
+while(k<numarrays)
+{       tempobase+=*nstrings;
+	for(l=0;l<*nstrings;l++)
+		tempobase[l]=optrarray[l];
+	k++;
+}
+
+/*
+** All done...go home.  Pass local pointer back.
+*/
+return(optrarray);
+}
+
+/**************
+** stradjust **
+***************
+** Used by the string heap sort.  Call this routine to adjust the
+** string at offset i to length l.  The members of the string array
+** are moved accordingly and the length of the string at offset i
+** is set to l.
+*/
+static void stradjust(farulong *optrarray,      /* Offset pointer array */
+	faruchar *strarray,                     /* String array */
+	ulong nstrings,                         /* # of strings */
+	ulong i,                                /* Offset to adjust */
+	uchar l)                                /* New length */
+{
+unsigned long nbytes;           /* # of bytes to move */
+unsigned long j;                /* Index */
+int direction;                  /* Direction indicator */
+unsigned char adjamount;        /* Adjustment amount */
+
+/*
+** If new length is less than old length, the direction is
+** down.  If new length is greater than old length, the
+** direction is up.
+*/
+direction=(int)l - (int)*(strarray+*(optrarray+i));
+adjamount=(unsigned char)abs(direction);
+
+/*
+** See if the adjustment is being made to the last
+** string in the string array.  If so, we don't have to
+** do anything more than adjust the length field.
+*/
+if(i==(nstrings-1L))
+{       *(strarray+*(optrarray+i))=l;
+	return;
+}
+
+/*
+** Calculate the total # of bytes in string array from
+** location i+1 to end of array.  Whether we're moving "up" or
+** down, this is how many bytes we'll have to move.
+*/
+nbytes=*(optrarray+nstrings-1L) +
+	(unsigned long)*(strarray+*(optrarray+nstrings-1L)) + 1L -
+	*(optrarray+i+1L);
+
+/*
+** Calculate the source and the destination.  Source is
+** string position i+1.  Destination is string position i+l
+** (i+"ell"...don't confuse 1 and l).
+** Hand this straight to memmove and let it handle the
+** "overlap" problem.
+*/
+MoveMemory((farvoid *)(strarray+*(optrarray+i)+l+1),
+	(farvoid *)(strarray+*(optrarray+i+1)),
+	(unsigned long)nbytes);
+
+/*
+** We have to adjust the offset pointer array.
+** This covers string i+1 to numstrings-1.
+*/
+for(j=i+1;j<nstrings;j++)
+	if(direction<0)
+		*(optrarray+j)=*(optrarray+j)-adjamount;
+	else
+		*(optrarray+j)=*(optrarray+j)+adjamount;
+
+/*
+** Store the new length and go home.
+*/
+*(strarray+*(optrarray+i))=l;
+return;
+}
+
+/****************
+** strheapsort **
+*****************
+** Pass this routine a pointer to an array of unsigned char.
+** The array is presumed to hold strings occupying at most
+** 80 bytes (counts a byte count).
+** This routine also needs a pointer to an array of offsets
+** which represent string locations in the array, and
+** an unsigned long indicating the number of strings
+** in the array.
+*/
+static void StrHeapSort(farulong *optrarray, /* Offset pointers */
+	faruchar *strarray,             /* Strings array */
+	ulong numstrings,               /* # of strings in array */
+	ulong bottom,                   /* Region to sort...bottom */
+	ulong top)                      /* Region to sort...top */
+{
+unsigned char temp[80];                 /* Used to exchange elements */
+unsigned char tlen;                     /* Temp to hold length */
+unsigned long i;                        /* Loop index */
+
+
+/*
+** Build a heap in the array
+*/
+for(i=(top/2L); i>0; --i)
+	strsift(optrarray,strarray,numstrings,i,top);
+
+/*
+** Repeatedly extract maximum from heap and place it at the
+** end of the array.  When we get done, we'll have a sorted
+** array.
+*/
+for(i=top; i>0; --i)
+{
+	strsift(optrarray,strarray,numstrings,0,i);
+
+	/* temp = string[0] */
+	tlen=*strarray;
+	MoveMemory((farvoid *)&temp[0], /* Perform exchange */
+		(farvoid *)strarray,
+		(unsigned long)(tlen+1));
+
+
+	/* string[0]=string[i] */
+	tlen=*(strarray+*(optrarray+i));
+	stradjust(optrarray,strarray,numstrings,0,tlen);
+	MoveMemory((farvoid *)strarray,
+		(farvoid *)(strarray+*(optrarray+i)),
+		(unsigned long)(tlen+1));
+
+	/* string[i]=temp */
+	tlen=temp[0];
+	stradjust(optrarray,strarray,numstrings,i,tlen);
+	MoveMemory((farvoid *)(strarray+*(optrarray+i)),
+		(farvoid *)&temp[0],
+		(unsigned long)(tlen+1));
+
+}
+return;
+}
+
+/****************
+** str_is_less **
+*****************
+** Pass this function:
+**      1) A pointer to an array of offset pointers
+**      2) A pointer to a string array
+**      3) The number of elements in the string array
+**      4) Offsets to two strings (a & b)
+** This function returns TRUE if string a is < string b.
+*/
+static int str_is_less(farulong *optrarray, /* Offset pointers */
+	faruchar *strarray,                     /* String array */
+	ulong numstrings,                       /* # of strings */
+	ulong a, ulong b)                       /* Offsets */
+{
+int slen;               /* String length */
+
+/*
+** Determine which string has the minimum length.  Use that
+** to call strncmp().  If they match up to that point, the
+** string with the longer length wins.
+*/
+slen=(int)*(strarray+*(optrarray+a));
+if(slen > (int)*(strarray+*(optrarray+b)))
+	slen=(int)*(strarray+*(optrarray+b));
+
+slen=strncmp((char *)(strarray+*(optrarray+a)),
+		(char *)(strarray+*(optrarray+b)),slen);
+
+if(slen==0)
+{
+	/*
+	** They match.  Return true if the length of a
+	** is greater than the length of b.
+	*/
+	if(*(strarray+*(optrarray+a)) >
+		*(strarray+*(optrarray+b)))
+		return(TRUE);
+	return(FALSE);
+}
+
+if(slen<0) return(TRUE);        /* a is strictly less than b */
+
+return(FALSE);                  /* Only other possibility */
+}
+
+/************
+** strsift **
+*************
+** Pass this function:
+**      1) A pointer to an array of offset pointers
+**      2) A pointer to a string array
+**      3) The number of elements in the string array
+**      4) Offset within which to sort.
+** Sift the array within the bounds of those offsets (thus
+** building a heap).
+*/
+static void strsift(farulong *optrarray,        /* Offset pointers */
+	faruchar *strarray,                     /* String array */
+	ulong numstrings,                       /* # of strings */
+	ulong i, ulong j)                       /* Offsets */
+{
+unsigned long k;                /* Temporaries */
+unsigned char temp[80];
+unsigned char tlen;             /* For string lengths */
+
+
+while((i+i)<=j)
+{
+	k=i+i;
+	if(k<j)
+		if(str_is_less(optrarray,strarray,numstrings,k,k+1L))
+			++k;
+	if(str_is_less(optrarray,strarray,numstrings,i,k))
+	{
+		/* temp=string[k] */
+		tlen=*(strarray+*(optrarray+k));
+		MoveMemory((farvoid *)&temp[0],
+			(farvoid *)(strarray+*(optrarray+k)),
+			(unsigned long)(tlen+1));
+
+		/* string[k]=string[i] */
+		tlen=*(strarray+*(optrarray+i));
+		stradjust(optrarray,strarray,numstrings,k,tlen);
+		MoveMemory((farvoid *)(strarray+*(optrarray+k)),
+			(farvoid *)(strarray+*(optrarray+i)),
+			(unsigned long)(tlen+1));
+
+		/* string[i]=temp */
+		tlen=temp[0];
+		stradjust(optrarray,strarray,numstrings,i,tlen);
+		MoveMemory((farvoid *)(strarray+*(optrarray+i)),
+			(farvoid *)&temp[0],
+			(unsigned long)(tlen+1));
+		i=k;
+	}
+	else
+		i=j+1;
+}
+return;
+}
+
+/************************
+** BITFIELD OPERATIONS **
+*************************/
+
+/*************
+** DoBitops **
+**************
+** Perform the bit operations test portion of the CPU
+** benchmark.  Returns the iterations per second.
+*/
+void DoBitops(void)
+{
+BitOpStruct *locbitopstruct;    /* Local bitop structure */
+farulong *bitarraybase;         /* Base of bitmap array */
+farulong *bitoparraybase;       /* Base of bitmap operations array */
+ulong nbitops;                  /* # of bitfield operations */
+ulong accumtime;                /* Accumulated time in ticks */
+double iterations;              /* # of iterations */
+char *errorcontext;             /* Error context string */
+int systemerror;                /* For holding error codes */
+int ticks;
+
+/*
+** Link to global structure.
+*/
+locbitopstruct=&global_bitopstruct;
+
+/*
+** Set the error context.
+*/
+errorcontext="CPU:Bitfields";
+
+/*
+** See if we need to run adjustment code.
+*/
+if(locbitopstruct->adjust==0)
+{
+	bitarraybase=(farulong *)AllocateMemory(locbitopstruct->bitfieldarraysize *
+		sizeof(ulong),&systemerror);
+	if(systemerror)
+	{       ReportError(errorcontext,systemerror);
+		ErrorExit();
+	}
+
+	/*
+	** Initialize bitfield operations array to [2,30] elements
+	*/
+	locbitopstruct->bitoparraysize=30L;
+
+	while(1)
+	{
+		/*
+		** Allocate space for operations array
+		*/
+		bitoparraybase=(farulong *)AllocateMemory(locbitopstruct->bitoparraysize*2L*
+			sizeof(ulong),
+			&systemerror);
+		if(systemerror)
+		{       ReportError(errorcontext,systemerror);
+			FreeMemory((farvoid *)bitarraybase,&systemerror);
+			ErrorExit();
+		}
+		/*
+		** Do an iteration of the bitmap test.  If the
+		** elapsed time is less than or equal to the permitted
+		** minimum, then de-allocate the array, reallocate a
+		** larger version, and try again.
+		*/
+		ticks=DoBitfieldIteration(bitarraybase,
+					   bitoparraybase,
+					   locbitopstruct->bitoparraysize,
+					   &nbitops);
+#ifdef DEBUG
+#ifdef LINUX
+	        if (locbitopstruct->bitoparraysize==30L){
+		  /* this is the first loop, write a debug file */
+		  FILE *file;
+		  unsigned long *running_base; /* same as farulong */
+		  long counter;
+		  file=fopen("debugbit.dat","w");
+		  running_base=bitarraybase;
+		  for (counter=0;counter<(long)(locbitopstruct->bitfieldarraysize);counter++){
+if (sizeof(long) == 8) {
+		    fprintf(file,"%08X",(unsigned int)(*running_base&0xFFFFFFFFL));
+		    fprintf(file,"%08X",(unsigned int)((*running_base>>32)&0xFFFFFFFFL));
+		    if ((counter+1)%4==0) fprintf(file,"\n");
+} else {
+		    fprintf(file,"%08lX",*running_base);
+		    if ((counter+1)%8==0) fprintf(file,"\n");
+}
+		    running_base=running_base+1;
+		  }
+		  fclose(file);
+		  printf("\nWrote the file debugbit.dat, you may want to compare it to debugbit.good\n");
+		}
+#endif
+#endif
+
+		if (ticks>global_min_ticks) break;      /* We're ok...exit */
+
+		FreeMemory((farvoid *)bitoparraybase,&systemerror);
+		locbitopstruct->bitoparraysize+=100L;
+	}
+}
+else
+{
+	/*
+	** Don't need to do self adjustment, just allocate
+	** the array space.
+	*/
+	bitarraybase=(farulong *)AllocateMemory(locbitopstruct->bitfieldarraysize *
+		sizeof(ulong),&systemerror);
+	if(systemerror)
+	{       ReportError(errorcontext,systemerror);
+		ErrorExit();
+	}
+	bitoparraybase=(farulong *)AllocateMemory(locbitopstruct->bitoparraysize*2L*
+		sizeof(ulong),
+		&systemerror);
+	if(systemerror)
+	{       ReportError(errorcontext,systemerror);
+		FreeMemory((farvoid *)bitarraybase,&systemerror);
+		ErrorExit();
+	}
+}
+
+/*
+** All's well if we get here.  Repeatedly perform bitops until the
+** accumulated elapsed time is greater than # of seconds requested.
+*/
+accumtime=0L;
+iterations=(double)0.0;
+do {
+	accumtime+=DoBitfieldIteration(bitarraybase,
+			bitoparraybase,
+			locbitopstruct->bitoparraysize,&nbitops);
+	iterations+=(double)nbitops;
+} while(iterations < BASE_ITERATIONS * 50000);
+
+/*
+** Clean up, calculate results, and go home.
+** Also, set adjustment flag to show that we don't have
+** to do self adjusting in the future.
+*/
+FreeMemory((farvoid *)bitarraybase,&systemerror);
+FreeMemory((farvoid *)bitoparraybase,&systemerror);
+locbitopstruct->bitopspersec=iterations /TicksToFracSecs(accumtime);
+if(locbitopstruct->adjust==0)
+	locbitopstruct->adjust=1;
+
+return;
+}
+
+/************************
+** DoBitfieldIteration **
+*************************
+** Perform a single iteration of the bitfield benchmark.
+** Return the # of ticks accumulated by the operation.
+*/
+static ulong DoBitfieldIteration(farulong *bitarraybase,
+		farulong *bitoparraybase,
+		long bitoparraysize,
+		ulong *nbitops)
+{
+long i;                         /* Index */
+ulong bitoffset;                /* Offset into bitmap */
+ulong elapsed;                  /* Time to execute */
+/*
+** Clear # bitops counter
+*/
+*nbitops=0L;
+
+/*
+** Construct a set of bitmap offsets and run lengths.
+** The offset can be any random number from 0 to the
+** size of the bitmap (in bits).  The run length can
+** be any random number from 1 to the number of bits
+** between the offset and the end of the bitmap.
+** Note that the bitmap has 8192 * 32 bits in it.
+** (262,144 bits)
+*/
+/*
+** Reset random number generator so things repeat.
+** Also reset the bit array we work on.
+** added by Uwe F. Mayer
+*/
+randnum((int32)13);
+for (i=0;i<global_bitopstruct.bitfieldarraysize;i++)
+{
+if (sizeof(long) == 8)
+	*(bitarraybase+i)=(ulong)0x5555555555555555;
+else
+	*(bitarraybase+i)=(ulong)0x55555555;
+}
+randnum((int32)13);
+/* end of addition of code */
+
+for (i=0;i<bitoparraysize;i++)
+{
+	/* First item is offset */
+        /* *(bitoparraybase+i+i)=bitoffset=abs_randwc(262140L); */
+	*(bitoparraybase+i+i)=bitoffset=abs_randwc((int32)262140);
+
+	/* Next item is run length */
+	/* *nbitops+=*(bitoparraybase+i+i+1L)=abs_randwc(262140L-bitoffset);*/
+	*nbitops+=*(bitoparraybase+i+i+1L)=abs_randwc((int32)262140-bitoffset);
+}
+
+/*
+** Array of offset and lengths built...do an iteration of
+** the test.
+** Start the stopwatch.
+*/
+elapsed=StartStopwatch();
+
+/*
+** Loop through array off offset/run length pairs.
+** Execute operation based on modulus of index.
+*/
+for(i=0;i<bitoparraysize;i++)
+{
+	switch(i % 3)
+	{
+
+		case 0: /* Set run of bits */
+			ToggleBitRun(bitarraybase,
+				*(bitoparraybase+i+i),
+				*(bitoparraybase+i+i+1),
+				1);
+			break;
+
+		case 1: /* Clear run of bits */
+			ToggleBitRun(bitarraybase,
+				*(bitoparraybase+i+i),
+				*(bitoparraybase+i+i+1),
+				0);
+			break;
+
+		case 2: /* Complement run of bits */
+			FlipBitRun(bitarraybase,
+				*(bitoparraybase+i+i),
+				*(bitoparraybase+i+i+1));
+			break;
+	}
+}
+
+/*
+** Return elapsed time
+*/
+return(StopStopwatch(elapsed));
+}
+
+
+/*****************************
+**     ToggleBitRun          *
+******************************
+** Set or clear a run of nbits starting at
+** bit_addr in bitmap.
+*/
+static void ToggleBitRun(farulong *bitmap, /* Bitmap */
+		ulong bit_addr,         /* Address of bits to set */
+		ulong nbits,            /* # of bits to set/clr */
+		uint val)               /* 1 or 0 */
+{
+unsigned long bindex;   /* Index into array */
+unsigned long bitnumb;  /* Bit number */
+
+while(nbits--)
+{
+if (sizeof(long) == 8) {
+	bindex=bit_addr>>6;     /* Index is number /64 */
+	bitnumb=bit_addr % 64;   /* Bit number in word */
+} else {
+	bindex=bit_addr>>5;     /* Index is number /32 */
+	bitnumb=bit_addr % 32;  /* bit number in word */
+}
+	if(val)
+		bitmap[bindex]|=(1L<<bitnumb);
+	else
+		bitmap[bindex]&=~(1L<<bitnumb);
+	bit_addr++;
+}
+return;
+}
+
+/***************
+** FlipBitRun **
+****************
+** Complements a run of bits.
+*/
+static void FlipBitRun(farulong *bitmap,        /* Bit map */
+		ulong bit_addr,                 /* Bit address */
+		ulong nbits)                    /* # of bits to flip */
+{
+unsigned long bindex;   /* Index into array */
+unsigned long bitnumb;  /* Bit number */
+
+while(nbits--)
+{
+if (sizeof(long) == 8) {
+	bindex=bit_addr>>6;     /* Index is number /64 */
+	bitnumb=bit_addr % 64;  /* Bit number in longword */
+} else {
+	bindex=bit_addr>>5;     /* Index is number /32 */
+	bitnumb=bit_addr % 32;  /* Bit number in longword */
+}
+	bitmap[bindex]^=(1L<<bitnumb);
+	bit_addr++;
+}
+
+return;
+}
+
+/*****************************
+** FLOATING-POINT EMULATION **
+*****************************/
+
+/**************
+** DoEmFloat **
+***************
+** Perform the floating-point emulation routines portion of the
+** CPU benchmark.  Returns the operations per second.
+*/
+void DoEmFloat(void)
+{
+EmFloatStruct *locemfloatstruct;        /* Local structure */
+InternalFPF *abase;             /* Base of A array */
+InternalFPF *bbase;             /* Base of B array */
+InternalFPF *cbase;             /* Base of C array */
+ulong accumtime;                /* Accumulated time in ticks */
+double iterations;              /* # of iterations */
+ulong tickcount;                /* # of ticks */
+char *errorcontext;             /* Error context string pointer */
+int systemerror;                /* For holding error code */
+ulong loops;                    /* # of loops */
+
+/*
+** Link to global structure
+*/
+locemfloatstruct=&global_emfloatstruct;
+
+/*
+** Set the error context
+*/
+errorcontext="CPU:Floating Emulation";
+
+
+/*
+** Test the emulation routines.
+*/
+#ifdef DEBUG
+#endif
+
+abase=(InternalFPF *)AllocateMemory(locemfloatstruct->arraysize*sizeof(InternalFPF),
+		&systemerror);
+if(systemerror)
+{       ReportError(errorcontext,systemerror);
+	ErrorExit();
+}
+
+bbase=(InternalFPF *)AllocateMemory(locemfloatstruct->arraysize*sizeof(InternalFPF),
+		&systemerror);
+if(systemerror)
+{       ReportError(errorcontext,systemerror);
+	FreeMemory((farvoid *)abase,&systemerror);
+	ErrorExit();
+}
+
+cbase=(InternalFPF *)AllocateMemory(locemfloatstruct->arraysize*sizeof(InternalFPF),
+		&systemerror);
+if(systemerror)
+{       ReportError(errorcontext,systemerror);
+	FreeMemory((farvoid *)abase,&systemerror);
+	FreeMemory((farvoid *)bbase,&systemerror);
+	ErrorExit();
+}
+
+/*
+** Set up the arrays
+*/
+SetupCPUEmFloatArrays(abase,bbase,cbase,locemfloatstruct->arraysize);
+
+/*
+** See if we need to do self-adjusting code.
+*/
+if(locemfloatstruct->adjust==0)
+{
+	locemfloatstruct->loops=0;
+
+	/*
+	** Do an iteration of the tests.  If the elapsed time is
+	** less than minimum, increase the loop count and try
+	** again.
+	*/
+	for(loops=1;loops<CPUEMFLOATLOOPMAX;loops+=loops)
+	{       tickcount=DoEmFloatIteration(abase,bbase,cbase,
+			locemfloatstruct->arraysize,
+			loops);
+		if(tickcount>global_min_ticks)
+		{       locemfloatstruct->loops=loops;
+			break;
+		}
+	}
+}
+
+/*
+** Verify that selft adjustment code worked.
+*/
+if(locemfloatstruct->loops==0)
+{       printf("CPU:EMFPU -- CMPUEMFLOATLOOPMAX limit hit\n");
+	FreeMemory((farvoid *)abase,&systemerror);
+	FreeMemory((farvoid *)bbase,&systemerror);
+	FreeMemory((farvoid *)cbase,&systemerror);
+	ErrorExit();
+}
+
+/*
+** All's well if we get here.  Repeatedly perform floating
+** tests until the accumulated time is greater than the
+** # of seconds requested.
+** Each iteration performs arraysize * 3 operations.
+*/
+accumtime=0L;
+iterations=(double)0.0;
+do {
+	accumtime+=DoEmFloatIteration(abase,bbase,cbase,
+			locemfloatstruct->arraysize,
+			locemfloatstruct->loops);
+	iterations+=(double)1.0;
+} while(iterations < BASE_ITERATIONS * 3);
+
+
+/*
+** Clean up, calculate results, and go home.
+** Also, indicate that adjustment is done.
+*/
+FreeMemory((farvoid *)abase,&systemerror);
+FreeMemory((farvoid *)bbase,&systemerror);
+FreeMemory((farvoid *)cbase,&systemerror);
+
+locemfloatstruct->emflops=(iterations*(double)locemfloatstruct->loops)/
+		(double)TicksToFracSecs(accumtime);
+if(locemfloatstruct->adjust==0)
+	locemfloatstruct->adjust=1;
+
+#ifdef DEBUG
+printf("----------------------------------------------------------------------------\n");
+#endif
+return;
+}
+
+/*************************
+** FOURIER COEFFICIENTS **
+*************************/
+
+/**************
+** DoFourier **
+***************
+** Perform the transcendental/trigonometric portion of the
+** benchmark.  This benchmark calculates the first n
+** fourier coefficients of the function (x+1)^x defined
+** on the interval 0,2.
+*/
+void DoFourier(void)
+{
+FourierStruct *locfourierstruct;        /* Local fourier struct */
+fardouble *abase;               /* Base of A[] coefficients array */
+fardouble *bbase;               /* Base of B[] coefficients array */
+unsigned long accumtime;        /* Accumulated time in ticks */
+double iterations;              /* # of iterations */
+char *errorcontext;             /* Error context string pointer */
+int systemerror;                /* For error code */
+
+/*
+** Link to global structure
+*/
+locfourierstruct=&global_fourierstruct;
+
+/*
+** Set error context string
+*/
+errorcontext="FPU:Transcendental";
+
+/*
+** See if we need to do self-adjustment code.
+*/
+if(locfourierstruct->adjust==0)
+{
+	locfourierstruct->arraysize=100L;       /* Start at 100 elements */
+	while(1)
+	{
+
+		abase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double),
+				&systemerror);
+		if(systemerror)
+		{       ReportError(errorcontext,systemerror);
+			ErrorExit();
+		}
+
+		bbase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double),
+				&systemerror);
+		if(systemerror)
+		{       ReportError(errorcontext,systemerror);
+			FreeMemory((void *)abase,&systemerror);
+			ErrorExit();
+		}
+		/*
+		** Do an iteration of the tests.  If the elapsed time is
+		** less than or equal to the permitted minimum, re-allocate
+		** larger arrays and try again.
+		*/
+		if(DoFPUTransIteration(abase,bbase,
+			locfourierstruct->arraysize)>global_min_ticks)
+			break;          /* We're ok...exit */
+
+		/*
+		** Make bigger arrays and try again.
+		*/
+		FreeMemory((farvoid *)abase,&systemerror);
+		FreeMemory((farvoid *)bbase,&systemerror);
+		locfourierstruct->arraysize+=50L;
+	}
+}
+else
+{       /*
+	** Don't need self-adjustment.  Just allocate the
+	** arrays, and go.
+	*/
+	abase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double),
+			&systemerror);
+	if(systemerror)
+	{       ReportError(errorcontext,systemerror);
+		ErrorExit();
+	}
+
+	bbase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double),
+			&systemerror);
+	if(systemerror)
+	{       ReportError(errorcontext,systemerror);
+		FreeMemory((void *)abase,&systemerror);
+		ErrorExit();
+	}
+}
+/*
+** All's well if we get here.  Repeatedly perform integration
+** tests until the accumulated time is greater than the
+** # of seconds requested.
+*/
+accumtime=0L;
+iterations=(double)0.0;
+do {
+	accumtime+=DoFPUTransIteration(abase,bbase,locfourierstruct->arraysize);
+	iterations+=(double)locfourierstruct->arraysize*(double)2.0-(double)1.0;
+} while(iterations < BASE_ITERATIONS * 400);
+
+
+/*
+** Clean up, calculate results, and go home.
+** Also set adjustment flag to indicate no adjust code needed.
+*/
+FreeMemory((farvoid *)abase,&systemerror);
+FreeMemory((farvoid *)bbase,&systemerror);
+
+locfourierstruct->fflops=iterations/(double)TicksToFracSecs(accumtime);
+
+if(locfourierstruct->adjust==0)
+	locfourierstruct->adjust=1;
+
+return;
+}
+
+/************************
+** DoFPUTransIteration **
+*************************
+** Perform an iteration of the FPU Transcendental/trigonometric
+** benchmark.  Here, an iteration consists of calculating the
+** first n fourier coefficients of the function (x+1)^x on
+** the interval 0,2.  n is given by arraysize.
+** NOTE: The # of integration steps is fixed at
+** 200.
+*/
+static ulong DoFPUTransIteration(fardouble *abase,      /* A coeffs. */
+			fardouble *bbase,               /* B coeffs. */
+			ulong arraysize)                /* # of coeffs */
+{
+double omega;           /* Fundamental frequency */
+unsigned long i;        /* Index */
+unsigned long elapsed;  /* Elapsed time */
+
+/*
+** Start the stopwatch
+*/
+elapsed=StartStopwatch();
+
+/*
+** Calculate the fourier series.  Begin by
+** calculating A[0].
+*/
+
+*abase=TrapezoidIntegrate((double)0.0,
+			(double)2.0,
+			200,
+			(double)0.0,    /* No omega * n needed */
+			0 )/(double)2.0;
+
+/*
+** Calculate the fundamental frequency.
+** ( 2 * pi ) / period...and since the period
+** is 2, omega is simply pi.
+*/
+omega=(double)3.1415926535897932;
+
+for(i=1;i<arraysize;i++)
+{
+
+	/*
+	** Calculate A[i] terms.  Note, once again, that we
+	** can ignore the 2/period term outside the integral
+	** since the period is 2 and the term cancels itself
+	** out.
+	*/
+	*(abase+i)=TrapezoidIntegrate((double)0.0,
+			(double)2.0,
+			200,
+			omega * (double)i,
+			1);
+
+	/*
+	** Calculate the B[i] terms.
+	*/
+	*(bbase+i)=TrapezoidIntegrate((double)0.0,
+			(double)2.0,
+			200,
+			omega * (double)i,
+			2);
+
+}
+#ifdef DEBUG
+{
+  int i;
+  printf("\nA[i]=\n");
+  for (i=0;i<arraysize;i++) printf("%7.3g ",abase[i]);
+  printf("\nB[i]=\n(undefined) ");
+  for (i=1;i<arraysize;i++) printf("%7.3g ",bbase[i]);
+}
+#endif
+/*
+** All done, stop the stopwatch
+*/
+return(StopStopwatch(elapsed));
+}
+
+/***********************
+** TrapezoidIntegrate **
+************************
+** Perform a simple trapezoid integration on the
+** function (x+1)**x.
+** x0,x1 set the lower and upper bounds of the
+** integration.
+** nsteps indicates # of trapezoidal sections
+** omegan is the fundamental frequency times
+**  the series member #
+** select = 0 for the A[0] term, 1 for cosine terms, and
+**   2 for sine terms.
+** Returns the value.
+*/
+static double TrapezoidIntegrate( double x0,            /* Lower bound */
+			double x1,              /* Upper bound */
+			int nsteps,             /* # of steps */
+			double omegan,          /* omega * n */
+			int select)
+{
+double x;               /* Independent variable */
+double dx;              /* Stepsize */
+double rvalue;          /* Return value */
+
+
+/*
+** Initialize independent variable
+*/
+x=x0;
+
+/*
+** Calculate stepsize
+*/
+dx=(x1 - x0) / (double)nsteps;
+
+/*
+** Initialize the return value.
+*/
+rvalue=thefunction(x0,omegan,select)/(double)2.0;
+
+/*
+** Compute the other terms of the integral.
+*/
+if(nsteps!=1)
+{       --nsteps;               /* Already done 1 step */
+	while(--nsteps )
+	{
+		x+=dx;
+		rvalue+=thefunction(x,omegan,select);
+	}
+}
+/*
+** Finish computation
+*/
+rvalue=(rvalue+thefunction(x1,omegan,select)/(double)2.0)*dx;
+
+return(rvalue);
+}
+
+/****************
+** thefunction **
+*****************
+** This routine selects the function to be used
+** in the Trapezoid integration.
+** x is the independent variable
+** omegan is omega * n
+** select chooses which of the sine/cosine functions
+**  are used.  note the special case for select=0.
+*/
+static double thefunction(double x,             /* Independent variable */
+		double omegan,          /* Omega * term */
+		int select)             /* Choose term */
+{
+
+/*
+** Use select to pick which function we call.
+*/
+switch(select)
+{
+	case 0: return(pow(x+(double)1.0,x));
+
+	case 1: return(pow(x+(double)1.0,x) * cos(omegan * x));
+
+	case 2: return(pow(x+(double)1.0,x) * sin(omegan * x));
+}
+
+/*
+** We should never reach this point, but the following
+** keeps compilers from issuing a warning message.
+*/
+return(0.0);
+}
+
+/*************************
+** ASSIGNMENT ALGORITHM **
+*************************/
+
+/*************
+** DoAssign **
+**************
+** Perform an assignment algorithm.
+** The algorithm was adapted from the step by step guide found
+** in "Quantitative Decision Making for Business" (Gordon,
+**  Pressman, and Cohn; Prentice-Hall)
+**
+**
+** NOTES:
+** 1. Even though the algorithm distinguishes between
+**    ASSIGNROWS and ASSIGNCOLS, as though the two might
+**    be different, it does presume a square matrix.
+**    I.E., ASSIGNROWS and ASSIGNCOLS must be the same.
+**    This makes for some algorithmically-correct but
+**    probably non-optimal constructs.
+**
+*/
+void DoAssign(void)
+{
+AssignStruct *locassignstruct;  /* Local structure ptr */
+farlong *arraybase;
+char *errorcontext;
+int systemerror;
+ulong accumtime;
+double iterations;
+
+/*
+** Link to global structure
+*/
+locassignstruct=&global_assignstruct;
+
+/*
+** Set the error context string.
+*/
+errorcontext="CPU:Assignment";
+
+/*
+** See if we need to do self adjustment code.
+*/
+if(locassignstruct->adjust==0)
+{
+	/*
+	** Self-adjustment code.  The system begins by working on 1
+	** array.  If it does that in no time, then two arrays
+	** are built.  This process continues until
+	** enough arrays are built to handle the tolerance.
+	*/
+	locassignstruct->numarrays=1;
+	while(1)
+	{
+		/*
+		** Allocate space for arrays
+		*/
+		arraybase=(farlong *) AllocateMemory(sizeof(long)*
+			ASSIGNROWS*ASSIGNCOLS*locassignstruct->numarrays,
+			 &systemerror);
+		if(systemerror)
+		{       ReportError(errorcontext,systemerror);
+			FreeMemory((farvoid *)arraybase,
+			  &systemerror);
+			ErrorExit();
+		}
+
+		/*
+		** Do an iteration of the assignment alg.  If the
+		** elapsed time is less than or equal to the permitted
+		** minimum, then allocate for more arrays and
+		** try again.
+		*/
+		if(DoAssignIteration(arraybase,
+			locassignstruct->numarrays)>global_min_ticks)
+			break;          /* We're ok...exit */
+
+		FreeMemory((farvoid *)arraybase, &systemerror);
+		locassignstruct->numarrays++;
+	}
+}
+else
+{       /*
+	** Allocate space for arrays
+	*/
+	arraybase=(farlong *)AllocateMemory(sizeof(long)*
+		ASSIGNROWS*ASSIGNCOLS*locassignstruct->numarrays,
+		 &systemerror);
+	if(systemerror)
+	{       ReportError(errorcontext,systemerror);
+		FreeMemory((farvoid *)arraybase,
+		  &systemerror);
+		ErrorExit();
+	}
+}
+
+/*
+** All's well if we get here.  Do the tests.
+*/
+accumtime=0L;
+iterations=(double)0.0;
+
+do {
+	accumtime+=DoAssignIteration(arraybase,
+		locassignstruct->numarrays);
+	iterations+=(double)1.0;
+} while(iterations < BASE_ITERATIONS/3);
+
+/*
+** Clean up, calculate results, and go home.  Be sure to
+** show that we don't have to rerun adjustment code.
+*/
+FreeMemory((farvoid *)arraybase,&systemerror);
+
+locassignstruct->iterspersec=iterations *
+	(double)locassignstruct->numarrays / TicksToFracSecs(accumtime);
+
+if(locassignstruct->adjust==0)
+	locassignstruct->adjust=1;
+
+return;
+
+}
+
+/**********************
+** DoAssignIteration **
+***********************
+** This routine executes one iteration of the assignment test.
+** It returns the number of ticks elapsed in the iteration.
+*/
+static ulong DoAssignIteration(farlong *arraybase,
+	ulong numarrays)
+{
+longptr abase;                  /* local pointer */
+ulong elapsed;          /* Elapsed ticks */
+ulong i;
+
+/*
+** Set up local pointer
+*/
+abase.ptrs.p=arraybase;
+
+/*
+** Load up the arrays with a random table.
+*/
+LoadAssignArrayWithRand(arraybase,numarrays);
+
+/*
+** Start the stopwatch
+*/
+elapsed=StartStopwatch();
+
+/*
+** Execute assignment algorithms
+*/
+for(i=0;i<numarrays;i++)
+{       /* abase.ptrs.p+=i*ASSIGNROWS*ASSIGNCOLS; */
+        /* Fixed  by Eike Dierks */
+	Assignment(*abase.ptrs.ap);
+	abase.ptrs.p+=ASSIGNROWS*ASSIGNCOLS;
+}
+
+/*
+** Get elapsed time
+*/
+return(StopStopwatch(elapsed));
+}
+
+/****************************
+** LoadAssignArrayWithRand **
+*****************************
+** Load the assignment arrays with random numbers.  All positive.
+** These numbers represent costs.
+*/
+static void LoadAssignArrayWithRand(farlong *arraybase,
+	ulong numarrays)
+{
+longptr abase,abase1;   /* Local for array pointer */
+ulong i;
+
+/*
+** Set local array pointer
+*/
+abase.ptrs.p=arraybase;
+abase1.ptrs.p=arraybase;
+
+/*
+** Set up the first array.  Then just copy it into the
+** others.
+*/
+LoadAssign(*(abase.ptrs.ap));
+if(numarrays>1)
+	for(i=1;i<numarrays;i++)
+	  {     /* abase1.ptrs.p+=i*ASSIGNROWS*ASSIGNCOLS; */
+	        /* Fixed  by Eike Dierks */
+	        abase1.ptrs.p+=ASSIGNROWS*ASSIGNCOLS;
+		CopyToAssign(*(abase.ptrs.ap),*(abase1.ptrs.ap));
+	}
+
+return;
+}
+
+/***************
+** LoadAssign **
+****************
+** The array given by arraybase is loaded with positive random
+** numbers.  Elements in the array are capped at 5,000,000.
+*/
+static void LoadAssign(farlong arraybase[][ASSIGNCOLS])
+{
+ushort i,j;
+
+/*
+** Reset random number generator so things repeat.
+*/
+/* randnum(13L); */
+randnum((int32)13);
+
+for(i=0;i<ASSIGNROWS;i++)
+  for(j=0;j<ASSIGNROWS;j++){
+    /* arraybase[i][j]=abs_randwc(5000000L);*/
+    arraybase[i][j]=abs_randwc((int32)5000000);
+  }
+
+return;
+}
+
+/*****************
+** CopyToAssign **
+******************
+** Copy the contents of one array to another.  This is called by
+** the routine that builds the initial array, and is used to copy
+** the contents of the intial array into all following arrays.
+*/
+static void CopyToAssign(farlong arrayfrom[ASSIGNROWS][ASSIGNCOLS],
+		farlong arrayto[ASSIGNROWS][ASSIGNCOLS])
+{
+ushort i,j;
+
+for(i=0;i<ASSIGNROWS;i++)
+	for(j=0;j<ASSIGNCOLS;j++)
+		arrayto[i][j]=arrayfrom[i][j];
+
+return;
+}
+
+/***************
+** Assignment **
+***************/
+static void Assignment(farlong arraybase[][ASSIGNCOLS])
+{
+short assignedtableau[ASSIGNROWS][ASSIGNCOLS];
+
+/*
+** First, calculate minimum costs
+*/
+calc_minimum_costs(arraybase);
+
+/*
+** Repeat following until the number of rows selected
+** equals the number of rows in the tableau.
+*/
+while(first_assignments(arraybase,assignedtableau)!=ASSIGNROWS)
+{         second_assignments(arraybase,assignedtableau);
+}
+
+#ifdef DEBUG
+{
+	int i,j;
+	printf("\nColumn choices for each row\n");
+	for(i=0;i<ASSIGNROWS;i++)
+	{
+	        printf("R%03d: ",i);
+		for(j=0;j<ASSIGNCOLS;j++)
+			if(assignedtableau[i][j]==1)
+				printf("%03d ",j);
+	}
+}
+#endif
+
+return;
+}
+
+/***********************
+** calc_minimum_costs **
+************************
+** Revise the tableau by calculating the minimum costs on a
+** row and column basis.  These minima are subtracted from
+** their rows and columns, creating a new tableau.
+*/
+static void calc_minimum_costs(long tableau[][ASSIGNCOLS])
+{
+ushort i,j;              /* Index variables */
+long currentmin;        /* Current minimum */
+/*
+** Determine minimum costs on row basis.  This is done by
+** subtracting -- on a row-per-row basis -- the minum value
+** for that row.
+*/
+for(i=0;i<ASSIGNROWS;i++)
+{
+	currentmin=MAXPOSLONG;  /* Initialize minimum */
+	for(j=0;j<ASSIGNCOLS;j++)
+		if(tableau[i][j]<currentmin)
+			currentmin=tableau[i][j];
+
+	for(j=0;j<ASSIGNCOLS;j++)
+		tableau[i][j]-=currentmin;
+}
+
+/*
+** Determine minimum cost on a column basis.  This works
+** just as above, only now we step through the array
+** column-wise
+*/
+for(j=0;j<ASSIGNCOLS;j++)
+{
+	currentmin=MAXPOSLONG;  /* Initialize minimum */
+	for(i=0;i<ASSIGNROWS;i++)
+		if(tableau[i][j]<currentmin)
+			currentmin=tableau[i][j];
+
+	/*
+	** Here, we'll take the trouble to see if the current
+	** minimum is zero.  This is likely worth it, since the
+	** preceding loop will have created at least one zero in
+	** each row.  We can save ourselves a few iterations.
+	*/
+	if(currentmin!=0)
+		for(i=0;i<ASSIGNROWS;i++)
+			tableau[i][j]-=currentmin;
+}
+
+return;
+}
+
+/**********************
+** first_assignments **
+***********************
+** Do first assignments.
+** The assignedtableau[] array holds a set of values that
+** indicate the assignment of a value, or its elimination.
+** The values are:
+**      0 = Item is neither assigned nor eliminated.
+**      1 = Item is assigned
+**      2 = Item is eliminated
+** Returns the number of selections made.  If this equals
+** the number of rows, then an optimum has been determined.
+*/
+static int first_assignments(long tableau[][ASSIGNCOLS],
+		short assignedtableau[][ASSIGNCOLS])
+{
+ushort i,j,k;                   /* Index variables */
+ushort numassigns;              /* # of assignments */
+ushort totnumassigns;           /* Total # of assignments */
+ushort numzeros;                /* # of zeros in row */
+int selected=0;                 /* Flag used to indicate selection */
+
+/*
+** Clear the assignedtableau, setting all members to show that
+** no one is yet assigned, eliminated, or anything.
+*/
+for(i=0;i<ASSIGNROWS;i++)
+	for(j=0;j<ASSIGNCOLS;j++)
+		assignedtableau[i][j]=0;
+
+totnumassigns=0;
+do {
+	numassigns=0;
+	/*
+	** Step through rows.  For each one that is not currently
+	** assigned, see if the row has only one zero in it.  If so,
+	** mark that as an assigned row/col.  Eliminate other zeros
+	** in the same column.
+	*/
+	for(i=0;i<ASSIGNROWS;i++)
+	{       numzeros=0;
+		for(j=0;j<ASSIGNCOLS;j++)
+			if(tableau[i][j]==0L)
+				if(assignedtableau[i][j]==0)
+				{       numzeros++;
+					selected=j;
+				}
+		if(numzeros==1)
+		{       numassigns++;
+			totnumassigns++;
+			assignedtableau[i][selected]=1;
+			for(k=0;k<ASSIGNROWS;k++)
+				if((k!=i) &&
+				   (tableau[k][selected]==0))
+					assignedtableau[k][selected]=2;
+		}
+	}
+	/*
+	** Step through columns, doing same as above.  Now, be careful
+	** of items in the other rows of a selected column.
+	*/
+	for(j=0;j<ASSIGNCOLS;j++)
+	{       numzeros=0;
+		for(i=0;i<ASSIGNROWS;i++)
+			if(tableau[i][j]==0L)
+				if(assignedtableau[i][j]==0)
+				{       numzeros++;
+					selected=i;
+				}
+		if(numzeros==1)
+		{       numassigns++;
+			totnumassigns++;
+			assignedtableau[selected][j]=1;
+			for(k=0;k<ASSIGNCOLS;k++)
+				if((k!=j) &&
+				   (tableau[selected][k]==0))
+					assignedtableau[selected][k]=2;
+		}
+	}
+	/*
+	** Repeat until no more assignments to be made.
+	*/
+} while(numassigns!=0);
+
+/*
+** See if we can leave at this point.
+*/
+if(totnumassigns==ASSIGNROWS) return(totnumassigns);
+
+/*
+** Now step through the array by row.  If you find any unassigned
+** zeros, pick the first in the row.  Eliminate all zeros from
+** that same row & column.  This occurs if there are multiple optima...
+** possibly.
+*/
+for(i=0;i<ASSIGNROWS;i++)
+{       selected=-1;
+	for(j=0;j<ASSIGNCOLS;j++)
+		if((tableau[i][j]==0L) &&
+		   (assignedtableau[i][j]==0))
+		{       selected=j;
+			break;
+		}
+	if(selected!=-1)
+	{       assignedtableau[i][selected]=1;
+		totnumassigns++;
+		for(k=0;k<ASSIGNCOLS;k++)
+			if((k!=selected) &&
+			   (tableau[i][k]==0L))
+				assignedtableau[i][k]=2;
+		for(k=0;k<ASSIGNROWS;k++)
+			if((k!=i) &&
+			   (tableau[k][selected]==0L))
+				assignedtableau[k][selected]=2;
+	}
+}
+
+return(totnumassigns);
+}
+
+/***********************
+** second_assignments **
+************************
+** This section of the algorithm creates the revised
+** tableau, and is difficult to explain.  I suggest you
+** refer to the algorithm's source, mentioned in comments
+** toward the beginning of the program.
+*/
+static void second_assignments(long tableau[][ASSIGNCOLS],
+		short assignedtableau[][ASSIGNCOLS])
+{
+int i,j;                                /* Indexes */
+short linesrow[ASSIGNROWS];
+short linescol[ASSIGNCOLS];
+long smallest;                          /* Holds smallest value */
+ushort numassigns;                      /* Number of assignments */
+ushort newrows;                         /* New rows to be considered */
+/*
+** Clear the linesrow and linescol arrays.
+*/
+for(i=0;i<ASSIGNROWS;i++)
+	linesrow[i]=0;
+for(i=0;i<ASSIGNCOLS;i++)
+	linescol[i]=0;
+
+/*
+** Scan rows, flag each row that has no assignment in it.
+*/
+for(i=0;i<ASSIGNROWS;i++)
+{       numassigns=0;
+	for(j=0;j<ASSIGNCOLS;j++)
+		if(assignedtableau[i][j]==1)
+		{       numassigns++;
+			break;
+		}
+	if(numassigns==0) linesrow[i]=1;
+}
+
+do {
+
+	newrows=0;
+	/*
+	** For each row checked above, scan for any zeros.  If found,
+	** check the associated column.
+	*/
+	for(i=0;i<ASSIGNROWS;i++)
+	{       if(linesrow[i]==1)
+			for(j=0;j<ASSIGNCOLS;j++)
+				if(tableau[i][j]==0)
+					linescol[j]=1;
+	}
+
+	/*
+	** Now scan checked columns.  If any contain assigned zeros, check
+	** the associated row.
+	*/
+	for(j=0;j<ASSIGNCOLS;j++)
+		if(linescol[j]==1)
+			for(i=0;i<ASSIGNROWS;i++)
+				if((assignedtableau[i][j]==1) &&
+					(linesrow[i]!=1))
+				{
+					linesrow[i]=1;
+					newrows++;
+				}
+} while(newrows!=0);
+
+/*
+** linesrow[n]==0 indicate rows covered by imaginary line
+** linescol[n]==1 indicate cols covered by imaginary line
+** For all cells not covered by imaginary lines, determine smallest
+** value.
+*/
+smallest=MAXPOSLONG;
+for(i=0;i<ASSIGNROWS;i++)
+	if(linesrow[i]!=0)
+		for(j=0;j<ASSIGNCOLS;j++)
+			if(linescol[j]!=1)
+				if(tableau[i][j]<smallest)
+					smallest=tableau[i][j];
+
+/*
+** Subtract smallest from all cells in the above set.
+*/
+for(i=0;i<ASSIGNROWS;i++)
+	if(linesrow[i]!=0)
+		for(j=0;j<ASSIGNCOLS;j++)
+			if(linescol[j]!=1)
+				tableau[i][j]-=smallest;
+
+/*
+** Add smallest to all cells covered by two lines.
+*/
+for(i=0;i<ASSIGNROWS;i++)
+	if(linesrow[i]==0)
+		for(j=0;j<ASSIGNCOLS;j++)
+			if(linescol[j]==1)
+				tableau[i][j]+=smallest;
+
+return;
+}
+
+/********************
+** IDEA Encryption **
+*********************
+** IDEA - International Data Encryption Algorithm.
+** Based on code presented in Applied Cryptography by Bruce Schneier.
+** Which was based on code developed by Xuejia Lai and James L. Massey.
+** Other modifications made by Colin Plumb.
+**
+*/
+
+/***********
+** DoIDEA **
+************
+** Perform IDEA encryption.  Note that we time encryption & decryption
+** time as being a single loop.
+*/
+void DoIDEA(void)
+{
+IDEAStruct *locideastruct;      /* Loc pointer to global structure */
+int i;
+IDEAkey Z,DK;
+u16 userkey[8];
+ulong accumtime;
+double iterations;
+char *errorcontext;
+int systemerror;
+faruchar *plain1;               /* First plaintext buffer */
+faruchar *crypt1;               /* Encryption buffer */
+faruchar *plain2;               /* Second plaintext buffer */
+
+/*
+** Link to global data
+*/
+locideastruct=&global_ideastruct;
+
+/*
+** Set error context
+*/
+errorcontext="CPU:IDEA";
+
+/*
+** Re-init random-number generator.
+*/
+/* randnum(3L); */
+randnum((int32)3);
+
+/*
+** Build an encryption/decryption key
+*/
+for (i=0;i<8;i++)
+        /* userkey[i]=(u16)(abs_randwc(60000L) & 0xFFFF); */
+	userkey[i]=(u16)(abs_randwc((int32)60000) & 0xFFFF);
+for(i=0;i<KEYLEN;i++)
+	Z[i]=0;
+
+/*
+** Compute encryption/decryption subkeys
+*/
+en_key_idea(userkey,Z);
+de_key_idea(Z,DK);
+
+/*
+** Allocate memory for buffers.  We'll make 3, called plain1,
+** crypt1, and plain2.  It works like this:
+**   plain1 >>encrypt>> crypt1 >>decrypt>> plain2.
+** So, plain1 and plain2 should match.
+** Also, fill up plain1 with sample text.
+*/
+plain1=(faruchar *)AllocateMemory(locideastruct->arraysize,&systemerror);
+if(systemerror)
+{
+	ReportError(errorcontext,systemerror);
+	ErrorExit();
+}
+
+crypt1=(faruchar *)AllocateMemory(locideastruct->arraysize,&systemerror);
+if(systemerror)
+{
+	ReportError(errorcontext,systemerror);
+	FreeMemory((farvoid *)plain1,&systemerror);
+	ErrorExit();
+}
+
+plain2=(faruchar *)AllocateMemory(locideastruct->arraysize,&systemerror);
+if(systemerror)
+{
+	ReportError(errorcontext,systemerror);
+	FreeMemory((farvoid *)plain1,&systemerror);
+	FreeMemory((farvoid *)crypt1,&systemerror);
+	ErrorExit();
+}
+/*
+** Note that we build the "plaintext" by simply loading
+** the array up with random numbers.
+*/
+for(i=0;i<locideastruct->arraysize;i++)
+	plain1[i]=(uchar)(abs_randwc(255) & 0xFF);
+
+/*
+** See if we need to perform self adjustment loop.
+*/
+if(locideastruct->adjust==0)
+{
+	/*
+	** Do self-adjustment.  This involves initializing the
+	** # of loops and increasing the loop count until we
+	** get a number of loops that we can use.
+	*/
+	for(locideastruct->loops=100L;
+	  locideastruct->loops<MAXIDEALOOPS;
+	  locideastruct->loops+=10L)
+		if(DoIDEAIteration(plain1,crypt1,plain2,
+		  locideastruct->arraysize,
+		  locideastruct->loops,
+		  Z,DK)>global_min_ticks) break;
+}
+
+/*
+** All's well if we get here.  Do the test.
+*/
+accumtime=0L;
+iterations=(double)0.0;
+
+do {
+	accumtime+=DoIDEAIteration(plain1,crypt1,plain2,
+		locideastruct->arraysize,
+		locideastruct->loops,Z,DK);
+	iterations+=(double)locideastruct->loops;
+} while(iterations < BASE_ITERATIONS * 75);
+
+/*
+** Clean up, calculate results, and go home.  Be sure to
+** show that we don't have to rerun adjustment code.
+*/
+FreeMemory((farvoid *)plain1,&systemerror);
+FreeMemory((farvoid *)crypt1,&systemerror);
+FreeMemory((farvoid *)plain2,&systemerror);
+locideastruct->iterspersec=iterations / TicksToFracSecs(accumtime);
+
+if(locideastruct->adjust==0)
+	locideastruct->adjust=1;
+
+return;
+
+}
+
+/********************
+** DoIDEAIteration **
+*********************
+** Execute a single iteration of the IDEA encryption algorithm.
+** Actually, a single iteration is one encryption and one
+** decryption.
+*/
+static ulong DoIDEAIteration(faruchar *plain1,
+			faruchar *crypt1,
+			faruchar *plain2,
+			ulong arraysize,
+			ulong nloops,
+			IDEAkey Z,
+			IDEAkey DK)
+{
+register ulong i;
+register ulong j;
+ulong elapsed;
+#ifdef DEBUG
+int status=0;
+#endif
+
+/*
+** Start the stopwatch.
+*/
+elapsed=StartStopwatch();
+
+/*
+** Do everything for nloops.
+*/
+for(i=0;i<nloops;i++)
+{
+	for(j=0;j<arraysize;j+=(sizeof(u16)*4))
+		cipher_idea((u16 *)(plain1+j),(u16 *)(crypt1+j),Z);       /* Encrypt */
+
+	for(j=0;j<arraysize;j+=(sizeof(u16)*4))
+		cipher_idea((u16 *)(crypt1+j),(u16 *)(plain2+j),DK);      /* Decrypt */
+}
+
+#ifdef DEBUG
+for(j=0;j<arraysize;j++)
+	if(*(plain1+j)!=*(plain2+j)){
+		printf("IDEA Error! \n");
+                status=1;
+                }
+if (status==0) printf("IDEA: OK\n");
+#endif
+
+/*
+** Get elapsed time.
+*/
+return(StopStopwatch(elapsed));
+}
+
+/********
+** mul **
+*********
+** Performs multiplication, modulo (2**16)+1.  This code is structured
+** on the assumption that untaken branches are cheaper than taken
+** branches, and that the compiler doesn't schedule branches.
+*/
+static u16 mul(register u16 a, register u16 b)
+{
+register u32 p;
+if(a)
+{       if(b)
+	{       p=(u32)(a*b);
+		b=low16(p);
+		a=(u16)(p>>16);
+		return(b-a+(b<a));
+	}
+	else
+		return(1-a);
+}
+else
+	return(1-b);
+}
+
+/********
+** inv **
+*********
+** Compute multiplicative inverse of x, modulo (2**16)+1
+** using Euclid's GCD algorithm.  It is unrolled twice
+** to avoid swapping the meaning of the registers.  And
+** some subtracts are changed to adds.
+*/
+static u16 inv(u16 x)
+{
+u16 t0, t1;
+u16 q, y;
+
+if(x<=1)
+	return(x);      /* 0 and 1 are self-inverse */
+t1=0x10001 / x;
+y=0x10001 % x;
+if(y==1)
+	return(low16(1-t1));
+t0=1;
+do {
+	q=x/y;
+	x=x%y;
+	t0+=q*t1;
+	if(x==1) return(t0);
+	q=y/x;
+	y=y%x;
+	t1+=q*t0;
+} while(y!=1);
+return(low16(1-t1));
+}
+
+/****************
+** en_key_idea **
+*****************
+** Compute IDEA encryption subkeys Z
+*/
+static void en_key_idea(u16 *userkey, u16 *Z)
+{
+int i,j;
+
+/*
+** shifts
+*/
+for(j=0;j<8;j++)
+	Z[j]=*userkey++;
+for(i=0;j<KEYLEN;j++)
+{       i++;
+	Z[i+7]=(Z[i&7]<<9)| (Z[(i+1) & 7] >> 7);
+	Z+=i&8;
+	i&=7;
+}
+return;
+}
+
+/****************
+** de_key_idea **
+*****************
+** Compute IDEA decryption subkeys DK from encryption
+** subkeys Z.
+*/
+static void de_key_idea(IDEAkey Z, IDEAkey DK)
+{
+IDEAkey TT;
+int j;
+u16 t1, t2, t3;
+u16 *p;
+p=(u16 *)(TT+KEYLEN);
+
+t1=inv(*Z++);
+t2=-*Z++;
+t3=-*Z++;
+*--p=inv(*Z++);
+*--p=t3;
+*--p=t2;
+*--p=t1;
+
+for(j=1;j<ROUNDS;j++)
+{       t1=*Z++;
+	*--p=*Z++;
+	*--p=t1;
+	t1=inv(*Z++);
+	t2=-*Z++;
+	t3=-*Z++;
+	*--p=inv(*Z++);
+	*--p=t2;
+	*--p=t3;
+	*--p=t1;
+}
+t1=*Z++;
+*--p=*Z++;
+*--p=t1;
+t1=inv(*Z++);
+t2=-*Z++;
+t3=-*Z++;
+*--p=inv(*Z++);
+*--p=t3;
+*--p=t2;
+*--p=t1;
+/*
+** Copy and destroy temp copy
+*/
+for(j=0,p=TT;j<KEYLEN;j++)
+{       *DK++=*p;
+	*p++=0;
+}
+
+return;
+}
+
+/*
+** MUL(x,y)
+** This #define creates a macro that computes x=x*y modulo 0x10001.
+** Requires temps t16 and t32.  Also requires y to be strictly 16
+** bits.  Here, I am using the simplest form.  May not be the
+** fastest. -- RG
+*/
+/* #define MUL(x,y) (x=mul(low16(x),y)) */
+
+/****************
+** cipher_idea **
+*****************
+** IDEA encryption/decryption algorithm.
+*/
+static void cipher_idea(u16 in[4],
+		u16 out[4],
+		register IDEAkey Z)
+{
+register u16 x1, x2, x3, x4, t1, t2;
+/* register u16 t16;
+register u16 t32; */
+int r=ROUNDS;
+
+x1=*in++;
+x2=*in++;
+x3=*in++;
+x4=*in;
+
+do {
+	MUL(x1,*Z++);
+	x2+=*Z++;
+	x3+=*Z++;
+	MUL(x4,*Z++);
+
+	t2=x1^x3;
+	MUL(t2,*Z++);
+	t1=t2+(x2^x4);
+	MUL(t1,*Z++);
+	t2=t1+t2;
+
+	x1^=t1;
+	x4^=t2;
+
+	t2^=x2;
+	x2=x3^t1;
+	x3=t2;
+} while(--r);
+MUL(x1,*Z++);
+*out++=x1;
+*out++=x3+*Z++;
+*out++=x2+*Z++;
+MUL(x4,*Z);
+*out=x4;
+return;
+}
+
+/************************
+** HUFFMAN COMPRESSION **
+************************/
+
+/**************
+** DoHuffman **
+***************
+** Execute a huffman compression on a block of plaintext.
+** Note that (as with IDEA encryption) an iteration of the
+** Huffman test includes a compression AND a decompression.
+** Also, the compression cycle includes building the
+** Huffman tree.
+*/
+void DoHuffman(void)
+{
+HuffStruct *lochuffstruct;      /* Loc pointer to global data */
+char *errorcontext;
+int systemerror;
+ulong accumtime;
+double iterations;
+farchar *comparray;
+farchar *decomparray;
+farchar *plaintext;
+
+/*
+** Link to global data
+*/
+lochuffstruct=&global_huffstruct;
+
+/*
+** Set error context.
+*/
+errorcontext="CPU:Huffman";
+
+/*
+** Allocate memory for the plaintext and the compressed text.
+** We'll be really pessimistic here, and allocate equal amounts
+** for both (though we know...well, we PRESUME) the compressed
+** stuff will take less than the plain stuff.
+** Also note that we'll build a 3rd buffer to decompress
+** into, and we preallocate space for the huffman tree.
+** (We presume that the Huffman tree will grow no larger
+** than 512 bytes.  This is actually a super-conservative
+** estimate...but, who cares?)
+*/
+plaintext=(farchar *)AllocateMemory(lochuffstruct->arraysize,&systemerror);
+if(systemerror)
+{       ReportError(errorcontext,systemerror);
+	ErrorExit();
+}
+comparray=(farchar *)AllocateMemory(lochuffstruct->arraysize,&systemerror);
+if(systemerror)
+{       ReportError(errorcontext,systemerror);
+	FreeMemory(plaintext,&systemerror);
+	ErrorExit();
+}
+decomparray=(farchar *)AllocateMemory(lochuffstruct->arraysize,&systemerror);
+if(systemerror)
+{       ReportError(errorcontext,systemerror);
+	FreeMemory(plaintext,&systemerror);
+	FreeMemory(comparray,&systemerror);
+	ErrorExit();
+}
+
+hufftree=(huff_node *)AllocateMemory(sizeof(huff_node) * 512,
+	&systemerror);
+if(systemerror)
+{       ReportError(errorcontext,systemerror);
+	FreeMemory(plaintext,&systemerror);
+	FreeMemory(comparray,&systemerror);
+	FreeMemory(decomparray,&systemerror);
+	ErrorExit();
+}
+
+/*
+** Build the plaintext buffer.  Since we want this to
+** actually be able to compress, we'll use the
+** wordcatalog to build the plaintext stuff.
+*/
+/*
+** Reset random number generator so things repeat.
+** added by Uwe F. Mayer
+*/
+randnum((int32)13);
+create_text_block(plaintext,lochuffstruct->arraysize-1,(ushort)500);
+plaintext[lochuffstruct->arraysize-1L]='\0';
+plaintextlen=lochuffstruct->arraysize;
+
+/*
+** See if we need to perform self adjustment loop.
+*/
+if(lochuffstruct->adjust==0)
+{
+	/*
+	** Do self-adjustment.  This involves initializing the
+	** # of loops and increasing the loop count until we
+	** get a number of loops that we can use.
+	*/
+	for(lochuffstruct->loops=100L;
+	  lochuffstruct->loops<MAXHUFFLOOPS;
+	  lochuffstruct->loops+=10L)
+		if(DoHuffIteration(plaintext,
+			comparray,
+			decomparray,
+		  lochuffstruct->arraysize,
+		  lochuffstruct->loops,
+		  hufftree)>global_min_ticks) break;
+}
+
+/*
+** All's well if we get here.  Do the test.
+*/
+accumtime=0L;
+iterations=(double)0.0;
+
+do {
+	accumtime+=DoHuffIteration(plaintext,
+		comparray,
+		decomparray,
+		lochuffstruct->arraysize,
+		lochuffstruct->loops,
+		hufftree);
+	iterations+=(double)lochuffstruct->loops;
+} while(iterations < BASE_ITERATIONS * 20);
+
+/*
+** Clean up, calculate results, and go home.  Be sure to
+** show that we don't have to rerun adjustment code.
+*/
+FreeMemory((farvoid *)plaintext,&systemerror);
+FreeMemory((farvoid *)comparray,&systemerror);
+FreeMemory((farvoid *)decomparray,&systemerror);
+FreeMemory((farvoid *)hufftree,&systemerror);
+lochuffstruct->iterspersec=iterations / TicksToFracSecs(accumtime);
+
+if(lochuffstruct->adjust==0)
+	lochuffstruct->adjust=1;
+
+}
+
+/*********************
+** create_text_line **
+**********************
+** Create a random line of text, stored at *dt.  The line may be
+** no more than nchars long.
+*/
+static void create_text_line(farchar *dt,
+			long nchars)
+{
+long charssofar;        /* # of characters so far */
+long tomove;            /* # of characters to move */
+char myword[40];        /* Local buffer for words */
+farchar *wordptr;       /* Pointer to word from catalog */
+
+charssofar=0;
+
+do {
+/*
+** Grab a random word from the wordcatalog
+*/
+/* wordptr=wordcatarray[abs_randwc((long)WORDCATSIZE)];*/
+wordptr=wordcatarray[abs_randwc((int32)WORDCATSIZE)];
+MoveMemory((farvoid *)myword,
+	(farvoid *)wordptr,
+	(unsigned long)strlen(wordptr)+1);
+
+/*
+** Append a blank.
+*/
+tomove=strlen(myword)+1;
+myword[tomove-1]=' ';
+
+/*
+** See how long it is.  If its length+charssofar > nchars, we have
+** to trim it.
+*/
+if((tomove+charssofar)>nchars)
+	tomove=nchars-charssofar;
+/*
+** Attach the word to the current line.  Increment counter.
+*/
+MoveMemory((farvoid *)dt,(farvoid *)myword,(unsigned long)tomove);
+charssofar+=tomove;
+dt+=tomove;
+
+/*
+** If we're done, bail out.  Otherwise, go get another word.
+*/
+} while(charssofar<nchars);
+
+return;
+}
+
+/**********************
+** create_text_block **
+***********************
+** Build a block of text randomly loaded with words.  The words
+** come from the wordcatalog (which must be loaded before you
+** call this).
+** *tb points to the memory where the text is to be built.
+** tblen is the # of bytes to put into the text block
+** maxlinlen is the maximum length of any line (line end indicated
+**  by a carriage return).
+*/
+static void create_text_block(farchar *tb,
+			ulong tblen,
+			ushort maxlinlen)
+{
+ulong bytessofar;       /* # of bytes so far */
+ulong linelen;          /* Line length */
+
+bytessofar=0L;
+do {
+
+/*
+** Pick a random length for a line and fill the line.
+** Make sure the line can fit (haven't exceeded tablen) and also
+** make sure you leave room to append a carriage return.
+*/
+linelen=abs_randwc(maxlinlen-6)+6;
+if((linelen+bytessofar)>tblen)
+	linelen=tblen-bytessofar;
+
+if(linelen>1)
+{
+	create_text_line(tb,linelen);
+}
+tb+=linelen-1;          /* Add the carriage return */
+*tb++='\n';
+
+bytessofar+=linelen;
+
+} while(bytessofar<tblen);
+
+}
+
+/********************
+** DoHuffIteration **
+*********************
+** Perform the huffman benchmark.  This routine
+**  (a) Builds the huffman tree
+**  (b) Compresses the text
+**  (c) Decompresses the text and verifies correct decompression
+*/
+static ulong DoHuffIteration(farchar *plaintext,
+	farchar *comparray,
+	farchar *decomparray,
+	ulong arraysize,
+	ulong nloops,
+	huff_node *hufftree)
+{
+int i;                          /* Index */
+long j;                         /* Bigger index */
+int root;                       /* Pointer to huffman tree root */
+float lowfreq1, lowfreq2;       /* Low frequency counters */
+int lowidx1, lowidx2;           /* Indexes of low freq. elements */
+long bitoffset;                 /* Bit offset into text */
+long textoffset;                /* Char offset into text */
+long maxbitoffset;              /* Holds limit of bit offset */
+long bitstringlen;              /* Length of bitstring */
+int c;                          /* Character from plaintext */
+char bitstring[30];             /* Holds bitstring */
+ulong elapsed;                  /* For stopwatch */
+#ifdef DEBUG
+int status=0;
+#endif
+
+/*
+** Start the stopwatch
+*/
+elapsed=StartStopwatch();
+
+/*
+** Do everything for nloops
+*/
+while(nloops--)
+{
+
+/*
+** Calculate the frequency of each byte value. Store the
+** results in what will become the "leaves" of the
+** Huffman tree.  Interior nodes will be built in those
+** nodes greater than node #255.
+*/
+for(i=0;i<256;i++)
+{
+	hufftree[i].freq=(float)0.0;
+	hufftree[i].c=(unsigned char)i;
+}
+
+for(j=0;j<arraysize;j++)
+	hufftree[(int)plaintext[j]].freq+=(float)1.0;
+
+for(i=0;i<256;i++)
+	if(hufftree[i].freq != (float)0.0)
+		hufftree[i].freq/=(float)arraysize;
+
+/* Reset the second half of the tree. Otherwise the loop below that
+** compares the frequencies up to index 512 makes no sense. Some
+** systems automatically zero out memory upon allocation, others (like
+** for example DEC Unix) do not. Depending on this the loop below gets
+** different data and different run times. On our alpha the data that
+** was arbitrarily assigned led to an underflow error at runtime. We
+** use that zeroed-out bits are in fact 0 as a float.
+** Uwe F. Mayer */
+bzero((char *)&(hufftree[256]),sizeof(huff_node)*256);
+/*
+** Build the huffman tree.  First clear all the parent
+** pointers and left/right pointers.  Also, discard all
+** nodes that have a frequency of true 0.  */
+for(i=0;i<512;i++)
+{       if(hufftree[i].freq==(float)0.0)
+		hufftree[i].parent=EXCLUDED;
+	else
+		hufftree[i].parent=hufftree[i].left=hufftree[i].right=-1;
+}
+
+/*
+** Go through the tree. Finding nodes of really low
+** frequency.
+*/
+root=255;                       /* Starting root node-1 */
+while(1)
+{
+	lowfreq1=(float)2.0; lowfreq2=(float)2.0;
+	lowidx1=-1; lowidx2=-1;
+	/*
+	** Find first lowest frequency.
+	*/
+	for(i=0;i<=root;i++)
+		if(hufftree[i].parent<0)
+			if(hufftree[i].freq<lowfreq1)
+			{       lowfreq1=hufftree[i].freq;
+				lowidx1=i;
+			}
+
+	/*
+	** Did we find a lowest value?  If not, the
+	** tree is done.
+	*/
+	if(lowidx1==-1) break;
+
+	/*
+	** Find next lowest frequency
+	*/
+	for(i=0;i<=root;i++)
+		if((hufftree[i].parent<0) && (i!=lowidx1))
+			if(hufftree[i].freq<lowfreq2)
+			{       lowfreq2=hufftree[i].freq;
+				lowidx2=i;
+			}
+
+	/*
+	** If we could only find one item, then that
+	** item is surely the root, and (as above) the
+	** tree is done.
+	*/
+	if(lowidx2==-1) break;
+
+	/*
+	** Attach the two new nodes to the current root, and
+	** advance the current root.
+	*/
+	root++;                 /* New root */
+	hufftree[lowidx1].parent=root;
+	hufftree[lowidx2].parent=root;
+	hufftree[root].freq=lowfreq1+lowfreq2;
+	hufftree[root].left=lowidx1;
+	hufftree[root].right=lowidx2;
+	hufftree[root].parent=-2;       /* Show root */
+}
+
+/*
+** Huffman tree built...compress the plaintext
+*/
+bitoffset=0L;                           /* Initialize bit offset */
+for(i=0;i<arraysize;i++)
+{
+	c=(int)plaintext[i];                 /* Fetch character */
+	/*
+	** Build a bit string for byte c
+	*/
+	bitstringlen=0;
+	while(hufftree[c].parent!=-2)
+	{       if(hufftree[hufftree[c].parent].left==c)
+			bitstring[bitstringlen]='0';
+		else
+			bitstring[bitstringlen]='1';
+		c=hufftree[c].parent;
+		bitstringlen++;
+	}
+
+	/*
+	** Step backwards through the bit string, setting
+	** bits in the compressed array as you go.
+	*/
+	while(bitstringlen--)
+	{       SetCompBit((u8 *)comparray,(u32)bitoffset,bitstring[bitstringlen]);
+		bitoffset++;
+	}
+}
+
+/*
+** Compression done.  Perform de-compression.
+*/
+maxbitoffset=bitoffset;
+bitoffset=0;
+textoffset=0;
+do {
+	i=root;
+	while(hufftree[i].left!=-1)
+	{       if(GetCompBit((u8 *)comparray,(u32)bitoffset)==0)
+			i=hufftree[i].left;
+		else
+			i=hufftree[i].right;
+		bitoffset++;
+	}
+	decomparray[textoffset]=hufftree[i].c;
+
+#ifdef DEBUG
+	if(hufftree[i].c != plaintext[textoffset])
+	{
+		/* Show error */
+		printf("Error at textoffset %ld\n",textoffset);
+		status=1;
+	}
+#endif
+	textoffset++;
+} while(bitoffset<maxbitoffset);
+
+}       /* End the big while(nloops--) from above */
+
+/*
+** All done
+*/
+#ifdef DEBUG
+  if (status==0) printf("Huffman: OK\n");
+#endif
+return(StopStopwatch(elapsed));
+}
+
+/***************
+** SetCompBit **
+****************
+** Set a bit in the compression array.  The value of the
+** bit is set according to char bitchar.
+*/
+static void SetCompBit(u8 *comparray,
+		u32 bitoffset,
+		char bitchar)
+{
+u32 byteoffset;
+int bitnumb;
+
+/*
+** First calculate which element in the comparray to
+** alter. and the bitnumber.
+*/
+byteoffset=bitoffset>>3;
+bitnumb=bitoffset % 8;
+
+/*
+** Set or clear
+*/
+if(bitchar=='1')
+	comparray[byteoffset]|=(1<<bitnumb);
+else
+	comparray[byteoffset]&=~(1<<bitnumb);
+
+return;
+}
+
+/***************
+** GetCompBit **
+****************
+** Return the bit value of a bit in the comparession array.
+** Returns 0 if the bit is clear, nonzero otherwise.
+*/
+static int GetCompBit(u8 *comparray,
+		u32 bitoffset)
+{
+u32 byteoffset;
+int bitnumb;
+
+/*
+** Calculate byte offset and bit number.
+*/
+byteoffset=bitoffset>>3;
+bitnumb=bitoffset % 8;
+
+/*
+** Fetch
+*/
+return((1<<bitnumb) & comparray[byteoffset] );
+}
+
+/********************************
+** BACK PROPAGATION NEURAL NET **
+*********************************
+** This code is a modified version of the code
+** that was submitted to BYTE Magazine by
+** Maureen Caudill.  It accomanied an article
+** that I CANNOT NOW RECALL.
+** The author's original heading/comment was
+** as follows:
+**
+**  Backpropagation Network
+**  Written by Maureen Caudill
+**  in Think C 4.0 on a Macintosh
+**
+**  (c) Maureen Caudill 1988-1991
+**  This network will accept 5x7 input patterns
+**  and produce 8 bit output patterns.
+**  The source code may be copied or modified without restriction,
+**  but no fee may be charged for its use.
+**
+** ++++++++++++++
+** I have modified the code so that it will work
+** on systems other than a Macintosh -- RG
+*/
+
+/***********
+** DoNNet **
+************
+** Perform the neural net benchmark.
+** Note that this benchmark is one of the few that
+** requires an input file.  That file is "NNET.DAT" and
+** should be on the local directory (from which the
+** benchmark program in launched).
+*/
+void DoNNET(void)
+{
+NNetStruct *locnnetstruct;      /* Local ptr to global data */
+char *errorcontext;
+ulong accumtime;
+double iterations;
+
+/*
+** Link to global data
+*/
+locnnetstruct=&global_nnetstruct;
+
+/*
+** Set error context
+*/
+errorcontext="CPU:NNET";
+
+/*
+** Init random number generator.
+** NOTE: It is important that the random number generator
+**  be re-initialized for every pass through this test.
+**  The NNET algorithm uses the random number generator
+**  to initialize the net.  Results are sensitive to
+**  the initial neural net state.
+*/
+/* randnum(3L); */
+randnum((int32)3);
+
+/*
+** Read in the input and output patterns.  We'll do this
+** only once here at the beginning.  These values don't
+** change once loaded.
+*/
+if(read_data_file()!=0)
+   ErrorExit();
+
+
+/*
+** See if we need to perform self adjustment loop.
+*/
+if(locnnetstruct->adjust==0)
+{
+	/*
+	** Do self-adjustment.  This involves initializing the
+	** # of loops and increasing the loop count until we
+	** get a number of loops that we can use.
+	*/
+	for(locnnetstruct->loops=1L;
+	  locnnetstruct->loops<MAXNNETLOOPS;
+	  locnnetstruct->loops++)
+	  {     /*randnum(3L); */
+		randnum((int32)3);
+		if(DoNNetIteration(locnnetstruct->loops)
+			>global_min_ticks) break;
+	  }
+}
+
+/*
+** All's well if we get here.  Do the test.
+*/
+accumtime=0L;
+iterations=(double)0.0;
+
+do {
+	/* randnum(3L); */    /* Gotta do this for Neural Net */
+	randnum((int32)3);    /* Gotta do this for Neural Net */
+	accumtime+=DoNNetIteration(locnnetstruct->loops);
+	iterations+=(double)locnnetstruct->loops;
+} while(iterations < BASE_ITERATIONS/2);
+
+/*
+** Clean up, calculate results, and go home.  Be sure to
+** show that we don't have to rerun adjustment code.
+*/
+locnnetstruct->iterspersec=iterations / TicksToFracSecs(accumtime);
+
+if(locnnetstruct->adjust==0)
+	locnnetstruct->adjust=1;
+
+
+return;
+}
+
+/********************
+** DoNNetIteration **
+*********************
+** Do a single iteration of the neural net benchmark.
+** By iteration, we mean a "learning" pass.
+*/
+static ulong DoNNetIteration(ulong nloops)
+{
+ulong elapsed;          /* Elapsed time */
+int patt;
+
+/*
+** Run nloops learning cycles.  Notice that, counted with
+** the learning cycle is the weight randomization and
+** zeroing of changes.  This should reduce clock jitter,
+** since we don't have to stop and start the clock for
+** each iteration.
+*/
+elapsed=StartStopwatch();
+while(nloops--)
+{
+	randomize_wts();
+	zero_changes();
+	iteration_count=1;
+	learned = F;
+	numpasses = 0;
+	while (learned == F)
+	{
+		for (patt=0; patt<numpats; patt++)
+		{
+			worst_error = 0.0;      /* reset this every pass through data */
+			move_wt_changes();      /* move last pass's wt changes to momentum array */
+			do_forward_pass(patt);
+			do_back_pass(patt);
+			iteration_count++;
+		}
+		numpasses ++;
+		learned = check_out_error();
+	}
+#ifdef DEBUG
+printf("Learned in %d passes\n",numpasses);
+#endif
+}
+return(StopStopwatch(elapsed));
+}
+
+/*************************
+** do_mid_forward(patt) **
+**************************
+** Process the middle layer's forward pass
+** The activation of middle layer's neurode is the weighted
+** sum of the inputs from the input pattern, with sigmoid
+** function applied to the inputs.
+**/
+static void  do_mid_forward(int patt)
+{
+double  sum;
+int     neurode, i;
+
+for (neurode=0;neurode<MID_SIZE; neurode++)
+{
+	sum = 0.0;
+	for (i=0; i<IN_SIZE; i++)
+	{       /* compute weighted sum of input signals */
+		sum += mid_wts[neurode][i]*in_pats[patt][i];
+	}
+	/*
+	** apply sigmoid function f(x) = 1/(1+exp(-x)) to weighted sum
+	*/
+	sum = 1.0/(1.0+exp(-sum));
+	mid_out[neurode] = sum;
+}
+return;
+}
+
+/*********************
+** do_out_forward() **
+**********************
+** process the forward pass through the output layer
+** The activation of the output layer is the weighted sum of
+** the inputs (outputs from middle layer), modified by the
+** sigmoid function.
+**/
+static void  do_out_forward()
+{
+double sum;
+int neurode, i;
+
+for (neurode=0; neurode<OUT_SIZE; neurode++)
+{
+	sum = 0.0;
+	for (i=0; i<MID_SIZE; i++)
+	{       /*
+		** compute weighted sum of input signals
+		** from middle layer
+		*/
+		sum += out_wts[neurode][i]*mid_out[i];
+	}
+	/*
+	** Apply f(x) = 1/(1+exp(-x)) to weighted input
+	*/
+	sum = 1.0/(1.0+exp(-sum));
+	out_out[neurode] = sum;
+}
+return;
+}
+
+/*************************
+** display_output(patt) **
+**************************
+** Display the actual output vs. the desired output of the
+** network.
+** Once the training is complete, and the "learned" flag set
+** to TRUE, then display_output sends its output to both
+** the screen and to a text output file.
+**
+** NOTE: This routine has been disabled in the benchmark
+** version. -- RG
+**/
+/*
+void  display_output(int patt)
+{
+int             i;
+
+	fprintf(outfile,"\n Iteration # %d",iteration_count);
+	fprintf(outfile,"\n Desired Output:  ");
+
+	for (i=0; i<OUT_SIZE; i++)
+	{
+		fprintf(outfile,"%6.3f  ",out_pats[patt][i]);
+	}
+	fprintf(outfile,"\n Actual Output:   ");
+
+	for (i=0; i<OUT_SIZE; i++)
+	{
+		fprintf(outfile,"%6.3f  ",out_out[i]);
+	}
+	fprintf(outfile,"\n");
+	return;
+}
+*/
+
+/**********************
+** do_forward_pass() **
+***********************
+** control function for the forward pass through the network
+** NOTE: I have disabled the call to display_output() in
+**  the benchmark version -- RG.
+**/
+static void  do_forward_pass(int patt)
+{
+do_mid_forward(patt);   /* process forward pass, middle layer */
+do_out_forward();       /* process forward pass, output layer */
+/* display_output(patt);        ** display results of forward pass */
+return;
+}
+
+/***********************
+** do_out_error(patt) **
+************************
+** Compute the error for the output layer neurodes.
+** This is simply Desired - Actual.
+**/
+static void do_out_error(int patt)
+{
+int neurode;
+double error,tot_error, sum;
+
+tot_error = 0.0;
+sum = 0.0;
+for (neurode=0; neurode<OUT_SIZE; neurode++)
+{
+	out_error[neurode] = out_pats[patt][neurode] - out_out[neurode];
+	/*
+	** while we're here, also compute magnitude
+	** of total error and worst error in this pass.
+	** We use these to decide if we are done yet.
+	*/
+	error = out_error[neurode];
+	if (error <0.0)
+	{
+		sum += -error;
+		if (-error > tot_error)
+			tot_error = -error; /* worst error this pattern */
+	}
+	else
+	{
+		sum += error;
+		if (error > tot_error)
+			tot_error = error; /* worst error this pattern */
+	}
+}
+avg_out_error[patt] = sum/OUT_SIZE;
+tot_out_error[patt] = tot_error;
+return;
+}
+
+/***********************
+** worst_pass_error() **
+************************
+** Find the worst and average error in the pass and save it
+**/
+static void  worst_pass_error()
+{
+double error,sum;
+
+int i;
+
+error = 0.0;
+sum = 0.0;
+for (i=0; i<numpats; i++)
+{
+	if (tot_out_error[i] > error) error = tot_out_error[i];
+	sum += avg_out_error[i];
+}
+worst_error = error;
+average_error = sum/numpats;
+return;
+}
+
+/*******************
+** do_mid_error() **
+********************
+** Compute the error for the middle layer neurodes
+** This is based on the output errors computed above.
+** Note that the derivative of the sigmoid f(x) is
+**        f'(x) = f(x)(1 - f(x))
+** Recall that f(x) is merely the output of the middle
+** layer neurode on the forward pass.
+**/
+static void do_mid_error()
+{
+double sum;
+int neurode, i;
+
+for (neurode=0; neurode<MID_SIZE; neurode++)
+{
+	sum = 0.0;
+	for (i=0; i<OUT_SIZE; i++)
+		sum += out_wts[i][neurode]*out_error[i];
+
+	/*
+	** apply the derivative of the sigmoid here
+	** Because of the choice of sigmoid f(I), the derivative
+	** of the sigmoid is f'(I) = f(I)(1 - f(I))
+	*/
+	mid_error[neurode] = mid_out[neurode]*(1-mid_out[neurode])*sum;
+}
+return;
+}
+
+/*********************
+** adjust_out_wts() **
+**********************
+** Adjust the weights of the output layer.  The error for
+** the output layer has been previously propagated back to
+** the middle layer.
+** Use the Delta Rule with momentum term to adjust the weights.
+**/
+static void adjust_out_wts()
+{
+int weight, neurode;
+double learn,delta,alph;
+
+learn = BETA;
+alph  = ALPHA;
+for (neurode=0; neurode<OUT_SIZE; neurode++)
+{
+	for (weight=0; weight<MID_SIZE; weight++)
+	{
+		/* standard delta rule */
+		delta = learn * out_error[neurode] * mid_out[weight];
+
+		/* now the momentum term */
+		delta += alph * out_wt_change[neurode][weight];
+		out_wts[neurode][weight] += delta;
+
+		/* keep track of this pass's cum wt changes for next pass's momentum */
+		out_wt_cum_change[neurode][weight] += delta;
+	}
+}
+return;
+}
+
+/*************************
+** adjust_mid_wts(patt) **
+**************************
+** Adjust the middle layer weights using the previously computed
+** errors.
+** We use the Generalized Delta Rule with momentum term
+**/
+static void adjust_mid_wts(int patt)
+{
+int weight, neurode;
+double learn,alph,delta;
+
+learn = BETA;
+alph  = ALPHA;
+for (neurode=0; neurode<MID_SIZE; neurode++)
+{
+	for (weight=0; weight<IN_SIZE; weight++)
+	{
+		/* first the basic delta rule */
+		delta = learn * mid_error[neurode] * in_pats[patt][weight];
+
+		/* with the momentum term */
+		delta += alph * mid_wt_change[neurode][weight];
+		mid_wts[neurode][weight] += delta;
+
+		/* keep track of this pass's cum wt changes for next pass's momentum */
+		mid_wt_cum_change[neurode][weight] += delta;
+	}
+}
+return;
+}
+
+/*******************
+** do_back_pass() **
+********************
+** Process the backward propagation of error through network.
+**/
+void  do_back_pass(int patt)
+{
+
+do_out_error(patt);
+do_mid_error();
+adjust_out_wts();
+adjust_mid_wts(patt);
+
+return;
+}
+
+
+/**********************
+** move_wt_changes() **
+***********************
+** Move the weight changes accumulated last pass into the wt-change
+** array for use by the momentum term in this pass. Also zero out
+** the accumulating arrays after the move.
+**/
+static void move_wt_changes()
+{
+int i,j;
+
+for (i = 0; i<MID_SIZE; i++)
+	for (j = 0; j<IN_SIZE; j++)
+	{
+		mid_wt_change[i][j] = mid_wt_cum_change[i][j];
+		/*
+		** Zero it out for next pass accumulation.
+		*/
+		mid_wt_cum_change[i][j] = 0.0;
+	}
+
+for (i = 0; i<OUT_SIZE; i++)
+	for (j=0; j<MID_SIZE; j++)
+	{
+		out_wt_change[i][j] = out_wt_cum_change[i][j];
+		out_wt_cum_change[i][j] = 0.0;
+	}
+
+return;
+}
+
+/**********************
+** check_out_error() **
+***********************
+** Check to see if the error in the output layer is below
+** MARGIN*OUT_SIZE for all output patterns.  If so, then
+** assume the network has learned acceptably well.  This
+** is simply an arbitrary measure of how well the network
+** has learned -- many other standards are possible.
+**/
+static int check_out_error()
+{
+int result,i,error;
+
+result  = T;
+error   = F;
+worst_pass_error();     /* identify the worst error in this pass */
+
+/*
+#ifdef DEBUG
+printf("\n Iteration # %d",iteration_count);
+#endif
+*/
+for (i=0; i<numpats; i++)
+{
+/*      printf("\n Error pattern %d:   Worst: %8.3f; Average: %8.3f",
+	  i+1,tot_out_error[i], avg_out_error[i]);
+	fprintf(outfile,
+	 "\n Error pattern %d:   Worst: %8.3f; Average: %8.3f",
+	 i+1,tot_out_error[i]);
+*/
+
+	if (worst_error >= STOP) result = F;
+	if (tot_out_error[i] >= 16.0) error = T;
+}
+
+if (error == T) result = ERR;
+
+
+#ifdef DEBUG
+/* printf("\n Error this pass thru data:   Worst: %8.3f; Average: %8.3f",
+ worst_error,average_error);
+*/
+/* fprintf(outfile,
+ "\n Error this pass thru data:   Worst: %8.3f; Average: %8.3f",
+  worst_error, average_error); */
+#endif
+
+return(result);
+}
+
+
+/*******************
+** zero_changes() **
+********************
+** Zero out all the wt change arrays
+**/
+static void zero_changes()
+{
+int i,j;
+
+for (i = 0; i<MID_SIZE; i++)
+{
+	for (j=0; j<IN_SIZE; j++)
+	{
+		mid_wt_change[i][j] = 0.0;
+		mid_wt_cum_change[i][j] = 0.0;
+	}
+}
+
+for (i = 0; i< OUT_SIZE; i++)
+{
+	for (j=0; j<MID_SIZE; j++)
+	{
+		out_wt_change[i][j] = 0.0;
+		out_wt_cum_change[i][j] = 0.0;
+	}
+}
+return;
+}
+
+
+/********************
+** randomize_wts() **
+*********************
+** Intialize the weights in the middle and output layers to
+** random values between -0.25..+0.25
+** Function rand() returns a value between 0 and 32767.
+**
+** NOTE: Had to make alterations to how the random numbers were
+** created.  -- RG.
+**/
+static void randomize_wts()
+{
+int neurode,i;
+double value;
+
+/*
+** Following not used int benchmark version -- RG
+**
+**        printf("\n Please enter a random number seed (1..32767):  ");
+**        scanf("%d", &i);
+**        srand(i);
+*/
+
+for (neurode = 0; neurode<MID_SIZE; neurode++)
+{
+	for(i=0; i<IN_SIZE; i++)
+	{
+	        /* value=(double)abs_randwc(100000L); */
+		value=(double)abs_randwc((int32)100000);
+		value=value/(double)100000.0 - (double) 0.5;
+		mid_wts[neurode][i] = value/2;
+	}
+}
+for (neurode=0; neurode<OUT_SIZE; neurode++)
+{
+	for(i=0; i<MID_SIZE; i++)
+	{
+	        /* value=(double)abs_randwc(100000L); */
+		value=(double)abs_randwc((int32)100000);
+		value=value/(double)10000.0 - (double) 0.5;
+		out_wts[neurode][i] = value/2;
+	}
+}
+
+return;
+}
+
+
+/*********************
+** read_data_file() **
+**********************
+** Read in the input data file and store the patterns in
+** in_pats and out_pats.
+** The format for the data file is as follows:
+**
+** line#   data expected
+** -----   ------------------------------
+** 1               In-X-size,in-y-size,out-size
+** 2               number of patterns in file
+** 3               1st X row of 1st input pattern
+** 4..             following rows of 1st input pattern pattern
+**                 in-x+2  y-out pattern
+**                                 1st X row of 2nd pattern
+**                 etc.
+**
+** Each row of data is separated by commas or spaces.
+** The data is expected to be ascii text corresponding to
+** either a +1 or a 0.
+**
+** Sample input for a 1-pattern file (The comments to the
+** right may NOT be in the file unless more sophisticated
+** parsing of the input is done.):
+**
+** 5,7,8                      input is 5x7 grid, output is 8 bits
+** 1                          one pattern in file
+** 0,1,1,1,0                  beginning of pattern for "O"
+** 1,0,0,0,1
+** 1,0,0,0,1
+** 1,0,0,0,1
+** 1,0,0,0,1
+** 1,0,0,0,0
+** 0,1,1,1,0
+** 0,1,0,0,1,1,1,1            ASCII code for "O" -- 0100 1111
+**
+** Clearly, this simple scheme can be expanded or enhanced
+** any way you like.
+**
+** Returns -1 if any file error occurred, otherwise 0.
+**/
+static int read_data_file()
+{
+FILE *infile;
+
+int xinsize,yinsize,youtsize;
+int patt, element, i, row;
+int vals_read;
+int val1,val2,val3,val4,val5,val6,val7,val8;
+
+/* printf("\n Opening and retrieving data from file."); */
+
+infile = fopen(inpath, "r");
+if (infile == NULL)
+{
+	printf("\n CPU:NNET--error in opening file!");
+	return -1 ;
+}
+vals_read =fscanf(infile,"%d  %d  %d",&xinsize,&yinsize,&youtsize);
+if (vals_read != 3)
+{
+	printf("\n CPU:NNET -- Should read 3 items in line one; did read %d",vals_read);
+	return -1;
+}
+vals_read=fscanf(infile,"%d",&numpats);
+if (vals_read !=1)
+{
+	printf("\n CPU:NNET -- Should read 1 item in line 2; did read %d",vals_read);
+	return -1;
+}
+if (numpats > MAXPATS)
+	numpats = MAXPATS;
+
+for (patt=0; patt<numpats; patt++)
+{
+	element = 0;
+	for (row = 0; row<yinsize; row++)
+	{
+		vals_read = fscanf(infile,"%d  %d  %d  %d  %d",
+			&val1, &val2, &val3, &val4, &val5);
+		if (vals_read != 5)
+		{
+			printf ("\n CPU:NNET -- failure in reading input!");
+			return -1;
+		}
+		element=row*xinsize;
+
+		in_pats[patt][element] = (double) val1; element++;
+		in_pats[patt][element] = (double) val2; element++;
+		in_pats[patt][element] = (double) val3; element++;
+		in_pats[patt][element] = (double) val4; element++;
+		in_pats[patt][element] = (double) val5; element++;
+	}
+	for (i=0;i<IN_SIZE; i++)
+	{
+		if (in_pats[patt][i] >= 0.9)
+			in_pats[patt][i] = 0.9;
+		if (in_pats[patt][i] <= 0.1)
+			in_pats[patt][i] = 0.1;
+	}
+	element = 0;
+	vals_read = fscanf(infile,"%d  %d  %d  %d  %d  %d  %d  %d",
+		&val1, &val2, &val3, &val4, &val5, &val6, &val7, &val8);
+
+	out_pats[patt][element] = (double) val1; element++;
+	out_pats[patt][element] = (double) val2; element++;
+	out_pats[patt][element] = (double) val3; element++;
+	out_pats[patt][element] = (double) val4; element++;
+	out_pats[patt][element] = (double) val5; element++;
+	out_pats[patt][element] = (double) val6; element++;
+	out_pats[patt][element] = (double) val7; element++;
+	out_pats[patt][element] = (double) val8; element++;
+}
+
+/* printf("\n Closing the input file now. "); */
+
+fclose(infile);
+return(0);
+}
+
+/*********************
+** initialize_net() **
+**********************
+** Do all the initialization stuff before beginning
+*/
+/*
+static int initialize_net()
+{
+int err_code;
+
+randomize_wts();
+zero_changes();
+err_code = read_data_file();
+iteration_count = 1;
+return(err_code);
+}
+*/
+
+/**********************
+** display_mid_wts() **
+***********************
+** Display the weights on the middle layer neurodes
+** NOTE: This routine is not used in the benchmark
+**  test -- RG
+**/
+/* static void display_mid_wts()
+{
+int             neurode, weight, row, col;
+
+fprintf(outfile,"\n Weights of Middle Layer neurodes:");
+
+for (neurode=0; neurode<MID_SIZE; neurode++)
+{
+	fprintf(outfile,"\n  Mid Neurode # %d",neurode);
+	for (row=0; row<IN_Y_SIZE; row++)
+	{
+		fprintf(outfile,"\n ");
+		for (col=0; col<IN_X_SIZE; col++)
+		{
+			weight = IN_X_SIZE * row + col;
+			fprintf(outfile," %8.3f ", mid_wts[neurode][weight]);
+		}
+	}
+}
+return;
+}
+*/
+/**********************
+** display_out_wts() **
+***********************
+** Display the weights on the output layer neurodes
+** NOTE: This code is not used in the benchmark
+**  test -- RG
+*/
+/* void  display_out_wts()
+{
+int             neurode, weight;
+
+	fprintf(outfile,"\n Weights of Output Layer neurodes:");
+
+	for (neurode=0; neurode<OUT_SIZE; neurode++)
+	{
+		fprintf(outfile,"\n  Out Neurode # %d \n",neurode);
+		for (weight=0; weight<MID_SIZE; weight++)
+		{
+			fprintf(outfile," %8.3f ", out_wts[neurode][weight]);
+		}
+	}
+	return;
+}
+*/
+
+/***********************
+**  LU DECOMPOSITION  **
+** (Linear Equations) **
+************************
+** These routines come from "Numerical Recipes in Pascal".
+** Note that, as in the assignment algorithm, though we
+** separately define LUARRAYROWS and LUARRAYCOLS, the two
+** must be the same value (this routine depends on a square
+** matrix).
+*/
+
+/*********
+** DoLU **
+**********
+** Perform the LU decomposition benchmark.
+*/
+void DoLU(void)
+{
+LUStruct *loclustruct;  /* Local pointer to global data */
+char *errorcontext;
+int systemerror;
+fardouble *a;
+fardouble *b;
+fardouble *abase;
+fardouble *bbase;
+LUdblptr ptra;
+int n;
+int i;
+ulong accumtime;
+double iterations;
+
+/*
+** Link to global data
+*/
+loclustruct=&global_lustruct;
+
+/*
+** Set error context.
+*/
+errorcontext="FPU:LU";
+
+/*
+** Our first step is to build a "solvable" problem.  This
+** will become the "seed" set that all others will be
+** derived from. (I.E., we'll simply copy these arrays
+** into the others.
+*/
+a=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYCOLS * LUARRAYROWS,
+		&systemerror);
+b=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYROWS,
+		&systemerror);
+n=LUARRAYROWS;
+
+/*
+** We need to allocate a temp vector that is used by the LU
+** algorithm.  This removes the allocation routine from the
+** timing.
+*/
+LUtempvv=(fardouble *)AllocateMemory(sizeof(double)*LUARRAYROWS,
+	&systemerror);
+
+/*
+** Build a problem to be solved.
+*/
+ptra.ptrs.p=a;                  /* Gotta coerce linear array to 2D array */
+build_problem(*ptra.ptrs.ap,n,b);
+
+/*
+** Now that we have a problem built, see if we need to do
+** auto-adjust.  If so, repeatedly call the DoLUIteration routine,
+** increasing the number of solutions per iteration as you go.
+*/
+if(loclustruct->adjust==0)
+{
+	loclustruct->numarrays=0;
+	for(i=1;i<=MAXLUARRAYS;i++)
+	{
+		abase=(fardouble *)AllocateMemory(sizeof(double) *
+			LUARRAYCOLS*LUARRAYROWS*(i+1),&systemerror);
+		if(systemerror)
+		{       ReportError(errorcontext,systemerror);
+			LUFreeMem(a,b,(fardouble *)NULL,(fardouble *)NULL);
+			ErrorExit();
+		}
+		bbase=(fardouble *)AllocateMemory(sizeof(double) *
+			LUARRAYROWS*(i+1),&systemerror);
+		if(systemerror)
+		{       ReportError(errorcontext,systemerror);
+			LUFreeMem(a,b,abase,(fardouble *)NULL);
+			ErrorExit();
+		}
+		if(DoLUIteration(a,b,abase,bbase,i)>global_min_ticks)
+		{       loclustruct->numarrays=i;
+			break;
+		}
+		/*
+		** Not enough arrays...free them all and try again
+		*/
+		FreeMemory((farvoid *)abase,&systemerror);
+		FreeMemory((farvoid *)bbase,&systemerror);
+	}
+	/*
+	** Were we able to do it?
+	*/
+	if(loclustruct->numarrays==0)
+	{       printf("FPU:LU -- Array limit reached\n");
+		LUFreeMem(a,b,abase,bbase);
+		ErrorExit();
+	}
+}
+else
+{       /*
+	** Don't need to adjust -- just allocate the proper
+	** number of arrays and proceed.
+	*/
+	abase=(fardouble *)AllocateMemory(sizeof(double) *
+		LUARRAYCOLS*LUARRAYROWS*loclustruct->numarrays,
+		&systemerror);
+	if(systemerror)
+	{       ReportError(errorcontext,systemerror);
+		LUFreeMem(a,b,(fardouble *)NULL,(fardouble *)NULL);
+		ErrorExit();
+	}
+	bbase=(fardouble *)AllocateMemory(sizeof(double) *
+		LUARRAYROWS*loclustruct->numarrays,&systemerror);
+	if(systemerror)
+	{
+		ReportError(errorcontext,systemerror);
+		LUFreeMem(a,b,abase,(fardouble *)NULL);
+		ErrorExit();
+	}
+}
+/*
+** All's well if we get here.  Do the test.
+*/
+accumtime=0L;
+iterations=(double)0.0;
+
+do {
+	accumtime+=DoLUIteration(a,b,abase,bbase,
+		loclustruct->numarrays);
+	iterations+=(double)loclustruct->numarrays;
+} while(iterations < BASE_ITERATIONS * 20);
+
+/*
+** Clean up, calculate results, and go home.  Be sure to
+** show that we don't have to rerun adjustment code.
+*/
+loclustruct->iterspersec=iterations / TicksToFracSecs(accumtime);
+
+if(loclustruct->adjust==0)
+	loclustruct->adjust=1;
+
+LUFreeMem(a,b,abase,bbase);
+return;
+}
+
+/**************
+** LUFreeMem **
+***************
+** Release memory associated with LU benchmark.
+*/
+static void LUFreeMem(fardouble *a, fardouble *b,
+			fardouble *abase,fardouble *bbase)
+{
+int systemerror;
+
+FreeMemory((farvoid *)a,&systemerror);
+FreeMemory((farvoid *)b,&systemerror);
+FreeMemory((farvoid *)LUtempvv,&systemerror);
+
+if(abase!=(fardouble *)NULL) FreeMemory((farvoid *)abase,&systemerror);
+if(bbase!=(fardouble *)NULL) FreeMemory((farvoid *)bbase,&systemerror);
+return;
+}
+
+/******************
+** DoLUIteration **
+*******************
+** Perform an iteration of the LU decomposition benchmark.
+** An iteration refers to the repeated solution of several
+** identical matrices.
+*/
+static ulong DoLUIteration(fardouble *a,fardouble *b,
+		fardouble *abase, fardouble *bbase,
+		ulong numarrays)
+{
+fardouble *locabase;
+fardouble *locbbase;
+LUdblptr ptra;  /* For converting ptr to 2D array */
+ulong elapsed;
+ulong j,i;              /* Indexes */
+
+
+/*
+** Move the seed arrays (a & b) into the destination
+** arrays;
+*/
+for(j=0;j<numarrays;j++)
+{       locabase=abase+j*LUARRAYROWS*LUARRAYCOLS;
+	locbbase=bbase+j*LUARRAYROWS;
+	for(i=0;i<LUARRAYROWS*LUARRAYCOLS;i++)
+		*(locabase+i)=*(a+i);
+	for(i=0;i<LUARRAYROWS;i++)
+		*(locbbase+i)=*(b+i);
+}
+
+/*
+** Do test...begin timing.
+*/
+elapsed=StartStopwatch();
+for(i=0;i<numarrays;i++)
+{       locabase=abase+i*LUARRAYROWS*LUARRAYCOLS;
+	locbbase=bbase+i*LUARRAYROWS;
+	ptra.ptrs.p=locabase;
+	lusolve(*ptra.ptrs.ap,LUARRAYROWS,locbbase);
+}
+
+return(StopStopwatch(elapsed));
+}
+
+/******************
+** build_problem **
+*******************
+** Constructs a solvable set of linear equations.  It does this by
+** creating an identity matrix, then loading the solution vector
+** with random numbers.  After that, the identity matrix and
+** solution vector are randomly "scrambled".  Scrambling is
+** done by (a) randomly selecting a row and multiplying that
+** row by a random number and (b) adding one randomly-selected
+** row to another.
+*/
+static void build_problem(double a[][LUARRAYCOLS],
+		int n,
+		double b[LUARRAYROWS])
+{
+long i,j,k,k1;  /* Indexes */
+double rcon;     /* Random constant */
+
+/*
+** Reset random number generator
+*/
+/* randnum(13L); */
+randnum((int32)13);
+
+/*
+** Build an identity matrix.
+** We'll also use this as a chance to load the solution
+** vector.
+*/
+for(i=0;i<n;i++)
+{       /* b[i]=(double)(abs_randwc(100L)+1L); */
+	b[i]=(double)(abs_randwc((int32)100)+(int32)1);
+	for(j=0;j<n;j++)
+		if(i==j)
+		        /* a[i][j]=(double)(abs_randwc(1000L)+1L); */
+			a[i][j]=(double)(abs_randwc((int32)1000)+(int32)1);
+		else
+			a[i][j]=(double)0.0;
+}
+
+#ifdef DEBUG
+printf("Problem:\n");
+for(i=0;i<n;i++)
+{
+/*
+	for(j=0;j<n;j++)
+		printf("%6.2f ",a[i][j]);
+*/
+	printf("%.0f/%.0f=%.2f\t",b[i],a[i][i],b[i]/a[i][i]);
+/*
+        printf("\n");
+*/
+}
+#endif
+
+/*
+** Scramble.  Do this 8n times.  See comment above for
+** a description of the scrambling process.
+*/
+
+for(i=0;i<8*n;i++)
+{
+	/*
+	** Pick a row and a random constant.  Multiply
+	** all elements in the row by the constant.
+	*/
+ /*       k=abs_randwc((long)n);
+	rcon=(double)(abs_randwc(20L)+1L);
+	for(j=0;j<n;j++)
+		a[k][j]=a[k][j]*rcon;
+	b[k]=b[k]*rcon;
+*/
+	/*
+	** Pick two random rows and add second to
+	** first.  Note that we also occasionally multiply
+	** by minus 1 so that we get a subtraction operation.
+	*/
+        /* k=abs_randwc((long)n); */
+        /* k1=abs_randwc((long)n); */
+	k=abs_randwc((int32)n);
+	k1=abs_randwc((int32)n);
+	if(k!=k1)
+	{
+		if(k<k1) rcon=(double)1.0;
+			else rcon=(double)-1.0;
+		for(j=0;j<n;j++)
+			a[k][j]+=a[k1][j]*rcon;;
+		b[k]+=b[k1]*rcon;
+	}
+}
+
+return;
+}
+
+
+/***********
+** ludcmp **
+************
+** From the procedure of the same name in "Numerical Recipes in Pascal",
+** by Press, Flannery, Tukolsky, and Vetterling.
+** Given an nxn matrix a[], this routine replaces it by the LU
+** decomposition of a rowwise permutation of itself.  a[] and n
+** are input.  a[] is output, modified as follows:
+**   --                       --
+**  |  b(1,1) b(1,2) b(1,3)...  |
+**  |  a(2,1) b(2,2) b(2,3)...  |
+**  |  a(3,1) a(3,2) b(3,3)...  |
+**  |  a(4,1) a(4,2) a(4,3)...  |
+**  |  ...                      |
+**   --                        --
+**
+** Where the b(i,j) elements form the upper triangular matrix of the
+** LU decomposition, and the a(i,j) elements form the lower triangular
+** elements.  The LU decomposition is calculated so that we don't
+** need to store the a(i,i) elements (which would have laid along the
+** diagonal and would have all been 1).
+**
+** indx[] is an output vector that records the row permutation
+** effected by the partial pivoting; d is output as +/-1 depending
+** on whether the number of row interchanges was even or odd,
+** respectively.
+** Returns 0 if matrix singular, else returns 1.
+*/
+static int ludcmp(double a[][LUARRAYCOLS],
+		int n,
+		int indx[],
+		int *d)
+{
+
+double big;     /* Holds largest element value */
+double sum;
+double dum;     /* Holds dummy value */
+int i,j,k;      /* Indexes */
+int imax=0;     /* Holds max index value */
+double tiny;    /* A really small number */
+
+tiny=(double)1.0e-20;
+
+*d=1;           /* No interchanges yet */
+
+for(i=0;i<n;i++)
+{       big=(double)0.0;
+	for(j=0;j<n;j++)
+		if((double)fabs(a[i][j]) > big)
+			big=fabs(a[i][j]);
+	/* Bail out on singular matrix */
+	if(big==(double)0.0) return(0);
+	LUtempvv[i]=1.0/big;
+}
+
+/*
+** Crout's algorithm...loop over columns.
+*/
+for(j=0;j<n;j++)
+{       if(j!=0)
+		for(i=0;i<j;i++)
+		{       sum=a[i][j];
+			if(i!=0)
+				for(k=0;k<i;k++)
+					sum-=(a[i][k]*a[k][j]);
+			a[i][j]=sum;
+		}
+	big=(double)0.0;
+	for(i=j;i<n;i++)
+	{       sum=a[i][j];
+		if(j!=0)
+			for(k=0;k<j;k++)
+				sum-=a[i][k]*a[k][j];
+		a[i][j]=sum;
+		dum=LUtempvv[i]*fabs(sum);
+		if(dum>=big)
+		{       big=dum;
+			imax=i;
+		}
+	}
+	if(j!=imax)             /* Interchange rows if necessary */
+	{       for(k=0;k<n;k++)
+		{       dum=a[imax][k];
+			a[imax][k]=a[j][k];
+			a[j][k]=dum;
+		}
+		*d=-*d;         /* Change parity of d */
+		dum=LUtempvv[imax];
+		LUtempvv[imax]=LUtempvv[j]; /* Don't forget scale factor */
+		LUtempvv[j]=dum;
+	}
+	indx[j]=imax;
+	/*
+	** If the pivot element is zero, the matrix is singular
+	** (at least as far as the precision of the machine
+	** is concerned.)  We'll take the original author's
+	** recommendation and replace 0.0 with "tiny".
+	*/
+	if(a[j][j]==(double)0.0)
+		a[j][j]=tiny;
+
+	if(j!=(n-1))
+	{       dum=1.0/a[j][j];
+		for(i=j+1;i<n;i++)
+			a[i][j]=a[i][j]*dum;
+	}
+}
+
+return(1);
+}
+
+/***********
+** lubksb **
+************
+** Also from "Numerical Recipes in Pascal".
+** This routine solves the set of n linear equations A X = B.
+** Here, a[][] is input, not as the matrix A, but as its
+** LU decomposition, created by the routine ludcmp().
+** Indx[] is input as the permutation vector returned by ludcmp().
+**  b[] is input as the right-hand side an returns the
+** solution vector X.
+** a[], n, and indx are not modified by this routine and
+** can be left in place for different values of b[].
+** This routine takes into account the possibility that b will
+** begin with many zero elements, so it is efficient for use in
+** matrix inversion.
+*/
+static void lubksb( double a[][LUARRAYCOLS],
+		int n,
+		int indx[LUARRAYROWS],
+		double b[LUARRAYROWS])
+{
+
+int i,j;        /* Indexes */
+int ip;         /* "pointer" into indx */
+int ii;
+double sum;
+
+/*
+** When ii is set to a positive value, it will become
+** the index of the first nonvanishing element of b[].
+** We now do the forward substitution. The only wrinkle
+** is to unscramble the permutation as we go.
+*/
+ii=-1;
+for(i=0;i<n;i++)
+{       ip=indx[i];
+	sum=b[ip];
+	b[ip]=b[i];
+	if(ii!=-1)
+		for(j=ii;j<i;j++)
+			sum=sum-a[i][j]*b[j];
+	else
+		/*
+		** If a nonzero element is encountered, we have
+		** to do the sums in the loop above.
+		*/
+		if(sum!=(double)0.0)
+			ii=i;
+	b[i]=sum;
+}
+/*
+** Do backsubstitution
+*/
+for(i=(n-1);i>=0;i--)
+{
+	sum=b[i];
+	if(i!=(n-1))
+		for(j=(i+1);j<n;j++)
+			sum=sum-a[i][j]*b[j];
+	b[i]=sum/a[i][i];
+}
+return;
+}
+
+/************
+** lusolve **
+*************
+** Solve a linear set of equations: A x = b
+** Original matrix A will be destroyed by this operation.
+** Returns 0 if matrix is singular, 1 otherwise.
+*/
+static int lusolve(double a[][LUARRAYCOLS],
+		int n,
+		double b[LUARRAYROWS])
+{
+int indx[LUARRAYROWS];
+int d;
+#ifdef DEBUG
+int i,j;
+#endif
+
+if(ludcmp(a,n,indx,&d)==0) return(0);
+
+/* Matrix not singular -- proceed */
+lubksb(a,n,indx,b);
+
+#ifdef DEBUG
+printf("Solution:\n");
+for(i=0;i<n;i++)
+{
+  for(j=0;j<n;j++){
+  /*
+    printf("%6.2f ",a[i][j]);
+  */
+  }
+  printf("%6.2f\t",b[i]);
+  /*
+    printf("\n");
+  */
+}
+printf("\n");
+#endif
+
+return(1);
+}

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/nbench1.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/nbench1.h?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/nbench1.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/nbench1.h Sun Jan 22 03:50:58 2012
@@ -0,0 +1,428 @@
+/*
+** nbench1.h
+** Header for nbench1.c
+** BYTEmark (tm)
+** BYTE's Native Mode Benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Creation:
+** Revision: 3/95;10/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/*
+** DEFINES
+*/
+/* #define DEBUG */
+
+/*
+** EXTERNALS
+*/
+extern ulong global_min_ticks;
+
+extern SortStruct global_numsortstruct;
+extern SortStruct global_strsortstruct;
+extern BitOpStruct global_bitopstruct;
+extern EmFloatStruct global_emfloatstruct;
+extern FourierStruct global_fourierstruct;
+extern AssignStruct global_assignstruct;
+extern IDEAStruct global_ideastruct;
+extern HuffStruct global_huffstruct;
+extern NNetStruct global_nnetstruct;
+extern LUStruct global_lustruct;
+
+/* External PROTOTYPES */
+/*extern unsigned long abs_randwc(unsigned long num);*/     /* From MISC */
+/*extern long randnum(long lngval);*/
+extern int32 randwc(int32 num);
+extern u32 abs_randwc(u32 num);
+extern int32 randnum(int32 lngval);
+
+extern farvoid *AllocateMemory(unsigned long nbytes,    /* From SYSSPEC */
+	int *errorcode);
+extern void FreeMemory(farvoid *mempointer,
+	int *errorcode);
+extern void MoveMemory(farvoid *destination,
+		farvoid *source, unsigned long nbytes);
+extern void ReportError(char *context, int errorcode);
+extern void ErrorExit();
+extern unsigned long StartStopwatch();
+extern unsigned long StopStopwatch(unsigned long startticks);
+extern unsigned long TicksToSecs(unsigned long tickamount);
+extern double TicksToFracSecs(unsigned long tickamount);
+
+/*****************
+** NUMERIC SORT **
+*****************/
+
+/*
+** PROTOTYPES
+*/
+void DoNumSort(void);
+static ulong DoNumSortIteration(farlong *arraybase,
+		ulong arraysize,
+		uint numarrays);
+static void LoadNumArrayWithRand(farlong *array,
+		ulong arraysize,
+		uint numarrays);
+static void NumHeapSort(farlong *array,
+		ulong bottom,
+		ulong top);
+static void NumSift(farlong *array,
+		ulong i,
+		ulong j);
+
+
+/****************
+** STRING SORT **
+*****************
+*/
+
+
+/*
+** PROTOTYPES
+*/
+void DoStringSort(void);
+static ulong DoStringSortIteration(faruchar *arraybase,
+		uint numarrays,
+		ulong arraysize);
+static farulong *LoadStringArray(faruchar *strarray,
+		uint numarrays,
+		ulong *strings,
+		ulong arraysize);
+static void stradjust(farulong *optrarray,
+		faruchar *strarray,
+		ulong nstrings,
+		ulong i,
+		uchar l);
+static void StrHeapSort(farulong *optrarray,
+		faruchar *strarray,
+		ulong numstrings,
+		ulong bottom,
+		ulong top);
+static int str_is_less(farulong *optrarray,
+		faruchar *strarray,
+		ulong numstrings,
+		ulong a,
+		ulong b);
+static void strsift(farulong *optrarray,
+		faruchar *strarray,
+		ulong numstrings,
+		ulong i,
+		ulong j);
+
+/************************
+** BITFIELD OPERATIONS **
+*************************
+*/
+
+/*
+** PROTOTYPES
+*/
+void DoBitops(void);
+static ulong DoBitfieldIteration(farulong *bitarraybase,
+		farulong *bitoparraybase,
+		long bitoparraysize,
+		ulong *nbitops);
+static void ToggleBitRun(farulong *bitmap,
+		ulong bit_addr,
+		ulong nbits,
+		uint val);
+static void FlipBitRun(farulong *bitmap,
+		ulong bit_addr,
+		ulong nbits);
+
+/****************************
+** EMULATED FLOATING POINT **
+****************************/
+typedef struct
+{
+	u8 type;        /* Indicates, NORMAL, SUBNORMAL, etc. */
+	u8 sign;        /* Mantissa sign */
+	short exp;      /* Signed exponent...no bias */
+	u16 mantissa[INTERNAL_FPF_PRECISION];
+} InternalFPF;
+
+/*
+** PROTOTYPES
+*/
+void DoEmFloat(void);
+
+/*
+** EXTERNALS
+*/
+extern void SetupCPUEmFloatArrays(InternalFPF *abase,
+	InternalFPF *bbase, InternalFPF *cbase,
+	ulong arraysize);
+extern ulong DoEmFloatIteration(InternalFPF *abase,
+	InternalFPF *bbase, InternalFPF *cbase,
+	ulong arraysize, ulong loops);
+
+/*************************
+** FOURIER COEFFICIENTS **
+*************************/
+
+/*
+** PROTOTYPES
+*/
+void DoFourier(void);
+static ulong DoFPUTransIteration(fardouble *abase,
+		fardouble *bbase,
+		ulong arraysize);
+static double TrapezoidIntegrate(double x0,
+		double x1,
+		int nsteps,
+		double omegan,
+		int select);
+static double thefunction(double x,
+		double omegan,
+		int select);
+
+/*************************
+** ASSIGNMENT ALGORITHM **
+*************************/
+
+/*
+** DEFINES
+*/
+
+#define ASSIGNROWS 101L
+#define ASSIGNCOLS 101L
+
+/*
+** TYPEDEFS
+*/
+typedef struct {
+	union {
+		long *p;
+		long (*ap)[ASSIGNROWS][ASSIGNCOLS];
+	} ptrs;
+} longptr;
+
+/*
+** PROTOTYPES
+*/
+void DoAssign(void);
+static ulong DoAssignIteration(farlong *arraybase,
+		ulong numarrays);
+static void LoadAssignArrayWithRand(farlong *arraybase,
+		ulong numarrays);
+static void LoadAssign(farlong arraybase[][ASSIGNCOLS]);
+static void CopyToAssign(farlong arrayfrom[][ASSIGNCOLS],
+		long arrayto[][ASSIGNCOLS]);
+static void Assignment(farlong arraybase[][ASSIGNCOLS]);
+static void calc_minimum_costs(long tableau[][ASSIGNCOLS]);
+static int first_assignments(long tableau[][ASSIGNCOLS],
+		short assignedtableau[][ASSIGNCOLS]);
+static void second_assignments(long tableau[][ASSIGNCOLS],
+		short assignedtableau[][ASSIGNCOLS]);
+
+/********************
+** IDEA ENCRYPTION **
+********************/
+
+/*
+** DEFINES
+*/
+#define IDEAKEYSIZE 16
+#define IDEABLOCKSIZE 8
+#define ROUNDS 8
+#define KEYLEN (6*ROUNDS+4)
+
+/*
+** MACROS
+*/
+#define low16(x) ((x) & 0x0FFFF)
+#define MUL(x,y) (x=mul(low16(x),y))
+
+
+typedef u16 IDEAkey[KEYLEN];
+
+/*
+** PROTOTYPES
+*/
+void DoIDEA(void);
+static ulong DoIDEAIteration(faruchar *plain1,
+	faruchar *crypt1, faruchar *plain2,
+	ulong arraysize, ulong nloops,
+	IDEAkey Z, IDEAkey DK);
+static u16 mul(register u16 a, register u16 b);
+static u16 inv(u16 x);
+static void en_key_idea(u16 userkey[8], IDEAkey Z);
+static void de_key_idea(IDEAkey Z, IDEAkey DK);
+static void cipher_idea(u16 in[4], u16 out[4], IDEAkey Z);
+
+/************************
+** HUFFMAN COMPRESSION **
+************************/
+
+/*
+** DEFINES
+*/
+#define EXCLUDED 32000L          /* Big positive value */
+
+/*
+** TYPEDEFS
+*/
+typedef struct {
+	uchar c;                /* Byte value */
+	float freq;             /* Frequency */
+	int parent;             /* Parent node */
+	int left;               /* Left pointer = 0 */
+	int right;              /* Right pointer = 1 */
+} huff_node;
+
+/*
+** GLOBALS
+*/
+static huff_node *hufftree;             /* The huffman tree */
+static long plaintextlen;               /* Length of plaintext */
+
+/*
+** PROTOTYPES
+*/
+void DoHuffman();
+static void create_text_line(farchar *dt,long nchars);
+static void create_text_block(farchar *tb, ulong tblen,
+		ushort maxlinlen);
+static ulong DoHuffIteration(farchar *plaintext,
+	farchar *comparray, farchar *decomparray,
+	ulong arraysize, ulong nloops, huff_node *hufftree);
+static void SetCompBit(u8 *comparray, u32 bitoffset, char bitchar);
+static int GetCompBit(u8 *comparray, u32 bitoffset);
+
+/********************************
+** BACK PROPAGATION NEURAL NET **
+********************************/
+
+/*
+** DEFINES
+*/
+#define T 1                     /* TRUE */
+#define F 0                     /* FALSE */
+#define ERR -1
+#define MAXPATS 10              /* max number of patterns in data file */
+#define IN_X_SIZE 5             /* number of neurodes/row of input layer */
+#define IN_Y_SIZE 7             /* number of neurodes/col of input layer */
+#define IN_SIZE 35              /* equals IN_X_SIZE*IN_Y_SIZE */
+#define MID_SIZE 8              /* number of neurodes in middle layer */
+#define OUT_SIZE 8              /* number of neurodes in output layer */
+#define MARGIN 0.1              /* how near to 1,0 do we have to come to stop? */
+#define BETA 0.09               /* beta learning constant */
+#define ALPHA 0.09              /* momentum term constant */
+#define STOP 0.1                /* when worst_error less than STOP, training is done */
+
+/*
+** GLOBALS
+*/
+double  mid_wts[MID_SIZE][IN_SIZE];     /* middle layer weights */
+double  out_wts[OUT_SIZE][MID_SIZE];    /* output layer weights */
+double  mid_out[MID_SIZE];              /* middle layer output */
+double  out_out[OUT_SIZE];              /* output layer output */
+double  mid_error[MID_SIZE];            /* middle layer errors */
+double  out_error[OUT_SIZE];            /* output layer errors */
+double  mid_wt_change[MID_SIZE][IN_SIZE]; /* storage for last wt change */
+double  out_wt_change[OUT_SIZE][MID_SIZE]; /* storage for last wt change */
+double  in_pats[MAXPATS][IN_SIZE];      /* input patterns */
+double  out_pats[MAXPATS][OUT_SIZE];    /* desired output patterns */
+double  tot_out_error[MAXPATS];         /* measure of whether net is done */
+double  out_wt_cum_change[OUT_SIZE][MID_SIZE]; /* accumulated wt changes */
+double  mid_wt_cum_change[MID_SIZE][IN_SIZE];  /* accumulated wt changes */
+
+double  worst_error; /* worst error each pass through the data */
+double  average_error; /* average error each pass through the data */
+double  avg_out_error[MAXPATS]; /* average error each pattern */
+
+int iteration_count;    /* number of passes thru network so far */
+int numpats;            /* number of patterns in data file */
+int numpasses;          /* number of training passes through data file */
+int learned;            /* flag--if TRUE, network has learned all patterns */
+
+/*
+** The Neural Net test requires an input data file.
+** The name is specified here.
+*/
+char *inpath="NNET.DAT";
+
+/*
+** PROTOTYPES
+*/
+void DoNNET(void);
+static ulong DoNNetIteration(ulong nloops);
+static void do_mid_forward(int patt);
+static void do_out_forward();
+void display_output(int patt);
+static void do_forward_pass(int patt);
+static void do_out_error(int patt);
+static void worst_pass_error();
+static void do_mid_error();
+static void adjust_out_wts();
+static void adjust_mid_wts();
+static void do_back_pass(int patt);
+static void move_wt_changes();
+static int check_out_error();
+static void zero_changes();
+static void randomize_wts();
+static int read_data_file();
+/* static int initialize_net(); */
+
+/***********************
+**  LU DECOMPOSITION  **
+** (Linear Equations) **
+***********************/
+
+/*
+** DEFINES
+*/
+
+#define LUARRAYROWS 101L
+#define LUARRAYCOLS 101L
+
+/*
+** TYPEDEFS
+*/
+typedef struct
+{       union
+	{       fardouble *p;
+		fardouble (*ap)[][LUARRAYCOLS];
+	} ptrs;
+} LUdblptr;
+
+/*
+** GLOBALS
+*/
+fardouble *LUtempvv;
+
+/*
+** PROTOTYPES
+*/
+void DoLU(void);
+static void LUFreeMem(fardouble *a, fardouble *b,
+	fardouble *abase, fardouble *bbase);
+static ulong DoLUIteration(fardouble *a, fardouble *b,
+	fardouble *abase, fardouble *bbase,
+	ulong numarrays);
+static void build_problem( double a[][LUARRAYCOLS],
+	int n, double b[LUARRAYROWS]);
+static int ludcmp(double a[][LUARRAYCOLS],
+	int n, int indx[], int *d);
+static void lubksb(double a[][LUARRAYCOLS],
+	int n, int indx[LUARRAYROWS],
+	double b[LUARRAYROWS]);
+static int lusolve(double a[][LUARRAYCOLS],
+	int n, double b[LUARRAYROWS]);
+
+

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/nmglobal.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/nmglobal.h?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/nmglobal.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/nmglobal.h Sun Jan 22 03:50:58 2012
@@ -0,0 +1,507 @@
+/*
+** nmglobal.h
+** Global definitions for native mode benchmarks.
+**
+** BYTEmark (tm)
+** BYTE's Native Mode Benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Creation:
+** Revision: 3/95;10/95
+**  10/95 - Added memory array & alignment -- RG
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/* is this a 64 bit architecture? If so, this will define LONG64 */
+/* #include "pointer.h" */
+
+/*
+** SYSTEM DEFINES
+*/
+
+/* +++ MEMORY +++ */
+
+/*
+** You must define ONLY ONE of the following identifiers
+** to specify the mechanism for allocating memory:
+** MALLOCMEM
+** DOS16MEM
+** MACMEM
+*/
+
+/*
+** Define MALLOCMEM to use the standard malloc() call for
+** memory.  This is the default for most systems.
+*/
+#define MALLOCMEM
+
+/*
+** Define DOS16MEM if you're running in the old 16-bit segmented
+** model.  This enables some fruity memory management routines
+** required for that model.  NOT defining this assumes that
+** you're running in an environment that allows malloc() to
+** get > 64K chunks of memory.
+*/
+/* #define DOS16MEM */
+
+/* Define MACMEM to use the Mac's GetPtr call to allocate
+** memory (instead of malloc()).
+*/
+/* #define MACMEM */
+
+/* +++ TIMING +++ */
+/*
+** You must define ONLY ONE of the following identifiers to pick
+** the timing routine used.
+**  CLOCKWCPS
+**  CLOCKWCT
+**  MACTIMEMGR
+**  WIN31TIMER
+*/
+
+/*
+** Define CLOCKWCPS if you are using the clock() routine and the
+** constant used as the divisor to determine seconds is
+** CLOCKS_PER_SEC.  This is the default in most cases.
+*/
+#define CLOCKWCPS
+
+/*
+** Define CLOCKWCT if you are using the clock() routine and the
+** constant used as the divisor to determine seconds is CLK_TCK
+*/
+/* #define CLOCKWCT */
+
+/*
+** Define MACTIMEMGR to use the Mac Time manager routines.
+** You'll need to be running at least system 6.0.3 or
+** better...extended time manager is recommended (system 7 or
+** better).
+*/
+/* #define MACTIMEMGR */
+
+/*
+** Define WIN31TIMER to user the timing routines in TOOLHELP.DLL.
+** Gets accuracy down to the millisecond.
+*/
+/* #define WIN31TIMER */
+
+/* +++ MISCELLANEOUS +++ */
+
+/*
+** Define DOS16 if you'll be compiling under DOS in 16-bit
+** (non DOS-extended) mode.  This will enable proper definitions
+** for the far*** typedefs
+*/
+/* #define DOS16 */
+
+/*
+** Define MAC if you're compiling on a Macintosh.  This
+** does a number of things:
+**  includes unix.h
+**  Incorporates code to mimic the command line via either
+**      the console library (Symantec/Think) or the SIOUX
+**      library (Code Warrior).
+*/
+/* #define MAC */
+
+/*
+** Define LONG64 if your compiler emits 64-bit longs.
+** This is typically true of Alpha compilers on Unix
+** systems...though, who knows, this may change in the
+** future. I MOVED THIS DEFINTION INTO THE FILE pointer.h. DO NOT
+** DEFINE IT HERE. IT WILL AUTOMATICALLY BE DEFINED IF NECESSARY.
+** Uwe F. Mayer, Dec 15, 1996, Nov 15, 1997
+*/
+/* #define LONG64 */
+
+/*
+** Define MACCWPROF if you are profiling on the Mac using
+** Code Warrior.  This enables code that turns off the
+** profiler in an evern of an error exit.
+*/
+/* #define MACCWPROF */
+
+#ifdef MAC
+#include <unix.h>
+#endif
+
+/*
+** ERROR CODES
+*/
+#define ERROR_MEMORY    1
+#define ERROR_MEMARRAY_FULL 2
+#define ERROR_MEMARRAY_NFOUND 3
+#define ERROR_FILECREATE 10
+#define ERROR_FILEREAD 11
+#define ERROR_FILEWRITE 12
+#define ERROR_FILEOPEN 13
+#define ERROR_FILESEEK 14
+
+/*
+** MINIMUM_TICKS
+**
+** This sets the default number of minimum ticks.
+** It can, of course, be overridden by the input
+** command file.
+** This ultimately gets loaded into the variable
+** global_min_ticks, which specifies the minimum
+** number of ticks that must take place between
+** a StartStopwatch() and StopStopwatch() call.
+** The idea is to reduce error buildup.
+*/
+#define MINIMUM_TICKS 60
+
+/*
+** MINIMUM_SECONDS
+**
+** Minimum number of seconds to run each test.
+*/
+#define MINIMUM_SECONDS 5
+
+/*
+** MAXPOSLONG
+**
+** This is the maximum positive long.
+*/
+#include <limits.h>
+#define MAXPOSLONG LONG_MAX
+
+/*
+** OTHER DEFINES
+*/
+#ifndef MAC
+#define TRUE    1
+#define FALSE   0
+#endif
+
+/*
+** Memory array size.  Used in SYSSPEC for keeping track
+** of re-aligned memory.
+*/
+#define MEM_ARRAY_SIZE 20
+
+/*
+** TYPEDEFS
+*/
+#define ulong unsigned long
+#define uchar unsigned char
+#define uint unsigned int
+#define ushort unsigned short
+/*
+typedef unsigned char uchar;
+typedef unsigned int uint;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+*/
+/*
+** The 'farxxx' typedefs were added in deference to DOS, which
+** requires far pointers to handle some of the bigger
+** memory structures.  Other systems will simply
+** map 'farxxx' to 'xxx'
+*/
+#ifdef DOS16
+typedef void huge farvoid;
+typedef double huge fardouble;
+typedef long huge farlong;
+typedef unsigned long huge farulong;
+typedef char huge farchar;
+typedef unsigned char huge faruchar;
+
+#else
+
+typedef void farvoid;
+typedef double fardouble;
+typedef long farlong;
+typedef unsigned long farulong;
+typedef char farchar;
+typedef unsigned char faruchar;
+
+#endif
+
+/*
+** The following typedefs are used when element size
+** is critical.  You'll have to alter these for
+** your specifical platform/compiler.
+*/
+typedef unsigned char u8;       /* Unsigned 8-bits */
+typedef unsigned short u16;     /* Unsigned 16 bits */
+typedef unsigned int u32;       /* Unsigned 32 bits */
+typedef int int32;              /* Signed 32 bit integer */
+
+/*****************
+** NUMERIC SORT **
+*****************/
+/*
+** DEFINES
+*/
+
+/*
+** The following constant, NUMNUMARRAYS (no, it is not a
+** Peter Sellers joke) is the maximum number of arrays
+** that can be built by the numeric sorting benchmark
+** before it gives up.  This maximum is dependent on the
+** amount of memory in the system.
+*/
+/*#define NUMNUMARRAYS    1000*/
+#define NUMNUMARRAYS    10000
+
+/*
+** The following constant NUMARRAYSIZE determines the
+** default # of elements in each numeric array.  Ordinarily
+** this is something you shouldn't fool with, though as
+** with most of the constants here, it is adjustable.
+*/
+#define NUMARRAYSIZE    8111L
+
+
+/*
+** TYPEDEFS
+*/
+typedef struct {
+        int adjust;             /* Set adjust code */
+        ulong request_secs;     /* # of seconds requested */
+        double sortspersec;     /* # of sort iterations per sec */
+        ushort numarrays;       /* # of arrays */
+        ulong arraysize;        /* # of elements in array */
+} SortStruct;
+
+/****************
+** STRING SORT **
+*****************
+** Note: The string sort benchmark uses the same structure to
+** communicate parameters as does the numeric sort benchmark.
+** (i.e., SortStruct...see above.
+*/
+
+/*
+** DEFINES
+*/
+/*
+** The following constant STRINGARRAYSIZE determines
+** the default # of bytes allocated to each string array.
+** Though the actual size can be pre-set from the command
+** file, this constant should be left unchanged.
+*/
+#define STRINGARRAYSIZE 8111L
+
+/************************
+** BITFIELD OPERATIONS **
+*************************
+*/
+
+/*
+** DEFINES
+*/
+
+/*
+** Following field sets the size of the bitfield array (in longs).
+*/
+#define BITFARRAYSIZE (4096L * sizeof(long))
+
+/*
+** TYPEDEFS
+*/
+typedef struct {
+        int adjust;             /* Set adjust code */
+        ulong request_secs;     /* # of seconds requested */
+        double bitopspersec;    /* # of bitfield ops per sec */
+        ulong bitoparraysize;           /* Total # of bitfield ops */
+        ulong bitfieldarraysize;        /* Bit field array size */
+} BitOpStruct;
+
+/****************************
+** EMULATED FLOATING POINT **
+****************************/
+/*
+** DEFINES
+*/
+#define INTERNAL_FPF_PRECISION 4
+
+/*
+** The following constant is the maximum number of loops
+** of the emulated floating point test that the system
+** will allow before flagging an error.  This is not a
+** critical constant, and can be altered if your system is
+** a real barn-burner.
+*/
+/*#define CPUEMFLOATLOOPMAX 50000L*/
+#define CPUEMFLOATLOOPMAX 500000L
+
+/*
+** Set size of array
+*/
+#define EMFARRAYSIZE 3000L
+
+/*
+** TYPEDEFS
+*/
+typedef struct {
+        int adjust;             /* Set adjust code */
+        ulong request_secs;     /* # of seconds requested */
+        ulong arraysize;        /* Size of array */
+        ulong loops;            /* Loops per iterations */
+        double emflops;         /* Results */
+} EmFloatStruct;
+
+/*************************
+** FOURIER COEFFICIENTS **
+*************************/
+
+/*
+** TYPEDEFS
+*/
+typedef struct {
+        int adjust;             /* Set adjust code */
+        ulong request_secs;     /* # of requested seconds */
+        ulong arraysize;        /* Size of coeff. arrays */
+        double fflops;          /* Results */
+} FourierStruct;
+
+/*************************
+** ASSIGNMENT ALGORITHM **
+*************************/
+
+/*
+** TYPEDEFS
+*/
+typedef struct {
+        int adjust;             /* Set adjust code */
+        ulong request_secs;     /* Requested # of seconds */
+        ulong numarrays;        /* # of arrays */
+        double iterspersec;     /* Results */
+} AssignStruct;
+
+/********************
+** IDEA ENCRYPTION **
+********************/
+
+/*
+** DEFINES
+*/
+/* Following constant defines the max number of loops the
+** system will attempt. Keeps things from going off into the
+** weeds. */
+/*#define MAXIDEALOOPS 50000L*/
+#define MAXIDEALOOPS 500000L
+
+/*
+** Following constant sets the size of the arrays.
+** NOTE: For the IDEA algorithm to work properly, this
+**  number MUST be some multiple of 8.
+*/
+#define IDEAARRAYSIZE 4000L
+
+/*
+** TYPEDEFS
+*/
+typedef struct {
+        int adjust;             /* Set adjust code */
+        ulong request_secs;     /* Requested # of seconds */
+        ulong arraysize;        /* Size of array */
+        ulong loops;            /* # of times to convert */
+        double iterspersec;     /* Results */
+} IDEAStruct;
+
+
+/************************
+** HUFFMAN COMPRESSION **
+************************/
+
+/*
+** DEFINES
+*/
+/*
+** MAXHUFFLOOPS
+**
+** This constant specifies the maximum number of Huffman
+** compression loops the system will try for.  This keeps
+** the test from going off into the weeds.  This is not
+** a critical constant, and can be increased if your
+** system is a real barn-burner.
+*/
+/*#define MAXHUFFLOOPS 50000L*/
+#define MAXHUFFLOOPS 500000L
+
+/*
+** Following constant sets the size of the arrays to
+** be compressed/uncompressed.
+*/
+#define HUFFARRAYSIZE 5000L
+
+/*
+** TYPEDEFS
+*/
+
+typedef struct {
+        int adjust;             /* Set adjust code */
+        ulong request_secs;     /* Requested # of seconds */
+        ulong arraysize;        /* Size of array */
+        ulong loops;            /* # of times to compress/decompress */
+        double iterspersec;     /* Results */
+} HuffStruct;
+
+/********************************
+** BACK PROPAGATION NEURAL NET **
+********************************/
+
+/*
+**  MAXNNETLOOPS
+**
+** This constant sets the max number of loops through the neural
+** net that the system will attempt before giving up.  This
+** is not a critical constant.  You can alter it if your system
+** has sufficient horsepower.
+*/
+/*#define MAXNNETLOOPS  50000L*/
+#define MAXNNETLOOPS  500000L
+
+/*
+** TYPEDEFS
+*/
+typedef struct {
+        int adjust;             /* Set adjust code */
+        ulong request_secs;     /* Requested # of seconds */
+        ulong loops;            /* # of times to learn */
+        double iterspersec;     /* Results */
+} NNetStruct;
+
+/***********************
+**  LU DECOMPOSITION  **
+** (Linear Equations) **
+***********************/
+
+/*
+** MAXLUARRAYS
+**
+** This sets the upper limit on the number of arrays
+** that the benchmark will attempt to build before
+** flagging an error.  It is not a critical constant, and
+** may be increased if your system has the horsepower.
+*/
+/*#define MAXLUARRAYS 1000*/
+#define MAXLUARRAYS 10000
+
+/*
+** TYPEDEFS
+*/
+typedef struct {
+        int adjust;             /* Set adjust code */
+        ulong request_secs;     /* Requested # of seconds */
+        ulong numarrays;        /* # of arrays */
+        double iterspersec;     /* Results */
+} LUStruct;
+

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/sysspec.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/sysspec.c?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/sysspec.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/sysspec.c Sun Jan 22 03:50:58 2012
@@ -0,0 +1,884 @@
+
+/*
+** sysspec.c
+** System-specific routines.
+**
+** BYTEmark (tm)
+** BYTE's Native Mode Benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Creation:
+** Revision: 3/95;10/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/***********************************
+**    SYSTEM-SPECIFIC ROUTINES    **
+************************************
+**
+** These are the routines that provide functions that are
+** system-specific.  If the benchmarks are to be ported
+** to new hardware/new O.S., this is the first place to
+** start.
+*/
+#include "sysspec.h"
+
+#ifdef DOS16
+#include <io.h>
+#include <fcntl.h>
+#include <sys\stat.h>
+#endif
+/*********************************
+**  MEMORY MANAGEMENT ROUTINES  **
+*********************************/
+
+
+/****************************
+** AllocateMemory
+** This routine returns a void pointer to a memory
+** block.  The size of the memory block is given in bytes
+** as the first argument.  This routine also returns an
+** error code in the second argument.
+** 10/95 Update:
+**  Added an associative array for memory alignment reasons.
+**  mem_array[2][MEM_ARRAY_SIZE]
+**   mem_array[0][n] = Actual address (from malloc)
+**   mem_array[1][n] = Aligned address
+** Currently, mem_array[][] is only used if you use malloc;
+**  it is not used for the 16-bit DOS and MAC versions.
+*/
+farvoid *AllocateMemory(unsigned long nbytes,   /* # of bytes to alloc */
+		int *errorcode)                 /* Returned error code */
+{
+#ifdef DOS16MEM
+union REGS registers;
+unsigned short nparas;            /* # of paragraphs */
+
+/*
+** Set # of paragraphs to nbytes/16 +1.  The +1 is a
+** slop factor.
+*/
+nparas=(unsigned short)(nbytes/16L) + 1;
+
+/*
+** Set incoming registers.
+*/
+registers.h.ah=0x48;            /* Allocate memory */
+registers.x.bx=nparas;          /* # of paragraphs */
+
+
+intdos(&registers,&registers);  /* Call DOS */
+
+/*
+** See if things succeeded.
+*/
+if(registers.x.cflag)
+{       printf("error: %d Lgst: %d\n",registers.x.ax,registers.x.bx);
+	    *errorcode=ERROR_MEMORY;
+	return((farvoid *)NULL);
+}
+
+/*
+** Create a farvoid pointer to return.
+*/
+*errorcode=0;
+return((farvoid *)MK_FP(registers.x.ax,0));
+
+#endif
+
+#ifdef MACMEM
+/*
+** For MAC CodeWarrior, we'll use the MacOS NewPtr call
+*/
+farvoid *returnval;
+returnval=(farvoid *)NewPtr((Size)nbytes);
+if(returnval==(farvoid *)NULL)
+	*errorcode=ERROR_MEMORY;
+else
+	*errorcode=0;
+return(returnval);
+#endif
+
+#ifdef MALLOCMEM
+/*
+** Everyone else, its pretty straightforward, given
+** that you use a 32-bit compiler which treats size_t as
+** a 4-byte entity.
+*/
+farvoid *returnval;             /* Return value */
+ulong true_addr;		/* True address */
+ulong adj_addr;			/* Adjusted address */
+
+returnval=(farvoid *)malloc((size_t)(nbytes+2L*(long)global_align));
+if(returnval==(farvoid *)NULL)
+	*errorcode=ERROR_MEMORY;
+else
+	*errorcode=0;
+
+/*
+** Check for alignment
+*/
+adj_addr=true_addr=(ulong)returnval;
+if(global_align==0)
+{	
+	if(AddMemArray(true_addr, adj_addr))
+		*errorcode=ERROR_MEMARRAY_FULL;
+	return(returnval);
+}
+
+if(global_align==1)
+{	
+        if(true_addr%2==0) adj_addr++;
+}
+else
+{	
+	while(adj_addr%global_align!=0) ++adj_addr;
+	if(adj_addr%(global_align*2)==0) adj_addr+=global_align;
+}
+returnval=(void *)adj_addr;
+if(AddMemArray(true_addr,adj_addr))
+	*errorcode=ERROR_MEMARRAY_FULL;
+return(returnval);
+#endif
+
+}
+
+
+/****************************
+** FreeMemory
+** This is the reverse of AllocateMemory.  The memory
+** block passed in is freed.  Should an error occur,
+** that error is returned in errorcode.
+*/
+void FreeMemory(farvoid *mempointer,    /* Pointer to memory block */
+		int *errorcode)
+{
+#ifdef DOS16MEM
+/*
+** 16-bit DOS VERSION!!
+*/
+unsigned int segment;
+unsigned int offset;
+union REGS registers;
+struct SREGS sregisters;
+
+/*
+** First get the segment/offset of the farvoid pointer.
+*/
+segment=FP_SEG(mempointer);
+offset=FP_OFF(mempointer);
+
+/*
+** Align the segment properly.  For as long as offset > 16,
+** subtract 16 from offset and add 1 to segment.
+*/
+while(offset>=16)
+{       offset-=16;
+	segment++;
+}
+
+/*
+** Build the call to DOS
+*/
+registers.h.ah=0x49;            /* Free memory */
+sregisters.es=segment;
+
+intdosx(&registers,&registers,&sregisters);
+
+/*
+** Check for error
+*/
+if(registers.x.cflag)
+{       *errorcode=ERROR_MEMORY;
+	return;
+}
+
+*errorcode=0;
+return;
+#endif
+
+#ifdef MACMEM
+DisposPtr((Ptr)mempointer);
+*errorcode=0;
+return;
+#endif
+
+#ifdef MALLOCMEM
+ulong adj_addr, true_addr;
+
+/* Locate item in memory array */
+adj_addr=(ulong)mempointer;
+if(RemoveMemArray(adj_addr, &true_addr))
+{	*errorcode=ERROR_MEMARRAY_NFOUND;
+	return;
+}
+mempointer=(void *)true_addr;
+free(mempointer);
+*errorcode=0;
+return;
+#endif
+}
+
+/****************************
+** MoveMemory
+** Moves n bytes from a to b.  Handles overlap.
+** In most cases, this is just a memmove operation.
+** But, not in DOS....noooo....
+*/
+void MoveMemory( farvoid *destination,  /* Destination address */
+		farvoid *source,        /* Source address */
+		unsigned long nbytes)
+{
+
+/* +++16-bit DOS VERSION+++ */
+#ifdef DOS16MEM
+
+	FarDOSmemmove( destination, source, nbytes);
+
+#else
+
+memmove(destination, source, nbytes);
+
+#endif
+}
+
+#ifdef DOS16MEM
+
+/****************************
+** FarDOSmemmove
+** Performs the same function as memmove for DOS when
+** the arrays are defined with far pointers.
+*/
+void FarDOSmemmove(farvoid *destination,        /* Destination pointer */
+		farvoid *source,        /* Source pointer */
+		unsigned long nbytes)   /* # of bytes to move */
+{
+unsigned char huge *uchsource;  /* Temp source */
+unsigned char huge *uchdest;    /* Temp destination */
+unsigned long saddr;            /* Source "true" address */
+unsigned long daddr;            /* Destination "true" address */
+
+
+/*
+** Get unsigned char pointer equivalents
+*/
+uchsource=(unsigned char huge *)source;
+uchdest=(unsigned char huge *)destination;
+
+/*
+** Calculate true address of source and destination and
+** compare.
+*/
+saddr=(unsigned long)(FP_SEG(source)*16 + FP_OFF(source));
+daddr=(unsigned long)(FP_SEG(destination)*16 + FP_OFF(destination));
+
+if(saddr > daddr)
+{
+	/*
+	** Source is greater than destination.
+	** Use a series of standard move operations.
+	** We'll move 65535 bytes at a time.
+	*/
+	while(nbytes>=65535L)
+	{       _fmemmove((farvoid *)uchdest,
+			(farvoid *)uchsource,
+			(size_t) 65535);
+		uchsource+=65535;       /* Advance pointers */
+		uchdest+=65535;
+		nbytes-=65535;
+	}
+
+	/*
+	** Move remaining bytes
+	*/
+	if(nbytes!=0L)
+		_fmemmove((farvoid *)uchdest,
+			(farvoid *)uchsource,
+			(size_t)(nbytes & 0xFFFF));
+
+}
+else
+{
+	/*
+	** Destination is greater than source.
+	** Advance pointers to the end of their
+	** respective blocks.
+	*/
+	uchsource+=nbytes;
+	uchdest+=nbytes;
+
+	/*
+	** Again, move 65535 bytes at a time.  However,
+	** "back" the pointers up before doing the
+	** move.
+	*/
+	while(nbytes>=65535L)
+	{
+		uchsource-=65535;
+		uchdest-=65535;
+		_fmemmove((farvoid *)uchdest,
+			(farvoid *)uchsource,
+			(size_t) 65535);
+		nbytes-=65535;
+	}
+
+	/*
+	** Move remaining bytes.
+	*/
+	if(nbytes!=0L)
+	{       uchsource-=nbytes;
+		uchdest-=nbytes;
+		_fmemmove((farvoid *)uchdest,
+			(farvoid *)uchsource,
+			(size_t)(nbytes & 0xFFFF));
+	}
+}
+return;
+}
+#endif
+
+/***********************************
+** MEMORY ARRAY HANDLING ROUTINES **
+***********************************/
+/****************************
+** InitMemArray
+** Initialize the memory array.  This simply amounts to
+** setting mem_array_ents to zero, indicating that there
+** isn't anything in the memory array.
+*/
+void InitMemArray(void)
+{
+mem_array_ents=0;
+return;
+}
+
+/***************************
+** AddMemArray
+** Add a pair of items to the memory array.
+**  true_addr is the true address (mem_array[0][n])
+**  adj_addr is the adjusted address (mem_array[0][n])
+** Returns 0 if ok
+** -1 if not enough room
+*/
+int AddMemArray(ulong true_addr,
+		ulong adj_addr)
+{
+if(mem_array_ents>=MEM_ARRAY_SIZE)
+	return(-1);
+
+mem_array[0][mem_array_ents]=true_addr;
+mem_array[1][mem_array_ents]=adj_addr;
+mem_array_ents++;
+return(0);
+}
+
+/*************************
+** RemoveMemArray
+** Given an adjusted address value (mem_array[1][n]), locate
+** the entry and remove it from the mem_array.
+** Also returns the associated true address.
+** Returns 0 if ok
+** -1 if not found.
+*/
+int RemoveMemArray(ulong adj_addr,ulong *true_addr)
+{
+int i,j;
+
+/* Locate the item in the array. */
+for(i=0;i<mem_array_ents;i++)
+	if(mem_array[1][i]==adj_addr)
+	{       /* Found it..bubble stuff down */
+		*true_addr=mem_array[0][i];
+		j=i;
+		while(j+1<mem_array_ents)
+		{       mem_array[0][j]=mem_array[0][j+1];
+			mem_array[1][j]=mem_array[1][j+1];
+			j++;
+		}
+		mem_array_ents--;
+		return(0);      /* Return if found */
+	}
+
+/* If we made it here...something's wrong...show error */
+return(-1);
+}
+
+/**********************************
+**    FILE HANDLING ROUTINES     **
+**********************************/
+
+/****************************
+** CreateFile
+** This routine accepts a filename for an argument and
+** creates that file in the current directory (unless the
+** name contains a path that overrides the current directory).
+** Note that the routine does not OPEN the file.
+** If the file exists, it is truncated to length 0.
+*/
+void CreateFile(char *filename,
+		int *errorcode)
+{
+
+#ifdef DOS16
+/*
+** DOS VERSION!!
+*/
+int fhandle;            /* File handle used internally */
+
+fhandle=open(filename,O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
+
+if(fhandle==-1)
+	*errorcode=ERROR_FILECREATE;
+else
+	*errorcode=0;
+
+/*
+** Since all we're doing here is creating the file,
+** go ahead and close it.
+*/
+close(fhandle);
+
+return;
+#endif
+
+#ifdef LINUX
+FILE *fhandle;            /* File handle used internally */
+
+fhandle=fopen(filename,"w");
+
+if(fhandle==NULL)
+	*errorcode=ERROR_FILECREATE;
+else
+	*errorcode=0;
+
+/*
+** Since all we're doing here is creating the file,
+** go ahead and close it.
+*/
+fclose(fhandle);
+
+return;
+#endif
+}
+
+/****************************
+** bmOpenFile
+** Opens the file given by fname, returning its handle.
+** If an error occurs, returns its code in errorcode.
+** The file is opened in read-write exclusive mode.
+*/
+#ifdef DOS16
+/*
+** DOS VERSION!!
+*/
+
+int bmOpenFile(char *fname,       /* File name */
+	int *errorcode)         /* Error code returned */
+{
+
+int fhandle;            /* Returned file handle */
+
+fhandle=open(fname,O_BINARY | O_RDWR, S_IREAD | S_IWRITE);
+
+if(fhandle==-1)
+	*errorcode=ERROR_FILEOPEN;
+else
+	*errorcode=0;
+
+return(fhandle);
+}
+#endif
+
+
+#ifdef LINUX
+
+FILE *bmOpenFile(char *fname,       /* File name */
+	    int *errorcode)         /* Error code returned */
+{
+
+FILE *fhandle;            /* Returned file handle */
+
+fhandle=fopen(fname,"w+");
+
+if(fhandle==NULL)
+	*errorcode=ERROR_FILEOPEN;
+else
+	*errorcode=0;
+
+return(fhandle);
+}
+#endif
+
+
+/****************************
+** CloseFile
+** Closes the file identified by fhandle.
+** A more inocuous routine there never was.
+*/
+#ifdef DOS16
+/*
+** DOS VERSION!!!
+*/
+void CloseFile(int fhandle,             /* File handle */
+		int *errorcode)         /* Returned error code */
+{
+
+close(fhandle);
+*errorcode=0;
+return;
+}
+#endif
+#ifdef LINUX
+void CloseFile(FILE *fhandle,             /* File handle */
+		int *errorcode)         /* Returned error code */
+{
+fclose(fhandle);
+*errorcode=0;
+return;
+}
+#endif
+
+/****************************
+** readfile
+** Read bytes from an opened file.  This routine
+** is a combination seek-and-read.
+** Note that this routine expects the offset to be from
+** the beginning of the file.
+*/
+#ifdef DOS16
+/*
+** DOS VERSION!!
+*/
+
+void readfile(int fhandle,              /* File handle */
+	unsigned long offset,           /* Offset into file */
+	unsigned long nbytes,           /* # of bytes to read */
+	void *buffer,                   /* Buffer to read into */
+	int *errorcode)                 /* Returned error code */
+{
+
+long newoffset;                         /* New offset by lseek */
+int readcode;                           /* Return code from read */
+
+/*
+** Presume success.
+*/
+*errorcode=0;
+
+/*
+** Seek to the proper offset.
+*/
+newoffset=lseek(fhandle,(long)offset,SEEK_SET);
+if(newoffset==-1L)
+{       *errorcode=ERROR_FILESEEK;
+	return;
+}
+
+/*
+** Do the read.
+*/
+readcode=read(fhandle,buffer,(unsigned)(nbytes & 0xFFFF));
+if(readcode==-1)
+	*errorcode=ERROR_FILEREAD;
+
+return;
+}
+#endif
+#ifdef LINUX
+void readfile(FILE *fhandle,            /* File handle */
+	unsigned long offset,           /* Offset into file */
+	unsigned long nbytes,           /* # of bytes to read */
+	void *buffer,                   /* Buffer to read into */
+	int *errorcode)                 /* Returned error code */
+{
+
+long newoffset;                         /* New offset by fseek */
+size_t nelems;                          /* Expected return code from read */
+size_t readcode;                        /* Actual return code from read */
+
+/*
+** Presume success.
+*/
+*errorcode=0;
+
+/*
+** Seek to the proper offset.
+*/
+newoffset=fseek(fhandle,(long)offset,SEEK_SET);
+if(newoffset==-1L)
+{       *errorcode=ERROR_FILESEEK;
+	return;
+}
+
+/*
+** Do the read.
+*/
+nelems=(size_t)(nbytes & 0xFFFF);
+readcode=fread(buffer,(size_t)1,nelems,fhandle);
+if(readcode!=nelems)
+	*errorcode=ERROR_FILEREAD;
+
+return;
+}
+#endif
+
+/****************************
+** writefile
+** writes bytes to an opened file.  This routine is
+** a combination seek-and-write.
+** Note that this routine expects the offset to be from
+** the beinning of the file.
+*/
+#ifdef DOS16
+/*
+** DOS VERSION!!
+*/
+
+void writefile(int fhandle,             /* File handle */
+	unsigned long offset,           /* Offset into file */
+	unsigned long nbytes,           /* # of bytes to read */
+	void *buffer,                   /* Buffer to read into */
+	int *errorcode)                 /* Returned error code */
+{
+
+long newoffset;                         /* New offset by lseek */
+int writecode;                          /* Return code from write */
+
+/*
+** Presume success.
+*/
+*errorcode=0;
+
+/*
+** Seek to the proper offset.
+*/
+newoffset=lseek(fhandle,(long)offset,SEEK_SET);
+if(newoffset==-1L)
+{       *errorcode=ERROR_FILESEEK;
+	return;
+}
+
+/*
+** Do the write.
+*/
+writecode=write(fhandle,buffer,(unsigned)(nbytes & 0xFFFF));
+if(writecode==-1)
+	*errorcode=ERROR_FILEWRITE;
+
+return;
+}
+#endif
+
+#ifdef LINUX
+
+void writefile(FILE *fhandle,           /* File handle */
+	unsigned long offset,           /* Offset into file */
+	unsigned long nbytes,           /* # of bytes to read */
+	void *buffer,                   /* Buffer to read into */
+	int *errorcode)                 /* Returned error code */
+{
+
+long newoffset;                         /* New offset by lseek */
+size_t nelems;                          /* Expected return code from write */
+size_t writecode;                       /* Actual return code from write */
+
+/*
+** Presume success.
+*/
+*errorcode=0;
+
+/*
+** Seek to the proper offset.
+*/
+newoffset=fseek(fhandle,(long)offset,SEEK_SET);
+if(newoffset==-1L)
+{       *errorcode=ERROR_FILESEEK;
+	return;
+}
+
+/*
+** Do the write.
+*/
+nelems=(size_t)(nbytes & 0xFFFF);
+writecode=fwrite(buffer,(size_t)1,nelems,fhandle);
+if(writecode==nelems)
+	*errorcode=ERROR_FILEWRITE;
+
+return;
+}
+#endif
+
+
+/********************************
+**   ERROR HANDLING ROUTINES   **
+********************************/
+
+/****************************
+** ReportError
+** Report error message condition.
+*/
+void ReportError(char *errorcontext,    /* Error context string */
+		int errorcode)          /* Error code number */
+{
+
+/*
+** Display error context
+*/
+printf("ERROR CONDITION\nContext: %s\n",errorcontext);
+
+/*
+** Display code
+*/
+printf("Code: %d",errorcode);
+
+return;
+}
+
+/****************************
+** ErrorExit
+** Peforms an exit from an error condition.
+*/
+void ErrorExit()
+{
+
+/*
+** For profiling on the Mac with MetroWerks -- 11/17/94 RG
+** Have to do this to turn off profiler.
+*/
+#ifdef MACCWPROF
+#if __profile__
+ProfilerTerm();
+#endif
+#endif
+
+/*
+** FOR NOW...SIMPLE EXIT
+*/
+exit(1);
+}
+
+/*****************************
+**    STOPWATCH ROUTINES    **
+*****************************/
+
+/****************************
+** StartStopwatch
+** Starts a software stopwatch.  Returns the first value of
+** the stopwatch in ticks.
+*/
+unsigned long StartStopwatch()
+{
+#ifdef MACTIMEMGR
+/*
+** For Mac code warrior, use timer. In this case, what we return is really
+** a dummy value.
+*/
+InsTime((QElemPtr)&myTMTask);
+PrimeTime((QElemPtr)&myTMTask,-MacHSTdelay);
+return((unsigned long)1);
+#else
+#ifdef WIN31TIMER
+/*
+** Win 3.x timer returns a DWORD, which we coax into a long.
+*/
+_Call16(lpfn,"p",&win31tinfo);
+return((unsigned long)win31tinfo.dwmsSinceStart);
+#else
+return((unsigned long)clock());
+#endif
+#endif
+}
+
+/****************************
+** StopStopwatch
+** Stops the software stopwatch.  Expects as an input argument
+** the stopwatch start time.
+*/
+unsigned long StopStopwatch(unsigned long startticks)
+{
+	
+#ifdef MACTIMEMGR
+/*
+** For Mac code warrior...ignore startticks.  Return val. in microseconds
+*/
+RmvTime((QElemPtr)&myTMTask);
+return((unsigned long)(MacHSTdelay+myTMTask.tmCount-MacHSTohead));
+#else
+#ifdef WIN31TIMER
+_Call16(lpfn,"p",&win31tinfo);
+return((unsigned long)win31tinfo.dwmsSinceStart-startticks);
+#else
+return((unsigned long)clock()-startticks);
+#endif
+#endif
+}
+
+/****************************
+** TicksToSecs
+** Converts ticks to seconds.  Converts ticks to integer
+** seconds, discarding any fractional amount.
+*/
+unsigned long TicksToSecs(unsigned long tickamount)
+{
+#ifdef CLOCKWCT
+return((unsigned long)(tickamount/CLK_TCK));
+#endif
+
+#ifdef MACTIMEMGR
+/* +++ MAC time manager version (using timer in microseconds) +++ */
+return((unsigned long)(tickamount/1000000));
+#endif
+
+#ifdef CLOCKWCPS
+/* Everybody else */
+return((unsigned long)(tickamount/CLOCKS_PER_SEC));
+#endif
+
+#ifdef WIN31TIMER
+/* Each tick is 840 nanoseconds */
+return((unsigned long)(tickamount/1000L));
+#endif
+
+}
+
+/****************************
+** TicksToFracSecs
+** Converts ticks to fractional seconds.  In other words,
+** this returns the exact conversion from ticks to
+** seconds.
+*/
+double TicksToFracSecs(unsigned long tickamount)
+{
+#ifdef CLOCKWCT
+return((double)tickamount/(double)CLK_TCK);
+#endif
+
+#ifdef MACTIMEMGR
+/* +++ MAC time manager version +++ */
+return((double)tickamount/(double)1000000);
+#endif
+
+#ifdef CLOCKWCPS
+/* Everybody else */
+return((double)tickamount/(double)CLOCKS_PER_SEC);
+#endif
+
+#ifdef WIN31TIMER
+/* Using 840 nanosecond ticks */
+return((double)tickamount/(double)1000);
+#endif
+}
+

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/sysspec.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/sysspec.h?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/sysspec.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/sysspec.h Sun Jan 22 03:50:58 2012
@@ -0,0 +1,168 @@
+/*
+** sysspec.h
+** Header file for sysspec.c
+** BYTEmark (tm)
+** BYTE's Native Mode Benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Creation:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/*
+** Standard includes
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+
+#include "nmglobal.h"
+
+#if !defined(__APPLE__)
+#include <malloc.h>
+#endif
+
+
+/*
+** System-specific includes
+*/
+
+#ifdef DOS16MEM
+#include "dos.h"
+#endif
+
+/* #include "time.h"
+#include "io.h"
+#include "fcntl.h"
+#include "sys\stat.h" */
+/* Removed for MSVC++
+#include "alloc.h"
+*/
+
+/*
+** MAC Time Manager routines (from Code Warrior)
+*/
+#ifdef MACTIMEMGR
+#include <memory.h>
+#include <lowmem.h>
+#include <Types.h>
+#include <Timer.h>
+extern struct TMTask myTMTask;
+extern long MacHSTdelay,MacHSTohead;
+#endif
+
+/*
+** Windows 3.1 timer defines
+*/
+#ifdef WIN31TIMER
+#include <windows.h>
+#include <toolhelp.h>
+TIMERINFO win31tinfo;
+HANDLE hThlp;
+FARPROC lpfn;
+#endif
+
+/**************
+** EXTERNALS **
+**************/
+extern ulong mem_array[2][MEM_ARRAY_SIZE];
+extern int mem_array_ents;
+extern int global_align;
+
+/****************************
+**   FUNCTION PROTOTYPES   **
+****************************/
+
+farvoid *AllocateMemory(unsigned long nbytes,
+                int *errorcode);
+
+void FreeMemory(farvoid *mempointer,
+                int *errorcode);
+
+void MoveMemory( farvoid *destination,
+                farvoid *source,
+                unsigned long nbytes);
+
+#ifdef DOS16MEM
+void FarDOSmemmove(farvoid *destination,
+                farvoid *source,
+                unsigned long nbytes);
+#endif
+
+void InitMemArray(void);
+
+int AddMemArray(ulong true_addr, ulong adj_addr);
+
+int RemoveMemArray(ulong adj_addr,ulong *true_addr);
+
+void ReportError(char *context, int errorcode);
+
+void ErrorExit();
+
+void CreateFile(char *filename,
+                int *errorcode);
+
+#ifdef DOS16
+int bmOpenFile(char *fname,
+                int *errorcode);
+
+void CloseFile(int fhandle,
+                int *errorcode);
+
+void readfile(int fhandle,
+                unsigned long offset,
+                unsigned long nbytes,
+                void *buffer,
+                int *errorcode);
+
+void writefile(int fhandle,
+                unsigned long offset,
+                unsigned long nbytes,
+                void *buffer,
+                int *errorcode);
+#endif
+
+#ifdef LINUX
+FILE *bmOpenFile(char *fname,
+                int *errorcode);
+
+void CloseFile(FILE *fhandle,
+                int *errorcode);
+
+void readfile(FILE *fhandle,
+                unsigned long offset,
+                unsigned long nbytes,
+                void *buffer,
+                int *errorcode);
+
+void writefile(FILE *fhandle,
+                unsigned long offset,
+                unsigned long nbytes,
+                void *buffer,
+                int *errorcode);
+
+#endif
+
+unsigned long StartStopwatch();
+
+unsigned long StopStopwatch(unsigned long startticks);
+
+unsigned long TicksToSecs(unsigned long tickamount);
+
+double TicksToFracSecs(unsigned long tickamount);
+

Added: test-suite/trunk/MultiSource/Benchmarks/nbench/wordcat.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/nbench/wordcat.h?rev=148656&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/nbench/wordcat.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/nbench/wordcat.h Sun Jan 22 03:50:58 2012
@@ -0,0 +1,81 @@
+/*
+** wordcat.h
+** Word catalog
+** BYTEmark (tm)
+** BYTE's Native Mode Benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Creation:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code.  We cannot, however, guarantee that the programs
+** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/*
+** Word catalog
+*/
+#define WORDCATSIZE 50
+
+char *wordcatarray[WORDCATSIZE] =
+{	"Hello",
+	"He",
+	"Him",
+	"the",
+	"this",
+	"that",
+	"though",
+	"rough",
+	"cough",
+	"obviously",
+	"But",
+	"but",
+	"bye",
+	"begin",
+	"beginning",
+	"beginnings",
+	"of",
+	"our",
+	"ourselves",
+	"yourselves",
+	"to",
+	"together",
+	"togetherness",
+	"from",
+	"either",
+	"I",
+	"A",
+	"return",
+	"However",
+	"that",
+	"example",
+	"yet",
+	"quickly",
+	"all",
+	"if",
+	"were",
+	"includes",
+	"always",
+	"never",
+	"not",
+	"small",
+	"returns",
+	"set",
+	"basic",
+	"Entered",
+	"with",
+	"used",
+	"shown",
+	"you",
+	"know" };





More information about the llvm-commits mailing list