Science makes it known,
Engineering makes it work,
Art makes it beautiful.


Combining Fujitsu COBOL 3.0, PowerCOBOL 3.0, Silverfrost FTN95,
and Numerical Recipes:
The Art of Scientific Computing^{1}
(Statistics Analysis)  FORTRAN Files
(This page also contains information for combining Digital Mars
D, Free Pascal, and Lazarus
programs with
the same Silverfrost FTN95 Numerical Recipes subroutines)
It is highly recommended that a FORTRAN subroutine called either
directly or indirectly by a COBOL program does not perform any
user I/O.
It is highly recommended that a FORTRAN subroutine called either
directly or indirectly by a D command line program does not
perform any floating point output.
When calling FORTRAN intrinsic floating point functions, it is highly
recommended to pass a single argument and not an expression;
passing
an expression may be interpreted as passing a complex variable.
Statistics Analysis  FORTRAN Files
is designed, like
MATHPROC.FOR,
to provide computational support for a main program as a dynamic link
library (dll)
of numerical subprograms. So far, these subprograms have been called
by a COBOL GUI
program, D command console programs (which do not seem to be very
robust for some reason), D GUI programs, Free Pascal programs,
Lazarus (Delphi compatible) GUI program, and FORTRAN command
console programs.
Statistics Analysis  FORTRAN Files
is a collection of
subprograms and functions for analyzing Moments of a Distribution
(mean, deviation, etc.) and supporting
functions (sorting, finding minimum and maximum, point smoothing,
etc.). A single FORTRAN source file, STTSTCS.FOR, is
used. It contains over 30
subroutines and functions, many of which are from
Numerical Recipes;
several functions and subroutines are from other sources; some were
developed by me.
Only those used by the various programs documented on
this web site are detailed here.
Fourteen of these subprograms are called by a
COBOL Windows program,
a
D command line program,
a
D Windows program,
a
D .dll,
a
Free Pascal GUI program
(compiled in {$MODE DELPHI}), and/or a
Lazarus
program, demonstrating the
versatility of FORTRAN. The original Numerical Recipes
FORTRAN source is
unavailable for download from this page; it is available at
Older Numerical Recipes book editions:
ISORT
(used internally to sort the statistical data points Integer array);
Published as SORT in Numerical Recipes
(STTSTCS.FOR also contains an enhanced
version of Numerical Recipes'
SORT3, called RSORT3, for sorting REAL*4 arrays;
the original Numerical Recipes (1986) FORTRAN defaulted to
IMPLICIT ALL;
this implementation uses IMPLICIT NONE and separate programs
for INTEGER*2 and REAL*4 arrays;
both ISORT and RSORT3 use
Heap Sort; was necessary
to modify both; also for highly unsorted data, may be required to call
RSORT3 twice; these could be language/compiler/processor
issues as well as algorithm
issues);
.
IMDIAN1 (called first; calls ISORT and finds the median,
or middle value of an Integer array; half the values in the array are
less than the median, half are greater);
Published as
MDIAN1 in Numerical Recipes, modified for Integer arrays
(Numerical Recipes' MDIAN2,
included in STTSTCS.FOR, can be used for REAL*4 arrays).
SUMMATION (used internally to summarize the Integer array data
points, from
www.chem.ualberta.ca);
IMOMENT (calls SUMMATION and computes, as REALs, the
Integer array average,
standard deviation, etc.); Published as MOMENT in Numerical Recipes
(STTSTCS.FOR includes Numerical Recipes'
AVEVAR to compute the same information for REAL*4 arrays).
IMODE
(finds most common Integer array data point);
CRANK (calls ISORT and ranks the Integer array data points);
Published as CRANK in Numerical Recipes
NROOT
(used internally by GEOMEAN; used externally by
Free Pascal Windows program
proot
to compute the Nth root of X);
GEOMEAN (computes the Integer array's geometric mean using NROOT);
HARMONICMEAN (computes the Integer array's harmonic mean);
Subprograms called by both D .dll
dnrprocs.dll
(function nScale (...)) and Lazarus program
ST95DLPH
unit stunit1
(indirectly^{2} via Free Pascal .dll
nrlazrs.dll
procedure rMoment (...)):
D12R3MINMAX (finds the minimum and maximum values in a
REAL*4 array); user written
Subprograms called by Lazarus program ST95DLPH unit stunit1
(indirectly^{2} via Free Pascal rMoment (...)):
AVEVAR (computes average, average deviation, standard deviation,
variance of a REAL*4 array)
MDIAN2 (finds the median, or middle value of an unsorted
REAL*4 array)
COBOL (and D) called FORTRAN subroutines:
IMDIAN1, IMOMENT, and IMODE are called
directly by the COBOL main program
STF95COB,
D main program
dstat,
or the D main program
winstat.
Only the subroutine statement and variable
declarations are shown to prevent a possible intellectual property
violation, since the original FORTRAN source code
is published (with the exception of IMODE and NROOT).
ISORT (used internally), IMDIAN1, and IMOMENT are modified
Integer versions from Numerical Recipes: The Art of Scientific Computing;
IMODE
has been added and is not a part of
Numerical Recipes. Also added another
variable, IERR,
to the parameter list; IERR is a returned error code.^{3}

data points, stored as an Integer array

IDATA(i)

number of data points

N

average (mean)

AVE = (∑IDATA(i)) ∕ N

average deviation

ADEV = (∑  IDATA(i)  AVE  ) ∕ N

variance

VAR = ( ∑ ( IDATA(i)  AVE )^{2}) ∕ (N  1)

standard deviation
(σ  2nd moment of a distribution)

SDEV =
√ VAR

skewness (3rd moment of a distribution)

SKEW = ∑ ( IDATA(i)  AVE )^{3} ∕ ( N*SDEV^{3} )

kurtosis (4th moment of a distribution)

CURT = { ∑ ( ( IDATA(i)  AVE ) )^{4} } ∕ (N*VAR^{2})  3
(3 causes CURT=0 for normal distribution)

error code

IERR (initialized to zero; set to nonzero value if an error occurs)

The original Numerical Recipes (1986) FORTRAN
source code did not have elaborate
error checking. As an example, added the code snippet at right
to IMOMENT to check that the passed number of data points
exceeds zero. The calling program then checks IERR.EQ.0,
indicating success. As can be seen, most of the SUBROUTINEs
include IERR.


Two possible causes for an N<=0 error would be a bug or
corrupted data.
This error checking allows a program to exit gracefully instead of
crashing or hanging if an error occurs. Often times hackers
will
attempt to bounds violate or buffer overflow a program to get into
protected memory.
IERR.NE.0 does not always mean an error condition. For
example, in both
QUADROOT and CUBCROOT
IERR=105 indicates that one of the roots is imaginary and
requires additional processing.


Have since added another argument, NUMVALS  Number Unique Values, between
MODE_CNT and IERR to the parameter list. Link to download the
source is at the above left.

D called FORTRAN subprograms:
These three subroutines are called directly by the D Windows program
winstat.
CRANK is a modified Integer version from
Numerical Recipes: The Art of Scientific Computing,
added another variable, IERR,
to the parameter list; IERR is a returned error code;
CRANK produces an ascending ranking of the array elements.
(NROOT
is an implementation of an algorithm at
gmplib.org
and is called internally by GEOMEAN, externally by Pascal
Windows program
proot);
GEOMEAN and HARMONICMEAN are from the textbook
FORTRAN For Scientists & Engineers, 2nd Edition, 1995

Note that the function NROOT is declared as a variable. This
is required since sttstcs.for is compiled with
IMPLICIT NONE
(Project, Properties, Compiler Options, Language, set global
IMPLICIT NONE).
GEO =
^{N}
√
IDATA(1)*IDATA(2)*⋯*IDATA(N)


HARM = 1 ∕ { (1 ∕ IDATA(1)) +
(1 ∕ IDATA(2)) + ⋯ + (1 ∕ IDATA(N)) }

D .dll and Lazarus unit called FORTRAN subroutine:
D12R3MINMAX, shown at right, is a simple subroutine to find the
minimum and maximum values in an unsorted REAL array R.
It is called by
the D float function nScale (...) in module
dnrprocs.
nScale (...)
then uses RMIN and RMAX (adjusting RMIN or
RMAX to zero, if required) to produce a scaling factor for
plotting points.
nScale scales array R into an INTEGER*2 output points
array for
plotting (the reason for adjusting RMIN or RMAX to zero,
so the output points array extends to the axis).
D12R3MINMAX is also called indirectly by
Lazarus
program
ST95DLPH
unit
stunit1
using
nrlazrs
procedure rMoment (...).
REAL array R is dynamically dimensioned
(or dimensioned with variable bounds)
for N
elements. In nScale array R is statically
dimensioned for
1024 elements, in ST95DLPH 300 elements. This does not
produce any errors in DMD D 2.0,
Free Pascal,
or Lazarus.
N must be <= dimension size in calling
program. Do not use variable bounds dimensioning for matrices.

Another example of
IERR being used as a returned error code. 0 indicates success.

Lazarus units called FORTRAN subroutines via Object Pascal Library
nrlazrs:
MDIAN2 (...) finds the middle value of a Real Array X of
N elements; while it
does not sort the array, it is more complicated and may not be
as precise under certain conditions.
AVEVAR (...) computes the average, avg deviation, std
deviation, and variance of a Real Array RCDATA of N elements.
Both MDIAN2 (...) and AVEVAR (...), as well as
D12R3MINMAX, are called by Free Pascal Library
nrlazrs
(FORTRAN Numerical Recipes  Lazarus Interface) procedure
rMoment (...). rMoment (...),
called by Lazarus program ST95DLPH unit stunit1,
also calculates skewness and kurtosis.

AVEVAR (...) uses the same average, average deviation,
variance, and standard deviation equations as IMOMENT (...)
above.
AVEVAR (...) is also called by
nrlazrs
procedure rCoorelation (...) to compute the correlation
r of two distributions.

nrlazrs procedure indxSort (...), used to sort parallel
arrays by building an index table^{4}, calls
RSORT3 (...) and
SAVECOPY (...)^{5}
in sttstcs.dll. RSORT3 (...) calls
INDEXX (...) and SAVECOPY (...).
INDEXX (...) (not shown; p. 233 of Numerical Recipes 1986)
builds
the index table IORDER;
SAVECOPY (...) resequences
the array(s) according to the index table.
To call RSORT3 (...) with fewer than three arrays,
simply pass the same array multiple times; RSORT3 (...)
was modified to ignore
it when ND < 3 (code snippet at right).


When called from a nonFORTRAN program, parameters N and ND
must be Integer variables; when called from a FORTRAN program,
N and ND can be Integer constants.
SAVECOPY (...) was written by removing repetitive
code from the original SORT3 (...) and placing it
in its own
subroutine. The repetitive code in SORT3 (...)
was then replaced by a call to
SAVECOPY (...). SAVECOPY (...)
also contains a secondary entry point,
RAZERO (...).

indxSort (...) is called by
Lazarus program ST95DLPH unit stunit1 and by
the applications shown in
Lazarus Tab Sheets
and
Lazarus Body Tubes Subforms.
SAVECOPY (...) is also called by
wmath
(Simulated Annealing; IORDER is the configuration table)

Project Properties, Compiling, Linking, Import Library
Linking:
First, STTSTCS.OBJ must be linked as STTSTCS.DLL and STTSTCS.LIB.
Later on, STTSTCS.LIB must be linked by
the MicroSoft linker used by Fujitsu COBOL (creating STF95COB.EXE)
OR the Digital Mars
implib utility (file bup.zip)
(creating D executables).
Prior to linking, verify that Export all is enabled.
Link STTSTCS.DLL as a normal .dll using Silverfrost SLINK
Depending on the setting of Project Target (modifiable thru
Project, Set Target), this is done automatically
when compiling.


.LIB file (STTSTCS.LIB import library):
For Fujitsu COBOL main programs (STF95COB.EXE):
The MicroSoft linker used by Fujitsu COBOL requires a .lib file
(library file). The Silverfrost SLINK is compatible with
the MicroSoft linker.
After building the .dll, build the STTSTCS.LIB import library file:
click Project, Set Target
click the LIB radio button
click OK
click Build, Build
For Free Pascal and Lazarus Main Programs:
sttstcs.lib is not needed, so can skip this step

For program development systems compatible with the Microsoft Linker:

For Digital Mars D main programs:
Digital Mars compilers use a different object and library file format than
Microsoft's 32 bit tools (the .dll's produced are compatible).
Therefore, for Digital Mars D main programs need to use the
implib utility (file bup.zip)
to create the import library (STTSTCS.LIB) from the dynamic link library
(STTSTCS.DLL).
WARNING  Be Careful Not To Overwrite Your Silverfrost SLINK
Generated Import Library.
After creating STTSTCS.DLL with Silverfrost SLINK,
open a Command Prompt (or MSDOS box) and type
implib sttstcs.lib sttstcs.dll
It is NOT necessary to do this with the Silverfrost salflibc.lib.
Do this only with user written .dll's called directly by the D executable
and whose object and library file format is incompatible with Digital Mars.
Only need to recreate sttstcs.lib when SUBROUTINE declarations
changes (change in number or type of arguments, adding or removing subroutines
from the .dll, etc.)

For Digital Mars D compatible programs:
(Be sure to use the D2 32bit Command Prompt for compatibility
with the CheckMate Win32 configuration)

1. Press, William H., Brian P. Flannery, Saul A Teukolsky,
and William T. Vetterling (1986). Numerical Recipes: The Art of
Scientific Computing.
New York:Press Syndicate of the University of Cambridge.
A student version (in English) of
Numerical Recipes In 'C': The Art Of Scientific Computing, Second Edition, © 19881992 is
available from the
University of Trieste
at no cost.
2. Called via a standalone Free Pascal .dll. Possibly related to a
known Windows problem,
calling direct may produce an Access
Violation Exception. However, when called via a Free Pascal Library procedure,
no exceptions are produced. In either case, no
data corruption occurred, calculated results were correct. When
attempting to call a D .dll directly/indirectly from a Lazarus
application, a floating point error occurs. Suspect the error occurs in the D .dll
DllMain function, not the called D function;
possibly modifying the DllMain function
for C calls
may work. This was not necessary for Object Pascal calling D.
3. The variable IERR (or iErr) is used throughout the applications
on this web site. Each error condition / location is given a
unique nonzero value, even among unrelated applications (for example,
COBOL calling FORTRAN Numerical Recipes and
Lazarus/Pascal/Fortran Center of Pressure).
4. Indexing is different from Ranking. Multiple array
elements may have the same ranking; each array element has its own unique
index.
5. The indxSort (...) calls are conditional on passed
arguments. See source code.
