include ../Makefile.inc

# This makefile may be used (with gmake) to build a set of
# executables which will run the extensive test suite supplied
# with this package and described in the accompanying user
# manual. This suite aims to be as comprehensive as possible
# in testing the accuracy of the four routines for computing
# the Euclidean norm of a given input vector which were
# originally published as part of the BLAS Level 1 package
# (Algorithm 539: Basic Linear Algebraic Subprograms  for
# FORTRAN Usage. J. J. Dongarra and J. Du Croz and S. Hammarling
# and R. J. Hanson. ACM Transactions on Mathematical Software,
# 5(3), pp. 324--325, September, 1979).
#
# The executables test a range of algorithms/implementations
# for computing the Euclidean norm. It is assumed that IEEE
# arithmetic is available to the software via the Fortran
# intrinsic modules,  ieee_features, ieee_exceptions and
# ieee_arithmetic. The way in which Inf and NaN values are
# dealt with and the setting of IEEE arithmetic status flags
# are described in detail in the accompanying article.
#
# The following executables may be built using this 
# makefile:
#
# a) sdTestHybrid: new hybrid version using simple loop and,
#       if necessary, Kahan's algorithm. The routines are
#       supplied as a module.
# b) sdTestOnePassKahan: Kahan's algorithm (one pass version)
#       on its own.
# c) sdTestOrigKahan: version of a) above using the original
#       Kahan implementation which requires a second pass
#       through the data when scaling is necessary.
# d) sdTestOrigBLAS: original BLAS routines (Algorithm 539) 
#       with the two parameters cutlo and cuthi set to their
#       defined values for IEEE arithmetic.
# e) sdTestNewOrig: more readable/maintainable version of c)
# f) sdTestBlue: Blue's algorithm as described in A Portable 
#       Fortran Program to Find the Euclidean Norm of a Vector 
#       by James L. Blue, ACM Transactions on Mathematical
#       Software, 4(1), pp. 15--23, March, 1978.
# g) sdTestLa: version available (June 2015) via netlib and 
#       distributed with Lapack software (v3.5.0, November, 2013).
# h) sdTestNorm2: version using the new Fortran (2008+) intrinsic
#       function, norm2.
# i) sdTestNewOrigCsum: version of e) above with compensated 
#       summation implemented. 
# j) sdTestBlueCsum: version of f) above with compensated 
#       summation implemented. 
# k) sdTestLaCsum: version of g) above with compensated 
#       summation implemented. 
# l) sdTestLaCsSc: version of g) above with compensated 
#       summation and intermediate scaling factors forced to be
#       powers of two to try and reduce rounding errors.
# m) sdTestNewBlue: version of Blue's algorithm which only uses
#       two accumulators rather than three.
# n) sdTestCInterface: version that calls the C interface
#       routines for the hybrid package.
# o) sdCheckTrue: version that uses extended precision to check
#       the test suite to ensure that the `true' values supplied
#       by the suite are correct.
# p) sdTestHybridSubs: the new hybrid version using a
#       simple loop and, if necessary, Kahan's algorithm. The
#       subroutines are supplied as stand-alone routines in a
#       single file nrm2HybridSubs.f90 within the Hybrid
#       directory. This run should generate exactly the same
#       results as sdTestHybrid.
# q) sdTestBLASLib: test an existing platform dependent
#       library; for example, a hardware dependent of the Level-1
#       BLAS specially tuned for a particular processor.
#
#       This is a template and may require editing to successfully
#       link to the library.
# r) sdTestBLASSubs: test an existing implementation of the
#       BLAS Level 1 nrm2 routines supplied as either a standalone
#       set of source routines (not wrapped in a module) in one
#       or more files or as one or more pre-compiled (.o) files.
#
#       This is a template and may require editing to successfully
#       link to the library.
#
# For details of how to build p) and q) see comments later
# in this makefile

executables = sdTestLa sdTestHybrid sdTestOrigKahan sdTestOnePassKahan \
              sdTestLaCsSc\
              sdTestLaCsum sdTestNorm2 sdTestNewOrig sdTestBlue \
              sdTestNewBlue \
              sdTestNewOrigCsum sdTestBlueCsum \
              sdTestCInterface sdTestOrigBLAS sdTestHybridSubs \
              #sdCheckTrue

all: $(executables)

# Use vpath to pick up source files and include files
# from other directories
vpath %.f90 ../Hybrid ../OtherVersions ../Benchmarks ../MpPackage ../Faithful
vpath %.inc ../Hybrid ../OtherVersions
vpath %.f ../OtherVersions
vpath %.c ../Faithful
SrcPath = ../Hybrid
OtherPath = ../OtherVersions

OrigBLAS = BlasOrig.o
NewOrigBLAS = newOrig.o
NewOrigBLASCsum = newOrigCsum.o
LaSubs = lapack.o
LaSubsCsum = lapackCsum.o
LaSubsCsSc = lapackCsSc.o
Norm2Subs = norm2Intrinsic.o
BlueSubs = Blue.o
NewBlueSubs = NewBlue.o
BlueSubsCsum = BlueCsum.o
OrigKahanSub = origKahan.o
OnePassKahanSub = onePassKahan.o
FaithfulNormSub = c_faithfulNorm.o
CFaithfulNorm = faithfulnormnooverflow.o

TESTOBJS = set_precision.o sdTestMod.o checkTests.o 

SRCMOD = nrm2HybridMod.o
SRCSUBS = nrm2HybridSubs.o

HYBRIDINCS = realHybrid.inc complexHybrid.inc
ORIGKAHANINCS = realKahan.inc complexKahan.inc setStatusFlags.inc
ONEPASSKAHANINCS = onePassRealKahan.inc onePassComplexKahan.inc
BLUEINCS = blueReal.inc blueComplex.inc
NEWBLUEINCS = newBlueReal.inc newBlueComplex.inc
BLUECSUMINCS = blueRealCsum.inc blueComplexCsum.inc
NEWORIGINCS = newOrigReal.inc newOrigComplex.inc
NEWORIGCSUMINCS = newOrigRealCsum.inc newOrigComplexCsum.inc

sdTestCInterface: set_precision.o $(SRCMOD)\
                   CInterfaceNrm2.o sdTestCInterface.o
	$(F95) $(F95LINKFLAGS) -o $@ set_precision.o $(SRCMOD) CInterfaceNrm2.o sdTestCInterface.o

sdCheckTrue: sdCheckTrue.o checkTests.o set_precision.o \
             oracle.o randMod.o checkTrueMod.o mpfun90.o mpmod90.o
	$(F95) $(F95LINKFLAGS) -o $@ $^

sdTestHybrid: $(TESTOBJS) sdTest.f90 $(SRCMOD) testSubsHybrid.f90
	$(F95) $(F95FLAGS) -c -o testSubsHybrid.o testSubsHybrid.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(SRCMOD) testSubsHybrid.o 

sdTestHybridSubs: $(TESTOBJS) sdTestBLAS.o nrm2HybridSubs.o
	$(F95) $(F95LINKFLAGS) -o $@ $^

sdTestOrigKahan: $(TESTOBJS) sdTest.f90 $(OrigKahanSub) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(OrigKahanSub) testSubsGen.o 

sdTestOnePassKahan: $(TESTOBJS) sdTest.f90 $(OnePassKahanSub) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(OnePassKahanSub) testSubsGen.o 

testScaleKahan: set_precision.o sdTestScaling.o oracle.o \
                randMod.o $(SRCMOD) mpfun90.o mpmod90.o

sdTestLa: $(TESTOBJS) sdTest.f90 $(LaSubs) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(LaSubs) testSubsGen.o 
	$(REMOVE) $(LaSubs)

sdTestLaCsum: $(TESTOBJS) sdTest.f90 $(LaSubsCsum) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(LaSubsCsum) testSubsGen.o 
	$(REMOVE) $(LaSubsCsum)

sdTestLaCsSc: $(TESTOBJS) sdTest.f90 $(LaSubsCsSc) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(LaSubsCsSc) testSubsGen.o 
	$(REMOVE) $(LaSubsCsum)

sdTestNorm2: $(TESTOBJS) sdTest.f90 $(Norm2Subs) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(Norm2Subs) testSubsGen.o 
	$(REMOVE) $(Norm2Subs)

sdTestOrigBLAS: $(TESTOBJS) sdTest.f90 $(OrigBLAS) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(OrigBLAS) testSubsGen.o 

  
sdTestNewOrig: $(TESTOBJS) sdTest.f90 $(NewOrigBLAS) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(NewOrigBLAS) testSubsGen.o 
	$(REMOVE) $(NewOrigBLAS)

sdTestNewOrigCsum: $(TESTOBJS) sdTest.f90 $(NewOrigBLASCsum) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(NewOrigBLASCsum) testSubsGen.o 
	$(REMOVE) $(NewOrigBLASCsum)

sdTestFaithful: $(TESTOBJS) sdTest.f90 $(FaithfulNormSub) $(CFaithfulNorm) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(CFaithfulNorm) $(FaithfulNormSub) testSubsGen.o 
	$(REMOVE) $(FaithfulNormSub)

sdTestBlue: $(TESTOBJS) sdTest.f90 $(BlueSubs) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(BlueSubs) testSubsGen.o 
	$(REMOVE) $(BlueSubs)

sdTestNewBlue: $(TESTOBJS) sdTest.f90 $(NewBlueSubs) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(NewBlueSubs) testSubsGen.o 
	$(REMOVE) $(NewBlueSubs)

sdTestBlueCsum: $(TESTOBJS) sdTest.f90 $(BlueSubsCsum) testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o testSubsGen.o testSubsGen.f90
	$(F95) $(F95FLAGS) -c -o sdTest.o sdTest.f90
	$(F95) $(F95LINKFLAGS) -o $@ $(TESTOBJS) sdTest.o $(BlueSubsCsum) testSubsGen.o 
	$(REMOVE) $(BlueSubsCsum)

# The executables sdTestBLASLib and sdTestBLASSubs will
# depend on the users set-up and are not portable as far as the
# Makefile is concerned. These are, therefore, not included in the
# executables that will be built using the simple command `make'.
# 
# To build sdTestBLASLib and sdTestBLASSubs the user needs to
# ensure that the correct path is set to an available, system
# dependent library / .o file containing the BLAS subroutines and
# give the required executable name explicitly when invoking make
# that is:
#
#       make sdTestBLASLib
#       make sdTestBLASSubs
#
# In the case of sdTestBLASSubs; if the source codes are
# provided then the name of the .o files should be added to
# the dependency list and details provided on how to build
# this file from the source code (via vpath or in a separate
# component build).

sdTestBLASLib: $(TESTOBJS) sdTestBLAS.o 
	$(F95) $(F95LINKFLAGS) -o $@ $^ $(LIBS)

# If the source file(s) are available then a dependency line
# of the form
# BLASSubs.o: BLASSubs.f90 # plus any dependent files
# should be provided.
#
# If only .o files are available this line is not necessary.

sdTestBLASSubs: $(TESTOBJS) sdTestBLAS.o BLASSubs.o 
	$(F95) $(F95LINKFLAGS) -o $@ $^ $(LIBS)

$(LaSubs): set_precision.o

$(LaSubsCsum): set_precision.o

$(Norm2Subs): set_precision.o

$(NewOrigBLAS): $(subst .o,.f90,$(NewOrigBLAS)) set_precision.o $(NEWORIGINCS)
	$(F95) $(F95FLAGS) -I $(OtherPath) -c $<

$(NewOrigBLASCsum): $(subst .o,.f90,$(NewOrigBLASCsum)) set_precision.o $(NEWORIGCSUMINCS)
	$(F95) $(F95FLAGS) -I $(OtherPath) -c $<

$(NewBlueSubs): $(subst .o,.f90,$(NewBlueSubs)) set_precision.o $(NEWBLUEINCS)
	$(F95) $(F95FLAGS) -I $(OtherPath) -c $<

$(BlueSubs): $(subst .o,.f90,$(BlueSubs)) set_precision.o $(BLUEINCS)
	$(F95) $(F95FLAGS) -I $(OtherPath) -c $<

$(BlueSubsCsum): $(subst .o,.f90,$(BlueSubsCsum)) set_precision.o $(BLUECSUMINCS)
	$(F95) $(F95FLAGS) -I $(OtherPath) -c $<

$(OrigKahanSub): $(subst .o,.f90,$(OrigKahanSub)) set_precision.o $(ORIGKAHANINCS)
	$(F95) $(F95FLAGS) -I $(SrcPath) -c $<

$(OnePassKahanSub): $(subst .o,.f90,$(OnePassKahanSub)) set_precision.o $(ONEPASSKAHANINCS)
	$(F95) $(F95FLAGS) -I $(SrcPath) -c $<

$(FaithfulNormSub): $(subst .o,.f90,$(FaithfulNormSub)) set_precision.o
	$(F95) $(F95FLAGS) -I $(SrcPath) -c $<

$(CFaithfulNorm): $(subst .o,.c,$(FaithfulNorm))
#$(CC) $(CCFLAGS) -I $(SrcPath) -c $<

$(SRCMOD): $(subst .o,.f90,$(SRCMOD)) set_precision.o $(HYBRIDINCS) \
             $(KAHANINCS) 
	$(F95) $(F95FLAGS) -I $(SrcPath) -c $<

$(SRCSUBS): $(subst .o,.f90,$(SRCSUBS)) set_precision.o $(HYBRIDINCS) \
             $(KAHANINCS) 
	$(F95) $(F95FLAGS) -I $(SrcPath) -c $<

set_precision.o:

checkTests.o: set_precision.o

sdTestCInterface.o: set_precision.o $(SRCMOD) CInterfaceNrm2.o 

sdTestHybrid.o: set_precision.o $(SRCMOD) sdTestMod.o 

sdTestOrigKahan.o: set_precision.o $(SRCMOD) sdTestMod.o 

sdTestMod.o: set_precision.o $(SRCMOD) sdTestMod.inc \
             indivTest.inc checkTests.o 

sdCheckTrue.o: checkTrueMod.o checkTests.o mpfun90.o mpmod90.o

sdTestScaling.o: set_precision.o oracle.o

checkTrueMod.o: set_precision.o oracle.o randMod.o checkTests.o \
                sdTestMod.inc indivTrueTest.inc

oracle.o: set_precision.o randMod.o mpfun90.o mpmod90.o

randMod.o: set_precision.o

$(FaithfulNormSub): $(CFaithfulNorm) set_precision.o

testSubsHybrid: $(SRCMOD)

testSubsKahan: $(SRCMOD)

testScaleKahan: $(SRCMOD) 

.PHONY: clean
clean: 
	# remove all files generated by the compiler
	# these are compiler dependent
	$(REMOVE) *.o *.d *.g90 *.mod 
	# remove all executables
	$(REMOVE) $(executables)
