makefile 0100755 0002055 0007177 00000014077 06653153213 0013611 0 ustar 00cleve compmath 0000040 0000006 drivers :
cd A2 ; make all_drivers
cd BKL ; make all_drivers
cd BPG ; make all_drivers
cd Chv ; make all_drivers
cd ChvList ; make all_drivers
cd ChvManager ; make all_drivers
cd Coords ; make all_drivers
cd DSTree ; make all_drivers
cd DV ; make all_drivers
cd DenseMtx ; make all_drivers
cd Drand ; make all_drivers
cd EGraph ; make all_drivers
cd ETree ; make all_drivers
cd FrontMtx ; make all_drivers
cd GPart ; make all_drivers
cd Graph ; make all_drivers
cd I2Ohash ; make all_drivers
cd IIheap ; make all_drivers
cd IV ; make all_drivers
cd IVL ; make all_drivers
cd Ideq ; make all_drivers
cd InpMtx ; make all_drivers
cd Lock ; make all_drivers
cd MPI ; make all_drivers
cd MSMD ; make all_drivers
cd MT ; make all_drivers
cd Network ; make all_drivers
cd PatchAndGoInfo ; make all_drivers
cd Pencil ; make all_drivers
cd Perm ; make all_drivers
cd SemiImplMtx ; make all_drivers
cd SolveMap ; make all_drivers
cd SubMtx ; make all_drivers
cd SubMtxList ; make all_drivers
cd SubMtxManager ; make all_drivers
cd SymbFac ; make all_drivers
cd Tree ; make all_drivers
cd Utilities ; make all_drivers
cd ZV ; make all_drivers
cd misc ; make all_drivers
clean :
cd A2 ; make clean
cd BKL ; make clean
cd BPG ; make clean
cd Chv ; make clean
cd ChvList ; make clean
cd ChvManager ; make clean
cd Coords ; make clean
cd DSTree ; make clean
cd DV ; make clean
cd DenseMtx ; make clean
cd Drand ; make clean
cd EGraph ; make clean
cd ETree ; make clean
cd FrontMtx ; make clean
cd GPart ; make clean
cd Graph ; make clean
cd I2Ohash ; make clean
cd IIheap ; make clean
cd IV ; make clean
cd IVL ; make clean
cd Ideq ; make clean
cd InpMtx ; make clean
cd Lock ; make clean
cd MPI ; make clean
cd MSMD ; make clean
cd MT ; make clean
cd Network ; make clean
cd PatchAndGoInfo ; make clean
cd Pencil ; make clean
cd Perm ; make clean
cd SemiImplMtx ; make clean
cd SolveMap ; make clean
cd SubMtx ; make clean
cd SubMtxList ; make clean
cd SubMtxManager ; make clean
cd SymbFac ; make clean
cd Tree ; make clean
cd Utilities ; make clean
cd ZV ; make clean
cd misc ; make clean
cd documentation ; make clean
- rm -f *.o *.a
lib :
cd A2 ; make lib
cd BKL ; make lib
cd BPG ; make lib
cd Chv ; make lib
cd ChvList ; make lib
cd ChvManager ; make lib
cd Coords ; make lib
cd DSTree ; make lib
cd DV ; make lib
cd DenseMtx ; make lib
cd Drand ; make lib
cd EGraph ; make lib
cd ETree ; make lib
cd FrontMtx ; make lib
cd GPart ; make lib
cd Graph ; make lib
cd I2Ohash ; make lib
cd IIheap ; make lib
cd IV ; make lib
cd IVL ; make lib
cd Ideq ; make lib
cd InpMtx ; make lib
cd Lock ; make lib
cd MSMD ; make lib
cd Network ; make lib
cd PatchAndGoInfo ; make lib
cd Pencil ; make lib
cd Perm ; make lib
cd SemiImplMtx ; make lib
cd SolveMap ; make lib
cd SubMtx ; make lib
cd SubMtxList ; make lib
cd SubMtxManager ; make lib
cd SymbFac ; make lib
cd Tree ; make lib
cd Utilities ; make lib
cd ZV ; make lib
cd misc ; make lib
#cd MPI ; make lib
#cd MT ; make lib
global :
cd A2/src ; make -f makeGlobalLib
cd BKL/src ; make -f makeGlobalLib
cd BPG/src ; make -f makeGlobalLib
cd Chv/src ; make -f makeGlobalLib
cd ChvList/src ; make -f makeGlobalLib
cd ChvManager/src ; make -f makeGlobalLib
cd Coords/src ; make -f makeGlobalLib
cd DSTree/src ; make -f makeGlobalLib
cd DV/src ; make -f makeGlobalLib
cd DenseMtx/src ; make -f makeGlobalLib
cd Drand/src ; make -f makeGlobalLib
cd EGraph/src ; make -f makeGlobalLib
cd ETree/src ; make -f makeGlobalLib
cd FrontMtx/src ; make -f makeGlobalLib
cd GPart/src ; make -f makeGlobalLib
cd Graph/src ; make -f makeGlobalLib
cd I2Ohash/src ; make -f makeGlobalLib
cd IIheap/src ; make -f makeGlobalLib
cd IV/src ; make -f makeGlobalLib
cd IVL/src ; make -f makeGlobalLib
cd Ideq/src ; make -f makeGlobalLib
cd InpMtx/src ; make -f makeGlobalLib
cd Lock/src ; make -f makeGlobalLib
cd MSMD/src ; make -f makeGlobalLib
cd Network/src ; make -f makeGlobalLib
cd PatchAndGoInfo/src ; make -f makeGlobalLib
cd Pencil/src ; make -f makeGlobalLib
cd Perm/src ; make -f makeGlobalLib
cd SemiImplMtx/src ; make -f makeGlobalLib
cd SolveMap/src ; make -f makeGlobalLib
cd SubMtx/src ; make -f makeGlobalLib
cd SubMtxList/src ; make -f makeGlobalLib
cd SubMtxManager/src ; make -f makeGlobalLib
cd SymbFac/src ; make -f makeGlobalLib
cd Tree/src ; make -f makeGlobalLib
cd Utilities/src ; make -f makeGlobalLib
cd ZV/src ; make -f makeGlobalLib
cd misc/src ; make -f makeGlobalLib
#cd MPI/src ; make -f makeGlobalLib
#cd MT/src ; make -f makeGlobalLib
makeLib 0100755 0002055 0007177 00000005022 06635771116 0013376 0 ustar 00cleve compmath 0000040 0000006 #! /usr/local/gnu/bin/perl
#
#-----------------------------------------------------------------------
#
# purpose : to help create the spooles.a library from scratch
#
# the spooles.a library is a global library and contains all spooles
# methods. (this is in contrast to local libraries that contain
# methods for only one object, e.g., A2/src/A2.a)
#
# the spooles.a library is usually created once, by executing
# "make global" in the spooles directory, which compiles each
# and every source file in all the object/src directories.
# (not quite true, just every src file that is found in
# object/src/makefile, which is considered as gospel.)
# the "make global" command goes into each object's src directory,
# calls this perl script to create a makefile that will compile
# each src file and load into the spooles.a library, and then
# executes that makefile and removes it.
#
# for those systems that do not have perl installed, we have a
# makeGlobalLib makefile in each object's src directory.
# typing "make Global" in the spooles directory will use
# this makefile. unfortunately, each object's /src/makefile
# and /src/makeGlobalLib are separate and must be kept up to date
# manually. (i.e., add another src file to /src/makefile and you
# must add the same to /src/makeGlobalLib).
#
# this is my second perl script, so don't laugh,
# just send me comments and suggestions.
#
# created -- 98dec16, cca
#
#-----------------------------------------------------------------------
#
# open the makefile to extract out the src file names
#
$makefile = "makefile" ;
open( MAKEFILE, $makefile ) or die "Cannot open $makefile" ;
#
# read in each line, look for $(OBJ).a(srcname.o)
# put srcname into the @srcnames array
#
while ( $line = ) {
chop($line) ;
if ( $line =~ /OBJ =/ ) {
($first, $objname) = split /OBJ = /, $line
}
if ( $line =~ /\$\(OBJ\)\.a\(/ ) {
($first, $second) = split /\$\(OBJ\)\.a\(/, $line ;
($srcname, $remainder) = split /\.o\)/, $second ;
$srcname = $srcname . ".c" ;
push @srcnames, $srcname
}
}
#
# now start printing the makefile to stdout
#
print "\ninclude ../../Make.inc" ;
print "\n" ;
print "\nOBJ = $objname" ;
print "\n\nSRC = " ;
foreach $src ( @srcnames ) {
$srcname = " \\\n " . $src ;
print $srcname ;
}
print "\n\nOBJ_FILES = \$\{SRC:.c=.o\}" ;
print "\n\n" ;
print <<'EOF' ;
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
EOF
bin/perl
#
#-----------------------------------------------------------------------
#
# purpose : to help create the spooles.a library from scratch
#
# the spooles.a library is a global library and contains all spooles
# methods. (this is in contrast to local libraries that contain
# methods for only one object, e.g., A2/src/A2.a)
#
# the spooles.a library is usually created once, by executing
# "make global" in the spooles directory, which compiles each
# and every source file in all tupdLib 0100755 0002055 0007177 00000010545 06635771010 0013250 0 ustar 00cleve compmath 0000040 0000006 #! /usr/local/gnu/bin/perl
#
#-----------------------------------------------------------------------
#
# purpose : to provide incremental updates to the spooles.a library
#
# the spooles.a library is a global library and contains all spooles
# methods. (this is in contrast to local libraries that contain
# methods for only one object, e.g., A2/src/A2.a)
#
# the spooles.a library is usually created once, by executing
# "make global" in the spooles directory, which compiles each
# and every source file in all the object/src directories.
# on many systems this can take quite a long time.
#
# there are times when we make a change to one method and want to
# update the spooles.a library. calling "make global" in the
# spooles directory would compile all the source once again.
#
# what is needed is a way to compile only those src files that
# need to be compiled. well, we haven't quite achieved this.
# what this perl script helps do is to create a makefile (written
# to stdout) that will compile all src files that are more recent
# than spooles.a library. this perl script is called when
# executing "make updateLib" within the object's src directory.
#
# this works well in some cases. for example, let us say that we
# are working in the FrontMtx/drivers directory and we see that
# the A2/src/QRreduce.c file needs a change. we open another window,
# move to the A2/src directory, and make the change in QRreduce.c.
# we then execute "make updateLib", which first calls this
# script to generate a makefile that will compile QRreduce.c
# and load into spooles.a. the makefile is then executed to perform
# that operation, and then removed. we have a good incremental
# change to the global spooles.a library.
#
# here is a second case where it doesn't work as well. assume again
# that we are working in the FrontMtx/drivers directory, and we
# see that changes need to be made to two different src files,
# the first A2/src/QRreduce.c and the second SubMtx/src/util.c.
# we edit the two source files and then need to update the spooles.a
# library.
#
# we first go to the A2/src directory and execute "make updateLib"
# then the QRreduce.c file gets compiled and loaded into spooles.a.
# we then go to the SubMtx/src directory and execute "make updateLib"
# and the util.c file # is NOT compiled and loaded into the library.
# this is because spooles.a is more recent the SubMtx/src/util.c,
# because spooles.a was just modified when A2/src/QRreduce.c was
# compiled and loaded.
#
# i presently don't know of a clean solution to this problem
# (and am open to suggestions). a decent workaround is this.
# (1) go to A2/src, modify QRreduce.c, then "make updateLib"
# (2) go to SubMtx/src, modify util.c, then "make updateLib"
# here the util.c file is more recent than spooles.a. in other words,
# update the library after each src file is changed.
#
# this is my first perl script, so don't laugh,
# just send me comments and suggestions.
#
# created -- 98dec16, cca
#
#-----------------------------------------------------------------------
#
# open the makefile to extract out the src file names
#
$makefile = "makefile" ;
open( MAKEFILE, $makefile ) or die "Cannot open $makefile" ;
#
# get the last modification time for ../../spooles.a
#
if ( -e "../../spooles.a" ) {
$lib_time = -M "../../spooles.a" ;
}
#
# read in each line, look for $(OBJ).a(srcname.o)
# put srcname into the @srcnames array
#
while ( $line = ) {
chop($line) ;
if ( $line =~ /OBJ =/ ) {
($first, $objname) = split /OBJ = /, $line
}
if ( $line =~ /\$\(OBJ\)\.a\(/ ) {
($first, $second) = split /\$\(OBJ\)\.a\(/, $line ;
($srcname, $remainder) = split /\.o\)/, $second ;
$srcname = $srcname . ".c" ;
#
# get the last modification time for srcname.c
#
$srcname_time = -M $srcname ;
if ( (! -e "../../spooles.a") or ($srcname_time < $lib_time) ) {
push @srcnames, $srcname
}
}
}
#
# now start printing the makefile to stdout
#
print "\ninclude ../../Make.inc" ;
print "\n" ;
print "\nOBJ = $objname" ;
print "\n\nSRC = " ;
foreach $src ( @srcnames ) {
$srcname = " \\\n " . $src ;
print $srcname ;
}
print "\n\nOBJ_FILES = \$\{SRC:.c=.o\}" ;
print "\n\n" ;
print <<'EOF' ;
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
EOF
dotar 0100755 0002055 0007177 00000014713 06650142470 0013142 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
tar -cvf spooles.2.2.tar \
makefile \
makeLib \
updLib \
dotar \
cfiles.h \
timings.h \
DLIST.h \
SPOOLES.h \
Make.inc \
*.html \
A2.h \
A2/{*.h,makefile} \
A2/src/{makefile,makeGlobalLib,*.c} \
A2/drivers/{do*,makefile,*.c} \
A2/doc \
BKL.h \
BKL/{*.h,makefile} \
BKL/src/{makefile,makeGlobalLib,*.c} \
BKL/doc \
BPG.h \
BPG/{*.h,makefile} \
BPG/src/{makefile,makeGlobalLib,*.c} \
BPG/drivers/{do*,makefile,*.c} \
BPG/doc \
Chv.h \
Chv/{*.h,makefile} \
Chv/src/{makefile,makeGlobalLib,*.c} \
Chv/drivers/{do*,makefile,*.c} \
Chv/doc \
ChvList.h \
ChvList/{*.h,makefile} \
ChvList/src/{makefile,makeGlobalLib,*.c} \
ChvList/doc \
ChvManager.h \
ChvManager/{*.h,makefile} \
ChvManager/src/{makefile,makeGlobalLib,*.c} \
ChvManager/doc \
Coords.h \
Coords/{*.h,makefile} \
Coords/src/{makefile,makeGlobalLib,*.c} \
Coords/drivers/{do*,makefile,*.c} \
Coords/doc \
DSTree.h \
DSTree/{*.h,makefile} \
DSTree/src/{makefile,makeGlobalLib,*.c} \
DSTree/drivers/{do*,makefile,*.c,cutoff.dvf} \
DSTree/doc \
DV.h \
DV/{*.h,makefile} \
DV/src/{makefile,makeGlobalLib,*.c} \
DV/drivers/{makefile,makeGlobalLib,*.c} \
DV/doc \
DenseMtx.h \
DenseMtx/{*.h,makefile} \
DenseMtx/src/{makefile,makeGlobalLib,*.c} \
DenseMtx/doc \
Drand.h \
Drand/{*.h,makefile} \
Drand/src/{makefile,makeGlobalLib,*.c} \
Drand/drivers/{do*,makefile,*.c} \
Drand/doc \
EGraph.h \
EGraph/{*.h,makefile} \
EGraph/src/{makefile,makeGlobalLib,*.c} \
EGraph/drivers/{do*,makefile,*.c} \
EGraph/doc \
ETree.h \
ETree/{*.h,makefile} \
ETree/src/{makefile,makeGlobalLib,*.c} \
ETree/drivers/{do*,makefile,*.c} \
ETree/doc \
Eigen.h \
Eigen/{*.h,makefile} \
Eigen/srcST/{makefile,makeGlobalLib,*.c} \
Eigen/srcMT/{makefile,makeGlobalLib,*.c} \
Eigen/srcMPI/{makefile,makeGlobalLib,*.c} \
Eigen/drivers/{do*,makefile,*.c,*.inp,*.pg} \
Eigen/doc \
FrontMtx.h \
FrontMtx/{*.h,makefile} \
FrontMtx/src/{makefile,makeGlobalLib,*.c} \
FrontMtx/drivers/{do*,makefile,*.c} \
FrontMtx/doc \
GPart.h \
GPart/{*.h,makefile} \
GPart/src/{makefile,makeGlobalLib,*.c} \
GPart/drivers/{do*,makefile,*.c} \
GPart/doc \
Graph.h \
Graph/{*.h,makefile} \
Graph/src/{makefile,makeGlobalLib,*.c} \
Graph/drivers/{do*,makefile,*.c} \
Graph/doc \
I2Ohash.h \
I2Ohash/{*.h,makefile} \
I2Ohash/src/{makefile,makeGlobalLib,*.c} \
I2Ohash/drivers/{makefile,makeGlobalLib,*.c} \
I2Ohash/doc \
IIheap.h \
IIheap/{*.h,makefile} \
IIheap/src/{makefile,makeGlobalLib,*.c} \
IIheap/doc \
ILUMtx.h \
ILUMtx/{*.h,makefile} \
ILUMtx/src/{makefile,makeGlobalLib,*.c} \
ILUMtx/drivers/{do*,makefile,*.c} \
ILUMtx/doc \
IV.h \
IV/{*.h,makefile} \
IV/src/{makefile,makeGlobalLib,*.c} \
IV/drivers/{do*,makefile,*.c} \
IV/doc \
IVL.h \
IVL/{*.h,makefile} \
IVL/src/{makefile,makeGlobalLib,*.c} \
IVL/doc \
IVL/drivers/{do*,makefile,*.c} \
Ideq.h \
Ideq/{*.h,makefile} \
Ideq/src/{makefile,makeGlobalLib,*.c} \
Ideq/doc \
InpMtx.h \
InpMtx/{*.h,makefile} \
InpMtx/src/{makefile,makeGlobalLib,*.c} \
InpMtx/drivers/{do*,makefile,*.c} \
InpMtx/doc \
Iter.h \
Iter/{*.h,makefile} \
Iter/src/{makefile,makeGlobalLib,*.c} \
Iter/drivers/{do*,makefile,*.c} \
Iter/doc \
LinSol.h \
LinSol/{*.h,makefile} \
LinSol/srcST/{makefile,makeGlobalLib,*.c} \
LinSol/srcMT/{makefile,makeGlobalLib,*.c} \
LinSol/srcMPI/{makefile,makeGlobalLib,*.c} \
LinSol/drivers/{do*,makefile,*.c,*.input,*.pg} \
LinSol/doc \
Lock.h \
Lock/{*.h,makefile} \
Lock/src/{makefile,makeGlobalLib,*.c} \
Lock/doc \
MPI.h \
MPI/{*.h,makefile} \
MPI/src/{makefile,makeGlobalLib,*.c} \
MPI/drivers/{do*,makefile,*.c,*.input,*.pg} \
MPI/doc \
MSMD.h \
MSMD/{*.h,makefile} \
MSMD/src/{makefile,makeGlobalLib,*.c} \
MSMD/drivers/{do*,makefile,*.c} \
MSMD/doc \
MT.h \
MT/{*.h,makefile} \
MT/src/{makefile,makeGlobalLib,*.c} \
MT/drivers/{do*,makefile,*.c,*.input} \
MT/doc \
Network.h \
Network/{*.h,makefile} \
Network/src/{makefile,makeGlobalLib,*.c} \
Network/doc \
PatchAndGoInfo.h \
PatchAndGoInfo/{*.h,makefile} \
PatchAndGoInfo/src/{makefile,makeGlobalLib,*.c} \
PatchAndGoInfo/doc \
Pencil.h \
Pencil/{*.h,makefile} \
Pencil/src/{makefile,makeGlobalLib,*.c} \
Pencil/doc \
Perm.h \
Perm/{*.h,makefile} \
Perm/src/{makefile,makeGlobalLib,*.c} \
Perm/drivers/{do*,makefile,*.c} \
Perm/doc \
SemiImplMtx.h \
SemiImplMtx/{*.h,makefile} \
SemiImplMtx/src/{makefile,makeGlobalLib,*.c} \
SemiImplMtx/drivers/{do*,makefile,*.c} \
SemiImplMtx/doc \
SolveMap.h \
SolveMap/{*.h,makefile} \
SolveMap/src/{makefile,makeGlobalLib,*.c} \
SolveMap/doc \
SubMtx.h \
SubMtx/{*.h,makefile} \
SubMtx/src/{makefile,makeGlobalLib,*.c} \
SubMtx/drivers/{do*,makefile,*.c,*submtx*} \
SubMtx/doc \
SubMtxList.h \
SubMtxList/{*.h,makefile} \
SubMtxList/src/{makefile,makeGlobalLib,*.c} \
SubMtxList/doc \
SubMtxManager.h \
SubMtxManager/{*.h,makefile} \
SubMtxManager/src/{makefile,makeGlobalLib,*.c} \
SubMtxManager/doc \
SymbFac.h \
SymbFac/{*.h,makefile} \
SymbFac/src/{makefile,makeGlobalLib,*.c} \
SymbFac/drivers/{do*,makefile,*.c} \
SymbFac/doc \
Tree.h \
Tree/{*.h,makefile} \
Tree/src/{makefile,makeGlobalLib,*.c} \
Tree/drivers/{do*,makefile,*.c} \
Tree/doc \
Utilities.h \
Utilities/{*.h,makefile} \
Utilities/src/{makefile,makeGlobalLib,*.c} \
Utilities/drivers/{do*,makefile,*.c} \
Utilities/doc \
ZV.h \
ZV/{*.h,makefile} \
ZV/src/{makefile,makeGlobalLib,*.c} \
ZV/drivers/{do*,makefile,*.c} \
ZV/doc \
misc.h \
misc/{*.h,makefile} \
misc/src/{makefile,makeGlobalLib,*.c} \
misc/drivers/{do*,makefile,*.c,*.input} \
misc/doc \
Matrices \
documentation
GPart/doc \
Graph.h \
Graph/{*.h,makefcfiles.h 0100644 0002055 0007177 00000000112 06535015747 0013515 0 ustar 00cleve compmath 0000040 0000006 #ifndef _cFILES_
#define _cFILES_
#include "Utilities/Utilities.h"
#endif
timings.h 0100644 0002055 0007177 00000000327 06535034566 0013732 0 ustar 00cleve compmath 0000040 0000006 #ifndef _TIMINGS_
#define _TIMINGS_
#include
static struct timeval TV ;
static struct timezone TZ ;
#define MARKTIME(t) \
gettimeofday(&TV, &TZ) ; \
t = (TV.tv_sec + 0.000001*TV.tv_usec)
#endif
SPOOLES.h 0100644 0002055 0007177 00000000557 06605446115 0013404 0 ustar 00cleve compmath 0000040 0000006 #ifndef _SPOOLES_
#define _SPOOLES_
#define SPOOLES_INDICES_ONLY 0
#define SPOOLES_REAL 1
#define SPOOLES_COMPLEX 2
#define SPOOLES_SYMMETRIC 0
#define SPOOLES_HERMITIAN 1
#define SPOOLES_NONSYMMETRIC 2
#define SPOOLES_NO_PIVOTING 0
#define SPOOLES_PIVOTING 1
#define SPOOLES_BY_ROWS 1
#define SPOOLES_BY_COLUMNS 2
#endif
Make.inc 0100644 0002055 0007177 00000006012 06650726107 0013451 0 ustar 00cleve compmath 0000040 0000006 .POSIX:
#----------------------------------------
#
# file created 98jun18, cca, (cleve.ashcraft@boeing.com)
# based on work by clay breshears (clay@turing.wes.hpc.mil)
# (much appreciated)
#
#----------------------------------------
#
# place your favorite compiler here
#
# for solaris
#
# CC = gcc
CC = /usr/lang-4.0/bin/cc
#
# for sgi
#
# CC = cc
#
# for hp
#
# CC = /opt/mpi/bin/mpicc
#
#----------------------------------------
#
# set the compiler flags
#
# OPTLEVEL =
# OPTLEVEL = -g -v
OPTLEVEL = -O
# OPTLEVEL = -xO5 -v
# OPTLEVEL = -O3
# OPTLEVEL = -O4
# CFLAGS = -Wall -g
# CFLAGS = -Wall -pg
# CFLAGS = $(OPTLEVEL) -D_POSIX_C_SOURCE=199506L
CFLAGS = $(OPTLEVEL)
# CFLAGS = -Wall $(OPTLEVEL)
#
#----------------------------------------
#
# set any load flags
#
# LDFLAGS = -Wl,+parallel -Wl,+tm,spp2000 # for hp exemplar
LDFLAGS =
#
#---------------------------------------------------------------------
#
# set any thread libraries
#
# THREAD_LIBS =
# THREAD_LIBS = -D_REENTRANT=199506L -lpthread
THREAD_LIBS = -D_POSIX_C_SOURCE=199506L -lpthread
# THREAD_LIBS = -lpthread
#
#---------------------------------------------------------------------
#
# set the purify environment (a memory monitoring tool)
#
PURIFY =
# PURIFY = /usr/local/purify-4.0.1/purify
#
# purify wouldn't work with the newest version of the gcc library,
# so we had to force loading the old version
#
PURIFY_GCC_VERSION =
# PURIFY_GCC_VERSION = -V 2.7.2
#
#---------------------------------------------------------------------
#
# set the archive flags
#
AR = ar
ARFLAGS = rv
#
#---------------------------------------------------------------------
#
# set the ranlib environment
# (if ranlib is not needed, we echo the library name)
#
# RANLIB = ranlib
RANLIB = echo
#
#---------------------------------------------------------------------
#
# set suffix rule *.c --> *.o
#
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $<
#
#---------------------------------------------------------------------
#
# set suffix rule *.c --> *.a
#
.c.a :
$(PURIFY) $(CC) -c $(CFLAGS) $<
$(AR) $(ARFLAGS) $@ $*.o
rm -f $*.o
#
#---------------------------------------------------------------------
#
# MPI install library
#
# MPI_INSTALL_DIR =
MPI_INSTALL_DIR = /usr/local/mpich-1.0.13
#
#---------------------------------------------------------------------
#
# MPI library path
#
# for sgi
#
# MPI_LIB_PATH =
#
# for solaris
#
MPI_LIB_PATH = -L$(MPI_INSTALL_DIR)/lib/solaris/ch_p4
#
# for hp
#
# MPI_LIB_PATH =
#
#---------------------------------------------------------------------
#
# MPI libraries
#
# for solaris
#
MPI_LIBS = $(MPI_LIB_PATH) -D_REENTRANT -lmpi -lsocket -lnsl -lthread
#
# for sgi
#
# MPI_LIBS = $(MPI_LIB_PATH) -lmpi -lpthread
#
# for hp
# MPI_LIBS = -lpthread
# MPI_LIBS = $(MPI_LIB_PATH) -lpthread
#
#---------------------------------------------------------------------
#
# MPI include path
#
# MPI_INCLUDE_DIR =
MPI_INCLUDE_DIR = -I$(MPI_INSTALL_DIR)/include
#
#---------------------------------------------------------------------
spooles.2.2.html 0100644 0002055 0007177 00000017072 06650700175 0014760 0 ustar 00cleve compmath 0000040 0000006
SPOOLES 2.2 : SParse Object Oriented Linear Equations Solver
SPOOLES 2.2 : SParse Object Oriented Linear Equations Solver
SPOOLES is a library for solving sparse real and complex
linear systems of equations, written in the C language using object
oriented design.
At present, there is the following functionality:
-
Compute multiple minimum degree, generalized nested dissection
and multisection orderings of matrices with symmetric structure.
Factor and solve square linear systems of equations with
symmetric structure, with or without pivoting for stability.
The factorization can be symmetric LDLT,
Hermitian LDLH,
or nonsymmetric LDU.
A direct factorization or a
drop tolerance factorization can be computed.
The factors and solve can be done in serial
mode, multithreaded with Solaris or POSIX threads, or with MPI.
Factor and solve overdetermined full rank systems of equations
using a multifrontal QR factorization, in serial or using POSIX
threads.
Solve square linear systems using a variety of Krylov iterative
methods.
The preconditioner is a drop tolerance factorization, with or
without pivoting for stability.
The SPOOLES library has been developed by members of the Mathematics
and Engineering Analysis Unit of Boeing Phantom Works.
The library was supported in part by DARPA contract
DABT63-95-C-0122 and the DoD High Performance Computing
Modernization Program Common HPC Software Support Initiative.
Individuals who have contributed to this package include:
- Cleve Ashcraft, Boeing Phantom Works
- Roger Grimes, Boeing Phantom Works
- Joseph Liu, York University
- Jim Patterson, Boeing Phantom Works
- Dan Pierce, Boeing Phantom Works
- Yichi Pierce, Boeing Phantom Works
- Peter Schartz, CSAR Corporation
- Juergen Schulze, University of Paderborn
- Wei-Pai Tang, University of Waterloo
- David Wah, Boeing Phantom Works
- Jason Wu, Boeing Phantom Works
This release is entirely within the public domain;
there are no licensing restrictions,
and there is no warranty of any sort.
Contact cleve.ashcraft@boeing.com for more information,
comments and bug reports.
The library is available as a gzip'd, tar'd file that contains the
entire source, drivers and LaTeX documentation.
There are seven Postscript files that contain documentation.
-
install.ps.gz
--- "SPOOLES 2.2 Installation Manual",
7 pages,
describes the library's structure and installation procedures.
-
ReferenceManual.ps.gz
--- "The Reference Manual for SPOOLES, Release 2.2:
An Object Oriented Software Library for Solving Sparse Linear
Systems of Equations",
over 400 pages, every object, method and
driver is documented.
-
fronttrees.ps.gz
--- "Ordering Sparse Matrices and Transforming Front Trees",
20, pages,
describes the different ordering methods in the library and
the effect of the front trees on performance.
-
LinSol.ps.gz
--- "Wrapper Objects for Solving a Linear System of Equations
using SPOOLES 2.2",
58 pages, provides the most gentle introduction to the library,
documents a set of software objects written to incorporate the
SPOOLES linear solver into the CSAR-Nastran finite element software
package.
-
AllInOne.ps.gz
--- "Solving Linear Systems using SPOOLES 2.2",
54 pages, contains example programs with commentary,
a general introduction to the library, much more detail
than the "Wrapper Objects" document immediately above.
-
Eigen.ps.gz
--- "Integrating the SPOOLES 2.2 Sparse Linear Algebra Library into
the LANCZOS Block-Shifted Lanczos Eigensolver",
42 pages,
documents a set of software objects written to incorporate the
SPOOLES linear solver into an eigenanalysis package,
also funded by DARPA contract DABT63-95-C-0122 and
the DoD High Performance Computing
Modernization Program Common HPC Software Support Initiative.
-
PP99.ps.gz
"SPOOLES: An Object-Oriented Sparse Matrix Library",
a paper to be included in the Proceedings of the
1999 SIAM Conference on Parallel Processing for Scientific Computing,
March 22-27, 1999.
-
spooles.2.2.tar.gz
--- gzip'd, tar'd file of library
Changes since the 2.0 release.
- Semi-implicit factorizations to reduce storage and/or
operation counts for direct and approximate factorizations.
(See the SemiImplMtx directory.)
- Krylov solvers for real SPD, symmetric indefinite,
and nonsymmetric linear systems.
(See the Iter directory.)
The preconditioner is a drop tolerance approximate factorization
obtained from the FrontMtx object.
There also exists a simpler ILU drop tolerance factorization
in the ILUMtx directory.
-
There is a "patch-and-go" functionality for factorizations
that must be modified on the fly.
One application is found in singular or near singular matrices
from structural analysis applications.
Another application is for matrices from interior point methods.
In both cases, the presence of a zero or small pivot element
requires special handling.
-
There is a "wrapper" object to solve linear systems
found in the LinSol directory.
It was used to incorporate the SPOOLES library into
the CSAR-Nastran finite element package.
-
There is a "wrapper" object used in an eigenanalysis package
found in the Eigen directory.
-
Several bugs were fixed in the multithreaded and MPI solvers.
Users of the SPOOLES 2.0 versions should upgrade.
-
The user manual and reference manual documentation has been
reorganized. There is a new documentation
directory, with five subdirectories:
-
documentation/Install holds
"SPOOLES 2.2 Installation Manual",
the installation manual.
-
documentation/AllInOne holds
"Solving Linear Systems using SPOOLES 2.2",
the driver programs manual.
-
documentation/FrontTrees holds
"Ordering Sparse Matrices and Transforming Front Trees",
the ordering manual.
-
documentation/ReferenceManual holds
"The Reference Manual for SPOOLES, Release 2.2:
An Object Oriented Software Library for Solving Sparse Linear
Systems of Equations",
the complete reference manual.
-
documentation/PP99 holds
"SPOOLES: An Object-Oriented Sparse Matrix Library",
a paper to be included in the Proceedings of the
1999 SIAM Conference on Parallel Processing for Scientific Computing,
March 22-27, 1999.
Changes since the 1.0 release.
- Complex linear systems are now supported
- Factor storage has been reorganized to improve parallel solves
- Several bugs in the MPI solvers have been fixed
A2.h 0100644 0002055 0007177 00000000064 06534106367 0012516 0 ustar 00cleve compmath 0000040 0000006 #ifndef _A2_
#define _A2_
#include "A2/A2.h"
#endif
A2/A2.h 0100644 0002055 0007177 00000056606 06635772400 0012774 0 ustar 00cleve compmath 0000040 0000006 /* A2.h */
#include "../cfiles.h"
#include "../SPOOLES.h"
#include "../ZV.h"
#include "../IV.h"
#include "../DV.h"
/*====================================================================*/
/*
-----------------------------------------------------------
the A2 structure holds a 2-d dense array of double complex
type -- type of entries
1 -- real
2 -- complex
n1 -- number of rows (first dimension)
n2 -- number of columns (second dimension)
inc1 --
increment in storage along first dimension,
when inc1 == 1, the storage is column major
inc2 --
increment in storage along second dimension,
when inc2 == 1, the storage is row major
nowned -- number of owned entries starting at entries
when > 0, storage pointed to by entries
has been allocated here and can be free'd.
when = 0, storage pointed to by entries
has not been allocated here and cannot be free'd.
entries -- base address for the entries
if real then
entry(i,j) is found in entries[i*inc1 + j*inc2]
else
entry(i,j) is found in entries[2*(i*inc1 + j*inc2)]
and entries[2*(i*inc1 + j*inc2)+1]
endif
-----------------------------------------------------------
*/
typedef
struct _A2 {
int type ;
int n1 ;
int n2 ;
int inc1 ;
int inc2 ;
int nowned ;
double *entries ;
} A2 ;
#define A2_IS_REAL(chv) ((chv)->type == SPOOLES_REAL)
#define A2_IS_COMPLEX(chv) ((chv)->type == SPOOLES_COMPLEX)
#define A2_STRICT_LOWER 1
#define A2_LOWER 2
#define A2_DIAGONAL 3
#define A2_UPPER 4
#define A2_STRICT_UPPER 5
#define A2_ALL_ENTRIES 6
#define A2_BY_ROWS 0
#define A2_BY_COLUMNS 1
/*====================================================================*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
simplest constructor
created -- 98may01, cca
-----------------------
*/
A2 *
A2_new (
void
) ;
/*
-----------------------
set the default fields
created -- 98may01, cca
-----------------------
*/
void
A2_setDefaultFields (
A2 *mtx
) ;
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98may01, cca
--------------------------------------------------
*/
void
A2_clearData (
A2 *mtx
) ;
/*
------------------------------------------
destructor, free's the object and its data
created -- 98may01, cca
------------------------------------------
*/
void
A2_free (
A2 *mtx
) ;
/*
------------------------------------------------------------------------
----- methods found in instance.c --------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------
return the number of rows in the array
created -- 98may01, cca
--------------------------------------
*/
int
A2_nrow (
A2 *mtx
) ;
/*
-----------------------------------------
return the number of columns in the array
created -- 98may01, cca
-----------------------------------------
*/
int
A2_ncol (
A2 *mtx
) ;
/*
--------------------------
return the first increment
created -- 98may01, cca
--------------------------
*/
int
A2_inc1 (
A2 *mtx
) ;
/*
---------------------------
return the second increment
created -- 98may01, cca
---------------------------
*/
int
A2_inc2 (
A2 *mtx
) ;
/*
-------------------------------
return a pointer to the entries
created -- 98may01, cca
-------------------------------
*/
double *
A2_entries (
A2 *mtx
) ;
/*
--------------------------------------------
return a pointer to the first entry in a row
created -- 98may01, cca
--------------------------------------------
*/
double *
A2_row (
A2 *mtx,
int irow
) ;
/*
-----------------------------------------------
return a pointer to the first entry in a column
created -- 98may01, cca
-----------------------------------------------
*/
double *
A2_column (
A2 *mtx,
int jcol
) ;
/*
-------------------------------------------
fill *pValue with the entry in (irow, jcol)
created -- 98may01, cca
-------------------------------------------
*/
void
A2_realEntry (
A2 *mtx,
int irow,
int jcol,
double *pValue
) ;
/*
---------------------------------------------------
fill (*pReal,*pImag) with the entry in (irow, jcol)
created -- 98may01, cca
---------------------------------------------------
*/
void
A2_complexEntry (
A2 *mtx,
int irow,
int jcol,
double *pReal,
double *pImag
) ;
/*
-----------------------------------------
set the entry in (irow, jcol) to be value
created -- 98may01, cca
-----------------------------------------
*/
void
A2_setRealEntry (
A2 *mtx,
int irow,
int jcol,
double value
) ;
/*
-----------------------------------------------
set the entry in (irow, jcol) to be (real,imag)
created -- 98may01, cca
-----------------------------------------------
*/
void
A2_setComplexEntry (
A2 *mtx,
int irow,
int jcol,
double real,
double imag
) ;
/*
---------------------------------------
fill pointers to the matrix first entry
in row irow and column jcol
created -- 98may01, cca
---------------------------------------
*/
void
A2_pointerToRealEntry (
A2 *mtx,
int irow,
int jcol,
double **ppValue
) ;
/*
---------------------------------------
fill pointers to the matrix first entry
in row irow and column jcol
created -- 98may01, cca
---------------------------------------
*/
void
A2_pointerToComplexEntry (
A2 *mtx,
int irow,
int jcol,
double **ppReal,
double **ppImag
) ;
/*
------------------------------------------------------------------------
----- methods found in init.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------------
initializer. sets the n1, n2, inc1 and inc2 fields.
must have
mtx != NULL
type = SPOOLES_REAL or SPOOLES_COMPLEX
n1, n2, inc1, inc2 > 0
(inc1 = 1 and inc2 = nrow) or (inc1 = ncol and inc2 = 1)
if entries is NULL then
entries are allocated and zeroed.
else
mtx->nowned is set to 0
mtx->entries is set to entries.
endif
n1, n2, inc1, inc2 set
created -- 98apr15, cca
------------------------------------------------------------------
*/
void
A2_init (
A2 *mtx,
int type,
int n1,
int n2,
int inc1,
int inc2,
double *entries
) ;
/*
--------------------------------------------------
submatrix initializer
A(0:lastrow-firstrow,0:lastcol-firstcol)
= B(firstrow:lastrow, firstcol:lastcol)
created -- 98apr15, cca
--------------------------------------------------
*/
void
A2_subA2 (
A2 *mtxA,
A2 *mtxB,
int firstrow,
int lastrow,
int firstcol,
int lastcol
) ;
/*
------------------------------------------------------------------------
----- methods found in norms.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------
return the entry of maximum magnitude
created -- 98apr15, cca
-------------------------------------
*/
double
A2_maxabs (
A2 *a
) ;
/*
---------------------------------------
return the frobenius norm of the matrix
created -- 98apr15, cca
---------------------------------------
*/
double
A2_frobNorm (
A2 *mtx
) ;
/*
---------------------------------
return the one-norm of the matrix
created -- 98apr15, cca
---------------------------------
*/
double
A2_oneNorm (
A2 *mtx
) ;
/*
--------------------------------------
return the infinity-norm of the matrix
created -- 98apr15, cca
--------------------------------------
*/
double
A2_infinityNorm (
A2 *mtx
) ;
/*
----------------------------------
return the one-norm of column jcol
created -- 98apr15, cca
----------------------------------
*/
double
A2_oneNormOfColumn (
A2 *mtx,
int jcol
) ;
/*
----------------------------------
return the two-norm of column jcol
created -- 98apr15, cca
----------------------------------
*/
double
A2_twoNormOfColumn (
A2 *mtx,
int jcol
) ;
/*
---------------------------------------
return the infinity-norm of column jcol
created -- 98apr15, cca
---------------------------------------
*/
double
A2_infinityNormOfColumn (
A2 *mtx,
int jcol
) ;
/*
-------------------------------
return the one-norm of row irow
created -- 98apr15, cca
-------------------------------
*/
double
A2_oneNormOfRow (
A2 *mtx,
int irow
) ;
/*
-------------------------------
return the two-norm of row irow
created -- 98apr15, cca
-------------------------------
*/
double
A2_twoNormOfRow (
A2 *mtx,
int irow
) ;
/*
------------------------------------
return the infinity-norm of row irow
created -- 98apr15, cca
------------------------------------
*/
double
A2_infinityNormOfRow (
A2 *mtx,
int irow
) ;
/*
------------------------------------------------------------------------
----- methods found in sort.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------
permute the rows of the matrix
A(*,*) = A(index(*),*)
this method calls A2_sortRowsUp
but does not overwrite the index[] vector
created -- 98apr15, cca
-----------------------------------------
*/
void
A2_permuteRows (
A2 *mtx,
int nrow,
int index[]
) ;
/*
-----------------------------------------
permute the columns of the matrix
A(*,*) = A(*,index(*))
this method calls A2_sortColumnsUp
but does not overwrite the index[] vector
created -- 98apr15, cca
-----------------------------------------
*/
void
A2_permuteColumns (
A2 *mtx,
int ncol,
int index[]
) ;
/*
----------------------------------------------
sort the rows of the matrix in ascending order
of the rowids[] vector. on return, rowids is
in asending order. return value is the number
of row swaps made.
created -- 98apr15, cca
----------------------------------------------
*/
int
A2_sortRowsUp (
A2 *mtx,
int nrow,
int rowids[]
) ;
/*
-------------------------------------------------
sort the columns of the matrix in ascending order
of the colids[] vector. on return, colids is
in asending order. return value is the number
of column swaps made.
created -- 98apr15, cca
-------------------------------------------------
*/
int
A2_sortColumnsUp (
A2 *mtx,
int ncol,
int colids[]
) ;
/*
------------------------------------------------------------------------
----- methods found in QRreduce.c --------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------------
purpose -- compute A = QR, where Q is a product of householder
vectors, (I - beta_j v_j v_j^T). on return, v_j is
found in the lower triangle of A, v_j(j) = 1.0.
return value -- # of floating point operations
created -- 98may25, cca
--------------------------------------------------------------
*/
double
A2_QRreduce (
A2 *mtxA,
DV *workDV,
int msglvl,
FILE *msgFile
) ;
/*
-----------------------------------------------------------
A contains the following data from the A = QR factorization
A(1:ncolA,1:ncolA) = R
A(j+1:nrowA,j) is v_j, the j-th householder vector,
where v_j[j] = 1.0
NOTE: A and Q must be column major
created -- 98dec10, cca
-----------------------------------------------------------
*/
void
A2_computeQ (
A2 *Q,
A2 *A,
DV *workDV,
int msglvl,
FILE *msgFile
) ;
/*
-----------------------------------------------------------
A contains the following data from the A = QR factorization
A(1:ncolA,1:ncolA) = R
A(j+1:nrowA,j) is v_j, the j-th householder vector,
where v_j[j] = 1.0
we compute Y = Q^T X when A is real
and Y = Q^H X when A is complex
NOTE: A, Y and X must be column major.
NOTE: Y and X can be the same object,
in which case X is overwritten with Y
created -- 98dec10, cca
-----------------------------------------------------------
*/
void
A2_applyQT (
A2 *Y,
A2 *A,
A2 *X,
DV *workDV,
int msglvl,
FILE *msgFile
) ;
/*
------------------------------------------------------------------------
----- methods found in copyEntriesToVector.c ---------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------------------------
purpose -- copy entries to a vector. the portion copied
can be a union of the strict lower portion,
the diagonal portion, and the strict upper
portion. there is one restriction, if the strict
lower and strict upper are to be copied, the
diagonal will also be copied.
length -- length of dvec[]
dvec[] -- vector to receive matrix entries
copyflag -- flag to denote what part of the entries to move
A2_STRICT_LOWER --> move strict lower entries
A2_LOWER --> move lower entries (includes the diagonal)
A2_DIAGONAL --> move diagonal entries
A2_UPPER --> move upper entries (includes the diagonal)
A2_STRICT_UPPER --> move strict upper entries
A2_ALL_ENTRIES --> move all entries
storeflag -- flag to denote how to store entries in dvec[]
A2_BY_ROWS --> store by rows
A2_BY_COLUMNS --> store by columns
return value -- number of entries copied
created -- 97jun03, cca, dkw
modified -- 98may25, cca
----------------------------------------------------------------
*/
int
A2_copyEntriesToVector (
A2 *mtx,
int length,
double *dvec,
int copyflag,
int storeflag
) ;
/*
------------------------------------------------------------------------
----- methods found in makeStaircase.c ---------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------------
purpose -- to permute the rows so the matrix is in staircase form
created -- 98may25, cca
-----------------------------------------------------------------
*/
void
A2_makeStaircase (
A2 *mtxA
) ;
/*
------------------------------------------------------------------------
----- methods found in util.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 98may01, cca
----------------------------------------------
*/
int
A2_sizeOf (
A2 *mtx
) ;
/*
---------------------------------------------------------------
shift the base of the entries and adjust dimensions
mtx(0:n1-rowoff-1,0:n2-coloff-1) = mtx(rowoff:n1-1,coloff:n2-1)
created -- 98may01, cca
---------------------------------------------------------------
*/
void
A2_shiftBase (
A2 *mtx,
int rowoff,
int coloff
) ;
/*
--------------------------------------------------------------
returns 1 if the storage is row major, otherwise returns zero.
created -- 98may01, cca
--------------------------------------------------------------
*/
int
A2_rowMajor (
A2 *mtx
) ;
/*
-----------------------------------------------------------------
returns 1 if the storage is column major, otherwise returns zero.
created -- 98may01, cca
-----------------------------------------------------------------
*/
int
A2_columnMajor (
A2 *mtx
) ;
/*
-----------------------
transpose the matrix
created -- 98may01, cca
-----------------------
*/
void
A2_transpose (
A2 *mtx
) ;
/*
----------------------------
extract row[*] = mtx(irow,*)
created -- 98may01, cca
----------------------------
*/
void
A2_extractRow (
A2 *mtx,
double row[],
int irow
) ;
/*
----------------------------
extract col[*] = mtx(*,jcol)
created -- 98may01, cca
----------------------------
*/
void
A2_extractColumn (
A2 *mtx,
double col[],
int jcol
) ;
/*
-----------------------
set mtx(irow,*) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setRow (
A2 *mtx,
double row[],
int irow
) ;
/*
-----------------------
set mtx(*,jcol) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setColumn (
A2 *mtx,
double col[],
int jcol
) ;
/*
----------------------------
extract row[*] = mtx(irow,*)
created -- 98may01, cca
----------------------------
*/
void
A2_extractRowDV (
A2 *mtx,
DV *rowDV,
int irow
) ;
/*
----------------------------
extract row[*] = mtx(irow,*)
created -- 98may01, cca
----------------------------
*/
void
A2_extractRowZV (
A2 *mtx,
ZV *rowZV,
int irow
) ;
/*
----------------------------
extract col[*] = mtx(*,jcol)
created -- 98may01, cca
----------------------------
*/
void
A2_extractColumnDV (
A2 *mtx,
DV *colDV,
int jcol
) ;
/*
----------------------------
extract col[*] = mtx(*,jcol)
created -- 98may01, cca
----------------------------
*/
void
A2_extractColumnZV (
A2 *mtx,
ZV *colZV,
int jcol
) ;
/*
-----------------------
set mtx(irow,*) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setRowDV (
A2 *mtx,
DV *rowDV,
int irow
) ;
/*
-----------------------
set mtx(irow,*) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setRowZV (
A2 *mtx,
ZV *rowZV,
int irow
) ;
/*
-----------------------
set mtx(*,jcol) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setColumnDV (
A2 *mtx,
DV *colDV,
int jcol
) ;
/*
-----------------------
set mtx(*,jcol) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setColumnZV (
A2 *mtx,
ZV *colZV,
int jcol
) ;
/*
-------------------------------------------------------------
fill the matrix with uniform random numbers in [lower, upper]
created -- 98may01, cca
-------------------------------------------------------------
*/
void
A2_fillRandomUniform (
A2 *a,
double lower,
double upper,
int seed
) ;
/*
-----------------------------------------------
fill the matrix with normal(0,1) random numbers
created -- 98may01, cca
-----------------------------------------------
*/
void
A2_fillRandomNormal (
A2 *a,
double mean,
double variance,
int seed
) ;
/*
----------------------------------------
fill the matrix with the identity matrix
created -- 98may01, cca
----------------------------------------
*/
void
A2_fillWithIdentity (
A2 *a
) ;
/*
--------------------------
fill the matrix with zeros
created -- 98may01, cca
--------------------------
*/
void
A2_zero (
A2 *a
) ;
/*
----------------------------
copy one matrix into another
A := B
created -- 98may01, cca
----------------------------
*/
void
A2_copy (
A2 *A,
A2 *B
) ;
/*
--------------------------------
subtract one matrix from another
A := A - B
created -- 98may01, cca
----------------------------
*/
void
A2_sub (
A2 *A,
A2 *B
) ;
/*
---------------------------
swap two rows of the matrix
created -- 98may01, cca
---------------------------
*/
void
A2_swapRows (
A2 *a,
int irow1,
int irow2
) ;
/*
------------------------------
swap two columns of the matrix
created -- 98may01, cca
------------------------------
*/
void
A2_swapColumns (
A2 *a,
int jcol1,
int jcol2
) ;
/*
------------------------------------------------------------------------
----- methods found in IO.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------
purpose -- to read in the object from a file
input --
fn -- filename, must be *.a2b or *.a2f
return value -- 1 if success, 0 if failure
created -- 98may01, cca
--------------------------------------------
*/
int
A2_readFromFile (
A2 *mtx,
char *fn
) ;
/*
--------------------------------------------------
purpose -- to read an object from a formatted file
return value -- 1 if success, 0 if failure
created -- 98may01, cca
--------------------------------------------------
*/
int
A2_readFromFormattedFile (
A2 *mtx,
FILE *fp
) ;
/*
-----------------------------------------------
purpose -- to read an object from a binary file
return value -- 1 if success, 0 if failure
created -- 98may01, cca
-----------------------------------------------
*/
int
A2_readFromBinaryFile (
A2 *mtx,
FILE *fp
) ;
/*
---------------------------------------
purpose -- to write an object to a file
input --
fn -- filename
*.a2b -- binary
*.a2f -- formatted
anything else -- for human eye
created -- 98may01, cca
---------------------------------------
*/
void
A2_writeToFile (
A2 *mtx,
char *fn
) ;
/*
-------------------------------------------------
purpose -- to write an object to a formatted file
created -- 98may01, cca
-------------------------------------------------
*/
void
A2_writeToFormattedFile (
A2 *mtx,
FILE *fp
) ;
/*
--------------------------------------------------------
purpose -- to write an adjacency object to a binary file
created -- 98may01, cca
--------------------------------------------------------
*/
void
A2_writeToBinaryFile (
A2 *mtx,
FILE *fp
) ;
/*
----------------------------------------------
purpose -- to write the object for a human eye
created -- 98may01, cca
----------------------------------------------
*/
void
A2_writeForHumanEye (
A2 *mtx,
FILE *fp
) ;
/*
--------------------------------------
purpose -- to write out the statistics
created -- 98may01, cca
--------------------------------------
*/
void
A2_writeStats (
A2 *mtx,
FILE *fp
) ;
/*
-----------------------------------------------
purpose -- to write the matrix in matlab format
created -- 98may01, cca
-----------------------------------------------
*/
void
A2_writeForMatlab (
A2 *mtx,
char *mtxname,
FILE *fp
) ;
/*====================================================================*/
can be a union of the strict lower portion,
the diagonal portion, and the strict upper
A2/makefile 0100644 0002055 0007177 00000000223 06636223476 0014046 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd drivers ; make clean
cd doc ; make clean
A2/src/makefile 0100644 0002055 0007177 00000001155 06635767156 0014651 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = A2
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(copyEntriesToVector.o) \
$(OBJ).a(init.o) \
$(OBJ).a(instance.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(makeStaircase.o) \
$(OBJ).a(norms.o) \
$(OBJ).a(QRreduce.o) \
$(OBJ).a(sort.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
A2/src/makeGlobalLib 0100644 0002055 0007177 00000000646 06635760341 0015552 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
OBJ = A2
SRC = basics.c \
copyEntriesToVector.c \
init.c \
instance.c \
IO.c \
makeStaircase.c \
norms.c \
QRreduce.c \
sort.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
A2/src/IO.c 0100644 0002055 0007177 00000032510 06542251313 0013577 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../A2.h"
static const char *suffixb = ".a2b" ;
static const char *suffixf = ".a2f" ;
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
purpose -- to read in the object from a file
input --
fn -- filename, must be *.a2b or *.a2f
return value -- 1 if success, 0 if failure
created -- 98may01, cca
--------------------------------------------
*/
int
A2_readFromFile (
A2 *mtx,
char *fn
) {
FILE *fp ;
int fnlength, rc = 0, sulength ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || fn == NULL ) {
fprintf(stderr, "\n error in A2_readFromFile(%p,%s)"
"\n bad input", mtx, fn) ;
return(0) ;
}
/*
-------------
read the file
-------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "rb")) == NULL ) {
fprintf(stderr, "\n error in A2_readFromFile(%s)"
"\n unable to open file %s", fn, fn) ;
} else {
rc = A2_readFromBinaryFile(mtx, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "r")) == NULL ) {
fprintf(stderr, "\n error in A2_readFromFile(%s)"
"\n unable to open file %s", fn, fn) ;
} else {
rc = A2_readFromFormattedFile(mtx, fp) ;
fclose(fp) ;
}
} else {
fprintf(stderr, "\n error in A2_readFromFile(%s)"
"\n bad A2 file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
} else {
fprintf(stderr, "\n error in A2_readFromFile(%s)"
"\n bad A2 file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
purpose -- to read an object from a formatted file
return value -- 1 if success, 0 if failure
created -- 98may01, cca
--------------------------------------------------
*/
int
A2_readFromFormattedFile (
A2 *mtx,
FILE *fp
) {
int rc, size ;
int itemp[5] ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || fp == NULL ) {
fprintf(stderr, "\n error in A2_readFromFormattedFile(%p,%p)"
"\n bad input", mtx, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
A2_clearData(mtx) ;
/*
-----------------------------------------------------------
read in the five scalar parameters: type n1, n2, inc1, inc2
-----------------------------------------------------------
*/
if ( (rc = IVfscanf(fp, 5, itemp)) != 5 ) {
fprintf(stderr, "\n error in A2_readFromFormattedFile()"
"\n %d items of %d read\n", rc, 5) ;
return(0) ;
}
/*
---------------------
initialize the object
---------------------
*/
A2_init(mtx, itemp[0], itemp[1], itemp[2], itemp[3], itemp[4], NULL) ;
/*
----------------------------
read in the entries[] vector
----------------------------
*/
if ( (size = 1 + (mtx->n1-1)*mtx->inc1 + (mtx->n2-1)*mtx->inc2) > 0 ) {
if ( A2_IS_REAL(mtx) ) {
if ( (rc = DVfscanf(fp, size, mtx->entries)) != size ) {
fprintf(stderr, "\n error in A2_readFromFormattedFile"
"\n %d items of %d read\n", rc, size) ;
return(0) ;
}
} else if ( A2_IS_COMPLEX(mtx) ) {
if ( (rc = DVfscanf(fp, 2*size, mtx->entries)) != 2*size ) {
fprintf(stderr, "\n error in A2_readFromFormattedFile"
"\n %d items of %d read\n", rc, 2*size) ;
return(0) ;
}
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
purpose -- to read an object from a binary file
return value -- 1 if success, 0 if failure
created -- 98may01, cca
-----------------------------------------------
*/
int
A2_readFromBinaryFile (
A2 *mtx,
FILE *fp
) {
int rc, size ;
int itemp[5] ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in A2_readFromBinaryFile(%p,%p)"
"\n bad input", mtx, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
A2_clearData(mtx) ;
/*
------------------------------------------------------------
read in the five scalar parameters: type, n1, n2, inc1, inc2
------------------------------------------------------------
*/
if ( (rc = fread((char *) itemp, sizeof(int), 5, fp)) != 5 ) {
fprintf(stderr, "\n error in A2_readFromBinaryFile"
"\n %d items of %d read\n", rc, 5) ;
return(0) ;
}
fprintf(stdout, "\n itemp = {%d, %d, %d, %d, %d}",
itemp[0], itemp[1], itemp[2], itemp[3], itemp[4]) ;
fflush(stdout) ;
/*
---------------------
initialize the object
---------------------
*/
A2_init(mtx, itemp[0], itemp[1], itemp[2], itemp[3], itemp[4], NULL) ;
/*
----------------------------
read in the entries[] vector
----------------------------
*/
if ( (size = 1 + (mtx->n1-1)*mtx->inc1 + (mtx->n2-1)*mtx->inc2) > 0 ) {
if ( A2_IS_REAL(mtx) ) {
if ( (rc = fread(mtx->entries, sizeof(double), size, fp))
!= size ) {
fprintf(stderr, "\n error in A2_readFromBinaryFile"
"\n %d items of %d read\n", rc, size) ;
return(0) ;
}
} else if ( A2_IS_COMPLEX(mtx) ) {
if ( (rc = fread(mtx->entries, sizeof(double), 2*size, fp))
!= 2*size ) {
fprintf(stderr, "\n error in A2_readFromBinaryFile"
"\n %d items of %d read\n", rc, 2*size) ;
return(0) ;
}
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------
purpose -- to write an object to a file
input --
fn -- filename
*.a2b -- binary
*.a2f -- formatted
anything else -- for human eye
created -- 98may01, cca
---------------------------------------
*/
void
A2_writeToFile (
A2 *mtx,
char *fn
) {
FILE *fp ;
int fnlength, sulength ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || fn == NULL ) {
fprintf(stderr, "\n fatal error in A2_writeToFile(%p,%s)"
"\n bad input", mtx, fn) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in A2_writeToFile()"
"\n unable to open file %s", fn) ;
} else {
A2_writeToBinaryFile(mtx, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "w")) == NULL ) {
fprintf(stderr, "\n error in A2_writeToFile()"
"\n unable to open file %s", fn) ;
} else {
A2_writeToFormattedFile(mtx, fp) ;
fclose(fp) ;
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in A2_writeToFile()"
"\n unable to open file %s", fn) ;
} else {
A2_writeForHumanEye(mtx, fp) ;
fclose(fp) ;
}
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in A2_writeToFile"
"\n unable to open file %s", fn) ;
} else {
A2_writeForHumanEye(mtx, fp) ;
fclose(fp) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to write an object to a formatted file
created -- 98may01, cca
-------------------------------------------------
*/
void
A2_writeToFormattedFile (
A2 *mtx,
FILE *fp
) {
int size ;
if ( mtx == NULL || fp == NULL ) {
return ;
}
fprintf(fp, "\n %d %d %d %d %d",
mtx->type, mtx->n1, mtx->n2, mtx->inc1, mtx->inc2) ;
if ( (size = 1 + (mtx->n1-1)*mtx->inc1 + (mtx->n2-1)*mtx->inc2) > 0
&& mtx->entries != NULL ) {
if ( A2_IS_REAL(mtx) ) {
DVfprintf(fp, size, mtx->entries) ;
} else if ( A2_IS_COMPLEX(mtx) ) {
DVfprintf(fp, 2*size, mtx->entries) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- to write an adjacency object to a binary file
created -- 98may01, cca
--------------------------------------------------------
*/
void
A2_writeToBinaryFile (
A2 *mtx,
FILE *fp
) {
int size ;
if ( fp == NULL ) {
return ;
}
fwrite((void *) &mtx->type, sizeof(int), 1, fp) ;
fwrite((void *) &mtx->n1, sizeof(int), 1, fp) ;
fwrite((void *) &mtx->n2, sizeof(int), 1, fp) ;
fwrite((void *) &mtx->inc1, sizeof(int), 1, fp) ;
fwrite((void *) &mtx->inc2, sizeof(int), 1, fp) ;
if ( (size = 1 + (mtx->n1-1)*mtx->inc1 + (mtx->n2-1)*mtx->inc2) > 0
&& mtx->entries != NULL ) {
if ( A2_IS_REAL(mtx) ) {
fwrite((void *) &mtx->entries, sizeof(double), size, fp) ;
} else if ( A2_IS_COMPLEX(mtx) ) {
fwrite((void *) &mtx->entries, sizeof(double), 2*size, fp) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
purpose -- to write the object for a human eye
created -- 98may01, cca
----------------------------------------------
*/
void
A2_writeForHumanEye (
A2 *mtx,
FILE *fp
) {
int i, j, jfirst, jlast, loc ;
if ( mtx == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in A2_writeForHumanEye(%p,%p)"
"\n bad input\n", mtx, fp) ;
exit(-1) ;
}
A2_writeStats(mtx, fp) ;
if ( A2_IS_REAL(mtx) ) {
for ( jfirst = 0 ; jfirst < mtx->n2 ; jfirst += 4 ) {
jlast = jfirst + 3 ;
if ( jlast >= mtx->n2 ) {
jlast = mtx->n2 - 1 ;
}
fprintf(fp, "\n ") ;
for ( j = jfirst ; j <= jlast ; j++ ) {
fprintf(fp, "%19d", j) ;
}
for ( i = 0 ; i < mtx->n1 ; i++ ) {
fprintf(fp, "\n%4d", i) ;
for ( j = jfirst ; j <= jlast ; j++ ) {
fprintf(fp, "%19.11e",
mtx->entries[i*mtx->inc1 + j*mtx->inc2]) ;
}
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( jfirst = 0 ; jfirst < mtx->n2 ; jfirst += 2 ) {
jlast = jfirst + 1 ;
if ( jlast >= mtx->n2 ) {
jlast = mtx->n2 - 1 ;
}
fprintf(fp, "\n ") ;
for ( j = jfirst ; j <= jlast ; j++ ) {
fprintf(fp, "%36d", j) ;
}
for ( i = 0 ; i < mtx->n1 ; i++ ) {
fprintf(fp, "\n%4d", i) ;
for ( j = jfirst ; j <= jlast ; j++ ) {
loc = 2*(i*mtx->inc1 + j*mtx->inc2) ;
fprintf(fp, " (%16.9e,%16.9e*i)",
mtx->entries[loc], mtx->entries[loc+1]) ;
}
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
purpose -- to write out the statistics
created -- 98may01, cca
--------------------------------------
*/
void
A2_writeStats (
A2 *mtx,
FILE *fp
) {
if ( mtx == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in A2_writeStats(%p,%p)"
"\n bad input\n", mtx, fp) ;
exit(-1) ;
}
if ( A2_IS_REAL(mtx) ) {
fprintf(fp, "\n A2 : double 2D array object :") ;
} else if ( A2_IS_COMPLEX(mtx) ) {
fprintf(fp, "\n A2 : double complex 2D array object :") ;
}
fprintf(fp,
"\n %d x %d matrix, inc1 = %d, inc2 = %d,"
"\n nowned = %d, %d entries allocated, occupies %d bytes"
"\n entries = %p, maxabs = %20.12e",
mtx->n1, mtx->n2, mtx->inc1, mtx->inc2, mtx->nowned,
mtx->n1*mtx->n2,
A2_sizeOf(mtx), mtx->entries, A2_maxabs(mtx)) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
purpose -- to write the matrix in matlab format
created -- 98may01, cca
-----------------------------------------------
*/
void
A2_writeForMatlab (
A2 *mtx,
char *mtxname,
FILE *fp
) {
int irow, jcol, ncol, nrow ;
if ( mtx == NULL || mtxname == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in A2_writeForMatlab(%p,%p,%p)"
"\n bad input\n", mtx, mtxname, fp) ;
exit(-1) ;
}
nrow = A2_nrow(mtx) ;
ncol = A2_ncol(mtx) ;
for ( irow = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
if ( A2_IS_REAL(mtx) ) {
double value ;
A2_realEntry(mtx, irow, jcol, &value) ;
fprintf(fp, "\n %s(%d,%d) = %24.16e ;",
mtxname, irow+1, jcol+1, value) ;
} else if ( A2_IS_COMPLEX(mtx) ) {
double imag, real ;
A2_complexEntry(mtx, irow, jcol, &real, &imag) ;
fprintf(fp, "\n %s(%d,%d) = %24.16e + %24.16e*i ;",
mtxname, irow+1, jcol+1, real, imag) ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
tx->inc1 + (mtx->n2-1)*mtx->inc2) > 0 ) {
if ( A2_IS_REAL(mtx) ) {
if ( (rc = DVfscanf(fp, size, mtx->entries)) != size ) {
fprintf(stderr, "\n error in A2_readFromFoA2/src/QRreduce.c 0100644 0002055 0007177 00000102604 06643451250 0015010 0 ustar 00cleve compmath 0000040 0000006 /* QRreduce.c */
#include "../A2.h"
/*--------------------------------------------------------------------*/
static int copyIntoVec1 ( A2 *mtxA, double H0[],
int msglvl, FILE *msgFile ) ;
static double getHouseholderVector1 ( int type, int n, double H0[],
double *pbeta0, int msglvl, FILE *msgFile ) ;
static double computeW1 ( A2 *mtxA, double H0[], double W0[],
int msglvl, FILE *msgFile ) ;
static double updateA1 ( A2 *mtxA, double H0[], double beta0,
double W0[], int msglvl, FILE *msgFile ) ;
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
purpose -- compute A = QR, where Q is a product of householder
vectors, (I - beta_j v_j v_j^T). on return, v_j is
found in the lower triangle of A, v_j(j) = 1.0.
return value -- # of floating point operations
created -- 98may25, cca
--------------------------------------------------------------
*/
double
A2_QRreduce (
A2 *mtxA,
DV *workDV,
int msglvl,
FILE *msgFile
) {
A2 tempA ;
double nops ;
double beta0 ;
double *colA, *H0, *W0 ;
int inc1, inc2, jcol, lastrow, length, ncolA, nrowA, nstep ;
/*
---------------
check the input
---------------
*/
if ( mtxA == NULL || workDV == NULL
|| (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr, "\n fatal error in A2_QRreduce()"
"\n bad input\n") ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtxA) || A2_IS_COMPLEX(mtxA)) ) {
fprintf(stderr, "\n fatal error in A2_QRreduce()"
"\n matrix must be real or complex\n") ;
exit(-1) ;
}
nrowA = A2_nrow(mtxA) ;
ncolA = A2_ncol(mtxA) ;
inc1 = A2_inc1(mtxA) ;
inc2 = A2_inc2(mtxA) ;
if ( A2_IS_REAL(mtxA) ) {
DV_setSize(workDV, nrowA + ncolA) ;
H0 = DV_entries(workDV) ;
W0 = H0 + nrowA ;
} else if ( A2_IS_COMPLEX(mtxA) ) {
DV_setSize(workDV, 2*(nrowA + ncolA)) ;
H0 = DV_entries(workDV) ;
W0 = H0 + 2*nrowA ;
}
/*
-------------------------------------------------
determine the number of steps = min(ncolA, nrowA)
-------------------------------------------------
*/
nstep = (ncolA <= nrowA) ? ncolA : nrowA ;
/*
-------------------
loop over the steps
-------------------
*/
nops = 0.0 ;
for ( jcol = 0 ; jcol < nstep ; jcol++ ) {
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% jcol = %d", jcol) ;
}
/*
----------------------------------
copy the column of A into a vector
and find the last nonzero element
----------------------------------
*/
A2_subA2(&tempA, mtxA, jcol, nrowA-1, jcol, ncolA-1) ;
length = 1 + copyIntoVec1(&tempA, H0, msglvl, msgFile) ;
lastrow = jcol + length - 1 ;
if ( msglvl > 5 ) {
fprintf(msgFile,
"\n %% return from copyIntoVec1, length = %d, lastrow = %d",
length, lastrow) ;
}
/*
------------------------------
compute the Householder vector
and place into the column of A
------------------------------
*/
colA = A2_column(mtxA, jcol) ;
if ( A2_IS_REAL(mtxA) ) {
nops += getHouseholderVector1(SPOOLES_REAL, length, H0,
&beta0, msglvl, msgFile) ;
A2_subA2(&tempA, mtxA, jcol, lastrow, jcol, jcol) ;
A2_setColumn(&tempA, H0, 0) ;
H0[0] = 1.0 ;
} else if ( A2_IS_COMPLEX(mtxA) ) {
nops += getHouseholderVector1(SPOOLES_COMPLEX, length, H0,
&beta0, msglvl, msgFile) ;
A2_subA2(&tempA, mtxA, jcol, lastrow, jcol, jcol) ;
A2_setColumn(&tempA, H0, 0) ;
H0[0] = 1.0 ; H0[1] = 0.0 ;
}
if ( msglvl > 5 && jcol == 0 ) {
fprintf(msgFile, "\n %% beta0 = %12.4e;", beta0) ;
}
if ( beta0 != 0.0 && jcol + 1 < ncolA ) {
A2_subA2(&tempA, mtxA, jcol, lastrow, jcol+1, ncolA-1) ;
/*
------------------------------------------------
compute w = v^T * A(jcol:lastrow,jcol+1:nrowA-1)
------------------------------------------------
*/
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% compute w") ;
}
nops += computeW1(&tempA, H0, W0, msglvl, msgFile) ;
/*
-------------------------------------------------
update A(jcol:lastrow,jcol+1:nrowA-1) -= beta*v*w
-------------------------------------------------
*/
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% update A") ;
}
nops += updateA1(&tempA, H0, beta0, W0, msglvl, msgFile) ;
}
}
return(nops) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
copy the first column of mtxA into the vector H0[]
created -- 98may30, cca
--------------------------------------------------
*/
static int
copyIntoVec1 (
A2 *mtxA,
double H0[],
int msglvl,
FILE *msgFile
) {
double ival, rval ;
double *colA ;
int ii, inc1, irow, jj, lastrow, ncolA, nrowA ;
/*
----------------------------------
copy the column of A into a vector
and find the last nonzero element
----------------------------------
*/
nrowA = mtxA->n1 ;
ncolA = mtxA->n2 ;
inc1 = mtxA->inc1 ;
lastrow = -1 ;
colA = A2_column(mtxA, 0) ;
if ( A2_IS_REAL(mtxA) ) {
for ( irow = ii = jj = 0 ;
irow < nrowA ;
irow++, ii += inc1, jj++ ) {
rval = colA[ii] ;
if ( rval != 0.0 ) {
H0[jj] = rval ;
lastrow = irow ;
}
}
} else if ( A2_IS_COMPLEX(mtxA) ) {
for ( irow = ii = jj = 0 ;
irow < nrowA ;
irow++, ii += 2*inc1, jj += 2 ) {
rval = colA[ii] ; ival = colA[ii+1] ;
if ( rval != 0.0 || ival != 0.0 ) {
H0[jj] = rval ; H0[jj+1] = ival ;
lastrow = irow ;
}
}
}
return(lastrow) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
compute a householder transformation
(I - beta*v*v^H)x = alpha*e_1
where v[0] = 1.0
on input,
H0 contains x,
on output,
beta0 contains beta
H0[0] = alpha
H0[1:n-1] = v[1:n] ;
created -- 98may30, cca
----------------------------------------------------------------
*/
static double
getHouseholderVector1 (
int type,
int n,
double H0[],
double *pbeta0,
int msglvl,
FILE *msgFile
) {
double beta0, ifac, ival, nops, normx, rfac, rval, sigma,
sum, v0imag, v0real, y0imag, y0real ;
int ii, jj ;
/*
--------------------------------------------
compute ||H0(1:n-1)||_2^2 and the
row that contains the last nonzero entry
--------------------------------------------
*/
sigma = 0.0 ;
beta0 = 0.0 ;
nops = 0.0 ;
if ( type == SPOOLES_REAL ) {
for ( ii = 1 ; ii < n ; ii++ ) {
rval = H0[ii] ;
sigma += rval*rval ;
}
nops += 2*(n-1) ;
} else if ( type == SPOOLES_COMPLEX ) {
for ( ii = 1, jj = 2 ; ii < n ; ii++, jj += 2 ) {
rval = H0[jj] ; ival = H0[jj+1] ;
sigma += rval*rval + ival*ival ;
}
nops += 4*(n-1) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% sigma = %12.4e", sigma) ;
}
if ( sigma != 0.0 ) {
/*
--------------------------------------------
there are nonzero entries below the diagonal
--------------------------------------------
*/
if ( type == SPOOLES_REAL ) {
rval = H0[0] ;
if ( rval == 0.0 ) {
normx = sqrt(sigma) ;
v0real = normx ;
y0real = - normx ;
nops++ ;
} else {
normx = sqrt(sigma + rval*rval) ;
rfac = normx/fabs(rval) ;
v0real = rval*(1 + rfac) ;
y0real = -rfac*rval ;
nops += 7 ;
}
} else if ( type == SPOOLES_COMPLEX ) {
rval = H0[0] ; ival = H0[1] ;
if ( rval == 0.0 && ival == 0.0 ) {
normx = sqrt(sigma) ;
v0real = normx ; v0imag = 0.0 ;
y0real = - normx ; y0imag = 0.0 ;
nops += 2 ;
} else {
normx = sqrt(sigma + rval*rval + ival*ival) ;
rfac = normx/Zabs(rval, ival) ;
v0real = rval + rfac*rval ; v0imag = ival + rfac*ival ;
y0real = -rfac*rval ; y0imag = -rfac*ival ;
nops += 16 ;
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% normx = %12.4e", normx) ;
}
/*
-------------------------------------
scale u so u1 = 1.0 and compute beta0
-------------------------------------
*/
if ( type == SPOOLES_REAL ) {
rfac = 1./v0real ;
for ( ii = 1 ; ii < n ; ii++ ) {
H0[ii] *= rfac ;
}
sum = 1.0 ;
for ( ii = 1 ; ii < n ; ii++ ) {
rval = H0[ii] ;
sum += rval*rval ;
}
nops += 3*(n-1) ;
beta0 = 2./sum ;
/*
rfac = 1./v0real ;
sum = 1.0 ;
for ( ii = 1 ; ii < n ; ii++ ) {
rval = H0[ii] = rfac*H0[ii] ;
sum += rval*rval ;
}
nops += 3*(n-1) ;
beta0 = 2./sum ;
*/
} else if ( type == SPOOLES_COMPLEX ) {
Zrecip(v0real, v0imag, &rfac, &ifac) ;
sum = 1.0 ;
for ( ii = 1, jj = 2 ; ii < n ; ii++, jj += 2 ) {
rval = H0[jj] ; ival = H0[jj+1] ;
H0[jj] = rfac*rval - ifac*ival ;
H0[jj+1] = rfac*ival + ifac*rval ;
rval = H0[jj] ; ival = H0[jj+1] ;
sum += rval*rval + ival*ival ;
}
nops += 10*(n-1) + 5 ;
beta0 = 2./sum ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% sum = %12.4e, beta0 = %12.4e",
sum, beta0) ;
}
/*
---------------------------------------------
set the first entry of the transformed column
---------------------------------------------
*/
if ( type == SPOOLES_REAL ) {
H0[0] = y0real ;
} else if ( type == SPOOLES_COMPLEX ) {
H0[0] = y0real ; H0[1] = y0imag ;
}
}
*pbeta0 = beta0 ;
/*
fprintf(msgFile, "\n H0") ;
DVfprintf(msgFile, n, H0) ;
*/
return(nops) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
compute W0 = v^H * A
created -- 98may30, cca
-----------------------
*/
static double
computeW1 (
A2 *mtxA,
double H0[],
double W0[],
int msglvl,
FILE *msgFile
) {
double nops ;
int inc1, inc2, ncolA, nrowA ;
if ( msglvl > 5 ) {
fprintf(msgFile, "\n %% inside computeW1, nrow %d, ncol %d",
mtxA->n1, mtxA->n2) ;
}
nrowA = mtxA->n1 ;
ncolA = mtxA->n2 ;
inc1 = mtxA->inc1 ;
inc2 = mtxA->inc2 ;
if ( inc1 != 1 && inc2 != 1 ) {
fprintf(stderr, "\n error in computeW1"
"\n inc1 = %d, inc2 = %d\n", inc1, inc2) ;
exit(-1) ;
}
nops = 0.0 ;
if ( A2_IS_REAL(mtxA) ) {
int irow, jcol ;
if ( inc1 == 1 ) {
double sums[3] ;
double *colA0, *colA1, *colA2 ;
/*
----------------------------
A is column major,
compute W(j) = H0^T * A(*,j)
----------------------------
*/
for ( jcol = 0 ; jcol < ncolA - 2 ; jcol += 3 ) {
colA0 = A2_column(mtxA, jcol) ;
colA1 = A2_column(mtxA, jcol+1) ;
colA2 = A2_column(mtxA, jcol+2) ;
DVdot13(nrowA, H0, colA0, colA1, colA2, sums) ;
W0[jcol] = sums[0] ;
W0[jcol+1] = sums[1] ;
W0[jcol+2] = sums[2] ;
nops += 6*nrowA ;
}
if ( jcol == ncolA - 2 ) {
colA0 = A2_column(mtxA, jcol) ;
colA1 = A2_column(mtxA, jcol+1) ;
DVdot12(nrowA, H0, colA0, colA1, sums) ;
W0[jcol] = sums[0] ;
W0[jcol+1] = sums[1] ;
nops += 4*nrowA ;
} else if ( jcol == ncolA - 1 ) {
colA0 = A2_column(mtxA, jcol) ;
DVdot11(nrowA, H0, colA0, sums) ;
W0[jcol] = sums[0] ;
nops += 2*nrowA ;
}
} else {
double alpha[3] ;
double *rowA0, *rowA1, *rowA2 ;
/*
-------------------------------
A is row major
compute W := W + H0(j) * A(j,*)
-------------------------------
*/
DVzero(ncolA, W0) ;
for ( irow = 0 ; irow < nrowA - 2 ; irow += 3 ) {
rowA0 = A2_row(mtxA, irow) ;
rowA1 = A2_row(mtxA, irow+1) ;
rowA2 = A2_row(mtxA, irow+2) ;
alpha[0] = H0[irow] ;
alpha[1] = H0[irow+1] ;
alpha[2] = H0[irow+2] ;
DVaxpy13(ncolA, W0, alpha, rowA0, rowA1, rowA2) ;
nops += 6*ncolA ;
}
if ( irow == nrowA - 2 ) {
rowA0 = A2_row(mtxA, irow) ;
rowA1 = A2_row(mtxA, irow+1) ;
alpha[0] = H0[irow] ;
alpha[1] = H0[irow+1] ;
DVaxpy12(ncolA, W0, alpha, rowA0, rowA1) ;
nops += 4*ncolA ;
} else if ( irow == nrowA - 1 ) {
rowA0 = A2_row(mtxA, irow) ;
alpha[0] = H0[irow] ;
DVaxpy11(ncolA, W0, alpha, rowA0) ;
nops += 2*ncolA ;
}
}
} else if ( A2_IS_COMPLEX(mtxA) ) {
int irow, jcol ;
if ( inc1 == 1 ) {
double sums[6] ;
double *colA0, *colA1, *colA2 ;
/*
----------------------------
A is column major
compute W(j) = H0^H * A(*,j)
----------------------------
*/
for ( jcol = 0 ; jcol < ncolA - 2 ; jcol += 3 ) {
colA0 = A2_column(mtxA, jcol) ;
colA1 = A2_column(mtxA, jcol+1) ;
colA2 = A2_column(mtxA, jcol+2) ;
ZVdotC13(nrowA, H0, colA0, colA1, colA2, sums) ;
W0[2*jcol] = sums[0] ; W0[2*jcol+1] = sums[1] ;
W0[2*(jcol+1)] = sums[2] ; W0[2*(jcol+1)+1] = sums[3] ;
W0[2*(jcol+2)] = sums[4] ; W0[2*(jcol+2)+1] = sums[5] ;
nops += 24*nrowA ;
}
if ( jcol == ncolA - 2 ) {
colA0 = A2_column(mtxA, jcol) ;
colA1 = A2_column(mtxA, jcol+1) ;
ZVdotC12(nrowA, H0, colA0, colA1, sums) ;
W0[2*jcol] = sums[0] ; W0[2*jcol+1] = sums[1] ;
W0[2*(jcol+1)] = sums[2] ; W0[2*(jcol+1)+1] = sums[3] ;
nops += 16*nrowA ;
} else if ( jcol == ncolA - 1 ) {
colA0 = A2_column(mtxA, jcol) ;
ZVdotC11(nrowA, H0, colA0, sums) ;
W0[2*jcol] = sums[0] ; W0[2*jcol+1] = sums[1] ;
nops += 8*nrowA ;
}
} else {
double alpha[6] ;
double *rowA0, *rowA1, *rowA2 ;
/*
---------------------------------
A is row major
compute W := W + H0(j)^H * A(j,*)
---------------------------------
*/
DVzero(2*ncolA, W0) ;
for ( irow = 0 ; irow < nrowA - 2 ; irow += 3 ) {
rowA0 = A2_row(mtxA, irow) ;
rowA1 = A2_row(mtxA, irow+1) ;
rowA2 = A2_row(mtxA, irow+2) ;
alpha[0] = H0[2*irow] ; alpha[1] = -H0[2*irow+1] ;
alpha[2] = H0[2*(irow+1)] ; alpha[3] = -H0[2*(irow+1)+1] ;
alpha[4] = H0[2*(irow+2)] ; alpha[5] = -H0[2*(irow+2)+1] ;
ZVaxpy13(ncolA, W0, alpha, rowA0, rowA1, rowA2) ;
nops += 24*ncolA ;
}
if ( irow == nrowA - 2 ) {
rowA0 = A2_row(mtxA, irow) ;
rowA1 = A2_row(mtxA, irow+1) ;
alpha[0] = H0[2*irow] ; alpha[1] = -H0[2*irow+1] ;
alpha[2] = H0[2*(irow+1)] ; alpha[3] = -H0[2*(irow+1)+1] ;
ZVaxpy12(ncolA, W0, alpha, rowA0, rowA1) ;
nops += 16*ncolA ;
} else if ( irow == nrowA - 1 ) {
rowA0 = A2_row(mtxA, irow) ;
alpha[0] = H0[2*irow] ; alpha[1] = -H0[2*irow+1] ;
ZVaxpy11(ncolA, W0, alpha, rowA0) ;
nops += 8*ncolA ;
}
}
}
return(nops) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------
compute A := A - H0 * beta0 * W0
created -- 98may30, cca
---------------------------------
*/
static double
updateA1 (
A2 *mtxA,
double H0[],
double beta0,
double W0[],
int msglvl,
FILE *msgFile
) {
double nops ;
int inc1, inc2, ncolA, nrowA ;
if ( msglvl > 5 ) {
fprintf(msgFile, "\n %% inside updateA1, nrow %d, ncol %d",
mtxA->n1, mtxA->n2) ;
}
nrowA = mtxA->n1 ;
ncolA = mtxA->n2 ;
inc1 = mtxA->inc1 ;
inc2 = mtxA->inc2 ;
nops = 0.0 ;
if ( A2_IS_REAL(mtxA) ) {
int irow, jcol ;
if ( inc1 == 1 ) {
double alpha[3] ;
double *colA0, *colA1, *colA2 ;
/*
-----------------------------------------
A is column major
compute A(:,jcol) -= beta * W0(jcol) * H0
-----------------------------------------
*/
for ( jcol = 0 ; jcol < ncolA - 2 ; jcol += 3 ) {
colA0 = A2_column(mtxA, jcol) ;
colA1 = A2_column(mtxA, jcol+1) ;
colA2 = A2_column(mtxA, jcol+2) ;
alpha[0] = -beta0 * W0[jcol] ;
alpha[1] = -beta0 * W0[jcol+1] ;
alpha[2] = -beta0 * W0[jcol+2] ;
DVaxpy31(nrowA, colA0, colA1, colA2, alpha, H0) ;
nops += 6*nrowA ;
}
if ( jcol == ncolA - 2 ) {
colA0 = A2_column(mtxA, jcol) ;
colA1 = A2_column(mtxA, jcol+1) ;
alpha[0] = -beta0 * W0[jcol] ;
alpha[1] = -beta0 * W0[jcol+1] ;
DVaxpy21(nrowA, colA0, colA1, alpha, H0) ;
nops += 4*nrowA ;
} else if ( jcol == ncolA - 1 ) {
colA0 = A2_column(mtxA, jcol) ;
alpha[0] = -beta0 * W0[jcol] ;
DVaxpy11(nrowA, colA0, alpha, H0) ;
nops += 2*nrowA ;
}
} else {
double alpha[3] ;
double *rowA0, *rowA1, *rowA2 ;
/*
-----------------------------------------
A is row major
compute A(irow,:) -= H0[irow]*beta0*W0(:)
-----------------------------------------
*/
for ( irow = 0 ; irow < nrowA - 2 ; irow += 3 ) {
rowA0 = A2_row(mtxA, irow) ;
rowA1 = A2_row(mtxA, irow+1) ;
rowA2 = A2_row(mtxA, irow+2) ;
alpha[0] = -beta0 * H0[irow] ;
alpha[1] = -beta0 * H0[irow+1] ;
alpha[2] = -beta0 * H0[irow+2] ;
DVaxpy31(ncolA, rowA0, rowA1, rowA2, alpha, W0) ;
nops += 6*ncolA + 3 ;
}
if ( irow == nrowA - 2 ) {
rowA0 = A2_row(mtxA, irow) ;
rowA1 = A2_row(mtxA, irow+1) ;
alpha[0] = -beta0 * H0[irow] ;
alpha[1] = -beta0 * H0[irow+1] ;
DVaxpy21(ncolA, rowA0, rowA1, alpha, W0) ;
nops += 4*ncolA + 2 ;
} else if ( irow == nrowA - 1 ) {
rowA0 = A2_row(mtxA, irow) ;
alpha[0] = -beta0 * H0[irow] ;
DVaxpy11(ncolA, rowA0, alpha, W0) ;
nops += 2*ncolA + 1 ;
}
}
} else if ( A2_IS_COMPLEX(mtxA) ) {
int irow, jcol ;
if ( inc1 == 1 ) {
double alpha[6] ;
double *colA0, *colA1, *colA2 ;
/*
-----------------------------------------
A is column major
compute A(:,jcol) -= beta * W0(jcol) * H0
-----------------------------------------
*/
for ( jcol = 0 ; jcol < ncolA - 2 ; jcol += 3 ) {
colA0 = A2_column(mtxA, jcol) ;
colA1 = A2_column(mtxA, jcol+1) ;
colA2 = A2_column(mtxA, jcol+2) ;
alpha[0] = -beta0 * W0[2*jcol] ;
alpha[1] = -beta0 * W0[2*jcol+1] ;
alpha[2] = -beta0 * W0[2*(jcol+1)] ;
alpha[3] = -beta0 * W0[2*(jcol+1)+1] ;
alpha[4] = -beta0 * W0[2*(jcol+2)] ;
alpha[5] = -beta0 * W0[2*(jcol+2)+1] ;
ZVaxpy31(nrowA, colA0, colA1, colA2, alpha, H0) ;
nops += 24*nrowA ;
}
if ( jcol == ncolA - 2 ) {
colA0 = A2_column(mtxA, jcol) ;
colA1 = A2_column(mtxA, jcol+1) ;
alpha[0] = -beta0 * W0[2*jcol] ;
alpha[1] = -beta0 * W0[2*jcol+1] ;
alpha[2] = -beta0 * W0[2*(jcol+1)] ;
alpha[3] = -beta0 * W0[2*(jcol+1)+1] ;
ZVaxpy21(nrowA, colA0, colA1, alpha, H0) ;
nops += 16*nrowA ;
} else if ( jcol == ncolA - 1 ) {
colA0 = A2_column(mtxA, jcol) ;
alpha[0] = -beta0 * W0[2*jcol] ;
alpha[1] = -beta0 * W0[2*jcol+1] ;
ZVaxpy11(nrowA, colA0, alpha, H0) ;
nops += 8*nrowA ;
}
} else {
double alpha[6] ;
double *rowA0, *rowA1, *rowA2 ;
/*
-----------------------------------------
A is row major
compute A(irow,:) -= H0[irow]*beta0*W0(:)
-----------------------------------------
*/
for ( irow = 0 ; irow < nrowA - 2 ; irow += 3 ) {
rowA0 = A2_row(mtxA, irow) ;
rowA1 = A2_row(mtxA, irow+1) ;
rowA2 = A2_row(mtxA, irow+2) ;
alpha[0] = -beta0 * H0[2*irow] ;
alpha[1] = -beta0 * H0[2*irow+1] ;
alpha[2] = -beta0 * H0[2*(irow+1)] ;
alpha[3] = -beta0 * H0[2*(irow+1)+1] ;
alpha[4] = -beta0 * H0[2*(irow+2)] ;
alpha[5] = -beta0 * H0[2*(irow+2)+1] ;
ZVaxpy31(ncolA, rowA0, rowA1, rowA2, alpha, W0) ;
nops += 24*ncolA + 12 ;
}
if( irow == nrowA - 2 ) {
rowA0 = A2_row(mtxA, irow) ;
rowA1 = A2_row(mtxA, irow+1) ;
alpha[0] = -beta0 * H0[2*irow] ;
alpha[1] = -beta0 * H0[2*irow+1] ;
alpha[2] = -beta0 * H0[2*(irow+1)] ;
alpha[3] = -beta0 * H0[2*(irow+1)+1] ;
ZVaxpy21(ncolA, rowA0, rowA1, alpha, W0) ;
nops += 16*ncolA + 8 ;
} else if( irow == nrowA - 1 ) {
rowA0 = A2_row(mtxA, irow) ;
alpha[0] = -beta0 * H0[2*irow] ;
alpha[1] = -beta0 * H0[2*irow+1] ;
ZVaxpy11(ncolA, rowA0, alpha, W0) ;
nops += 8*ncolA + 4 ;
}
}
}
return(nops) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
A contains the following data from the A = QR factorization
A(1:ncolA,1:ncolA) = R
A(j+1:nrowA,j) is v_j, the j-th householder vector,
where v_j[j] = 1.0
NOTE: A and Q must be column major
created -- 98dec10, cca
-----------------------------------------------------------
*/
void
A2_computeQ (
A2 *Q,
A2 *A,
DV *workDV,
int msglvl,
FILE *msgFile
) {
double *betas ;
int irowA, jcolA, ncolA, nrowA ;
/*
---------------
check the input
---------------
*/
if ( Q == NULL ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n Q is NULL\n") ;
exit(-1) ;
}
if ( A == NULL ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n A is NULL\n") ;
exit(-1) ;
}
if ( workDV == NULL ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n workDV is NULL\n") ;
exit(-1) ;
}
if ( msglvl > 0 && msgFile == NULL ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n msglvl > 0 and msgFile is NULL\n") ;
exit(-1) ;
}
nrowA = A2_nrow(A) ;
ncolA = A2_ncol(A) ;
if ( nrowA <= 0 ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n nrowA = %d\n", nrowA) ;
exit(-1) ;
}
if ( ncolA <= 0 ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n ncolA = %d\n", nrowA) ;
exit(-1) ;
}
if ( nrowA != A2_nrow(Q) ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n nrowA = %d, nrowQ = %d\n", nrowA, A2_nrow(Q)) ;
exit(-1) ;
}
if ( ncolA != A2_ncol(Q) ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n ncolA = %d, ncolQ = %d\n", ncolA, A2_ncol(Q)) ;
exit(-1) ;
}
switch ( A->type ) {
case SPOOLES_REAL :
case SPOOLES_COMPLEX :
break ;
default :
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n invalid type for A\n") ;
exit(-1) ;
}
if ( A->type != Q->type ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n A->type = %d, Q->type = %d\n", A->type, Q->type) ;
exit(-1) ;
}
if ( A2_inc1(A) != 1 ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n A->inc1 = %d \n", A2_inc1(A)) ;
exit(-1) ;
}
if ( A2_inc1(Q) != 1 ) {
fprintf(stderr, "\n fatal error in A2_computeQ()"
"\n Q->inc1 = %d, \n", A2_inc1(Q)) ;
exit(-1) ;
}
/*
--------------------------------------------------
compute the beta values, beta_j = 2./(V_j^H * V_j)
--------------------------------------------------
*/
DV_setSize(workDV, ncolA) ;
betas = DV_entries(workDV) ;
if ( A2_IS_REAL(A) ) {
int irowA, jcolA ;
double sum ;
double *colA ;
for ( jcolA = 0 ; jcolA < ncolA ; jcolA++ ) {
sum = 1.0 ;
colA = A2_column(A, jcolA) ;
for ( irowA = jcolA + 1 ; irowA < nrowA ; irowA++ ) {
sum += colA[irowA] * colA[irowA] ;
}
betas[jcolA] = 2./sum ;
}
} else {
double ival, rval, sum ;
double *colA ;
for ( jcolA = 0 ; jcolA < ncolA ; jcolA++ ) {
sum = 1.0 ;
colA = A2_column(A, jcolA) ;
for ( irowA = jcolA + 1 ; irowA < nrowA ; irowA++ ) {
rval = colA[2*irowA] ; ival = colA[2*irowA+1] ;
sum += rval*rval + ival*ival ;
}
betas[jcolA] = 2./sum ;
}
}
/*
-------------------------------------------
loop over the number of householder vectors
-------------------------------------------
*/
for ( jcolA = 0 ; jcolA < ncolA ; jcolA++ ) {
double *V, *X ;
int jcolV ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n %% jcolA = %d", jcolA) ;
fflush(msgFile) ;
}
/*
------------------
set X[] to e_jcolA
------------------
*/
X = A2_column(Q, jcolA) ;
if ( A2_IS_REAL(Q) ) {
DVzero(nrowA, X) ;
X[jcolA] = 1.0 ;
} else {
DVzero(2*nrowA, X) ;
X[2*jcolA] = 1.0 ;
}
for ( jcolV = jcolA ; jcolV >= 0 ; jcolV-- ) {
double beta ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% jcolV = %d", jcolV) ;
fflush(msgFile) ;
}
/*
-----------------------------------------------------
update X = (I - beta_jcolV * V_jcolV * V_jcolV^T)X
= X - beta_jcolV * V_jcolV * V_jcolV^T * X
= X - (beta_jcolV * V_jcolV^T * X) * V_jcolV
-----------------------------------------------------
*/
V = A2_column(A, jcolV) ;
beta = betas[jcolV] ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% beta = %12.4e", beta) ;
fflush(msgFile) ;
}
if ( A2_IS_REAL(Q) ) {
double fac, sum = X[jcolV] ;
int irow ;
for ( irow = jcolV + 1 ; irow < nrowA ; irow++ ) {
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n %% V[%d] = %12.4e, X[%d] = %12.4e",
irow, V[irow], irow, X[irow]) ;
fflush(msgFile) ;
}
sum += V[irow] * X[irow] ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% sum = %12.4e", sum) ;
fflush(msgFile) ;
}
fac = beta * sum ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% fac = %12.4e", fac) ;
fflush(msgFile) ;
}
X[jcolV] -= fac ;
for ( irow = jcolV + 1 ; irow < nrowA ; irow++ ) {
X[irow] -= fac * V[irow] ;
}
} else {
double rfac, ifac, rsum = X[2*jcolV], isum = X[2*jcolV+1] ;
int irow ;
for ( irow = jcolV + 1 ; irow < nrowA ; irow++ ) {
double Vi, Vr, Xi, Xr ;
Vr = V[2*irow] ; Vi = V[2*irow+1] ;
Xr = X[2*irow] ; Xi = X[2*irow+1] ;
rsum += Vr*Xr + Vi*Xi ;
isum += Vr*Xi - Vi*Xr ;
}
rfac = beta * rsum ;
ifac = beta * isum ;
X[2*jcolV] -= rfac ;
X[2*jcolV+1] -= ifac ;
for ( irow = jcolV + 1 ; irow < nrowA ; irow++ ) {
double Vi, Vr ;
Vr = V[2*irow] ; Vi = V[2*irow+1] ;
X[2*irow] -= rfac*Vr - ifac*Vi ;
X[2*irow+1] -= rfac*Vi + ifac*Vr ;
}
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
A contains the following data from the A = QR factorization
A(1:ncolA,1:ncolA) = R
A(j+1:nrowA,j) is v_j, the j-th householder vector,
where v_j[j] = 1.0
we compute Y = Q^T X when A is real
and Y = Q^H X when A is complex
NOTE: A, Y and X must be column major.
NOTE: Y and X can be the same object,
in which case X is overwritten with Y
created -- 98dec10, cca
-----------------------------------------------------------
*/
void
A2_applyQT (
A2 *Y,
A2 *A,
A2 *X,
DV *workDV,
int msglvl,
FILE *msgFile
) {
double *betas ;
int irowA, jcolA, jcolX, ncolA, ncolX, nrowA ;
/*
---------------
check the input
---------------
*/
if ( A == NULL ) {
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n A is NULL\n") ;
exit(-1) ;
}
if ( X == NULL ) {
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n X is NULL\n") ;
exit(-1) ;
}
if ( workDV == NULL ) {
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n workDV is NULL\n") ;
exit(-1) ;
}
if ( msglvl > 0 && msgFile == NULL ) {
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n msglvl > 0 and msgFile is NULL\n") ;
exit(-1) ;
}
nrowA = A2_nrow(A) ;
ncolA = A2_ncol(A) ;
ncolX = A2_ncol(X) ;
if ( nrowA <= 0 ) {
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n nrowA = %d\n", nrowA) ;
exit(-1) ;
}
if ( ncolA <= 0 ) {
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n ncolA = %d\n", nrowA) ;
exit(-1) ;
}
if ( nrowA != A2_nrow(X) ) {
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n nrowA = %d, nrowX = %d\n", nrowA, A2_nrow(X)) ;
exit(-1) ;
}
switch ( A->type ) {
case SPOOLES_REAL :
case SPOOLES_COMPLEX :
break ;
default :
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n invalid type for A\n") ;
exit(-1) ;
}
if ( A->type != X->type ) {
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n A->type = %d, X->type = %d\n", A->type, X->type) ;
exit(-1) ;
}
if ( A2_inc1(A) != 1 ) {
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n A->inc1 = %d \n", A2_inc1(A)) ;
exit(-1) ;
}
if ( A2_inc1(X) != 1 ) {
fprintf(stderr, "\n fatal error in A2_applyQT()"
"\n X->inc1 = %d, \n", A2_inc1(X)) ;
exit(-1) ;
}
/*
--------------------------------------------------
compute the beta values, beta_j = 2./(V_j^H * V_j)
--------------------------------------------------
*/
DV_setSize(workDV, ncolA) ;
betas = DV_entries(workDV) ;
if ( A2_IS_REAL(A) ) {
int irowA, jcolA ;
double sum ;
double *colA ;
for ( jcolA = 0 ; jcolA < ncolA ; jcolA++ ) {
sum = 1.0 ;
colA = A2_column(A, jcolA) ;
for ( irowA = jcolA + 1 ; irowA < nrowA ; irowA++ ) {
sum += colA[irowA] * colA[irowA] ;
}
betas[jcolA] = 2./sum ;
}
} else {
double ival, rval, sum ;
double *colA ;
for ( jcolA = 0 ; jcolA < ncolA ; jcolA++ ) {
sum = 1.0 ;
colA = A2_column(A, jcolA) ;
for ( irowA = jcolA + 1 ; irowA < nrowA ; irowA++ ) {
rval = colA[2*irowA] ; ival = colA[2*irowA+1] ;
sum += rval*rval + ival*ival ;
}
betas[jcolA] = 2./sum ;
}
}
/*
------------------------------------------
loop over the number of columns in X and Y
------------------------------------------
*/
for ( jcolX = 0 ; jcolX < ncolX ; jcolX++ ) {
double *V, *colX, *colY ;
int jcolV ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n %% jcolX = %d", jcolX) ;
fflush(msgFile) ;
}
/*
-------------------------------
copy X(:,jcolX) into Y(:,jcolX)
-------------------------------
*/
colY = A2_column(Y, jcolX) ;
colX = A2_column(X, jcolX) ;
if ( A2_IS_REAL(A) ) {
DVcopy(nrowA, colY, colX) ;
} else {
DVcopy(2*nrowA, colY, colX) ;
}
for ( jcolV = 0 ; jcolV < ncolA ; jcolV++ ) {
double beta ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% jcolV = %d", jcolV) ;
fflush(msgFile) ;
}
/*
------------------------------------------------------------
update colY = (I - beta_jcolV * V_jcolV * V_jcolV^T)colY
= colY - beta_jcolV * V_jcolV * V_jcolV^T * colY
= colY - (beta_jcolV * V_jcolV^T * Y) * V_jcolV
------------------------------------------------------------
*/
V = A2_column(A, jcolV) ;
beta = betas[jcolV] ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% beta = %12.4e", beta) ;
fflush(msgFile) ;
}
if ( A2_IS_REAL(A) ) {
double fac, sum = colY[jcolV] ;
int irow ;
for ( irow = jcolV + 1 ; irow < nrowA ; irow++ ) {
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n %% V[%d] = %12.4e, X[%d] = %12.4e",
irow, V[irow], irow, colY[irow]) ;
fflush(msgFile) ;
}
sum += V[irow] * colY[irow] ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% sum = %12.4e", sum) ;
fflush(msgFile) ;
}
fac = beta * sum ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% fac = %12.4e", fac) ;
fflush(msgFile) ;
}
colY[jcolV] -= fac ;
for ( irow = jcolV + 1 ; irow < nrowA ; irow++ ) {
colY[irow] -= fac * V[irow] ;
}
} else {
double rfac, ifac,
rsum = colY[2*jcolV], isum = colY[2*jcolV+1] ;
int irow ;
for ( irow = jcolV + 1 ; irow < nrowA ; irow++ ) {
double Vi, Vr, Yi, Yr ;
Vr = V[2*irow] ; Vi = V[2*irow+1] ;
Yr = colY[2*irow] ; Yi = colY[2*irow+1] ;
rsum += Vr*Yr + Vi*Yi ;
isum += Vr*Yi - Vi*Yr ;
}
rfac = beta * rsum ;
ifac = beta * isum ;
colY[2*jcolV] -= rfac ;
colY[2*jcolV+1] -= ifac ;
for ( irow = jcolV + 1 ; irow < nrowA ; irow++ ) {
double Vi, Vr ;
Vr = V[2*irow] ; Vi = V[2*irow+1] ;
colY[2*irow] -= rfac*Vr - ifac*Vi ;
colY[2*irow+1] -= rfac*Vi + ifac*Vr ;
}
}
}
}
return ; }
/*--------------------------------------------------------------------*/
----------------------------
*/
DV_setSize(workDV, ncolA) ;
betas = DV_entries(workDV) ;
if ( A2_IS_REAL(A) ) {
int iroA2/src/basics.c 0100644 0002055 0007177 00000004317 06635766610 0014556 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../A2.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------
simplest constructor
created -- 98may01, cca
-----------------------
*/
A2 *
A2_new (
void
) {
A2 *mtx ;
ALLOCATE(mtx, struct _A2, 1) ;
A2_setDefaultFields(mtx) ;
return(mtx) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 98may01, cca
-----------------------
*/
void
A2_setDefaultFields (
A2 *mtx
) {
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_setDefaultFields(%p)"
"\n bad input", mtx) ;
exit(-1) ;
}
mtx->type = SPOOLES_REAL ;
mtx->n1 = 0 ;
mtx->inc1 = 0 ;
mtx->n2 = 0 ;
mtx->inc2 = 0 ;
mtx->nowned = 0 ;
mtx->entries = NULL ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98may01, cca
--------------------------------------------------
*/
void
A2_clearData (
A2 *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_clearData(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
/*
-------------------------------------
free the entries if present and owned
-------------------------------------
*/
if ( mtx->nowned > 0 && mtx->entries != NULL ) {
DVfree(mtx->entries) ;
}
/*
----------------------
set the default fields
----------------------
*/
A2_setDefaultFields(mtx) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
destructor, free's the object and its data
created -- 98may01, cca
------------------------------------------
*/
void
A2_free (
A2 *mtx
) {
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_free(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
A2_clearData(mtx) ;
FREE(mtx) ;
return ; }
/*--------------------------------------------------------------------*/
A2/src/copyEntriesToVector.c 0100644 0002055 0007177 00000037771 06534105763 0017310 0 ustar 00cleve compmath 0000040 0000006 /* copyEntriesToVector.c */
#include "../A2.h"
#include "../../Drand.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose -- copy entries to a vector. the portion copied
can be a union of the strict lower portion,
the diagonal portion, and the strict upper
portion. there is one restriction, if the strict
lower and strict upper are to be copied, the
diagonal will also be copied.
length -- length of dvec[]
dvec[] -- vector to receive matrix entries
copyflag -- flag to denote what part of the entries to move
A2_STRICT_LOWER --> move strict lower entries
A2_LOWER --> move lower entries (includes the diagonal)
A2_DIAGONAL --> move diagonal entries
A2_UPPER --> move upper entries (includes the diagonal)
A2_STRICT_UPPER --> move strict upper entries
A2_ALL_ENTRIES --> move all entries
storeflag -- flag to denote how to store entries in dvec[]
A2_BY_ROWS --> store by rows
A2_BY_COLUMNS --> store by columns
return value -- number of entries copied
created -- 97jun03, cca, dkw
modified -- 98may25, cca
----------------------------------------------------------------
*/
int
A2_copyEntriesToVector (
A2 *mtx,
int length,
double *dvec,
int copyflag,
int storeflag
) {
int inc1, inc2, kk, ncol, ndiag, nent, nrow ;
/*
--------------------------------------------
check the input, get dimensions and pointers
and check that length is large enough
--------------------------------------------
*/
if ( mtx == NULL || length < 0 || dvec == NULL ) {
fprintf(stderr,
"\n fatal error in A2_copyEntriesToVector(%p,%d,%p,,%d,%d)"
"\n bad input\n", mtx, length, dvec, copyflag, storeflag) ;
exit(-1) ;
}
if ( copyflag < 1 || copyflag > 6 ) {
fprintf(stderr,
"\n fatal error in A2_copyEntriesToVector(%p,%d,%p,%d,%d)"
"\n bad input\n"
"\n copyflag = %d, must be\n"
"\n 1 --> strictly lower entries"
"\n 2 --> lower entries"
"\n 3 --> diagonal entries"
"\n 4 --> strictly upper entries"
"\n 5 --> upper entries"
"\n 6 --> all entries",
mtx, length, dvec, copyflag, storeflag, copyflag) ;
exit(-1) ;
}
if ( storeflag < 0 || storeflag > 1 ) {
fprintf(stderr,
"\n fatal error in A2_copyEntriesToVector(%p,%d,%p,%d,%d)"
"\n bad input\n"
"\n storeflag = %d, must be\n"
"\n 0 --> store by rows"
"\n 1 --> store by columns",
mtx, length, dvec, copyflag, storeflag, storeflag) ;
exit(-1) ;
}
nrow = mtx->n1 ;
ncol = mtx->n2 ;
inc1 = mtx->inc1 ;
inc2 = mtx->inc2 ;
if ( nrow >= ncol ) {
ndiag = ncol ;
} else {
ndiag = nrow ;
}
/*
------------------------------------------
compute the number of entries to be copied
------------------------------------------
*/
switch ( copyflag ) {
case A2_STRICT_LOWER : /* strictly lower entries */
nent = (ndiag*(ndiag - 1))/2 + (nrow - ndiag)*ncol ;
break ;
case A2_LOWER : /* lower entries */
nent = (ndiag*(ndiag + 1))/2 + (nrow - ndiag)*ncol ;
break ;
case A2_DIAGONAL : /* diagonal entries */
nent = ndiag ;
break ;
case A2_UPPER : /* upper entries */
nent = (ndiag*(ndiag + 1))/2 + (ncol - ndiag)*nrow ;
break ;
case A2_STRICT_UPPER : /* strictly upper entries */
nent = (ndiag*(ndiag - 1))/2 + (ncol - ndiag)*nrow ;
break ;
case A2_ALL_ENTRIES : /* all entries */
nent = nrow*ncol ;
break ;
default :
break ;
}
if ( nent > length ) {
fprintf(stderr,
"\n fatal error in A2_copyEntriesToVector(%p,%d,%p,%d,%d)"
"\n nent = %d, buffer length = %d",
mtx, length, dvec, copyflag, storeflag, nent, length) ;
exit(-1) ;
}
/*
--------------------------------------------
make life simple, unit stride through dvec[]
--------------------------------------------
*/
kk = 0 ;
if ( storeflag == A2_BY_ROWS ) {
int irow, jstart, jcol, jend, jj ;
double *row ;
/*
--------------
loop over rows
--------------
*/
switch ( copyflag ) {
case A2_STRICT_LOWER :
/*
----------------------
strictly lower entries
----------------------
*/
if ( A2_IS_REAL(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < nrow ;
irow++, row += inc1 ) {
jstart = 0 ;
jend = (irow < ndiag) ? irow - 1 : ndiag - 1 ;
for ( jcol = jstart, jj = jcol*inc2 ;
jcol <= jend ;
jcol++, jj += inc2, kk++ ) {
dvec[kk] = row[jj] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < nrow ;
irow++, row += 2*inc1 ) {
jstart = 0 ;
jend = (irow < ndiag) ? irow - 1 : ndiag - 1 ;
for ( jcol = jstart, jj = jcol*inc2 ;
jcol <= jend ;
jcol++, jj += inc2, kk++ ) {
dvec[2*kk] = row[2*jj] ;
dvec[2*kk+1] = row[2*jj+1] ;
}
}
}
break ;
case A2_LOWER :
/*
------------------------------------
lower entries including the diagonal
------------------------------------
*/
if ( A2_IS_REAL(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < nrow ;
irow++, row += inc1 ) {
jstart = 0 ;
jend = (irow < ndiag) ? irow : ndiag - 1 ;
for ( jcol = jstart, jj = jcol*inc2 ;
jcol <= jend ;
jcol++, jj += inc2, kk++ ) {
dvec[kk] = row[jj] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < nrow ;
irow++, row += 2*inc1 ) {
jstart = 0 ;
jend = (irow < ndiag) ? irow : ndiag - 1 ;
for ( jcol = jstart, jj = jcol*inc2 ;
jcol <= jend ;
jcol++, jj += inc2, kk++ ) {
dvec[2*kk] = row[2*jj] ;
dvec[2*kk+1] = row[2*jj+1] ;
}
}
}
break ;
case A2_DIAGONAL :
/*
-----------------
just the diagonal
-----------------
*/
if ( A2_IS_REAL(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < ndiag ;
irow++, row += inc1, kk++ ) {
dvec[kk] = row[irow*inc2] ;
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < ndiag ;
irow++, row += 2*inc1, kk++ ) {
dvec[2*kk] = row[2*irow*inc2] ;
dvec[2*kk+1] = row[2*irow*inc2+1] ;
}
}
break ;
case A2_UPPER :
/*
------------------------------------
upper entries including the diagonal
------------------------------------
*/
if ( A2_IS_REAL(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < nrow ;
irow++, row += inc1 ) {
jstart = irow ;
jend = ncol - 1 ;
for ( jcol = jstart, jj = jcol*inc2 ;
jcol <= jend ;
jcol++, jj += inc2, kk++ ) {
dvec[kk] = row[jj] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < nrow ;
irow++, row += 2*inc1 ) {
jstart = irow ;
jend = ncol - 1 ;
for ( jcol = jstart, jj = jcol*inc2 ;
jcol <= jend ;
jcol++, jj += inc2, kk++ ) {
dvec[2*kk] = row[2*jj] ;
dvec[2*kk+1] = row[2*jj+1] ;
}
}
}
break ;
case A2_STRICT_UPPER :
/*
--------------------------
strictly the upper entries
--------------------------
*/
if ( A2_IS_REAL(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < nrow ;
irow++, row += inc1 ) {
jstart = irow + 1 ;
jend = ncol - 1 ;
for ( jcol = jstart, jj = jcol*inc2 ;
jcol <= jend ;
jcol++, jj += inc2, kk++ ) {
dvec[kk] = row[jj] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < nrow ;
irow++, row += 2*inc1 ) {
jstart = irow + 1 ;
jend = ncol - 1 ;
for ( jcol = jstart, jj = jcol*inc2 ;
jcol <= jend ;
jcol++, jj += inc2, kk++ ) {
dvec[2*kk] = row[2*jj] ;
dvec[2*kk+1] = row[2*jj+1] ;
}
}
}
break ;
case A2_ALL_ENTRIES :
/*
-----------
all entries
-----------
*/
if ( A2_IS_REAL(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < nrow ;
irow++, row += inc1 ) {
jstart = 0 ;
jend = ncol - 1 ;
for ( jcol = jstart, jj = 0 ;
jcol <= jend ;
jcol++, jj += inc2, kk++ ) {
dvec[kk] = row[jj] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( irow = 0, row = mtx->entries, kk = 0 ;
irow < nrow ;
irow++, row += 2*inc1 ) {
jstart = 0 ;
jend = ncol - 1 ;
for ( jcol = jstart, jj = 0 ;
jcol <= jend ;
jcol++, jj += inc2, kk++ ) {
dvec[2*kk] = row[2*jj] ;
dvec[2*kk+1] = row[2*jj+1] ;
}
}
}
break ;
default :
break ;
}
} else {
int iend, ii, irow, istart, jcol ;
double *col ;
/*
-----------------
loop over columns
-----------------
*/
kk = 0 ;
switch ( copyflag ) {
case A2_STRICT_LOWER :
/*
----------------------
strictly lower entries
----------------------
*/
if ( A2_IS_REAL(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ncol ;
jcol++, col += inc2 ) {
istart = jcol + 1 ;
iend = nrow - 1 ;
for ( irow = istart, ii = irow*inc1 ;
irow <= iend ;
irow++, ii += inc1, kk++ ) {
dvec[kk] = col[ii] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ncol ;
jcol++, col += 2*inc2 ) {
istart = jcol + 1 ;
iend = nrow - 1 ;
for ( irow = istart, ii = irow*inc1 ;
irow <= iend ;
irow++, ii += inc1, kk++ ) {
dvec[2*kk] = col[2*ii] ;
dvec[2*kk+1] = col[2*ii+1] ;
}
}
}
break ;
case A2_LOWER :
/*
------------------------------------
lower entries including the diagonal
------------------------------------
*/
if ( A2_IS_REAL(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ncol ;
jcol++, col += inc2 ) {
istart = jcol ;
iend = nrow - 1 ;
for ( irow = istart, ii = irow*inc1 ;
irow <= iend ;
irow++, ii += inc1, kk++ ) {
dvec[kk] = col[ii] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ncol ;
jcol++, col += 2*inc2 ) {
istart = jcol ;
iend = nrow - 1 ;
for ( irow = istart, ii = irow*inc1 ;
irow <= iend ;
irow++, ii += inc1, kk++ ) {
dvec[2*kk] = col[2*ii] ;
dvec[2*kk+1] = col[2*ii+1] ;
}
}
}
break ;
case A2_DIAGONAL :
/*
-----------------
just the diagonal
-----------------
*/
if ( A2_IS_REAL(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ndiag ;
jcol++, col += inc2, kk++ ) {
dvec[kk] = col[jcol*inc1] ;
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ndiag ;
jcol++, col += 2*inc2, kk++ ) {
dvec[2*kk] = col[2*jcol*inc1] ;
dvec[2*kk+1] = col[2*jcol*inc1+1] ;
}
}
break ;
case A2_UPPER :
/*
------------------------------------
upper entries including the diagonal
------------------------------------
*/
if ( A2_IS_REAL(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ncol ;
jcol++, col += inc2 ) {
istart = 0 ;
iend = (jcol < ndiag) ? jcol : ndiag - 1 ;
for ( irow = istart, ii = irow*inc1 ;
irow <= iend ;
irow++, ii += inc1, kk++ ) {
dvec[kk] = col[ii] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ncol ;
jcol++, col += 2*inc2 ) {
istart = 0 ;
iend = (jcol < ndiag) ? jcol : ndiag - 1 ;
for ( irow = istart, ii = irow*inc1 ;
irow <= iend ;
irow++, ii += inc1, kk++ ) {
dvec[2*kk] = col[2*ii] ;
dvec[2*kk+1] = col[2*ii+1] ;
}
}
}
break ;
case A2_STRICT_UPPER :
/*
--------------------------
strictly the upper entries
--------------------------
*/
if ( A2_IS_REAL(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ncol ;
jcol++, col += inc2 ) {
istart = 0 ;
iend = (jcol < ndiag) ? jcol - 1 : ndiag - 1 ;
for ( irow = istart, ii = irow*inc1 ;
irow <= iend ;
irow++, ii += inc1, kk++ ) {
dvec[kk] = col[ii] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ncol ;
jcol++, col += 2*inc2 ) {
istart = 0 ;
iend = (jcol < ndiag) ? jcol - 1 : ndiag - 1 ;
for ( irow = istart, ii = irow*inc1 ;
irow <= iend ;
irow++, ii += inc1, kk++ ) {
dvec[2*kk] = col[2*ii] ;
dvec[2*kk+1] = col[2*ii+1] ;
}
}
}
break ;
case A2_ALL_ENTRIES :
/*
-----------
all entries
-----------
*/
if ( A2_IS_REAL(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ncol ;
jcol++, col += inc2 ) {
istart = 0 ;
iend = nrow - 1 ;
for ( irow = istart, ii = 0 ;
irow <= iend ;
irow++, ii += inc1, kk++ ) {
dvec[kk] = col[ii] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( jcol = 0, col = mtx->entries, kk = 0 ;
jcol < ncol ;
jcol++, col += 2*inc2 ) {
istart = 0 ;
iend = nrow - 1 ;
for ( irow = istart, ii = 0 ;
irow <= iend ;
irow++, ii += inc1, kk++ ) {
dvec[2*kk] = col[2*ii] ;
dvec[2*kk+1] = col[2*ii+1] ;
}
}
}
break ;
default :
break ;
}
}
return(kk) ; }
/*--------------------------------------------------------------------*/
row ;
A2/src/init.c 0100644 0002055 0007177 00000011554 06534105763 0014250 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../A2.h"
/*====================================================================*/
/*
------------------------------------------------------------------
initializer. sets the n1, n2, inc1 and inc2 fields.
must have
mtx != NULL
type = SPOOLES_REAL or SPOOLES_COMPLEX
n1, n2, inc1, inc2 > 0
(inc1 = 1 and inc2 = nrow) or (inc1 = ncol and inc2 = 1)
if entries is NULL then
entries are allocated and zeroed.
else
mtx->nowned is set to 0
mtx->entries is set to entries.
endif
n1, n2, inc1, inc2 set
created -- 98apr15, cca
------------------------------------------------------------------
*/
void
A2_init (
A2 *mtx,
int type,
int n1,
int n2,
int inc1,
int inc2,
double *entries
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || n1 <= 0 || n2 <= 0 || inc1 <= 0 || inc2 <= 0 ) {
fprintf(stderr, "\n fatal error in A2_init(%p,%d,%d,%d,%d,%p)"
"\n bad input\n", mtx, n1, n2, inc1, inc2, entries) ;
exit(-1) ;
}
if ( type != SPOOLES_REAL && type != SPOOLES_COMPLEX ) {
fprintf(stderr, "\n fatal error in A2_init(%p,%d,%d,%d,%d,%p)"
"\n bad type %d\n",
mtx, n1, n2, inc1, inc2, entries, type) ;
exit(-1) ;
}
if ( entries == NULL
&& !( (inc1 == 1 && inc2 == n1) || (inc1 == n2 && inc2 == 1) ) ) {
/*
---------------------------------------------------------------
whoa, when we own the data we can only initialize a full matrix
---------------------------------------------------------------
*/
fprintf(stderr, "\n fatal error in A2_init(%p,%d,%d,%d,%d,%p)"
"\n entries is not NULL and we have bad increments"
"\n inc1 = %d, inc2 = %d, nrow = %d, ncol = %d\n",
mtx, n1, n2, inc1, inc2, entries,
inc1, inc2, n1, n2) ;
exit(-1) ;
}
if ( entries != NULL ) {
/*
----------------------------
set pointer to these entries
----------------------------
*/
if ( mtx->entries != NULL ) {
DVfree(mtx->entries) ;
}
mtx->nowned = 0 ;
mtx->entries = entries ;
} else {
int nbytesNeeded, nbytesPresent ;
/*
----------------------------
allocate and own the entries
----------------------------
*/
if ( mtx->type == SPOOLES_REAL ) {
nbytesPresent = mtx->nowned * sizeof(double) ;
} else if ( mtx->type == SPOOLES_COMPLEX ) {
nbytesPresent = 2 * mtx->nowned * sizeof(double) ;
} else {
nbytesPresent = 0 ;
}
if ( type == SPOOLES_REAL ) {
nbytesNeeded = n1 * n2 * sizeof(double) ;
} else if ( type == SPOOLES_COMPLEX ) {
nbytesNeeded = 2 * n1 * n2 * sizeof(double) ;
}
if ( nbytesNeeded > nbytesPresent ) {
DVfree(mtx->entries) ;
mtx->nowned = n1 * n2 ;
if ( type == SPOOLES_REAL ) {
mtx->entries = DVinit(n1*n2, 0.0) ;
} else if ( type == SPOOLES_COMPLEX ) {
mtx->entries = DVinit(2*n1*n2, 0.0) ;
}
}
}
mtx->type = type ;
mtx->n1 = n1 ;
mtx->n2 = n2 ;
mtx->inc1 = inc1 ;
mtx->inc2 = inc2 ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
submatrix initializer
A(0:lastrow-firstrow,0:lastcol-firstcol)
= B(firstrow:lastrow, firstcol:lastcol)
created -- 98apr15, cca
--------------------------------------------------
*/
void
A2_subA2 (
A2 *mtxA,
A2 *mtxB,
int firstrow,
int lastrow,
int firstcol,
int lastcol
) {
/*
---------------
check the input
---------------
*/
if ( mtxA == NULL || mtxB == NULL
|| firstrow < 0 || lastrow >= mtxB->n1
|| firstcol < 0 || lastcol >= mtxB->n2 ) {
fprintf(stderr, "\n fatal error in A2_subA2(%p,%p,%d,%d,%d,%d)"
"\n bad input\n",
mtxA, mtxB, firstrow, lastrow, firstcol, lastcol) ;
if ( mtxA != NULL ) {
fprintf(stderr, "\n first A2") ;
A2_writeForHumanEye(mtxA, stderr) ;
}
if ( mtxB != NULL ) {
fprintf(stderr, "\n second A2") ;
A2_writeForHumanEye(mtxB, stderr) ;
}
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtxB) || A2_IS_COMPLEX(mtxB)) ) {
fprintf(stderr, "\n fatal error in A2_subA2(%p,%p,%d,%d,%d,%d)"
"\n bad type %d\n", mtxA, mtxB, firstrow, lastrow,
firstcol, lastcol, mtxB->type) ;
exit(-1) ;
}
mtxA->type = mtxB->type ;
mtxA->inc1 = mtxB->inc1 ;
mtxA->inc2 = mtxB->inc2 ;
mtxA->n1 = lastrow - firstrow + 1 ;
mtxA->n2 = lastcol - firstcol + 1 ;
if ( A2_IS_REAL(mtxB) ) {
mtxA->entries = mtxB->entries
+ firstrow*mtxB->inc1 + firstcol*mtxB->inc2 ;
} else if ( A2_IS_COMPLEX(mtxB) ) {
mtxA->entries = mtxB->entries
+ 2*(firstrow*mtxB->inc1 + firstcol*mtxB->inc2) ;
}
mtxA->nowned = 0 ;
return ; }
/*--------------------------------------------------------------------*/
A2/src/instance.c 0100644 0002055 0007177 00000035067 06535011101 0015075 0 ustar 00cleve compmath 0000040 0000006 /* instance.c */
#include "../A2.h"
/*--------------------------------------------------------------------*/
/*
--------------------------------------
return the number of rows in the array
created -- 98may01, cca
--------------------------------------
*/
int
A2_nrow (
A2 *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_nrow(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(mtx->n1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------
return the number of columns in the array
created -- 98may01, cca
-----------------------------------------
*/
int
A2_ncol (
A2 *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_ncol(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(mtx->n2) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------
return the first increment
created -- 98may01, cca
--------------------------
*/
int
A2_inc1 (
A2 *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_inc1(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(mtx->inc1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------
return the second increment
created -- 98may01, cca
---------------------------
*/
int
A2_inc2 (
A2 *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_inc2(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(mtx->inc2) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------
return a pointer to the entries
created -- 98may01, cca
-------------------------------
*/
double *
A2_entries (
A2 *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_entries(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(mtx->entries) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
return a pointer to the first entry in a row
created -- 98may01, cca
--------------------------------------------
*/
double *
A2_row (
A2 *mtx,
int irow
) {
double *row ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_row(%p,%d)"
"\n bad input\n", mtx, irow) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr, "\n fatal error in A2_row(%p,%d)"
"\n bad structure, entries is NULL\n", mtx, irow) ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_row(%p,%d)"
"\n bad input, irow = %d, n1 = %d\n",
mtx, irow, irow, mtx->n1) ;
exit(-1) ;
}
if ( A2_IS_REAL(mtx) ) {
row = mtx->entries + irow*mtx->inc1 ;
} else if ( A2_IS_COMPLEX(mtx) ) {
row = mtx->entries + 2*irow*mtx->inc1 ;
} else {
fprintf(stderr, "\n fatal error in A2_row(%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX",
mtx, irow, mtx->type) ;
exit(-1) ;
}
return(row) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
return a pointer to the first entry in a column
created -- 98may01, cca
-----------------------------------------------
*/
double *
A2_column (
A2 *mtx,
int jcol
) {
double *col ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_column(%p,%d)"
"\n bad input\n", mtx, jcol) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr, "\n fatal error in A2_column(%p,%d)"
"\n bad structure, entries is NULL\n", mtx, jcol) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_column(%p,%d)"
"\n bad input, jcol = %d, n2 = %d\n",
mtx, jcol, jcol, mtx->n2) ;
exit(-1) ;
}
if ( A2_IS_REAL(mtx) ) {
col = mtx->entries + jcol*mtx->inc2 ;
} else if ( A2_IS_COMPLEX(mtx) ) {
col = mtx->entries + 2*jcol*mtx->inc2 ;
} else {
fprintf(stderr, "\n fatal error in A2_col(%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX",
mtx, jcol, mtx->type) ;
exit(-1) ;
}
return(col) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------
fill *pValue with the entry in (irow, jcol)
created -- 98may01, cca
-------------------------------------------
*/
void
A2_realEntry (
A2 *mtx,
int irow,
int jcol,
double *pValue
) {
int loc ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || pValue == NULL ) {
fprintf(stderr, "\n fatal error in A2_realEntry(%p,%d,%d,%p)"
"\n bad input\n", mtx, irow, jcol, pValue) ;
exit(-1) ;
}
if ( ! A2_IS_REAL(mtx) ) {
fprintf(stderr, "\n fatal error in A2_realEntry(%p,%d,%d,%p)"
"\n bad type %d, must be SPOOLES_REAL\n",
mtx, irow, jcol, pValue, mtx->type) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr, "\n fatal error in A2_realEntry(%p,%d,%d,%p)"
"\n bad structure, entries is NULL\n",
mtx, irow, jcol, pValue) ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_realEntry(%p,%d,%d,%p)"
"\n bad input, irow = %d, n1 = %d\n",
mtx, irow, jcol, pValue, irow, mtx->n1) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_realEntry(%p,%d,%d,%p)"
"\n bad input, jcol = %d, n2 = %d\n",
mtx, irow, jcol, pValue, jcol, mtx->n2) ;
exit(-1) ;
}
loc = irow*mtx->inc1 + jcol*mtx->inc2 ;
*pValue = mtx->entries[loc] ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
fill (*pReal,*pImag) with the entry in (irow, jcol)
created -- 98may01, cca
---------------------------------------------------
*/
void
A2_complexEntry (
A2 *mtx,
int irow,
int jcol,
double *pReal,
double *pImag
) {
int loc ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || pReal == NULL || pImag == NULL ) {
fprintf(stderr, "\n fatal error in A2_complexEntry(%p,%d,%d,%p,%p)"
"\n bad input\n", mtx, irow, jcol, pReal, pImag) ;
exit(-1) ;
}
if ( ! A2_IS_COMPLEX(mtx) ) {
fprintf(stderr, "\n fatal error in A2_complexEntry(%p,%d,%d,%p,%p)"
"\n bad type %d, must be SPOOLES_COMPLEX\n",
mtx, irow, jcol, pReal, pImag, mtx->type) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr, "\n fatal error in A2_complexEntry(%p,%d,%d,%p,%p)"
"\n bad structure, entries is NULL\n",
mtx, irow, jcol, pReal, pImag) ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_complexEntry(%p,%d,%d,%p,%p)"
"\n bad input, irow = %d, n1 = %d\n",
mtx, irow, jcol, pReal, pImag, irow, mtx->n1) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_complexEntry(%p,%d,%d,%p,%p)"
"\n bad input, jcol = %d, n2 = %d\n",
mtx, irow, jcol, pReal, pImag, jcol, mtx->n2) ;
exit(-1) ;
}
loc = 2*(irow*mtx->inc1 + jcol*mtx->inc2) ;
*pReal = mtx->entries[loc] ;
*pImag = mtx->entries[loc+1] ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------
set the entry in (irow, jcol) to be value
created -- 98may01, cca
-----------------------------------------
*/
void
A2_setRealEntry (
A2 *mtx,
int irow,
int jcol,
double value
) {
int loc ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr,
"\n fatal error in A2_setRealEntry(%p,%d,%d,%f)"
"\n bad input\n", mtx, irow, jcol, value) ;
exit(-1) ;
}
if ( ! A2_IS_REAL(mtx) ) {
fprintf(stderr,
"\n fatal error in A2_setRealEntry(%p,%d,%d,%f)"
"\n bad type %d, must be SPOOLES_REAL\n",
mtx, irow, jcol, value, mtx->type) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr,
"\n fatal error in A2_setRealEntry(%p,%d,%d,%f)"
"\n bad structure, entries is NULL\n",
mtx, irow, jcol, value) ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr,
"\n fatal error in A2_setRealEntry(%p,%d,%d,%f)"
"\n bad input, irow = %d, n1 = %d\n",
mtx, irow, jcol, value, irow, mtx->n1) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr,
"\n fatal error in A2_setRealEntry(%p,%d,%d,%f)"
"\n bad input, jcol = %d, n2 = %d\n",
mtx, irow, jcol, value, jcol, mtx->n2) ;
exit(-1) ;
}
loc = irow*mtx->inc1 + jcol*mtx->inc2 ;
mtx->entries[loc] = value ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
set the entry in (irow, jcol) to be (real,imag)
created -- 98may01, cca
-----------------------------------------------
*/
void
A2_setComplexEntry (
A2 *mtx,
int irow,
int jcol,
double real,
double imag
) {
int loc ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr,
"\n fatal error in A2_setComplexEntry(%p,%d,%d,%f,%f)"
"\n bad input\n", mtx, irow, jcol, real, imag) ;
exit(-1) ;
}
if ( ! A2_IS_COMPLEX(mtx) ) {
fprintf(stderr,
"\n fatal error in A2_setComplexEntry(%p,%d,%d,%f,%f)"
"\n bad type %d, must be SPOOLES_COMPLEX\n",
mtx, irow, jcol, real, imag, mtx->type) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr,
"\n fatal error in A2_setComplexEntry(%p,%d,%d,%f,%f)"
"\n bad structure, entries is NULL\n",
mtx, irow, jcol, real, imag) ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr,
"\n fatal error in A2_setComplexEntry(%p,%d,%d,%f,%f)"
"\n bad input, irow = %d, n1 = %d\n",
mtx, irow, jcol, real, imag, irow, mtx->n1) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr,
"\n fatal error in A2_setComplexEntry(%p,%d,%d,%f,%f)"
"\n bad input, jcol = %d, n2 = %d\n",
mtx, irow, jcol, real, imag, jcol, mtx->n2) ;
exit(-1) ;
}
loc = 2*(irow*mtx->inc1 + jcol*mtx->inc2) ;
mtx->entries[loc] = real ;
mtx->entries[loc+1] = imag ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------
fill pointers to the matrix first entry
in row irow and column jcol
created -- 98may01, cca
---------------------------------------
*/
void
A2_pointerToRealEntry (
A2 *mtx,
int irow,
int jcol,
double **ppValue
) {
int loc ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || ppValue == NULL ) {
fprintf(stderr,
"\n fatal error in A2_pointerToRealEntry(%p,%d,%d,%p)"
"\n bad input\n", mtx, irow, jcol, ppValue) ;
exit(-1) ;
}
if ( ! A2_IS_COMPLEX(mtx) ) {
fprintf(stderr,
"\n fatal error in A2_pointerToRealEntry(%p,%d,%d,%p)"
"\n bad type %d, must be SPOOLES_COMPLEX\n",
mtx, irow, jcol, ppValue, mtx->type) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr,
"\n fatal error in A2_pointerToRealEntry(%p,%d,%d,%p)"
"\n bad structure, entries is NULL\n",
mtx, irow, jcol, ppValue) ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr,
"\n fatal error in A2_pointerToRealEntry(%p,%d,%d,%p)"
"\n bad input, irow = %d, n1 = %d\n",
mtx, irow, jcol, ppValue, irow, mtx->n1) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr,
"\n fatal error in A2_pointerToRealEntry(%p,%d,%d,%p)"
"\n bad input, jcol = %d, n2 = %d\n",
mtx, irow, jcol, ppValue, jcol, mtx->n2) ;
exit(-1) ;
}
loc = irow*mtx->inc1 + jcol*mtx->inc2 ;
*ppValue = mtx->entries + loc ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------
fill pointers to the matrix first entry
in row irow and column jcol
created -- 98may01, cca
---------------------------------------
*/
void
A2_pointerToComplexEntry (
A2 *mtx,
int irow,
int jcol,
double **ppReal,
double **ppImag
) {
int loc ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || ppReal == NULL || ppImag == NULL ) {
fprintf(stderr,
"\n fatal error in A2_pointerToComplexEntry(%p,%d,%d,%p,%p)"
"\n bad input\n", mtx, irow, jcol, ppReal, ppImag) ;
exit(-1) ;
}
if ( ! A2_IS_COMPLEX(mtx) ) {
fprintf(stderr,
"\n fatal error in A2_pointerToComplexEntry(%p,%d,%d,%p,%p)"
"\n bad type %d, must be SPOOLES_COMPLEX\n",
mtx, irow, jcol, ppReal, ppImag, mtx->type) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr,
"\n fatal error in A2_pointerToComplexEntry(%p,%d,%d,%p,%p)"
"\n bad structure, entries is NULL\n",
mtx, irow, jcol, ppReal, ppImag) ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr,
"\n fatal error in A2_pointerToComplexEntry(%p,%d,%d,%p,%p)"
"\n bad input, irow = %d, n1 = %d\n",
mtx, irow, jcol, ppReal, ppImag, irow, mtx->n1) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr,
"\n fatal error in A2_pointerToComplexEntry(%p,%d,%d,%p,%p)"
"\n bad input, jcol = %d, n2 = %d\n",
mtx, irow, jcol, ppReal, ppImag, jcol, mtx->n2) ;
exit(-1) ;
}
loc = 2*(irow*mtx->inc1 + jcol*mtx->inc2) ;
*ppReal = mtx->entries + loc ;
*ppImag = mtx->entries + loc + 1 ;
return ; }
/*--------------------------------------------------------------------*/
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX",
mtx, jcol, mtx->type) ;
exit(-1) ;
}
return(col) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------
fill *pValue with the entry in (irow, jcol)
created -- 98may01, cca
-------------------------------------------
*/
void
A2_realEntry (
A2 *mtx,
int irow,
int jcol,
A2/src/makeStaircase.c 0100644 0002055 0007177 00000003442 06534105763 0016056 0 ustar 00cleve compmath 0000040 0000006 /* makeStaircase.c */
#include "../A2.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------------
purpose -- to permute the rows so the matrix is in staircase form
created -- 98may25, cca
-----------------------------------------------------------------
*/
void
A2_makeStaircase (
A2 *mtxA
) {
double imag, real, value ;
int irow, jcol, ncol, nrow ;
int *firstnonzero ;
/*
--------------
check the data
--------------
*/
if ( mtxA == NULL ) {
fprintf(stderr, "\n fatal error in A2_staircase(%p)"
"\n bad input\n", mtxA) ;
exit(-1) ;
}
nrow = A2_nrow(mtxA) ;
ncol = A2_ncol(mtxA) ;
/*
---------------------------------------------
fill firstnonzero[irow] with the first column
that contains a nonzero entry in this row.
---------------------------------------------
*/
firstnonzero = IVinit(nrow, -1) ;
for ( irow = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
if ( A2_IS_REAL(mtxA) ) {
A2_realEntry(mtxA, irow, jcol, &value) ;
if ( value != 0.0 ) {
break ;
}
} else if ( A2_IS_COMPLEX(mtxA) ) {
A2_complexEntry(mtxA, irow, jcol, &real, &imag) ;
if ( real != 0.0 || imag != 0.0 ) {
break ;
}
}
}
firstnonzero[irow] = jcol ;
}
/*
---------------------------------------------------
sort the rows in the order of their leading nonzero
---------------------------------------------------
*/
A2_sortRowsUp(mtxA, nrow, firstnonzero) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(firstnonzero) ;
return ; }
/*--------------------------------------------------------------------*/
A2/src/norms.c 0100644 0002055 0007177 00000047207 06534105763 0014447 0 ustar 00cleve compmath 0000040 0000006 /* norms.c */
#include "../A2.h"
#define CAUTIOUS 1
/*--------------------------------------------------------------------*/
/*
-------------------------------------
return the entry of maximum magnitude
created -- 98apr15, cca
-------------------------------------
*/
double
A2_maxabs (
A2 *a
) {
double maxval, val ;
double *entries, *row ;
int inc1, inc2, irow, jcol, kk, n1, n2 ;
/*
---------------
check the input
---------------
*/
if ( a == NULL
|| (n1 = a->n1) < 0
|| (n2 = a->n2) < 0
|| (inc1 = a->inc1) < 0
|| (inc2 = a->inc2) < 0 ) {
fprintf(stderr, "\n fatal error in A2_maxabs(%p)"
"\n bad input\n", a ) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(a) || A2_IS_COMPLEX(a)) ) {
fprintf(stderr, "\n fatal error in A2_maxabs(%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
a, a->type) ;
exit(-1) ;
}
entries = a->entries ;
maxval = 0.0 ;
row = entries ;
if ( A2_IS_REAL(a) ) {
for ( irow = 0 ; irow < n1 ; irow++ ) {
for ( jcol = 0, kk = 0 ; jcol < n2 ; jcol++, kk += inc2 ) {
val = fabs(row[kk]) ;
if ( maxval < val ) {
maxval = val ;
}
}
row += inc1 ;
}
} else if ( A2_IS_COMPLEX(a) ) {
for ( irow = 0 ; irow < n1 ; irow++ ) {
for ( jcol = 0, kk = 0 ; jcol < n2 ; jcol++, kk += inc2 ) {
val = Zabs(row[2*kk], row[2*kk+1]) ;
if ( maxval < val ) {
maxval = val ;
}
}
row += inc1 ;
}
}
return(maxval) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------
return the frobenius norm of the matrix
created -- 98apr15, cca
---------------------------------------
*/
double
A2_frobNorm (
A2 *mtx
) {
double norm ;
int ncol, nrow ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr,
"\n fatal error in A2_frobNorm(%p) "
"\n bad input\n", mtx) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_frobNorm(%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, mtx->type) ;
exit(-1) ;
}
if ( (nrow = mtx->n1) <= 0 || (ncol = mtx->n2) <= 0 ) {
return(0.0) ;
}
norm = 0 ;
if ( A2_IS_REAL(mtx) ) {
if ( mtx->inc1 == 1 ) {
double *col ;
int inc2 = mtx->inc2, irow, jcol ;
for ( jcol = 0, col = mtx->entries ;
jcol < ncol ;
jcol++, col += inc2 ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
norm += col[irow]*col[irow] ;
}
}
} else if ( mtx->inc2 == 1 ) {
double *row ;
int inc1 = mtx->inc1, irow, jcol ;
for ( irow = 0, row = mtx->entries ;
irow < nrow ;
irow++, row += inc1 ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
norm += row[jcol]*row[jcol] ;
}
}
} else {
double *entries = mtx->entries ;
int inc1 = mtx->inc1, inc2 = mtx->inc2, irow, jcol, loc ;
for ( irow = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
loc = irow*inc1 + jcol*inc2 ;
norm += entries[loc]*entries[loc] ;
}
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
if ( mtx->inc1 == 1 ) {
double *col ;
int inc2 = mtx->inc2, irow, jcol ;
for ( jcol = 0, col = mtx->entries ;
jcol < ncol ;
jcol++, col += 2*inc2 ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
norm += col[2*irow]*col[2*irow]
+ col[2*irow+1]*col[2*irow+1] ;
}
}
} else if ( mtx->inc2 == 1 ) {
double *row ;
int inc1 = mtx->inc1, irow, jcol ;
for ( irow = 0, row = mtx->entries ;
irow < nrow ;
irow++, row += 2*inc1 ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
norm += row[2*jcol]*row[2*jcol]
+ row[2*jcol+1]*row[2*jcol+1] ;
}
}
} else {
double *entries = mtx->entries ;
int inc1 = mtx->inc1, inc2 = mtx->inc2, irow, jcol, loc ;
for ( irow = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
loc = irow*inc1 + jcol*inc2 ;
norm += entries[2*loc]*entries[2*loc]
+ entries[2*loc+1]*entries[2*loc+1] ;
}
}
}
}
norm = sqrt(norm) ;
return(norm) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------
return the one-norm of the matrix
created -- 98apr15, cca
---------------------------------
*/
double
A2_oneNorm (
A2 *mtx
) {
double norm ;
int ncol, nrow ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_oneNorm(%p) "
"\n bad input\n", mtx) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_oneNorm(%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, mtx->type) ;
exit(-1) ;
}
if ( (nrow = mtx->n1) <= 0 || (ncol = mtx->n2) <= 0 ) {
return(0.0) ;
}
norm = 0.0 ;
if ( A2_IS_REAL(mtx) ) {
if ( mtx->inc1 == 1 ) {
double sum ;
double *col ;
int inc2 = mtx->inc2, irow, jcol ;
for ( jcol = 0, col = mtx->entries ;
jcol < ncol ;
jcol++, col += inc2 ) {
sum = 0.0 ;
for ( irow = 0 ; irow < nrow ; irow++ ) {
sum += fabs(col[irow]) ;
}
if ( norm < sum ) {
norm = sum ;
}
}
} else {
double sum ;
double *col ;
int inc1 = mtx->inc1, inc2 = mtx->inc2, irow, jcol, kk ;
for ( jcol = 0, col = mtx->entries ;
jcol < ncol ;
jcol++, col += inc2 ) {
sum = 0.0 ;
for ( irow = 0, kk = 0 ; irow < nrow ; irow++, kk += inc1 ) {
sum += fabs(col[kk]) ;
}
if ( norm < sum ) {
norm = sum ;
}
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
if ( mtx->inc1 == 1 ) {
double sum ;
double *col ;
int inc2 = mtx->inc2, irow, jcol ;
for ( jcol = 0, col = mtx->entries ;
jcol < ncol ;
jcol++, col += 2*inc2 ) {
sum = 0.0 ;
for ( irow = 0 ; irow < nrow ; irow++ ) {
sum += Zabs(col[2*irow], col[2*irow+1]) ;
}
if ( norm < sum ) {
norm = sum ;
}
}
} else {
double sum ;
double *col ;
int inc1 = mtx->inc1, inc2 = mtx->inc2, irow, jcol, kk ;
for ( jcol = 0, col = mtx->entries ;
jcol < ncol ;
jcol++, col += 2*inc2 ) {
sum = 0.0 ;
for ( irow = 0, kk = 0 ; irow < nrow ; irow++, kk += inc1 ) {
sum += Zabs(col[2*kk], col[2*kk+1]) ;
}
if ( norm < sum ) {
norm = sum ;
}
}
}
}
return(norm) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
return the infinity-norm of the matrix
created -- 98apr15, cca
--------------------------------------
*/
double
A2_infinityNorm (
A2 *mtx
) {
double norm ;
int ncol, nrow ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_infinityNorm(%p) "
"\n bad input\n", mtx) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_infinityNorm(%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, mtx->type) ;
exit(-1) ;
}
if ( (nrow = mtx->n1) <= 0 || (ncol = mtx->n2) <= 0 ) {
return(0.0) ;
}
norm = 0.0 ;
if ( A2_IS_REAL(mtx) ) {
if ( mtx->inc2 == 1 ) {
double sum ;
double *row = mtx->entries ;
int inc1 = mtx->inc1, irow, jcol ;
for ( irow = 0 ; irow < nrow ; irow++, row += inc1 ) {
for ( jcol = 0, sum = 0.0 ; jcol < ncol ; jcol++ ) {
sum += fabs(row[jcol]) ;
}
if ( norm < sum ) {
norm = sum ;
}
}
} else {
double sum ;
double *row = mtx->entries ;
int inc1 = mtx->inc1, inc2 = mtx->inc2, irow, jcol, kk ;
for ( irow = 0 ; irow < nrow ; irow++, row += inc1 ) {
sum = 0.0 ;
for ( jcol = 0, kk = 0 ; jcol < ncol ; jcol++, kk += inc2 ) {
sum += fabs(row[kk]) ;
}
if ( norm < sum ) {
norm = sum ;
}
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
if ( mtx->inc2 == 1 ) {
double sum ;
double *row ;
int inc1 = mtx->inc1, irow, jcol ;
for ( irow = 0, row = mtx->entries ;
irow < nrow ;
irow++, row += 2*inc1 ) {
sum = 0.0 ;
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
sum += Zabs(row[2*jcol], row[2*jcol+1]) ;
}
if ( norm < sum ) {
norm = sum ;
}
}
} else {
double sum ;
double *row ;
int inc1 = mtx->inc1, inc2 = mtx->inc2, irow, jcol, kk ;
for ( irow = 0, row = mtx->entries ;
irow < nrow ;
irow++, row += 2*inc1 ) {
sum = 0.0 ;
for ( jcol = 0, kk = 0 ; jcol < ncol ; jcol++, kk += inc2 ) {
sum += Zabs(row[2*kk], row[2*kk+1]) ;
}
if ( norm < sum ) {
norm = sum ;
}
}
}
}
return(norm) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------
return the one-norm of column jcol
created -- 98apr15, cca
----------------------------------
*/
double
A2_oneNormOfColumn (
A2 *mtx,
int jcol
) {
double sum ;
double *col ;
int inc1, irow, kk, nrow ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || mtx->entries == NULL
|| jcol < 0 || jcol > mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_oneNormOfColumn(%p,%d)"
"\n bad input\n", mtx, jcol) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_oneNormOfColumn(%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, jcol, mtx->type) ;
exit(-1) ;
}
nrow = mtx->n1 ;
sum = 0.0 ;
if ( A2_IS_REAL(mtx) ) {
col = mtx->entries + jcol*mtx->inc2 ;
if ( (inc1 = mtx->inc1) == 1 ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
sum += fabs(col[irow]) ;
}
} else {
for ( irow = 0, kk = 0 ; irow < nrow ; irow++, kk += inc1 ) {
sum += fabs(col[kk]) ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
col = mtx->entries + 2*jcol*mtx->inc2 ;
if ( (inc1 = mtx->inc1) == 1 ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
sum += Zabs(col[2*irow], col[2*irow+1]) ;
}
} else {
for ( irow = 0, kk = 0 ; irow < nrow ; irow++, kk += inc1 ) {
sum += Zabs(col[2*kk], col[2*kk+1]) ;
}
}
}
return(sum) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------
return the two-norm of column jcol
created -- 98apr15, cca
----------------------------------
*/
double
A2_twoNormOfColumn (
A2 *mtx,
int jcol
) {
double sum ;
double *col ;
int inc1, irow, kk, nrow ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || mtx->entries == NULL
|| jcol < 0 || jcol > mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_twoNormOfColumn(%p,%d)"
"\n bad input\n", mtx, jcol) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_twoNormOfColumn(%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, jcol, mtx->type) ;
exit(-1) ;
}
nrow = mtx->n1 ;
sum = 0.0 ;
if ( A2_IS_REAL(mtx) ) {
col = mtx->entries + jcol*mtx->inc2 ;
if ( (inc1 = mtx->inc1) == 1 ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
sum += col[irow]*col[irow] ;
}
} else {
for ( irow = 0, kk = 0 ; irow < nrow ; irow++, kk += inc1 ) {
sum += col[kk]*col[kk] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
col = mtx->entries + 2*jcol*mtx->inc2 ;
if ( (inc1 = mtx->inc1) == 1 ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
sum += col[2*irow]*col[2*irow] + col[2*irow+1]*col[2*irow+1] ;
}
} else {
for ( irow = 0, kk = 0 ; irow < nrow ; irow++, kk += inc1 ) {
sum += col[2*kk]*col[2*kk] + col[2*kk+1]*col[2*kk+1] ;
}
}
}
sum = sqrt(sum) ;
return(sum) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------
return the infinity-norm of column jcol
created -- 98apr15, cca
---------------------------------------
*/
double
A2_infinityNormOfColumn (
A2 *mtx,
int jcol
) {
double norm, val ;
double *col ;
int inc1, irow, kk, nrow ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || mtx->entries == NULL
|| jcol < 0 || jcol > mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_infinityNormOfColumn(%p,%d)"
"\n bad input\n", mtx, jcol) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_infinityNormOfColumn(%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, jcol, mtx->type) ;
exit(-1) ;
}
nrow = mtx->n1 ;
norm = 0.0 ;
if ( A2_IS_REAL(mtx) ) {
col = mtx->entries + jcol*mtx->inc2 ;
if ( (inc1 = mtx->inc1) == 1 ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
val = fabs(col[irow]) ;
if ( norm < val ) {
norm = val ;
}
}
} else {
for ( irow = 0, kk = 0 ; irow < nrow ; irow++, kk += inc1 ) {
val = fabs(col[kk]) ;
if ( norm < val ) {
norm = val ;
}
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
col = mtx->entries + 2*jcol*mtx->inc2 ;
if ( (inc1 = mtx->inc1) == 1 ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
val = Zabs(col[2*irow], col[2*irow+1]) ;
if ( norm < val ) {
norm = val ;
}
}
} else {
for ( irow = 0, kk = 0 ; irow < nrow ; irow++, kk += inc1 ) {
val = Zabs(col[2*kk], col[2*kk+1]) ;
if ( norm < val ) {
norm = val ;
}
}
}
}
return(norm) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------
return the one-norm of row irow
created -- 98apr15, cca
-------------------------------
*/
double
A2_oneNormOfRow (
A2 *mtx,
int irow
) {
double sum ;
double *row ;
int inc2, jcol, kk, ncol ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || mtx->entries == NULL
|| irow < 0 || irow > mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_oneNormOfRow(%p,%d)"
"\n bad input\n", mtx, irow) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_oneNormOfRow(%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, irow, mtx->type) ;
exit(-1) ;
}
ncol = mtx->n2 ;
sum = 0.0 ;
if ( A2_IS_REAL(mtx) ) {
row = mtx->entries + irow*mtx->inc1 ;
if ( (inc2 = mtx->inc2) == 1 ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
sum += fabs(row[jcol]) ;
}
} else {
for ( jcol = 0, kk = 0 ; jcol < ncol ; jcol++, kk += inc2 ) {
sum += fabs(row[kk]) ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
row = mtx->entries + 2*irow*mtx->inc1 ;
if ( (inc2 = mtx->inc2) == 1 ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
sum += Zabs(row[2*jcol], row[2*jcol+1]) ;
}
} else {
for ( jcol = 0, kk = 0 ; jcol < ncol ; jcol++, kk += inc2 ) {
sum += Zabs(row[2*kk], row[2*kk+1]) ;
}
}
}
return(sum) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------
return the two-norm of row irow
created -- 98apr15, cca
-------------------------------
*/
double
A2_twoNormOfRow (
A2 *mtx,
int irow
) {
double sum ;
double *row ;
int inc2, jcol, kk, ncol ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || mtx->entries == NULL
|| irow < 0 || irow > mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_twoNormOfRow(%p,%d)"
"\n bad input\n", mtx, irow) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_twoNormOfRow(%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, irow, mtx->type) ;
exit(-1) ;
}
ncol = mtx->n2 ;
sum = 0.0 ;
if ( A2_IS_REAL(mtx) ) {
row = mtx->entries + irow*mtx->inc1 ;
if ( (inc2 = mtx->inc2) == 1 ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
sum += row[jcol]*row[jcol] ;
}
} else {
for ( jcol = 0, kk = 0 ; jcol < ncol ; jcol++, kk += inc2 ) {
sum += row[kk]*row[kk] ;
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
row = mtx->entries + 2*irow*mtx->inc1 ;
if ( (inc2 = mtx->inc2) == 1 ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
sum += row[2*jcol]*row[2*jcol] + row[2*jcol+1]*row[2*jcol+1] ;
}
} else {
for ( jcol = 0, kk = 0 ; jcol < ncol ; jcol++, kk += inc2 ) {
sum += row[2*kk]*row[2*kk] + row[2*kk+1]*row[2*kk+1] ;
}
}
}
sum = sqrt(sum) ;
return(sum) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
return the infinity-norm of row irow
created -- 98apr15, cca
------------------------------------
*/
double
A2_infinityNormOfRow (
A2 *mtx,
int irow
) {
double norm, val ;
double *row ;
int inc2, jcol, kk, ncol ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || mtx->entries == NULL
|| irow < 0 || irow > mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_infinityNormOfRow(%p,%d)"
"\n bad input\n", mtx, irow) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_infinityNormOfRow(%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, irow, mtx->type) ;
exit(-1) ;
}
ncol = mtx->n2 ;
norm = 0.0 ;
if ( A2_IS_REAL(mtx) ) {
row = mtx->entries + irow*mtx->inc1 ;
if ( (inc2 = mtx->inc2) == 1 ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
val = fabs(row[jcol]) ;
if ( norm < val ) {
norm = val ;
}
}
} else {
for ( jcol = 0, kk = 0 ; jcol < ncol ; jcol++, kk += inc2 ) {
val = fabs(row[kk]) ;
if ( norm < val ) {
norm = val ;
}
}
}
} else if ( A2_IS_COMPLEX(mtx) ) {
row = mtx->entries + 2*irow*mtx->inc1 ;
if ( (inc2 = mtx->inc2) == 1 ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
val = Zabs(row[2*jcol], row[2*jcol+1]) ;
if ( norm < val ) {
norm = val ;
}
}
} else {
for ( jcol = 0, kk = 0 ; jcol < ncol ; jcol++, kk += inc2 ) {
val = Zabs(row[2*kk], row[2*kk+1]) ;
if ( norm < val ) {
norm = val ;
}
}
}
}
return(norm) ; }
/*--------------------------------------------------------------------*/
}
}
return(norm) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------
return the one-norm of column jcol
created -- 98apr15, cca
----------------------------------
*/
double
A2_oneNormOfColumn (
A2 *mtx,
int jcol
) {
double sum ;
double *col ;
int inc1, irow, kk, nrow ;
/*
A2/src/sort.c 0100644 0002055 0007177 00000015551 06534105763 0014275 0 ustar 00cleve compmath 0000040 0000006 /* sort.c */
#include "../A2.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------
permute the rows of the matrix
A(*,*) = A(index(*),*)
this method calls A2_sortRowsUp
but does not overwrite the index[] vector
created -- 98apr15, cca
-----------------------------------------
*/
void
A2_permuteRows (
A2 *mtx,
int nrow,
int index[]
) {
int *rowids ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || nrow < 0 || nrow > mtx->n1 || index == NULL ) {
fprintf(stderr, "\n fatal error in A2_permuteRows(%p,%d,%p)"
"\n bad input\n", mtx, nrow, index) ;
exit(-1) ;
}
rowids = IVinit(nrow, -1) ;
IVcopy(nrow, rowids, index) ;
A2_sortRowsUp(mtx, nrow, rowids) ;
IVfree(rowids) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------
permute the columns of the matrix
A(*,*) = A(*,index(*))
this method calls A2_sortColumnsUp
but does not overwrite the index[] vector
created -- 98apr15, cca
-----------------------------------------
*/
void
A2_permuteColumns (
A2 *mtx,
int ncol,
int index[]
) {
int *colids ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || ncol < 0 || ncol > mtx->n2 || index == NULL ) {
fprintf(stderr, "\n fatal error in A2_permuteColumns(%p,%d,%p)"
"\n bad input\n", mtx, ncol, index) ;
exit(-1) ;
}
colids = IVinit(ncol, -1) ;
IVcopy(ncol, colids, index) ;
A2_sortColumnsUp(mtx, ncol, colids) ;
IVfree(colids) ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
sort the rows of the matrix in ascending order
of the rowids[] vector. on return, rowids is
in asending order. return value is the number
of row swaps made.
created -- 98apr15, cca
----------------------------------------------
*/
int
A2_sortRowsUp (
A2 *mtx,
int nrow,
int rowids[]
) {
int ii, minrow, minrowid, nswap, target ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || mtx->n1 < nrow || nrow < 0 || rowids == NULL ) {
fprintf(stderr, "\n fatal error in A2_sortRowsUp(%p,%d,%p)"
"\n bad input\n", mtx, nrow, rowids) ;
if ( mtx != NULL ) {
A2_writeStats(mtx, stderr) ;
}
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_sortRowsUp(%p,%d,%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, nrow, rowids, mtx->type) ;
exit(-1) ;
}
nswap = 0 ;
if ( mtx->inc1 == 1 ) {
double *dvtmp ;
int jcol, ncol ;
int *ivtmp ;
/*
---------------------------------------------------
matrix is stored by columns, so permute each column
---------------------------------------------------
*/
ivtmp = IVinit(nrow, -1) ;
if ( A2_IS_REAL(mtx) ) {
dvtmp = DVinit(nrow, 0.0) ;
} else if ( A2_IS_COMPLEX(mtx) ) {
dvtmp = DVinit(2*nrow, 0.0) ;
}
IVramp(nrow, ivtmp, 0, 1) ;
IV2qsortUp(nrow, rowids, ivtmp) ;
ncol = mtx->n2 ;
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
if ( A2_IS_REAL(mtx) ) {
DVcopy(nrow, dvtmp, A2_column(mtx, jcol)) ;
DVgather(nrow, A2_column(mtx, jcol), dvtmp, ivtmp) ;
} else if ( A2_IS_COMPLEX(mtx) ) {
ZVcopy(nrow, dvtmp, A2_column(mtx, jcol)) ;
ZVgather(nrow, A2_column(mtx, jcol), dvtmp, ivtmp) ;
}
}
IVfree(ivtmp) ;
DVfree(dvtmp) ;
} else {
/*
----------------------------------------
use a simple insertion sort to swap rows
----------------------------------------
*/
for ( target = 0 ; target < nrow ; target++ ) {
minrow = target ;
minrowid = rowids[target] ;
for ( ii = target + 1 ; ii < nrow ; ii++ ) {
if ( minrowid > rowids[ii] ) {
minrow = ii ;
minrowid = rowids[ii] ;
}
}
if ( minrow != target ) {
rowids[minrow] = rowids[target] ;
rowids[target] = minrowid ;
A2_swapRows(mtx, target, minrow) ;
nswap++ ;
}
}
}
return(nswap) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
sort the columns of the matrix in ascending order
of the colids[] vector. on return, colids is
in asending order. return value is the number
of column swaps made.
created -- 98apr15, cca
-------------------------------------------------
*/
int
A2_sortColumnsUp (
A2 *mtx,
int ncol,
int colids[]
) {
int ii, mincol, mincolid, nswap, target ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || mtx->n2 < ncol || ncol < 0 || colids == NULL ) {
fprintf(stderr, "\n fatal error in A2_sortColumnsUp(%p,%d,%p)"
"\n bad input\n", mtx, ncol, colids) ;
if ( mtx != NULL ) {
A2_writeStats(mtx, stderr) ;
}
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_sortColumnsUp(%p,%d,%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, ncol, colids, mtx->type) ;
exit(-1) ;
}
nswap = 0 ;
if ( mtx->inc2 == 1 ) {
double *dvtmp ;
int irow, nrow ;
int *ivtmp ;
/*
---------------------------------------------------
matrix is stored by rows, so permute each row
---------------------------------------------------
*/
ivtmp = IVinit(ncol, -1) ;
if ( A2_IS_REAL(mtx) ) {
dvtmp = DVinit(ncol, 0.0) ;
} else if ( A2_IS_COMPLEX(mtx) ) {
dvtmp = DVinit(2*ncol, 0.0) ;
}
IVramp(ncol, ivtmp, 0, 1) ;
IV2qsortUp(ncol, colids, ivtmp) ;
nrow = mtx->n1 ;
for ( irow = 0 ; irow < nrow ; irow++ ) {
if ( A2_IS_REAL(mtx) ) {
DVcopy(ncol, dvtmp, A2_row(mtx, irow)) ;
DVgather(ncol, A2_row(mtx, irow), dvtmp, ivtmp) ;
} else if ( A2_IS_COMPLEX(mtx) ) {
ZVcopy(ncol, dvtmp, A2_row(mtx, irow)) ;
ZVgather(ncol, A2_row(mtx, irow), dvtmp, ivtmp) ;
}
}
IVfree(ivtmp) ;
DVfree(dvtmp) ;
} else {
/*
----------------------------------------
use a simple insertion sort to swap cols
----------------------------------------
*/
for ( target = 0 ; target < ncol ; target++ ) {
mincol = target ;
mincolid = colids[target] ;
for ( ii = target + 1 ; ii < ncol ; ii++ ) {
if ( mincolid > colids[ii] ) {
mincol = ii ;
mincolid = colids[ii] ;
}
}
if ( mincol != target ) {
colids[mincol] = colids[target] ;
colids[target] = mincolid ;
A2_swapColumns(mtx, target, mincol) ;
nswap++ ;
}
}
}
return(nswap) ; }
/*--------------------------------------------------------------------*/
A2/src/util.c 0100644 0002055 0007177 00000103171 06534105763 0014257 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../A2.h"
#include "../../Drand.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 98may01, cca
----------------------------------------------
*/
int
A2_sizeOf (
A2 *mtx
) {
int nbytes ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_sizeOf(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_sizeOf(%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, mtx->type) ;
exit(-1) ;
}
if ( A2_IS_REAL(mtx) ) {
nbytes = sizeof(struct _A2) + mtx->nowned*sizeof(double) ;
} else if ( A2_IS_COMPLEX(mtx) ) {
nbytes = sizeof(struct _A2) + 2*mtx->nowned*sizeof(double) ;
}
return(nbytes) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
shift the base of the entries and adjust dimensions
mtx(0:n1-rowoff-1,0:n2-coloff-1) = mtx(rowoff:n1-1,coloff:n2-1)
created -- 98may01, cca
---------------------------------------------------------------
*/
void
A2_shiftBase (
A2 *mtx,
int rowoff,
int coloff
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_shiftbase(%p,%d,%d)"
"\n bad input\n", mtx, rowoff, coloff) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_shiftBase(%p,%d,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, rowoff, coloff, mtx->type) ;
exit(-1) ;
}
mtx->n1 -= rowoff ;
mtx->n2 -= coloff ;
if ( A2_IS_REAL(mtx) ) {
mtx->entries += rowoff*mtx->inc1 + coloff*mtx->inc2 ;
} else if ( A2_IS_COMPLEX(mtx) ) {
mtx->entries += 2*(rowoff*mtx->inc1 + coloff*mtx->inc2) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
returns 1 if the storage is row major, otherwise returns zero.
created -- 98may01, cca
--------------------------------------------------------------
*/
int
A2_rowMajor (
A2 *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_rowMajor(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_rowMajor(%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, mtx->type) ;
exit(-1) ;
}
if ( mtx->inc2 == 1 ) {
return(1) ;
} else {
return(0) ;
} }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------------
returns 1 if the storage is column major, otherwise returns zero.
created -- 98may01, cca
-----------------------------------------------------------------
*/
int
A2_columnMajor (
A2 *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_columnMajor(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_columnMajor(%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, mtx->type) ;
exit(-1) ;
}
if ( mtx->inc1 == 1 ) {
return(1) ;
} else {
return(0) ;
} }
/*--------------------------------------------------------------------*/
/*
-----------------------
transpose the matrix
created -- 98may01, cca
-----------------------
*/
void
A2_transpose (
A2 *mtx
) {
int inc1, n1 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in A2_transpose(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_transpose(%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, mtx->type) ;
exit(-1) ;
}
n1 = mtx->n1 ;
mtx->n1 = mtx->n2 ;
mtx->n2 = n1 ;
inc1 = mtx->inc1 ;
mtx->inc1 = mtx->inc2 ;
mtx->inc2 = inc1 ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
extract row[*] = mtx(irow,*)
created -- 98may01, cca
----------------------------
*/
void
A2_extractRow (
A2 *mtx,
double row[],
int irow
) {
double *entries ;
int inc2, j, k, n2 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || row == NULL || mtx->entries == NULL
|| irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_extractRow(%p,%p,%d)"
"\n bad input\n", mtx, row, irow) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_extractRow(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, row, irow, mtx->type) ;
exit(-1) ;
}
k = irow * mtx->inc1 ;
n2 = mtx->n2 ;
inc2 = mtx->inc2 ;
entries = mtx->entries ;
if ( A2_IS_REAL(mtx) ) {
for ( j = 0 ; j < n2 ; j++, k += inc2 ) {
row[j] = entries[k] ;
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( j = 0 ; j < n2 ; j++, k += inc2 ) {
row[2*j] = entries[2*k] ;
row[2*j+1] = entries[2*k+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
extract col[*] = mtx(*,jcol)
created -- 98may01, cca
----------------------------
*/
void
A2_extractColumn (
A2 *mtx,
double col[],
int jcol
) {
double *entries ;
int i, inc1, k, n1 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || col == NULL || mtx->entries == NULL
|| jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_extractColumn(%p,%p,%d)"
"\n bad input\n", mtx, col, jcol) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_extractColumn(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, col, jcol, mtx->type) ;
exit(-1) ;
}
k = jcol * mtx->inc2 ;
n1 = mtx->n1 ;
inc1 = mtx->inc1 ;
entries = mtx->entries ;
if ( A2_IS_REAL(mtx) ) {
for ( i = 0 ; i < n1 ; i++, k += inc1 ) {
col[i] = entries[k] ;
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( i = 0 ; i < n1 ; i++, k += inc1 ) {
col[2*i] = entries[2*k] ;
col[2*i+1] = entries[2*k+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set mtx(irow,*) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setRow (
A2 *mtx,
double row[],
int irow
) {
double *entries ;
int inc2, j, k, n2 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || row == NULL || irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_setRow(%p,%p,%d)"
"\n bad input\n", mtx, row, irow) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_setRow(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, row, irow, mtx->type) ;
exit(-1) ;
}
k = irow * mtx->inc1 ;
n2 = mtx->n2 ;
inc2 = mtx->inc2 ;
entries = mtx->entries ;
if ( A2_IS_REAL(mtx) ) {
for ( j = 0 ; j < n2 ; j++, k += inc2 ) {
entries[k] = row[j] ;
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( j = 0 ; j < n2 ; j++, k += inc2 ) {
entries[2*k] = row[2*j] ;
entries[2*k+1] = row[2*j+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set mtx(*,jcol) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setColumn (
A2 *mtx,
double col[],
int jcol
) {
double *entries ;
int inc1, i, k, n1 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || col == NULL || jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_setColumn(%p,%p,%d)"
"\n bad input\n", mtx, col, jcol) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(mtx) || A2_IS_COMPLEX(mtx)) ) {
fprintf(stderr, "\n fatal error in A2_setColumn(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
mtx, col, jcol, mtx->type) ;
exit(-1) ;
}
k = jcol * mtx->inc2 ;
n1 = mtx->n1 ;
inc1 = mtx->inc1 ;
entries = mtx->entries ;
if ( A2_IS_REAL(mtx) ) {
for ( i = 0 ; i < n1 ; i++, k += inc1 ) {
entries[k] = col[i] ;
}
} else if ( A2_IS_COMPLEX(mtx) ) {
for ( i = 0 ; i < n1 ; i++, k += inc1 ) {
entries[2*k] = col[2*i] ;
entries[2*k+1] = col[2*i+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
extract row[*] = mtx(irow,*)
created -- 98may01, cca
----------------------------
*/
void
A2_extractRowDV (
A2 *mtx,
DV *rowDV,
int irow
) {
double *entries, *row ;
int inc2, j, k, n2 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || rowDV == NULL || mtx->entries == NULL
|| irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_extractRowDV(%p,%p,%d)"
"\n bad input\n", mtx, rowDV, irow) ;
exit(-1) ;
}
if ( ! A2_IS_REAL(mtx) ) {
fprintf(stderr, "\n fatal error in A2_extractRowDV(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_REAL\n",
mtx, rowDV, irow, mtx->type) ;
exit(-1) ;
}
if ( DV_size(rowDV) < (n2 = mtx->n2) ) {
DV_setSize(rowDV, n2) ;
}
row = DV_entries(rowDV) ;
k = irow * mtx->inc1 ;
inc2 = mtx->inc2 ;
entries = mtx->entries ;
for ( j = 0 ; j < n2 ; j++, k += inc2 ) {
row[j] = entries[k] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
extract row[*] = mtx(irow,*)
created -- 98may01, cca
----------------------------
*/
void
A2_extractRowZV (
A2 *mtx,
ZV *rowZV,
int irow
) {
double *entries, *row ;
int inc2, j, k, n2 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || rowZV == NULL || mtx->entries == NULL
|| irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_extractRowZV(%p,%p,%d)"
"\n bad input\n", mtx, rowZV, irow) ;
exit(-1) ;
}
if ( ! A2_IS_COMPLEX(mtx) ) {
fprintf(stderr, "\n fatal error in A2_extractRowZV(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_COMPLEX\n",
mtx, rowZV, irow, mtx->type) ;
exit(-1) ;
}
if ( ZV_size(rowZV) < (n2 = mtx->n2) ) {
ZV_setSize(rowZV, n2) ;
}
row = ZV_entries(rowZV) ;
k = irow * mtx->inc1 ;
inc2 = mtx->inc2 ;
entries = mtx->entries ;
for ( j = 0 ; j < n2 ; j++, k += inc2 ) {
row[2*j] = entries[2*k] ;
row[2*j+1] = entries[2*k+1] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
extract col[*] = mtx(*,jcol)
created -- 98may01, cca
----------------------------
*/
void
A2_extractColumnDV (
A2 *mtx,
DV *colDV,
int jcol
) {
double *entries, *col ;
int i, inc1, k, n1 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || colDV == NULL || mtx->entries == NULL
|| jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_extractColumnDV(%p,%p,%d)"
"\n bad input\n", mtx, colDV, jcol) ;
exit(-1) ;
}
if ( ! A2_IS_REAL(mtx) ) {
fprintf(stderr, "\n fatal error in A2_extractColumnDV(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_REAL\n",
mtx, colDV, jcol, mtx->type) ;
exit(-1) ;
}
if ( DV_size(colDV) < (n1 = mtx->n1) ) {
DV_setSize(colDV, n1) ;
}
col = DV_entries(colDV) ;
k = jcol * mtx->inc2 ;
inc1 = mtx->inc1 ;
entries = mtx->entries ;
for ( i = 0 ; i < n1 ; i++, k += inc1 ) {
col[i] = entries[k] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
extract col[*] = mtx(*,jcol)
created -- 98may01, cca
----------------------------
*/
void
A2_extractColumnZV (
A2 *mtx,
ZV *colZV,
int jcol
) {
double *entries, *col ;
int i, inc1, k, n1 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || colZV == NULL || mtx->entries == NULL
|| jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_extractColumnZV(%p,%p,%d)"
"\n bad input\n", mtx, colZV, jcol) ;
exit(-1) ;
}
if ( ! A2_IS_COMPLEX(mtx) ) {
fprintf(stderr, "\n fatal error in A2_extractColumnZV(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_COMPLEX\n",
mtx, colZV, jcol, mtx->type) ;
exit(-1) ;
}
if ( ZV_size(colZV) < (n1 = mtx->n1) ) {
ZV_setSize(colZV, n1) ;
}
col = ZV_entries(colZV) ;
k = jcol * mtx->inc2 ;
inc1 = mtx->inc1 ;
entries = mtx->entries ;
for ( i = 0 ; i < n1 ; i++, k += inc1 ) {
col[2*i] = entries[2*k] ;
col[2*i+1] = entries[2*k+1] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set mtx(irow,*) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setRowDV (
A2 *mtx,
DV *rowDV,
int irow
) {
double *entries, *row ;
int inc2, j, k, n2 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || rowDV == NULL || DV_size(rowDV) != (n2 = mtx->n2)
|| irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_setRowDV(%p,%p,%d)"
"\n bad input\n", mtx, rowDV, irow) ;
exit(-1) ;
}
if ( ! A2_IS_REAL(mtx) ) {
fprintf(stderr, "\n fatal error in A2_setRowDV(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_REAL\n",
mtx, rowDV, irow, mtx->type) ;
exit(-1) ;
}
k = irow * mtx->inc1 ;
inc2 = mtx->inc2 ;
entries = mtx->entries ;
row = DV_entries(rowDV) ;
for ( j = 0 ; j < n2 ; j++, k += inc2 ) {
entries[k] = row[j] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set mtx(irow,*) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setRowZV (
A2 *mtx,
ZV *rowZV,
int irow
) {
double *entries, *row ;
int inc2, j, k, n2 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || rowZV == NULL || ZV_size(rowZV) != (n2 = mtx->n2)
|| irow < 0 || irow >= mtx->n1 ) {
fprintf(stderr, "\n fatal error in A2_setRowZV(%p,%p,%d)"
"\n bad input\n", mtx, rowZV, irow) ;
exit(-1) ;
}
if ( ! A2_IS_COMPLEX(mtx) ) {
fprintf(stderr, "\n fatal error in A2_setRowZV(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_COMPLEX\n",
mtx, rowZV, irow, mtx->type) ;
exit(-1) ;
}
k = irow * mtx->inc1 ;
inc2 = mtx->inc2 ;
entries = mtx->entries ;
row = ZV_entries(rowZV) ;
for ( j = 0 ; j < n2 ; j++, k += inc2 ) {
entries[2*k] = row[2*j] ;
entries[2*k+1] = row[2*j+1] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set mtx(*,jcol) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setColumnDV (
A2 *mtx,
DV *colDV,
int jcol
) {
double *col, *entries ;
int inc1, i, k, n1 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || colDV == NULL || DV_size(colDV) != (n1 = mtx->n1)
|| jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_setColumnDV(%p,%p,%d)"
"\n bad input\n", mtx, colDV, jcol) ;
exit(-1) ;
}
if ( ! A2_IS_REAL(mtx) ) {
fprintf(stderr, "\n fatal error in A2_setColumnDV(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_REAL\n",
mtx, colDV, jcol, mtx->type) ;
exit(-1) ;
}
k = jcol * mtx->inc2 ;
inc1 = mtx->inc1 ;
entries = mtx->entries ;
col = DV_entries(colDV) ;
for ( i = 0 ; i < n1 ; i++, k += inc1 ) {
entries[k] = col[i] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set mtx(*,jcol) = y[*]
created -- 98may01, cca
-----------------------
*/
void
A2_setColumnZV (
A2 *mtx,
ZV *colZV,
int jcol
) {
double *col, *entries ;
int inc1, i, k, n1 ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || colZV == NULL || ZV_size(colZV) != (n1 = mtx->n1)
|| jcol < 0 || jcol >= mtx->n2 ) {
fprintf(stderr, "\n fatal error in A2_setColumnZV(%p,%p,%d)"
"\n bad input\n", mtx, colZV, jcol) ;
exit(-1) ;
}
if ( ! A2_IS_COMPLEX(mtx) ) {
fprintf(stderr, "\n fatal error in A2_setColumnZV(%p,%p,%d)"
"\n bad type %d, must be SPOOLES_COMPLEX\n",
mtx, colZV, jcol, mtx->type) ;
exit(-1) ;
}
k = jcol * mtx->inc2 ;
inc1 = mtx->inc1 ;
entries = mtx->entries ;
col = ZV_entries(colZV) ;
for ( i = 0 ; i < n1 ; i++, k += inc1 ) {
entries[2*k] = col[2*i] ;
entries[2*k+1] = col[2*i+1] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
fill the matrix with uniform random numbers in [lower, upper]
created -- 98may01, cca
-------------------------------------------------------------
*/
void
A2_fillRandomUniform (
A2 *a,
double lower,
double upper,
int seed
) {
double *entries ;
int i, inc1, inc2, j, loc, n1, n2 ;
Drand drand ;
/*
---------------
check the input
---------------
*/
if ( a == NULL
|| (n1 = a->n1) <= 0
|| (n2 = a->n2) <= 0
|| (inc1 = a->inc1) <= 0
|| (inc2 = a->inc2) <= 0
|| (entries = a->entries) == NULL ) {
fprintf(stderr,
"\n fatal error in A2_fillRandomUniform(%p,%f,%f,%d)"
"\n bad input\n",
a, lower, upper, seed) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(a) || A2_IS_COMPLEX(a)) ) {
fprintf(stderr, "\n fatal error in A2_fillRandomUniform(%p,%f,%f,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
a, lower, upper, seed, a->type) ;
exit(-1) ;
}
/*
----------------
fill the entries
----------------
*/
Drand_setDefaultFields(&drand) ;
Drand_init(&drand) ;
Drand_setSeed(&drand, seed) ;
Drand_setUniform(&drand, lower, upper) ;
for ( j = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
loc = i*inc1 + j*inc2 ;
if ( A2_IS_REAL(a) ) {
entries[loc] = Drand_value(&drand) ;
} else if ( A2_IS_COMPLEX(a) ) {
entries[2*loc] = Drand_value(&drand) ;
entries[2*loc+1] = Drand_value(&drand) ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
fill the matrix with normal(0,1) random numbers
created -- 98may01, cca
-----------------------------------------------
*/
void
A2_fillRandomNormal (
A2 *a,
double mean,
double variance,
int seed
) {
double *entries ;
int i, inc1, inc2, j, loc, n1, n2 ;
Drand drand ;
/*
---------------
check the input
---------------
*/
if ( a == NULL
|| (n1 = a->n1) <= 0
|| (n2 = a->n2) <= 0
|| (inc1 = a->inc1) <= 0
|| (inc2 = a->inc2) <= 0
|| (entries = a->entries) == NULL ) {
fprintf(stderr, "\n fatal error in A2_fillRandomNormal(%p,%d)"
"\n bad input\n",
a, seed) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(a) || A2_IS_COMPLEX(a)) ) {
fprintf(stderr, "\n fatal error in A2_fillRandomNormal(%p,%f,%f,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
a, mean, variance, seed, a->type) ;
exit(-1) ;
}
/*
----------------
fill the entries
----------------
*/
Drand_setDefaultFields(&drand) ;
Drand_init(&drand) ;
Drand_setSeed(&drand, seed) ;
Drand_setUniform(&drand, mean, variance) ;
for ( j = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
loc = i*inc1 + j*inc2 ;
if ( A2_IS_REAL(a) ) {
entries[loc] = Drand_value(&drand) ;
} else if ( A2_IS_COMPLEX(a) ) {
entries[2*loc] = Drand_value(&drand) ;
entries[2*loc+1] = Drand_value(&drand) ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------
fill the matrix with the identity matrix
created -- 98may01, cca
----------------------------------------
*/
void
A2_fillWithIdentity (
A2 *a
) {
double *entries ;
int ii, inc, inc1, inc2, j, n ;
/*
---------------
check the input
---------------
*/
if ( a == NULL
|| (n = a->n1) <= 0
|| n != a->n2
|| (inc1 = a->inc1) <= 0
|| (inc2 = a->inc2) <= 0
|| (inc1 != 1 && inc2 != 1)
|| (entries = a->entries) == NULL ) {
fprintf(stderr, "\n fatal error in A2_fillWithIdentity(%p)"
"\n bad input\n", a) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(a) || A2_IS_COMPLEX(a)) ) {
fprintf(stderr, "\n fatal error in A2_fillWithIdentity(%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
a, a->type) ;
exit(-1) ;
}
inc = (inc1 == 1) ? inc2 : inc1 ;
A2_zero(a) ;
for ( j = 0, ii = 0 ; j < n ; j++, ii += inc + 1 ) {
if ( A2_IS_REAL(a) ) {
entries[ii] = 1.0 ;
} else if ( A2_IS_COMPLEX(a) ) {
entries[2*ii] = 1.0 ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------
fill the matrix with zeros
created -- 98may01, cca
--------------------------
*/
void
A2_zero (
A2 *a
) {
double *entries ;
int i, inc1, inc2, j, loc, n1, n2 ;
/*
---------------
check the input
---------------
*/
if ( a == NULL
|| (n1 = a->n1) <= 0
|| (n2 = a->n2) <= 0
|| (inc1 = a->inc1) <= 0
|| (inc2 = a->inc2) <= 0
|| (entries = a->entries) == NULL ) {
fprintf(stderr, "\n fatal error in A2_zero(%p)"
"\n bad input\n", a) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(a) || A2_IS_COMPLEX(a)) ) {
fprintf(stderr, "\n fatal error in A2_zero(%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
a, a->type) ;
exit(-1) ;
}
for ( j = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
loc =i*inc1 + j*inc2 ;
if ( A2_IS_REAL(a) ) {
entries[loc] = 0.0 ;
} else if ( A2_IS_COMPLEX(a) ) {
entries[2*loc] = 0.0 ;
entries[2*loc+1] = 0.0 ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
copy one matrix into another
A := B
created -- 98may01, cca
----------------------------
*/
void
A2_copy (
A2 *A,
A2 *B
) {
double *entA, *entB ;
int inc1A, inc1B, inc2A, inc2B, irow, jcol, locA, locB,
ncol, ncolA, ncolB, nrow, nrowA, nrowB ;
/*
---------------
check the input
---------------
*/
if ( A == NULL
|| (nrowA = A->n1) < 0
|| (ncolA = A->n2) < 0
|| (inc1A = A->inc1) <= 0
|| (inc2A = A->inc2) <= 0
|| (entA = A->entries) == NULL
|| B == NULL
|| (nrowB = B->n1) < 0
|| (ncolB = B->n2) < 0
|| (inc1B = B->inc1) <= 0
|| (inc2B = B->inc2) <= 0
|| (entB = B->entries) == NULL ) {
fprintf(stderr, "\n fatal error in A2_copy(%p,%p)"
"\n bad input\n", A, B) ;
if ( A != NULL ) {
fprintf(stderr, "\n\n first A2 object") ;
A2_writeStats(A, stderr) ;
}
if ( B != NULL ) {
fprintf(stderr, "\n\n second A2 object") ;
A2_writeStats(B, stderr) ;
}
exit(-1) ;
}
if ( ! (A2_IS_REAL(A) || A2_IS_COMPLEX(A)) ) {
fprintf(stderr, "\n fatal error in A2_copy(%p,%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
A, B, A->type) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(B) || A2_IS_COMPLEX(B)) ) {
fprintf(stderr, "\n fatal error in A2_copy(%p,%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
A, B, B->type) ;
exit(-1) ;
}
if ( A->type != B->type ) {
fprintf(stderr, "\n fatal error in A2_copy(%p,%p)"
"\n A's type %d, B's type = %d, must be the same\n",
A, B, A->type, B->type) ;
exit(-1) ;
}
nrow = (nrowA <= nrowB) ? nrowA : nrowB ;
ncol = (ncolA <= ncolB) ? ncolA : ncolB ;
if ( A2_IS_REAL(A) ) {
if ( inc1A == 1 && inc1B == 1 ) {
double *colA = entA, *colB = entB ;
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
colA[irow] = colB[irow] ;
}
colA += inc2A ;
colB += inc2B ;
}
} else if ( inc2A == 1 && inc2B == 1 ) {
double *rowA = entA, *rowB = entB ;
for ( irow = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
rowA[jcol] = rowB[jcol] ;
}
rowA += 2*inc1A ;
}
} else {
for ( irow = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
locA = irow*inc1A + jcol*inc2A ;
locB = irow*inc1B + jcol*inc2B ;
entA[locA] = entB[locB] ;
}
}
}
} else if ( A2_IS_COMPLEX(A) ) {
if ( inc1A == 1 && inc1B == 1 ) {
double *colA = entA, *colB = entB ;
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
colA[2*irow] = colB[2*irow] ;
colA[2*irow+1] = colB[2*irow+1] ;
}
colA += 2*inc2A ;
colB += 2*inc2B ;
}
} else if ( inc2A == 1 && inc2B == 1 ) {
double *rowA = entA, *rowB = entB ;
for ( irow = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
rowA[2*jcol] = rowB[2*jcol] ;
rowA[2*jcol+1] = rowB[2*jcol+1] ;
}
rowA += 2*inc1A ;
rowB += 2*inc1B ;
}
} else {
for ( irow = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
locA = irow*inc1A + jcol*inc2A ;
locB = irow*inc1B + jcol*inc2B ;
entA[2*locA] = entB[2*locB] ;
entA[2*locA+1] = entB[2*locB+1] ;
}
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------
subtract one matrix from another
A := A - B
created -- 98may01, cca
----------------------------
*/
void
A2_sub (
A2 *A,
A2 *B
) {
double *entA, *entB ;
int inc1A, inc1B, inc2A, inc2B, irow, jcol, locA, locB,
ncol, ncolA, ncolB, nrow, nrowA, nrowB ;
/*
---------------
check the input
---------------
*/
if ( A == NULL
|| B == NULL
|| (nrowA = A->n1) <= 0
|| (ncolA = A->n2) <= 0
|| (inc1A = A->inc1) <= 0
|| (inc2A = A->inc2) <= 0
|| (nrowB = B->n1) <= 0
|| (ncolB = B->n2) <= 0
|| (inc1B = B->inc1) <= 0
|| (inc2B = B->inc2) <= 0
|| (entA = A->entries) == NULL
|| (entB = B->entries) == NULL ) {
fprintf(stderr, "\n fatal error in A2_sub(%p,%p)"
"\n bad input\n", A, B) ;
if ( A != NULL ) {
fprintf(stderr, "\n\n first A2 object") ;
A2_writeStats(A, stderr) ;
}
if ( B != NULL ) {
fprintf(stderr, "\n\n second A2 object") ;
A2_writeStats(B, stderr) ;
}
exit(-1) ;
}
if ( ! (A2_IS_REAL(A) || A2_IS_COMPLEX(A)) ) {
fprintf(stderr, "\n fatal error in A2_sub(%p,%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
A, B, A->type) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(B) || A2_IS_COMPLEX(B)) ) {
fprintf(stderr, "\n fatal error in A2_sub(%p,%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
A, B, B->type) ;
exit(-1) ;
}
if ( A->type != B->type ) {
fprintf(stderr, "\n fatal error in A2_sub(%p,%p)"
"\n A's type %d, B's type = %d, must be the same\n",
A, B, A->type, B->type) ;
exit(-1) ;
}
/*
fprintf(stdout, "\n debug : A") ;
A2_writeForHumanEye(A, stdout) ;
fprintf(stdout, "\n debug : B") ;
A2_writeForHumanEye(B, stdout) ;
*/
nrow = (nrowA <= nrowB) ? nrowA : nrowB ;
ncol = (ncolA <= ncolB) ? ncolA : ncolB ;
if ( A2_IS_REAL(A) ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
locA = irow*inc1A + jcol*inc2A ;
locB = irow*inc1B + jcol*inc2B ;
entA[locA] -= entB[locB] ;
}
}
} else if ( A2_IS_COMPLEX(A) ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
locA = irow*inc1A + jcol*inc2A ;
locB = irow*inc1B + jcol*inc2B ;
entA[2*locA] -= entB[2*locB] ;
entA[2*locA+1] -= entB[2*locB+1] ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------
swap two rows of the matrix
created -- 98may01, cca
---------------------------
*/
void
A2_swapRows (
A2 *a,
int irow1,
int irow2
) {
double temp ;
double *row1, *row2 ;
int inc2, j, k, n2 ;
/*
-----------
check input
-----------
*/
if ( a == NULL
|| irow1 < 0 || irow1 >= a->n1
|| irow2 < 0 || irow2 >= a->n1 ) {
fprintf(stderr,
"\n fatal error in A2_swapRows(%p,%d,%d)"
"\n bad input\n", a, irow1, irow2) ;
exit(-1) ;
}
if ( a->n1 <= 0
|| a->inc1 <= 0
|| (n2 = a->n2) <= 0
|| (inc2 = a->inc2) <= 0
|| a->entries == NULL ) {
fprintf(stderr,
"\n fatal error in A2_swapRows(%p,%d,%d)"
"\n bad structure\n", a, irow1, irow2) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(a) || A2_IS_COMPLEX(a)) ) {
fprintf(stderr, "\n fatal error in A2_swapRows(%p,%d,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
a, irow1, irow2, a->type) ;
exit(-1) ;
}
if ( irow1 == irow2 ) {
return ;
}
if ( A2_IS_REAL(a) ) {
row1 = a->entries + irow1*a->inc1 ;
row2 = a->entries + irow2*a->inc1 ;
if ( inc2 == 1 ) {
for ( j = 0 ; j < n2 ; j++ ) {
temp = row1[j] ;
row1[j] = row2[j] ;
row2[j] = temp ;
}
} else {
for ( j = 0, k = 0 ; j < n2 ; j++, k += inc2 ) {
temp = row1[k] ;
row1[k] = row2[k] ;
row2[k] = temp ;
}
}
} else if ( A2_IS_COMPLEX(a) ) {
row1 = a->entries + 2*irow1*a->inc1 ;
row2 = a->entries + 2*irow2*a->inc1 ;
if ( inc2 == 1 ) {
for ( j = 0 ; j < n2 ; j++ ) {
temp = row1[2*j] ;
row1[2*j] = row2[2*j] ;
row2[2*j] = temp ;
temp = row1[2*j+1] ;
row1[2*j+1] = row2[2*j+1] ;
row2[2*j+1] = temp ;
}
} else {
for ( j = 0, k = 0 ; j < n2 ; j++, k += inc2 ) {
temp = row1[2*k] ;
row1[2*k] = row2[2*k] ;
row2[2*k] = temp ;
temp = row1[2*k+1] ;
row1[2*k+1] = row2[2*k+1] ;
row2[2*k+1] = temp ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------
swap two columns of the matrix
created -- 98may01, cca
------------------------------
*/
void
A2_swapColumns (
A2 *a,
int jcol1,
int jcol2
) {
double temp ;
double *col1, *col2 ;
int i, inc1, k, n1 ;
/*
-----------
check input
-----------
*/
if ( a == NULL
|| jcol1 < 0 || jcol1 >= a->n2
|| jcol2 < 0 || jcol2 >= a->n2 ) {
fprintf(stderr,
"\n fatal error in A2_swapColumns(%p,%d,%d)"
"\n bad input\n", a, jcol1, jcol2) ;
exit(-1) ;
}
if ( (n1 = a->n1) <= 0
|| (inc1 = a->inc1) <= 0
|| a->n2 <= 0
|| a->inc2 <= 0
|| a->entries == NULL ) {
fprintf(stderr,
"\n fatal error in A2_swapColumns(%p,%d,%d)"
"\n bad structure\n", a, jcol1, jcol2) ;
exit(-1) ;
}
if ( ! (A2_IS_REAL(a) || A2_IS_COMPLEX(a)) ) {
fprintf(stderr, "\n fatal error in A2_swapColumns(%p,%d,%d)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
a, jcol1, jcol2, a->type) ;
exit(-1) ;
}
if ( jcol1 == jcol2 ) {
return ;
}
if ( A2_IS_REAL(a) ) {
col1 = a->entries + jcol1*a->inc2 ;
col2 = a->entries + jcol2*a->inc2 ;
if ( inc1 == 1 ) {
for ( i = 0 ; i < n1 ; i++ ) {
temp = col1[i] ;
col1[i] = col2[i] ;
col2[i] = temp ;
}
} else {
for ( i = 0, k = 0 ; i < n1 ; i++, k += inc1 ) {
temp = col1[k] ;
col1[k] = col2[k] ;
col2[k] = temp ;
}
}
} else if ( A2_IS_COMPLEX(a) ) {
col1 = a->entries + 2*jcol1*a->inc2 ;
col2 = a->entries + 2*jcol2*a->inc2 ;
if ( inc1 == 1 ) {
for ( i = 0 ; i < n1 ; i++ ) {
temp = col1[2*i] ;
col1[2*i] = col2[2*i] ;
col2[2*i] = temp ;
temp = col1[2*i+1] ;
col1[2*i+1] = col2[2*i+1] ;
col2[2*i+1] = temp ;
}
} else {
for ( i = 0, k = 0 ; i < n1 ; i++, k += inc1 ) {
temp = col1[2*k] ;
col1[2*k] = col2[2*k] ;
col2[2*k] = temp ;
temp = col1[2*k+1] ;
col1[2*k+1] = col2[2*k+1] ;
col2[2*k+1] = temp ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
c1) <= 0
|| (inc2B = B->inc2) <= 0
|| (entB = B->entries) == NULL ) {
fprintf(stderr, "\n fatal error in A2_copy(%p,%p)"
"\n bad input\n", A, B) ;
if ( A != NULL ) {
fprintf(stderr, "\n\n first A2 object") ;
A2_writeStats(A, stderr) ;
}
if ( B != NULL ) {
fprintf(stderr, "\n\n second A2 object") ;
A2_writeStats(B, stderr) ;
}
exiA2/drivers/do_QR 0100755 0002055 0007177 00000000471 06643451321 0014751 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
set msglvl = 2
set msgFile = stdout
set type = 2
set nrow = 10
set ncol = 5
set inc1 = $ncol
set inc1 = 1
set inc2 = 1
set inc2 = $nrow
set seed = 1
set ncolX = $ncol
set ncolX = 6
set type = 2
testQR $msglvl $msgFile $type $nrow $ncol $inc1 $inc2 $seed $ncolX
A2/drivers/do_norms 0100755 0002055 0007177 00000000400 06535035377 0015566 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
set msglvl = 2
set msgFile = stdout
set type = 2
set nrow = 10
set ncol = 20
set inc1 = $ncol
set inc1 = 1
set inc2 = 1
set inc2 = $nrow
set seed = 1
test_norms $msglvl $msgFile $type $nrow $ncol $inc1 $inc2 $seed
A2/drivers/makefile 0100644 0002055 0007177 00000000633 06653142307 0015521 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
DRIVERS = test_norms testQR
LIBS = ../../spooles.a -lm
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
testQR : testQR.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_norms : test_norms.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIF_GCC_VERSION} ${LIBS}
A2/drivers/testQR.c 0100644 0002055 0007177 00000014713 06643450765 0015424 0 ustar 00cleve compmath 0000040 0000006 /* testQR.c */
#include "../A2.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
----------------------------------------------------------------
test the A2_QRreduce(), A2_QRcomputeQ() and A2_applyQT() methods
created -- 98dec10, cca
----------------------------------------------------------------
*/
{
A2 *A, *Q, *R, *X, *Y ;
double nops, t1, t2 ;
DV workDV ;
FILE *msgFile ;
int inc1, inc2, irow, jcol,
msglvl, nrow, ncol, ncolX, seed, type ;
if ( argc != 10 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile type nrow ncol inc1 inc2 seed ncolX"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n type -- entries type"
"\n 1 -- real"
"\n 2 -- complex"
"\n nrow -- # of rows in A"
"\n ncol -- # of columns in A"
"\n inc1 -- row increment, must be ncol"
"\n inc2 -- column increment, must be 1"
"\n seed -- random number seed"
"\n ncolX -- # of columns in X"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
type = atoi(argv[3]) ;
nrow = atoi(argv[4]) ;
ncol = atoi(argv[5]) ;
inc1 = atoi(argv[6]) ;
inc2 = atoi(argv[7]) ;
if ( type < 1 || type > 2 || nrow < 0 || ncol < 0
|| inc1 < 1 || inc2 < 1 ) {
fprintf(stderr,
"\n fatal error, type %d, nrow %d, ncol %d, inc1 %d, inc2 %d",
type, nrow, ncol, inc1, inc2) ;
exit(-1) ;
}
seed = atoi(argv[8]) ;
ncolX = atoi(argv[9]) ;
fprintf(msgFile, "\n\n %% %s :"
"\n %% msglvl = %d"
"\n %% msgFile = %s"
"\n %% type = %d"
"\n %% nrow = %d"
"\n %% ncol = %d"
"\n %% inc1 = %d"
"\n %% inc2 = %d"
"\n %% seed = %d"
"\n %% ncolX = %d"
"\n",
argv[0], msglvl, argv[2], type,
nrow, ncol, inc1, inc2, seed, ncolX) ;
if ( inc1 != 1 && inc2 != 1 ) {
fprintf(stderr, "\n inc1 = %d, inc2 = %d\n", inc1, inc2) ;
exit(-1) ;
}
/*
-----------------------------
initialize the matrix objects
-----------------------------
*/
MARKTIME(t1) ;
A = A2_new() ;
A2_init(A, type, nrow, ncol, inc1, inc2, NULL) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize matrix object",
t2 - t1) ;
MARKTIME(t1) ;
A2_fillRandomUniform(A, -1, 1, seed++) ;
MARKTIME(t2) ;
fprintf(msgFile,
"\n %% CPU : %.3f to fill matrix with random numbers", t2 - t1) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n matrix A") ;
A2_writeForHumanEye(A, msgFile) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n %% matrix A") ;
A2_writeForMatlab(A, "A", msgFile) ;
}
/*
--------------------
compute the R matrix
--------------------
*/
DV_setDefaultFields(&workDV) ;
/*
------------------
use rank-1 updates
------------------
*/
MARKTIME(t1) ;
nops = A2_QRreduce(A, &workDV, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile,
"\n %% CPU : rank-1: %.3f to compute R, %.0f ops, %.3f mflops",
t2 - t1, nops, 1.e-6*nops/(t2-t1)) ;
/*
----------------------
write out the R matrix
----------------------
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n %% matrix R") ;
R = A2_new() ;
A2_subA2(R, A, 0, ncol - 1, 0, ncol - 1) ;
A2_writeForMatlab(R, "R", msgFile) ;
fprintf(msgFile,
"\n for jj = 1:%d"
"\n for ii = jj+1:%d"
"\n R(ii,jj) = 0.0 ;"
"\n end"
"\n end", ncol, ncol) ;
fflush(msgFile) ;
A2_free(R) ;
}
/*
-------------------------------
check the error |A^H*A - R^H*R|
-------------------------------
*/
if ( msglvl > 1 ) {
if ( type == SPOOLES_REAL ) {
fprintf(msgFile,
"\n emtx1 = transpose(A)*A - transpose(R)*R ;"
"\n error = max(max(abs(emtx1))) " ) ;
} else if ( type == SPOOLES_COMPLEX ) {
fprintf(msgFile,
"\n emtx1 = ctranspose(A)*A - ctranspose(R)*R ;"
"\n error = max(max(abs(emtx1))) " ) ;
}
DV_clearData(&workDV) ;
}
if ( inc1 == 1 ) {
/*
---------
compute Q
---------
*/
Q = A2_new() ;
A2_init(Q, type, nrow, ncol, inc1, inc2, NULL) ;
A2_computeQ(Q, A, &workDV, msglvl, msgFile) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n %% matrix Q") ;
A2_writeForMatlab(Q, "Q", msgFile) ;
fprintf(msgFile,
"\n emtx2 = A - Q * R ;"
"\n error = max(max(abs(emtx2))) " ) ;
}
A2_free(Q) ;
/*
---------------------------------------------------
create a matrix X with the same number of rows as A
---------------------------------------------------
*/
MARKTIME(t1) ;
X = A2_new() ;
A2_init(X, type, nrow, ncolX, inc1, inc2, NULL) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize matrix object",
t2 - t1) ;
MARKTIME(t1) ;
A2_fillRandomUniform(X, -1, 1, seed++) ;
MARKTIME(t2) ;
fprintf(msgFile,
"\n %% CPU : %.3f to fill matrix with random numbers", t2 - t1) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n matrix X") ;
A2_writeForHumanEye(X, msgFile) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n %% matrix X") ;
A2_writeForMatlab(X, "X", msgFile) ;
}
/*
-------------------
compute Y = Q^T * X
-------------------
*/
MARKTIME(t1) ;
Y = A2_new() ;
A2_init(Y, type, nrow, ncolX, inc1, inc2, NULL) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize matrix object",
t2 - t1) ;
A2_applyQT(Y, A, X, &workDV, msglvl, msgFile) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n %% matrix Y") ;
A2_writeForMatlab(Y, "Y", msgFile) ;
fprintf(msgFile, "\n [Qexact,Rexact] = qr(A) ;") ;
if ( A2_IS_REAL(A) ) {
fprintf(msgFile, "\n emtx3 = Y - transpose(Qexact) * X ;") ;
} else {
fprintf(msgFile, "\n emtx3 = Y - ctranspose(Qexact) * X ;") ;
}
fprintf(msgFile, "\n error = max(max(abs(emtx3))) " ) ;
}
A2_free(Q) ;
A2_free(X) ;
A2_free(Y) ;
}
/*
------------------------
free the working storage
------------------------
*/
DV_clearData(&workDV) ;
A2_free(A) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
A2/drivers/test_norms.c 0100644 0002055 0007177 00000011136 06535034733 0016364 0 ustar 00cleve compmath 0000040 0000006 /* test_norms.c */
#include "../A2.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-----------------------
simple test program
created -- 98apr15, cca
-----------------------
*/
{
A2 *A ;
double t1, t2, value ;
FILE *msgFile ;
int inc1, inc2, irow, jcol,
msglvl, nrow, ncol, seed, type ;
if ( argc != 9 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile type nrow ncol inc1 inc2 seed "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n type -- entries type"
"\n 1 -- real"
"\n 2 -- complex"
"\n nrow -- # of rows "
"\n ncol -- # of columns "
"\n inc1 -- row increment "
"\n inc2 -- column increment "
"\n seed -- random number seed"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
type = atoi(argv[3]) ;
nrow = atoi(argv[4]) ;
ncol = atoi(argv[5]) ;
inc1 = atoi(argv[6]) ;
inc2 = atoi(argv[7]) ;
if ( type < 1 || type > 2 || nrow < 0 || ncol < 0
|| inc1 < 1 || inc2 < 1 ) {
fprintf(stderr,
"\n fatal error, type %d, nrow %d, ncol %d, inc1 %d, inc2 %d",
type, nrow, ncol, inc1, inc2) ;
exit(-1) ;
}
seed = atoi(argv[7]) ;
fprintf(msgFile, "\n\n %% %s :"
"\n %% msglvl = %d"
"\n %% msgFile = %s"
"\n %% type = %d"
"\n %% nrow = %d"
"\n %% ncol = %d"
"\n %% inc1 = %d"
"\n %% inc2 = %d"
"\n %% seed = %d"
"\n",
argv[0], msglvl, argv[2], type, nrow, ncol, inc1, inc2, seed) ;
/*
-----------------------------
initialize the matrix objects
-----------------------------
*/
MARKTIME(t1) ;
A = A2_new() ;
A2_init(A, type, nrow, ncol, inc1, inc2, NULL) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize matrix object",
t2 - t1) ;
MARKTIME(t1) ;
A2_fillRandomUniform(A, -1, 1, seed) ;
seed++ ;
MARKTIME(t2) ;
fprintf(msgFile,
"\n %% CPU : %.3f to fill matrix with random numbers", t2 - t1) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n matrix A") ;
A2_writeForHumanEye(A, msgFile) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n %% matrix A") ;
A2_writeForMatlab(A, "A", msgFile) ;
}
/*
-------------
get the norms
-------------
*/
value = A2_maxabs(A) ;
fprintf(msgFile, "\n error_maxabs = abs(%20.12e - max(max(abs(A))))",
value) ;
value = A2_frobNorm(A) ;
fprintf(msgFile, "\n error_frob = abs(%20.12e - norm(A, 'fro'))",
value) ;
value = A2_oneNorm(A) ;
fprintf(msgFile, "\n error_one = abs(%20.12e - norm(A, 1))",
value) ;
value = A2_infinityNorm(A) ;
fprintf(msgFile, "\n error_inf = abs(%20.12e - norm(A, inf))",
value) ;
for ( irow = 0 ; irow < nrow ; irow++ ) {
value = A2_infinityNormOfRow(A, irow) ;
fprintf(msgFile,
"\n error_infNormsOfRows(%d) = abs(%20.12e - norm(A(%d,:), inf)) ;",
irow+1, value, irow+1) ;
value = A2_oneNormOfRow(A, irow) ;
fprintf(msgFile,
"\n error_oneNormsOfRows(%d) = abs(%20.12e - norm(A(%d,:), 1)) ;",
irow+1, value, irow+1) ;
value = A2_twoNormOfRow(A, irow) ;
fprintf(msgFile,
"\n error_twoNormsOfRows(%d) = abs(%20.12e - norm(A(%d,:), 2)) ;",
irow+1, value, irow+1) ;
}
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
value = A2_infinityNormOfColumn(A, jcol) ;
fprintf(msgFile,
"\n error_infNormsOfColumns(%d) = abs(%20.12e - norm(A(:,%d), inf)) ;",
jcol+1, value, jcol+1) ;
value = A2_oneNormOfColumn(A, jcol) ;
fprintf(msgFile,
"\n error_oneNormsOfColumns(%d) = abs(%20.12e - norm(A(:,%d), 1)) ;",
jcol+1, value, jcol+1) ;
value = A2_twoNormOfColumn(A, jcol) ;
fprintf(msgFile,
"\n error_twoNormsOfColumns(%d) = abs(%20.12e - norm(A(:,%d), 2)) ;",
jcol+1, value, jcol+1) ;
}
fprintf(msgFile,
"\n error_in_row_norms = [ max(error_infNormsOfRows) "
"\n max(error_oneNormsOfRows) "
"\n max(error_twoNormsOfRows) ]"
"\n error_in_column_norms = [ max(error_infNormsOfColumns) "
"\n max(error_oneNormsOfColumns) "
"\n max(error_twoNormsOfColumns) ]") ;
fprintf(msgFile, "\n") ;
/*
------------------------
free the working storage
------------------------
*/
A2_free(A) ;
return(1) ; }
/*--------------------------------------------------------------------*/
A2/doc/ 0042755 0002055 0007177 00000000000 06650232140 0013103 5 ustar 00cleve compmath 0000040 0000006 A2/doc/main.tex 0100644 0002055 0007177 00000001147 06622330544 0014555 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
% \documentstyle[leqno,11pt,twoside]{report}
\documentclass[leqno,10pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt A2} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt A2} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
A2/doc/intro.tex 0100644 0002055 0007177 00000000526 06535020771 0014765 0 ustar 00cleve compmath 0000040 0000006 \par
\chapter{{\tt A2}: Real or complex 2-D array}
\par
The {\tt A2} object is one way to store and operate on and
with a dense matrix.
The matrix can contain either double precision real or complex
entries.
It is used as a lower level object for the {\tt DenseMtx} object,
and during the $QR$ factorization to hold a staircase matrix.
\par
A2/doc/dataStructure.tex 0100644 0002055 0007177 00000003152 06535016443 0016463 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:A2:dataStructure}
\par
\par
The {\tt A2} structure has six fields.
\begin{itemize}
\item
{\tt int type} : type of entries,
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
{\tt int n1} : size in first dimension, number of rows
\item
{\tt int n2} : size in second dimension, number of columns
\item
{\tt int inc1} : increment or stride in first dimension
\item
{\tt int inc2} : increment or stride in second dimension
\item
{\tt int nowned} : the number of entries that are ``owned'' by this
object.
When {\tt nowned > 0},
{\tt entries} points to storage for {\tt nowned} entries,
({\tt nowned} {\tt double}'s for the real case,
{\tt 2*nowned} {\tt double}'s for the complex case),
that have been allocated by this object and can be free'd by the object.
When {\tt nowned == 0} but {\tt n1 > 0} and {\tt n2 > 0},
this object points to entries that have been allocated elsewhere,
and these entries will not be free'd by this object.
\item
{\tt double *entries} :
pointer to the base address of the {\it double} vector
\end{itemize}
One can query the properties of the front matrix object
using these simple macros.
\begin{itemize}
\item
{\tt A2\_IS\_REAL(mtx)} is {\tt 1} if {\tt mtx}
has real entries and {\tt 0} otherwise.
\item
{\tt A2\_IS\_COMPLEX(mtx)} is {\tt 1} if {\tt mtx}
has complex entries and {\tt 0} otherwise.
\end{itemize}
The {\tt A2\_copyEntriesToVector()} method
uses the following constants:
{\tt A2\_STRICT\_LOWER},
{\tt A2\_LOWER},
{\tt A2\_DIAGONAL},
{\tt A2\_UPPER},
{\tt A2\_STRICT\_UPPER},
{\tt A2\_ALL\_ENTRIES},
{\tt A2\_BY\_ROWS} and
{\tt A2\_BY\_COLUMNS}.
d} entries,
({\tt nowned} {\tt double}'s for the real case,
{\tt 2*nowned} {\tt double}'s for the complex case),
that have been allocated by this object and can be free'd by the object.
When {\tt nowned == 0} but {\tt n1 > 0} and {\tt n2 > 0},
this object points to entries that have been allocated elsewhere,
and these entries will not be free'd by this object.
\item
{\tt double *entries} :
pointer toA2/doc/proto.tex 0100644 0002055 0007177 00000117311 06650162446 0015002 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt A2} methods}
\label{section:A2:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt A2} object.
\par
\subsection{Basic methods}
\label{subsection:A2:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
A2 * A2_new ( void ) ;
\end{verbatim}
\index{A2_new@{\tt A2\_new()}}
This method simply allocates storage for the {\tt A2} structure
and then sets the default fields by a call to
{\tt A2\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_setDefaultFields ( A2 *mtx ) ;
\end{verbatim}
\index{A2_setDefaultFields@{\tt A2\_setDefaultFields()}}
The structure's fields are set to default values:
{\tt type} = {\tt SPOOLES\_REAL},
{\tt n1} = {\tt inc1} = {\tt n2} = {\tt inc2} = {\tt nowned} = 0 and
{\tt entries} = {\tt NULL} .
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_clearData ( A2 *mtx ) ;
\end{verbatim}
\index{A2_clearData@{\tt A2\_clearData()}}
This method clears the object and free's any owned data.
If {\tt nowned > 0} and {\tt entries} is not {\tt NULL},
then {\tt DVfree(entries)} is called to free the storage.
It calls {\tt A2\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_free ( A2 *mtx ) ;
\end{verbatim}
\index{A2_free@{\tt A2\_free()}}
This method releases any storage by a call to
{\tt A2\_clearData()} and then free the space for {\tt mtx}.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Instance methods}
\label{subsection:A2:proto:instance}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_nrow ( A2 *mtx ) ;
\end{verbatim}
\index{A2_nrow@{\tt A2\_nrow()}}
This method returns the number of rows in the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_ncol ( A2 *mtx ) ;
\end{verbatim}
\index{A2_ncol@{\tt A2\_ncol()}}
This method returns the number of columns in the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_inc1 ( A2 *mtx ) ;
\end{verbatim}
\index{A2_inc1@{\tt A2\_inc1()}}
This method returns the primary increment, the stride in memory
(with respect to real or complex entries)
between adjacent entries in the same column.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_inc2 ( A2 *mtx ) ;
\end{verbatim}
\index{A2_inc2@{\tt A2\_inc2()}}
This method returns the secondary increment, the stride in memory
(with respect to real or complex entries)
between adjacent entries in the same row.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double * A2_entries ( A2 *mtx ) ;
\end{verbatim}
\index{A2_entries@{\tt A2\_entries()}}
This method returns a pointer to the base address of the entries.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double * A2_row ( A2 *mtx, int irow ) ;
\end{verbatim}
\index{A2_row@{\tt A2\_row()}}
This method returns a pointer to the leading element of row {\tt irow}.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt entries} is {\tt NULL},
or if {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double * A2_column ( A2 *mtx, int jcol ) ;
\end{verbatim}
\index{A2_column@{\tt A2\_column()}}
This method returns a pointer to the leading element
of column {\tt jcol}.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt entries} is {\tt NULL},
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_realEntry ( A2 *mtx, int irow, int jcol, double *pValue ) ;
\end{verbatim}
\index{A2_realEntry@{\tt A2\_realEntry()}}
This method fills {\tt *pValue} with the entry in
location {\tt (irow, jcol)}.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt pValue} is {\tt NULL},
or if the matrix is not real,
or {\tt irow} is not in {\tt [0,n1-1]},
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_complexEntry ( A2 *mtx, int irow, int jcol,
double *pReal, double *pImag ) ;
\end{verbatim}
\index{A2_complexEntry@{\tt A2\_complexEntry()}}
This method fills {\tt (*pReal,*pImag)} with the entry in
location {\tt (irow, jcol)}.
\par \noindent {\it Error checking:}
If {\tt mtx}, {\tt pReal} or {\tt pImag} is {\tt NULL},
or if the matrix is not complex,
or {\tt irow} is not in {\tt [0,n1-1]},
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_setRealEntry ( A2 *mtx, int irow, int jcol, double value ) ;
\end{verbatim}
\index{A2_setRealEntry@{\tt A2\_setRealEntry()}}
This method sets entry {\tt (irow,jcol)} to {\tt value}.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
or if the matrix is not real,
or {\tt irow} is not in {\tt [0,n1-1]}
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_setComplexEntry ( A2 *mtx, int irow, int jcol,
double real, double imag ) ;
\end{verbatim}
\index{A2_setComplexEntry@{\tt A2\_setComplexEntry()}}
This method sets entry {\tt (irow,jcol)} to {\tt (real,imag)}.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
or if the matrix is not complex,
or {\tt irow} is not in {\tt [0,n1-1]}
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_pointerToRealEntry ( A2 *mtx, int irow, int jcol, double **ppValue ) ;
\end{verbatim}
\index{A2_pointerToRealEntry@{\tt A2\_pointerToRealEntry()}}
This method sets {\tt *ppValue} to the pointer
of the {\tt (irow,jcol)} entry.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt ppValue} is {\tt NULL},
or if the matrix is not real,
or if {\tt irow} is not in {\tt [0,n1-1]},
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_pointerToComplexEntry ( A2 *mtx, int irow, int jcol,
double **ppReal, double **ppImag ) ;
\end{verbatim}
\index{A2_pointerToComplexEntry@{\tt A2\_pointerToComplexEntry()}}
This method sets {\tt *ppReal} to the pointer to the real part
of the {\tt (irow,jcol)} entry,
and sets {\tt *ppImag} to the pointer to the imaginary part
of the {\tt (irow,jcol)} entry.
\par \noindent {\it Error checking:}
If {\tt mtx}, {\tt ppReal} or {\tt ppImag} is {\tt NULL},
or if the matrix is not complex,
or if {\tt irow} is not in {\tt [0,n1-1]},
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initialize methods}
\label{subsection:A2:proto:initial}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_init ( A2 *mtx, int type, int n1, int n2, int inc1, int inc2,
double *entries ) ;
\end{verbatim}
\index{A2_init@{\tt A2\_init()}}
This is the basic initializer method.
We require that {\tt mtx} not be {\tt NULL},
{\tt type} be either {\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX},
{\tt n1} and {\tt n2} both be positive,
and both {\tt inc1} and {\tt inc2} both be
positive and that one of them be equal to one.
Also, we only initialize a full matrix, i.e.,
one of
{\tt inc1 = 1} and {\tt inc2 = nrow}
or
{\tt inc1 = ncol} and {\tt inc2 = 1}
must hold.
\par
The object is first cleared with a call to {\tt A2\_clearData()}.
If {\tt entries} is {\tt NULL} then {\tt n1*n2} new entries
are found, {\tt mtx->entries} is set to this address and {\tt nowned}
is set to {\tt n1*n2}.
If {\tt entries} is not {\tt NULL}, then {\tt mtx->entries} is set
to {\tt entries} and {\tt nowned} is set to zero.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
or if {\tt n1}, {\tt n2}, {\tt inc1} or {\tt inc2} are
less than or equal to zero,
or if the matrix is not full matrix
(i.e., {\tt inc1} must be {\tt 1} and {\tt inc2} must be {\tt n1},
{\it or}
{\tt inc1} must be {\tt n2} and {\tt inc2} must be {\tt 1}),
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_subA2 ( A2 *mtxA, A2 *mtxB,
int firstrow, int lastrow, int firstcol, int lastcol ) ;
\end{verbatim}
\index{A2_subA2@{\tt A2\_subA2()}}
This initializer method makes the object {\tt mtxA} point into a
submatrix of object {\tt mtxB}, as
\begin{verbatim}
A(0:lastrow-firstrow,0:lastcol-firstcol) = B(firstrow:lastrow, firstcol:lastcol)
\end{verbatim}
Note, {\tt firstrow}, {\tt lastrow}, {\tt firstcol} and {\tt lastcol}
must satisfy {\tt 0 <= firstrow <= lastrow < mtxB->n1}
and {\tt 0 <= firstcol <= lastcol < mtxB->n2}.
Object {\tt mtxA} does not own its entries, but points into the
entries of {\tt mtxB}.
\par \noindent {\it Error checking:}
If {\tt mtxA} or {\tt mtxB} are {\tt NULL},
or if {\tt firstrow} or {\tt lastrow} are out of range,
or if {\tt firstcol} or {\tt lastcol} are out of range,
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Methods used in the $QR$ factorization}
\label{subsection:A2:proto:QR}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_makeStaircase ( A2 *A ) ;
\end{verbatim}
\index{A2_makeStaircase@{\tt A2\_makeStaircase()}}
This method permutes the rows of {\tt A} by the location of the
leading nonzero of each row.
Upon return, the matrix is in {\it staircase} form.
\par \noindent {\it Error checking:}
If {\tt A} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_QRreduce ( A2 *A, DV *workDV, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{A2_QRreduce@{\tt A2\_QRreduce()}}
This method computes $A = QR$ factorization.
On return, the matrix $Q$ is not available, and $R$ is found in the
upper triangle or upper trapezoid of {\tt A}.
The Householder vectors are stored in the lower triangle of {\tt
mtxA}, with $v_j(j) = 1.0$.
The return value is the number of floating point operations that
were executed.
\par \noindent {\it Error checking:}
If {\tt A} or {\tt workDV} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} if {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_computeQ ( A2 *Q, A2 *A, DV *workDV, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{A2_computeQ@{\tt A2\_computeQ()}}
This method computes $Q$ from the $A = QR$ factorization computed
in {\tt A2\_QRreduce()}.
Note: {\tt A} and {\tt Q} must be column major.
\par \noindent {\it Error checking:}
If {\tt Q}, {\tt A} or {\tt workDV} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} if {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_applyQT ( A2 *Y, A2 *A, A2 *X, DV *workDV, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{A2_applyQT@{\tt A2\_applyQT()}}
This method computes $Y = Q^T X$ (if real) or $Y = Q^H X$ (if
complex), where $Q$ is stored in Householder vectors inside $A$.
We assume that $A2\_reduce()$ has been previously called with $A$
as an argument.
Since $Y$ is computed column-by-column, $X$ and $Y$ can be the same
{\tt A2} object.
The {\tt workDV} object is resized as necessary.
Note: {\tt Y}, {\tt A} and {\tt X} must be column major.
\par \noindent {\it Error checking:}
If {\tt Y}, {\tt A}, {\tt X} or {\tt workDV} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} if {\tt NULL},
or if {\tt Y}, {\tt A} or {\tt X} is not column major,
or if the types of {\tt Y}, {\tt A} and {\tt X} are not the same,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Norm methods}
\label{subsection:A2:proto:norms}
\par
These methods return a norm of a row or a column, or the easily
computable norms of the matrix.
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_maxabs ( A2 *mtx ) ;
\end{verbatim}
\index{A2_maxabs@{\tt A2\_maxabs()}}
This method returns magnitude of the entry with largest magnitude.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_frobNorm ( A2 *mtx ) ;
\end{verbatim}
\index{A2_frobNorm@{\tt A2\_frobNorm()}}
This method returns the Frobenius norm of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_oneNorm ( A2 *mtx ) ;
\end{verbatim}
\index{A2_oneNorm@{\tt A2\_oneNorm()}}
This method returns the one norm of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_infinityNorm ( A2 *mtx ) ;
\end{verbatim}
\index{A2_infinityNorm@{\tt A2\_infinityNorm()}}
This method returns the infinity norm of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_oneNormOfColumn ( A2 *mtx, int jcol ) ;
\end{verbatim}
\index{A2_oneNormOfColumn@{\tt A2\_oneNormOfColumn()}}
This method returns the one-norm of column {\tt jcol} of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL}, or {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_twoNormOfColumn ( A2 *mtx, int jcol ) ;
\end{verbatim}
\index{A2_twoNormOfColumn@{\tt A2\_twoNormOfColumn()}}
This method returns the two-norm of column {\tt jcol} of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL}, or {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_infinityNormOfColumn ( A2 *mtx, int jcol ) ;
\end{verbatim}
\index{A2_infinityNormOfColumn@{\tt A2\_infinityNormOfColumn()}}
This method returns the infinity-norm of column {\tt jcol}
of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL}, or {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_oneNormOfRow ( A2 *mtx, int irow ) ;
\end{verbatim}
\index{A2_oneNormOfRow@{\tt A2\_oneNormOfRow()}}
This method returns the one-norm of row {\tt irow} of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL}, or {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_twoNormOfRow ( A2 *mtx, int irow ) ;
\end{verbatim}
\index{A2_twoNormOfRow@{\tt A2\_twoNormOfRow()}}
This method returns the two-norm of row {\tt irow} of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL}, or {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double A2_infinityNormOfRow ( A2 *mtx, int irow ) ;
\end{verbatim}
\index{A2_infinityNormOfRow@{\tt A2\_infinityNormOfRow()}}
This method returns the infinity-norm of row {\tt irow}
of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL}, or {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Sort methods}
\label{subsection:A2:proto:sort}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_permuteRows ( A2 *mtx, int nrow, int index[] ) ;
\end{verbatim}
\index{A2_permuteRows@{\tt A2\_permuteRows()}}
The {\tt index[]} vector contains the {\it row ids} of the leading
{\tt nrow} rows.
This method permutes the leading {\tt nrow} rows of the matrix
so that the {\tt index[]} vector is in ascending order.
This method calls {\tt A2\_permuteRows()} but does not overwrite
the {\tt index[]} vector.
\par
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt index[]} is {\tt NULL},
or if {\tt nrow < 0} or {\tt nrow > n1},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_permuteColumns ( A2 *mtx, int nrow, int index[] ) ;
\end{verbatim}
\index{A2_permuteColumns@{\tt A2\_permuteColumns()}}
The {\tt index[]} vector contains the {\it column ids} of the leading
{\tt ncol} rows.
This method permutes the leading {\tt ncol} columns of the matrix
so that the {\tt index[]} vector is in ascending order.
This method calls {\tt A2\_permuteColumns()} but does not overwrite
the {\tt index[]} vector.
\par
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt index[]} is {\tt NULL},
or if {\tt ncol < 0} or {\tt ncol > n2},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_sortRowsUp ( A2 *mtx, int nrow, int rowids[] ) ;
\end{verbatim}
\index{A2_sortRowsUp@{\tt A2\_sortRowsUp()}}
This method sorts the leading {\tt nrow} rows of the matrix
into ascending order with respect to the {\tt rowids[]} vector.
The return value is the number of row swaps made.
\par
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt rowids} is {\tt NULL},
or if {\tt nrow < 0} or {\tt nrow > n1},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_sortColumnsUp ( A2 *mtx, int ncol, int colids[] ) ;
\end{verbatim}
\index{A2_sortColumnsUp@{\tt A2\_sortColumnsUp()}}
This method sorts the leading {\tt ncol} columnss of the matrix
into ascending order with respect to the {\tt colids[]} vector.
The return value is the number of column swaps made.
\par
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt colids} is {\tt NULL},
or if {\tt ncol < 0} or {\tt ncol > n2},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:A2:proto:utilities}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_sizeOf ( A2 *mtx ) ;
\end{verbatim}
\index{A2_sizeOf@{\tt A2\_sizeOf()}}
This method returns the number of bytes owned by this object.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_shiftBase ( A2 *mtx, int rowoff, int coloff ) ;
\end{verbatim}
\index{A2_shiftbase@{\tt A2\_shiftBase()}}
This method is used to shift the base of the entries and adjust
dimensions of the {\tt A2} object.
\begin{verbatim}
mtx(0:n1-rowoff-1,0:n2-coloff-1) := mtx(rowoff:n1-1,coloff:n2-1)
\end{verbatim}
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_rowMajor ( A2 *mtx ) ;
\end{verbatim}
\index{A2_rowMajor@{\tt A2\_rowMajor()}}
This method returns 1 if the storage is row major,
otherwise it returns zero.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_columnMajor ( A2 *mtx ) ;
\end{verbatim}
\index{A2_columnMajor@{\tt A2\_columnMajor()}}
This method returns 1 if the storage is column major,
otherwise it returns zero.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_transpose ( A2 *mtx ) ;
\end{verbatim}
\index{A2_transpose@{\tt A2\_transpose()}}
This method replaces {\tt mtx} with its transpose.
Note, this takes $O(1)$ operations since we just swap dimensions and
increments.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_extractRow ( A2 *mtx, double row[], int irow ) ;
\end{verbatim}
\index{A2_extractRow@{\tt A2\_extractRow()}}
This method fills the {\tt row[]} vector with row {\tt irow} of the
matrix.
\par \noindent {\it Error checking:}
If {\tt mtx}, {\tt entries} or {\tt row} are {\tt NULL},
or if {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_extractRowDV ( A2 *mtx, DV *rowDV, int irow ) ;
\end{verbatim}
\index{A2_extractRowDV@{\tt A2\_extractRowDV()}}
This method fills the {\tt rowDV} object with row {\tt irow} of the
matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt rowDV} are {\tt NULL},
or if the matrix is not real,
or if {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_extractRowZV ( A2 *mtx, ZV *rowZV, int irow ) ;
\end{verbatim}
\index{A2_extractRowZV@{\tt A2\_extractRowZV()}}
This method fills the {\tt rowZV} object with row {\tt irow} of the
matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt rowZV} are {\tt NULL},
or if the matrix is not complex,
or if {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_extractColumn ( A2 *mtx, double col[], int jcol ) ;
\end{verbatim}
\index{A2_extractColumn@{\tt A2\_extractColumn()}}
This method fills the {\tt col[]} vector
with column {\tt jcol} of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx}, {\tt entries} or {\tt col} are {\tt NULL},
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_extractColumnDV ( A2 *mtx, DV *colDV, int jcol ) ;
\end{verbatim}
\index{A2_extractColumnDV@{\tt A2\_extractColumnDV()}}
This method fills the {\tt colDV} object
with column {\tt jcol} of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt colDV} are {\tt NULL},
or if the matrix is not complex,
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_extractColumnZV ( A2 *mtx, ZV *colZV, int jcol ) ;
\end{verbatim}
\index{A2_extractColumnZV@{\tt A2\_extractColumnZV()}}
This method fills the {\tt colZV} object
with column {\tt jcol} of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt colZV} are {\tt NULL},
or if the matrix is not complex,
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_setRow ( A2 *mtx, double row[], int irow ) ;
\end{verbatim}
\index{A2_setRow@{\tt A2\_setRow()}}
This method fills row {\tt irow} of the matrix
with the entries in the {\tt row[]} vector.
\par \noindent {\it Error checking:}
If {\tt mtx}, {\tt entries} or {\tt row[]} are {\tt NULL},
or if {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_setRowDV ( A2 *mtx, DV rowDV, int irow ) ;
\end{verbatim}
\index{A2_setRowDV@{\tt A2\_setRowDV()}}
This method fills row {\tt irow} of the matrix
with the entries in the {\tt rowDV} object.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt rowDV} are {\tt NULL},
or if the matrix is not real,
or if {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_setRowZV ( A2 *mtx, ZV rowZV, int irow ) ;
\end{verbatim}
\index{A2_setRowZV@{\tt A2\_setRowZV()}}
This method fills row {\tt irow} of the matrix
with the entries in the {\tt rowZV} object.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt rowZV} are {\tt NULL},
or if the matrix is not complex,
or if {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_setColumn ( A2 *mtx, double col[], int jcol ) ;
\end{verbatim}
\index{A2_setColumn@{\tt A2\_setColumn()}}
This method fills column {\tt jcol} of the matrix with
the entries in the {\tt col[]} vector.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt colZV} are {\tt NULL},
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_setColumnDV ( A2 *mtx, DV colDV, int jcol ) ;
\end{verbatim}
\index{A2_setColumnDV@{\tt A2\_setColumnDV()}}
This method fills column {\tt jcol} of the matrix with
the entries in the {\tt colDV} object.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt colDV} are {\tt NULL},
or if the matrix is not complex,
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_setColumnZV ( A2 *mtx, ZV colZV, int jcol ) ;
\end{verbatim}
\index{A2_setColumnZV@{\tt A2\_setColumnZV()}}
This method fills column {\tt jcol} of the matrix with
the entries in the {\tt colZV} object.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt colZV} are {\tt NULL},
or if the matrix is not complex,
or if {\tt jcol} is not in {\tt [0,n2-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_fillRandomUniform ( A2 *mtx, double lower, double upper, int seed ) ;
\end{verbatim}
\index{A2_fillRandomUniform@{\tt A2\_fillRandomUniform()}}
This method fills the matrix with random numbers taken from a
uniform distribution on {\tt [lower,upper]} using the {\tt Drand}
object.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_fillRandomNormal ( A2 *mtx, double mean, double variance, int seed ) ;
\end{verbatim}
\index{A2_fillRandomNormal@{\tt A2\_fillRandomNormal()}}
This method fills the matrix with random numbers taken from a
normal distribution with mean {\tt mean} and variance {\tt
variance} using the {\tt Drand} object.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_fillWithIdentity ( A2 *mtx ) ;
\end{verbatim}
\index{A2_fillWithIdentity@{\tt A2\_fillWithIdentity()}}
This method fills the matrix with the identity matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL} or if {\tt n1 != n2},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_zero ( A2 *mtx ) ;
\end{verbatim}
\index{A2_zero@{\tt A2\_zero()}}
This method fills the matrix with zeros.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_copy ( A2 *mtxA, A2 *mtxB ) ;
\end{verbatim}
\index{A2_copy@{\tt A2\_copy()}}
This method copies entries from matrix {\tt mtxB}
into matrix {\tt mtxA}.
Note, {\tt mtxA} and {\tt mtxB} need not be of the same size,
the leading {\tt min(mtxA->n1,mtxB->n1)} rows
and {\tt min(mtxA->n2,mtxB->n2)} columns are copied.
\par \noindent {\it Error checking:}
If {\tt mtxA} or {\tt mtxB} is {\tt NULL},
or if the matrices are not of the same type,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_sub ( A2 *mtxA, A2 *mtxB ) ;
\end{verbatim}
\index{A2_sub@{\tt A2\_sub()}}
This method subtracts entries in matrix {\tt mtxB}
from entries in matrix {\tt mtxA}.
Note, {\tt mtxA} and {\tt mtxB} need not be of the same size,
the leading {\tt min(mtxA->n1,mtxB->n1)} rows
and {\tt min(mtxA->n2,mtxB->n2)} columns are subtracted.
\par \noindent {\it Error checking:}
If {\tt mtxA} or {\tt mtxB} is {\tt NULL},
or if the matrices are not of the same type,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_swapRows ( A2 *mtx, int irow1, int irow2 ) ;
\end{verbatim}
\index{A2_swapRows@{\tt A2\_swapRows()}}
This method swaps rows {\tt irow1} and {\tt irow2} of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtxA} or {\tt mtxB} is {\tt NULL},
or if {\tt irow1} or {\tt irow2} are out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_swapColumns ( A2 *mtx, int irow1, int irow2 ) ;
\end{verbatim}
\index{A2_swapColumns@{\tt A2\_swapColumns()}}
This method swaps columns {\tt jcol1} and {\tt jcol2} of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtxA} or {\tt mtxB} is {\tt NULL},
or if {\tt jcol1} or {\tt jcol1} are out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_copyEntriesToVector ( A2 *mtx, int length, double dvec[],
int copyflag, int storeflag ) ;
\end{verbatim}
\index{A2_copyEntriesToVector@{\tt A2\_copyEntriesToVector()}}
This method copies selected entries from {\tt mtx} into the vector
{\tt dvec[]} with length {\tt length}.
The return value is the number of entries copied.
This method is used during the $QR$ factorization to extract factor
entries and update matrix entries from a front.
All entries may be copied, or
only the diagonal, lower or upper entries,
and the entries may be copied to {\tt dvec[]} by rows or by
columns.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt dvec} is {\tt NULL},
or if {\tt length} is not as large as the number of entries to be
copied,
or if {\tt copyflag} is not one of {\tt A2\_STRICT\_LOWER},
{\tt A2\_LOWER}, {\tt A2\_DIAGONAL}, {\tt A2\_UPPER},
{\tt A2\_STRICT\_UPPER} or {\tt A2\_ALL\_ENTRIES},
or if {\tt storeflag} is not one of {\tt A2\_BY\_ROWS}
or {\tt A2\_BY\_COLUMNS},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:A2:proto:IO}
\par
There are the usual eight IO routines plus a method to write the
object to a Matlab file.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_readFromFile ( A2 *mtx, char *fn ) ;
\end{verbatim}
\index{A2_readFromFile@{\tt A2\_readFromFile()}}
\par
This method reads a {\tt A2} object from a file.
It tries to open the file and if it is successful,
it then calls {\tt A2\_readFromFormattedFile()} or
{\tt A2\_readFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.a2f} (for a formatted file)
or {\tt *.a2b} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_readFromFormattedFile ( A2 *mtx, FILE *fp ) ;
\end{verbatim}
\index{A2_readFromFormattedFile@{\tt A2\_readFromFormattedFile()}}
\par
This method reads a {\tt A2} object from a formatted file
whose pointer is {\tt fp}.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fscanf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_readFromBinaryFile ( A2 *mtx, FILE *fp ) ;
\end{verbatim}
\index{A2_readFromBinaryFile@{\tt A2\_readFromBinaryFile()}}
\par
This method reads a {\tt A2} object from a binary file
whose pointer is {\tt fp}.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fread}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_writeToFile ( A2 *mtx, char *fn ) ;
\end{verbatim}
\index{A2_writeToFile@{\tt A2\_writeToFile()}}
\par
This method writes a {\tt A2} object to a file.
It tries to open the file and if it is successful,
it then calls {\tt A2\_writeFromFormattedFile()} or
{\tt A2\_writeFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.a2f} (for a formatted file)
or {\tt *.a2b} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_writeToFormattedFile ( A2 *mtx, FILE *fp ) ;
\end{verbatim}
\index{A2_writeToFormattedFile@{\tt A2\_writeToFormattedFile()}}
\par
This method writes a {\tt A2} object to a formatted file
whose pointer is {\tt fp}.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fprintf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int A2_writeToBinaryFile ( A2 *mtx, FILE *fp ) ;
\end{verbatim}
\index{A2_writeToBinaryFile@{\tt A2\_writeToBinaryFile()}}
\par
This method writes a {\tt A2} object to a binary file
whose pointer is {\tt fp}.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fwrite}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_writeForHumanEye ( A2 *mtx, FILE *fp ) ;
\end{verbatim}
\index{A2_writeForHumanEye@{\tt A2\_writeForHumanEye()}}
\par
This method writes a {\tt A2} object to a file in an easily
readable format.
The method {\tt A2\_writeStats()} is called to write out the
header and statistics.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_writeStats ( A2 *mtx, FILE *fp ) ;
\end{verbatim}
\index{A2_writeStats@{\tt A2\_writeStats()}}
\par
This method writes a header and some statistics to a file.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_writeForMatlab ( A2 *mtx, char *mtxname, FILE *fp ) ;
\end{verbatim}
\index{A2_writeForMatlab@{\tt A2\_writeForMatlab()}}
\par
This method writes the entries of the matrix to a file
in Matlab format.
The name of the matrix is {\tt mtxname}.
\par \noindent {\it Error checking:}
If {\tt mtx}, {\tt mtxname} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
tt Drand}
object.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void A2_fillRandomNormal ( A2 *mtx, double mean, double variance, int seed ) ;
\A2/doc/main.log 0100644 0002055 0007177 00000007511 06650162453 0014542 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.14159 (C version 6.1) (format=latex 97.4.4) 16 JAN 1999 11:14
**main
(main.tex
LaTeX2e <1996/12/01> patch level 1
Babel and hyphenation patterns for english, german, loaded.
(/home/tex/teTeX/texmf/tex/latex/base/report.cls
Document Class: report 1996/10/31 v1.3u Standard LaTeX document class
(/home/tex/teTeX/texmf/tex/latex/base/leqno.clo
File: leqno.clo 1996/07/26 v1.1b Standard LaTeX option (left equation numbers)
)
(/home/tex/teTeX/texmf/tex/latex/base/size10.clo
File: size10.clo 1996/10/31 v1.3u Standard LaTeX file (size option)
)
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
\abovecaptionskip=\skip41
\belowcaptionskip=\skip42
\bibindent=\dimen102
)
\@indexfile=\write3
Writing index file main.idx
(main.aux)
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 17.
LaTeX Font Info: ... okay on input line 17.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 17.
LaTeX Font Info: ... okay on input line 17.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 17.
LaTeX Font Info: ... okay on input line 17.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 17.
LaTeX Font Info: ... okay on input line 17.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 17.
LaTeX Font Info: ... okay on input line 17.
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 17.
LaTeX Font Info: ... okay on input line 17.
(intro.tex
Chapter 1.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <7> on input line 9.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <5> on input line 9.
) (dataStructure.tex
LaTeX Font Info: Try loading font information for OMS+cmr on input line 9.
(/home/tex/teTeX/texmf/tex/latex/base/omscmr.fd
File: omscmr.fd 1997/01/14 v2.5a Standard LaTeX font definitions
)
LaTeX Font Info: Font shape `OMS/cmr/m/n' in size <10> not available
(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 9.
Overfull \hbox (22.05931pt too wide) in paragraph at lines 44--54
\OT1/cmr/m/n/10 The \OT1/cmtt/m/n/10 A2[]copyEntriesToVector() \OT1/cmr/m/n/10
method uses the fol-low-ing con-stants: \OT1/cmtt/m/n/10 A2[]STRICT[]LOWER\OT1/
cmr/m/n/10 , \OT1/cmtt/m/n/10 A2[]LOWER\OT1/cmr/m/n/10 , \OT1/cmtt/m/n/10 A2[]D
IAGONAL\OT1/cmr/m/n/10 ,
[]
) (proto.tex [1
] [2] [3]
Overfull \hbox (9.5478pt too wide) in paragraph at lines 290--295
\OT1/cmr/m/n/10 Note, \OT1/cmtt/m/n/10 firstrow\OT1/cmr/m/n/10 , \OT1/cmtt/m/n/
10 lastrow\OT1/cmr/m/n/10 , \OT1/cmtt/m/n/10 firstcol \OT1/cmr/m/n/10 and \OT1/
cmtt/m/n/10 lastcol \OT1/cmr/m/n/10 must sat-isfy \OT1/cmtt/m/n/10 0 <= firstro
w <= lastrow < mtxB->n1
[]
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <12> on input line 303.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <8> on input line 303.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <6> on input line 303.
[4] [5] [6] [7]
Overfull \hbox (0.273pt too wide) in paragraph at lines 776--779
[]\OT1/cmr/m/n/10 This method fills the ma-trix with ran-dom num-bers taken fro
m a uni-form dis-tri-bu-tion on \OT1/cmtt/m/n/10 [lower,upper]
[]
[8] [9]) (drivers.tex [10]) (main.ind [11] [12
]) (main.aux) )
Here is how much of TeX's memory you used:
321 strings out of 10908
3334 string characters out of 72189
50228 words of memory out of 262141
3233 multiletter control sequences out of 9500
9705 words of font info for 35 fonts, out of 150000 for 255
14 hyphenation exceptions out of 607
23i,5n,21p,140b,423s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (12 pages, 42424 bytes).
A2/doc/main.aux 0100644 0002055 0007177 00000003223 06650162453 0014552 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\contentsline {chapter}{\numberline {1}{\tt A2}: Real or complex 2-D array}{1}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {1.1}Data Structure}{1}}
\newlabel{section:A2:dataStructure}{{1.1}{1}}
\@writefile{toc}{\contentsline {section}{\numberline {1.2}Prototypes and descriptions of {\tt A2} methods}{1}}
\newlabel{section:A2:proto}{{1.2}{1}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.1}Basic methods}{2}}
\newlabel{subsection:A2:proto:basics}{{1.2.1}{2}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.2}Instance methods}{2}}
\newlabel{subsection:A2:proto:instance}{{1.2.2}{2}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.3}Initialize methods}{4}}
\newlabel{subsection:A2:proto:initial}{{1.2.3}{4}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.4}Methods used in the $QR$ factorization}{4}}
\newlabel{subsection:A2:proto:QR}{{1.2.4}{4}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.5}Norm methods}{5}}
\newlabel{subsection:A2:proto:norms}{{1.2.5}{5}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.6}Sort methods}{6}}
\newlabel{subsection:A2:proto:sort}{{1.2.6}{6}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.7}Utility methods}{6}}
\newlabel{subsection:A2:proto:utilities}{{1.2.7}{6}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.8}IO methods}{9}}
\newlabel{subsection:A2:proto:IO}{{1.2.8}{9}}
\@writefile{toc}{\contentsline {section}{\numberline {1.3}Driver programs for the {\tt A2 object}}{10}}
\newlabel{section:A2:drivers}{{1.3}{10}}
A2/doc/main.idx 0100644 0002055 0007177 00000007542 06650162453 0014551 0 ustar 00cleve compmath 0000040 0000006 \indexentry{A2_new@{\tt A2\_new()}}{2}
\indexentry{A2_setDefaultFields@{\tt A2\_setDefaultFields()}}{2}
\indexentry{A2_clearData@{\tt A2\_clearData()}}{2}
\indexentry{A2_free@{\tt A2\_free()}}{2}
\indexentry{A2_nrow@{\tt A2\_nrow()}}{2}
\indexentry{A2_ncol@{\tt A2\_ncol()}}{2}
\indexentry{A2_inc1@{\tt A2\_inc1()}}{2}
\indexentry{A2_inc2@{\tt A2\_inc2()}}{2}
\indexentry{A2_entries@{\tt A2\_entries()}}{2}
\indexentry{A2_row@{\tt A2\_row()}}{3}
\indexentry{A2_column@{\tt A2\_column()}}{3}
\indexentry{A2_realEntry@{\tt A2\_realEntry()}}{3}
\indexentry{A2_complexEntry@{\tt A2\_complexEntry()}}{3}
\indexentry{A2_setRealEntry@{\tt A2\_setRealEntry()}}{3}
\indexentry{A2_setComplexEntry@{\tt A2\_setComplexEntry()}}{3}
\indexentry{A2_pointerToRealEntry@{\tt A2\_pointerToRealEntry()}}{3}
\indexentry{A2_pointerToComplexEntry@{\tt A2\_pointerToComplexEntry()}}{3}
\indexentry{A2_init@{\tt A2\_init()}}{4}
\indexentry{A2_subA2@{\tt A2\_subA2()}}{4}
\indexentry{A2_makeStaircase@{\tt A2\_makeStaircase()}}{4}
\indexentry{A2_QRreduce@{\tt A2\_QRreduce()}}{4}
\indexentry{A2_computeQ@{\tt A2\_computeQ()}}{4}
\indexentry{A2_applyQT@{\tt A2\_applyQT()}}{5}
\indexentry{A2_maxabs@{\tt A2\_maxabs()}}{5}
\indexentry{A2_frobNorm@{\tt A2\_frobNorm()}}{5}
\indexentry{A2_oneNorm@{\tt A2\_oneNorm()}}{5}
\indexentry{A2_infinityNorm@{\tt A2\_infinityNorm()}}{5}
\indexentry{A2_oneNormOfColumn@{\tt A2\_oneNormOfColumn()}}{5}
\indexentry{A2_twoNormOfColumn@{\tt A2\_twoNormOfColumn()}}{5}
\indexentry{A2_infinityNormOfColumn@{\tt A2\_infinityNormOfColumn()}}{5}
\indexentry{A2_oneNormOfRow@{\tt A2\_oneNormOfRow()}}{5}
\indexentry{A2_twoNormOfRow@{\tt A2\_twoNormOfRow()}}{6}
\indexentry{A2_infinityNormOfRow@{\tt A2\_infinityNormOfRow()}}{6}
\indexentry{A2_permuteRows@{\tt A2\_permuteRows()}}{6}
\indexentry{A2_permuteColumns@{\tt A2\_permuteColumns()}}{6}
\indexentry{A2_sortRowsUp@{\tt A2\_sortRowsUp()}}{6}
\indexentry{A2_sortColumnsUp@{\tt A2\_sortColumnsUp()}}{6}
\indexentry{A2_sizeOf@{\tt A2\_sizeOf()}}{6}
\indexentry{A2_shiftbase@{\tt A2\_shiftBase()}}{6}
\indexentry{A2_rowMajor@{\tt A2\_rowMajor()}}{7}
\indexentry{A2_columnMajor@{\tt A2\_columnMajor()}}{7}
\indexentry{A2_transpose@{\tt A2\_transpose()}}{7}
\indexentry{A2_extractRow@{\tt A2\_extractRow()}}{7}
\indexentry{A2_extractRowDV@{\tt A2\_extractRowDV()}}{7}
\indexentry{A2_extractRowZV@{\tt A2\_extractRowZV()}}{7}
\indexentry{A2_extractColumn@{\tt A2\_extractColumn()}}{7}
\indexentry{A2_extractColumnDV@{\tt A2\_extractColumnDV()}}{7}
\indexentry{A2_extractColumnZV@{\tt A2\_extractColumnZV()}}{7}
\indexentry{A2_setRow@{\tt A2\_setRow()}}{7}
\indexentry{A2_setRowDV@{\tt A2\_setRowDV()}}{8}
\indexentry{A2_setRowZV@{\tt A2\_setRowZV()}}{8}
\indexentry{A2_setColumn@{\tt A2\_setColumn()}}{8}
\indexentry{A2_setColumnDV@{\tt A2\_setColumnDV()}}{8}
\indexentry{A2_setColumnZV@{\tt A2\_setColumnZV()}}{8}
\indexentry{A2_fillRandomUniform@{\tt A2\_fillRandomUniform()}}{8}
\indexentry{A2_fillRandomNormal@{\tt A2\_fillRandomNormal()}}{8}
\indexentry{A2_fillWithIdentity@{\tt A2\_fillWithIdentity()}}{8}
\indexentry{A2_zero@{\tt A2\_zero()}}{8}
\indexentry{A2_copy@{\tt A2\_copy()}}{8}
\indexentry{A2_sub@{\tt A2\_sub()}}{9}
\indexentry{A2_swapRows@{\tt A2\_swapRows()}}{9}
\indexentry{A2_swapColumns@{\tt A2\_swapColumns()}}{9}
\indexentry{A2_copyEntriesToVector@{\tt A2\_copyEntriesToVector()}}{9}
\indexentry{A2_readFromFile@{\tt A2\_readFromFile()}}{9}
\indexentry{A2_readFromFormattedFile@{\tt A2\_readFromFormattedFile()}}{9}
\indexentry{A2_readFromBinaryFile@{\tt A2\_readFromBinaryFile()}}{9}
\indexentry{A2_writeToFile@{\tt A2\_writeToFile()}}{10}
\indexentry{A2_writeToFormattedFile@{\tt A2\_writeToFormattedFile()}}{10}
\indexentry{A2_writeToBinaryFile@{\tt A2\_writeToBinaryFile()}}{10}
\indexentry{A2_writeForHumanEye@{\tt A2\_writeForHumanEye()}}{10}
\indexentry{A2_writeStats@{\tt A2\_writeStats()}}{10}
\indexentry{A2_writeForMatlab@{\tt A2\_writeForMatlab()}}{10}
A2/doc/main.ind 0100644 0002055 0007177 00000004612 06622330554 0014530 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt A2\_clearData()}, 2
\item {\tt A2\_column()}, 3
\item {\tt A2\_columnMajor()}, 6
\item {\tt A2\_complexEntry()}, 3
\item {\tt A2\_copy()}, 8
\item {\tt A2\_copyEntriesToVector()}, 9
\item {\tt A2\_entries()}, 2
\item {\tt A2\_extractColumn()}, 7
\item {\tt A2\_extractColumnDV()}, 7
\item {\tt A2\_extractColumnZV()}, 7
\item {\tt A2\_extractRow()}, 7
\item {\tt A2\_extractRowDV()}, 7
\item {\tt A2\_extractRowZV()}, 7
\item {\tt A2\_fillRandomUniform()}, 8
\item {\tt A2\_fillWithIdentity()}, 8
\item {\tt A2\_free()}, 2
\item {\tt A2\_frobNorm()}, 5
\item {\tt A2\_inc1()}, 2
\item {\tt A2\_inc2()}, 2
\item {\tt A2\_infinityNorm()}, 5
\item {\tt A2\_infinityNormOfColumn()}, 5
\item {\tt A2\_infinityNormOfRow()}, 5
\item {\tt A2\_init()}, 4
\item {\tt A2\_makeStaircase()}, 4
\item {\tt A2\_maxabs()}, 5
\item {\tt A2\_ncol()}, 2
\item {\tt A2\_new()}, 2
\item {\tt A2\_nrow()}, 2
\item {\tt A2\_oneNorm()}, 5
\item {\tt A2\_oneNormOfColumn()}, 5
\item {\tt A2\_oneNormOfRow()}, 5
\item {\tt A2\_permuteColumns()}, 6
\item {\tt A2\_permuteRows()}, 6
\item {\tt A2\_pointerToComplexEntry()}, 3
\item {\tt A2\_pointerToRealEntry()}, 3
\item {\tt A2\_QRreduce2()}, 4
\item {\tt A2\_readFromBinaryFile()}, 9
\item {\tt A2\_readFromFile()}, 9
\item {\tt A2\_readFromFormattedFile()}, 9
\item {\tt A2\_realEntry()}, 3
\item {\tt A2\_row()}, 3
\item {\tt A2\_rowMajor()}, 6
\item {\tt A2\_setColumn()}, 8
\item {\tt A2\_setColumnDV()}, 8
\item {\tt A2\_setColumnZV()}, 8
\item {\tt A2\_setComplexEntry()}, 3
\item {\tt A2\_setDefaultFields()}, 2
\item {\tt A2\_setRealEntry()}, 3
\item {\tt A2\_setRow()}, 7
\item {\tt A2\_setRowDV()}, 7
\item {\tt A2\_setRowZV()}, 7
\item {\tt A2\_shiftBase()}, 6
\item {\tt A2\_sizeOf()}, 6
\item {\tt A2\_sortColumnsUp()}, 6
\item {\tt A2\_sortRowsUp()}, 6
\item {\tt A2\_sub()}, 8
\item {\tt A2\_subA2()}, 4
\item {\tt A2\_swapColumns()}, 9
\item {\tt A2\_swapRows()}, 8
\item {\tt A2\_transpose()}, 7
\item {\tt A2\_twoNormOfColumn()}, 5
\item {\tt A2\_twoNormOfRow()}, 5
\item {\tt A2\_writeForHumanEye()}, 10
\item {\tt A2\_writeForMatlab()}, 10
\item {\tt A2\_writeStats()}, 10
\item {\tt A2\_writeToBinaryFile()}, 10
\item {\tt A2\_writeToFile()}, 9
\item {\tt A2\_writeToFormattedFile()}, 9
\item {\tt A2\_zero()}, 8
\end{theindex}
A2/doc/main.ilg 0100644 0002055 0007177 00000000457 06622330554 0014534 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (69 entries accepted, 0 rejected).
Sorting entries....done (417 comparisons).
Generating output file main.ind....done (73 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
A2/doc/makefile 0100644 0002055 0007177 00000000027 06542767257 0014623 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
A2/doc/drivers.tex 0100644 0002055 0007177 00000005513 06535056617 0015321 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt A2 object}}
\label{section:A2:drivers}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_norms msglvl msgFile type nrow ncol inc1 inc2 seed
\end{verbatim}
This driver program tests the {\tt A2} norm methods.
Use the script file {\tt do\_norms} for testing.
When the output file is loaded into matlab,
the last two lines contain matrices whose
entries should all be around machine epsilon.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt nrow} parameter is the number of rows.
\item
The {\tt ncol} parameter is the number of rows.
\item
The {\tt inc1} parameter is the row increment.
\item
The {\tt inc2} parameter is the column increment.
\item
The {\tt seed} parameter is a random number seed.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_QR msglvl msgFile type nrow ncol inc1 inc2 seed
\end{verbatim}
This driver program tests the {\tt A2\_QRreduce()} and
{\tt A2\_QRreduce2()} methods which reduce $A$ to $QR$
via rank-1 and rank-2 updates.
Use the script file {\tt do\_QR} for testing.
When {\tt msglvl > 1}, the matrix $A$ and matrices $R1$ and $R2$
(computed from {\tt A2\_QRreduce()} and
{\tt A2\_QRreduce2()}, respectively)
are printed to the message file.
When the output file is loaded into matlab,
the errors $A^TA - R_1^TR_1$ and $A^TA - R_2^TR_2$
(if $A$ is real)
or
the errors $A^HA - R_1^HR_1$ and $A^HA - R_2^HR_2$
(if $A$ is complex) are computed.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt nrow} parameter is the number of rows.
\item
The {\tt ncol} parameter is the number of rows.
\item
The {\tt inc1} parameter is the row increment.
\item
The {\tt inc2} parameter is the column increment.
\item
The {\tt seed} parameter is a random number seed.
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
--------------------------------------------
\item
\begin{verbatim}
test_QR msglvl msgFile type nrow ncol inc1 inc2 seed
\end{verbatim}
This driver program tests the {\tt A2\_QRreduA2/doc/main.ps 0100644 0002055 0007177 00002312252 06636037154 0014411 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0
%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software
%%Title: main.dvi
%%Pages: 12
%%PageOrder: Ascend
%%BoundingBox: 0 0 612 792
%%DocumentFonts: CMBX12 CMTT12 CMR10 CMTT10 CMMI10 CMSY10 CMTI10 CMSL10
%%+ CMMI12 CMMI7 CMR7
%%DocumentPaperSizes: Letter
%%EndComments
%DVIPSCommandLine: dvips main -o
%DVIPSParameters: dpi=600, comments removed
%DVIPSSource: TeX output 1998.12.16:1512
%%BeginProcSet: tex.pro
/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N
/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72
mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1}
ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale
isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div
hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul
TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if}
forall round exch round exch]setmatrix}N /@landscape{/isls true N}B
/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B
/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{
/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N
string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N
end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{
/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0]
N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup
length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{
128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub
get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data
dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N
/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup
/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx
0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff
setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff
.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]}
if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup
length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{
cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin
0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul
add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict
/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook
known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X
/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for
65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0
0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V
{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7
getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false}
ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false
RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1
false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform
round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg
rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail
{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M}
B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{
4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{
p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p
a}B /bos{/SS save N}B /eos{SS restore}B end
%%EndProcSet
%%BeginFont: CMBX12
%!PS-AdobeFont-1.1: CMBX12 1.0
%%CreationDate: 1991 Aug 20 16:34:54
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.0) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMBX12) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Bold) readonly def
/ItalicAngle 0 def
/isFixedPitch false def
end readonly def
/FontName /CMBX12 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /Gamma put
dup 162 /Delta put
dup 163 /Theta put
dup 164 /Lambda put
dup 165 /Xi put
dup 166 /Pi put
dup 167 /Sigma put
dup 168 /Upsilon put
dup 169 /Phi put
dup 170 /Psi put
dup 173 /Omega put
dup 174 /ff put
dup 175 /fi put
dup 176 /fl put
dup 177 /ffi put
dup 178 /ffl put
dup 179 /dotlessi put
dup 180 /dotlessj put
dup 181 /grave put
dup 182 /acute put
dup 183 /caron put
dup 184 /breve put
dup 185 /macron put
dup 186 /ring put
dup 187 /cedilla put
dup 188 /germandbls put
dup 189 /ae put
dup 190 /oe put
dup 191 /oslash put
dup 192 /AE put
dup 193 /OE put
dup 194 /Oslash put
dup 195 /suppress put
dup 196 /dieresis put
dup 0 /Gamma put
dup 1 /Delta put
dup 2 /Theta put
dup 3 /Lambda put
dup 4 /Xi put
dup 5 /Pi put
dup 6 /Sigma put
dup 7 /Upsilon put
dup 8 /Phi put
dup 9 /Psi put
dup 10 /Omega put
dup 11 /ff put
dup 12 /fi put
dup 13 /fl put
dup 14 /ffi put
dup 15 /ffl put
dup 16 /dotlessi put
dup 17 /dotlessj put
dup 18 /grave put
dup 19 /acute put
dup 20 /caron put
dup 21 /breve put
dup 22 /macron put
dup 23 /ring put
dup 24 /cedilla put
dup 25 /germandbls put
dup 26 /ae put
dup 27 /oe put
dup 28 /oslash put
dup 29 /AE put
dup 30 /OE put
dup 31 /Oslash put
dup 32 /suppress put
dup 33 /exclam put
dup 34 /quotedblright put
dup 35 /numbersign put
dup 36 /dollar put
dup 37 /percent put
dup 38 /ampersand put
dup 39 /quoteright put
dup 40 /parenleft put
dup 41 /parenright put
dup 42 /asterisk put
dup 43 /plus put
dup 44 /comma put
dup 45 /hyphen put
dup 46 /period put
dup 47 /slash put
dup 48 /zero put
dup 49 /one put
dup 50 /two put
dup 51 /three put
dup 52 /four put
dup 53 /five put
dup 54 /six put
dup 55 /seven put
dup 56 /eight put
dup 57 /nine put
dup 58 /colon put
dup 59 /semicolon put
dup 60 /exclamdown put
dup 61 /equal put
dup 62 /questiondown put
dup 63 /question put
dup 64 /at put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /bracketleft put
dup 92 /quotedblleft put
dup 93 /bracketright put
dup 94 /circumflex put
dup 95 /dotaccent put
dup 96 /quoteleft put
dup 97 /a put
dup 98 /b put
dup 99 /c put
dup 100 /d put
dup 101 /e put
dup 102 /f put
dup 103 /g put
dup 104 /h put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 108 /l put
dup 109 /m put
dup 110 /n put
dup 111 /o put
dup 112 /p put
dup 113 /q put
dup 114 /r put
dup 115 /s put
dup 116 /t put
dup 117 /u put
dup 118 /v put
dup 119 /w put
dup 120 /x put
dup 121 /y put
dup 122 /z put
dup 123 /endash put
dup 124 /emdash put
dup 125 /hungarumlaut put
dup 126 /tilde put
dup 127 /dieresis put
dup 128 /suppress put
dup 160 /space put
readonly def
/FontBBox{-53 -251 1139 750}readonly def
/UniqueID 5000769 def
currentdict end
currentfile eexec
9B9C1569015F2C1D2BF560F4C0D52257BACDD6500ABDA5ED9835F6A016CFC8F00B6C052ED76A
87856B50F4D80DFAEB508C97F8281F3F88B17E4D3B90C0F65EC379791AACDC162A66CBBC5BE2
F53AAD8DE72DD113B55A022FBFEE658CB95F5BB32BA0357B5E050FDDF264A07470BEF1C52119
B6FBD5C77EBED964AC5A2BBEC9D8B3E48AE5BB003A63D545774B922B9D5FF6B0066ECE43645A
131879B032137D6D823385FE55F3402D557FD3B4486BE79011D1F5BFAE5C1F476EE6F05EB1D2
CAEB269958B194521197B312FCCED4867F3C8FBD030BD715D8FFDA1DCD454B174E7A1A97B59F
E770E67702519D9D9B23D61AC08424D555242A8CA08C49AEF300945D99B999A79CE74804AE6B
FDE623F4463371442F6523A5F6CE19C839A708C025132E22C696C8CCADE45680E5197189D0F9
8E7F0D5F955E353970B392CF530A68CC56B0035DDFBF206C3074BEEB0739DCBCA272A6E629FB
7AEA2C5BA7BAE50C7B4CA595DF78200C352997EC3EE564DF229FBB5473F5E8CCB1CC0153E9A7
E299A8EAA29B69D1B622B1F0CFFC58291248759607D91150CB0651120970DC9F743BEBEF44F6
AE92FACEC57658999C8BF01F60611560043962C0695E1BB87D090E0FDAAB659D6557208A660B
E9AEEF8AE55F71B8BC76394D792967E41BD8023B6E7F8C3D9987D5E54C53BF2BBB32855B9464
73B44833BD78873DF8E4C7E668FFFF25AABB8DA4148F744B9D0524D6CB8281247B3052CC5D66
F3F1BCF8A56A3FB446EA587BD8BE30257652CEE035628AEDDFD8283B5AD21B8B1480AD24D898
970AC8A1E33E543CE4E3C48F9EE621C5CE3E8AE930F890011B630866C988606068D9E92396EB
F51BB3DB204505FC3D09D4701AC703A14D92BBFE27BD7411B363A88E33A8E9A8025AC31F21E7
3DC52B333B918D0B1270C54873A490222D041A66E0192612BE6D2C88958A8F70C10390146EE5
091DF020AB97675E8E6901226EED50125D36C221BE8F20647442444B13F0325F899B8FA15E14
14119B45F920F73DC3496F6DE0DD4418A1181E791B49A52866C79D377494BEFF7F1B444111BC
A4FC2BFB7279FA2938FA9BE2DE762F20D470813C4EE0034371812EFB9F87014528B7A09BE4F0
1F1F84DE922D6C66D7F6FF96A49233B2396D9C19B85B132FF565893AD3A11DDB88E469FC1DEC
D51E5B3FADFD1E3E50914839DEE5D5D2B63F83E8A7953833EFE2492A30314F32E2BD9A758F2A
BDA8107618EEF886F13905EECE29E3A0267FA506A77271C89450B6CB4320E2A9169EC494917A
370CE72227860BB7ECCA9D1DAC4AFDD4BC59CA1DFC10A5D530DC1E8AFA557BA49454F211BBB2
4B86044A9008092E262BBACE0C5F084A66DAB3BD57DF91E3D4440C9974666E46AF84B0C0F928
6045D15EF5C5E601CFC42D8D2A14117BF73DF97A8C602FAFA97F13823603CD70D202551F6BAE
D6F13442564A85BAF8FC53676FCA540943F23146BEEF9691FC26B2C7327B63627570EAA85ACE
4938C3884221F1A91F5E57E303425C649D12E0977D78BC7D32CB30710817926509A49DAE5C95
30BD89B44C105695CE609BABD50A7A2CCDB30F679D849577A8E7C0300D2606DAC4658B4A0555
DF2D2740EC5F9D76270DAC943DA0E0271755607D355709DC9B0DB68098E3DED0C081DD742BFA
7C29090A2BDA699D4EBBAD79BB3B901E59159869FF13361A167ECDC51D1E655F475D453CCF93
5F637C2CF08B222968F2DA3D3630A9747CB5B8AC4B042BC44CC22A488CC8099AA15FA2C43D1B
C9ADAFB2A4129E880F5CFCD563B41A16096EA07B96BCE2B2E81C89968F5A3949889EBDF25E07
042B81DFF462DB36311BB3FAF1387A3BFF193C09FF4972FF743A3FAC0DD57995444D2AE34BA0
A8AA9C69457654D2221C8927124BF9E1B2D768CF672CDE3A6945E627F11D1D08E1403A06ADDC
A67CAA82958FFD15CE17CEB235F4CA05231E6E10CC2BC7803FC2F92CBFDCDD09F100A0CDA8B6
D73A1F2F4778BE732F2FFD8AF6170FC11D37A83C9260606E5EB14A411E1C7CD5B6D2E0D722A3
7A1F628512DD6598F9845398F854BB17DF1840FA7AF1CD58981A5EA8993F45CC1A3FFEB6BACA
6CF815DADCE91BB92C9BE218C4BD91EBEAEE4E17E302284B42FACDCC1ABA0C22A8FE7A30E401
6EC238B6A530112E7BC5371AB48E599F966C94EBDA672001483D1E35E683F93EBB02BA0F647C
6F79918B8E2D7C0D292F306BC366B9679A7A8A5998250DC90F0A752E5A23EDA3CD8B699BA875
E05D2B6758C1F886864764FE26BAAFD976AC47150B12B93C97315AB530EEF6A8F8D32B727F84
EB7C05DAEA7DF55B4847AD59DBEF771A5E47347E8A5872B4A2414EF8A4D1B37924BE9FC1DCCA
A10D6E78817CDB99D5F42D5645454AA8D2151E48EEE83725BED583D358514F58A919256F22E1
AC4BF1CA50DF0F807470859EF15928B40B9C95B6116B1FFD997B32D93E38B128C9230D1A040F
B8B3829FD409FE25BD28EA79BA3258B22F939D7985A98C8FAF502225F5100B3EF74E4520531D
F8C8A2D3AC2D58E3253CB250D45E7E556DD90CEC4592C52D9156606C4DD6382BBAB9F31DCE02
BA08F28FFE973935DBF3C98DC25CFCF02ABAC24117B76E4792525848C321C47505D2FEED7623
6E9780014483026CC580F40C5F259AD273E1F24DB59B1639B1BCB62290D4AB2B2088FE370158
BF3C2431A00256C9658DD428D0DF17D1F89C7689E1E0C659B595C4C34BF20DE7F5C0F3649BE0
87B6DD06CFCC99E75CFFCBC48BB87101E0877A8FDB807754688211F442CEAB20069AFA09DB64
5E42B931FC22C739B14110DA27C7B04D591FF8DF2F8DEBDD2E8A443F37E7A75512ED33CB5A71
9E7082005E1F721484EDE774637BC948E02D3F6B044B10BB61A1A233938C3A916E90911328D7
3EEB236257DFE33BA5BD5BB8F51472AC89BAAF3F9E462F6BFEFABC6BB2A2A906A8E56A2A5AB7
312E2916065328E1E641C44336913473F2215707C8589C0BD6B3B8599531D10C1CF65D27567E
EFF8C237141AD3696EBFB9FD0F4C7B4A21844B49CA7992D9A0EF837C2F3D3A2F8E2840B18968
4954F0957DB9ACDF6E4695C532312027093C7D0F81371452A1A53BB20114C06C068A7536E074
FDD44626B54496C92FF4F165B83DE07627DB4F0CD4722F4FDB11457FCAA43A82CB382178AB36
F347BAAE3251FED22CC067E92B812D3ACBC28A8FE180D155D9C5FBEC15659B06A82E27D6BDE2
7B009702E3B50797BBB275B2A60455FAEDC9BDC471A5851DA8196600C6FB6DECC045D3B2B38C
AEC0DB9AA656277F3FA30F1BCB83147917E117A24514073D79F1BE0E5BF96B4D693349D78759
940EF4EA6B070E18870A8D6B2A0786D03F6012872AF771A623706A655D50D12663BD97FACEBB
A4931766132796CE9409533394AA54084B952AD4E9E903F1E78A18AE224E1452E3EAFC9BB774
5131D76290E8C6EFEB4CBBBCD535BDDC3CE5A05CA2B4082AE44410C1E3412B0F6B7D85374D0F
B877AD4925C4E51AD251BBBDADCB2CD0F5499E912E7D1F990FE5226CEF4CF5407E1391B5D4B3
3EF359429E92BEF23CD65434A96921B803C779AD7A7729CD428B6032147EB8D5820262B34A49
9B2F00E5E8D4A58220DD26BD583C474332F99F0FEFD5CE4967396CC85C8BC36088556B214FAA
19D7AEF255CFC8901B6170FFEBE5529301198328010992EEFED22015A09981E34213C4262351
738911A3C2B671357FFB5EAB7682DB8D397BAAEA9FBD77F82C0A79E7DCFAA3C6ED6883B61B3B
5111B88E2A942D7459AA5F53B51A25042668F5D5FF4A557301762A1D2AE18D80C484171D62E6
BD2C06E70C2AB20922247DE62912A28DEC4DAC4972F680E71E85EC91688DB753E7EE6DB6EE5E
8FAF7D27E0CC82F44DB9761DA4684F99FE3AC501583FFB4C46C006BDE1FBCBCCA4F3DD2CF4AF
C0F291565180564913D487EBAF5A952EB8BFBFD3C6B4A5B039B9E7BA51319226C1C576E5E35F
334F7672A6F547A1F655FD7BE11DBD0384F33519E240C1E6D7190220F6B655234BF89916FE04
4B72DD365B5FEF3A883073304ABB1140CFF90AC69A1D97AE9C50BD4CC351C845C3948E2A9FCB
87F2008EB6CE3062850B9D62B9771562431D857DB4CAD5358CAC24C5611F0BCDB1827BDCC7B6
C3F11AB223EA3C628F9A13CCCEC21F9269A53396F580CEA765E84A2E35B26C65255B8C5A44B6
3A776A0F26951226838156AEF2CF8BF7D543E0B3BA996D17977BA5D485CFB7E6D486A5653550
1EF6A915AE5A9F085A5DA01CD63579CE067256494661DE2F0955BCB4D9DB4B3F80366CC82050
B10956B665F8EE8CE42FD744C123A7555150A08D2096F995592A208270271357BD8501E7180B
D9AAC78029B6C34021474C4804523D5378E39DF856B0A472AE88BDE75ECF8AB07B83F5EF3D4C
9CDA72DB9E2F32DA943950DA10610D6618B3FEF5B75DFEFC72F64B8BFB700DA3C86594A8BE10
13C03ECB9C95DBAB90D2A05E3183A23280CD878A5B4DB7A6D6A47325B5DA70D4CF1CF8EB2EFA
7712169DEFA459545CA551A81021A587FFE5B8760A1A78897E9C9F34B167458AE9D6E56CA4E9
21620628AB8F73F73E174944623AC10FCF21644F64D7BBFC59CC02DBE0AD7C4409C6F66440B8
49668F7E2A0053BE5B5A825AAB22BB3434F7B2DA21214A3587CDACE32AEB83FA4A183C198C02
BD03648AC9278F3FC195E4E69B72A5CB745F081E32163A698FEC233F0AFA15939D940FBE917C
51CBC887E2EBD9DE24290790290042ED7F7DC16E866E5313A3E790BF7D8EA7D785E641054E5D
B4D3FA933DAC53C3BE7E971C70388E6B8171A6FDE2055F3A8C490877A89F4790F57C0D61FBE7
8A39D7A0391C78C503AD0C38D88FA809F7B5F8E902018ED0F9777610A3D38ECE44C3903D9917
86338D7A9AC65FDDE2692C9344D55B1D9668775543BCCEF80299EC86DF2E36ACC5C4CB2B4B99
08D009E93D86CC368D00D4C5378D16DB76E705D5ADEFFE926658DAE283740BD3A89FD9A58C04
84537258493A0206FAE4E0BE0A29F79DA258C34801B4A43BCFD52E3569CA9C10E5685FAFC1BD
2F51DDC62F4337976463C0251737081A65516D01120E16EE8D5DF0B91BBB79DA0C5ED1EF4861
4F6EE3FD267346F3D2E27EB67A5525782F8317E3088DBE7B0E5F3A6511622457ADF255CAC387
F5C6F43FEE8E3B6376F840ACC54A59CA06239324D63084F4BC92CBC68C4AE84EF3E564022D31
38358ABF949BFCBD44F8844281223DAC02741A51851EBDF4CA1CE54A6B12735A0DFB27290382
D73A99AA9B3E6F6095F9ECF650A95E2DC65FE753CAA05A2FFBF69B80F15A6EA308D2BEE55654
263D6F89C3B5E221BBEEC02904F134CC2B658D48555101101CDA5F3A4CD7885F274D98F221A9
EF4B9F3BFA7A67E19DF1D51155116AE7BB81455C6A87F7B2F55FB0F87A2C993B6E580CB73D84
FFADE6F51C1AE0DBBE5F6C01D294D6A86634661692E48AE5F340F2DEDBDFC5C886CDBF5B9FA1
219F8A4942BBA3E3950B40EADED15480F3BD19EA73CD34C413E0F10B39302B1344C4583C806D
F07025287630E2A058EE41E75FEA0DD30C5675CAA994FB6548403E4A974CB1C8B7E6FA451751
813DAA7A151B8DA6F6A83943D8C863A22ACA521CB48FF44005B755732CF460E576246923FB80
5EEB14273C11223EC80ADBA78310840E535C9035E64F74C153EDD5BC599B1A34CA78D097461E
96B316512232CD0055AF1432571BEF54A3C20B0821C1E70F5628C55FF91374C2DD41ED49EB38
A48CE23ECDE5396A1B067E1FEA6A3A76FB8D6FB64FA64CB8C0689492AEFB149EFA33273F4BB8
A54A81830843451E2249DAA708885617168901506D8847DAA295994F554F5A5246A7DE45CFDF
E2A698ED607639CD8BF8038A936EA0F7010AF52FA87A215724A01D28A230C84AD8582152E0C5
859237D9B361733EE78ABF2FD1EF19F69E366BB89858BE92C3FB979215DDD2C3F05B9424D513
D8CDDDBA7614332F5F9D95B52A1D20EBD8821710A0D1CDD07272241F6420663959BD6F7DDFA7
1BEE74E03797DBB29082C414DCB96E0DAC42D630576FA4EACC54D150E3BFBFF35A28939BE164
4E12FD13F4FB0C05E89C0B58167E3D48C8378AC05805C98DF4F0F152C12C8F79EF93E5473BED
582362876286E71D119037C9E2BAF29E1DCFD46F5E5EC4B19E97C73DDE60D3CC50B696D7E62E
4312BE7587163D3ABC9EBFA9895535B704F7070D69F5B19E335E15EC9CE099A0EAC212A175AC
CDF7C5312A927AA67473DF1F6F21E7D7467889EA082131E7223E4BF4A71271EFBF6102977DA8
54407DEE2CACB78146F78B23BFD7FFA492FFB3799AFA4BC88E686F0941DB77C845E4866B1E8B
5DA393B3D26E3841FBB7BB53E0DC558FEACAB01F8B5F7745E3BC8B823C5789BEE21493DF48A0
D8253B1DC1C879F824977C2AF5D39FCC7773483B7352176C0100F06D9DC8FDCC4B92B2EC113D
DE787FFAA650308A720F7C69F712456B3A9F6A3BE1A4664FEFF85A251243AFB7E1748C12A64F
1C492A47830057C282F0825BBBFB73C82DC488C6D8A532AB60DA409E9BFEEF119A6D520FBEB7
BF4E561FFA8A9DB7E5A3FB8F177331EBB016D41131BF1F84B23FC2F003C248FA9F78DC13255F
35F5D269DAF722364DB47927F90E76DA79F7721B2C610F51DF3C28111D1463C44F96F6F9E847
31378BE592C0D97B8F2DB6E6F2CEF9CD3EF05F6AEBA16E02DA551D53D96B2A2976DF8E7FD23D
8B502E739D4B82C0220C6F3BE0C0F3EE31E3AEF001FFC4CD22D6E79EAAD191627A8BDECAAD17
D135E74AA817DBF43C3EE5923CC4F8B1FBA58F18891AC6BFFA484ED7652B37DBBF3AED56A2DA
5350807A71A369E08ACA1EEFED4BFBAE14580F8EE4BF718C15A0CA869EB567BCB97AAA3E0695
E5827274CDB917BD3D7D808BD98DAD257FA37D747C6669EE577C8FD8ABD025CE81BECD5210D1
5275B81236FDBA2740972C653D8641626C41DD2B72EA32393F3F5D8153D91C9C3A53B073FE66
9175FF999D6D07E9E306C98D1EDE9C2EF23FE83FB0A41F3981C62B4F39206946032D3D24A1FE
812088A332CB13456C8E25DC6787B4E2780893A3A4E005E10EFCB80A388A20D3CBDE094351E2
E9CC5913392A09B96CD320B23DC4992CC6CFAB53B513A2A9D044C299A3B2FBBD6B7F622CB380
1CEB1D7BF3AF0ABB5DA14AF5EC8E90DCDF6999BD1322218FEA4220E210FD6F81A21DDA2AC4CF
1C4DA55222B288D7FC9953751880DABEAB14976E8983F34F87C571CEDC1A3E0734E26864BEDD
4AA8A834E348D83D2B66FA86C1C0EDFEC28592283B075E85AEE3504593DFA740B82B292853BC
39348A54E93AB0A815742535A382B0FEE5B552F0F02366850F97DC9FCEE811B1188FE21663D4
C7505B7F243A9023EC54E2C2FA4E5800F600190C7B959AB5F0C67C82C305A2EE245B6D4EBEE0
A862D577F718CB719212550133120EABCB69F88B45CE14BDCFB88176EBA9A02797B395B022B3
99C6DD835C093D6C4758913B05C3D6340935E1E54DF4B9A2BC85BB6460656292E8FC57F332A7
E3D31EFBFC21FFAD5C08579A27AF547AB338BB2DF92E85D22B16903B3FEA1834B23590A2FD70
568F6E4D979B52879D12202BC250D9F59F1994E68A7774EAC77A0B43FA04CFD024E8CDC496E0
7DBD2B1939278DBF4E0BAB271F152470E8BE9190F39DCE106C8218AF820AF686FE79BAFBB0C2
A9FF956A72E9639268DBD561AD58660FEFADFE64E26E112E86619DA4114B7AFE5A28BB7EA87E
8D2A4E10735F5092B411C57605C10D38C1DF81DA3799C08C03E24827496CC88082FF78209151
840FE9C741B9B665495D50AF95DBCA1E04B84A4E17E2C25BC7A2FB1F8819638F852707E15016
157AF20893D6E9EDBEFBF30937CA50C7C6E7D389776E5C19FB78AD37ACF1B9E09C17E09358EF
3C42ACB14892ECC993D208624B3B8267962211E762E43D40C8E38AF8F87FE34743B8B3562401
DAE7020D87F0DC8F1D4C34C7B0AAC0329539F31C01C8BB434AE4F79CE6A5A1143621F71ADB4A
9354DFB795C5C078405662D58A1E9A8EBA25B7BB1B10A699A50BEB3D53440207429D692D939C
228D61F31B59A8E30DB0B661D98890E4F30C9D60C8B8E5BCBB61DA5FF3C5180CDBCCAABBB9BD
A0AA52B126E408F0640BCDAE439F4EA033BF794282C2E8D11EA81081FFC0AC7C9860B9EB2E24
CF7BD764ED6583479F5F69809968E1730A3D520666A78CBE0D9043DA21AF1BE118B7C361D5BC
AD5BCC44B1246E1C23D51019961BBC2C8878013F01AB5663F88AF58C122A720B37A58FEBD448
DC9B7E5D0CF899D4E30821E52C6E813B0D35BFD25E77AC15DDCC4DA4CF088A2E09634CC3D33F
0E5E01E64AC6F52A878A687EB5833F6603170E8A95F86612E6C64AC4D454DBC792AEA828675B
04B3FBC2A516D6DF08A8E6D5B2C4DD184083F7CE348FC6E00FCD2FEC3275B5B798998ED7D82E
C26ABE6B84C9496669F6B91B850DE68C93D8C88C87DB649260899EA6D47C511DC61C55698B52
5D9AC30A25137A131E81D4C46EF4D10F1B22B19AFD9A25B2275649C2E0A36059B9112C3CE9EC
E70F60BF199DC446E98298CC330E7C9BA5CBA216324AAA0D716A85941FD89FDC3418BBD50E6F
2065CAFAF0CB8BDB929C9AEE28C7ABBA000AA86878ED57FEFD9E8EBDA6FBB1F904434F54C8A5
23B2499B1976D751F39445A1B5DEAF740DC6167E4C686E57C85C9CC7928E81F5FBCBE180E351
58B0193C4A9366913D16F7CA770C5B339F767D1A6B78DEE14C41205024CB91C022AFC8C50E7B
46D599EC421F7932FFF7A5658514C04D79CE7888CAB8C0C2EB7AB618B457F7C87F3566ED1E6E
3A079B4138DB57172BD5749AC5E927014D994345222A9471799E453A42D9FF5DBE1E667D3330
DD78C367FAA10F4CA07BE0988888799391A326531D519C737DC4239B17C8517F0DA8579CAED0
F4435C49467B2DAFBC20DBA54DD3F1817F640B4102DA5959943291A2DF95120179030BEF4B89
D00C97589383C4DB1D12D1B0AA92644E331645C3D29D0E627EF393F8548DFA97BDEE2562852B
048B68DE53C73A34F6BFFD46B06531FB0DE9BFC1CCDACBC0E01AB74A7E1080C37DD61CFA5692
5977DEC172EEC9CEC0AB77CDFD5FFAB6BB9EF1D7D09E577E957A87899F231B07D0D56349CFAD
B9304F8F0644433B373D652E961AF6E3F144076D0C64DED32EE2C4161CD1DEBECDFE672479C9
9500FD1B830202D5DEE3EFEC8D4C0117110626DD178DFCCE0F4B223410C3B27E5C1B4FCC9575
D2B54BA6D147912F88A301AE52324E8992F359C81DF160C062F978C70022C9518F61E3C0665A
D283858A9A5444E48295B744A7B8361156D59AF3AD40CA71D441F3C8123C06A2CCF2854E6186
415ADDAA381348FD5EFC7750C33E9C7F4AA936F0BA0CD58343F1B9FF545138565223061ECB76
81BE43B021D629F6B11CE8D740AC875C5DBA8D4D1F241DCEC7B1931188609AA3246FD1AB4F76
A3BEE835B9BB0A0F042E2F79F49278FDEAFF07DAC5A3E697BBCCFF1CA9C4FCC3D3F0C6DD57B7
C30B241188D0FABB3C6447BB5F64776AA3270F56C4240A9BB282CC4F3B7EEC6A4C76523BD82C
603859E99D354B27151E90D488F1B38C89442C9066CFB7134303112CE4A49DC85F1D730C97F8
82A561906B6AB8701F90C79DF081A21671E7F4353B34E744CB825DE60DEE525CA9ECD73B2632
7C5CE54322CABE4FEE57ED2185C6FDF42BAD9FC37844B280E8B7B4FA9D0349C65BD24FEFFB55
DED55CABA317031F48F1A15710AA9B7B6B3BC1962C3A430B02B1DE05283386ED065946063D1B
469F939B3E7347C0E73E00BB1286731245F90573C9C81F478AB32F995F8DAECEE22982B2693D
D0B0C8B9E6709C45EAD5C03EC0D56CEABCB52054F8EF3D81AD23729A174872535435165358B9
2B8A3BF046235333244465DB7D82EC059C586D7120C3166489FA8785FF7E7514C6307B477A7B
5E1BC04E5A40AAC790038E462C5B9EC505DBADD1DF4A91E4C4BB904E24C4D15830E9F83A938F
1A2B9640ECA597F78C330A2BA05C1BCFD0B414A70EF2C6F36971E77B9BDAD5B2CBDEE001FCC9
F407C6850468381FAFD112EEE30C4FDCA2349C940D22513C88F06E13E70A5956F9FC600FEC55
FE1C4A902C2C97618E6C5E10EF4C679296F5A1D076B78E365D947109D928D641C7CF8AE98204
6DCC359544BB0A031D21B0EE902FC526000D1105B30C4DAE93D2A00F9235A299978F22B7F596
9E20B200DCDD753FC301187E510F04A056D0B7DDE478DBF963CB77E3563547AB30CA42B02DB1
F3EB664B99722AD0BD3C68DD4AE1777B80A830CDE780E2AE13400ACB0027AC9A0B929915E196
4A4B030A15622071D62A4BC379CF1077ADBB17D870D641355F6AFF1180318BC7D00ADBCAE1CA
6B303D6D96FA5E01C48D367B0E161D37B64454E292A04F62A49974ED6A2862EF0EAF918F481F
FDB142677AB8C292C0CBB170E1F5C61D52198EED8B445DC1806C424AFF7FE410AFFBFAD628CC
BDE0D47515A3F76A0A635234FF38C200D43E64FB83565F8EEEAFED18DFB96C9C0F274A0B454D
1337C38F2DEFF120B5D96C1C34C470F5777E975CB078FB20FA4C64D5BB5AFF659949F7343457
4B597A5D5339F3AA378436360B2DBDD1312AF74F69655FEC1E0C54E8FF56AA83F9026E9D700E
6D07BEE86247803FC034EC026CFB805D8E8636C1D26629C1DA5820F973D6166AB3A667157FBF
3C111203C8E2AA0047A88229C584DE59E855690095298F20E9D5D5508509A2EF415B3D5D57F0
488CAE89785404E4FA2A952F812269E688E816E60760B864F03B6418E4A60E173C47D30DD5C5
D830A6C2DD7C033C283ECBB3A3E540D1B0411218E68D15373AEE1DCD3EB547504BEC9D409EE5
AC9BD6E25595B85BC081B63B8DDC04A7A73AF371E8B4CE4442D7E992D699B98187DE6EA37251
52CB1096CE26CBCD00F8556F280E070E792832D788079AAB8E19B6435F24AA5DF6EE06805FBB
10EB523D87526815958169FA3CC5023504BA39227BA2BF9BA68F7D2CC3D35E55E9D4D2E43F2B
1DCE3D4C340C1DDD30544A3B5DEF7C8AE1714B761D9BCB68BA2069865579E94C5C4F77C536CE
296DBB8591A9992E6B094B1E880BB3D386B62EB79AB2D2FF5232BF209E9492251434D1D1505F
D4ED79BD3C5857139105E19EBA5291B872E9B521E605314931E4A6BDE8E6060483695E9ADDE1
D23A1EBCF65A1D70DDD30B4BDC41ACD776E4FE6F43562004D2C256A19341D8BB460569D0DC29
242082F57D911065EAA0FD333B1F536DEBD235510987C1C211AFF2CFA09FDA26AACE78EB9704
5F7F79F0629C29DFA844E61F1C908B25B378091B69A4631B123BA6357CA673747B2BADF8D7AA
D722DB0C3C7F736A3B0486351B2E09F407F9F0999BA41962052F6A2BE21CE7F50F2FB327D4E8
717A6EE7698398164187446CBC66ECF404154914EA0B73B50079A31FB772F7B2F69C5C4D91C8
15FA0D16B80AF6934B57203D09C74E7E2AF81AB8E1262DA81C7D1B4AB465DCCE17702093486D
CC4D1C2B42E82CB1AFAC08074E828C10FC504C352D555B3EBC718B177B453CCAFAC5F452928D
2D6F996ABBEA6F56AEA83DDAA2572539C9387BACB8F51794AFB53D8D0600A57C3F47068B7DC1
C87BD6AC0109E1071B08975D8C36A7622108873C66D4DD5F94ED291CCED279613F8E5D781EC7
9C45841AF61B11D4D63E9E81D0A1CDC746D5A2269B8FF812F360C715F72C12A95D259E9336E1
893B0B63490E45BAE5B218D48D4FB7F8AF334B0C8868E476B094718F125314677F70D55D8270
665BCAA9BF61237A4A51E538FF77B64AFA102FE54B2B376AB91FAA4DB74EBAF5A9E7EF7B3B92
D7632C29612A14F97D34BF6B0B350AB70FEE1D189C0B91565CF6CFD2B127F74202910FA0CDA0
99BE1AB21DF0790E11BE8CFF67E5D5F532C28984BE7F663CBE2DBD216EBFEC440AE57672D73E
F239AB13FBF96F971714EC97DF0A817DD554F9C8E4F5D83097635665B9F9ED9FCA4B90F2F7C9
1500405E51709FC23339173A7AA82BFA6855A597407794D64DF5BC6BED7C9BE5467BADE6CBBA
350CC97E1946B831DCB9667EEB0F765938A366F0A2E9EDF7B18462A7562B16FC0571CF134521
9BA2B5DD81ABA342E3D5E669064558AF03F193BE70859357CF225BE8F4CA91BA6FD586FCBB19
36EFBB98CD53F4C20C6356EEABE99AA6EFE12344ED993F6900CEA58CEAA2C3CA11A9800EE66A
77F166796E50CF91CD03E7549BBE8A6DD164A5030601C38C4E27C7E6646241F3D7BB507B5768
30188BC6257B6EE2456D833E4DFDCA89CC9D42E9D633AA37FCF53B1FA3082DC71F07645C36E7
C28F7FFA23D2ABC86C35D233DB0D1A9E294D26C7735830EB84BA4A1462AE05273A1857F7B415
1195EE1544A159E20CC9A3D02D5080C1799834DAFDCD3519914BACC3DD0EFBBFC9AB8F5C642E
E43A0A03DC418E30C692797ED182436FEB233D7DF3CF503BD04CA23EAC21BB125661A3486C63
3FB7DB486D2C92BA706653115D1CF76534161F2C0787E2DF2A7D3B17C25EAC19BE80B13C9B64
2E947BCEB6068FB0A784CFFF5ED7EDAA0ED85232A17843F3B8EA51869F928369467A1C0DFCD5
2D1B8DA34612ADDD5AB8B0DCB43D7069EC100F022DC0AA8A58DF4077C9B51FEB8C83489722AF
993FF35EB326CB03F366476975220493DC515C8B0E81E9E4A10C08A299A060A59D3AA36552C7
1DE029ADB6E935D83BFC60B4C8695DB88601B7175772253F71B47DF4570EC3CF45CB121F17A5
7893CD830AA443BBA910D2C17F16B92E97DFAB2CB1B127FD4301B4FB8B7D252FD241A3088EBB
74FE703AAEC0C4FA72750D805110A6385E63BA36479A57EF6503AD517D6068E46CD7CB598D1D
B4DD9159099A971DCA8EC7B541F53640050297B51E7DEBDB6C8255D20E5A9002E06685981F70
27B83292D91BF860DC74FD97035918480ADA40A1CC39895717FE28F5D2F4287AAF9CF7476186
A47BFB88E148C84DE9252BA906AB9173C40E4260D753C2F26206DBF8DE9DC9F999DF84E14B77
EF8451C83068FF946A5BADD00C3FDC07898D356314F8174CE325CA1104294E3C04C1FE78BB87
C24F7FDC9A61A47839AF3BD717FE9A406AD590FF710FA3DBAB5A8C2C8D5E209FD764981F4F9B
AB49C7BCBEB6F2FC6F120D00255A457EA8883E0E5AA8B73DAE41235D9CCD14CC870209635C1E
C5C8FD4F1D3C8CF5B46B1B29A462A73EE776C3C4FA8BA77A96FF8C5E53CABAF07BA97C1B9765
98EF63DC102AE8F4178726ED80A86007ECDD4F1F2DB902A914B8713B267164227B87970BC84D
ECCBA36FD9EC1541D774476BDBD010D056E919E324DBB8EF94E6FE323B74D823CDC39BA65DC4
CF79EFBD53275847EAD4436ADBB90A423EC11C7BC7D5F92EE8BD1185A6AE517E5BA092AC4DC3
65CD09B76918A17E47BE0ADB78DB14AFED185566501EA8E700BB8AB39DFBEC17FABD673D0064
8C7691C0B70981292C10E8C5685454B12697F4039B7A868E7500AD0940EB401405DD2111261D
76F6CAE355CAC9AE1D9494555540B3F0C70E612B62FFDBB46FBCDE3D92D789BCBA8C191DF73D
1B3664AFE893E74E061B53957FCC15651D7C8B2A6BEF972745DA44BD7C5E9E1811CE0B226EB8
A0FA1D9E65A5F7A67255E5D869B891CD2A7048683443BEB68F6F080FDDA4FBDDEA5354BB83B3
A66CA4D6222FAA71E961BD7B8D8A40EE15AB6F8E5F08D0C8CD8101F903FD01448A8F8AAA5ADD
78EBCC4CA1F1CCB3F7189379F1B8C78430471916B7DE75FBBECB451B4C1552971F76C77FD3DA
7BD8F4219C37EDE680061ECF469048E7AC2FCE74E9390FAB831234E94160A8897C22F410EB01
3749E0B1E31350D4FB24D4D1E42AFA8B560667E90AD4D3AD433F7E4867CF8FEBD10E897F163B
8FBD4649CCE6406653ECFC89E006D7F53A198313D2D70E44ED8D6E1AF4D028A2BA8B56171BC5
81A698A8D1482F293F3388E36E1295F70C016524408EA17B8A9AC5E5EC2CEC4A17EA1D4A9F95
87DC738D2F684F4C85EBA085729181FD6D492468C9B75CA04893BF655A536F7666666A54E9CF
FAC2F7CB1FCB0300D173BDCF967FBE99FD66ECE5D5466E729C2CA6D649910E62C212E6ECB391
B5DCAFF8C2441F78C55D7A4522DBFB9E29F594D6D046F302F2DF18A4CCBD0FB9BC072787691E
3CEA1958375F9E693F6EF181C515254718CF96966EA02368602DD5C39E11A3C0763A3BD1D948
E80C085CA48FAB3C91BB1EC8952684B838A2BDF474CFA4F658BA40A551400336A3AF4228ABE1
26FA57C0BDC176274EE8A943482D3A883909006A8A4EE589541659A3F79575F0F80525199F52
2D6699B2E60F7D42D0A6897DCF801560DCB7285EB868BB90734412B0BAB00627CBB051A95544
9AF1A1DEDB97B169D48FCA4243C0DF6F630CDF0C6CE6C595609E6BE97A15D4CA210B2E10D2C2
A15D005017BC9674C8ADA52FC5C601E34FA33BD7976000D5590E8BA944C5588DD09D2739D54B
90E04C3048A9AC893177CDF6CF915B1B117A467D9DA6240E06621D94026ED305BA951037B0C4
1B81AA5F06119AB3E0D7A6C1D10B1ADF3C76C8BD7CDD8517D02C710AA48B42A9B9082731BA53
AFE1BEE778B2A14A3D8411DD9E806693C6C403770474BE70892A83129C91450A90A786EDAA5D
C7F5F00A30D991045C7EF4929CA7BF663BA9115D9D32F2E65EDCDE9158D803385A8B2CF71AA8
70F4B05B475AC88C76E29A572A20570BC96E21489DA313BB670B6940FA8562BF9AC584312EE4
973B163DE0E417CB32A66724E8617152661666683FFF437ABC531F8A7C4973859A9A97E86CA5
02D9D4F63BE74048017A9E76598BFA5A50ACC823BA92740D9B9260A56E2F2BB7E64032E6A79F
017800666BB51C2F5CCA5B3966E7C608E7F9152DADE0C782CEF7DC785ADE657AB2B792553578
91A94C95319C2A385B766113ED7D87E8D74FA8FA72E163D54E07DC638C92570F5CD4C6CC5EA6
9E5B2D12AD68815F37517209CBF56CDE3B15C20D0A3F42DB87574EBD3F51CE770556E9C641AB
B7E8513BCDF9D630D15F41F7C55CA229F1CFCDB456C9C45FE13C4144BAE9ED1E62C68EA466B4
7CE7D1F2BB3573E6E382E01E637822118099B18EB6B9F4733ECC2CB1FDC22065AC4C480B354E
7ACCB3A2CEC06E1D32DEF08CFC567273E3A74893688F767B86E30B2EDF454842C0B96F8A1721
050B7BF33BFBE167BA34D63F381EF5A35351BE8D7643A89CBC6809FEEE622FFFB1B7EEA7B1F0
D140930BBC6AF4AA6B9ECD64CC6FB79C999B914EB7D427183D41BC539A38E903F315BA6627D5
9FADFF710A81B23A5D684993DF1E1ED04EDE664F05DA10E8601FB33909C1A9BA6CD1CC544181
CFF9BBA596B0B0EFBBC7542AB8589BD5CAEA7C4FDD0607CFBE48AC53CDAE2944B86DC0C11986
5F916AABC627A9D20FDD79E8C62CFB3673BD29EE23F2B9BCA08467AE907D59F3FBBFC238FF23
B15303E623C9E6DE820810E19B47A8723C2B5141F3B0AC89725934EA7080F90197DDAB0AD4DA
98907EDF2464213FA29F0B14A9A2BF1920C7908787DCB5500AA7D27DA7EF5D15C7CEA19D58DD
ED19854D37D24F4F863C02CE9348BE6A2214C728258F5790104581428E33502D34FCA3925ABC
5249EFD1372FE677793561625B75BE1FADA5AAE50B38E657DD80AD035A588C2C6F666E55C876
9A7932257B25B526F831AFD78B65057D3B6D39626D3521D2920A9D2B5BCAC0C684896AE016E0
D8BF361DC68FBE58BBF511E2C05F603AB07BB4D417A00F4A4FD0307C6A5FB67702B1B0678908
90EB03091975CD4E42269334A5E5DBFD776B35429721E589513F1312C33100FB9459FCA71766
0C0CA07F4EC7E799DF7117A096B1A5EDB41BD85C193FC11AA642CAD84288FD41251DC0D1871A
970FB66CCB957EE0C92F1CC4A1D5AD2A54595950062D885B4CA0FCF92C48F417E79D1A27D181
32C4BB84D5FA007ED0A38E16740D9638C264CB01194CDF428B840DDB21DDA112C352AE4CE983
6F303B4A68778FD10820A54AB50A0299AD7E0C75FA88CCFE3BC240A27509A3623A57B35480CF
6CFB39A28ED1945745C8C7D250140CCCE794B0D93F00278CB0CAD38029B0C9B723AA80EFA675
EE43AFA3EFC4384BD524EE051D27ABD21B2E2D6BFFAF1B6F1FA258918CB65FED56437EACC243
9B646FE845952AC70248A9CAFE886EB5C2083E9434C75A5C6D79BD250408CD9CEE45E3E15EBC
BB635246B7233380B7FE8B1A0B18B678F4230808E48BBD980457CCB0CA8550F4E01FC89EAFFE
011BD6787B63AD6C116800C622B3E657B485D87B839889F071C2988CED7786AF2ABE03212AEF
97B0FF6591500014B0A188460F814C3C67B1A1E435D6DD6A1C748505312678B85B7AE9EBB880
CF0402EAAB49539288DD1FA78A8B00D654FA0E778382FC372C235B69D5D4AD284FC8B1A1F9D2
A06E0BAA7B99405BDBB7646888D8902F907E41036796D5CB431478DB858B2A2693E56377905C
30890C13B4FD088BD9545EB2E57E0D339BFE9C4C5A157E9856EECDD95C7F0008E4D802458FA5
E77EB7E104970DA2A83EE44705FC4B6AA2638FADCDFA8D041783A5E5A79518A9410A4FCAFA71
30A0A022083C5F36BB8C5C339E9F39EF79C8DCA9294190D02AC32A1395CDE6B35E1D22FCFF88
5A809AD1F94E9AF767A7CB627398A2043F93B42947D5A7B61968224A7585376E6409E98C091D
08AE8E9B2761C995709E7F2C1FDF573CB660392DFC4B9CD5CEDBCC06A3BD6873EBC39C07DC0C
067B21673B9CD246144A478BE0FAC9585242F0938F142D24ED5F6E2865238A1975A09A45BF8E
B110BA16EB33E514B3F4581B2BE3B2D5CC58549EAFF5D9936E2102AD13BA32C32CA9DB3CDBCD
9EB5B7AFBEC3168BF3A4F8E52D3A3A178A35E152F96D619C75806DB974453800E4B2A546052D
DE37A3588BA43C171DB5078C64557F86989C769655298EE6A23FDA1905A423EDC6A69E4A81C1
6DE852B1DFA65B4962151651169E33CE04D79600C1FCA9494533BD2B0BC117C2A6B920572FDE
2C20BDBC750C4591F0C3EF957328B5C38740853E13C4E525D33C3CA08251BB79C3A274A448CA
4AF4755FD55071D0A4439583462E66E434A0E55750D02AE2E56F72764BF88553DD1CC1AB6FBD
B818794881272D351E9D33DE2B6945CA7F48DC9E7862840C07774CB0ED9012E1FC428F990392
753956DD8972775A1BC32917A4A79426FDE3B859451D6820B2D27B056FFC8D779D8158387949
CE1EBC9E660482C969A1440006E9B0526C17A8297D2DAB83DB20EB4A6E043F8D19DFCA4BC478
3FE49DA57F99776F99C53648371D88C9FAFD33481F3567B9F5000D2F631E8C9E9EE72F712298
A9E19867D22E87628EE8579F2EC09D6FA836D0011C73C2C7D8AFA7F9AB34C28B8D9C90CE9E41
109B24035477DD75B5DAA912FAF4841E8B9916653EB0DA935B54BAF3655953E0A7DB4901E7DA
C00D01C07AF44A7DD106FDF8799A1F9DE4AF629C6A9C8D6ECCEFD0A44FB6718CC8A198F79BD1
B589F83B3CD92A95D639005D60C221F3829BC4E113D2FED0F29740A7DCED9154E2CB6B02678B
9F85D1951E6EEEADBC4EC7FFBA50C87B66C7D45D217A0A91263D15AD722402975CFC4B90B2FC
AD630C2AA120FD0D6C263BD63FAF531BEA97993E73BB629D35DDB106B8EFC8F8124F1442453A
0586245FC6B44E5316C2A291A884302F750C2120D3868EB1C8C4CB62799DDC1DFE62B0C4D800
67207C194F3BA90FBE6339F98C7B1DF79487144E28DB29C57CC3F275BD8A66BAA89130F3E16F
F9162DAB12C58C3FD9B062D4A8D0A4C215BA14EF1D7ABF92BF3887930E8A6099D54DD502AFCC
2F2FFFAFB8EFF2298141E7D48E671D99F093F0E7ACB5FB4363230758D7B81CB86B58E762FF1F
2F20DF1F0DC33DA8F618E87485478A97145C83D0C69D741A545CA4C91F21FBA87B25EE14D0CB
51EB473C1068225EC32200E7D4715E03742426CA000EF3B6E661A63C7EFDD89D687C07B86831
51C316070399C1AFA39576ED47BB18F999D06F7B0BCFDB35E9F2F6D495D4FE3B402B4FD6705D
D5E2BFCA05B4220A360C9D808B52AC98D4DDF5B6D853C2AA82211E9D0F96B2002375238E1586
15FEA9A161EFD7DAA69B82EC279CE440755F57BF63B2079044A49FA5889B5DA2E800FBAA4793
73B10F93D5963B8FC6E57A34B3FA3E1C4332037A17B5282CB9A5160AB0D17E13D8ED1617C258
10DF28BAB41FACD21F31114A01DEDA3FF4199960B84A986DFBA78667B8E2CB1B47E7D3242FD7
C5AB801D2A0B7A133DF86291AC4DC49A4660230D90BBDCF739013D4F6CEA79A1216A8764ECD1
147832228491314B147EC9C8E2F993B940D876767DD3E7E8AE360BC5E6EDA9EB6308F30998BB
600B0848D1D858AA80EEE4778A7C3EBC13408A24A4EF51D013DC85137819E314FDD0184937D7
FDAF472D7FADF58CB0FF3D25ECAAA2898E391D93E993D24BD902C559733EBF55116D0D55D9B2
874CD649646E61C5461833F62AFB581E6012C8930ACE1C2A3CE51BED10266580B7414B543F7B
EFA58E741A746A989815E25D20F104C081A7839C04D2F74EC149140D621273F0D9A5E9333278
612B73DFDBF108278582EDF0010EC2CD26B62E18C0CDC5ED5F9E29A0DF2055A097517B174A2F
92F614ABB9F52BB19ED260AA886E87488D81E4FDB334B2E5C882D8E7BED9D77AD1C7FD6441ED
445F04280E66294A259F8BB54CD414E48845C21EAE82337DE9A4566D5BE0952F09EFA6A9B4F0
E9A0D7F22B4824A1894C84DB3A4945E438AA6018FB67FDE9934327D47A4412988D21C7DD19A5
916D467419EA0F28E49816F57FA749E541D0459D87338BEB777E923EAB04ABD6505F69FFA311
267FAF0EE5CE0A99B5E60A89371A0906DBD1687E278CE40088702B3B0AE80802F1674A465EA5
2638F46D7D86A287AB78BA715E3D42FBBEE7C8967707A7E25DC9E0F309F484156A0FD2B55941
B103880E29B7086D604B666EBA5EDBFD91F0C80C15CE75665FE2A759248CC49CAF11DE03465A
564A94469A9D9021EB7055AB79B4A2CBE984CF5E5EB6A8A0B6EFD6249BE428788A44A92A077A
EB1BEF546F1A1F003B8DD3DCCEDEBBB1782D769DE4E2268D8AD88FFF96433426365221699EE2
DF551789A3A11BB8CF89C874F7A97F666D609E14E58802E176C804618D14CD07D79BECD9D97D
9E1852A631B585648AFE1A4D3D848FD2A514857D02B817CBB6702D5D654955A39DE5AA1858F9
BD8DD56D0D40C64CB26BA9A934566D066D79F9D8C237786964218D794DBB39A1AFCDE7466F94
E2FC9F819D396DFD8784BE7FA5AA12DA11CDD6BCF74CBF8843C029BE70E0CC67974ED1E5B645
61EE9D259145414B51B07C362E710614B778BD72036B502A3791D3E17E1BCA74773BC1488F8F
D87CDF23412C53304618365A06A41CF545FCE8A75F8882417E4B330738B5B6A008AA681595AB
A5EB562A27D9210185D4006CF27AFA035ADC7CC4A5BC12FDC17D186DB3089B6524177D822459
5665415B277216BC8ECBB1A44CFD285CC550FE40945F809AC2C3BDB2220D24001A2D1781F860
4C4EFBA8CACB9DC84A986CD8C123EB82E8092F1D244690AC562B17CD2796B34EA1F8FAA4C1D0
1EB8630686259468473F5B6EF4553F42A97E5C90987D47EA0E0A582884037FEE85BB1A31B0EB
E54D4BE1336D2EDBEB7073A37EC6A171280FCEE583979C4EC7FD555496011A983DCEBB1638E7
1A1998A1F46963637D15881A6084CA64541F18FD2F6BB1A2D6ECC2C9FECA9AABE5528173956B
8B1AE9CD064096DA93A47451EABBB6F66871D819348FDF933F6ACD6A1665DFABA9DFFA45AC7F
19576910EE2D29B55893C1C37C96111A4309FE3867982D442182B9EEA4223EB0AC1BF024EFFC
B6B763F89789F2CCF741837E0D070CE490C98290BC3B7C1EB0F1F63897E97808395955E21DE5
D901298B8369941CF82758F8E50706842FEE4D5D3EAAF5B90CE83E28E102F0DD6DB09337B68B
EDD79043C9ACD85456970ACFC4A3A7B5185F4CA5AE34292ABC51F08901E81B9305276A1FB4BA
7B6FD947D8DA0C247116A567BBF53394146A5C4F83067E1ED282582302A1910A7B9722451B60
1F86AE0F15A02075E9109F4320FF3C8593254A13C98C1E9E9BDFDDB990C5F509D72A9AEED360
D907821438A9B0171808E8A3D6C97C53858262A942F8AF989C42A59934C6CF38500FE955EA7D
B23AA4A041C0F9FEE2083A1A7F80499191A5EBE1512E1FB59F6F2AF9B0A554CCB018C272B8B3
46B56251222CE57388554B40975B9077711A94505BD9437BA3FE1705ECB8E39EC490F5597F8D
5F3BE4AC1B544C6003923764739E900CC9AC92A1CC521A827EF69EA1144A8AC65A817EE6F9E9
279032D3EED5BF37EE84434CA0F045A292A8EF703C787FB99196438E79281F4148B13C6BFDBF
DCDF079CB53021750E8F46C18EEBAEF2147ED9B6C743E349136F41D1F3CCC18749CD0BD08C80
C428C7EC37FA7ADBC24E31AC9A1DC0AB67486FEAB6DB8F8E25AF5564C2C43A64DF503A69A1B9
5FD86BEE84E8B672E34AB2985139024E58DE8B94740F1F4C7A68FBA709AD8069658F6D4E0DC4
74063F68F61F877E802BAD74E5FFC2B57639D6842E80EE741F9F659CD28ECA3976CBFE947429
51A0060705BDBAF15AE41E883F76911F7FEB57955E0355C301594A7B0F6223B603B94F201C43
CFDA55003ED5EC7372CCF2DDDF64B129638F12113E67A0D9140E7111F2CCED3E9A9B1F909C61
254848174B16CC5B192D48FBCCA707ECBD0F2CF43BA2819CF7F5BB74AAF99A37B56D7F6181EF
BBBB62E18C26B79B691B22AD307DA6820639CF96C7A346EA38A7DBE38EC4A9D102976D8EA550
D1C94B32C0EE1469F76C3996CB82FFFE1F2571D96F173A6DDF5CB9A5F76C977DC9F316F25FC4
61040D8CBBCCCF9941D034F4ABADF1630DB3CFAB2B20FC47DB8D06B7E1846B518CE9E0C628D0
CAF7F80D5FF7B1B1DEB5018675A0FCFA07A996F3CD40B0F792338FA5B63131C88B2DD26ECB7D
0A97B28DC6CB48F50B02A7C208DA73CF5377C561A6E8D78AB59C282AEA1DE094EE74EF5E80F9
44025F7F9E00380308D75DD7E0C059A9A7317A488A007670BE08D38FCA8D197B03C483FA0F46
1EF4806CDC0B23F10E7CF09ECDB1395A1428B56B4EF3F1A89DB6FA66460DCF1ED1A157BCBB98
084F630377A92FFE603374BA934399723457DA7D0253863E7C8F5E3CB01BB74BA6753678EC36
6CA115B5836A1BD43155F956C7F107765D8E746E8BD0E11C2BC4F80EBAC352D85CC09EE42970
14D8791D481D2E1C654F4C267FAAE6C46D9780903DC788EA32436675CB65F8833D340F58675E
8731170473C45ECBD5AB02D77E252FEB8AC276D505EE1343F3F5F1046F29BF706C4C3F52E024
A0DBB4572AB187C8503BA0E9EB4969F44DB6068ED207B457896E9FD05411580988166437D89B
9F3AE0D16CB87A94843639CBBA97A156F8B07BF16C661F6F4929EE7CF184ADAC2DA87F2E7E90
BA4916B23CE8F1C6C3E452533BD39F9BC14F7B3422DBAAB75FA96C5EFA4B0CA4B1813E5D823C
4592A0C54320135B9E8FD92D9F75CF800EF2EA5AAB64149075C40617D405084F46AE813A6F78
F29F34441614BCD95FAAE355F771F53DA38E193D9F9460CFE4ED2F38918056DD5FE1C5E25394
5064B5E1F76F6E48949D3C021EC198E1AC5AED61CDDA8FDF39A3C121D263391A602163DDFA46
3E6749B01F4EDE29600C5FEA1DAFCD849F51AAFD04A0C8A504915A8CACB61FFD61E17C9B0EED
9590909B765CCE927136FF1FFB71D33A18C626AF34D52BFFD9FAA9538388A139DEDC21BB04CD
99173E96758B75E8053A5C27D9EB7A29D0CAD4F055A6ACF498EF1765CA08D669898D9EE0F30E
9BDC5774B83D6D7EE498997C2EBBA9D2AFC5251BAA4899CD0B64B543A67861314F4CA2F667A4
94C57C209AB2AF7EE8E4E5FC0FB0E24235F48D83CB44CD5D833076499AD6BC5FBC97A5F2ED11
731AA9D3146D4AE8D9E79D316667AC445EA9D63C5F2ADED44AEFBD382B7037ED814DEB9527F4
5E58047F3B1B3FCD0BED6478E17BD4DAFBD57F365B977FEC7D94BC31EFC2C1B4985DDB28705F
EBF645E10124CFE0F1348B2F99073CF2F910AFFB284C17B436008E17E75B1E12D3A80E4AAEAA
EC845628EA6BDB454F2E04D2168789AB27215C831C9EC510D46FD73821DDA2CEA3BE3CBD56AC
3C6527C43F233FBBC3FEE7D97EC19E9CEF7C98C0658B52AAEF32B5F053B6E1C9FAB55E026680
2B34235FBB374A421BD90722EC6C8455C3F657260AB830A1C32E8A04A159D8858238E6FA8525
96CD16D891BF65DAD55EFD61585FD7FEE57FBD8398591DE62535BA65B3B13F37C51F4E927100
5224ABD38B47F488A0E5A7EE5FBEE849E839E5764636C3AFCDC52881C7E187A46974B8C9DFA7
B27F01197C9660E0F489DA5FFE4B1000BC6290760B02D74FA0C1EF2D5BCD4E9B2C6AC41E3B76
3C946C2C648E12962BCF5BFAC0374CCC1F3659F91EB9821CADC614B4983C9C7AABA083E35CAE
18559FF42FB6A2E80BC8EAD7ECADAD0BB19D090067DEA2956A597AA9E5DF460F3E9B8E629BDC
1992EDD41A3277CD5808F2DC4B8C7FD9C69F08867FD68689D4BF50E9505E505AAC5134563675
72009E9B96E7ED4BBB366D08C41DC44491560A43D2BCAB86E6ADC9BC829CFF096C8181180BFC
C249C3DB759B05978393F4B2380FB857D48380BFFAD9D00E445E620BB081CFD2FDA09105E182
FA8F8B72BA849CB74E4FA168C3E0EF861EA99615869BCFE9A70B0A44330387D1F2275FFC441B
BD8DA42FF01816AAB6FAA53000C1ED613F6CDA9A0C00A18A9567881D39A369753E5725E3AF79
2FC729D3AF70D6039F7E71E05D4EEEB4800A09948AB2918DA9DB5FD672B2C951F512554B8A76
02295555E7CDF2F39BC048AC30479276B9EA4A0B56E88D1260017B9C2863DDECEA427A6CA9A3
8E92EE00FBE42438C84B9F394C7FEF519C6FE32644110398A8088371E4C0A0CBAE6F1DBDB864
B08C2984A600B2A2A4B1523F07D4F04D479D12F8AE39A602560784DA69BE1FC3361E9E9A9188
EC68019D2C29EC12A5452C27564F4808FCF7CB42638E838286A3F96CF603EF88FEF15E41620E
263F86E6DF082E3ACDF8C9700A1F7F167D8C7AF6B591EEE2A22B4DD38EDA5B3928D6527DA5BD
C9537DB63A4031FF0F7057A4F42F535E7BC4297021526A79DD5ABE4F63D4EE9499A9B64E6575
0CAE0C6A280475D6376FB67B3D8A274CA3AD188F8DBC75CA19F1B281324E85927D912C89CE26
F423753B53A55C0D085E576F2EA05BD25C4C1CB67D0335BFB839420C14B5D5FFD66989FF2C59
2EB45947A81678EC6CD0D8693CEBEBB22A18F9FC5B25BB67A2AA8BEFCB08A47A637333DA4534
97C4A2CC411118B3F9C2363D144F7B71F72512C92762A90BCF9BE05AD62E5E37C36CCB796075
426C946A3EA7A7B2C3EB669566500259E2416F6F70182B1898BFA7A9C7A36A8D25380D3AA703
7C364321FFD9FB8CDE851B2F88DF2C4501CD51467F2DF02DE0CB4CD6B8D19CACF0C6E26E3080
E589C1246018A94A6667EB7B9AAAF40EBD8CF7EFBFD286C896068119F65EC69196FC9AF064DB
6641088B73D339235FD9FC8543E0074DA85899058920BE8C0B2E9AD854D230E3A6280F1C0940
064E99A15E36A1B60B71717FCB68AAF53FB877D48DD15B68EF58C51B36ACE7BBC95147BF984F
1C57C216ED78B32C54E66328E01117D813247073927EEC57D912BC848B912F360FDC3DD8BF20
33C5C9D445BB26F1E2E9193BEAEC0F262A3639AADE399DAA245D8974AC09B41B59C453ACBEF3
D92B86273D580929ED4BAA8033457B490C2C652FBB6896A782C05AE45406BAF49B1289EEDCF4
4493F9C3253D851ACE91A5B2853A22F00724470B9529C84DF49797F636B3D95D43E23AC3015E
D9D9A78A3758963C1A82E7AB7A716BBF96EAFB1DD49D56A7C037886CA6F66D9679036FBEBDAD
86FDE112C44CDD7D1878EE00EF4F142A71A4A67AD34A9458A610AD82A7C6104AE60B0A4811F9
8084AEA6FAB407ED8C05311AB3A63049BAA67EFBAAC66B46F3FC4318A7A76BE15772513C5CBE
41A83B7BAEA045066D6BEE773D7C6A619F692A5999657F4ED2119E54117C8CF12528ED9BCA06
CBBB81DE3743020D146FF5B9572F7359A7AA29D616D48A64435155577F3446D9F4041F1F40BF
A1B7C0A637921F5953D6459EF605A612CF3E05050100E101A4B07E7B22E68622349FD62AA0CD
8807399B223462CC2B2571896E36EAD5081A651DD4AECA736E04E11D172FCF656108BF725393
E6047E08280A4ADA62807FE911A15E7F5A1224DA23C47D3DF9A508F8BA13941C222162A54B84
44180D1F8270C48747274F55EF4CA73B14FDEE152D09AC094213266B6C47669E7B83DA8C8B94
C1D082E6EE5031017E112AF6F5ACF48AD3B1106AB79B6AB03C83B2928A17436BE7F09851589B
45D8C64EDAAB50C649D8F3F27BB16EF656CC8E0306E82C8237034A8C5803B0F3B1AECDC981BC
D70FF6428B2995BE2C10290C630EA07E0AE82009F1D3696FFBE386749E71A4025DDE64309A0E
39A16ED744090224C6E7D167D9B8D09E083A748FF4A93D734EA6A74B031E9681152ABD0413A2
C81D5635E8A41C8CEC4A80D0AF319BE22FD450E357B0E8979FA8A229F6748053E911EB8C8C6B
601F915C32D89810C669024D98B7310238907E1535909A4D86047741CB9A60CE1745E67F10E5
C701B2D0516D8A701FA7DCDDC9B63C61825D19400A1580730001EA089C0F28227C19E15E0D65
C1CD06013331D365A5F7A967150966DEE3AA6FCE26C325E7D58DC98B2B1C1FBFB02214BC4B1A
9648ADF27DDCCC963EA7E093FD55731950E93604EC6025DD86E9287B0C67C6EA0D966603377A
C3CD7B63102990A20AB67E8135E4D1A919F71C94B3DAD964B8ECAEEC67EDA37CCDCD05A1CD56
687A27B9A34CF64AA79F8122ACF294AF7DCEAB5089CEEA9844DF0963A89DACB9B335C79B4F2D
56A3A79912EC12D1997108AEC17D09BC5195504476738195A370BA31391216C1DA185C52EA3E
C1663F0366CF3AD8AF5A8D249165E195C382D3ADB9DDA81E6CFD5111BA3A1F9E34925C96E50A
F59FA2FF2AC7F3DC83934B34C6AFEAD5C77655486ED36D142E3816A1349A12E5040700169BFA
F7BE4788032671F296076FCB427A76DF2834FB0386B2EBE115FDB5B5CE32D57A15410005208F
C897D88EC8B2B46A870F0D476103548D553D2438222CEB4EC6897D2810DB5DADF53B5B6ADD9B
9A71EB194549B33B3BF7A68E97DE150F4D0252FF10808947A8C101176E95453A15D0E66D511F
04F38F403D391B3D288CCCF72DB576BC570A40D3E8E5D2E7DA7F30BC7935987669009525BA8A
455B82CBD926F9D1618FCA6DC148789ADFF738AC49633EEAF3B888661885457F4391CE7C1828
EED082EDB38D41FF225B33EA712F582D90F09C6330CAC12C489140DF4504C4DA101347C5114D
14C07D745E1FFB92896CCB79705BA14834A75F0F3DDFD1FCCDA8BC5DE059529680DF1876E41A
F43FE1A14310AB93DB5E786A167E446FE4302025AF6B3D8D5C725636CDDF52C9816AB82B8CD4
83AABF7D64383CA9486ACD71DAD03CDCDF43E145CA1FC94D9ACD5420A01005666DE5FC83E43F
6A96A3F1670E75A23F740CF7A60E18171B14A94DA4D07C4147A23F89C97E6D00C96A14E66C22
EC782FA58FDE3AF40BB4A5C11AA5A9796025179AFD88D99F723B3973BB671E34D209DDB0EB6D
C1732A128527B328DE5C4DBA0EEF997428A2E45CB00480C231B5D92225CFF3309F433B1D7A8F
69157A9604EDB80B3CEE8115D70EDF96DF018F7201FD18F06F3458CAF1159BF90CB565163926
BD8F4D0977FDD4695D035FFE9F78E9DAF495268A87F0F8E1BA42E1C4F4DD9B05356988E11BFD
95C1D802FFBE17FA86B5ECCB2B5E9CD88F207F90A3778748DFB87C512569A1469780A0FB01D5
A384E0CD78113ED23256AE529B7E781373B80BF1EE6E77F200F8D1FED4CBC879B5EC66FE7E13
AE60FBC69D4F2FB1FE730F186D3BDD4978CABF4CEEA2C7BC7C1F02D9E6AB312F6E8FAD1A0F70
67974F05648EE94D0EA8BF45D2F4EFDD5380125C4BCB71839761CA99CA4452A4140C13ABB97B
4DB59F6CC6A4308B8185DCB4E95AF89D58493209D8A9FBF86D999E67CC864DCF467258C5C605
03D54EC2F758C4DA866D8891016BF166091B12E72B1216CEEB2954ACC9B1DF4B640702923EA1
F340EDD3419E5FFBAF1BB29F51956ABB395B1AA815E103479DFE45B3677615C08AC770317269
7C7F5223C9547961A33FFC5D794C5CF7280C0417635B9A64B837C6CDF1940BF5D3A2CD9212D4
14A3167FF7C7A51C83889964D92FFE0D550CA7C102DE86C82BAB1DA3912F3190F00872ED9D0C
19AC14B72CA8FEF8B826B63A163022183F998CC7814D78D9D8C38AC122B1267CF92D075D8EBD
79E1209E8BD89B056E4CFAD4B1D6A822EECDBB2FF40DA248325DDE31A95EEB9EB75D699B9EA9
46ADD2365455D9F24A436476CE9E962E33E450C186A006EA57651AEB09D8DB7134D0520C1468
1BEE3EEF9F3A84177B6D5CCDCDEF2BE7DBEE03997F7B34FCCF9AB319F0680C03C2771B179EEA
27E1FA6B2EADAB7F6592538CC1ACCB5F64C3F7972943A942E7FC28DAB2D8BD0D4A585E94CD6B
467DEE7EB490397F3A6820B7CD9E043A785A26D0509FFC935900EADF6297B35ACA9239C776C2
B6A61523A529A54E01199B30522328053878C3DCECE69AC39BCF136290C5BC6CD04F5355723A
80C79624AEB7F76423400BEC6EA0531C57816DA649A44CB791275F8146C6F6AC95CCE9C7DF4D
18E8DE58B7F96F425D92C7D3449F1CF5E067442391F0F0441DC254A8A3D4C7597150331450B4
5BFC026AA5D0BEC87414AD2A6E07F5FD61218AB4D1AF843C2AB6696361DDED9A9E331F368824
22791FFBFD40927A9A65580CA9AA9CB36367C52559FC3209A96CFDA7478517C28ADEECB8C2EA
E5F937AAABFD9CAE42C17749D721F19D318388F7F2E859EBD55AA68F41DED828451700EEBF9A
7763D95905407731A817A5E785509C123754F745600659A07EAF8C4D08FFE1E41AA8CB78CE5C
FCF7293E5AF48777561A4231034DB95CC1196C847A1958C4F1AB2989F8364BB8BEBD6FAB569F
C4CE68D99C7B7771665B895220261DAFFD471B89D2DE6066C8CEC85823898879291674D51382
6A44A5A2FCCD842B9CEEEA58DFE92B0A78D913DB57D8A15711609F451D60321AACE03FB0EAB5
BC4E05FC73C0E29B7AE92403439D3DDA8D36129B1CB0A760C0677745105F93936AD4AA8AB435
77C79E15150460A16F1C217152779715493F0396F46A80CC38E2C9991C9866796D03AC9DF4F5
C59547F4671C27A74010B946BEF91FDED2BCB2E88249B37FE24F6B642350AEE9FDE8AF9A1846
B5CB26DD18AA8785CC4B24A829B5F3E8293CB1CFE81797FEB369872B9530A3C0E966EA3A173D
25EC080F4B8FD4F556165CDF8B64563FE05611C9B3EE283D58BFD1B6A358DB387C4CCB3EA0F4
5CA7A1D1578BA672D16C1B200443BBF30EF30EA2A5CE8B4C0B3EF08067D319CAEA860E047CA4
3C1F7DE53CA65A7D92CF0579D13F5AE278C09D0DE5A169692AA07F740D829654F0680CAB9C79
87614B458A3CAD5F0E2BD34782705CDA7F9C0C00B5606E0323CE23C78B43ED2FE475FCEDE0BE
1440FE42F488209643F76CB8F4DBFA2D8F089C7B425FF199570FA1D811CA4EBCCE920CB75986
FAA11E1A666D3B821AD30CFB9648B97FA98EFB14D3EFE11B9E84FC33080755FD53825468775D
7460CC9758AEFF32610EABC33709088D60E7BA195279D2D1E7F8E2A5B3A427D0322B65D486D1
E623DA45652AB7F71EEDDEF1FC1AD31A5B4C620A85BF26D732F678FD79A2213F78DF9ABB79FF
B9CE5AD8D59ABB59B75E48265E5F89994A4E3FE517980C63B94E0CB5C31C3858DFE6F6744682
D300A12844F97B4EB8DC14D52B1FADA4C2694596F889621F0C60D7F59909928D6B9C4BF0260C
DD1E984C167D3BFA86145DC3733CAB12C945CE524341B6BE5BDBC882BA89B8493F4BB5DAAAC6
8265AC8F0D1D8781FEC6A913F6C967C2E6809E6E7DA7F55E99AF47FF083836E2D59B1DE167BF
7B85F21A51848D37345BD6617ACB7C939FCE5A99615CAA1592669199C54C616A00DC2858B1EE
3E06548146B81EBFEB1B52CD3033FE447CEA19567F80EB109C9F64EF24B2E067019DBA2C2608
FD901D7C9F6072226B543542D917D89731586A4B758ED05C95A2E8A264CC2AFA63F2A7952BBA
E1A771122530B8770ED378FAE3AD93406107AFA5EFFCEC6C66CD3427BE67C8405536562F9039
033B25742F13ED631550799EE520ACD98B6AE8CE08C3951FA3D04D66E91D42D54431E7F4C36B
F29B792922BCF1D85DB39D66B6FA92AEB89E2CFF9C0A150FC67A419D926F10F01A8F3E18DFEA
9470586ADD9DE03892B9E0989A2B1AAB57FAD07E5D9F7A5CB510AC82459949A286E4FBCA5199
54F1EC6118A03538FBCD4C0CF85AAFEAAB0390AE0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginFont: CMTT12
%!PS-AdobeFont-1.1: CMTT12 1.0
%%CreationDate: 1991 Aug 20 16:45:46
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.0) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMTT12) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle 0 def
/isFixedPitch true def
end readonly def
/FontName /CMTT12 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /Gamma put
dup 162 /Delta put
dup 163 /Theta put
dup 164 /Lambda put
dup 165 /Xi put
dup 166 /Pi put
dup 167 /Sigma put
dup 168 /Upsilon put
dup 169 /Phi put
dup 170 /Psi put
dup 173 /Omega put
dup 174 /arrowup put
dup 175 /arrowdown put
dup 176 /quotesingle put
dup 177 /exclamdown put
dup 178 /questiondown put
dup 179 /dotlessi put
dup 180 /dotlessj put
dup 181 /grave put
dup 182 /acute put
dup 183 /caron put
dup 184 /breve put
dup 185 /macron put
dup 186 /ring put
dup 187 /cedilla put
dup 188 /germandbls put
dup 189 /ae put
dup 190 /oe put
dup 191 /oslash put
dup 192 /AE put
dup 193 /OE put
dup 194 /Oslash put
dup 195 /visiblespace put
dup 196 /dieresis put
dup 0 /Gamma put
dup 1 /Delta put
dup 2 /Theta put
dup 3 /Lambda put
dup 4 /Xi put
dup 5 /Pi put
dup 6 /Sigma put
dup 7 /Upsilon put
dup 8 /Phi put
dup 9 /Psi put
dup 10 /Omega put
dup 11 /arrowup put
dup 12 /arrowdown put
dup 13 /quotesingle put
dup 14 /exclamdown put
dup 15 /questiondown put
dup 16 /dotlessi put
dup 17 /dotlessj put
dup 18 /grave put
dup 19 /acute put
dup 20 /caron put
dup 21 /breve put
dup 22 /macron put
dup 23 /ring put
dup 24 /cedilla put
dup 25 /germandbls put
dup 26 /ae put
dup 27 /oe put
dup 28 /oslash put
dup 29 /AE put
dup 30 /OE put
dup 31 /Oslash put
dup 32 /visiblespace put
dup 33 /exclam put
dup 34 /quotedbl put
dup 35 /numbersign put
dup 36 /dollar put
dup 37 /percent put
dup 38 /ampersand put
dup 39 /quoteright put
dup 40 /parenleft put
dup 41 /parenright put
dup 42 /asterisk put
dup 43 /plus put
dup 44 /comma put
dup 45 /hyphen put
dup 46 /period put
dup 47 /slash put
dup 48 /zero put
dup 49 /one put
dup 50 /two put
dup 51 /three put
dup 52 /four put
dup 53 /five put
dup 54 /six put
dup 55 /seven put
dup 56 /eight put
dup 57 /nine put
dup 58 /colon put
dup 59 /semicolon put
dup 60 /less put
dup 61 /equal put
dup 62 /greater put
dup 63 /question put
dup 64 /at put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /bracketleft put
dup 92 /backslash put
dup 93 /bracketright put
dup 94 /asciicircum put
dup 95 /underscore put
dup 96 /quoteleft put
dup 97 /a put
dup 98 /b put
dup 99 /c put
dup 100 /d put
dup 101 /e put
dup 102 /f put
dup 103 /g put
dup 104 /h put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 108 /l put
dup 109 /m put
dup 110 /n put
dup 111 /o put
dup 112 /p put
dup 113 /q put
dup 114 /r put
dup 115 /s put
dup 116 /t put
dup 117 /u put
dup 118 /v put
dup 119 /w put
dup 120 /x put
dup 121 /y put
dup 122 /z put
dup 123 /braceleft put
dup 124 /bar put
dup 125 /braceright put
dup 126 /asciitilde put
dup 127 /dieresis put
dup 128 /visiblespace put
dup 160 /space put
readonly def
/FontBBox{-1 -234 524 695}readonly def
/UniqueID 5000833 def
currentdict end
currentfile eexec
9B9C1569015F2C1D2BF560F4C0D52257BACDD6500ABDA5ED9835F6A016CFC8F00B6C052ED76A
87856B50F4D80DFAEB508C97F8281F3F88B17E4D3B90C0F65EC379791AACDC162A66CBBC5BE2
F53AAD8DE72DD113B55A022FBFEE658CB95F5BB32BA0357B5E050FDDF264A07470BEF1C52119
B6FBD5C77EBED964AC5A2BBEC9D8B3E48AE5BB003A63D545774B922B9D5FF6B0066ECE43645A
131879B032137D6D823385FE55F3402D557FD3B4486BE79011D1F5B667EED85FADE30AB2EC4E
1C2F4FE750CF9A69506458071DE8896261C001B1C290937FA42A1FA87DE406E9F86A4C9C0F03
F69FBA719114F8AE51040A4C03A58B6F3DE027F6726F32743DCE739514C2C6F3C2DE1AEDDCFA
8EED7DA56DD68DBCDE33C29FF7A694769049E4325EC961B2DF16ADD2AD46F18781FBD63EEC62
C26F1DB41E6A666A09886382DCEBA91D8FF7CEDD64DDC8A2F15FE34076A064C46FEBD1F4DC37
07AEDE0CE8AF161BCB8E4ADA202D0954BACA5BE71C28AB8BF32FD72029AA07F27D658A68F454
A4BF386F6314224D16C7F0A8624F6B86319A4E2FD178F596F3B20DB032EA28C157A68A69FAD2
BC88881658D2286C0D4EF061BC070C3145F2A37EBEC03F51DE7CDA34CD977EEEBD86B00F9758
B3A496F41D9A74279EF3C6322DC54945F95062C5F37A1E51CF7EAF45F2B3634B2D7D01EC3B29
8FF35B6616CD3020E096F6C6AA2BF04C4A9361C19F3C67A28D936FFC8120F1E46980B29BF540
47C5F1FA48E67611A74FA4343384F802A4079B28B94681E119AB0C1692DE5BBF426440AD1023
506CB80732DEC64D9061869CB34DE924D2C26E404B7DBD9BE55B9C0C5AE3095C15D278ADBB49
12DF1484ED2D73128E5D9C1F1A3B9AC19E2CE5366C96644F5B3D3EEA589CAEDB586FD9B8F4DF
32EC910E9B7434D5BBE57E03892EB03890567DF5B811AFA0DA5E929D456AF3606092E69DD7FD
0FD505A1343C143D8CD853C485C30537C448AEA64F31F887275696A3272E00F8860E60AFB1A9
32247B70D45FEC9B75834DA16FE9B6D1977D6CF251568EC6E1B2321F0A168FE01CABB0DB855A
3C93DB62021467C39F33BE34A345A834C0F570EFC4E6810FAD9BFD353F241BF896E600111C2F
AFA2E7CEBCF89378418F7FB54127058217A073788F37E315B5547BD1FB607460AF1C5A025B77
222E7599F1DDCFD5A604825E440FB0A5E2C8F2337A6A3E23591A2428B5187801786BC527CEEB
07E0479F2F46050658EAA3AA39A7FEA3F3E3F54CFF92DD7E2DD80087D9B54158BF6DA0D15B85
C7D7FC603FABFF9F14D3B9223600ECE9A913C077770B25519408B8D9A111D7A6FD94528B2EFD
4DFADA964A5060263366D3C3127C33CF0F01700942E1DAB4781962873F7E87F34B702C04EFAB
55CA34951EADA440B96837B566752ADFD20ECEFDB7E7783FB4ED521ED75E8472917DF30C394A
38B7203CE31DEFC6AD7C723E4C78239F35F1C3650F39AC87F5270132B617BA31E3ABD72E14C8
253FC4FAFD4D76B06B2DEA10F527C246DB1C9178DAE2C626854DA20D3997AD464466268D3645
2727FBEC29E1C15A0208DB47F4C49F6436CCB01EE8D499CEB56AEF12A2BD351ECDFA7C16DB36
5EC4F29E84CDEEB6C69406711DF79A53CEA0C23E13793221403D887FD83ECCA853181E013793
10D777DF4CD3085C894B27CF5573C1A39AEEA28BF9EEFE2949720B7ADDE635BE2ACF587E89AF
27F3FB94929AE2539FE9F7BC7DF6B0629F2003CB5C6E84B704B5453B2579CE0EE6A7D6B45867
24D1E87117E0391FAA87C44EA920DE04290B2C1095D9B3173DB9718B188FF8F57E674BA27AAA
37FB45B5254204F20DD420AA84F6010F512A1CFDF837A08EC7B0F25E97328B99BDBADF1F9A8C
BA4D1FA311A416B185653ED2CEA3E77CB228AB746CEC1D1A6F46AACE75E57425A0C386BC43CC
92114FFC834F5A997549383E7BF2115532275A95815E0A1205831E90B7556E7D88CC17314CA7
EBC2221E9E2017095B5F3743AF3C34B3767083853EA9192579BEC83BC6EDC0FE4D5DD45D69FF
096DC155019D813B9940DD336A025C715EDD62BFBFAEAF49386CE28403CF87CE9F3E6CBF6338
EC09556303B9602B0EA318CC45E7905D43C74E88D8E6429C96D4E668A0D1F80BACF3C8ADFB81
26857A5F30BAC745EDBEFB8D56E0DFB96473C2867F06D98C43495EB9267F2948C8A30203C5AD
85D98C04554C2212119F947BAE7D5D5485D0FEA7F2A187FCBCB6A86A08CD6C9F02137AE82CC3
F90E175EC2F92B132D4CCBD5083F29FAE03B0A59071F9A0D947F5B1EBB91A8716E27BB0369C2
DBB201A59D837FCED4EBD4A30991E38849C7356A8A7B73A79A0E284A391BB70368495E950791
917BC308FF2E6A6F045592C60F3C6107A1ACAACA3BCF11269C9FCA80DDDD917FC689512F3604
01EE3E9BEE13926D486A4C6078AC32C3E6C9574DD3E777E1B65C9C920CD6A7E9AF7D26DF1CED
8810F0F68D82F386381B9CD8CACBD3DD3199E0A2ADAA11993B2D7AB5222293F744500DDD44D3
EB05663B97A087CD62E7726C4CE7BBBA46A43B340DA333326AC565C92E8081B6A44C272EE707
E58951714D4F864E6CC7339A448A2FE4030C8581563CC84FEB4CEFFD10B0A04FA4CCBB49422C
949E3075CDCFBE821FAD084F7B58AF48111DE80384F7CBEA2E5AB9D75994A01489A00F71B818
19BE8D5036476DB5CD3F63AB0BB0232F6907C7F8F90D9808BAC65B86D8C842FB4DA0963D60D4
428918EC71E3618B6743FC95499878D73CB72E0E936344C37621D19B8C9BFEA952AED28FA90B
08EC515A69B5148EB53A9CA6983A45DA53440E73308A85568A95C2BC299682A93C913511546D
6E7E4FCCFFF1A8D0364F20270BF4B161A5FA099BD14E1147B08794EEF74AC57E8D0FA62B595E
D7CC33948FF5CBA1DF0C8E4224B98E03013D19294FC946CE648064668925C0E7E5AD39147B93
C4CB0D13BE84F557DE1FFC50586723C843490C804A9AAA45808781F40F09FB8F9F518B40F62F
CA77C506A6DF9B6A053CE20F733155E4AB409A271BB5C7A9055A6190D044621389F3A9BC7E98
437127BA49D45C3EFF1FB8FCA8F8D728936E17895B6D666A958B9E84C3C8CC7C720D82446AEC
140F5AC5EEFC95541B549535E59B9C0040376A7F3CBC75A51FCF1739880A982B49E08345718A
7FAC7F005B22584D8914A4590F18D9825D3926A78DCBD1FFADC03B00C8CDFA6B5BC19EEAC5A9
4FCAE8BB23D901858C3E274D84BBE889580B65DCC75DB58536C4AB6E402BDC01DB039F692858
462BD53456468D2ABBE829A64BC47ACAAACC19587BAC5225D2CF31B60712E5BB9D4065A03925
639B8AC1475C5431344B4F05181E0B12C7D40AEF56DFFA7B7B3146CCDF7BD342ABD78DF93681
34C8545E09D76C2ACB79ECAD66D05FB8D5DF83A3F36221B6A4157FE39114B4CFC20C197893DC
26D6D3BEBB079D3CAABBBFB3489D46BF65B4644C92EBE8C870B10BB4246AF3C16DEBA71C1572
3F5DCD416FA8A35AEB2DBED7E2890DBCF327B9A1BDD8F327158F5CFA6613AC55B54BBE821CDD
2148E716BD8F1C3DA35FBDE6798B44D3973C677884376ADEEC4BB07F2FB93BC3010ECF6FC493
02B87247EB55D7C4EA57D0892D6AE86DF45C02AA7E59B1B1DC9CF62DAB182474688FCC120836
1EC9A586E6A212C32FC4913D1AD9D2718D879C1C57B81BFD1A24636375136BDB7A10D7C943E1
18B8DBF145D8C5D0507E5B67E683B75B392A9CA2B9F31C5E9CAD38B46CD365D796AE5B06FE59
3A7BEE53B7B3C5212AA5C6ECB06450E587974317197AC7C4BDBF4505A6F62FE7D28CA01D61E1
898E11FB892C46088F174594536B2AFFB1F4C06C48835EB430A21C8B2D5126334D4118D72F67
51011244A386C9F66901DA5C90F7F72572779934A66962B1FE168760F27030770F0BA6B55108
4B933F76DE3E4116B5366F93F795668797A97A8A9C581B3A200573A6B9D289D773B12F3B67DF
57A2ECD9A2CCA23C4D6917F8CBC5D21C9B5B8A7B0823DF0E570FB618C787D78D2DD9E0C1EE61
36C8DF3BF011BAE7D5909F2900AEC1EF6E0A2B51F82D402BB28FB3E745BFA92E66720FA0AD85
51EF7447E39DFD62086E0658FC0C6ACFFEAFC55245E1E28133E53A29687459E7EFF97328DBD2
3B85AB82EA25927299918CFB0270271307E7565BB7B077B7425681A6FE2D0B0082F62F3D461A
C1094838097918C4284C7D2AF752D89EC9E0BB6369A9E4582195B8FCD616C0B3E15E9C5D0145
C8ADCF4175C4A55B4CAA16930059A30C533557D03264A5D255AACB9D3CE20DA2A9CE3490FAE9
F5F12C719CE5AACC06FFABC769A2C144B469F7ECE4F056E4C66D9510CE75AD52D3D881D71D22
C90524A566F5207EE0843A7EA235D1E7B6F5D7365785E21DEEF2B461A206A666B172F156E9C8
30DC2A2784F5FE2C25EEF48F63708994CB54C0AF1BF790F493F44407C0AB8EEB19606A187FDD
D2D0CFE8C4B40413BAE547490BDD6A52D69B4AAD1D2676D88EA9F3E7BB389FC078B93C67BF47
127C286C48B66CAAFF5E7E8AFC3F2FCC65FAABD66B39EE80D33FDA99C44B9A1C8F94B4F94366
06F91150F8CAED3E6BA194D220C3FC9DAB3A42ABBA3D110045D3203B3F085C37F16FEE556F61
402FA5DAB44191B1592F88B5FFEA31C51E1B8EF02A692AC93B0781D32BD30B9FCA7F3CF6EF94
4AC7AE66416E97F80BE111CB0B7F5CA0BA5546EDA8F2F01E997FE0469A5EC986824055ADDBEF
C5A66CE8CF6BA59C356219CCB32D458B9DB14A34FCF0544E7148C8164F36EB0B54AFFF5D0FD8
050233BB83DA5C0F9C30D20F41DC1A31F2BCDCB50855D0B2B171C04CB5798A4E6FD648086395
709294B9FE74DC5593440A585A4716496E57BF688CFF9D57502961FCBCDC212D47F027EB74C1
CBE000D139122B4675A37050A15C90F4E3C7E03539422956A2D909F53FAD6AFECF0DAF6A3AB9
051BEB6D780935F397D9567B73F8A201C4B6688114DB7D9AB953D6DE066D926C9E028C54DBEC
37A6118501E09A49CD64C0CEE80AC726AC8F273C93E50AF97726C1F592C5C100ED8217E057AA
4CBD11B0EAEE4C58BBF5C4040CFEDACF167A5EAC9605B9AD4904B557B0A2565BA0692057B8AA
63FCA8C88C7D4D02C6343FBBE65C37B717456FFB609E79C40CBFC00A2E408BD5171D44020176
05447F73393190287998E7C515D115B08B692A725A55C62F38EA91AFDE05404C8A2FCDA96C1A
2C94F196837DC250BABCAC9A2E242852450B5EC43CB90927AC2321866D52CF10D1AB637C929D
6C3500A405A6C9E2527B4AAE2A9043107547D69F02F652FD8160092E5926B9F556761A5AC7BA
E9FE295CCF424C65D09290F6002EDDCF671C2E79768820B3D7AAC8A93D96B570BEADD291F94B
866313B290684EB5B864CD7D0AED407934B54DBD7A0F0D42D018541D46F06023F70952FC8AE9
C47B45A7DFFF666263CE7F844D26CCAE6662F68D82B4E61C676A3021F3B2A69BAAA7D084751F
764638E86F8191397CB55F8A50FC855375E1C27615D2313FE443B4ED59852A20656CA3FB018A
EAFA5C494CCEFA7ED73119A8B72E6FA570271F5C4F9B7E17CA967A765302B02F4572EE924F4E
D6F9E06752E4FCA351A9EDD922485487E223B4408D335F5CAA8608745D601C0CAFD4B066DF82
7C5C32437DCD4C2F72354A5DCBD461DC358BF3B5284DBB55E5DE6673480C331C561B9A31EAC7
D400D4B4AA714BC61EE01EF584B73762D5181760F82F31B3AF82A09418E0308B6FC0B9EBF75D
F7A0CF2DDB5D4046B6CDAAFE9FFB76D83FF26B6DBF20F07A5C63B5508BFFBAB24F098F75D5B8
D025878AB6020591C7AB79B25693A09987307896F8EBFDC77A9C87758AF67F1DF4DD557B61DE
39661130AE6268DB29856733943C0275D0934CB512E50F436AA6B3065929D99E50C629B1BA7F
7102B41551CEEB2BDF211B27FC863F3B910CCB8886CE5C17F05D09184AABA0FE7C8A79A37DDE
680886ECFD40692FF71C6402F6A9B5B651BD53DFABB8A6B47DAA35D0B048E0D1CDD313D3A9DA
87F7E93A474D32EDECF006FD15D3C0D6CBA42DD22FAB6F546DDEBB827D89006156EF4FE9F3DB
46FFE0D128CF8537BC6744C22634A078825F5DF773CFFFD4B7A56580975A360C188AF5FB1EAF
54043C85E9F7D71D9BC7EB417EAFC6C5879878F405EF57682D7831A92AA8EA5BF71CA8363D00
281DDF930E81C6782C322F841CC3909997738B5511FBDF47429CF5EBF33E7A4C2E372D5A52D8
1B2EC98CCEA3B0E675CF2C3703F1A629843927766A7747E049323E2C22F85A58B927E8E41E59
34173DEAEBC37D9F66F9F27B8B7DB0CC2110390CFDEACFE8E51F4DC3C99FF8DE54A9057EF779
BC438CAF7B1899C01A1CF5FB2D6E572B55753C90FC41E99C5AF4B979F61211D1D32FC1DB9314
A9FB773E5D8A556E3699C1F196F0B4727D4003278AC43CD32939368C7733BC419D26FFEBADDA
523ACF07A230F446A1BCE99FAD2709FAAE5A0E617D8EF2EAC4BC01E5C76CF5587DCFB6816CAF
6F9E390C4B8947C9CE3AD29007742B2BB6C6FFE51FC20BBC8C17694A548AA61CFF6D6F318726
8C54E3E81F9FF3B0AEDD6EF44E1FCCBF5BF7FADE6D9252FE367931D28298923B478482713939
52255D1A66878C4D44768EC352C83AA97B35BA388A098186DF61D8ADA96C49B7D2388160A60E
1A8FA86CD71DAB040DFC26B6A6A681D9ECFCE51C7783AB4091429731829A59B2FB5E8818AE8E
D733D1B55074D5B248F2A1A361087B4BFEDB91FAD81276EE08E6513A716E284C5AE0EFFDDDB1
E67BA59AE6B6A833057B69A350502ECE25C8F6AB28F2F35940EBFDF4BED3A3447FB00394301E
F5B19998F1834EAF4070FADFE4B142F473FEC46D0A96E60C500D31170BC4834A0B1508FE55D9
343906CBEECED81AF972C50B9D04A3B29EEA90B76557DC3F18A9C57C852ECCA395E51F0E77CD
CC135A6CB83AB71541D2850C85D8D4944D534F32227EA33A0E8840CD7B753D824254EE8D2829
3C40B21FADD0B0C0125E97E9930A0C727BBE3C8D0815DE74281DCA5E38D940973930274D0D2C
EE698F578DC9C56DC080574DC3CB50787D357F8211A7A48730D033249503904659BF05D5ED5E
9190AEA4BDDCB1BE3A1A4C50B0D407A799FEE4878E5C30BFC0D9251B03CDD80D8FD4321AE249
E530AD243C671F34A53742F3D6A07645A2409A3707EFEF4E4F35398CFCBEF2510C94D45FE636
D80515FC13275FDFAE1D33BFE972FD44FEBB65A8C704B71DAB5E84316FD25801C35681E056A4
D21CBD6766ACB5461C55FEF91564244C6764E7EE15BD40A04744B458C2B6E93477C9FE9CCF42
9D4E5E98D2FDD6CB278023C682984A99979BC1A74BCC38A6D0D6C5A8683587E807D9AA7D4EDB
E01115970AC85BAEB3839015CC2D2015AFB0E6C8346884F25AD8304F08E229EF2A3BA89DAE83
A2F22A34E861A634E9AED19BFD674A9DD3A9049172759E0D8BD4F1D79FA2F39251F099671D18
ED9FDC960137AC05EC03E5A62965BCF0BBD0BA69C8CC6A35192225F2E58023D0330EDDC612FB
ADC69A0E9B8EF09AF0EA5AAF781C2716E8DCF253FCD750D8B5C829B2C62811F9EC9EE7A794E4
5858D26766ACD5101BEA259B6119588EC8A652AE2AD82C5F19CBDFCD8E5268A039469F8FA2B6
76638239737D495182ADE2E5E1069B54B0A272F173632515726A4DDCDC92FC3CAF236FEEB0D6
1FB16199E500F9456BB4C72A88A9C8B96D50446AA691CFA8C7FF7E58B49C40B50CFF81EC491B
8EC6A89DB049CAC589ABEBE717AE25A976FF9D7A16C654B53B08DAB2B983067F3C55842DCEBD
FE839B0FB44E455A4ADEEF4B730E72FEF94A84FD26FCA4632E6D1ADE7BDEC2F107BBC6B6C476
4853C634B8B9EBD2ADD7F097041FD14414EAE550680242BB82CEA70A98866A444280325FEBE5
A346A103D268EE2332A08E9C7C31771CB2F9BB82D8E684A4C662C440A9591C56F84448001909
DFE801BFD354113071814A705FE28CC88E7A019C259E0D799CE896748B10F110D30A3D4144E6
59C7FEE3640A069C3EFAABE805826967BC07A7F625ED66C069C665F0A354CD318977F9C5F34F
1EF97C6372E94506A664E4D7ECAC7411FC8FE3A160F721A69B1C4DDEF146803821A795DA8BDA
9AF0FC130445B9F6FBAEC9FCB74DE5AF2A104A1E50E404380F20A8DE559C5458E6DA81BD5618
AD74EB0D6FBA61589CCA81A71558CBD7B7D4DAC6886E024E917DF2D5E3E8790DFADE1FDE7BB7
908EC62E12C3EDB23B412F1C330E89E0C18E65C675FB03366EDDEDC783CEFC84F71F7F68DCDA
94B672779C9FF82F974402A2A62CF047A5AB8D71633C457920D1B092ACC4F5795CA6D0DF2C43
C41640776EAFF464ABA9BB73972386B53C6A71FB621AD8F98C734C262A2212126812CFB65275
4212BC7FCA79E3B53D6C3CE762676F5880AD3DE63581A3CE3EF72A42B7E73CC6E23A6A0933D5
F5324380F8A53E98DF6BF77233C2B0EF534D569C0B3ADFECBE402CC5034857A1CBEA655B9D45
FFC54DB388A8141E4E6DC30270F9001603543B44C9AF54604B8AE1F2877A9A0ABF2E14015E4D
91E14A94B376F3CCA39D17AA21A07EA09D047691AA463EA1914121ED4277760D9766CE1A8C14
EB59A8ECFDC03061C9BDBAF8FAE84540CB0AF1EFFC17348CCF5090C72CDA21007ABABB67B0C3
EA8EE0B104046E6E77E4DC5D614DA2A5E3CF0AC6F98BD9AD8FB0486F7326DB53C89D3467F6E4
B9007DED8415DACB451E14281A6F0E3360C8B9993365E4689B53F96386C237D56A1474406388
35301465BBD6B3B8C943EFA7D6981902FE62EEDEDD267FBA38F1FC395EFA99342EB0FEB63521
2D561BC01F27874613B20C640E5A82D787F45CB4395D04CC699E70378C806AF923DF381CD1A3
7EBB28E9AECC1CDD167ADDFCDAF629403704702CD8FE167B25A4A185003A8B3B0F915EAFE06C
CD3C9B0827B5CA8C1F574A26726307FDA1217026D04F48C9E2853A9576D32DD1817B5ED74FBF
68A7FD00FE3FFE84F76918087D43E0915560C78DBD151EB0AC294356575289780295D05CEE51
953F1C413AD2D60BC9CF2CB5724533D39B36AF05BBD15AE4066325A93EE9258D9A968CEFD692
11184CAD62E223FFDBF979673334E584B5B52EBE7526E4859B201CC38C22AEFED2E59D6C785E
F1CBE25849BD1E7904E13B58F8B643E480BE312893276269ED4CF656D12A495941340EC5DB5E
2177B25390DE9071F34A44AC79620FDB558CC8766B4DC8111292F7757793B2A7D8DAFA9AAA57
0BED572C4325D65EF7A41A5C533132739FC0FFBECCE7EB19D69D4249F412D3D9B383F6E6D171
E3182BB107303AD650ABC00E1783410BF5F669EE91CBD30ED84E1E0A199A69F17204F043FF90
DB432A505502850D743716EDE4946011113ECB45AD46DEFAF0F299A698639DF3A1F133AB75D5
86BEFE281B8983550A3A22F239E654CDA506671D53C1E044440BF367A2C5F75C65E25419AFA6
74585D137365D4AE7B6716D3E8AA41D7ED2DD711B4ED75B88F12CCB3A6A0F7B2785743AA4E42
4AC7D5E8ADE9EF8F2F2B6C96A35C30F5A32575AD05FF47598B111CFA095BC77E29DA89E63D40
72F1FEF1E617B48B82D27CBD863A8683FBC6825448752F2944D3BA7D34464942A0AD6423EACC
D2A28136FD1EA51D849667160E07A7C1CF1983AA4273D6D2CC936B18B4A43EB67678C2285246
64AE0ADDBB4325DB098CB246D9D0AC1B49456D30F3D06113FFBD255CB7713C7970C8A5D486A7
A42ACD0EE68939894772D6D4333B174C1B6C004F4D9AC917075DF0C10B404214C1881E531E16
000DDB9FBB93ADCB36690D064CD1131B5ECAFA201257A74DFB7DC4FB7478916D513FE138A725
A0545E916EE8D1C597B9AAB070C09E0539D1421FC84E1AFC9433D99F202E54F6CDA9D704566D
EBA11F79C383433EEADD4EA8DAC0512F123D447BE2BEC0B176B8E4828622B6D14FCA0BCA414E
35FC210DFCCD31207097A211E3C6596E676E39E4EEEAFC12403887FFF032B325F621367A4459
06F4D78C7D136CA1A4B25EBE2400288DD85C70AD649B1A8E21A5666057D93F944AEDEC5C1102
61092DB8A07566D3C4843918FC70ACEB2CF648BCD73FCC4775CA0376D16A297938D6497A2E21
6F5FC72FAB216ABE6B00C487F65362E7FD8D61A8C99E068279A338828A119429D3B0495D12C9
E8881455D80684344F92D0306E501AA5A2E9102A67AD77BB77A2191EA1BBEB573A2D1437A542
A2808E5F358274308720B10447917870BD6846B2D4B2A2F9448D7F5A261A3A12267F5AAC2ECF
DF284DCC39EF73E57A0A77EBA848F1139D73AC5F3298F0A2B431458EBBED3341AE9D40F5521E
864F57154271E27DE965512C85608CC7D5ED75AAB3FD2C096C5A6C23DD1A719BBC66A0ABED8E
270230C807187EA702B36305889D8807F2F7D75ECE5AA1F3D1D1C7E60675912CF34B1E0C306C
2B62C9FA7F51FD7D17BA7021A1BBD88B0D5D8C2C347F5D2DDD2AC27B089471F3DCE65474D000
4FFF976A6859780EC2A8E271F7CF08336E1B38D4DDAD20379E033F3F21945C0D79B46F876CDB
64DDE6B0D31BFF2D0F0EA5E37DA1BA958D3986FBF2425FD4D36ED0B07050F8631AB315619DF0
3F1B39B30CB93BC3DCA5283CC36BF9C29EF64B3660770E915B2C4C8A4416BFCB8D3213F725C8
4772C5F774FED4E6DB73D407972F896B05C7138539C729C2A20387AE91BC783F357CFC2FB1F1
B035ED416854385385DA6772225010F945313D2733C24396F863AD16058412A70306CB2DBB8F
6428D7B327521C951DD1F5BC489015DB31831F93B559CCAB8B914215C3E739BB558EAA8BAD63
C3B06F033DE0F9B6F5932C8500F00A14F974B645FE50ADF8E5246950B02E817919E7B2BC27B9
DF8E67564EA5B0B9897B46315CB71961B76D814E29C6174CE60EF242D7DA4D1EB465F72FC26B
0DA9D3BF154527BEA86286B8BE614839827A06D7328E20B7C0751C00DBACA3B3E548E093AB8A
B726E2202E4F712B6DA77F09DC2AC9A389F9E02329680201A819D992F7D7E46F981CA81BD8BA
640F7D4EABA8A0313BBD3582FA19D6828C0B5BB4AB753422F647ED0AC4E2ED4B23ECA84B40C0
067ABFCCBBE0E30C5BE1E50C085244A308E8494091944FEF469A3B195BFDCB80621314F276A0
DC46A1FDA00C5F8DF059EEFB1E6DF6F2F7DCB0A52395B2DF0228464C753B3760B8AA15C297ED
FE86D42D08E40286BFAFBC98DAA4528EBE9362CCA21937DFE8A53595BB590F0AFD86F92C0FF7
3CB21EA18D69CC3394A78AA12699A5431CC0E786DC0DFCE332D4850E8247586DC99B5A1BA337
400AED4246D717A48327CBB14B43A2DB10338D6573770BF9C4CBBDC028DB50F6A8A3038580F7
5F04D1849536340E3C283E8C318609FD20619C47B18022580FFA1559EB1D76CDB7683DD10933
2AB61CD004E2EA9EFA9467734ADC9052B769ADEC5142822028C6E590644ADBAA94655CA7539F
5615D40237507E4FEA65088BF2EDC65BCD163B979D67AAED3794C0744CA1E037EC158FC4AED2
59CD5AE2D6FE56BA985EE9FBE9CB3BEA352D7F5934F0A37655FDB297EBD9D72BAFE407ECA9CA
4AC0029C9916CE462833551A9CF7148E7045F4DBB8B868BB699BDD3D1AAC3B3BA5E8EE7274F7
4B0BB47EAE73DEE2895BF7EF789E313A226198D85B1805E5A7B771A879CD8421D3813119FACD
797463970536F95C52D77A4FDDA562CB33CED74277435C5FFDE717AE5717FFE46B35350B22BB
F70BA6AFDC66BF0F6674BE52C9568531D36A8963CDBA1377915005443FC9374C9185C58CD25C
EB096B0F86271F99AEED8BB365FF384CBFA5E826ABD30540E1162AE030E9033E6474B15FCB0A
71C9DEEA1762479412BA28E004431CA38AD42EB71BFE5B7E172714FD081F1600D0119768014F
E219834913B26817D8BF37D51BB5C85AA3F46F06E4D78361ABCC4D2B66AB2EA51F308006E996
228F1C2C4709B809D05C0FBFA810446D07F7A0530C7B947448E310806FF1215FB2A293DBD04D
7C2C22573962D83F65AD82D770536FD354BDA1426A0B2757F7588F793C1F84343DD122419D91
BCABFAF04289A8A9F727BDD082D04640C1C0B4CE103D2919E53BE623F89B12D1F71363914D12
352A6A2D0A1E4E28FA43CC3C2893B64379C098DCAC2E5FC4BAA4C2410E92D3D4C7D8FDE9E552
330253F3F62721F69CAFF9539CE3F37984885642235F65BF484AD23C33C74A3B8DBF2C7393B2
6640638C4F3B4617A6C12CB760EFE5ECCA312972113089E2D924982D6912ED4B68FF99028440
226EB94D91F44C62D6878861FC7F47B8965D0C3AEE31D6F9FFFA92D63F8E7AC120B97CD905AF
68AA5119F08807E255E6AFA5EBE87CC238C0E35E133C3DB18CDB73AB421D600DC4B3CBF491FE
B931A95C2167EDFD9BCB8F7821262546F61A13994498CFA00361D23D235762B2F36E5E96A310
F3685E61B5E4A08C1734F8D36F2F6B90E6E4FAAD352B070AA20DE71B9B829C2A9F854551182B
A086EF04BAC9C50CB65684ABE48D4A5271CB7B869DE8E8AD503E493CB1DC442239D5B86FEDD8
8EF0C6A9729A92889CCA3BB785C5BFE760D2743B3386D3DBC41D8FD2DDA1D5BDBE2C648C118C
DAA25E1097273F05C0C01DD339D7839BC389BE0FAC354C4B23561C1529B2AD6F8D019140B2E0
681BC9F5370D775BFB92F9E0112F1EC9F9C09B0BE4DE62D723A44C31060A507FA5A3B9068B4C
0AC83710D31DF2F161A3F5FA3E66127AF55A6419DF17976CAB2980CFB4CF5EBA41D4B16F69EE
5839AB4BD7AA2C1A8285CC2CABBD906045B6666116041D8A10ACB8B7675305A0C3F05FAF1DC4
D3EAEFDAA67EAD720E69C86260B3A26C99AE36B2BF548746DC150DE1D79FDD3C3C8BE6329787
F8B95F9D52D1EC3BFB87189362DBE13E4F6703C8B6615BD6D5BD610AAEAB4E4DB5A80B523362
53E104F40CDADAC5E33BFEF07317F6E45EF27DB4115676C7407B51A4080C86D7228AA4CFF41B
3E8810458856B987064A9DBCD6EC2A2C134D1B7F86CA1992D2F177B8CCCB6DB7362EC6C505C6
D2619D54434A03B702A5EC5D99965AD2830F3C9A6A621772EF498E5F4F34A2ACF85F8593C64D
BF44E78D439CC105978AA1B77BEAB55A2927C45C2A775D66EC84E5934D9CC6C51580F6C70FF3
79B353F8F06C4C592268CFE979F2B171F07AE41FE6EFF0FAC3D64EC2C99D09DC32C0FF0005D6
8B5139AB63664D1E4BFADC5E51AD14E50BB49171467C793E7C33E0C83CD8E725774642B5FB20
284F2B4B0BD511DD99FAC6CC0662541CA12F2E97588ED5150555E7591DF2AD71990DC9D4027C
7C3922E0DD8E51B5A8A83B3F21B71A6A89C2069173A2DA9BFC5F76ACA58B3A970AC998394978
A356873F91C265A4E121F5E149EDACC2F614E59B5A9F7A9D0BC278F5F7FF575DAEC80908AE21
B72578A179F25A3236DAD66900AFFCD1C4DF57714243772903DBB704C5953450B0CE21F21042
6C335845BAA8D509BB4D0025750D6D2633142FD3BC368D4054A23F218B36CBEAFAF6BC06936A
6B72B5419271FE225839BA5687E967F392B8C782647AF4A206AFE5C5EF34EE98228E4D551131
37B10DEC2C1081AACCFA2F2916F2734C349AD7C167EB1873FF494678B0CC337073F5BF56E886
6A795D55C7C7535293E13A7886EEF83736CC11C57F2655607A9607A5C7A5000356AA3E696DD2
7641AC65719D7D5C0AF1F621CE70C03AC15222F7881B125EBDACCA3FD243E302904B8901EF4E
CF7F885972EEAB3999E093DE43CCABFA927D415E7703909EE028FC98E978A934AF9500628A80
EFDEA8D72B199F12164E597FAFE7C085BF3D6CFEA62A10C5A0889E978024A45C2E4EE0B0D4EB
E332752D57B28F52C77E4B7EE7F8217DD12294CEE9807645C4C1EB833247C19A41B6395727D9
D50708A0367DC931ADD77B4D977B0769E654DCCC17FCF05F7BA79978F9A970858EE1D1415554
A2667C479FE0BEAC02C26DEEA7D3F19E47A59A56BC45AB52102563951B7D84E57323021B4865
4E3C61E12E3F2FE08646BD52BBA29B61E3F9DCA9784724EED237CEF46E2E1F464EBB0B4BF694
E13C02CF2C421416764E731844C9BD69674D9D63643CBDC9DC5446A51EF3910BE8AB674FDA64
B52E8DE0D859650342A7B09195B41104CA58C1D8126ED46269013A99672217233B55D534C5E9
C4B35092B5849E159DE0F26A53DF170A092A5F04DDA515347E8C36E0BDF48D6460F212195D94
5300658B4E7F53BCF666DCFA459595E250F39B7E54C3364D18056CEC4921D86A54256750710C
E0AD4A20930A40A02186021E7B010FBD2DD62E5CF5BFCA82E90F720D04922D4BDD0F50D1D51D
1B25A80E260E0E00899A702CF0FC9EAB51EC7F4CD9301A8CEF10B6CA1AA8829A5EEAF08A69D4
35A69BF691B7BD6CA4048725B963CEC24380063AD550BD418D8678F8289C2666404A817EF7F9
07AFD2575932D5A72964B1C92E44403110B79DD247A0571F37D9396F806B9C57C22B744F549D
2A946D14D838B63E6FE77099D63E76BE82E7107850D914B080CE2AC1C34F6DF81DAA4E14B33A
401FF86DBA292ABB27CB8F2E4E8DEB873465EF8E29C56FE0309BAC322B37D1A3AD19404713BE
77566F12DBA2A615952CC52473CC5C7554E054D246C71A96BE19042F85E696ED0A8BB8492D2A
9D2EF7E306A608A73B0751F965CCAD6C71BE26DD75AB06F13BA014F1A795F4249FF41C87764F
A7596DFCEFD5FCEAC567EB760F7910BB19A122B27B687BE4BF8449B135D0637A5752011EE889
8F855A3883B81E8F8A8F4D4DB59BC4306F6890C1A6393404D63857B806BBD98638D9EBC162AC
E5CE654500076639218E83407553B99844761B1B8B9E353CE111AB1A4AFA69B633C564A0A9EC
E4BCA8F6566E8F856DFD616527AFACDD5C0C2A5AFA98852F165420EB33AB9892D62A86DEEBED
34BB7A6591274844BFC17249C04955DB780937A1AC9C231A5A0FD88E94C9AAE3E5C410730E69
26B92C63F4B13218EC7598E5640CFF74803712C681C5D01142F8D59F852ABEF10A720AC70A6B
A97B1225178E9F04B1542A7A20417CEF1783DBB501E72569EC4DD9F6AAC17A5DB49C26DE1FE5
14F9029883DD2B5FAAB9B33D0D1B54C2EB17771D6F9CB2B3057E5644489C53C76B800B9894FE
2E9A750D11350C30BECC8DA4B15C153D3860CD5D7C65A655E9FFA4F29A109EC2AB7EE0ACF745
0CCB1CCFA23FE3ED28D4966BA6BBF15CC94781B2F46FE4614612DF12ED408A62938A760D81EC
E1CB72DA11E59F4260CC0C1596FB1E71A8DA86D4CD2478F29DE9400314B79C5C96F465B63775
682026FB95BF23DFAD4B5344CEF2661F412980896CB656A00AC4C85BFAE906BFD4FC8E3FC494
251594DFCC39056F08A6CE5CAE362627AFFAF70A0DC1DC0ED201160E4F87499F94217103BA43
C7E4CB5A8F454F802DBBDFF5E9A6B204D761999CD2A2724371412AD58D974D55DA8EEF1EAEC3
E6E2C0A9357194295424886667382A48A7B4F1B4457E12F8B8DE868671C701E4EFF00340ED1E
F32A19228C8E09CBED8D0FEB6CFDF88A53CD1577584E06579E3DDCD7AA4E88DA92FF4193AD56
96960D2F653667E3F120C6ABE0FFA2F6CF78645E079C46D8DCEFCD6FF61B653DDC85A49CEA8D
49F3EB111A650BDBF8F1DC379F60094E6D6DAE86FC7A6C45B0B0B62091ADF7C2FD1C68A938B9
C4FA888756B4EC2CFD9E530747BC9A6B539BE75BFD0C95489FB6CD05EB913217B3FC6DAB2BFE
006A6F68F5FD0BA803D3D9039EDE46F76852D12A3D5C9987ABFA0D6BF0330C8488CD5A863E6C
543A31B1DA6596165F195417E45226BCAEA6CAC112D27F53B10059B8880C89E53A2B101F30C6
356BEFC84A44A36C2138F0C96EC656DD61265DE095F6C038039397CCB2AC2B43C916AD2BB154
5264055E22473098B61F1AB184F9821436FCB338940C9A7B3DEF162FDEDB709F7D40BE2E6D4D
831FFDE9A1D531CE1618289BC635F5D1B00F4E3E83E656302075EBDF2D24B81AB3D46FA86C45
DE437E87233B543AB99F93C7D32DFCD9587C16BDC697614A2B049062798F0BAE90B8835E68AB
5EC7B74B8C5DFE6F2BC51E22BAE42756D4282915496C479B3352CF9DC3EB8B270ADE29DD3961
E16E71E5A07DDD8A42FE4BCC987E6035296E13C52D931C7491628B8EF9D391A34585557877B1
0DE2D4989C652EBB4A0AFF5FC62E63AC8861623AA84B6FB40BF1A4A379474F0245079390A211
742F49706553BB02E7E4C720D977C661CD225334CC8F2E9FDFE542FD1CE21B7D51E1FA28A7FE
B1ED584E1ADA0B8BAA72EF99F5F7C2875C09E11A12D019EE7C51973A73791168297EEFE53A0D
A28A104963C82C1F8B0A275CFDC6D954F7A786022B143A6B5E2531AF3EE0932B8B7871D38B48
7C23D099B484888D5799028084795326B45CC0AF0F4F38034475A04C44CCC197C0834C92CF12
22A5AD9ED5814578EF16461CF530DB0BDAE4B013AD95E991D51EA5625886A159484E0490DE92
C682F3BCFC84BC60F5633C98FFDF4E4DF11F9926FDEF3C5369EE89B5D0009249E33A6B5ACBBD
2CCD9B56DF174DD99671C9EC503B639D04154A0FF8B166E19AA4142DE404D2B39E95471CA353
BEC85E73FA3184C6DFE7756BCCD79FF30C612276D149547D74E68A74060E316728248FC29898
8C3B142B0269AF519376DC26AC896D95F1EDFB871449EADED36EC0D962D06121CD197B6C7587
0B5C9E7C06EC2D248E02838C78AB047FF8E2A8ECE9EF55416D72E5030893E6EEF91A0A7476B0
05FA6D276A00191FF46CE53CECB26D959E5438D07AAD9D3B5DDEF9889DD62A7C62FF5EA2F526
E2B3ECE0EF9BB9C62CDDACBAA995F334CC6F285120B390310E09BC0664C6E5F3DDBB7038288B
DB5A3F410F53EC29A3C847DA5A290307E3C0A278B262C18FE5AB2A590F52EAE3AEC6110BA5C6
C4284F7BFF88FE93FDB0655C36F8D29859D8D838A050B3D41FD3EE7CB981FF512548BF7FCB4E
54ADEC95788A4ED708AD836B320B91670935621119CB73DAF0068DC9E65FF632F0936481CC75
55CAA6B2C5AD0C8EDFDB101407D4A0119E2124456E17019019FED2E098284CAB786FFB31122F
4F735776A97ED51F40D45FB280B935EA90CEB6AAAA6081CC70ECBE9F554B2BC67DC8793FFF81
6EAFD33B53CC1D6484DB93CE057FD1C54E633A5D8A1907B75086B3D4A93ED8FF3C32FD91280C
24CA4C96B707FBAF60A238822EB716F90EDE57229D505D2AC82B0567D9668275644ED0030F08
D76C24B3B8E927057477CA2BCF8292A8256594476511A19D1B4FF330B36F94AF99EC31A3E1C8
1334B18A31808828E55E9D64ECB717ED7BBD62D47137A2224465C3088340399DD8AE3DC04571
148AB3128639D9440F94A8D4F24BF84CF16A43B852EC488FB66ADD6318AAD54C6121EE0257CA
19526FD50754C2C995AA45DB5F2D20B010390B9210BBBC3E6E91B52BB606BC91E34F8C028317
40CD62A317804768228D54205E4CF5D51598314B9A80FCD1C5635757A46C438BDAAA197EEDD1
92D1D168ECD10EA495C1C3E095C4C6AB13C3274A64DCFF1227C31CB1765F8BE24A4CD83A1CA4
A7FD122A0880723700F10A59257B23DA50EAD4D82FB1D9C6DD5E5527E7C267907DA539CF95A2
65C766B7F45328F79F1813306F184568BC77CFF542C7C0876E2B437A0ACDF9FFE79E69F73AC6
32B535E68561C5DDD1D44A4F160C81400B77EC107D03E878B80A39E180D432046E1ABE60293C
5CB3C0F838E2881311F3E18F8093370CC018CC42B2CAB90B84CA722C36D20C4D26D1C47D60AE
D7DF6CC89886C6280FA2CFA6F0190C85C312C9CF0A23D79E9DBE0C742CEEA394829D78572D81
4461E990CB133D20103B77416AF2680EAD7A87460785B5F7A19E9CC5DFB8C4DB0D0C4B795E35
5515CDCE324FEF9EBEA5B059FADA1C0C7AAB8D9DA95CCCEAA3D9A274592C9554B53938A39412
6E2F640653E21015266DCB33D660F0740AAB8EBC1E12DEE7725BB0FE290C63679517FD040236
D0976FD14B88EF81FC8643D3820B03E976DC7F09285B2DE889563FD68FBAACB52ED622669359
EDE41DA14C1B704166D181AC4B9B62A5275BDC9EE009543F592FCF84FDA8A14AC0C18C5F52C1
F39040C1BD4D5AA7BE0FA967B1FC460524752FC2960E7954738693FF18E31F8A8964CF8028BC
A14BC661C6FB0F24CDB663F4A52972EA64110D3BAD36817975CEEA0B80A22DC3D3BF9FFCFBC5
DE5B22C89BDE64B240AA9BF50453C3B8F432797FCDC5BDF83F08EBDA7A10EC524C31E764CD1E
D3CC4643E7555CEB59793DDF22950DB8C8C5EF8AE42F948319B5DC93943644B8611E8E23A0FC
FA50895565DF07359A54038172A5009A41DA953CC0DC877552059038DA7E4025394BF74ED5ED
07DEFC25573809D6121C43DB5788F231CAAA92FE587569AC71C172EAA1079DD656DEE442D466
1552D10E17BC097E33C93549815B6C7936BA7FEF189D665A1488886C1DFF0BF5645ABF24AE1E
3094DDC9D4F89EB0C706C6B546A28B66DDD89DC4458C3D6AC25675127EB251ECC5AE020674B7
6689612418C7EFCAE5DAC7EEF8532F2744E5DBBDE4CBDA2A226FF09C9AD75D3CC16BFE4ADC78
B86CE0EE6456986DE74E0BE3E38E07890EE1C53C07FE188264850394753EE56D0E2F7B81B0E9
3BFA5841B2F13219A693E736D6AE8BD51A15B777FA0AE3647A538C8E081AECB737058C918085
13F07D6BF2788E792FD414CF79C953773A489DC8C1A5AB20A9C9BDEECCB69CD6E23EF7AF9594
8E6625DC3F0E9044AD3E786650C845DDF7A73AD8FDEBE33F68AECCF19C6DE8D792BFCE4CEB7A
F5D21052D5E3BA72E225153A58E2D5980739041D0102A47248E26CE4ECF9DCA785330D6AA804
F8DECBF21A9A4462F74D10BC9549900721E53B1A2B1B98ABC0949B6A5EB058C682AF62D3F3E6
3DE91F213CFC03C670E2334CCA2B3D8B41D96FF3B2A1D5AA346890467BE931A6D909ED04B1A8
36276233C7E30002A47B35D7B6A918B2C34BCB3C225C02563FB80AB95E63F0A355C76D5BF1C4
AD481B4604B506B9C32BA27F4DF89E7737F124F29FC2CC721A4062E90DB04140FBCDCAE1AEA7
7EA1E679B2B963E50B238956C147970ED054C2F037F908E569ADB2CE6430A2F3F9FA788335FF
FEE802BD84AB94377B7C336427235C1EEBD78794BB4F85B4CF55419220C79AF00A964CB33E65
E18359609628E556A84E06D60B8C781FDC356ABD98660F929F96E81FC105E41980F86F7EB877
DC83FCDF916319B73C46B832E150B01F948F4218180617411B7E4B5052F1F511E71B976225A6
5D79F5A8A055E7211A5120613616FF3E01B96EDC3FFC08D2AC92A3093BB6143EE4907AE5FFB3
1B5FB5C53B2D2634D9BC7230E0EFC16F9867BD7695BA8CDBF2140AC6183CD277B5FC6A0E71A5
327393211336D64936D43C5C922019AB4878047CAC2CEEFFE4A59D3BB0EC0F6DE845E5B175DD
DBCB74B527837DA7E292189F4303EC7282CE013B7E3AEB0E3E07E56D5D77638C3408724978E0
7D3678F9C4EBFD2880DC4883314359833FA270B28D9116FFC3CA8F50C880A1F8602D47B9D454
1C68644591D67FAEC5EB46840A3D9362FCC091135E66EC9D79656627075CB7ECADCD7F8EDD1A
697C7A942360B1659209AA18C04B7A283281A27EBCF1F6234E8F1F0604E65C9DE7ADEF778ED9
E6ACFE640FDFB20C68591E8080BD1C31A09D69261EDC19A250490A51C1AF501A66FF341A708D
7AF211DA47C66C7A3161BB05CCE9E60A661896E7CD7771B1B48B2C3B795CE94A0391F1388AB9
5DD7F2F4FBBB8CAB870120F7E898DA8E99F245CDC728FC6507C4547FCCCF5E26BF2915BB3B6A
892415753729572B5E833CE0CAFEFB6715C2AD5B00529B5526657ED81E8F5823B2F9AD402E0F
60B398457EA0C86E245659578791D92402BC267389494D2E4E18F7CB6EB37426A18D575234C0
FD871EE805AB7886A683BEE4E05D2FA5A332D53683BA1781B00ABE05432FF548014621FC0529
4DE73AA4B59C2BDAFFD5A981B5DF1DBEC484DBA328AA110E28CC0D865D73AFDF1D241DE5546B
10588A46BF34C9345F987C495DEBA0E06CCCAB4871585E5FD1F82C253CB9A3F12EAF2347E66A
3E6629120080593D07924D6EDA6CCDED9C97E416C1263E49B1F7D94FB7843425291C9A79615B
645E173CEA7D027EDC804B1D36D0B3DD808EDCF89C6BDD57808F73EED83A4AF6F841331A0DBF
DFB37C1AD39907683447DA9096B3FB77A3AB717BA42537B364667F114DE35A0D96D76048049F
648F610AF65E49A6E050D77AD5A3A2EDDA9BE71C110D6F5A9C5A9F3A9B8A4F25EBB0B19C63EA
7A8685314D46A0B1E2731921D38771882ACCE671450A95FCCFC13DCF5DF92D9828BC43B15AE1
9E6183C4B9D49F6A4F24F580379EC1AB20641F2BAD6C04C1A8AC71C557CF2B6729F1855AC6EE
270B93233CCCEFA99AC4405830CBC1629FABEB9621013518C7AF03D8A613D15ECFEE25954D98
889C90F58A39C9F724D7CBB21B622565E00B742475955B35ABFD65A02C85F3A83B60395BEAFA
86A64BB07D698798A866BAAE35EE91AB55CFA516E84213F47DBF67BB94171FFA4F9BAC54A998
E73F11EBF323B2DE85F77E242703AA9863881A62376B434CB3939BDFE84B1F4AF1F3A92FB1B1
102159B4356E5BD308E0CC9DFEEB78F514A005D00240BD7826F376AAFEC1D81FF6CF017A41A9
AEE1F8DAFB9F928DD110FEFCDDDF6AFDB8BDF9FBE75603CC2833614DC893DA48F8C1343628E9
B7021E6919167A4B263FE3600FB766606E23D8CD4A5BD3DA63148D40B0366E1B2A2E003E7A8B
64832FE3AEB64736B8FFD4A3BE9D3307AC8F0DDC61D6A391198CEE7D7F01C3C099B37635BBDC
61032CAA04EFE52113AEBB7290A9C2F5AB0C17B465C9F3956C954A3CA84587989AFFFF1D3B10
06D86C11FA183BC11BAB5D9B62C0DC936142844766B1A412DA4D3FCD5E53E5BD343A0C4E7007
F7A501D75DA2B9B0F29B57980FDBA557C92E6B2FD8D8DAEC867AE57C852F19BCC4B7898B34D7
C65C297AEE64F0BD75A6E00F7AD08ED07B74AE0801F1621E25A2A3A9FE51D8E5CFBF41206E2A
67E8E994BF25333F5A05DFD069F0CB45C9FA2F8DE1C6F11389868ADAF2E96189F8D3AF33118D
4CAB32DBDEACB223424B5AED2F7FA8E30D59DB5C26504FE0914B6B729E4AE84C0C4D965359FD
1B134625B131C3699C8568CEB046855DED5725D205AB35246888A6BC5364B5F59EC7E1DE44B8
C594E43F4785887E3691E208E7FA72080E05199B4C630AC7A3CD2C0FF0EDDFE623D2A9CC44C2
FAD9EB435306319B62A2BC0CC08DE031092C9F41A5E35D32E8DDA95B99A627DC63EF5A44B114
B80A1B6F824FF05DEED9F59B40FFA90EF0A9624E93828EA5013BEF7655957627480B2AEBC4F2
484AC084F1307697790B580359A99A327CE8AA56609A934AD32DD85B27B4ADF4937A0CD140CC
E1D624D2093E751B6CF05D3268B8F9884FC64CFECA9818D2DF276279E0DB0D92485226CB1C91
8C03D47FCA46AFD7F0483FBABB80CE4BD671CBA56A63251661F1CDDC2B9B2A656F39A2A8F18F
0466BCBC6114BDAD0165730C4BA845CFBC12A3D027E38D54ED89A157BAAA94F302C255C1DD10
2F216AD664123117E085177B357E9648620F1A2C907169B14A87A7CAA9AE4D0B6C277F5B1431
1247AEB10C65CE3A1703E7438FB7BE81890A5E4C5B639645E90B6C93910DE2E2FD86C0E44712
1FE37FA66AD652989F52A257E975362C1A5EE4D4456D889F73110477347CA1AE273E45045754
6AF55296833FD83ED186E63C591A84008D34D925DB46042C1F05BE6E429E7F2E63B627F7B2FB
9E190F2EC24F5A3BC03E1D84D7C308FB3E5D8BF6EA42E6AB84EF0C4C082837D9C2876204DE71
ABFC4A0E580170E7338A2843F10423F784FD4141DFAA9BCADAB98169E9D874D4C6B088EBF07C
AC2DAD3D569AED109C75237E004D7D16F51A4B76F4FA2200F5932F436744D65BAEECFD0126BA
948042F1174BB210FD3467C52DEE9F1058AFD38478486A515C580421B179B64CD44AB4507985
61B5C4A6B76253EBB04061D91323231AA4DCE16B266E9A4909CF6CFFB68E7F26BBB20894049B
8480B8BCE06D1EFF70FC5BEC4684B3E2DC0FC097DE6EFAB180673E6422ECE34C256C6E242DB9
EA31D1E3CD36967603BC5D7C886A6E53EF6298DC8540FA56BA31F9171E89FA3B4AC527FFBC92
9E3B32C15A05D52ACD3415C80CAF2697DE96346238603375B9AC2878AEE9652FF4BC2DBCDC2C
56C9E133F9A26790BF05744D730C2992DDD00528B52E9579E5BB7E4A6C2C4E1FD902429281A4
9238E38E6E6F01CBA1B2235C1C21C6840204027C0AA3D4D9EDD08DB513A9584A83BC5A17FE9F
2AE7C9AF494D5DCC3FA27831E82E9604646937241DD511AD8B1A495800EA4134E4622B33D04A
0F43BAA2C22EB3CEA8AC9619F65FF6D1828622DD70C9EE73A4A3BD96DBB852674B85550645DE
F536D06FE1A819A1278724D3528E207FDA8EDE4F2BFB78534258EC4E9DDF094390DADC99B0EB
3B4CEA10A11DD8A265D4FE95062C2E38A67AA31421BD7A826A143E123E2F47B2455B5EB7E006
08FA2B677CA8C84E225004FFE3472F73335D2EBBE348D60FC93B692B2584F4FB70AE4A03472A
DC0B22B2DAEBC1AD880AA8E42CEB861C9679B6D390E2A28762A6E17BA08E300913A7AB44F48F
52A522AC1F2D1E9B3A7241FD6C3FDE78AC147FA39F74D8CF34761398A445CFD4F76F013DC26C
040B637F86868ED89EDA4792A674ABDC27BF4CB7976BDB6EBB8760F390A87CB9A967F215738D
A8174CCC502A151FB2B76864C1097503799FE658E9CECEB0D157CD55EE1C347DCAFEDDA62ADC
04F8E2D2506688B16C7AAB33DE08A767EA004C5E172A3AF59236AC58A473A2BABB771004F965
A617BA9DCC41678F5383067728ABF5C2B8D6631883C6793C25A040B8C6C81244A2834D27BE8F
B81345E9A37612991D9F8CAEEBAF76647003F8EE3A536CBED2F05C2D5A23CC9162BC3E2E376B
87489EB21AF59A9715FE24E40B0C2B52E7059A995621B85399A97B1E6323D027E0893C97D5AC
9204129C8259A5631D5476D6579568FC6FB0C9C9814CC14A2E37274E93B98093BD3B098CA610
16C64B8E9955850F491A3FB44CD6D8F47B10CA825A5A41DC106136D87C40F7E94FF131F81212
742AC8FF1DF4D8A60106ECC3151D8EB1D02ACC30AF3FA413D397DF2FE235D6266412131A2F86
28205C407FE897724BCE54A8FE9C544970DE236EB1C9517BA5E4414FFC346754D8B8E2BD680D
F3B92661051E7E4929F842CAA53D7C947BE00C5C23A4547487C7049DE63CF966D156F0E6E888
909FD551894A6E2A2F64933E639D8873A9F9AF7FB69431542AA6E28EA3433B50B36034936E98
9E7E2F566041D95145A45BED860799EEBCD61D57D9853331C0CBF4D3C9B73D445AEFA6FB8C06
82654A1C69882EAAA9EF6D95415C9FEEABE69DD6FD26FD16741A96D78270313DF0D874B5F044
BB3074BCF1A03206A45BC425E3FEF9589975825719C6B6E866A634021CCC47206B0ABDFA13BC
9489EE0B3CCF83B268B3908CC4CB2310C02E0EA8CBF08EC2ECEDECD1E388067500B6EF25937D
D88EF68F77B34076B2AFF3BB9D3C04F811CFA309D9F824715C5B1524D1FF930C76D79119554D
6E186B6709C0EF0FBCD7921C256C42C41536C2DBC3D87800A4E0DC308251719CAFA133737CE9
8E711A13C35BA683D79BCAB512B5A16C5277AEC7680A6B8F12E83F6AF1163BEBF3C68EF9CC54
6D6221A5AD1C7E23E4025DC73E9E0609A51130491CECA6B4244F5F44866744A7AA6CE4A254E3
6B0CDDB5DDE478336241D941825FC38BACE3CBA8466FF4012318AD09546C6E3DE8417A5C750C
8AB0BFB307077E56C9B3A60FA407FEBC8E2B574E11C77778D72D43BDB1327D2C7B5FCD6A17FF
E02276132214C408765440E01F2A787DBE497F4378CE47AB16BB547AEAA321E38317B1EB3A32
C37D7C65CF4DCAA8DE9949453593435CC9F2DE5F3901BA59220C9205840F60494DA87EF62349
4303B2A7C889A003C74E9F0DA9D2C8BCE2123F7CAED5CDA4C54A090830AD1151A0EE620983FB
B07F1F98AB5FCE07DAF258B01298778FE752AC0E70BD3F58C8E43BE1C5CA093896C1DBDFC5F3
E117014C1FDCA8C820C605142C3C4C949D583B45B68A9B062ED9AA5E89DCDAAAEAA309503F34
9A330C2CC45CDC9C975999764B2B7B27A05EC6B1C880129CD122A8C83B4D5B5969D16137462E
4CFD940A0972BCD78FBB298EED78225690588A32EF2554C04B5D42C9864736BA20CC08633B2D
547CE1E209A8A2A021FA83D05BC05AE6FB714D7B45A76AD1E0E07B6EC1A91F3557047E13BFB7
E0C0E363E4AD9C583F794ECB15756D3DA1075936A33EABDE36D1213F7DFC1F2E8C92B70739AA
7E747DB7C08BC77B9E9481146977A11E98F3863F27391A0A0F63FF684DCBC957217A29CCA37E
6A1FEED928E80325B04080C2CBA0F2B4C74A8614C08D419BCE99FE4C086C758B0BA23F275412
B4A3A16D9E2EA569A6E4656073756CE08B88A700C836B231C28E62D6A6D432AC8567C93591FB
2EECDDB2940B1C39C3D29DCEBCAF6E7CDDB61F89EA5A9E440C2E97FD04CA5E6AAE9C67A478ED
87780A8584272164C41B757220EDF415096A7349E7545E8C6F04FA7016AD4678712B7848BC77
B3C0C7F2DCEEC77BD6BF8805B12E90E0C0A163DB0A27FEADCBB5166E8FAA4DFE237C04E2B4A9
C69778FD43DD6B98CDF597BF0B3C35AE85A4BA48927325BC7AD59C0145F35891E9E051BC48D8
448A5CDA8A4D7F7744A7C0D9255C32839A66E8505DA51B56C2509005DD446B2CB08B46417A58
BAAEDCE67AA392D4C12447D021B7757262C7625C6C42A3D65BD5380E58B80FB18913DD298A94
75A555635F7E3468B6C33851DA238AD2C6B46B86D43AD830F3ECB8B633033C6B8CDCF3CE86FB
9984AF44DC129731F4935B5052D2A69C34A74954AA899E9AC33DCA41D7F7E8728A6C815D4BEE
1DE25622AC387C4BCB86FA9A28DCADDBB8C4F783853420FDDB196C4FC5969F039CB3F2925D04
E9BD5DFE69E812E086CC7997A675A860CDD6ADAE88966BC55FF8B76EB76F4B2B1B957A2C000B
C71B9EC5B79EF4EC9F2A2123575DD2DEB30335A85C6BF4CD4F3A0E78C5855A3CB531DC0B4AC1
874A211B0346347ABDDF82435BCA9502454FC95BAE2F5833FBBD1C6624F1076E707235B8EE05
B2334F208810D4382BC1430E779CE360BC622E850AA96994F12B616E3CEAFCF982884AADDB6B
6437A48280EFF0F119B016FF787CC05606411B1C086C67FCD01DA8EB3C2880C939AD143DC95B
1C164A19377B06A313D5C34D2F1365F6D7F46726105B4D76838CBE1469F9D3A33FB07AA2B387
2859E28984006FAAD16751D619173095230483731666360933B4622080238CFB7C5B199DDBFD
8BABC9E36E23B9246ADA37DE17B6B8795E75AEE77E830A8C2C2020AF1F5B740A91042A9119EB
4555DB534F51B56FE92AE8A475B09D65C572F5FF54FD6AAA8933B4153DEC2ABA5F5C58EF7026
A77818F5FB32DCA9D52479B009B626BE665ABB2FD01D8A1D9350615180D3B978D312722C9803
56161A2B861D308FB89A01D92FA8E81D9DBFACCD035E936BF9EB76599C59AF3B6906ECC1BEF5
6FD2724B2B3AD3C363AD5F20E3039CA7883DD83114DED0427BF8EE9D8B41A8E646EE9B6F949D
7C1E0230F35C5BE6DB05E6DAB7E2780C9FDEE34CDAC5EB8AEC92645ACE83F38A7C270C0DD303
88A1CA18FDD1A38097BE733F6AA279D0861BBAFECF9EF7293518F5343D3FABB1CBB8BAF9EEEB
4EA21EBFDCFCC6191EE3FB98EBB22AC7D1FC4EBDA4337DC1F155D6B10A8DA925738C76EEF7B2
82D0177AF7694A576AF9B186CED25823E6BB856D89AC769D68F66D23F9A5FEF24680A13DD44A
7B31D9201726D2F24FF22D48B4FCA4E3FE08862942C602217A75338470120427C05448403DBF
6B729D06336145B4C1B91E65C5EB0E9D7521D273916D5A8B17579C8F4F698B7211488A87C1D5
4CFD50D017BA0FD348FC0F61CCC82DD98324CB3D3AB9D4F6FD396681DEC984C33778AD67E239
46E492019E84D2FD6C7CDC1F825FFD6F4216E3C926F5B12D6E3E9FD5662B5735FD0681C932C5
C7492153904A4CA41E94D1EA57008CD4BFFFF93F918D0C3C4ABD27DBAEA4D65527F667E4E711
468A3EAD84935566857FC972A605379FC4B63C9C27CC73600591AD8C7BC47625C61CA69B4540
EFAA53D37A73B028FFDD08A772FCBC499C01F5A8220D17A8AFF37D3A0DE7236EC77569D193FF
67172E449A49BCD6BBFB77F19209EF351E15D0FC9E146B84B79A7E099A255B663728E833C25C
4AB2D4D2833644EF9E3029B7AFD7736ACD3E58E794261B1CDE1490442085C4F848F6B3958AB4
DE052674386B590AF64B66173B311402CBD30C91CA3B07DAA67DA0A057DDECBB3B19FD6B3F7A
1C232BFD49BFBB30C2BA6F48DFCE34A2FFCB911041C1FEAE5887A739A8E079ABC623529BB250
8899AEC0F861B06056B68AC9B5C7DBE9F7A00337823D8747655497E65EC053F98FF65EF4FBC9
09579E206C33D0178D6C2D60939BB8CD94A80AAB56B660443492CDF0CB9CC3023F00B0B39F80
9C062027FF1CD3409673BCA5DDD3CBE7FF21C94CC7E84FFD488A99D21A703DEFEF9BAA490C59
3B0F47BCB348D1683E02170054496E415494190D5DB20A96C3C1D2D593D3E25EA65997FC07ED
D68BA0AF1CC34320385235BA488DD44F3EE33F6A290993A387998ABC0D6D906BECA5F58FD14B
52D2DBFC847A708F8EB3712813AB23D8C85AAECC1E6F54ECD758D08CC3DBA223A5C50909B029
ED521C20CB444A2DBBF9C8A0C4C21EB4140F7FC7E0497D5E21039CBA96876AF926E4A7565A26
C7E203BC5A547CBCC4223F903B8FD833BE6CABB94E7E3801689B73CB037A35E2418C9F4B15BB
902FE80F463D81DDC0904ADE5CEAA569A58C88688F70223B69E8A1028A79DA63CDA3F47BE4AD
F06BF087A5B616A95A6D54D89F4C22276835E1412C89A6339F87A1E8DA230CA7985C33BEE355
E18CE97E53030BE021DD3FB3AE2C261430996652216E74C295077660F4C3094E1F1882ED7236
D492B7D91655C1EB5F35B10BCC14E50927D68215323C2B0680174C2376A816AE9BFB5D6ED92D
E760A9A808A4F151228BDFD462BEE8AC251DCF4286839EC0B254BE7B454012EB50A10DC9FE30
3C28F27AA0D401F37FC59B9FC40F5C0DD5563D4B06AF82C0983B43E95483372AA545CD8E8B11
EF00B8BC09534DA1B9E66C4E84DB2988AD3726EAFAF12699C6F1BA1CCAA51FCBFE6D45B3E95F
55D2D238AF847B1EC69F92CC536548BAF8B41241580CA88FFEBB394EBDC7C22C24FB0D470A6E
CA4AFA718E6DFB3E5FC6E21577D67A07E29BF8B7059938F86F0D877D53BEEE0A1C11356E1D07
554770F23EB78AF92E113F1DCC916285CF8BA2BB246F8FCF76C49DCB74E2A1074ACDF7AC19F2
2B953E49D7857750C1434A8886A151D150FD6D9DDDC5D078BA46980F3F1A7CC1E2C67276A31C
75F198B56BBF328B3B17F386AEA047233B67BC93A4F76376AA4C092694E881687E589F4E2317
1BA3DF6BE35A16526921B16266B8BCA3545EEFFE1B9F2BA347E20C2F094632269AB26982F9D1
C3A43238C4D973B15B896080286AB6F093446841139AB22E0FA0F4788B96C02F24123CC6ADE3
9B02B45641A9464106804BFE9E88AD3751F11430811DD264A5E92D09E3B212825320B4AE29B6
BC0E65C9784B68B05C4CD1648AA20DC5375E59E678038E6CB1F4C0A0393B32EBAD4E6E8913ED
C147412D3F035431E9F28902618BBDB11E9C9902F9D462A6014B5ACA9B50829EF93F5D7E45F7
413982AAB70AC6A8313DFB9F93D8E867FB7F848DD34E497575CE012D36AE468A00F72125874B
6C4D6916EEA2117B3A1A78199EFDBE7A8944C34D835DC6005D00167A4A9FDA2019AA0FA521DC
4729DE8EF77DD4D2C4289542133C5124DF315974272178AEB8932B41203C5DE0CF2E9E79FA25
0426B474068F9A3AA907C15E72F881C12D4A43E2B783E8DEDC4A8ECB51ACB5955B82D496689C
7AB9BCBD634DB3DA04716E240857129CAACDE83E956CD89ECE290C69D15B4F206B13B722CACD
A803E376D985CFF24E477B964BCCC6084348F01A4125585945BAFFCF31C3B30A01ECAB7FEA50
970C3F938261608690AF59E3C42A87C085569498D6BD29C1CA59FCE1E05BABCDD02E752E42BE
145E88D703DA34D5290F8B495A4C8F9DA813454A1ED5488C067D85E98A64FF9D0ED467347BCA
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginFont: CMR10
%!PS-AdobeFont-1.1: CMR10 1.00B
%%CreationDate: 1992 Feb 19 19:54:52
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.00B) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMR10) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle 0 def
/isFixedPitch false def
end readonly def
/FontName /CMR10 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /Gamma put
dup 162 /Delta put
dup 163 /Theta put
dup 164 /Lambda put
dup 165 /Xi put
dup 166 /Pi put
dup 167 /Sigma put
dup 168 /Upsilon put
dup 169 /Phi put
dup 170 /Psi put
dup 173 /Omega put
dup 174 /ff put
dup 175 /fi put
dup 176 /fl put
dup 177 /ffi put
dup 178 /ffl put
dup 179 /dotlessi put
dup 180 /dotlessj put
dup 181 /grave put
dup 182 /acute put
dup 183 /caron put
dup 184 /breve put
dup 185 /macron put
dup 186 /ring put
dup 187 /cedilla put
dup 188 /germandbls put
dup 189 /ae put
dup 190 /oe put
dup 191 /oslash put
dup 192 /AE put
dup 193 /OE put
dup 194 /Oslash put
dup 195 /suppress put
dup 196 /dieresis put
dup 0 /Gamma put
dup 1 /Delta put
dup 2 /Theta put
dup 3 /Lambda put
dup 4 /Xi put
dup 5 /Pi put
dup 6 /Sigma put
dup 7 /Upsilon put
dup 8 /Phi put
dup 9 /Psi put
dup 10 /Omega put
dup 11 /ff put
dup 12 /fi put
dup 13 /fl put
dup 14 /ffi put
dup 15 /ffl put
dup 16 /dotlessi put
dup 17 /dotlessj put
dup 18 /grave put
dup 19 /acute put
dup 20 /caron put
dup 21 /breve put
dup 22 /macron put
dup 23 /ring put
dup 24 /cedilla put
dup 25 /germandbls put
dup 26 /ae put
dup 27 /oe put
dup 28 /oslash put
dup 29 /AE put
dup 30 /OE put
dup 31 /Oslash put
dup 32 /suppress put
dup 33 /exclam put
dup 34 /quotedblright put
dup 35 /numbersign put
dup 36 /dollar put
dup 37 /percent put
dup 38 /ampersand put
dup 39 /quoteright put
dup 40 /parenleft put
dup 41 /parenright put
dup 42 /asterisk put
dup 43 /plus put
dup 44 /comma put
dup 45 /hyphen put
dup 46 /period put
dup 47 /slash put
dup 48 /zero put
dup 49 /one put
dup 50 /two put
dup 51 /three put
dup 52 /four put
dup 53 /five put
dup 54 /six put
dup 55 /seven put
dup 56 /eight put
dup 57 /nine put
dup 58 /colon put
dup 59 /semicolon put
dup 60 /exclamdown put
dup 61 /equal put
dup 62 /questiondown put
dup 63 /question put
dup 64 /at put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /bracketleft put
dup 92 /quotedblleft put
dup 93 /bracketright put
dup 94 /circumflex put
dup 95 /dotaccent put
dup 96 /quoteleft put
dup 97 /a put
dup 98 /b put
dup 99 /c put
dup 100 /d put
dup 101 /e put
dup 102 /f put
dup 103 /g put
dup 104 /h put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 108 /l put
dup 109 /m put
dup 110 /n put
dup 111 /o put
dup 112 /p put
dup 113 /q put
dup 114 /r put
dup 115 /s put
dup 116 /t put
dup 117 /u put
dup 118 /v put
dup 119 /w put
dup 120 /x put
dup 121 /y put
dup 122 /z put
dup 123 /endash put
dup 124 /emdash put
dup 125 /hungarumlaut put
dup 126 /tilde put
dup 127 /dieresis put
dup 128 /suppress put
dup 160 /space put
readonly def
/FontBBox{-251 -250 1009 969}readonly def
/UniqueID 5000793 def
currentdict end
currentfile eexec
8053514D28EC28DA1630165FAB262882D3FCA78881823C5537FE6C3DDA8EE5B897E17CB027F5
C73FDBB56B0A7C25FC3512B55FE8F3ACFBFFCC7F4A382D8299CC8FD37D3CEA49DABDCA92847A
F0560B404EF71134B0F3D99934FC9D0B4E602011B9CFB856C23F958F3C5A2FBE0EF8587D1F57
74879C324E51FCB22888B74F241550D7401EB990D4F3A7AF635198422283CAC1B6CD446DDBCB
D915DB9BFF88844E784C6BF7389803D9450B0C21756A017306457C7E62C1D269F306BD3402E2
66DEFC3B5E7D8A8D2F5BF0FE6DDD40D07391DF4FAD4A6018DCE29A2B8F692B29F2023A7C0E66
DE8ED85C14F1F8492167357F51A7E84CC5D92E0FEE4D81CF7FBC8DE52D2E7BB57142033993F9
C08C315ABADE8DBC4A732E84E142D3BEE51557910E12CD8AA37C459A5E6B7F5269F59078ABA3
BE4641A11AC48D0B625C8325B38EC08E4C9E5E7FED976A5650D99D82114F449B9CA14C4EC957
702295A39A93EF93F61899B8EA06B092C3C1E503E6E436E0A9FA22576C8930AB3DC8C20F5D82
B69CDDF8FF4DACFA9C54BED5A3AA3EA5B129FE96BE632843B9B6BC91B615581A985DB56B1E01
CA60EE69CA92CF5C0882ECE62EDAD3E106D835348822400F0B66AF658F2AE56ED08F8B001057
1807009B73AB12A8CF14CA6C71F03C2A48C500F9D62266AF154A6375FF600D9BAC3F05CE3414
2D6867A79581C533176BB2F3117336671E2E44638A97167E2EA9644E31EA16C2AD2990EA33C5
4001E0C8156E6DE8AB6A4D40A7137BA275F39589FEA2E2DB8256ADC103D6F9CC038037A47E8F
D469C5F98A5E3C15BD4ACE40D340018B1CFF7D1ED8ABB0AC57B5B5A2C20A51957B96C453EDB7
DAE5AFFD91A46D938FE0A13363001D844DED4323F1EE6D30012AEA19B024A552315505535C85
DC26BAD31E09C50E6512802976D298C4E90D0044C362E6BF3AB362A454EE93DE25CE54411090
C29E9D75C80CE26A84404BD9DE3AEE0E3F921AC587F907572B8354A5C3165EEA7E8B2BA4E333
802132F760B41A900C698EB3D2738BEA0AAF7AAE96A558F08B61AEC7C7D65B2889BB7B99800C
FFEE5BA19AC90FCE11437BE1DDFCF0BCA5670B543B9644A71C8726D0C1005ABDB96F6E0CF7CA
AA3195017CA81519151C2C0B04F81E717C0691B63A76E9B25329CE2625B711CB7BF99D23EC2B
B5EC8AEFB8C1A3B422AD617B3DA4D49685FD44CC21A1FE5E1541163AB3E1594601D63C7E9880
1D7746474377CE93F81404F3570AFBD5DBFE77578605917AB96963987E6EFC2D3F99FA56ECAE
6422579852567F90CC90E4EF6D6F71D1858270205477E221018A375CA83C572B3F972C5181D1
8643CECB04909D84CF767174B3C0C8EC69BF1E9FDFBC0FC7ED97EC67D878EA4DDAC8CAA522FD
C6932DF721B81AF837AB56B547D4799241310D6692918FCF8A46189A78D6638AAD7CB4462D87
74EC73D184076595C94C0B4A8233CD34F2D92F6FF94F941DFD589DEF2CE790D5CB2159B95333
8C7384CB68C11779120A68BFA20B993D8C0313987EB96A2EAA2C11CFD838E6AA48A89E6DDEF3
FAE1A1B078BE9787140270556A96E2725A8CF1AD46FB52938900730154AEC60F544C3D49F176
3861F54B46A3B70315B46EBE51C42FABEA87A5339ECE2B64270749188D73A07E0E3866EF9AAE
A996FA92AB443C08FB8A840DED26BA68E94CC23CC1F6968B0F3C7E8F4FC0C5CAD0F7A332E7F9
55287ACF2485539C7B652F7A29D9E4AEC20A8E023AEDE26BD4C761BD3561269FAAC6FD5A651F
FFF9211F8DF220994DAD6D105A92D5794CF2AA526B2143C7150BA584A2B597F6982403D93073
CB066B569BACF95DA04B4202BD24059A8DBDD3ED8AA9E89B2788F3B078A81A557BC743C12A1E
00FDEFFD030C032E81DE3142A106C0EDE1BC9D566440BCEC4260295CEACDD54BD0E25F6B9DD8
FAC41F453BCC731777E1E6ACAF37A8178D11BE1BEDD6681815F3D5EE8D240B7CE9B14FCFAFD5
04216F26DC2827FB0F6158416EB24F8BD7616EBBFE9378718824CC6E51135F8F489E9A55A0F8
40608A99A32EADE4251F27FF86EC7F324DC9B534D7135E30F2EC1B6D93D7DB919651E03F30A8
82F2DFA457D307F17751532AD70E632A04A63CA1A507FC6AF4073126BE0127D86974B426F489
FF62A53C1986FD048AD76454D42BE16A6060101239B138BB638765C46EB006F7F8DD312337BE
08D4381272FCEFBD74B7B2EC098B436365586A832721A0113B2BF1D853FA8B062BEEA25CABC6
0998CF4D38B49A3F4BCB372198A196C9EB6DF2CBE59A59858AE212031C9AD7FBB9C3E8E9E6DE
45DCCA521F3AF361282F7B3EC507C8B3AFCF18B9678EBB2F11C01C9DC3C4FD3134C5A3DF6B6F
4C75EC985466C4F505847F1475C91E5D83A6BF754837DA02F9E868EB0DD76EC4D31C8B1ED935
ACCA73E1CB9B4192BB0A853F947228C3064E8F923A9133EEC9C52C626E29689DD54FA433B970
2636FBD87C5D81C4F278168783509D5F4256C77A855C97A48D18DE6EE1D47C7C33E9AD227ED7
02F120303731BEA6F3055D764046EED36A06C75855A928084C5773168AB985DEA7CD767C780A
91E740E6E088CB93D43A489145030221DE0E1B2DBE954EF414B9568F3B1C5329F5FCBEE927AA
23309AD22E10F9349B6CADE7A090D19B9460405CDEB89BF1617B2C297AF5629458235F1B8C95
F5BC442DEBB34DA5D20B11E96660CE9E5CD19A84AA54F42B106FC87C7C0405B0CBBC249950D3
A7C353D691D77BA031C840C8F43A220CFC749CE34C2791DD627CA074753963D2E59794496D55
AEC96FFD48EAFDB29F8ABC8D91932DD5B01F65EBDA034BEF3C7219E097670621058662C5BBFA
A939DEBF999E9F68E5C4E64CBB0774A9A186E741346103865FEFB088AF547545CF7763DA0664
96986377B587EFCA5C9EDF22EC13D1AA6F483C4A0ADDFE395F83534D7BE5285E6A207D53A8A9
60ED89E9BD27AFCBBDA23B2D9876A8D8CFCC299990D521E076CF8387D514570871376C21509B
95EA15CCFC7278851F14DE8308B72E111893F0338488BCEDD0F2F8EAF07326BF97C3727459EC
89F8121C96A45E3DB1C63D478D0A6DA5F5E6834938EF1CA41B910F25A82F2774E3CAE9F1909D
BE21EE8E003E27B84C43B39FE247B8E19538648F246D325357A246365B9B2B13DC68CDD7E44D
99D86C642565B1FC376D2E530048B27A7C44B6811719054D3AC99CBBF5665AE76F11E2781B8C
040F73454BC794B1432E6C3A58BBB8CBEF345D3178C8D01D6B26BF7F485A5C3BD36DD01F39B0
34E536ABDC6632EB4038FCCAE0453E85B3BED8C3D4620A2AA2DABD0CD93090E9B8E964C491C3
AEE45B592E4EB12970647E2A5E68BDA429F53074257C02975268F8C28F06350C26646D658008
FAB0562F40644EDB0FBAB79826B16CFFEF1302C8A13173CC9CF7C8FC906693E486FF096B2D18
E96841A5FA8A34A5B4B68462BFFA48102464DC22EB50F1F80A26E929D4CDC4B90589266915E8
433D46D433ED8920543777360D25546794CD9A3A1EACE8AF188CC18DDB9DD1659F9FA462A5AC
E6A6AD068140356E8C1E48DEFD171947F78F086C6E267FEF13D16EE68D0FB0AAE589F7E090F0
88FE80BD6CF8EC0EDD28C735748FC6E7FD421E33B16EA6319937D2D63A94AD76F95B61813DB1
81A113274D5F3B4DF5EE90E69FAFCAFBE4466F5D5F48EEA62A7CDCD4F9418437707F706B290B
86C30FEED99522875EF5E2D491920983BF4E9F1C71F20F1B9645E30521EBF2F1C9010103C60A
9A6DB7E6297F7C3E29CB150307FB7A1A1A94710EDDC6AE88742CC7044492DD7A217583C99A6B
E7B720246FDAA00683A3B82EF6BFA87F2FCD741AD8BBA68B751740435DC6AFB1BB88D1593DB1
52CE92C19E1AB29C8E8FE89477CDDBBE29B8DCF1EA6F70990BE9A0425000404F2F5DFBAFA35E
70BB87066464C992343E8BEC66EF483DCE474F3ED7953DC1F6BBC14EB3495704D1765D0B3285
A05AE494342F6B70D9A4241291B3147C77A8AC0E08E5BFE60C8B6E2048876A6CBFAD8EFE4860
95DA764F4AB9E4D8153F89BFA2D9BF2759826EC18F64F1AB083949F4BC127411A477D4C24D7E
0FB0C96A96A31386CC5892B398D48750FD09638BA6D62CC685688E79AF31F13B744F395984B2
0AA483FDA558C6A91CB9AAE9053E7A5B5B8659BF0631C543F4C370FFB006290353908786BB5D
B373233C12F3506E2C4DB0D59C1EA8EA75A7662B90C4AC1561303F4FB8536C1534FEAE4ED772
DCB49734F5285FAFC99FBB081ABC3DBE87180D9BDE2A844B054D8BBBBEF5CEB39F5CADE252EC
6164A74E75625050CEAB8FD8D8513550D4420FDFE6FDDCBB816E204115614FE82CEF36DB23A7
DD31CE6FC923B575EAABEBB5820BB2739CCBB41BE2A4A95CFFEC9332DACF05936A3194AB4F77
39E5B4A868A7CAD3B1D940056F84B41E81B072C02C0D0BDE7C64DEF54B1097F68368AC0B39E0
DF5E5733FEACF02EF12A1CD0ABB0805C2F7E7FD7C824D9B348E893D68F3F31B807829015C54B
8D2AA7E8DAA14A364428F3E706FC649E274E47914452704B1BC56A41CAAC736C8826B7BACA1D
4FAEBFEDDD0EE8FE3BCB53EE291356B7A4B699C33CD7EAAC34E3B92E7F3ABC32852453259908
74E34513647D521ADA13F83584CEF20DC503EB352BF881AAD4C00894CC581A819CA7CDE96A9F
8DBFC22767B215141C8677BFE6F1F0DEE4254986AE871F87BCCDCC10E2298BBD90A625337936
3FFB2B093C2F54001070E655E9C4CD389266DE373971BB763279F9EFC4E5A223990153618C66
54B5740049A3DE2A80D613CD5AC5BACD34315C43996D1A420DDDFE7365060EAC81AF060B8344
3FA8176CBE3F4C2EA819B493FB5B4A2E4A0039F028CAB0B47FC70F178DF04C7CD4DA22BFBBE5
344C9E9CDF1020AC1A43C8E5B9D19B621565A6DAB2B1CB6CDE2524B33FB1DA6B5988F5BE4E73
08A17C73E406DBCB51FEB3D79B84FF8B0284F7EA92BEB9CBA6CD5999CA7DD20EC02E000FB48C
DCA51B8E747C0E25B28431543D9095482657364ACC1C647B2140C502623F7B9E3F335C2E44DB
33DB82C01AE27AF66BC2284971A5249911D897263210DE4A9A65232738D83D10AEA8C5D3C687
128B64EAE94D6FB30B7BA9105BA8E01BC9925C312CCD8BD273E904D8FF13F4DF7EDD21C23D0C
09A32A4C90B0577ABE7AAA53E836CA60B1697621049BB36F8013026D77910193742725574222
DDD3ADF4E872E6D57C1DED571A1636893DD7F49D8280233CFF4339B075628AB591783783548F
17134E69EC5EC25B3B8036039DA276BA1507649E7DF1EF9E29F0AF07BEEEA346D470B4F1DF92
5040602539BD1D8218384B53BDF16C74A1A6BA2A7871B67E06CCC015BECF2F020295E27CFAD6
2D3EB7831922FAB24780FB158C21E769875373606E1BA9BDA9F15352EB5413FFE162EB2AC194
4BD7D980D232A2F3DB3CD38390E0DCE3241113CEAAC83EE29B2980EA6DDDD4EF5727024E4343
AFF44318AA1382662A78A41BFD6ED98264A6B0BC629CF924EA0A635B0885D682C26819043E39
ED44241D4E8B50AB92256F9431A8123117D77891AFFE4E2833BC0517DE287A747E88409CC30D
7D098A4FC80C6D91534304E7FDA873FEFF704EC1F7450226F09D5E89E245622973D9A789736C
71E6651182BABE81ACA969C62E1458FA67A3B9D38CF364F383E719F7066D2839D95F262F8A5A
F87DEF903EC3269466519E68E857088D318839FD0B0E51A6D358A93A543E2401F57FF7E970F8
BB7BEB37BEACAA000EC58DF62D2064EB45A81144C146B744B10406EAC2C1E350E2DC328B6A83
9DF820B289A84167B404BA1FC63E453DE7B58A9EF959D7E2FC1DAEB5CE90A1DD935E8C5D7DE7
E2684FF0502901BB451FAF9ACB439F548657E3BE938E7A2B5924DDA2E7010CD26A181D84A5D7
5294F6E56DFF88F3C207C9D457CDDBF2D3037AC9A93CE9D53FA0CAA4F21057762954580F0F2D
47AF43D5D7679A9D44D45D682EE73493A2B8C390E24EF27C84E701C879BBB1FAD6BC8B89BB27
959EE86BE486786D1C81612D9546AB59D5216367C027B5B0F51A41C9AE2778A04965A846990D
1727F3F3E09AD0B913C9742371AB5669A2CF4863833A19CE69FF161B1D6BB0CD61272CF94526
4584ECDCD290E2767F087A836F12AACBECAC49C3FB28A605C6220E8233EA2C9AEFDA87EA2CF9
D3D52FD6D16612AD07279DDFC4F20B59C905A146B1F4A51547DB82758886E9D3609B495BD941
616057E460B94856191791A2D16B90A7C33534A9DBAE17C96D68E009219857FBC92EBE189875
EFABA56704CC9305DE0D32C4CA5293B306A4EE9DCBB131C128626C4171EBCB2DEE830B9BCB98
B4FE23BC63C9186C21EB7D9CDFE2E685399D57D6D1A857C11FFE47F6D0BB79839B6C88702EAF
6A59BEFDC8B35A03768AF411EA16C277F7EFBADA006619B31CD2EAB657BBC8CD4A44340F4D9F
D34007ADDDF2DCAC3058D22267490E90657808CC716B7EC3444638215495A7BF077956F16EE3
053864EBD2EAE7B210EA370D71414952F2076D689ABD98E76030D92E4D49A79734FEA3F05719
8F8DE62F64468D06D0E6443EEE3F2677049B08E8A09907A2785D91C009F8FAF6F1DF1CC39D0A
E11E8F1C939A0C13E49A448E89B0EDA7CCEF06166A8449B358B0C661E40A7935A6E4F866ECE4
23CE4C978CF749F3B2B8AAB56AEEEDD498DB77143F77B4FEDF5C6502A3D2AB4D0BDB8EE456D7
DA3B9CC800DA8D0CCAAD981DA5193A528C7B5628F065B7FD1DDB0FBC4A74C32751E8B4747206
8A3A6F380CE2258D33FC49780EF2570FD279BBB54D4246F40CFA9F13AA9E13C6CC030DC19960
115C2DAECF52027F917D3D9D44C60B0B2D1030EDC6BB055926CCC512AC2BAFAE7C12D8ED487D
D3901FC2842D3A7A69117A8B82292FEA44FBD40BF6C27686EAB94A520F63B77B82D5425478D7
4B5E4E81A8439F560B1CE7C626E51CC3EFB877A9AF37BFCC1A72D40855995DF53B3F4451CC29
A5600CEA6B2FD2BD9DDF106FB7B6B6E19477426212F3B5C25DCB1B777B643A318046E02ABBEB
67201DD98D892D6E13B0853CC206B62AC7E7D386A77C6C9A3817FFD5009D515EB5F770DCA0BC
4D9DE562EFDAAACEDE34096EF6DCEE08C735DA36893C41592443E0B69446B93EE9F758EB75C2
4FCC4E8193A1F77999F2D4395E1BD24909CB805CE3A26A47ECF376A79F480C9402DCF3A86BFA
971DB7C977F813C21AC8C071B6F210B251695A40B735D7F8E27F9DA47AF7FDE2A6E7321488DB
E7555BA82E23FA2DE3092227E1A21C5E6DF4EC83A0578B4E99FF377C9E655D7D6DE412CF0F67
D3ECA45624BD1AD4EE76AAA5F99C73A1FB470C8C7EA472890E1436BB51FE764F95810DA0C3FF
D1C3136223F6610F3B226978B8F9E35C9B09DC863C05DF439717251910A64E4AFAF2323CE1D2
A168DC57CB1F4F2F9D24071F49444B1A5C6956F236734816FA3147656FD7C5F547748AF983E5
529FA4787E540BDC4023377A7B7E248A37550CB0FD519F30F1BA3A323D171612F802068AE4FE
FF8D067185F9E5211B1218656EFFB8762824E05EDBD304B71678B3C4808F7819AF193B247D3D
7A3EE51986157E6D101C07A521379A097751CC6C53FC6AA6519E2D0093AD0CCC5145F4D788F0
46EABE997100DEFFC6B7D79BEE09A92E34BCC15124D2405BB614B4E265378126544D041C4A16
71E65832930D6F15E11387F39862F9BCD513CC611A9F9ECDFA53175DADF03BAAF5C32FCCAEFF
3446E67A62D3B15294E426310F64B6509E88D3225DF909BE2C73A9CC8CC643645B394CC3F5C6
1FEB91F1522CE9882A60504C14C69CE7089F3EE5B3202D3E5C2C2A98B8A4C8655A911EE03DBE
72E474EFE0A0B1FB9062E474DDAE008B0ACE5016AEFBB40F157B9BF07ACBCA319380105AFD61
5DA19C9F932BC8D14480F6AC4E607FD4A7C34AAC43CD26301EAACAB8A4DC8584EFEB56A2E569
5E84030F39501223DF87FD3F16D3950713C483D8164FE2A180AFD985C11D55A9E22A61F0C5FD
3A0036DC51904A84B07D409388B897FC92C1C91A971B2482E668A27386B33494F751B5B9EC4C
5ED765A88F5A675960AA7F644E77696BEE684E098C69A8119BCA27067E52E1FA95C3E54CFA56
8FEB54B92C3A8A2DA2CB44C9DA1DA7BAE1B05087D025F767658D885E89D654620C2827013ECC
B38C7021F83863313BF35116AEB2669FFABD5F1F035C23BF0244099A32D2FD13EE00C09E30EA
3BFE334227C6A143CB716A3C584B6ADD52C6370F7BA917855F2295B9DFF2BCA64A0504D0E557
861EFB856A19CE99B64EB7EAD11C2474E79D5EC30DE5DDD094AC37D8EE50C4F4D39E32E284B2
F347848ACACCF519272AA1FEE3000AC3A495B54385CB50373AB7B790B473D0449B7622AD526A
1BAC985945964D6D2B05089ADCF9DB30F1032639205877D7E78DB7F9B136055C1451663CE4D3
9FE864E02B1339006A1065FB76C6E438EB132629AF5E1FCF6022E608674E3546CB02A893B558
F3B2C76BD0A897B4EDE61A21B8F6C34FFE820D66F3B89EDEA86E13EF5CF0E33E82BAC2B4CE6C
DDDB572ED1C9AD69FF853ABC58C0CACFFC0D86D80D7C8D10139ED4C9DDA73C4B56E375CA70FC
E18EB1E322F046A4A44AD7F2731BC2059E391688C03B86B305E9BD9BAB8F3D1B6EE52789D559
A5200AC84183FEE544DB210122C74BB2CA648599DB3CD1AF261567B84AEB332F0647288F8F8B
01D5068D74D7E89472D8DF3E901F6B523FE04C519843E0B730F403BB99CAD493201F950E943D
B95FC52B13A3AD8CCC6478D5CBE5DD019BED1ACE4D02E09353E6E31B9A9EA9C76D89D9490D71
3CA451693D235A0C8B0A3DED5CF2A846ECE5CAF52627ACDBE76CF57A09CF6768D0A53906B15A
FC5183B9DE1029D19E64B64BC2E075B536663C524BFE35C9E412A7C0D23D316E0645BAA41DF9
ABA61284F801F7CB852F49B24A96CD4C743F9B1D1A69F3E30808282C32C2C4655715D8F3AD53
F3FDE97823989864479EABAB5876C77CC134EB66C688BE3777C74B3A87EF1616DDE5A8A46185
997DF2FAFF5518EA7AEC3379730BC509D09C5C378B47DA67F9F5740B641DC790766896352D0B
E0EE84D686496066469C995583EDA0BFA51178091918D2B9EE8CED4163E45FA312885A64F177
F03E6D77DD649C7D71B47FE885D72887927AC070CC64E825917776264E722AA6157C22A429BC
0D38B56E5A0D6473FCCAFCC17B4BD8860ADDB9BC33E2FDED66EF95205FFF084578C37913E205
9CB3C1ECFA4142C0A2AD1781C373CB6FE9819F4CF8E5B5774D7A6BABB1FAA71D0C96175B9DFC
08A3154C2F1AD566E0D03E6A01D3848F0C6C06755A0511948D51FE8626A32AE97CEE9C01E15E
A61A556170E7E4D3697783BD42D586535C38CCA8D543A9AAA828C4813E89BC30B686049910A6
C01D7FDCC55895A3F7019B0CC78C23925D8CC1207C51FA19E6B8992A289EDD5669C33186A7E8
38D5A0A3C101C82558785010F877B05D943C5F874D0524622D43EEE25CA87C2AA4553804CB6A
D1508B9406BB1CDF868DCFFD19483BF1D8EE2844E62A2E1CD09807983B7742A841BA2A03D8A9
2568624EF3C504F9B2F4389E23E323D1FA1F4F0670711DA7D827400F36C9FC870EA2553C7E25
45E2A5086FED5BF966114D5FB48721AF70E04393326BDE080D3082C292C9C251E2D82C0C3F03
04E9A46203E0E5E76829E21A3B961F02AFAEA15397F0060E5059A5FC66A2B622AF1D62FCAC51
6EC3327C95A0C2810EB42A7209D12E90D1D41EF442D0F3DE55493615D4135B4F44BD09759657
58B16A8DF9D39E78A73DF41C2EFBACC2C91ABF75C849E2BBCBAD263F8577E16D60BB6BD463DF
3A4BAC62F28B44CE08BF52A268AC27779E3A317B965A44321615891B627541C53768F33694D6
EE76903BBED8ACC45FA00EEFD20224E09D95E93605987839D92C4E0E1853D8C3F25FDF0A8268
B38A6B8D9286535A49B25631BF31451F81B5ABCBA66A07056EE34EC320367DCE6CFA97113291
32E1155535F8094570639F9FC72E1ADBB4EA99EF7C7CFCEE8D74C2AC70927CA9973C4E1C4DB1
13613466EAB58C0037BA93230A3D6EF41739122912A15319374C6A6D7FEDA8B1DC15EDD2F286
12EDD846D8AA051F24523BF92C6920C2AE3CEED5868BDA6ECD483ED181AB69CCE78668A087DE
0A00A960810675F75412A8EB6018C638583DFB07B4B4CA48C2D3A7CD407F552DDD7A91556004
2B173D2DFE64EAA41500FDB64FE572E09D06BEE892AAF0CD711F3D6752302EA4F69AEA675A48
EE69C2416805E7E6EAD9889FE072F1C2F5D3A89D277A90DC9EA38271DA1A455CCB3598FA99C5
5A788073DC12B2265D409DE2DE24FB4399E911CA80169AD5812BCAB83BD0692C37A1B8053585
BD7303C20B6A06BDE9873823DE9E9EDD9F403E78E7C386341919035561CB94379210A5E14CB7
43687CD843FB306B6946D8BB1C290D802EE3F096F54D70743B22E661F81C89F190971F27FF9B
0E6C273CE3B35E6F5A586B411F6CF55C2909AD70D348C6F6322EF1DD08EA36F1B99ED590D012
3DB978BCFF31E5EE9EC3FB969E71C0864757AEEF1750ACD6A6F08A086CCF15E65A712ED37564
B73DCF2A5E86E05C7725DE9F13DF59ED3E92438D9017754365735E5731853520D9771223DE22
52388C4C6F7FF44614112780B14180C0CE01C50F94BDE65F4692CFF4B52F6D9D1FB562475BF9
E94120A510389E9B3574C62FE0CD45E19615971BECB8C2388B4D5D095B914E6F887F3F708D7A
65B516758CF5EEEE4DD127315FC3EF04CD5915978141B2CEFB3D2C0FB5DD64E25EEFC85CB2F8
80CC6AD20B9C9F0C1256A9C4E8CEB2B400C8D50079E6F58F7A064CCA9FC3EEAA7F7C34BC51D6
799520C5534EEC1A1EFCC52B9ED43E7695ACAF3EC4590D9C0BC16915769DEEF8F39BF7992449
4888D4DCA2484053A29598DEC70C2BF94BC2494BE4841F9676DE13196AF9B9A329DA016F17F6
2ED26A75CA3089750BE5DE919429B989EEB4C10C20AB764BA2C4035F14264B055771B6AB98E0
D673580FDEBADD2719C80E9B8322112C9AAA9AD2329B045EFFA948AF1EF7B0038B4D3C068CDE
62E5F808213F4A04D4979BFDFFFAC94483C546B35E965D4D0625FC01856623E146EF193A5538
09C0D1E182E8D7759CD2B467A84254A2EABCEAF9E764A05BBB84522353B2505C56115F489E4A
906064C9C5266F823741A1BD1695796BCDAD01B38003522EEF9FFB7FB7F79F8D6C43B6685C17
F72F06060993C9A30F8E31AE8CAE4F3BAD51D8262688A6443CE6A07C1CF676CC4F755849E2F9
DA19B14130FC72E31BC6E4E062C041EAC5EAC486032535FEDC0DA2F8BDFEE2B72C1BF0BE510D
BA08E0A5700FAF1686EAA93420F20F92C0516609ADAC4F7EAFB5FB2CCDA18BB3FEE2702A462F
8AE39A733B0699D29FDA1E821FB03964F477A2FF5580FA4874F60D6F3505A4287E17AC2BF565
9E42FD41F257EF45798CE2D8E09C0593FE7C41E67D79316E8D61CDEEEEEEC60EFC9BF26E803F
5C3EE7404D05ED2018F8C9DD0EBEC3BD39E20AFFB51582BD5049DE9AD7437849330674FD17CE
6B9B6F646F9CB66CB5DE5457BD512BECCAED183FD5C5D834846E6F8BE301FB267A4A67758590
3CE45864294FEACC65B46D604D84D846098339D20FE034B77A49DDF85718CF9DE18D10028B37
15994C5F2571EA3DC7E98F66601C647C80839E3F3477D78584870837F653243BEF6FF49C347C
5FE9C7F45A28F7BAC5AD9929D508628CDBBD4EED3295F06CEB89D378632C34D514A0B22BEFA7
E090AFBE45EA64C03BD1367B63763F4570D25F59E83D344E8DDCD26CA66C1787FF09EFB314E4
CDAA3BCAF8C94372828623E973768B6FAB1327C6CF5BEDCD37972CC2505B12D2A26F7D5AC9E3
F623024A9370A44BC95FB17C035F71BB43853DC7CA66BBA610CC29FAE5636B21C2366F88675E
C0EB2BE3C127BFD579CF818ED98D657779430F5C75A0CB97A52F3547907BFE2AD55A59B0B5A0
DF0D25000907FDB6D5781EA549FA89078516665CBEF095D9411A2DD1CF6A355BC77E2447ABDD
21DA230AA18D5E130DFEC1B75E5C1F6CB9D3C860A95E9FD960EB8D73EED1E168E357CF305786
A8F01B63EA2D9301A6A3F886CBE4F678BF1BA1CAD67F3924B6408561A435E0720DCDD29C53AA
53C1747BA074E6588B3AB7B66B5686AA58EC9BFE7DC107D97B8EE627C9E79601B95791704FCE
469944BC90EC77AE5A9A5F2A73A4894712899DEF4BA334DB850A7187988BFC315A5E207AA6D5
76741B3068F18C7AD741B6A4B6DEBF5A3C3E178D10E25FDDE0A01AFD5EEF225849E3B5BF1846
28EE473A34303C2524D78B8E7B8D9308F1A90852C8463AC1997C91DD233CCB7E4A16E95CCAA0
E4AD48E2C499397A4F558C23360EDE957D872238A446C39024A369429B2CE348AA5FAB425897
EE02B71F085DE26264002AD168130598150C4F560E0510A135014E55A74F65B4CE7E1A96146C
609280B49F0AF1830C3C8A6045BC7774D3895348962A7AEE947AC962547AA28B02608CE2F91F
EC34848EC86C4BF8507A9C0AE9A0697699531E11ED9E85CCF52231672F0879B801860B013181
5CCFC49012F03305D6D382E4E4565BD1D2F860EA8BD636D8582FD332972F1CBE62844355C933
786BE37490A7EE43217854DF7797EB8680B93D9220F643DD70B2993A7A0A194159A9BE04441F
478A77B3D2CC38302701166DEA70D72224C9481BE0E68BB6802BC6E9D131C3B3FED642779139
5CB3393D4817AAAEDD39AFD6508C9CB4FD67FD3BC18C65F27203AE022A522C1B750960B7A745
0EEB8718DC911D645198227B2E729B6CA4149EB9D21369500208D94593A087C76205D1046B91
4C31FB5F5D6FA1EFC908532B27AFBF73C27E2FC9228ABF72920CE48C03E3381A952A0B1F25A9
9EDCD216B154AE6279B33315E822EACF095C00D7359EA834885DB0E6D07BAA9091FB364CFD43
E378ED0C06B9A1F7C3A7922C85DAF6CAC5FC111A51292D4C7D43E9773F262AA032782252CEBF
2274842EA390B0056C3E0BBAF1DFE11D91679F6313316735FF6820166D4FDDD7E76A72469529
1E224466ED210C82AE79C44A828E7B625F872C5A3723FF9A09E7D77D0555C9984F7EFCBF3B9A
1B156E5047E312C8CB86D26B0E6345FCE3BCF8D0196C95C5AEDED0403733EB6BDE2F6A65CD1A
0FE13DE66A2DDB3F912ABBFE0CD59D4A6D9299E1309CF7494C93896FE76C132FFB98E3315B28
950E21CACA613DA51EA612678FE24DB3B04BA25EAD7E2A020318D2C79619B78BAEB21AEE2E60
69D8470392695EDFBFE2DFBC2274D8BC8BB3551CA84E341419C7E718187260497EDCAFB7F588
D1C7663CCBF8DDF1FE23C48D1A9B211BB0C75871CF8DE53C45A00E601F87BD65B9471CCC46D4
481C5E83BA65153CE608D5FF6595FCED940CC0999FAFB2F44E0055E57E59C73BF3AD6FF70CC5
A0F32A97D61CDCBEDDD34A295A3A7A9DF1EDD9169616D1F8D4C5E20A86DD2FA590B46A974D11
45FE89D1F0664C3E0FEF70DF6D393AE7CF0B662E285C02E9C447672F73E90138E68F216C0072
F5BBAB3943B40D24FB09841E142889A4B927E4A7F762E0ABDE430D6C4D8026F76A62B3B35BF9
53B1EC19932E8E24EF20D2A50BD0EC86D6C0A61D1B206AFDB625353E1FDC15F96F3A48303DC6
CDB7E4131FB3B6E7D80B1B332673F6D1DDA6BCD90F359014D59EB5445FB90E31E51D9E1962D8
20792C2AC64E60125B0EE5CBBE02AC8BB9CA43A2961A5012E0BAFB42DA92DCC8948B043F0F98
C522149E57FE699C9BCA6DF84D5FEB2F55C49407AA52345AF0F2B39C360876D5A6FD1C3C6D42
82F070B8AE2DD3BB78DD78C7801A235EEF4A700128A9CFC7CC3B122CE69DBF577F6531B7898B
A31A1B915CCACC4B3B1226104877EF805795A93A2F2EB41CCB759441A17E6B7B033094D0861A
5A55F80D94B203FEC9582926A9CB5F8CB395C110ECE72754485D674DF6CC0BB84882BA26FC17
01E3B2530A2D44DB5E8702DF2CDC597A8BD9CC12E95B7D274A51136B61E49C7F920BE8E6E17F
1B20EFD1F6F84ECF575B2CCB40AD7876E8B8C7B083E2CF8253D06CC4F6CC2A5FDBBD8CE6986E
18F759ABB35F7E77AEF16D5BB2DFBB457DA2ABDB2148EEBD4F88DE2B9B3244FF78BCEF9F98D9
3AFEF587269D7952B9557D0EC61FB268980730EF3B6C5CF569EA19DEDD3AAFEC29D8FB9DBC80
43E7C702920C678DEFE3017BD9791D74A6CE7A6BA312EC7407D2771A6F22E3E81EA35351C3CB
BDA7A7A5256C67AB65C84F0193D75209307DA141DC60D87B33684BCAAEAC9047A0F3861EC185
132A14F5F48F19E38E132FEE76B5D7C70AFD29FE30411C5B7D624BD75FBF27D89844B1845F02
7B866433344AF2DBF37587F2144E40358096A2F6CB884595E57C3A21A1B5FD1A9E007C530FBB
2FA384169531124511C0E643D093478AAFD5CBDEC5EB0EF47546A893EF0D04E30A89BC3D4516
351662F937F26C80CA874E471EABA85AB541F51FE6F94E01BA628A0EA320FF000A2C3B93162B
40E33F49C81F759B0CDFC167B5E06A6B2592D78794A4A91A03F9F95AAB96850F726DE1782B03
F66CF1C647872FE423AB0DAD21098C19A267859AB150D8CEE49EA83C0984C348D06E99EDB60D
797683B4B5255E3C521619DA2C26038BEEA2C6C013383A30D6155C3C6FECB3FEBF3205D291B3
E26CB6F76AB6E222FAE350EF49B9C15AB1DBCAE734E377610A27B1013F0AC3B11E9235E952F6
C65DAEB43581FE06E04BD94DBDD42AADE4CD6B475DA642910A0240BCFBB2848039B614F11B5C
0DE8B157BA49EC715748F2857009BBB3A0B550B4EB88631B53A69F025F61E4F0A1BF13265E20
78C6291C114B8ED63A7F3A2D3FA6EA7BDA7445CE3DFA913FAB9FC964D6A5599175CE8EDE602C
7F17CC5E9390AF0D3148FBE8E7D5C8780DF83D34E4C1CFC0BA9DB11975A171928147D4053086
BB7A29B4CB6620278E5D7D42B5778DB639D37D3149B525FA9A2B972D3F33A2E6735130446448
EABC73AD3E00E0B2F5E774ADC1AA4E9ECA4C0E5DC2AEF0F7DAA42D37CAFBCF8FE67CDD3E7C02
413E617562850E2EE2E68744895071D192B4505470D228C8CE86FF4B650F07E454F8DF8F5376
8226231441DC5A026FB268E920C71680BB1426E4FFB38B27A019398C3CBBBEBA91C4988E10E3
D873D3A7C8FC4FAA207B94A23E653BD646505B8688530D3DD734EB22AEDEAEE8274FB964378E
744E82C76A1E65E40A60DA47189ADB7FEF7006F180C2AEDE96672B55E12700D795951BFE14DF
F7EAFCF483E8036C07226D1259883EC8380404BA3523D786E55685878EA1CC6F9D2B32DD91AE
126BECFDC77B9825D602E3F18EA08021413BC95E5F64A120D41C719CD786BF2EF3E1A9B5CF28
D80F65B01191653515BE6B53E59834541465F45839682F587530B63A3BA92D74062042AAA119
12B071EC81BF6667D22DC7302F0A5299F3F3432FD03820E43BCE1007BBF0620163A0AE9C1A62
B6FF44204FFA819F9D85849D450ABEFF5F3EE19B3FCA8EEB405ADB8A05C4809BCA050F846975
C56B5079AE720299A7ECC8D846776048693005704658E43640CD89E6149093B4778AB677B379
7DE560AEB7E09DBE57D723A4AA62EE8C42A83C10418133D262E5E9CBD39532F3881662FB84C3
8F33ED685443965795C725956506FB106FE0960832A2C292560D3A43EEB72F4355B836CF5044
767477AAD5346469F8E4E90F712DF820A0B7183C0FF090444A994D81E2941EA3C373282BF57B
9952FEE56B1B0B7AD89AEC79A85DC03FD2A35F5B87E061D15B65A48398F836788F6B41C749DB
F425391D99F0B31420DEB5C800EE281A427DB0C1FF7E03105C434F95907BD74775C980B4AB46
A88652C8D59BE6CDB3531123CB25E9AF5CDADC324AAEFB9F8DC7E1EF4D288C6DA52487B922A9
C9526875CB3E528AB79122F9886517E892115104A20A8EB4CA7628083B24C0B0F0DD2BB0D35E
3E1D3BD0D50135F7B7F1F5FA5349C9953C4F61F00EF5F11E662AD12E8D9F156E32B845FB8E12
1297658DBFCD943F1AAA74F38D43EBD080C41DDC92101722D829DFD3EA37DD5120803EB06734
6B636815A8738403DBC18BB8D8164A8E450A7273F8164031290B465A44A268CAA510E9EFBB71
114E603718BBE415F2426ED24BA413B286C42902D8C5E483070D3A3C57058E6D640369797383
5C78166A00C235F8B4A4D155E723010F7500A7179625D248F2DCD8A368AA5FC85600143AE81E
BE8D901EF42702D30AA628595AD111ABF0E1E06A7939420D648F03FC840A51919C588BE0F7B3
BF71B51EC7DED081D0E2FACC72D65C77FD6864A2A30748803D0558ED2BEC1FC3A91710CC9F6B
2C8A66F8C4EB43635926CB75B89AF438F224DCC5A542C653790E2CB2831E6AC5590BA51EFF51
40C5F620102ADA7E964D21ED4E7AA39B2735E67E1862227C6E1DA2210EA7080000E90162F5F5
2677F188D75022B9A6173AA3F4E45449348EFA7A4D119A8C4682A1E205DD922BD9D65A5620A8
D9D103B853D56B872122F3B649565C904E6284D66979793B16C853BECCF478864EB043CFB096
42F0675D88E62AAA8088291E844F34AE84CE4A93721B4F262E0BFE50BC17184D4A2A469FFA94
8671A565C708A79A8DA61041C5F60B1D82A50C52A6E145FEBDBC69CD0F32D81382EAB87FE7EA
2EBAB016E169E5092C277D28A0C1197B760AE2EE5E307FE6B23D120605E03374AFA65DE773C9
B543D6B6321732A158873823AACEDAC38B2AE5DC0DD9EC0BC159C6861C99B18722B6C84CE819
07EA32F1D8434B6CD6C68523720859F1C1663A921B7DA0DE2A9775B181AFF992AB12E1A1F3E4
54E7342B9947D893557DEA500F36598D00064657C8B952E299D679BA20D0583FD6869F131495
6CF2D1D8E81A0C20556F28F8729ADC075535CF1006D8F1750E479AC6066823B31E969ACDC75F
62EF2704DB581A7B4FBCD22ED0A794B52494A69F4D57816E604BEDB0C1CEECCD3F80B6B50C76
065503F13C1DD3834D7DB2BF297B0C8B4875985310DDF076F0D6721FC205C9C0957E43E07EE2
CFE21647A2BFBAB8136866C9C4EC51706D04E2408E72B6106F02085E5213C5D88BA0B90E0078
FCD4A4214120820F0809736F4E3C06C6E0E6B4468A4089236565AD25A85730BFC3E476E5F0A4
DE180BE7A504ED02596543DF24359B7EAB8E5CB1AF98528D4F0FA8DF2EDF90C2C6D75600BC94
61924029635FA8E2BF07BE105288333A93A0A70A6C4A7F6D8D5F3EE677A017478747CAC65A57
A0FAE14371CB16FD6C39BAAFEC9AEA1CEED0E66F30E5F4B5D0E8D9D56DAC6D552163270CEDDA
49E5272BC389831BF07FCE638F7299F5C0FE332B7E29089D77B0140604B8AC0377C10C002046
8F250B3F03BBB37DC29F5B1CB2189063B8BB0F278AFF414A86A2F8A18FF13EBEFF00B4D723E4
90B2947195648367E0A7DFBCED6EFAA53EF849C79DEE21E5665409A44422C3A36FFB74FDFD10
17D31C32F9E269640AC36C3A519DB5F76198F1AF12F71ABBDF8CE85E7E6C2ADABE4B47897CF2
4A1C7B5934494F07790965C18296B977E332BD853232F2E2BE755F36AB8B1773964A689E1BA8
48F9F7F01BC585E125F00B90576FF82BB1BF90557D064D38079520D19DAE87A298514BAF1ED0
0B89467F5FD445762B80F1EE8E67FEBE8B5B2558B32CE738201712612A56D824983EB5403A70
6383D135BA5F1EDCE9833B81465B34244901802B7684AB914548C88C32FE91DFB0917751D843
5058ACBF0BB78D11118F14A0B9411BAA1A6E04088543E99B70130884BA971F4DD03F1AA3F9DE
4B1935663AAC294C9597AE21EB145DB431FFFDBF163B23F3C2675662C37CA63569A818D47B85
3B59983C8B6EE24560B2C7D426283995D86A7DFEC4B6558BCDED8A74D214BB6C86CFB902CEAD
F6C5FEFFCD06777DD761F9F9EEF09E9A510E0DA31C3B847130961459642DB3E533407A19AE36
00973E4F70EF0912C462769AE399EC9861AE5D2A243CA6538943520DCDB2A86633F3D95F1F14
E6D63126FF361FD287539C686CA9A6E4B46154467CE9CF10EAA3DE0EFEFDD09BF305A5584C29
DAC82DF9418734B01CCCB57666E0EB5E5617EFFA3059FBEC27D3DFF8DAAD45EEBDADBD272AE7
9909A4CD3476F9E1275298429DDA620C15B1E229135A472B013F5457269B9682A3D41E20C66E
EB7B874F26FA9CE0B2C8658937711366BD4BEC4F30A14BB1FECA238CE9476D66D1BF4259941F
61A7DE0FEBA45E5002A9AC44A7587FB206277C01F479D7CFCE8809687AAED92F7D148432CE8B
AC0AD62DFF7640554D59E88CD83022A8A42D2CAD6EC197BEFB73669DB969D468E7519943F53D
D324F2E9795526537393C3E5298B9F4E9961A182A324DE0D8109539FD483E1C6B0588584A30C
B5052487BA59B78E2959B3A2BF30DB1374D585BDDA52E088AA672AF40A933C94CE9B9F63FC83
ED72B19AB818CBF269FC03F38DD982A48B8206307A10E6833B3CD33869526F10FE1C92F7D0DD
56C163CE8F04442CB0DF0E496F2A1DCCBA88D0BF260C0EB856E081EED167C6EC1D8105B2D3F1
73D367CC27D0F26FD89995A2EDC6D1A215F57847F7236753FBEAB4954510CA68688E51034121
F2CD0D46C7B8E89E138FC4EE229245D537F8F5009B76D6117403E10DB46109C7B58A67E0C14E
6347DDE8242030734D02A5C3986148528BF20973DF3D17DA67E53334B678643F09B7F887CD90
87A6F635FA5FAD0A2EE43668A8B1973A42866A399B280787809820D0AB51787DF2A3907A564D
10FACA4D9B6349C60852C06444FA49F8E2563ADBB0EFE7B8250142BB06FC4C93C81BD8B51F85
86AFCE9678D4373ECF051908E3435470C360935180B80B2C03B5033E2AE1B256B426E09FEC5F
902F7A8878B3ADE833EA39EF3D0AAC1160E1AC3FC15170DC3FAF6D17664E6292C51B268666DA
DB416E5738176D6CEF2152B529C6DBEA6E563B5F7DEBDA3E49EE6EFCB88677EA2AAD003CF528
6B21E648EC332F0F0579EE648925B05D50261FCEC1BD57A22E58595CF326B5FDB2FFD9B8DC79
4C5E7854EF9EA34411546D28C5112B9DE1C25B861233341B2CC117C9C310160F612AC6F13F53
4DFAAEC92D6B2CBD9C3F3C0CED06B910260F7A2DD09B1B9D44346CC5A7D10B4D637275D505D1
301078EC936B96BCCD9A2B783A93019C5B769C15636CD94E9D4A24BEA9521A41703FD6F4EE8E
362FE33E21EAFF8AE02DEBBE9D9B379B7AA0AA0FE94C3320CA64F41FE488FB58CCC5F13314A9
F8A8428DD1D713C07489BB76A462E9C0E237FA5FCDFD3A0349B6B77067F055B7FB0F28953384
537535177D190465C354DFA1280FB3E804D3FC0D6E2FA88A5F2829E9AE07E9F7844463AB695D
A17806C271E20C58939A04B5F8DF439659990D8D8F885F3A7A43A4BE49C7ABD03DAF5DC78CE6
6ACDE634AD08C33363EB642ABA7D9C34C71C74CCCBF7F4ADF9A201E203F6540BC467DB200646
9FCA0ED2234AB1A31E73FC05E8D8D906E40B3055B3696D72C48080934CC62E8E850350E70CB9
558CEBAE7EDDF38DFE79FB501A6EE6676F9B7697FB4A90B84CE04808434D244ED68AE441F19F
FCB2E0E62DB832C31F7EE26D90CB6FEA5DAA44C297E51E6F9952C794562BF286BE8727262E51
5DF58D26BD9B97A5ECB5641D517DE35941143757645D511409808347297FD5D84E4BC1595158
9C4E272C6DB003B51628D3753DCE430C6154F4A7C5009CF5AA61D9CD61CFE3398701B65CAFC9
372339E6642D01C461EC04840A4F37E8289A232B1C06D659AB081C25CC56DCB1B914EDF4C7F2
3CA7598B264309A0CA15F079ACA4F69630C6AB6192EDD8A2350D3D1F239FCE30CEC5C7597971
6E22A6B3917E8F0A05D75F8D1EFE57E71836EF46D41E4CD87F11CD8857A3821E6A7E4D596C39
739424E37535699B423A22CB07CC47041D7B97260181794435F38CFAB11A7F571A725D084101
07FE3E53B16CAFF56F14B35CEB1363EF20271620260552B0B9FF5ACC9E8C508A0F07A4768AD1
77975F80D7EB3FB92B04A9AC5FCDD9738982DFE4B8DBD646D0F1035589116E961E1000B677DF
7B598EF17FB7442E07F625CC07E7B7BD4FDFED5CBA26EF286DB92F99CED631ADA9B6E4AB3654
C549D5539A2C6B2BEF7D9685F6C5BA2AE5273D15CA66EFC6FC14B3DC2FD47B50E6FE3678531F
E11B861DA29708943D8914EC5B164EDBD2B04DA634314AA7EF8158C3F4311CE9FFD5973DA940
22C33E3A69931930572FD8DA9DCF8AB915CFF613E7628C5773652D55C64E1DCEAE37C879FC17
A35028F33B8D14731DC832193B35D6EAE7B2B5BBEAE7DAF05B3B34CA3235D81FA537EADC80DD
C32567E15F80BB2A484CA51AA8F3C853696A740C271E1FB34D3DFA72394B88ECABC1F4E92CDE
907A139A5B57406DAA97AEA576412937FFE4E2689853C7B86FD869270B2FED848BDB95AB3E04
C77836021AE12BBDFB0BC68C09AA4F5B607D8B724C24CF6DCF4F54222CEE4EC643F1D4024C39
8ABD99169DE91191911AEFA67675C21D539DB7C39462FE640C5F9C9EB684C6037315B548DD49
F0C35252F2E9D5D4571880E66CDE49FA9653949D2F28AD44426978A2127122CD77B607E9D03C
74D9DD7D11E4A9AC2E3457FA9C79DB76AD398AD5743F6E077C36423E0DAFADD1D391EE4451D3
F94EC65470BC74FE2D2252F0540BED609F760145914E9437D9CAAC61BE91F76C5F1979C9C6A6
F73E690DDADE3B1295251F0E9DC3100CACBC3EC17689A8CE1AA3089A387B2727035514F69E27
048AAC20A38EE49ABC7928D0109D3B230B37F6092388AB62CA5B382DB76922CBBDA2D61B5745
6880763654B4D83478DB9C0F63790EA68F5C154EA4853D02B9A849FFD65684C368E68C6CEDCD
85BF1F041EBA86E9BDB490CD8CEF298DBA42ED4FAFD561C2CBA47869505575220B8E3390BA7D
411C2BB7B16578A834BB1504CFE2644713BB30F2C76D9DB397F45967B8F146E7C4782B203A97
BE20412D4B2B6D53511525292E48896BC91D3891300E48DB9B7A650DB26FDF8992063729A8FE
4E8C6F786FF4F4BCA2018C2861DE6002A8D4954BD7EC80CEAB7DAE6CD07586E733B1E862DA8B
1D4D2B0381058A810522C303C06AE34D5EA6F05C97B4FDB3FB1DEE799511F2EA9750D53E2A1E
CB6058C9988B55BE1E6F1B682C689C996749691B6057DBCEEF6AB5EFCD604DF7420EB44763FC
30B4812891FB2B67402A24DEC15BA326BC89E6C574597178EC7CC644FBDAB6493E545D89CC86
BDF8826284E8697D2417FBC5630CFFF686E9F8F6C5F7788E975FA9F201FFD1E99B75E69C2395
F2EB3CD74E2E61B44049DF0B65F91195233228490EA9B9380800C1B43905B862770DD378C920
CC3EEA51351DDD3EF6C68302F96DCBE3D740F4A3E359419599817FE10E5EE241B516A7AB852D
01B570CA085D306C75BA899A5BE0F5BD883B1A6EDFA8EA72E5F66878BFE1208151032ADE4804
2F2C7DD0D66220F5EF66F4D3BEA1014EE7327242F8A8D948750934D22B7C36B2CBC01971D5CA
B439BB320D7831FEF3C9785645D9996615DB538084C5072F2D20F6A8909C248AA6D34DEE11C9
1E5C41C931DD5076C9CE87398A58AB06A1AA7A07DDAC01B730957DFA34FCD86188DBCC7C8A94
101F09209E7B123FA9D671222BB65EAB845F7787EBF82A0F59A7EAC3CCD936F54A048AA9E36C
983FA1376E1F825FE112D4FAC62BCE3DCB285C5138215EEADC3FF9504496AEB0C443DC9EB28C
1C3F27BD1C449FB7ECC661697186F9C31CCB922F2B9C9CD4AFD63BA3CD71A95A52CCCD50C9C9
BE17A47D3123DB4898A75275D93D74EADFE72B7BE3679FDD9DAD4C885196194DBA0D297F8033
1B1471EF61A839DFB26FFF95487496B4280D02CBD88C1DFABB04F98207ACB5E5AD8B4D4D26FC
232FE653E9B30BD50930833E2B9D72A7A3C57C9744A0992131CF0AE770788FC6376FB187EB6F
1605CAD55B40D0B9132B1799170BA18EBB01A6B92D5CE2580E5D5BC15B14113CC32643C74805
17AC33E95FA1B318328613709D3B05296982772B4784B762103E906EABC30A8C542598B970BE
13D8F79EC2D4229118B8A71E708F049B728205008B75CC96661B1F19CB27320E6231644CABB8
E8A3C07ADD08A88F5BD1448FAECE9C2E9E959FF42AB856C9F0C45B170D4BD63743867FF08D0B
C568D473801E2B40F9E99DA8DF577732784B52FAAD05893033ED069CC2996540E9BAE9916E13
9276031E66E1ED34CAC0228B8C7B8E0E0A8C9CBDEDFB20E406D5C2698733F1912BE83FC517C9
268D3287C66D5059D84F52604387E0684850DA394D1F2B4BBFBFDECD45BF88738074512A1905
70057E2275BA2803036A91F9A32E64CD7429AAAE7DD6D28C3159694901450896D483717E9ECC
4820349ED3E5FDEA88B1F9AE1A7E9A9090DADB0DEC035EA6EA90399F3A942E3401EBE5B483CF
0779ECA7685E8D278CDF6EA2FBD2A7CBF18314F5257756CD3E342479E3AB75A6DFD4F9D7C3B3
5AE5042A2B7FD3CF5C93ACBC3167BDC9A7F0D25D0CEC8F73D79A98EE89A769E5A41AAFE97D55
688F39C661B575A6601ADB6399B43DC5064D54F07E8299627A114254B11F1E8DDD1E7783CC7C
ADB44A96E8E54CB72A448CD387FACC2BE66A5D9A4583EA6B1C0E4E7685739E22F50E52488EE8
D38903E9BDF9CED151FFBAB79C1E159A06C11C70D91E114ADD520627460CAF3E57F77063FCAD
E73F05C563FB50CBF0F2913B6899926A6BFD891E986FC06001C9D8073A781F0981FE9D4C4D17
E49D1793608913238CBE6B973F9493DF8C7123702646446944399EE25B1E5A40D3AE74728879
203E2D5F005C3955382FA450B86A58C68BDAD3FE1793D8E184CE250070CC6F8C21E277DD506D
4C8064374CDB89D4C5EF1859FF45BCA98BB91FFF5E52BC1458991E9C296CE2F8BE62B7A34D2A
DE95004D86ABB1925B24296C39130971B68A2B1228EBA1575447FEFF25F6D887EF14B66FEB4A
377F60681A4B44F63B6A067E367E379628CD7342D80B79913F4797FEA6506A56D47DDD7E0AE0
B06D1E9D52359EC8D1FFF0502D3D7898ED4642974DA2483F6D5F4F48FBA2862B9684DAD5F1FE
7434786F28446523FA121E0445942EA29694E03F2CE367B6EF118288033B36F87CD456F566A4
767D31794A827595EA4E03E805A5D0255463FFA40893B34EE0107FBC6CC1D25215A70FE0F9B5
526E65C3E50376D9555BCC9F60BDD3DDBAFAECEFE4659ABCE230EFCC3BF8BD7F7AC3F5CFEE3E
AD7E09C9F2027DD12F7D85837C9A693A330281D730982A1A2B854D5BB19879DC69A0FDD1033A
7A858BF14C949B17D26B491B123F3DC89E67100412DD9DC767EC66FB690EA83850B80DCFAE83
EB437F5A5F4D22517DA8A21075D6A0CB1FCA94446C8138FE3F28B8BDBEEB3DCD67E4D6C9AB24
9F3BCAABF7EFFCF8162C37F3DDB6DBEA59D74D515BF19507880F19F99EC7AF622FD9ACE7BC07
5D853517B494438AD1B7BA2F0C696E77543EA59F951D5B8C2D364DA095F4B174C878FAB8CE90
B0312FC2D3C62B4A9F02166FA0EABC1FDFA7839A250BF3627D3AD5ADD5BDBCF75B271157E012
F723A51A76ECCACCCD693F81590D99FFF80B21C7FEBAAFB921C0A91AE44E8C3A870FDB69B2E7
7A65D13626A3113B069A1382AEA90C6076D4D4B553153B3CE24D1382117307E0D1195E39AB80
58E44DDB927058A8D71AE41B86ADD4692AF0E852F0C1C92A6B5CD4E7C49C7774BCE30E0F5256
4437E6553B1E6486FE7F8DC97451C934C3939EB137A8EC09486F10F2A7FC4BD3ACFF77F03B1D
92F19A015FF6F515E9963C870DB70977F9B697E07CEB75B9AE87B03FD70CE2008B941924DEF6
27DE71F750EF0F378CB2648EA07174E62FCA3FCBD6C6F1F91C9BA4EAB493E28751FBC57D6897
8F553DBD6759FA9CCA70AE9A7372A70CC6CE35137CBE4C289575555D92083E92DAA3845FB214
DAC0FDCB355A5C08A1F3647C85E3B747F1FEA12CF8AA1D2162E03221BDCDFDCAF4B74DC3ECE1
657CD9819BC34ECA91FE1E7987FD75D3E434307B208F2077457E99134E108E38B99B6D1D8DBB
530D3AC7CC5811A7FA92BB080D8E2A3A09CF3F6452941D063D275E2AC849E0B35B39C63551C1
90A43F3C3564AD6F153C44F67E6D50E311ED225861B94CD108D278A4785632CF7E47E89C8FF4
3114044CA9D48BC15C5EB1E9D1DD3965B84A20522340F81FD0EA60D7B763BDE818B5F9522634
7A5220F043B89DBC6A41DF825DDBBBB05736F7709B752B42A1FC78B1DC61EF6DFDE867C1EBBE
0E7F332C0BDCF86B706C2089EFCB1896B62ADBACD8E2358C75060046A54784A41F66B5DDE678
06625477FCA24396747DB263092F82314E7440FEA9CE8630FCC10D7F4BA6821613F64A16D00E
4BD9BCBB0EBF087C2A88720504CAC249D2B2E67A823C4F34260A7672E8D6E7AD168806779B39
ED0847E82037AF28416AD3B5C5C6823ED9D1912A6B45874E5C67B258DACDDF6BACF5D735899E
A6C62DE3BCF40145859A58C0D744588D070AB252A26E87FBBF2CE51E95E5AF46AF3EEDEB147F
75EA1F698B2D3F582B76381780E2BA8F6F2AA75A0DF480A0B5BCE7C3EF61755A4D9BFD0E9AC8
5CF716407021CC32CB84C16A90C37E83EB5F0D6B7BEB221FDCE3F9A6701F6BA690748F767AAC
D6F886F1B2A54037AE8D8B8546E9DD0ED71C2E03B1148BC4763F95CE2A92F2E29E3820F8BC5E
610200FBCA96221AC7CE0E8DE251618EBA754542FB8EDE1632D48C0D20E882F915BE1F742ECA
7FFEE8F323B05EACF81846F87CF833E6FD877E01172686BF92B875FC6977B3D524E8D8BF0215
C3D72182BF368C7F89506B058A2A6042CF86D8DE16BB8210321B5CB1CF42CC5DD52E29D82D9E
84C957E52BAE129068A6417FAC32427F8C1AF08E2CB44F7CBF3E8B1451DEB7B2CBC772227117
736D41FF4A6772569A4B2C2C48908A1E36FE12D950521F269A0DCC4449DB961E101D3203E88F
7910663B7C672EB85F26562A35A26871947B14D69F7E09153F1CC980F0663644C9EBE030EA87
1399577ECE5CFFD2B7490AC8CBC565359683207E92D072854E094E718CE9D4DF1117A46C223A
5F095DFF3C1721B52502F7366170444898620985ADD2CD198B292433C88ACF33C022AC15E910
E56EB3B821341BF3ADC6FBCF1CB7BA72A2318D1C6D36810768674C325CEC8B2F86E19A0CEB06
64AEC6E1F57BA2952DE44C1DC85FA8AFBA808459222C7608842D4DADE3C8D21210F366BCC222
BA7BA907328AF3304F9AE2A542FE84DCE9B4B3E13C23E687BC3360E578F660F31F948694ECB1
766365C13BEABAC7B589D2ECBA799491735B417532E392D56C9DE2B503C2A49CADA4280C863E
D36CDF747D1BADF31AA0F4C6AB910BFB708F2B3D763C041836C9C4792C8CCCF39519F3B80BB2
0C7767314CFE03C5BE8FC81AEDF28ADA7C576135618BCE77ED1ED0ED1F8804D4DAFC126B4E94
83E61917775578AEBC58EE5823CCE006610FF2108E5EC5E9F6EE0B7B09BCD064A2EFCDF71CAB
DBA10D0FE3DF95A68F85965CF756B19A9664A167263B2751A9B7CA9CD76905A9A16D070912C5
FD49959C93601DE4998FD65F6B506B9F54A16C92BB88C6CA8751CEFE60731952B2B9550251D0
612901121CCA0D3A8A51D7F1F5D9C771EB86BDCE40ACC8F35831C9E5ED6F5D5332275D01748F
88428E97DDD24A036CF030A8D04E3EEB7E86E6B6E6F01BBA6ECDA8B4806DB2DB9D053CA1299F
5C6D43A64ADE6A7A6F19AC608CEC86FD93407D6BD802EA487D7C46E5190B6B34266184235859
250E09C49583F8B856EC06E4C120A0E12E4E305540AC662E171DFE00F687EECB571D2DE79473
E7D22FE4BDB30B9A526F8D68B4129D71FB1620CB3182FAE6B55625F9C2664AAA3FFBF9B799E2
FC92EE7A19C5E37F0EF4B3A6A902CBED35E34E86D9B7E5E41E5ECAE9876A83B2F2BFB7038EA9
0A232AF9F300BFB6A45F55D73BCC6B9E5852395D5CD5C77819C568741A7FDBA3A2FFC81FB1B1
EA0D4D9B450199617FFA0BA8CE26FEAA16F62CBD663798FBB3CD164D6EE6E4F505067C0EC75C
1C5F81C699DF4165633E0708F8CD2BE2280350C902890FADE818E5B31A6FDB45F7A6F8E5F924
B4D670B9E3D4EFE00D2B04D6F433753454B3D3EFA16276577DE3F28D146907CB6C05570A6D4E
DC284093A4B2588162BE6BC867A00CA1A9254234766503FCD3A0E29D9C5676EEABBB3E26FF09
1E21CA21FEB29365A56B6960E1E76796C097D80454261FB63D5F941B66D9DEDFF932793F1569
75004F36E2D91D2203049E5D9DE711D832E78CFA18E2B5348B74AA8605E6425D8099C6B10EF3
E4A299FB76F028BDCAF8ADEA2E908E3535BBA4B42A905F30D13129209DF390139E3C548087BB
BB46621E71CDE60F450A8C61B247CEBEF47B5F311B3CDC843790CA79DD6C72AE76A679AF24D3
6D0B1B5388485F880096057CB6287845EE438CE1E6404C5BE7371EB6C060092ACC76AE336835
1D481984240E51E33061F1D9FCE34A4C65C441F5B4E4D0781103AE0B0CF637CA2FF26182B855
B696605FE114AB2F7DE5F016E396B5A4FEC79F05ED451EB3EA7CF718936E0CFD2F9CE7781162
825FD98BE70C3B16123F8D9B0C970DCB545A7CF6A8CA6B4FCAA319C6C4256B10D6D7AAD98931
40122431F2B0068C10D0398F55FB91DAF2C624A716726513EAADC369BB29FBD1B2B7DC5324D4
08B0B02E46ACCA565D1413D1F65F545603B06E28637C326053DDD2B78DA99BF320DA2A565258
CC9F548B2F87511C628610AA00A6C8F5CC5BA2CCB13BB9EC7F123EA7FC49EFBEAF5D7244EACA
D013A08D3FE370767128687A488302AD3D95067AF108B76886ED16B59E7345DFD143A24CBD75
E828AE300CA7D24437D4A5F0038DD5265D82CBF39A4F8F542D491486F5BC3566931665909986
41510AC914312D22803F242311DFBA932BBBCA9DF24B56EB52209A5A9CC8AF2688B59F348E7B
8FB08281143B2C849BDA4FBDE9D8819E97589EC110FA9F31FF85D07B6D58D58CE5DAC7F22D0F
97468FC790D913622007DC8045E2D05DCCAF592A540870FB4EBBCE3B5AB9818D49B4E40FC919
FB8FD87617733360FCE02FDBA5E57B33461D5E085569129B5B7B657DB36D29E3F87E17E9C7B3
8F6F1FEFD369D314E329440BD0AC26697B34D4E87048EC54F7C381E66C908A658BA83A811285
E93E32BBC6C641BF0F2412C276B85CB18FED61F22ACA7FFDBD37B994314CE4B711B82402DD26
632B7DC376AFD3C4D66BE5E40E282B74FB120F6E4E144D90404C7A4513F2AB180E00FD410AB9
C10CE9B1C2A8EE695E4CEB0F1472A959E70899B1A07DCCB20546431FE6B541A05291D5DDA490
991BD3560490CAC148A2D623903B630DE49F10DDA865A74AF0866C2FCC595F6FD0A0CDC0A146
5398818C46554C37A4CB1E543C4760E804B39564BB853400D0E1E9DAAC58D0577AE177726D1B
9075BBC70B2AECC2F7F44D34F4C691485BBAE03E43E8BC5535CCDFB1CAD1D66F38A49001C4CE
CBD71202FCC47BBD3B224812C677F4F9E4FD523D44EFCFB05A57E45AE2078E3E16DC785125D9
55D3B941F4FD72FF547B069EAB30BFD33E3EFF0686FC7E582CF73EEF9866D6E62C19AA005F73
4CD8FCC0A012F41F38107E135CE4C0AD8A8B81101FE4EF8F32065B2C279A435CF5A032DDCD52
9628509FB6773B475DC13517625705B5D3A9D9EF6995A37DD3F0D6CE5451845CF9151C40F990
60ED58E0F2CF5D6DD71944731CC4ED0FC72641E287E295CBB53AEEFC3FF3EC0A5DBAB8C3AD31
E5F6B339C1748A9E58851F6CDD6BF091227B2835761B7D9A10DF0242A7B61B39AEC0A0697F43
794FBD2A51A66F860FEA136A9D7DD82B42B61710909104E0FABABE3F5485CF1474D494B97508
DFF80A698BFA58ECB590D8C38873724BFBA60FB1150B04282AC1022A1214E9513D27C5D45DFB
C47631BB27CFA2806C2CBB130DDA940B65E75F956846F4E6438773C94E8EAED71EBA5E87A886
DA7A846EE29A43CFC2D130A3FEB4762091B6AC357C973487573A230DFF74A29E203BD78B89E1
729B747FF9B58BF1FE5FAE6DD70E9DA091A330078845363681AC2BA501286DDA2038A0FE2235
C10656143783D50129A728B4EC2C64405B7C97AE562AFA240D35FD9E3A6E034683C60F32AC09
968A76C775D5547D85D7A3168D6F19F12FE132DEEF497E90951A56CB17E543A76F8A526B1B7C
481CEEA4F5FFC637DA5CE954A742BF39837F08DFD7156A4F4E4805494C1957B2577ADACC0D3B
F9B0EFFA5860F454EC947625E70D7E4E652ACF276F57F2137F451540ADC35D501CFC1F7597A1
502A198EA502D67E7886790A84DD9D225E83D9ECAA18FF9EFFA77AAC3AE57D034E67CBA014C5
FE1E3403AE4277D864856FEFADD2EDDB1161E8595DB1B2CA6CCADC4253B95300ACEFFBF9C3B3
32E1FFD71B91898CD0EF1B9F64C3969FFBA7929BAFBDCCCB943373EFDBA057003069C4ACCBBD
82DF6ED1624FB8D0D4B3E561A05B13550A7EEE9AB35E47E9A96FE49EC2716AA68224E3A65AE1
E96D530FEE45054DDDCF949E7F3977334E3A9AE459085F366393D232B2CAA244B029F2BC602D
05B421E14C08563C4296D3E9AD328DC324EA5685E2FED03DFA3D3AFF2482EBB368484FF8D015
53CB8D5686067F99C5617FA2A7F6F183F4BEA8C1AC39AF726341501AC8875104D11DBF241B9D
C9929A8B70ED71BD62AFAB7981E452086163DA2DE543E52D57AFD080AFE373E8E321670F8A47
4E9DFF36441F6C1A4D2AC6DA6E5C9FFC0C4EC9CDD8614C2D65D55019378D678CF46F483FA9EA
0152D9D3A12175774B56B11BE03362D2A36BA13945979C64163A696B0A6CC760BB6111EC47D0
A5260DFA7FD147FF35AB84DA889DCF4BA4146647D5BF8773096FAD1EC8001A6085C4F4721428
F4D4B85F1C03C71576F497D3A5A99392C647DD42F8804DA5D33CCDCE19DF1A16C143C449F1F9
37F6F75B05ABD0CE90E4EF696E1BCEFCD950634E414DC724B0084BCB515CD4ACD71A6CD3784A
402C3CF3ADAAFFB763C5F7E17BBBE19172E4455923BA48869B4D9D0C1EAA623D9C728D887C15
BB8377AC74239EFEF6389EA10C7C8820AAF857BF8EF2B64EAACF096B742ADB9B666D96715364
CF18D88AD8DA6A0CD303557F04908CD28D11ACB9A730AA3A37B6028914674816E6AC076C4559
A84880E82D433A5F5722531B0287F11B24AB4CECC2264BAB4E6601C990E32E1C5F9AEA52CA22
2D2698507A4B235531C3FB7E9FDF6FDA186888A74B902A0EF3457537233376E8667035C092CC
C3797AD2FDFE1CC8BD71C49B91E4520091922CE87856F1DC60A209A9BC9D97B0141D8820E1F3
B86BFF25CD1BA07E5664D32C09CDAF569EC7815F41E0E8731E2FCE769BAFB3A751B3EB7082C4
992A4FD8BA363D0888FF39FF986B80D5568CDFE1DEEFF98CC54F05B842694BE023E0E0507DE4
7AC1B53BE427D31E0DC9CD5963BC3A5183C54D8C9046068BD6F300F4C0CDB8CB779E6828271D
BB9EE44B70BDD1C1B5A345AF01E5E9A74260781AA473199CEFB232EE9C60D14DA8C5D3D22291
A33E592BB7FBE5E9B28F18EF70DD0877DBEB43EBCD12F9AC95B7D46A2E0DC88E3B7D34C6FB32
1593E7FD7C070D44037B2EB5C5E7F40C2BFA3A282D85932C19D3C3D07F5BD37C5CAB34816E9B
008BB5988A1703DD971AC36A0F1C61DE0828A6108A1454A17E63F68FC5604101184FAF38061C
515C0439010551A933CE9701EA75A59D88310C564CA3C4D9BAB34668C6ADA1792C550D08B029
5E6A2AC490B06A3BA9118ACA61A951BDC06EB5EA612992BAD973AD703F5B25D1007F47CD92E7
4D824140CE1A827616DF813898FBFE32C87E692FD324FE78FE9101B1789C8C094207BF77C290
16ECC3734E103ADE9FC7717ED2E6979BE347F72A514B943A7F1101ED25B0AFDCD6C8374182ED
E624911F458A5EA76FA982C3CEDA0195275DD50BE2AB3FA62F5545F802CE3784159E281A810B
87DACB95D4D75AE2EED997DAD39BA7346083A046660F0D63D4416EC1AFBCDBFE18966B4C4C10
9D5C9E9DD7B1202D6AA73AFAFBC169E752DB200656FA28A29A9AEBFA1D4EAED03478778AFE82
E0AA2DB79ED37AF8C5B940ECC6A5FBF38762505235415B285C72DA21F4FF986376E407C04843
24B3A2ACFC6D796FF53B5412A1A73DBDAD921F402308041C18C5D7FD9705959A8C0F5EEA851B
5AB726748A6F0BAE196F879A3A1A5A87F7FC723B7A6E85189914EA451E2BE92B908AFCD4BE5D
3D2C6C1C40984D10483A9F85648CA31977A4CD0F9781CEA0EBFB97B8B07DA6FE5694C32F0B5D
23D58CB259E54C46DDABEAEC138EC1C5922337B8CB2741341E3DE7D141E7316B2F0DC75C1A62
ECD7106141548C31F7B90C0F70106E4E788FCE549DACF492225530F427A6BDFF5ACBAE8913C0
BBD9E3DEA41EE41FC7C13796A4A7D32AA56305F2420AA9BA5C0A0425861F97FC2B0D586678B9
5F28A395FC340E5CB4D0DE633E406347BB83E56126872B389CBD57C359807E3AE6CE23C5F1EF
746BE92625E161BAC1584CB79940DB009844EA870326A7BB6CC8FE67084726E36EACCDD1A5E1
87D49E1CAD01037E58EEA820171B29968A2E4A08352959052EF9CA920E736C7337D85A44A3DB
0DA96FB9BFC14177AFE17AAA27B79E1C92B4D53F4CB9C277BAB838C640EFAF3EF4D95CF7BC61
4F3EECEED6A657E1FB361302500E5DEA28E5B5EE4F3886C23F670090FCA5D2EBA7A5E4B3ED0F
AEEA8A7E6DC041F9988D43F645BB388FBE848EE495B391FBA4C0C3939F3B5B3203A5527F397E
D758BEE1E0F0FFE9A379DE0FD8CA3DB83B767C3BAA6214BE3FB012708F1327E1C96B8FE26597
A0B8403DE77750565067F42F1587B5EEB69D5024A807E98A3BEAF5FE5F88DECEF57F2FAD58E5
20D282ADEBD2051F086B3B871F0839C71379E6A0F800C7022978C84EF6363B7A79B10386E38E
8C7DDF0606ED85B780145FA4428DA212AE5386205BA129AD33D28BCC36A0B6CDEE13C37A6C2B
7456F0C3402FD5B3E3DCE43B479EF0F81DC571FD102BE21029C721E4148729755F19CFF14B1E
0E30CEFCC09D175AF0811BE99498F4A8632B85879AF0E005495FEF5548F2A1F8C989140726D5
4BA1FB448E54549A2434A1FBD152E7DF166EA70953C6595CF824CC77984DCB8F8807B7347131
CB727A589B651697C32E0D52BFC2B36B4C050CF9A1CE072746992EA2ED9B052DE1B2B9A21A89
682B2BE4A1328C769DBC40BD71202D0287D1F8B909AD0E95E5D80BF8314B457A042F304CA330
14D4578D50158EECDE6821D1B672B1973393FCFCD432EEB0EB4FB362DCD9B4B280EB5EE2091F
A3853D779EDAC21A120FA7E03B339CED20115F404C3A086EED187281EC31F25A664811E2B712
351528C4F0ABCE55D29BDBC1E067C01CB44F8A3E094F104097C5A36DCD1CC621E32747176643
18D99F5F5D1EA11959CC751FF9F3739F735A12612629BD3346A840DADF0A61567D880597EDC2
2C70DD8EE5DA9171AE46A8D1D78A64DD2E0F01042CA59FF7F83EC74E1CC0E786DC17A112A062
7640B89D5F3EA4A57DAA15E9965A81021CF737E0108267C404ABED66D9CFFA22E05C351194A4
1913A0D12931F26477A06773829D8AEFB25184755DA27F5DF42B23F493D024CF38C544257830
1EE65AE593127DE8B9E0F19287015892DD881BBF034DF3C789470B567B7AE5130E821870E504
F893CF1844FE400752C5CA00371433A36DE4C96938F6B7FC81D26DEDCBB7AD4F2519857A81D4
F06F6A23A74825477C912968FC03B13DE8517BE24831C0E223A601AD7834A3CE0C7059822D1B
663094AA1D7DE8C524D1E0E5558C664655454A3AA0A5034B50429C5A2AF0C3C862C6D63C415D
92B2B720CEFCEA0D0C6CDEB5CD89EB701CB49CD568E39059E7B7DA7A85B44213F1060598CAA5
8D8830DF46C628B18F908DE0C7360B9175F698FF66C5E4EECBCC0010F43C251001F06C45AAA3
174C8841237E204AD5D7E1C403DFC40F9FD5F469C65625EBA0BC5DF2344228399846C285D9A9
6E21EEBCD9EA38F25584C5D4B7893E64AF5261656E3FFA0CB1FC10CB512328E87AE3C83CA38E
9CCF96AED112B93EF8E4D5CE7BF47E8A800E00C4A0AB624DC3C03089BD5C415E8BA33DB289F0
8E151E5E45865E9CE2EE9E160CF3646726DD25D5EABC96B72A7D2C89178FB92F0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginFont: CMTT10
%!PS-AdobeFont-1.1: CMTT10 1.00B
%%CreationDate: 1992 Apr 26 10:42:42
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.00B) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMTT10) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle 0 def
/isFixedPitch true def
end readonly def
/FontName /CMTT10 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /Gamma put
dup 162 /Delta put
dup 163 /Theta put
dup 164 /Lambda put
dup 165 /Xi put
dup 166 /Pi put
dup 167 /Sigma put
dup 168 /Upsilon put
dup 169 /Phi put
dup 170 /Psi put
dup 173 /Omega put
dup 174 /arrowup put
dup 175 /arrowdown put
dup 176 /quotesingle put
dup 177 /exclamdown put
dup 178 /questiondown put
dup 179 /dotlessi put
dup 180 /dotlessj put
dup 181 /grave put
dup 182 /acute put
dup 183 /caron put
dup 184 /breve put
dup 185 /macron put
dup 186 /ring put
dup 187 /cedilla put
dup 188 /germandbls put
dup 189 /ae put
dup 190 /oe put
dup 191 /oslash put
dup 192 /AE put
dup 193 /OE put
dup 194 /Oslash put
dup 195 /visiblespace put
dup 196 /dieresis put
dup 0 /Gamma put
dup 1 /Delta put
dup 2 /Theta put
dup 3 /Lambda put
dup 4 /Xi put
dup 5 /Pi put
dup 6 /Sigma put
dup 7 /Upsilon put
dup 8 /Phi put
dup 9 /Psi put
dup 10 /Omega put
dup 11 /arrowup put
dup 12 /arrowdown put
dup 13 /quotesingle put
dup 14 /exclamdown put
dup 15 /questiondown put
dup 16 /dotlessi put
dup 17 /dotlessj put
dup 18 /grave put
dup 19 /acute put
dup 20 /caron put
dup 21 /breve put
dup 22 /macron put
dup 23 /ring put
dup 24 /cedilla put
dup 25 /germandbls put
dup 26 /ae put
dup 27 /oe put
dup 28 /oslash put
dup 29 /AE put
dup 30 /OE put
dup 31 /Oslash put
dup 32 /visiblespace put
dup 33 /exclam put
dup 34 /quotedbl put
dup 35 /numbersign put
dup 36 /dollar put
dup 37 /percent put
dup 38 /ampersand put
dup 39 /quoteright put
dup 40 /parenleft put
dup 41 /parenright put
dup 42 /asterisk put
dup 43 /plus put
dup 44 /comma put
dup 45 /hyphen put
dup 46 /period put
dup 47 /slash put
dup 48 /zero put
dup 49 /one put
dup 50 /two put
dup 51 /three put
dup 52 /four put
dup 53 /five put
dup 54 /six put
dup 55 /seven put
dup 56 /eight put
dup 57 /nine put
dup 58 /colon put
dup 59 /semicolon put
dup 60 /less put
dup 61 /equal put
dup 62 /greater put
dup 63 /question put
dup 64 /at put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /bracketleft put
dup 92 /backslash put
dup 93 /bracketright put
dup 94 /asciicircum put
dup 95 /underscore put
dup 96 /quoteleft put
dup 97 /a put
dup 98 /b put
dup 99 /c put
dup 100 /d put
dup 101 /e put
dup 102 /f put
dup 103 /g put
dup 104 /h put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 108 /l put
dup 109 /m put
dup 110 /n put
dup 111 /o put
dup 112 /p put
dup 113 /q put
dup 114 /r put
dup 115 /s put
dup 116 /t put
dup 117 /u put
dup 118 /v put
dup 119 /w put
dup 120 /x put
dup 121 /y put
dup 122 /z put
dup 123 /braceleft put
dup 124 /bar put
dup 125 /braceright put
dup 126 /asciitilde put
dup 127 /dieresis put
dup 128 /visiblespace put
dup 160 /space put
readonly def
/FontBBox{-4 -235 731 800}readonly def
/UniqueID 5000832 def
currentdict end
currentfile eexec
8053514D28EC28DA1630165FAB262882D3FCA78881823C5537FE6C3DDA8EE5B897E17CB027F5
C73FDBB56B0A7C25FC3512B55FE8F3ACFBFFCC7F4A382D8299CC8FD37D3CEA49DABDCA92847A
F0560B404EF71134B0F3D99934FC9D0B4E602011B9CFB856C23F958F3C5A2FBE0EF8587D1F57
74879C324E51FCB22888B74F241550D7401EB990D4F3A7AF635198422283CAC1B6CD446DDBCB
D915DB9BFF88844E784C6BF7389803D9450B0C21756A017306462C563D51ECEFAACD079732F1
2C29315E4B9623A5752C6F1D8145869E120D910B2644887CEA7E30B15676A92537C29D3AA80D
C30082ABA94B40990B82FB1A877E805E0C8C48F61E9F2EDAC05B944EE4D8084EC1D5CC517AAE
EC5B3EA379DD011EEB454CECAB3AD2443C887C58278972355673E503AFFE0394FC7DB31DE364
E4F56C24033C7DF2265C56445EC63A1D5695A6041EA1B94407E1CDB7C5635603A4FD047E6EDC
AEB2D0DA6C9E0E9396D51A4A58E8FDC1578730F992435560A6E2D3E3687703EE2F78F5896389
AC8470BC806169EB01762E89B6DC9ADF857EAD656620E2589AAE722C37A2ED7A2941C360B067
EE34D8D5CA3BF68DB725614D936BCB207781F4D4EC2AC67B13A5AD161F3F059ADD7B5E3D9048
31E31C20C04546FAE83CA93A35989E65C201756888F727B97E5313C9870EC96E4CEC3901EA03
A5C744754485E7D169BBC98BF872D0796E189D43B712950C3786257D8BE06AB6080B9D939231
3298327549A8A41C00A2CEA3690B4A333E45AA815A64FACAE1C2B44640860B8B8687AFBEFDBD
5B4A541A72514EE7D3E0752AF3E96A88C95D31FA16D34BA2F02FDB0088B165844F02611C734A
DBCC2037BF741FDEA7E8BCDC130C70C33772F777D8BCDDF4611DB99001CCFF14D7AF2BB05DEF
C3480BDAB312A0EFF2F375AFB4E0DF2F803C594B7C93F71CA4AF861AE1711932FEF19BFE2F9B
7ADB69D68E5A70EA4D1A3D5BD85231B16993F65EFB37A0A823F0542F8C2340A073DC1BE4A834
7F9D3068A6435CD8278B0DB1809E8AF9664C2C989B9F16873C009449B6284B85DA4DEE11C96A
05BA83292F0EDBD92CF674AAD6AC1A5FF966FFC37E88A66048DEED053565B55EF6BDB8C2F2F6
7832F8939A32442EA54F13D003494D6350A2864B427A9126A9C26A031909FE53FA8463B80C3F
FD536C9A5DD29CEB03148DBC24C0033AEE72DDD159F2E8A6FC113F428070EB36CE5A38A72ED5
BD94D81AB4DAF08EBD42C8E5BC695622E02AECD4004E6D4CFE72534CA56291FF5F2F83361BCD
B9489A993F663289B6DD492499DD5713227210F89370928ADA0085E2AF277F53E4CEC34D6C4B
8CD5F2E016052A04C20AAECE8B81AF9E9F33643C0FA69A5BA864D2A173221071A965F9970D72
93DCDE8C3FF60A86A4D3706850CBC45440DCD22F307261E2F6FAA3EE156A58069DF979C9B5EA
A326C5A36B6E0FC0333D7B4046D636461CA2EF70648C37A953F96FAED6266EC9022753EBC390
BE93C0CCB7C318C4314D9F6E54274C8046A8C5CC7EEBE625BF59A03F5405733ED120841560CB
93210EA1EAAF3402ADCF1FAB986521BDB7CBA72A2353942FBEA4A0D1B67ECDE589A65AF8E7A5
FA4B87672AD55F57D783C66DE1D11E0A16BCF32530692380C730D12834777AC6750F85131D77
B0F53B626635CAD3BB8E9F0454FA085CBCCB0339034F5FB2E225E62CE12E8C792F5B7E234688
D2AA8F627A4670339E646399F91E94424263E5C12F9F3D411FA44449611EA9785A20FBA733FF
2A7892D1641F836CD42C58CCB81E41D6E2A5AE30FA18DE9846AD981923604C799B16A99779FC
CBA11044740BBCC78116E857B4B390DE0E66921376101D621E1FA003F01AE344FEA0215F2577
E9C92C6AD07F2F4674A00FE42AC51FE5A9186C3C1956B535FF1DD64BA514534DDD73C0C61C54
FBD6FAC3B4FD9010FC55DF2A37A111BD1402D4E90FD8B3601DD3E9FE25634D709C289E524A66
DFC33CDA640D397269BD9ECB9D0EE84A7D7B93A97DC522A16B6965B7D5D7790A3002341ECB3E
80985371A5169B38133B13FC5C1DEBE2D90C43BA5D2CEC7D3B972D32AA1A932B750D6CC83439
73FBB9972D84670AC5CAC5D0B5E75CE021F99493CE29AE90BCA0CB75058BB0A47DFAE6C8D075
043BFD738991C2A0B80BE18386D7A6FAF89FEBC4AD142A1B0EEA8884EBFA87817E22C222170C
B6D04BC6DDB541284E16400028EEA275244B69B033D200AD997BE7D1DEBE13CF783BE1137278
24006CE4B5E3F34D09FAB236749D3E72C033997A652982829376DF91ABF533F0100BF224C279
D3515176DFD56C325B3D7A3EFE0BEFF84233B5A7EE262557F84D754F03817C900945DBD5DC59
B46BE8847D1FBEDD70799DC42D0148841DE2F816F894ADD5EB2C0E1BF19F52558AF84DE5B693
86020DF814DE7647FD41127459D65798B06EC5D132AC0F181BE211624E97F8096C0A22E6B216
0878909D00A918E90B435C8C87D1033E40B56B4F15752D5A8AC019837604DB9E1AF709A2EA36
4F174DC2EB1957F0E5F477CE06A0EB78026BD1B23D76102C6862156C47040EC259FF4E89F83A
42D8DFE53F96127C8AB4037EFEF724ED011928C2CEECB4A8A4B5A480595A2AAF93228EE37205
2428BCCCB4685246BF3E9FFDB2845CA05DFD4902E74483626C2FEBB4E76C78B2AD6A96372D0E
AE47FDF4B8D1F068FF0D1EED01C6860C86275A2EE3C2A97AA6033AAAC489E1A540432BF92A75
7205428AEE30CCD48DC234C521003D7EF7B88BDA8E72A12AD36C2BEAB1177CA82BB2458997A4
B5094A9DABAAE0A83D7ACF4F7727223303D5D8ACB9B265B3326CFB1AAC4BDB80B28E828DA936
BCA574722A73B05D447C9F7E506D78B33F582B3BBEA37BF8380CDD32B15E74ACFEA5BD635C2D
FC3A6090E7D96DB7E9127A3660024258A3A7DA06D08C4691B19F88D0BC719B1414E953B26F09
6A0379BD71ADCE16DA6EB552A50EC318456CFDE8FBED1DD92200A9EBE83849AE3FDE58B5400E
0C173E01F5E23E883119421C7BF5F12ACAE87B3C3DF0D824A67A320273D41607306B14A63D46
2C042A6C6A31B92D54E01D7AFEE232DDAC002D012B950A71C2F065BD478196779544093A5B61
93247AAD7970AB5E306EDBDC24EB4C6B71A174ADC6565A99EBD7EC83E01ECEA533D364C2F07D
8A48C84C0A3941DD6B75422FCB49AE7BB79245CFE9ADC2C9B3E6B48A46867CC72F26D8C82C2B
F5E8F60763CB9B473473F521FB016CD1D07B3216C496CDC68F72C6E9AC5B8193CB3E20EA84C5
A7CAE4905261B554D6BA006C787658463215646AE218972219EB34A5964F0A277A1D1A20CBBC
94FBE359573A672EFD0019B2C0A6A02F4B15D14B961383630F0CC578168F9DF7D33D3509CE75
D272141AC8EAD6C708227A193A5542A213E6435AB543754A75D066C000A1FA060053A862A013
799F762B5403BEF0E52C8208D3E690393BD3FF71C8EAA08C49C77F33BFD9A6F9370A88CDC3E5
B1012FB13C784E637A4891503B5FFB4A0BEB105458413D3FC880B92671E786BFD03F158429E1
E80EE252159C6B61079092C2035748A3C0D1B7C400B88666F94601D53C2EB3308AA791F66E40
DB8CD2CD53ABE4A018A2BEFF566806C6CA7108EFE8C70C7E4058853019425AA8EE77D3E75973
1A80FFFB59CDECD15D099E336A63A605DCCCAAD3FC55300B12402FB10A9FA4292D61F8967C21
8E008343617BE44D29AA7DD755609EBEEF555F8291543623BE6CDAD4F46CA20063DDE0EC4F24
B9052D6092BA0FB03EC7277643F178CFDD5314F597B93139183823C2049FA4FE0E1F7913348E
B83F151E13251C3C2ED100CB9C907969669D98C5F349FD064A677FB689671C27B658C3118B20
6AFA9478A4F0AC3E6325139045C83C046D0F81BB002757DE25E9778A4D835E6D61E563293923
CCF415FF132B34BA9ADC441B806151561C59662867F91CDDA7579CB77326D5C34BE9149E9629
8787F98EAE3B5A2E2190D932581F36C547680C3266770786DF978FDFBF96D7DAD68969EFC46F
5A39567D97CCF08BD361FE650629A6CEC31DDF856640E6A2842447A87264503B7917AF46D7D5
14BDCC09B23E7DA51C47816EF27100FA60AE3FBDC320B6E792AF15CCE9412C8C80B3A46F5E31
E380D93EE3D17A5F674684AE28C56381892B66AA5A37B67B6E7CB9D65D359791E8EE0A36A4B6
537315C99505BF6264B6C3BDB62A368AA4C5784409166831B36AC6241C24C9EBEE261196E7C5
B55480CDFADA76C0F979FBFC9F3AB5A53CAC4C6DE0BC8CC9BC93221347EC17FC024CEF796410
67DE49A3460AE6C83464CE27DB329E16605DC22D727F578F14764720F4D6BDC24E171B27EAF1
43EB293A70525452FEE8100DBB2D7ABCC5177C7BA96CD07A8667103312BC495FD7813A5DC7BD
37C1C96B1DDD53841B9DE37C5BE008AD67706045EC1AB4F418F60A17C0786136A5B9617CAEA4
BF319CA20636691BCA83918785CC15FA19B4E8CB5AFFA398DCB868AE139124E6DF8BC1CA29C4
3E4F7D57AD6D625D570B498FD8D2B3FB7080E312D95DBED16A8FD3ADCFAC9FC0EDA131913647
6EA4C0FA1B6EEAC95FFC35326124EB2DDA055EC0FF6A304EF0CBFB3DEA094810A52D5193F041
D99872CC6A71DFE5B46ED2EFC3F45D6560276FDBA056A78F9D76EDA2467AD4C44930558DB88E
ED42F6C88B0C1E3DD5101A6590ECBF56E32BE0BF76B515235D00121CF0ADC12346997AB62DC2
A1FC37DA89CC3992BC1C6D5380D0D5AB94551833B65A2336EBC9923E58CB1E47444BC6E49BE3
042C94624373B1C34F593E7C8E043A6DE75A27DE4E305272EC9996499517F1577DEE3F9ADC0E
3C21B61F81D165E903E1457BF33830E5369CFED65ABC46089647B5C01CD089DDCC7CB8CBBE01
EDD7BF01C3636CE3D274A7C59B937E4547BE0DDB0FE9616E0EBC5078ADF5D7C8984C5DC85FF5
099A00B84E44178D78B293288F664F19C7FFB7C52C04ADCF8718DBC94021C28290E2E5808687
5C2B23EDF938C52CF0274F8150CB577FA02A7BDDD290839B69F6D5AF1B70896ECBC07CA8F1F8
6EA38CFC5F852A5F5249BCF04A878BB56EAB61A1F53B60697DB77FEE8327166B399D413C62B7
42870C3D77544FBF9B63511669E778C3CB1C009D17EAA536B93EEB5D15DF014673A66B43A102
02C424DB51D501610A59B01D5ADDB4A62B7E86688D86A3786B08F14D5BBB93C63C88D7F70D57
4AD84DE70430799DB3C19FC1EBC35D44C8661ECC763B46445AED62F1BB25A6C7D1A7E8C685DD
1ECC9660FE97CE2CDF6D259CF0869BB93F00D98D4BF87969636FB6DDAA09FD32F6F31DA2F1B2
47ADFE919932298D32C8C96FE9DCE6F4A75F071EEA657935F7F30C32353DC4B25819F7070F6B
518C909BE0CEE0FB262EAC59C893DCA6C2B69CB0147206BDD4ECA2C4C8A232FE1B1DDB9C9B7E
EE10FD8A0259364B697AB94D2481FF1751FA9782EB84DD7B481D0FE16D09AA95C00861F081C4
04B638F1086D8C108953B5828960BE46BAC02B635F7E4290EDECDE73860DDB2E987467C70E20
D93CAD40AE9BE998D64B3BD4D600EA6C8E2F5155A9264F9D090567FB7ABE1B4E2E1EC5D4E298
66D289B5647146B7989DBAFEFB7AC0DBEC9DE8D12749113212DA3C5E9CF4224825F9AAA5ABC1
662AE3B3FABD40D17408BBCB0FFAA37EA2C05569ADAE243114BE87B6421590A440036A071E70
B77968A4A6C6AA4FB68D32417DA597F5396A4ACDB74BDB1FDEA82BAD3B998B8399029F0726C8
F83C65AD45D14A1AEBC019F885BA60B0B6A260899BECA00C0F01E1AC25490DD78CF40924901F
E877E66F23C977B8754623D1D0F7ABD00753C3A0D124FC297D647F78380C139C2F82EFA9C9D6
7600079805EA3BBB31C79716E3A4DACB2BB00A21F34220BE2A202FE29265024AAE48C23B0FCF
6142EC6587DA235577B6E57345FCDF32B83F6532023F8A3DDF97B01FBFC8B853E90536165AC9
29DF10E253D8C4569616F297F7E09C06489E67618FD7148E6A89E249C62898E64A03D958EB88
F6E3361F0EF2148BE4576E4D97D320B4CB7F412FEDBAABBFAE057AC533AF9CF9627BBFAED3A6
C6CA676148B005038149259589FE227CBB4B8576810EFACA8EBFB5B52ACD96B373462336D791
9FE2D926C0B23BAFA3024F15EA433414CEA280F1E20650F1EFDD04959A61A5C362C98B855361
F2971287F63D512AF98695C02A5473AC45088D478509C2BA84967AEC0FC1D538654523791773
D8A5B9D73C2EB52FEE2586333FBF6241A829811E06C2CE93EE1F0FA3CE620AD06984347CB30C
2AEC9CDB0F97CE991ADD184ABA3783B556662C833A874E5C38A64B6438CE5348ED802000631D
B9B3B33F0D90941BA80E92D4F00C64E62A7A0520D94E76F782CC734DE498ECFF23A5F24BCAA9
7150F721064114CCA8CD690993A1274A5BD3F15A6D6EE5C237D7823E18661667B593FEFA30EC
07E974AC8C6629A8DCC41F3F02D14F620BD415841709E7296D2E606D040D29D501927F9CEE38
A4FEEC83A2FF45814700D41437C65AE671A5A6E83964EE131D909E56926D3BE03871341FF7FB
BD19437C7A0C3FFE3D6B50479B56D774F8D2EFB59006AF71B47C7BED0DBFA8E8D95CEB3E5B1C
65111377CB66E0817B2AF45607708868976661C469D4C1A3719B90B43FAC9BD8F0FA5558DA8A
158B31D4866017BD8E144C630CB3FB547A0C6035D3D4565536D88D219D98FE96580B651FE0B6
4FF75E13BFB841137459E93A0779616B9F67865F5F72503E60EA30AC387ECB6BBB2039582DBD
891BB344D685BD7B4A44C73B3ACAF4BFD4170B2A529E8181763CF0990EEC3310B321F4D6D5F8
84824ACD20B409B7DAA1186B998DE184C41A1C815F09C5902EFA03BCD1AC9DB7B844353B399C
184088DA2DE7A98D789F1F7B56FD8375ECF32AC7AE6B9645C3EBD42D333061835230C4068720
4AB8AF146DB9E945A631AFA80CD3237A27C6ADA5DF3F1E65DD74289E58048A40AB6374A4F479
13A872042CCA0CF0BC34A30ABB0AB215BB09AA2FEF09CD664AC1F76736CB236AACB271B9783E
1A94EF666A52B5A56A0BC90DB43762B33CECA87E1C8BC43B6B1FC6F0D8D8829A1DDC6A87A8EC
8287A7D9FA52C848A76BF04EB015DC3C79DE6AACDF7316415280AFF2DFD989F8C7887253E6AD
B49D6C78C8350F6764BA14AD14ADE05C76D9BC480B394753468AE029865248C2C760E3BBF647
178F10A294506950073262EAFF3E956E7484636D18F2F4B4AC01F7F3DBA5C647209C29CC0ECB
195764FE2AF2DB0C9086B587EC51A76AF1590D67102AD6BCEBF7B6D845FAE94D6BDF6BD0E910
14DD679F56DA651F747FD08494A136E401A8E23772D3EC931A7524673346AC575756E278AB36
4A1055CC920294D276373C881D8AB49CEC190A4DC921BBEB75A413CBCC503F96B862F1F446F2
CE232E45652292A02349D7856904B46F9606D6AC8446F91B03118E28ECB7DB4BFAA9D79A12ED
57B1F9086541F1D2AD9C55834A5061B1434BDA4F001BB74A3EBC61CE7D8353B6C57A7DAD0FD2
403CB55B1111DB56CA38D2F5BDF3FCB687B08BA9CA70380EF03E837B95CA0C7812EB9D7D0B51
00E052493BCFCC91B26D64B3B95BEA68F7AB187F5BC4B15CD5B2182103FF8C21D7B23FE7E302
69E19619103362EF40128B0E1A0285299853239D28EA3EAE1F32ADCC813FA4C2D2FE80D3124F
4BB2BC57F386DE387454AADAFF1CE4FE5769DB0B7A53B49DAF9E6B501834A117988081D2AF14
56160BDF52CE6E1EEB12FD7B4C8B4C8C71D766C71A99F768B16EF1574583006FBA51963655ED
C565B7306093E356B223DBE43B25162600F4E0254F9D8BF36306ABAE55C77640A63F4F7EB19F
091F533DAEF035E5F7BFEEB59AF6A3DC336D953CDC9B527B1E6CB4E75BC0D6704AB8AFF7C511
35EE9EC739B4DB64B145E42D7CE5C33FA78310654E0E02359BD52B49074CDE8768741ACB2922
4EB52BABE235547A693E94D591673F5070045973D20AA8B76A525F6F3BC6E456A1BB17DB2556
04A60A8344A7CF57411CB1626CEB4E02375AD6F549E6B21AF25C18418908ED928057525C9C84
71F15F7EB1A471F57C314ED9EC16CA55B2D2492EF44BD9104AF9C7283FD1B192457AC32F8760
32F204BA71A9010FF71FA0A74E6649BC382F883FA09EC0C46410E3AA49A39CD0A56F30A74233
844F786EB37AE9E0FF1891EA5A7BA07A826D3A543462B30F5DDB9398B3618D06AEFC7221C8C5
D1313BDD8179E2C38571CE735ED88592E1464E0A27876F40C2AC6CDC00D6B6BB2093AB39C825
57D0DF90654D57EB09E4978BD9F5AEF16B76F80154EDC4CB61A17E2DEA5EAB9032101B259058
4600FE5F74E288B16B41B18D42410D91E391F31FBD5B9DBC1A42BBF529F33EDA35757560AC9A
13336809D78CA855015D9B3254F54FA9047CCAC1A1DECD2359FD6C5388A54F21C009402E5E6C
5B2E4A504FCFD286EB6448E94012BF6AEA62AB724D774589B1818D2372E76200C1E13194A2B3
4C2445AF8E6A63E7E270F54694CD71967FECB36CB10F9B7C7EB9C53B98128FA6A2D8171FB911
20FA46D522C6682030000BB239F8BF8D1D9A923AF7104DE7DE2125425951040FB14466EC2B77
E04DADC9CFA4E13C52CF0E75237E3CA0500857930D1B5BFF827AAAB103F5E220D1FA7FC206F3
6967E00346C436BF3D15B0DDED15E17A33EF57991C0727C12863177BE68654EB63B242CE4D8A
B2992DDB37130156C9D380F721C6B954ED6062033A11291332F32763B7DE9A35CFD34DFE9D76
8C5187FAB040057769D2E52AFB30F7D5372165827680E85C3BC7645AF4441B11712C9DD1935D
32C58B92709B7ECAFB1F9008582C8E0FD93FDF6BA3F93E38666F37C79DA45E8A7F0017F3A887
A4F54923C9C107801AC9736E344693D57BA6648B44B9F6ACF6A9D940CA7960F35E0734213EBC
6745E5AB6424B0F1FADAEB69C35319266314003C80EF00DD1C373DB42EBCF5ABE5D16142B44D
BAD5C8E9E291C912F828D2BAF4965CBE826AC4D2081C8C382752C3EE0BCFD391A46B2A304187
3BD2B28D7038EADFC4B031D06E4150801DDAC8B18264BE969DFA3C80C4FF17D29BAF3AF53F93
6DD506C33704055B0AC76E436F2D54F4AA3CBD545FF1B67CD57325D48F28F3F7FC171548C106
8AF2AF4414B92A014FAC72BB51A0279CB33B881DD767DFEAB867D0069273EE9DE19FF1D63A59
AE534DA02495E0E4E5AA0B52F923228AC819E084F4E94CA631BD44B01B3025D8CAAB06F57D23
1652FEFE73803221E39F284150DC944B0D2CD9A1F208AB552CA3C6A23D5ED3E0A350FBC963A3
16B37D2CDB610A9FCC069B7669E2CB7505DE6D003D7F4F695DB88BC696AB9F87CCCB1EB635BB
CB1978F46F4D1EE5A5ACB380BB435E424A7FE8A20F6F3F1E8745781601D76567AD9C1076FA1A
1EFBDFF6F9969DF3C0F337B805B1AE318124274C0D7E0EC6F43299EE7DC48AFE50D428430524
73CCA6ECA462CE40CBD2ADDCE28D3676DD125D404EB2C2706170EB35DA0FF60C1A8A9E36A659
00C02D19219C6AF5BC3DBE759153B27658663F7C6ABA6327031A37F58F948FA4F636FA989C95
3FA91EE86B93617C3369C51841B3FC5A533FB1754ACFB5BC80E97B002B34388D365CE95067B7
F31DF8D6BB61DB83C0FC5C3FB54350C9B3A2F69153620AA7D2639116DB4A06166BB58FA0B9EC
87726935BC6324D503017B679F52840957DE5C018C4F02F86D2F555CBE67568AC075877B1B96
A759556EF292881CC358114E60A1B72F589F749E64BE973B6BF41692AA93F7604AD7D8376A94
37A13EBE498DEE73F6E22BACC58108C83791C496773240B7BCFE6702FEDB9C4A3BEC1CE45396
C5E88A770A61BCFE8755519D7E4007CFEE9919D528C651E40E05D7D03B28839255B7182CFAAF
FEEAB7B7BD2DF6C56F52F7201351BA2B7705054B418E691276A78984A2EA2E7D991721C368BA
22A7C8B738F1A9266064FF5DC036A20C8570A2CC0BBF74B25D7A691A20A1C1A5FB1400C66AEB
CD3013C43D1328F5F5D0635631A3A21AC4884F0306623EE1C2EAE491DCB845E34D749A6CE4CC
80B2E2049C0907249284BBBDBDE08588D5D1FE1031B2A2FF3756E7E2F670FF768F638D83216A
2270902867F072D9E4E6735CEDE427730B942FA67D89494D959D0FCCB923A85C07EA3272FE4D
018F1EB2A34FA95FDB6D31650AC2D6355EC338D36DE42547A6432CB847D27C74834036DB59A9
344F59C9F610091E2D5FA6157C8BA4232937DB379D43F922E2A7581819A4598B436C60510B95
6450A6DD2AC04FEC337B443463B4336008DB2289A8F9B126F0A998431D8E503B1781F42443E4
0BE700D6C47D1D65EDC74E665C0EA196767E46BB11BC0ED69199F32DA3F4398342DD22EFC529
6CB169043C3C902DF485A8B50A94C307FC14A6274570F878C6CBF18AF910EC20B0726684ED02
1F862FD1F9273F32826D6D9569BFCD3DAC8B6D9BEC14562E22031BD61B4CFDA7B2C95F25E78F
045E616A6090417F1DFC14A7A168B1B121C229598FDB040B336E1959BE810C03401D601A63E2
7F8D501F830A591884EDCFED1C2A44409DAB3CFCEF74FA27D44734D071E33EC9C23A525E4612
32135D02388D032BB8B9B8C1C8F46EDB55C98EAE149619244642D2926D3180BB66CB7D0C0146
561E452B59FC7437D42B5F3424D5F30509EF1914E75D4B73E483701026F269169934EA1AD0EE
3D1DBD25DE247F866E6FF52999DEFE6F5D5DDE98E974FF9DB4D9B99688652D209EC49AA0E0EC
F73574CCC419039056CDD2D2EB3290D0784E295400ABE8331D978DE83A2B4001D35F51E39034
E0BF49945B9B7C4EA6CA382684B996F12EC9438567A20C6C7713D4A6CCB3389B2934E45A1796
42CC9E65199AD61C07769C3030D87E9F23E85469C583DB065691EE228FC2AF56632E9EF15646
67ABFDD20776425AE23D22C16C3C005518590DED8A5DB841CE25BFB4C1BEDA4FA6575726517A
269274B1517662BDFEEC6018FF525B4604446520067198FFE83C950F3D2880B5C9FB91DAA169
91BFE63CFB48A3EBF24B7A33F43E1C7827D81CA611DF3476CACCE15A7978271C3DE2B48E1929
B4233CE6A62F54BAC964C9ACBD1DC4B64C5CFAD4682FFC880B8B6E14DBA2234D6CE8F0494E02
9A2123FE0D63B39DF8DC30F65969B8A659C0C40DF04B603EDAE85E81E634E58D053FB8826603
96B30790E8D2613B273B238365F35F21631335882693410ECFA8749E23D34371FD28F3CE9AE7
192389D7162E3F180D161B3A46B371F27E4596209057C4EF994E2D63791F32B77F9ACCE54577
A56B50B4FA026D6C1573F45542D9B9338BBD2D4695F124C83D489606103807B66385C5E70078
5418C29853BEC2D18985AE0640DC7F2FEE566599EC473AB3E04052BCA6F6BB26C27D6CE87187
A3D4C69845A242FCAD1B66F5CD67D7F70422577DF10B05CC54D9F7FB036C289948F0387CBCEA
D3A91CDEB9C2D1547BC6CB7B4A2581F39DBB75EA08A22542A723CDFFE7CFDE9D9FD926D1003B
A3137A003FEFBB9FC84B0665D5B2DA9B37A3951A3E6EE16CE6F2216575C7C53061E5D64250C0
9E8EEA685306DD9F693CBBAFDEE2A6A188B21EC458230E078BF9C7CAFC1FD601449F647C4B59
B37CF7DB2B3070356900B3056B9272B476277AA35B97486585983EB96361D26F6714B49E000D
16007B397175B0AC21D7064AF77144D1C0800689468351A1605E21FE5175320701DFEFBAF066
2B93D79B0E5E7CCCCF8CEA636AB27E0A852F67B2C5F201081335D3C2B4EE9BC5D7F342B49848
E6DBC3D2BC0F4274C2C6F54DF2EB4A23D2D736BF0823581C1EB35C8C0471AD17FD0E177F4C85
A33522F002954E8BFB33C0ACE5DCF7B8310D71678C0EEB45A6F0014F0080B4DAF40BE2D890BD
3FD44E14F04AFF9FBA9D98466BDED50680BDFA0C95011E2026053FCF08E0C67AF107D50CE001
C7AAAE3FE75F5C3505BE54CC683FC9660425C17C9740D27C0634F04B784F758A6947A4F69010
8FACB2D6B08C7FAE8D40A4183CC6329F8B921660E54420E2FBC44E43724E8F30196888AECD45
5CFF68E47E28F68A8D82E0E7FDA8CCCE35EBDE0D146D120B1044A6E0BBD91B29A38FCF4DC8BE
9158C1C698DDEE07E0BB6D0AF5DFF5C1020E8406CD1449E012EEC3A82D6CDB42F8318BDFF262
54F3B528F01E8D09C147934DF965ECE201038EE90F5982CDA85381C2431A2BBC8DD5BA1FDB8D
9236B699215626F78172D3B4135716D592EC1DA0F30B6EFA498CC3192847C45F2019DC74F618
A7414DE75988D8AB737EE75A0CC778B00D6A84A647105664A6D147715C2CD14B78F261C05464
490115BEF6A00282BF422807BA6E62E5D6FDD7D838E8C39EC86970CC7D86BB6EF72E885987EC
8D919C37112C63FBE1993071D9B5B467E0917B35BBACB4ED99D4DD7E037B9AF008A5F7EB8308
037E0E5C6862864C9F77CE7054ECED04E93A1FE549E1200368F3702A95B519D50AC654CDE6ED
297A3C6A60EF1BB36A036900D4BE955EB4D72CB719B08694DCFB3125386C7CDA2DADD0AFE974
C974E18501F4A21AEFD4E0B4A9D2124EAD0F97C5F20F67C7100921B151E8D492B0D607D0A208
ADD6F315FAF3F054CDBB8EB9C5D39B56752B0AF1187F076A7CB7FC79DD1D01394FA6529C309A
77F74E0614E79A84FE47A6518F74376B4E4E76A6E0BBA7043066C177BC8B979A6F5EE3EB5BC3
16FF17BA8C4026F9BC861D524B223208CF94D89633DEDC9D80E79C0B8A620A5AF902879CEBDF
1E0EDE231BDBEF0BAB71952B8D04A1D572EC97FCA725883FB2D4CAB5572261FAC4BDF70615D1
5A1B79B856F0B393F2A065555FD2522EA74FED08700EFA68270627E09B91ED5D02299E75B066
C5908A5790E45376C149AD782BBC1DD01D49B555B7F3B4BE829E3D28878F575C778D26FA2CC1
74683854E0FA65D3969A3F9200F91258F274CF60978E45534514703BD6F1B7D69B41526CB310
2FC836D074C3FAD523CFE04EF705552C365A82E2376D208AC859E308CB61603C59C80FDBEE2D
15E1950EC314F2039B03B0FC16F45B2579CE2D45AEB8B978872E19E55CB9841859BC72AEFE96
BC6CD048DD1F2FDAF87E31AD8292B7BFB9623B1D1DF85325B5F757206F8228A5F81BB4D93A77
550632DDD41E61DECC1441152D3743A5074B6381F5842D8C9B5B468AF871978DA6B8A7301640
323C65FDDB483A6F7CC512D523AC9A2F47616BB4847A61D187408664C758A79904D81DD29127
9E8134FE1EE90AC55B2DA653FFD91E2D9D0B3594D19FF546DB593C8A699046C0F841B5F19758
749A14CFB0AB686D7E17C58468E950255FD299DC7E6435A303B5100FF844DCDF52E3FCDA4A20
8F42CC3BB0960E28B8ED5906AEE9C176BA5FDD3EF8BEF2A6C00E01D44AF23ED706E740ABA3D6
FE39A0E806A2FAC4E5D7BDF53322682A8D0DC5FE490815F388223B0316592FB2DA05434BF842
29DFB33DB898A5CC233102E29AB9C0DDEC5163E8D8E5FECF77C3D829FC98099C1F43A56161BD
DE9373A14F69D5C35FB258CB96508DDB7B35A191C49ECD2A14C1907107BFB583E7B9BFCA5C7E
E6D72F573E067990572BBC240D4C828E61F6394B4A071608637338987115F7437A65DF30ABBF
5DED1A9DD5059610EB306071E42F46A55EB396EA11832FEFD4BE1E6F8704E5124A162CF209D9
27F725D8D528408E8CDDA8BB494EB5EF2EF90DADEAF45E8624E89FE5080A04D2625DE67AD601
DFB2131AF164F8169239A4478434FC2C2D882FF899721938BD643A41298DF0BFE1EE3F3698C5
128028FF6BE57E6700B20649CEB0FB3C78B2BEF03BA238615FB8AE5201B111607CBE45241AF2
AD6473AA54E9739E20F3F84DDDE871F1C881705E2C75FD0143398D968F49BE08899FF79A6076
B4F283588F2DB488B2B58275E6E28739D80D0B4D18EE94EA308C01EA16F856C94C95DAAAA0AC
A857F66E40498FD7CC3A8A98DB095BF04C6411A90A534E5FCFAFB3A2EAF29D2C9B24863F1D9E
12A63FEF41A06F1BA5D26962C6A12D1A73DA880AD379F14BF568C90F206CFB6D5D53FF552D15
C261F08B12965ACC6D86C25C0D1278A0F929EB931436A24875A01CC6E793EBBE243D880F9D38
9C96E63793DD75CECD3D86895117F3AE55D9921A1968AAC765AA2B99AA4B21B203EE68F644EC
5C1E965BE0885CEFD3FD0A2E0537BD02EB24102C8F3B365E255AEEBBC1CEDC7BC2A8DD1EAEC5
7EC0E642A22805F2BC745A778E25A9723B420C1FFCDD3E641445E18AE18097A7A8E54E1C9DDA
53E7EBD84CE3C18D56BBDC54C180E899D4BCF87C1CED04E10C401FDB83C6F353A28688BA6317
D51A09250E1C2C63A6F9E8707D4B578CC61CC39E60B29EC86FE27FE12CD893C0C4CE3EC5F88E
837623E202D5CF939AD560888684DF0A6C0BEBC5478F588F5234EDC52384895A564AF2145FE1
E11228F9BF5106D900011F9A9A953B768B5CFDD595987C6F5A1F2031261C2AAB5B5CEDB11F76
BED3147F301F821662B24D3FEED7A7A2D08F1009BD80593A7B885A4998E59683EC88DEC130BF
CA01BD0A9265D74CC75A2560280FEF13012351B99176CE25E7BBB0E3CFB46BD5D7C64494478C
87E7060C80CA5D5AC356CFE128783D6513670E1574FB06F009BB2671F0201B847460A54C669D
8059A0056B75EAA5236216911B9FF62DB67979DE3DF71977EA93B3626961CE1D174A10B675A5
763B8126E0E7E9D862ED49D82F1CFAB85CE6C94AED40A3E28EC2C7130C1BB420AB7DB578EAF4
D81E4FADECC7E639F154D90E1194E1FBA01F611AAF2D634CAC03A34E9E25CD247DA54A1FB27B
2888342850824E004B167D9EE44BCFB4541344E4F7884591622DB99132B1AF86A261CA17DA15
FD4A2584681C7189FE4CE25B2986CDDED549BB0DA8C06FDEBF64C80B0B1A89D2585B9190EF58
847BA4559EFB7C7BAAE64D37D95549061A8064637238FE3DE8AE31F06AE4E7FA588F85C45766
EED78D8E2D9E8D96E40CD161D820C00CB0312463FEDE8441E6CD3AA8777F8D4FA553FE9A747B
416A83FA728A52AC033A2DC128EFAE88808CCC435F1FD45CBCF963B263E714CD8C11715B4BFD
8E0F5613101E11720C2EBEED9879894FC85927DD8303B990A2062198CE7F3A0A48528FE25497
0DDBEBCA2C1A2160548C1E97EF58769EB684598ABA001EC66A278D4E353CDCFFF720AFDE2481
B9DBCAC57EE38D9C464FC1F331A45D1CEEB585388E00B139F638BAED8F6ADF8D11FBD0677716
AB72017C1349B72739749FFD24D00D8435AFE78805E455DAD15F6F4500A041E25E4E890DC0FB
A5E88B7354302F59D03203997948AEF1FD05116A2856CC2A44BD0C2147C7CFE5AE9A9575A49E
1EDAFB0FE0C7F18D1466946398B8099D3CD61F38950BADDAB531B2757395B3718FD42651344F
CBB9AE1783CEEBD9F1AE5260AFEE7A037D195E25C673BE0389CA160BBF2D117DDFCC409DDB63
DCD48185ADF29955FDB42537EC1C19A0B5E51D8785F06769C0ADCC90F5632A9F58F89D333F04
623ADC50F2C78661B84FADFC524445374F394EF24EBB0FCF338FE9F86B654F112E8C987BE7A9
A23C0AE29841F69B6F936E22507882D1A557E36B4F9F2C3D5D054A0167CF2890EDC16E5D260F
3D48E5117E6B8758DA5CB55694862564D0060AFB15641040F1BFC982926BDD21FAEA2264C8BC
94F5E4F882DC8772C4A0E049AD5561F0F240C28F7F863AA572E1743E27C1E9C1FD00D0C501E3
A90E9F86536B2695B38955C97095E1892ADFC6A6BE12A986F2C79F218B1F0BE6BF3364A29B20
3FDDE896664EACA5D770C769A36BCB8AA57083B55E9A31457EA37E4B83EA4C28EAADF56256CC
630EC37F5CA96952F816EC04A3797A8DD0A33CFF1C4171AE5163D786105B0AFC689BC96336B5
B28396E0F56193E684163234A361A57C826E805477BFA84F78BED285E64C5C0B0173A82EEC75
A897AA2739DB136529C9CA30E67832981685D75F7B51360A97256CF5CF87E2A0CD4FCB59E64B
3B506871549892DE880F4C39D40865E1A643D72B5CF0AD4A56FF0A6E68B356E2FF10265B069E
954D2E1C5F6D0BF4633F5CA75617C42D53A35AF4EA98654303B54BF58EA419F054E4786704AB
99B67A3F293A027B6F3D6EC6ED3AAF74B7CFE18ACEFE143F65CD7774191CBB8F00B3027BA684
194B6CBE20796A9A85E205D774C47EDD8D68D754C8EED1211044BB4DCC0E7E14A1F1EB857BB2
5D4191E0984EEFDBB7CD70958673AD34A0D182687DADC837139F087F94F526B93189C2AD5495
56621F38A8D492B144881C69C76E611DEEE5606E8D9A3620B946571711ABC30BD4C2BD2153D5
E557F53B667F996199989CB477381AAF8B554E4B0D0B3B41CD2DA66E120856DDFBE6894484C8
8EC36E804C598C9DE38490313ABFC3B2E9E67F6E304B347F537995416CF9B00CD0DA9045003D
7D3F6C7F358C00BCF66C9924D4D0ABF8BA9EAB1F37ABC4FC276D18ABCD2CF5E583004A4787A1
0DD260923D86CD83BCB52B8E1A7643EC39F4EAAE5F4C7FA0B93177D273492F0EE0688F63A0C7
765168619C5793BFF01FB5E65557D3452BDB63377DEA0462A0294114C125D79A59BAA2DB0B61
0E9A5DDBA3A298AB82E721674656EBADAF525861D924DD0BE6182B74B548ED0912E6D0216F94
D2DE6103F81C8DFEE4E771DA478E303D5A19170CC4CCE2DECDFCE2260A491DC221A04CE42EA8
2AC34011E8DF80DDDBB11D5CD87C77EFEB80179BB5834D4D4F84CD7ED478DC2D5D6C20E9F666
B5345B4C34DA11391C607CB413BC8C7169ACB9C2BA5CD27436B274C5342B2AF7AF334A2D6307
6DA21B66E87F86F916C03AE2D514931A8251DF60C4E50780F4622279B8A8612377401411A808
2EE7A7363381C053BB136FBEF76B96B3AD7D1018C9991A4D17CE2F3B626169F606787B2A54EE
FA97EDA191919F4C9511ADA863E93135BE665ADBE9C523813004175CDA72A880C72FE711ABC6
7446CBD6DB20D7EE6C0EC8CE999A4E28B7125086B0600AB0F34C5AF47892FE3FB9403AF0EB4C
7C8E39E2229A2512A6944119F10C7136F81385372B28D39F1850E77DDF02E7A0FE4063915E12
BCCEFA52086840D7E26B6FB8BCE852311CAD8B0FECA03DC393B896B0EF334BD4A25D80EFCFAE
9398CE495A8176810DF51AC2C7D6145DFCE312860248C802EA7373D7B1F59BAE9A8EBC594E2B
11C184AD793E8F9F0C03F2BD30EB454101EE8ED0FB66B9AE0594897F908273E591849F822285
35D122BEAED330283C76080394C89B534029B637E895A8F1A36B01CCDA7924FE2AC9F0442520
47D9979C77F4F52442A806A9CC723EDAFC8B9AE8AB884E9AC1309C9E55AE8B5935AB1F70F413
41E718E995262DAA8716A2BE97F1506441317E556690684E040D23A1B83A32B747E7C44F3046
58E9B8A364028086EA8BB8E654B4612BA44D8E39A1163E7103912B98894A79BD5EAE70815A16
8229B8965DF0D76B20B081B527F16039AD39FE609510F68BD48D8B6CFE02A9784E282FE64DC3
061AC3094BF3BE7E9E7F7EC1807F0EEBB0225CB37A4443CD9E4B2F25DAC8196ADA984DC31CD3
52424CAB7FD0497A3FBF2F02435B8E661F0F73D21DA704FA37C69407AE9DF10DB5723CF9AEF4
0D3A860F9027D0B1431CD2A92409E1E4D986D34B64DE243CA561293D0569648D5BC9CAD90581
C666709DED4565C386907F9397C442A2C0D358701AC2AF50D5F376B384D52E395D52BF6A741D
18E6AD76914D68C7E3FE1246CEAE4BFFFFEFBD7178BD8EBD239EF6D5D59F2BD71E899E763A3B
EE734080790DE33CD9D0FE3D1289E80C3EB0C8ACAFD4F3BD4DF6537B1ACD2BBCA186CE615A9D
0F0735048268D370AE929E84D2953882F8762D3819F61C0ED85A115C6037BCB108B66C7CD1C8
3673914FE883AE6331BF32C3E199F7235FEFF1895577D216C8ED6E77DC5708F4CBA32CF1EEB1
3D9C0145713A954072637DB4FCC1C1FDF0B5FE965DB518500063090DA4BEB238EF9F67F92B1B
ABD56D2D82975D246E6AFA021E0C23E88A70554C2B5F0A328BE693E22400BA163AEA84453BFB
05396E1C1A90AE9EE51F5C8A98EACE0A0CCDFE699B5DD368CBC7F6FB25A237FF848C01414DE5
63BC991CC1A0A5AE840E8EC328303206D4FDC06BC7D89EB8498B611A91DC1037378AFFBF21EE
248D15C95BC9F07A856771546E28EF1954445155DF4689527EE4B72A3F54D2F66696371B6AB5
848A50D4A3F5534BE82FF257BF014769B253DEE02AC57A1CC3325B5DC44895D210671E7C77B3
0C8266A1C9D9552DBEB49177A44A6F5F018C1D6DAD19F65C5ABA1F7FE55D80E93507338B0F0B
3FEFA0565E6BF4334D98AE53911433146731E6399A8E5783BDBEFA8EF739FEC5353E07E423DF
FE5CAA3DA0A486E4DA42E84618ED89E60ECC6E103BE8E61ED5C396EE9D800CC83AFB6E532BFD
DD96ADDAD7DD85146F410B40C43BF1F12BC27E07982099BC4718170D8043297DB95A571E1268
638621D6E295CAA2739F9251E7644EEA31715A42FC9A56EC891B5366F3C4F26C77AAEBDC1BC1
FDD5E1AF4A140D6AE1EAAF67C0C28B2B4F886F0D8674B7C0FA6E7AE7F05D56457D1A9E055C2B
30B809E3A84E706CE981107FC33D61FB6B6BBC9FE5952EFAAB183C994A2C606AEDA95E949231
926FA1CFEFF17B86469CB504ACAB435E8CDC732380E4B887DD9E08618BB8134F4E75417EE647
8B9BFB11DA7595E042B8D1BA639A1606441872AC2BBF7065341604565B8D266D64340B9B1810
8B9A065E9614107C3B2A6E1E7FC4C65331D63278F113D9724A92C0AE7A1F98D5C07DD09A7802
A77F14A551508B77316E4DF79497DA97823812A6153D81DF7F172C96E5827A5BEC3BF2401009
E212C8AD794D49548485B72C67DB2815DDDC3055ADB819C1461DBCF71FE60F7E0D5BBFD010ED
BDB843603BF2DBF73B69A9685CB4D282B4B5CFBD47D805B9E9BF38949A59B4DBEE9FFFD200E1
8E163866CFB2300DC446A7F7BFD22AA5474B706573FB73336840A60CD62906CACA961B801AF7
8DE0CEF472C0B96413847AE7A911CD28638F44BD04E6D1A1F6847A50407CA9A351B914EC5906
540B097448B4473F56E77E568DC0822CB54B312E4F9AE5742F6E61C1A5557BC04BC08F39AAA4
2AB36A10996E1412D7B046EBE11C4131F1859178DFE84AC8CFBE05CC3B919D5BC91DF294640D
4FD5835CC5CDA37E9062634745E5F3D3C310CF73F810100EF5945725FBF38496AC8763E28B9E
69566C0F8032129D569ED8B93FB794473094700911A2090A9F6D8FC5186ED4DB8648C32BA583
65D1DC247BA2FE69FE4A42F5423EC4A8D1B9B07A836B83201EC205D158A80A8918143CAED74A
60A4D022EFEE3C44FA24FAAFD7E0B08106AC9B851DF68C1643D9BCDDC72905440C980113BD78
91394313840F7B4ACFD26CA6C1FC757436AE7D499801FE39594393E0FB3699AE6A7F387AAA2A
6D955739B2729CBD00BEFFE282E12D0E938D512C451E186E82703BFAC1FC85C57957B482CABD
8D3032CEC83C3F75D981129A6B5736577CF55C417D11F26BA143D197B53FD97B7766971DBDC2
BE12F9EFA47A0DAF683F504EF5726AAFDF01FF5B5D941722C6D1973FF92DEFA5DAAE8554DD48
B01FF2660B6A31A210F504BEF75C1E8EA6E243972114DB296D19C790F1806E58CEF7F17673EE
6254A4D8D14C3ECF591AEBBC869861604E181BC8E70E19A178F0118FA307C16778810FDBDA4B
148BA33FF3A4B38F3175267E7924E7912C52CD78352688C45644794CBB843A501F6DCB88BAB4
6CBBD6F36E31DD0FDFE755081BF4F0168AC57D32E63BCD9E95C6C55D9E56690B7ABCBFB535C8
0AF3825F921CF6C3953E40BAEC3795A32B04328750932DDA02B0408EB74210EAA082D7E81C04
DEFE9E7923DBC0A175EE616161F96FEA8BC29953EC47B82951DDFD4996A6573C40220A36355A
C3E696C07F61D6C0B16D2124F2CAC8766C65BBC7B8BC8B8B0D5D766533868A1664E319719863
F29BB802EEAEB5D384E95FB9A784F894CE477D8A41DF73E6B560447644F54EE71741AA8C3CFC
F40547426B5D397F873D38051A1C37C05DC2BF7C77F4068D01DBB0E5FC2E3CF2524774C37525
8AB840929F058BB06B958E6C9157425C3D7A2C047272C387E92ED820C92583E3624E6E498A5C
23264DE1CD9000C7B97081E40023C071EC3968D22331DA058AB5DC1A4039B0A313D70255281A
B7CDF91FCB32A991EEB82E6AFB4313D4E236E57819ED4739863997EFBF139624F650842DCF91
A3782B41851EDA4B45FD9E46BD4002379C66F700AFCF7B04328948841749EDC07B03277B01DC
DF1527F14E261788FBD4D326177246589B5D6003653154D8CF5B262FFEF2BC3C5A4F2C1000CF
1E22408F1C4C972969EA4156B3B0DE2905EDCC99326C3F72438C659BCFE4E420C643BF6FE226
5CE6EC9092859A20C8A8D0BBEE2FC3FB0D14217E973E4C7B318CB7A8F6ECE8021EFBA044B1FD
CA1BB763C1E37D622F833FAC366C66CCB1C44D8EDD405087D720BAB0EC695D22D86272BFD95F
35FEBDE770C397DA6D5B212AF2DBF1A16FF5F125F3F524F53B98BA064535346D0DCDD2CC02E1
C55EA0E0F847F766720D6A9D45B9D9776F35B65DA3D8A3C78BB235B0E5FF8819217B77B86A46
FA0ECC6ACA8C6A053562FAFFD3350F2A056D2622A3A4D673A6A586A03042815ABA31AEAA78F1
09410D270DDE0CC99110A420B54AD9CE4B54D4687B07EB3AF950C1D4B88B0AFC37D792407D94
50EC4D77EE6DDFF803CFD0F67354DE749FCCBFE296924AEC3A305857E94B65E91FDD9F11B289
CA47B191C7613DF209896366E9D07431BEA6A229652AB7FE6A210277334784C8D6627D7D8ECA
43D4B8E75E1E6AE21651E7B9942FC0E781D502D8D51D7ED6F9576A12A2CDC40F3781AB70437F
9D958EB6477833B9B85F391AA10201E89C70C0A6B053E5D95A550BD380809C3D9249602F7EFD
81EF86F7BEA0CEBEE78FF7E51FFDC2CAC7BC2692E3096A1642F40687ADC3CAB1626F7311CDC3
B1EDBCF3BC8A56153580484B30875BD19B65F77320A26A4540C1079D23B07C48FE5D69EBD7E8
AC5C11333D9837FD706D1C52FDCC2AE9D13B3CEAD494B7D0AF602A57E5032F872EF41C71BD1C
53896529E6050BFB85998F489CDCEFFCF9B70E5D7371422F031AC9C00D00E8C436B6EC76C9A1
1B9F92AEF7246D46EA779C051C539A5D0B537F05ACAB9C2C22BE43EEA3D56F52CC7087EBA41A
894CF633481422F5E6270A4E6445496DD020BD3CD846F98CB64061BC16E6C7E5430EC1BBE8CA
2A9390EC2B3EBF282226EB70D5AAB4B911EF1347299FDE67868D6C1ECD96B2A8377068808629
E2BEF81138EE0966A059BB6058CDB7D418CD5F217DE21C03C596471AD4125FF448B5DE9D50EF
DA9CCF04B3D4D74B452BD00C7AE549FD0F2F1E7919DEC06ACB53D39A38E75397296A32E61A43
5D4554A1DB7757288ED367DC6989FAE7F428A8E28E806EF90C4CE040D1478FBE47E2CED9C3C2
4716AB2E4A138046BF7F7C5C6ADBC75A3283CCB5F9F53E1FF05D09186C8EAD24CE641DF1844B
A76AA15586A93049EA5C279CD92F070B162F59A7023B716D9901F332C7C05DF88C27BEB76A50
4BFB2F9DD053627942AD6F04315B51140A6DD16A9CE1A4AF46AF3EEDEB07EFF17F6BCC85BD86
6E763C64CE25F9F9D278F04AC4B12A03EA26BE39FEC35434A1A105DD410FFFE7B99C0AADA93C
6A834BA7774BAA5C01D2A8D89812433D5AFA22507ECE5014737136641953F6B053E93500B069
34C25D5F2E7F45B00D78A4702A086AD89A965EBFAEDE1CCB95DCB9B8F0BC376CF29EAB1288CE
A94F572383D358AA48EE8DFF88B20A78262813BC1A2849716F6FE7295CC153069E511281DE2E
1135B90F14A9AF09AB377E76A38D0A8C87AA352130228BE170E0845B1FD3C115E7BCD94A807D
0B079CF9D0A4FBA455CA2CE547F24A5AF1A58EE39CA617E2C15ADFD2AF1B6625EB8310CF7831
EA2744FB523816373E69139B2014771C6D7C9DE12CDC486943D716B9ED76F5500455641DBC52
D5D20D43A41D28FBD23D557AFE215ED0E7B9ABED8A5F908CC8331E3FB61C9A9E73546AF3ED88
A024607B738849BCF80112E995BEB93433174D2FA06F12B159979743EA404625BA7448F54DE4
46C9252A6A2769506905F8448A938EC2BF8EEF3F73BD5C7B5B5DD81416DCE2EC74AA7ED2D510
CC6F591D0C51F2DC4B8379D06775F0C2BEF70343097C44EC7FA8F711A745F3330DF7B8BB7742
EDE598BED07CC879A10B0B34B20335A36383A01057A53A5243363855C70AFF48F259A5B2882B
B302D320E533225326249E426BA07FBE02C76D5193DBDAA10FB23DFFEAC7E2AD096F324E86E5
A6B76FCD07D6129338D14A893EE8D92F71A9DE75D6195F71DBB650F0AF3989A02002DC32D1EA
DCDB40CA3ADB7B50286F2618EC285B822EBE484E9AD72591F5DDB07F3A31EA9FFC3B26039676
D1BB14983439F0E7517674C9E36D1F86FF8032E6BF2801ADA6BD004454BC61FBDF33A2788CEA
419B4BA1A0AC2E19660D6173F539E7EFE000AB18CE9F724E5CC641D6052A70F994A38E050030
ED2CF32A037B56E9CB96C149A10F34932FEB06AAF48C2BD54D25B58412CA1FEC65891DB9064F
3CAF93D6FCC90EDCB298BCD09ED00AB7B46F5E776DB5AE0E397F8E780C4F9F19A339CFF8C9D6
6920AC9E95B3D90F335B7B5BBEA40082EE405AFEB3397A4090BF854F0A34DDBB7D80FC30BDF6
DA9032106C0A090004D0DAD25B27B99470796E5C4402D05D82FE0533A2FC0641E06086D5A63D
FB4C9E35A8A6ECAA9259F93B812796C4A331895EA2547ECEA1EB254B1AB777FD3EF87E583817
4BD6919E04FA04FF349906D4AA7AD2CE33BA754276E5712F3EF752065019563446103EF6713F
E9ABEEB69D73A66FE463A37EFBD1A37A53B42F445D13DC40C1042C38B09478E35901501053E5
6E98C2EC86B364594FA23DEB6EC3D4B16C41A5FE34A13B880066B3DDFE51D5DD7C74CAE27085
9934A57FDE18D4BCCEA46CF0B05C2EDED63629700526B0FC9B40A3ED89A3718DDF61A554FAC0
6F4722CBCC8FAABD7960DD7D733A73E820787F5AE1F5B0526A76FE49057AFAA7D42654C95B39
C9294C20F36694DEE69404A8F1FAE78CD75FBF9F59AA7D9887DF8783775F26CFACBA6CB01B30
602446E1754E2F6BC3CA692B4A6F078736F9FC74312DD87AD5974C45B386CDC5E64205AFAEED
297B40BEDD7630660FF644A7A9734113E58ED8893C3B93A73F183C1CCE12035FFEE9A515C349
16A92220D07F065436313638617BF3780BE2C9173472B8A69E9EF800CD93709AAFECC61734D5
DFBE4DF2AA1AF855786753A0CF176BF74CCB46D2CF239BFC37B2554F17C1DCBD693786A0B5EB
82831F9E8A4B42EFAEA6B10E7942AD1B783B1D644DBA9B5EE4B45CFC496FDA6F98881689760F
734AA938CDEA288427833C4F24999E85DC610EF3A484587266F72E1D9EC3ED7798DD3A9EFAD9
854133875C0F42453C21287E5A4D1854CDD50DF26F572A5933CBF0944F611366C6E6E3B80D2C
4C44DD99E80FB8351C9DFBF38CA541892804DC2FBD14B1CB344555FE484BF649C9308B751AE3
F27D7FA779B59C3D796493D14426A31C4825DAE251B80D462C98F287C5E60B782153854E29FC
3BF95B2C4B3A987909ED65D3345F947DF42A7C0249602EC342404301F2D1D1DF0CB61DDC5F38
C3A967A0CBB707EF6D2458AC4F51388F803C2D4ABAE337F604D8508BF79A9A1BC185C5030DEF
FAC72A16CB51EA6FA8DA134DEE3EF13226FC0C5C5A00573CCC71B7F414E93442B0558A328805
786DBAF0E9470431002F0EA58A40AC74DBD1805734CEC67FF5B8E3AD354FCF9AAA26FC636EA3
0B026DDB98B7749DE54C37EED9B0C614C1CC5F1DBFD618BE5728772E67F85AFE1DA3E907AD8A
BF69F6CA96E5452DDE3C047E35FC55AE164729E59AE10FE733FE1B58FAB7EBAB46120ADFBE71
3529D6B8728C772DCF0B43D42E9D7B7DE2FD45B042DABB9D573FD68BBDAFD6E26ECA6672A425
5D591136049F9C2CD467299EEE7766880F5B174C2CD570011824C958D102EB97BDEEDADC9B07
33BDDF99CF1C20136F34EE2461C6D5CD1A77DA5A901A66B2E3D57910CEBB30C60AB149336F2A
91A9CCD9C6771D4A48DF99FA4683DB39A8161B83CD29E70D51E2ECDA3DD5A34455585899F61E
7E4FC376111D29CAB945D3FFA57E7DB12B894948A37DCB2BA9E79537E3FF095C81CDC6A4B228
19D7E579355B281A4F44C5F475AC8F984B78A91B20D4B11EB47BE5905059A211A6696DC066D2
A5792F6AA667BD5AFE92C81CCE1753DD689FA80010DBC4E0BC917CD4FC8171C991D6FCBE5D42
CCD8EA0017C0DA02CF307EF321A0F883FE33731655A5528AF87F05C406C7A05DDFD4D6889654
99A3ACA7E82F3F2D85941653AC8E45C3956CFFDAF91CEF1F1AEBA26EE5495A3A28073D190A38
1DF5F2384D12C1FDE082378B6FCEED74831C12A54337D64A6352E2EA85E67DE10B4CB5E09E5A
B6A356F2345EB68EDE34CCCBFA9AA7DE38B5FBFDC6973531B20F85D127EAA05DF03AD933D546
0C50933F551493AE28544F62D126F2964E834DAA0C652C2EB4DE3B0FEF10C974FCC7C10F0196
AB56D47E268AF927A96EAFADA234F1030E58A257163B72793D8340957515D2E7FF6153923E5E
3EE290B6284960967479B4D81BAEB242B327D6B2D0FF46F77E43B4A0F820F66204D507E7C1E7
BBAF0927478F9F9F7121E11CA789C0E0418217CDAF10875F96FD05D49913091B920DCA3BB373
99A1D88109D834742524CDA2FEC84E86F232E5DD433F924E9E01BF6E446A63DC40741D349420
26DBFC8D3888A3A834BD4AEF3F5D38000FE075AFD4CB3DEC0415EFE16FA1820341A48EC4B3A1
086BBF729E68EC9DA96296A4C9D551E099E3D3BD8F464FAA5735B99963DE4C2AC96BD0FAEC57
E61C59133EF494085A9DD295B45B5B86307C7FA720F7170DEE2728CC31C58BA1360EF0733918
D1663BD355295CB8363E9C53B1F271D5CAA6D53B80D8DAA29E9B834271422637CCBE92D7D9F2
7B3D3BFB8B3FDE5C6959CD831B09948F92943A455E911801BB69CDC4AF15ED67529D529B9915
2AB50B8ADA7690135C54465F46AA2D6E17FBC36E92E3C9A2EE01CA9693646DDBCCB439F3405E
A6C6FB477B56BEF0FA5C5EBCC067C959C4453046959C4A9F1B166AACE020CA94F082899CD9B0
FEC62E8B60851D872E56D48C6CD9D69D5540D1B3F1102E0B641BC40E17FD99A9FCF1048E44F6
ABF60352446E3C8520273DED902ED39EB7BAE21995A6F48D89A74A31C40E585D6206D90434DF
E9E3FD3DAF501AA292BDAE3040FCE06586D10B19612590DF6D9D60C086C9BE4D2467DFC042D3
4BC7C37C93E58924BDF35C5380B84B5BB19F3658696D32AD3E48F95A0EBD2005E50423C9E3F5
DF1DF53F001CF6A914D3F7545531E578422D99F9D914C7D83FAB83424C583F4A78C51B194E0C
5A80BD051BB9C62553EC3443315DED169EA666119BF3C5730391FC08EBFE0F2B8D6B18EF38FE
726E9EB4C41E11C9A22351C374341AB728D0224582689A104A8B3E7DE0FCAE31EE8BD13397DF
DFD04211B18938BCA715A66A1C7AEC553A14C20C909AFD757241C62DCA34D6CF7ABA262066C6
3BDA13D3ED508F90AC4CC8F34A3C7B8596A47A24B0C048898CA14D7DBE9C48B8D1DF2057BF83
1C0C89C470F3E526DCC94D247E54757DE9AB8516A1EDE99EA0902025818A06C68064AA4A7706
3908CCFFE4751E161EBB1F5BF09AB351D39D0FC2CB8021B73A8CBFC7BE80FF63577CD226554F
A9DB429B058B02314ADC063D859740747B54961512B3160EA441AD31F6DC6A0D8AE9BA50B0DB
545870A451690DADBE35FD8BF54D32C06BAC67C886516BDC7FC91CB9B6435525073E37CF4670
708805243C6F9809C610CCA49C7D53A638B04B15FE1FDC4F6C2C6C274D18DE17284A4A6E871C
22D1D525C23FFD924AAD6367E6F3E576667A2766102BA4754E6E3BF0F854B328874BEAE2065B
5984E0FD540F228BC854E6DDE07788975FA64CB562656490CD30C95D4DDBD8171E4FB1A2B5C6
D50755375446CDD0B405B47143538D4FDBDA098AF40A06B1CF7A0565009458CD116069C86746
DAD2C0E2F24AF45B40BE740E7485BAA6B776D99ABA9BB0A25C53E3AA56EDAAC25BCA78BA2A7D
0AE5DC30D2D80493F95AE152DC0C07946BC5B5EEC417E1903B3ADA7D1738A3EFCD223F743CDB
75F34A83E3EE70339BE05C352D8A8C3D3BB7B3F934A43C26EB2A849A2B390D779C9989E57006
AE913F406998391013A463175E9E4C8DFA17ADD0A743322734CE5BEA82CD7A4CC1115FB00D1B
212C8A340B0AFE77568219B9A3C523090ECE0515CA21C05264BF1934F557AA0197934B8D27DC
634A30C5C325309E6E7704E97BA8C06A8200B041FCBD0D539D972FFC6B1250F047C4D6C5D549
7B3FDDC7DFC0AE135AF47C31446D8EBB91190847F870897CD034F87F76C4AB03901B37B18746
0A32360B86D753C9FA87EFA92B79919BC2D181A81CEA92C438E05EB257839443FDB5E96A4CC9
898801D4D69EABCE3B92AB3427930C462290300E334EC1DBC9E54453F466B9CE2374CAB66535
DCF6312784A708A25165D6667088BEC143F05A827EBA0A9F6AB536B69F8EECC44CA548F7072D
B51B6A189B4260ABF269B0A1869763ADA330A595CEBE655FAAD08D62415ED6587B393360DD36
6E5350EBBBC3098317B97581BE36742DCC36CCDBB3B42420C791A20CD92FE82947EE6144787C
4C3A6EAE1B13EB6BCF4D0BFDCF25DC941B47FEEBDF2D49293DAADE949AE1CE74037676E01A39
C2AAC54ECE35A8630A1756AB03059A7456E1048033C7F1248324643395FA6FACAB5E915F76D4
40CBF009E1AB1F39E87D9D5F2B5F6BEB9034A987A18F05A558C173B145BB865FBD5EEEAC935C
70E207BFCD63C514FFEA2250B6EBB33EAFCDA4CCFD0503E5842D6B1E27E546BE5FBED519603A
EE73CBF5B83C51C1BAE439A559477FD7BABE6B33AFF69EBBA394355679A1518928FBEED5A751
6488EDC265BE1C1BAED666E33FC9CFFC35347FF8834489A916F048B25E96AD4E8DEE3AE05C75
D3AECEB30547329D9FFC69BA98E2FBB7D1D78FB6355CCDA87826AACCE1AD13C39D718AE32310
14EEEA3A5C79309FF453C8461A4C66C3751F1CBC06CB25B9DC60BF3583B142AFB8334EE23DF3
C69F8AC7C2CBEE75CD7F4A33DAB9C8481B6282FC58ED195F1780E493541C208686B71EAAD9F5
358C0DE284D54F0B6341807BE697E3D737BA6D7796529FC73843722507DFC1598C1B808BDC6B
12A4259862FE387617B2E189B194D96AC95DA4DE3663FBB4770341BCEEF13C75D76C655B40FF
EBC66713A3416E7BE641F5F8875D36495DE4E94A8B6508E6F3EDABAB9FF52829CC674340DB57
B248864BB9365AEA3A6C84B6A1D0D6928D275B5A79ECADBC1836F4768A715556B98FAF6AB81B
289831B71AAD06F5217610CD7BF4F92B48F7681EEC635B26E9DA602962E4BB9B3FC4E561E629
767C0816DDF8073E7E387A125FD81592A714B58A03768A8309BFFE17F7BF45FC0C0820F0137B
398E2DFA6376F9A7808E9F7987F7E8D4898CC8D16500BF4BBD6BE2B9A166DF05DA84AAA132EC
B88A11BE7929811EAEA87299F26CCC439A374173B6AB3CACC2645781F787F3EEEDCE87427F6F
FDCE837946A0D5171769FB3F150A51E16448C08B8F8D78CFAE3A98D5F18F26E745CF9DC64403
91AECB0B61C713978EA17623CC5ECCD22F4BFA6E655BD0A3212B9E2ED3BA6E85D61F099983AA
1EA8CF1D1D852C03B2BD92F0F51E09C154DA9EC5C879CF489BF99923DB4D9B68A6EC66EF1D37
B8A1B27D50CB931B87E74B65A9130423C162E66AF90B61A32C63B1C92F9A01C4A3917407FE69
A2F64FA60C808EEDD1825A02C9AC689641B6AD379D64F153D063CF3664751B06FAE88D17014E
5E0B0DB0D41A5817149DF3773F81541EBA95093B338EA9CA58ADEE6578A540B59927384F0F08
536A57686AAB0AD877E29AB626E9B14FA7B1C4710300583DD5AF73098E1CF1B807D647149523
E1B64427E7E5D1CE78EE1E7025A34041E87D9F6A97CD1B37BE324571FF184EF3DB86EBF77894
5F7277D0C194419CCE2546727552660115002034E6DA52BDF3FA669EA30318BEDDA7E7C02588
8C1DEC52925AF96697919C162167E3746FDA83CBFEB79DF4D2E8576C8F186C31ED02BB428817
B0F8BDA82D74DB4903CC1F7B18872EBE75C7EEF577BE9309DEA7ADA7565B6943A28BAB624C0E
7FD1783314A82C41097031886D8D70FDF368E95BAD9CED5F620A11031ED312FFC1C2A587BB5A
6570AD89CC3FFF6F5AF56C361BA367A5FAF9C1E4D9F2F799479730FAD7DDE0F1557225054646
9C9C64EA50DD1071701D2E0CF69F227C2400F01B5ADBD34887C95CE68F26A6879CD224D2B1C1
8F11E02E3CD42E35D3C3D30084688F798FF91EB3D0A82F11AC9212B2F7D9E135BD3411CC7188
76775573497F2E5D97F5FD3D0C8AD2FEF53654D0E016A39D4E5717D09CCC87367E1F3193A4ED
5714F783794436403209E50D8B96533F76CC66151CC6124CD63F33BD572D25FF824AD44D5163
7BBB017453E4B3B37C0140075422BCAC441047654119577EC6ECFF0B580655C21772F99DE072
503A7688E22BDD7723AE7E7537ABEDA2064A1C48424B0BFCE52607CAC741B762622E6BDE5B27
794B4989FFE55F4F2EBF290B0FFB53C62A2BF670946C8CFD089242341637B237C37269FC32B3
E61A27DDEDDAF2897844A3AAC99E2E23AD7EF3010D2AD92EA14FCA6D68448E961212AD79962F
1608F0193E7C301F5117C3B7CA92DCD9613F4F90FE4235916F17598AE3CBD144CCFE9F2937FB
44CE9CEA13CB7298B02621DDCDF2CCEAC48D2A22177E244592FDB96BC75B0D4D9C2108DE86A0
1D197E13FDF277FEC5D59A04380AAEE76ED736324239FE2103240000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginFont: CMMI10
%!PS-AdobeFont-1.1: CMMI10 1.100
%%CreationDate: 1996 Jul 23 07:53:57
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.100) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMMI10) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle -14.04 def
/isFixedPitch false def
end readonly def
/FontName /CMMI10 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /Gamma put
dup 162 /Delta put
dup 163 /Theta put
dup 164 /Lambda put
dup 165 /Xi put
dup 166 /Pi put
dup 167 /Sigma put
dup 168 /Upsilon put
dup 169 /Phi put
dup 170 /Psi put
dup 173 /Omega put
dup 174 /alpha put
dup 175 /beta put
dup 176 /gamma put
dup 177 /delta put
dup 178 /epsilon1 put
dup 179 /zeta put
dup 180 /eta put
dup 181 /theta put
dup 182 /iota put
dup 183 /kappa put
dup 184 /lambda put
dup 185 /mu put
dup 186 /nu put
dup 187 /xi put
dup 188 /pi put
dup 189 /rho put
dup 190 /sigma put
dup 191 /tau put
dup 192 /upsilon put
dup 193 /phi put
dup 194 /chi put
dup 195 /psi put
dup 196 /tie put
dup 0 /Gamma put
dup 1 /Delta put
dup 2 /Theta put
dup 3 /Lambda put
dup 4 /Xi put
dup 5 /Pi put
dup 6 /Sigma put
dup 7 /Upsilon put
dup 8 /Phi put
dup 9 /Psi put
dup 10 /Omega put
dup 11 /alpha put
dup 12 /beta put
dup 13 /gamma put
dup 14 /delta put
dup 15 /epsilon1 put
dup 16 /zeta put
dup 17 /eta put
dup 18 /theta put
dup 19 /iota put
dup 20 /kappa put
dup 21 /lambda put
dup 22 /mu put
dup 23 /nu put
dup 24 /xi put
dup 25 /pi put
dup 26 /rho put
dup 27 /sigma put
dup 28 /tau put
dup 29 /upsilon put
dup 30 /phi put
dup 31 /chi put
dup 32 /psi put
dup 33 /omega put
dup 34 /epsilon put
dup 35 /theta1 put
dup 36 /pi1 put
dup 37 /rho1 put
dup 38 /sigma1 put
dup 39 /phi1 put
dup 40 /arrowlefttophalf put
dup 41 /arrowleftbothalf put
dup 42 /arrowrighttophalf put
dup 43 /arrowrightbothalf put
dup 44 /arrowhookleft put
dup 45 /arrowhookright put
dup 46 /triangleright put
dup 47 /triangleleft put
dup 48 /zerooldstyle put
dup 49 /oneoldstyle put
dup 50 /twooldstyle put
dup 51 /threeoldstyle put
dup 52 /fouroldstyle put
dup 53 /fiveoldstyle put
dup 54 /sixoldstyle put
dup 55 /sevenoldstyle put
dup 56 /eightoldstyle put
dup 57 /nineoldstyle put
dup 58 /period put
dup 59 /comma put
dup 60 /less put
dup 61 /slash put
dup 62 /greater put
dup 63 /star put
dup 64 /partialdiff put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /flat put
dup 92 /natural put
dup 93 /sharp put
dup 94 /slurbelow put
dup 95 /slurabove put
dup 96 /lscript put
dup 97 /a put
dup 98 /b put
dup 99 /c put
dup 100 /d put
dup 101 /e put
dup 102 /f put
dup 103 /g put
dup 104 /h put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 108 /l put
dup 109 /m put
dup 110 /n put
dup 111 /o put
dup 112 /p put
dup 113 /q put
dup 114 /r put
dup 115 /s put
dup 116 /t put
dup 117 /u put
dup 118 /v put
dup 119 /w put
dup 120 /x put
dup 121 /y put
dup 122 /z put
dup 123 /dotlessi put
dup 124 /dotlessj put
dup 125 /weierstrass put
dup 126 /vector put
dup 127 /tie put
dup 128 /psi put
dup 160 /space put
readonly def
/FontBBox{-32 -250 1048 750}readonly def
/UniqueID 5087385 def
currentdict end
currentfile eexec
80347982AB3942D930E069A70D0D48311D725E830D1C76FBA12E12486E989C9874C2B527F092
5722787027F44470D484262C360CDFDDDF3657533A57BB16F73048BFBBFCB73A650484015441
FDC837ADD94AC8FBD2022E3EC8F115D4B4BB7B7F15388F22CC6198EFE768BD9FCEB3446EE4A8
DC27D6CD152485384EF5F59381FFDA43F2D20C8FB08AA27AB2015B774DB10DACFDCD33E60F17
8C461553146AB427BDD7DA12534BA078AD3D780414930DA4F8D58ABEFD45DB119B10EB409DD8
97923C6E705479464A4B310B58348C4B42393988FEF4925CF984423AAF65FEA9F0E64629953B
CF50B919D968D99BD185F83112B2759CC411764E9BDE677F57C5EE5AC555448D5F81A16259DE
D1E11BF4119D53E8AB07A802DF900D3A2D5CCC1C6876D29C5E9EFFB7AF3EF83400B0910C0787
3A8C56FA7B1EB1BA426043B00CC95DBEDC6E136CBBBCB3F67509964F9F281EBF81FE5B018122
EAF66C4A838487E82E186E006093042848A903EFB3469AB6B4049767AADB95C30408DFD58D8A
10F4CB22168DECD9F3EE100F07B49AA44C92139B669CC312BA20192454EB2375BE6284B02665
9D964B96AE82D4942E758027FCF23C25ED01115AF27CE7F20EFE2A822BB684004F20243A49C9
E93301FC21B80815C033C3E2BA58EF53DA2157D524B395F2B37ABCA13BC6A2F42E824AB7E471
06176B0D6DB267FBB795AC7425582DF2E3DC55863468A9200742BD7B552C48F8CF58BC21343B
D3B95ABFA140F33F37C6F3F78B0D8A5154EB7C1F62EC598267F13E841A3E64172663935AC8B6
65D86540D316DDECE329C008049C5E74B27D59022C5515059BC3B89370B1BC6A169C888BB325
E0B74282D6F053A50DA4024ED1E433271A32AB8C17D41C632B41CF9F3ECD5FE124DAF7AEA7CE
8A63047B245822930D517DF7BAAAFA69D2D17F7D93CEBD47DEB85405D720DE0BB4DCAE731A8E
27BDBB6E6BE38D168B7DAFF815ACFC32CE367374BF9FD98C0AE5BA1BCCDB84D94B5C173ABC92
F7D18E19A68F64A2241A0A1639108DC46B8A04EAD17662B7BBFF3D3D9A95D5937698573BFAC6
4973DC8D8B8D9F68C52D0C133119ECA4FAE72F7553D276C817003234A98337D7C037C0F1BCE8
A80457113BCD97515C002D20F836FA086A3277727873EC2B64A92BEDB01193491134B6692A08
DE4A201A3F11DBE070D797F7629AD487D2B8DBF89A0631956C93864A4460AA3BCC8EC6B98DB7
5209AA1B4A2E2B1B9866CC7F3BEE4E0EB0DD68627A97A3FE6141FAF10A2CE00391796C5438DB
AD93FBD065D1ED7E8B7879E0D1BE9AC145B9AA91756EB6EB81146048072303229CB8DCEB133E
572EC8E2BC954BADCE75356EC8EA0C7F76CA08533E874BBAEAADB89D86CEB974A52DE0F9A434
80E5076265AA6EE49ECC896182E6091EB30B7DA8CD0E3A26AE7FC03BA5C0D56526ECC6F2D6F6
91D84DC9E7DF306863FE0B6DAB3CBC588C28292DF3F7A47D9C4E3652C72F6BBFB3F4983CAF59
C7D877103DE7AD73F95A100AE860B4E55814F00A7026C306E85B8A48F8F69CA48AE710950A2A
1F2892F31A3849CF917002086DCA5F66B84EFEECADAACEB33A0932E394A5E17628D52E725FC0
C69E8B00C9DF81DFA32B2970756D947A9F56831B19FA3A2F2795017381C05919032FC19A6B8E
D2D0188DC35923F486A62C8AE61E0A5BC681A57DC20223629C0339F67D689B63D842909188E2
CB82A4E0471B9F17CB8FDC6A6D2C3AA6FEA17A756B4D4860FB72B50CC39CC7E5329DC202A5D9
0160DCECB7ED07B9CFAEB7E766887C9B93727E5DF348FD2F5158A2424F443A8C72811CFC9CD9
E2CE8219667D7364E85BB01D8CBD63CC11533CB0D14B793D5E1DA99278E636CFE6A34AB61D46
44DFB5939746F67C71EA1632A43F457583D3478D159400E04CB7BFD0011048ECFE912EA5B72F
6C01F941C78CE1FDFE23370848D6DB1C88D27C9118B3C8C8CF0BBF33FF12B509D3594E187F52
05B9E96F9854002E8944B8126A8B2B41BD572E7FE727B10441F3B4B303FB576084008DF04128
F28A3BA5BF987BDD3AD278F316615D70634C47E6C924A9CC634A249D1D57DF395AFFD6B0C524
68061B62CCB46EC8CF95AE99EFA5DEAADC48F433ACE21B45CB502F37F06EF95B4D8880FCE2EA
E511E2F7130A96097066127391923616B95EB7E3D70CAED613BAE4F2D65E6AB1F81D63745FCF
A57A9BC5788BD1288607539A0EB5D7C139FCAC70436ABE12B7D57C1D915C3AE1575CC7EEDC26
297231B8A510CEECD3F0B291782BB1C342BD44219F004AC2F1A869F1448354BE54DD59CC8CC8
DEB38E3B8F4899845DA13CCB707CC10D715B01CF3D7D3BD1246A449F90E96D40BC79F879B7AF
43B7A09D9DD4884F7563910E4CDA099284CF094D1D0246583B01F1E687F0A365B463E7C7B4F3
70E924900712B02B20792D0DB404E08ED5ABBCA0F1F447292857A96F3F73CCCBC73F223C7FFB
BC96E095E349CC72D2A37DC40D196FB55782050E83C7097617FE0D2C663D32A7F03460EBF9E1
904A12877EE0D4A4053BD5B673B3B65BDBAF76D7BE76E4F49A0C0912A87BF7BFEE30BC1E91A9
55729D55B0691D2E573B7CA693ADA3E865E87F4C48122AB163919CEDEEAB29E83020E4391D59
00AE2FF0F086AB51FEA2FBE72549C4CD3A674C8EEC28AF24EE314876F4ECB7F161CB9F55A2FD
8611C48F3E8396DF873D8EFD9141474A86B8906CC01736588436A3636933ED22C8B8D97611D6
26BA7667B33BBB0DDD4EE1FDA2E89A3F03A18516456C029B96AB181F945C6C81990E19A732E9
ADE2DC846D19386E874ECF08F33C48C812BD31E6056FB1ECB4049E6C66A5FC814A77709745E6
9A645627D45362E798F3336BD9996C42B37134CCBD6A4BBE9D938DAF6EC6240A4C4F4DBD4E68
1C77127B4D3DCBC7D770AF6FE20529F19FB6B332D0B6CC01B4E4B2ECFA05F2F768775B311574
F662C4487683A979D3A65E824E55EECBF4789664EE971B374F62F34918524BF9671A57C8A7BE
A7518A1D5FD3B27A5D116A6B0F9E3A9E4CE276A5D103FE6A4FA0E28B6F68F5A4D89C032B298C
B03ECBB2E1D94A4199C6255D93BB029AFAA00B7D6E658713FAF433F2777FA3A0AF6F898D88A4
D32FC6C3E0D8BFC67CA1AD7B9D6FEC4A2A99325D83CBF1F6165842FA8D033D7682EE635A5DC1
185DE824BDB8EA5BC7F3BC046E83527228F17459BA440F783D08F1DD156DC0BEE9E8EAB6F8B9
950C39DC03000F0488EA4071047ED99C550FB8AB843AA639B6289B7284EA8E69AC785AA88066
D9F3D4090D01878D960DEAE07C2A13B8015556AB50AEF2BB8FA969764D3CB40AD44D5A9E548D
E2BD511FB8E38AD40181ED288C8FF88B04120295677DC6228939DFC33B7764BA80C32D4664B6
61D7407309CDDC605428A7F4CED1F86708466E0BA2F05D4DD7244A803341D0B0D86E48DECC59
25A75DC331472BBF13E3D024B85ECF438073303ABCA65B8309BC57E64AA97C244F6B89E82B17
F68D520E28182F101116F48A34E349107DCC6ADD53F2084CD42720E35946F520E56669BD5EAF
BB02185D6EADF788D2AAF54D2E2C2ECACDFC7C91765BAF663BE838114B333687A1B7DBCD498C
8A28876426B354E6B5556EA862DE3C0305645B75235A32A2AD5DA5C9B9CA573D6C88A3CB4CA8
847F60F731454F264150DE6EFDB9BE02E6F5B868DEDC1E7C55F2C46F99F80AFE84260B4D94FC
5947754F7D98E96D932DD3D13E78ADF22B9A06360B38E7395B7E2339C07FEA445F16C2022C0E
B8CEA6EF469AEFBA3A398FBF747F271C26E1870A86732E4D23B9BD9A564CAB079620105583FA
E5EEDA2B5395E39DAA46FE5865D29ECDBCAB4D5FFF236CA8834777B0D1CD347DEEA5EFA2F387
006125E46AF358867E7CCA258AD4A5222373749041225381D44BDB3BFB3661FC5CB3EF365444
B2D19559411E3861C3468AD08A3330D842F16439E1C7CC62F639EACE059BAD656B292C9D8C3F
F72FB53CBFC7F942A57C78A9B4EE3C531413D57C2EBAABF4F32956626AFCE2BA1F7FECF1D36B
B77BFA4DEC303C0F3B0B011BF3A079A32DE973D5198F82771ABE8017F9D0D40473B996CFAD73
A36D4DC52BB211880E1924CF30E191C1BBA6FE59F54E0F0DC2471BF45830ECD99893A96E136B
1A45EC4EA86E357A5A8BB49B2161AC9A7472454D5BF9748F34177036D448D14BE4171F0B81DA
E7008F0C3ED828FEB647F0D06661ECD3997B3D87648CA02D3B6BC5AF94CBCFA12EA2B41DDE42
B61DA7C83CD97B66C7C0EE10EF0A4EC5E063A24B5AE434C55753E6A8245A0F745669801755DE
324CE91D1CEE35E5B44CA4D6CE8DC88E15057A20B14035DB0B84B4E9D938F68236992C1A5F3F
7620D04972807F8C4FBB3A610B5E3C5295E2A34C14504E2DD400019A770A8F28344B981DC493
976B115228E575B89406EAEB7FAE63933FD79FD29A1A489DC4B5C516F09830CF7DF23889ED50
2457176F21D1D3D192EC42A5C39E7D301D4BD47CD9B56191C5CB0D1923AE941B336451EC95B9
519326AC3014798A56C22A9CB24FDDC6C46184F14B6068854D0FDA7192F97F7B783B7F51053B
3DCFF411F4C965649F7E61880B194037C6C69CB15907E7989F4188B1B1FA92CCB2EC1F43DD09
6B3B1D991DE5882F43AF1E023F2A4437F684757EAFAA011EE65F1D9507E79C44873366253EB7
84CDE128401BCFFCCCFC56DC8900376552F45397EF8F5D40D5D1BEE737C6C307A475819A5D33
7F4B02BF28461EA571CDD79F39F9491B37108525EC550E9D8A90AE63D56A1A733CCA38407505
C1A7690C67529EF6E51E117ED62274135F8744241CF456F827E15D512E78DFF679A117FCD7EB
45D7818BFE675607F002E8902B6A179B4210296EB19A6B5BC646371784FF5137220B6FB81DE4
5FCD8901A4A0FCEBFCED40F456F6F09D59C66B0BDE0EDFF2070D64B1EEEAB48C1885A939463C
4ED7E10D194A31F9859D58F160C881C7E7679052EF3D0BD0037088C5BE74CF9CD8B441655AC4
C21C063D5CF157E63D154E2A3C0FA0A1B796B7EE86207252EAB2A8F6BCED4901CFD178EF5B0C
BF5EE7CD9270AD1B1055025C14AAA045A9C2D6F01A9AA133870EFE0A7FC63104EC2B4AFBC027
7013E787E82B9581B38E70F585F4F2E01E4E7804ABE534F97D8F92C460A609492ABAE7D236E2
70CA04C2E5ADAEC2BFF1F219208B2F8BF5CFB5F13EE94D3B9A601DCC6D9AB03EF624DDF287A3
A950856F44B3A31E54D64468BF8BF92F4432937DE368FD31D7A2E0710CAAB3D479B52105E910
787A4C6A97C11496550971442CD159755924C31ABDCEA68A874A9C6529DB2563BE8880576C07
7C4C5A20262C89FF4391ABB2DFCF24500708D191BDE0FE49FF456AF3D8355E56B0729BFDEC11
884ECCC7CC061B44F48766D6C2F31793A5898A8F5900587995A2A19FF4619131F5E665C98C19
1C2D6F9511DA129C471823E78138C038B17314B37FED7AD3190C938F040BA89E65EA6DF47460
6138937EB395AFFD6CCB55FC0371F8BA2650CF2846015A912D67A848D29B06563A76A65B5CDD
EF34D1B76DDDB801B3CC0B910B8487BE26DAC3695DDDEFDED0347228D046AE30B64637C3DB66
35E697493A0E72AE1C2CFC611BB42F9138F608DB7DE51CDE8520CAEBBEB05A29F7578395CBBA
7B01DCF6AE7664EEA3DC1554A62028DBB478A18F6EB6EC084917427CF6D40689468406C923BE
93E0A8DFC250DE798B7211E91855FF7CD3DFDC9D0F67E52DF1AC3C2020B593C77E8A5E6FC3D5
7AF2957B4F876A90A9493941F316AC9C1CD05F73C1301537574A7EF78D73D23C31C1D4689387
A2D4396185442858A745B98D81F2580586C88D6CF54AEE1517549241B59292C8DA1F6FAFC3F6
1F2E82315ECF37E5E8306F4FD0FB4B4D0BBDEDD2BA55ACA3EA3EB02705571DBCDF339F326842
0DA8A59DDBF5CF721D9BAC5A1BE8CB3C0B4FF98D6B15A2DF24215EF121CC06F4700F2609C817
C7C4A0659AEF7C646DDF125E9ACE18348DA6770D3DFA3B9486D9971834A7EA6881368A9612F5
293601FAE200974434D1C24354AC8E9335D5DCFC27D447CCAE4B0923CF15178484B24C944FBD
847A64B146D0F77DEB7665247E855C600237B1E311FAAAB4E80A2B8058F6F26054D111E94142
1A2A143F3C4106A506F844DCB8EEEE5ABB05C2D0B4563C1D1080B42EC330D3DEBE87B65D9FE0
A684FB5D125F7EC7ADD81FA8D82E938BD2AD25E1DF6E473BFD81659317C91BD2256FB4164888
73DD9D67CA6D52BD2C5524903C68989C3F5132F029EF0A078B8C2DB830186A2DC9CC47B9E6AD
6AAC42FC7A12BF5FB5386C558A73DD4AD02D7DD4FDAB2152B138326D968EF837B79A3BA3C0FC
A3A629D8143DD8B974F8326851AFE08BAEC65344751A2B076D71EF4F49148E6FC9F3CD520645
604726239FCB202117EE1CAA906E37AD6CADB6AB92B1D31D277FA27F6930ACB68D128CD0AD70
60C4960C4B409664C8580F1C5F3B93E673A74B8094284837117A644F0CA9398FDAE7CBB29DB6
AAD38CE5CDF855E84B3794DEB9362E1DAFFF74ED1E87561A4D33A7B6C93D18F231ED180B0D11
2D789C9E7B35B31EEF4D5FE50329D6AE3E9324DCD038EDF01F1B10E249CE33E8BC8E77E84483
96FB9B74B316EE1A78F2463AF742CC468215923BFC5477A74A353A3CB7286AF8D782111B09CC
436ED7E7126E5C70122E81142DA5F1056694F2CE5D5706C6C3DD6384CC42563E5BEA094392D2
876486F313B8409A2A03CE6718B7F5A58A6BDC7D7E3967D6F7D2F2A1652D578C0C43438B67F2
E67AFCEFE2F1A031330A1337D7442AA8D15A4B1B0DDF56AE3477599A1C04370BB06C5075A9CD
D5D9A6BD26B3901F46D90B45098E5940B44BD1485840CB585B8B8BA7CD45625803FC1420C850
F434E84DF2CDB1C6E2B48716DC287BDBDE64CF54C9EF6C3DF4BC3452798A72DF4C2AEA80415C
9521648EBE5B65ED763B5A393AAAAC1227C1E017DF5FF4F2428423373BD6D5FD39D90599D30F
8D39740D6255FB22ADECA70C5EC3A8F87A59EF93EBE91BFD0C9AA2BEE6B3748B3914752F0E5A
34D2624FAABCD7EAE3D4051B088C9AE1105B541DC62EEBFB0161D05818A73DE9606A3BE82B2A
37D1F7F22CA33F57AA00A40F3189FB57BB46658710E278833C08F3C5D428BCA99ED499E1B3AE
16892C9ABAAF45E29C7036D1B0EF9F17FC51399EE7E7BD85EC424EC4AC17275D980FFD2EB1BB
92E78B2B38868AE908740E0CC26F414334CEF4E8CF5222F46E1AA40E0032E59FFCBB395B4ECA
2573730D1965B2D4939F24A154B6E44334BC0C465360BC2827B14E03E0F428DF065E9F36D256
E9A76F41C0F81747DE63134EFC9CEE6DDFF528FD0FE979237FDDA7782127B2A44B2F97A2611E
FB1B03BC3846CC19C86330F9D2B4B557D47B5367D597E4964257C0109A26DEB44CCA07186DF2
D26769BBCD6BC499B3717D6DEC05675016943C69EF60BE9E2A004340202288D22D6476A05A27
FFB9A4C7A2AB606619ADF733C05C38C80B1E2300CF34A1E32213B83735EF20991D4C487472B0
571AF8F33EAC2B12E0F302C63371A42F1F27DF2027211D6ED6EF86766E35151B67AAABBA4B46
9F5F2164CECB46FB0866EEA5480B615D6F9BEC31CFC9A898148363C039BA8DD87FE65F1F9C8F
754A1D38B643BDED590D7E4B45DA77B64FDC835CB412C5CBA906DC46A7C9D3584B4EA5F7701F
257DF04B12274B3833957D2869D52433EBD119E69278D93D7423C0AC9AF9DE81B6CB125C02E5
723C495492060D6CC6B4BCBA6033601A6BB3131A474BB29FF433A1F3FA9EDADAB29F591F029F
ECBFC5CBD578BF738D57F8AC962C6C4196FECD4CCE3B8679A2B805E736ED48F01E027151421D
1AC18D5473F299FD612542DF45DF5E8CDE582D236BA5A3A7554C7111BD2D9AE4BFD5D53C025B
BB737716686C68645C01327F7E91AAAC5FB9B31EC344CD1BE4427C612F3E397C8C9756C7B30C
D4A31FFC6EA5C0BBB2453D2FC5AF8CECC5BF27F3D22E919E9B4C70BDE1E55A39461821B30266
B8DD029B63683997CE276A28EB79E52DB38E3E00FC6C9F0C98A2ADE2A3FCCF651329F33E754A
A2637EE13D8F0275BD9E3670E9B6DF5E5C7B60FF2E9BC284895179A6B54A6501B09C90CE1F53
7B181DB63CFA3502B27699C0FA32BFAEF33560EAF17035A22B24AD1A92204835506F9AB0636C
7E1C4B9BDE7B1E3C85A6746574082D5A66DD35BF0925B91BC10F973B607D990EA83AFE2B43D0
D12B61D5246A4B2E6399C626A2215C6B477B33355DB9977D26F0F4E0E750EFD66855852780E4
70DAE19BE56CCAD5DA484E8A1405860F582219BD238F18084A13DBA3BB6673190846660FD16F
243A0188B6626FBE383F47C9D115AC75810B9FC34F56F4B223D6ECEC3CC04A64D56CC48029DB
AD5CB5723F037904AA357A377635B0693F08BE60F7AE5E4825C939A53D481553C1E5A5D57DF6
073D9E94E402AEC39387B6534B10D27E16A85F20F20D17627EE9CFBF60CE0B42C6472C7A21ED
5FB251748D454C7B7FC51C447C6AEE85E84FD3112EAFB348EC75D99D8FE3F1942C261D1D8FE2
1CF2D4A7350F05B983594E1F47BE21E1BA9A263273ED14B9161B494D50B9B9EB5FFBDFB088CC
1CFE9A639A8E405BED650531A96D1C3313617FE5E0DAB14A2E3E95CD4A0B018A08AFFF8C5E0B
9728642B9BB9905689CC6FEBD1072CC9881DB5BD7F102BD4CEAC2D861F3AEF8F1E24DEB48A0D
E5C10011828BF7F0EFDA8992F6EC5C053F050790739D0D9D04272FE9FAC41B86562075AB2030
C9329A89224DE27FA74F61FD49D8CF7F13F0A5E69600E075A6090AECB2DB740A6507AA28A7F1
57B20558FFA64A4DE9DEC8F877EB9DF61ECE54E3281AE89C207005EA3C9F5E64F2966BAE9DB2
21365367B95AD4107A842FA8AEDA660FE530D0B37E5B8E46A2956E7DAF0A5231E33FB6D96395
CFC427B7F6866C1730BD33BF55A4C43A769585D54699B5B956751B6E441ADD82A2E5ABD2B9D3
3608E9333F408B931E77D48258415A789435EAFB9A164E651162F587565CC912731A5F840D03
9CB7EA0D281A34BBAB93238A449D8E8DDCF9B36DF3D8DD2DFDC5278B98F0BC3E070E3C354A3A
39F9A97A92397D6D0F618F522A600035529518D6D90420A8D79AA2AA712CADAFBF5DCAB8E183
D4AB84232717D60DA8C9711DD697F2F46A2223DC3E48008DCFC18618C35D237FC2D7A84F709F
D570BAD4BA6D5BB74835E3540746B0535F04EAC2EF06A74134742AC32E0C4D2A726EB4155C23
3275C7348BBA01064F695ADFC933B502006D654C2B21213918E177D3E4751908A3A6FEB3E612
268DBF27A6C253738D34396F50EE834F075AA4AEF14FF3A3BD5CB25DF06253212F75ABFC9BDF
7F480D66719C3A5619DABBE3EAD77F6AD80A6B7A6D83AF722BACC170293F9A5E51BF9B4152E6
4DA40806AF4417E4FD9308A4D8EA2645EFAA35B30A6214DCAA83E2F531DBB02AFF7015EA1149
A333CD619B7B614BA3B5069ACFD80C2D4DD5D19BAD17C3AC5FCDA1818719A9CAD9913E187027
7B6383290E27702BD87E10AB54B531B0A7662398585F7B67CFA1EB1E252E5C477025D77AD4D9
D7D943C3B5F6127EF5BF7F422CA9AF4A648E4213E1D6A9B6F02AE5119F91385B93F00C438A27
ABA9D0D1E52AF1CAC6A56C9E2FE7D5D37B9EFC4BAC853C23D07531F8F7879313247F9A978468
5048DB25AF1CC60602089DBA16F25E9AB0855D83BA874C00E28ED5633EB234EA457467BFC887
27A17C570FFB595ED41AA2EAD4D68703D0D70EF899E43E3ABFAF95447349DC61EE1F070E8F5F
580D691D80913A1DE2EED591859D684670E5CB9E3CD6354DBB51F66B5DB8469364E709033D02
C5F13179E5400C71A9A82FD4FDCB5DC94E53B116506B41EBA9B34741D3B5BAC7468FC68527A1
E51C12A45DC6A61C55B21CD9F8C3FCDBCD037044833BEF5B8EFEAE27A1C406DF2DF775BDBA2B
055C86BDD754577C83632A70D63023D3A80ACFCF501D3407CD7B880D7BF5C9A6EF55F643AEFC
6306BD9080505AB7395F809BA5BDC8CF5BF56BFF4D2F2DA56425FE88211CA111426425D4BD5D
1D606C1377C2EB7014A6EC0392D74A059E5CA21BB6C505DF776AAC0704488DADC008DC89843F
73806262ECB38180595CEAFC29311113C41E8FEC8A6BC75A4CD616A02607B1B0C3F4C2423C98
F45B76ABB69CA4E43F37E2F3CBE32A0947B8FABB8664C0070D72B4A464381DCBAF741319E659
7D5E648BA2A11F5B7CE3A45A83E094A1537E7E7DE0150210A675EA77F9B563423F71B2221AD3
FFF529649172CCE6F6493AFA7D2FBCC812C269309C426E8570C6992255BB8CA8157C9F2958E4
C63FC2CDCCA1A3EC1AF935CC9C35B71CF779E87B51A16DC602BFDB4C9CA1653E1BD1AA6DACB8
C038276107AD61D6E33D65B6B98E28091D4568B49DEDB9E9023F2977B4FE952FECCB1ADE607E
3C60D74DE8662C1A08C6C4F6A8E50F91C62D104A7812DFC67EAADB90E674686585680A0F2EB9
8CC92A793F13DF552E6C695623CD5F161A15807FB396DE2C4B32E0E168D765EC0AC448089A24
5B65FEE72EB77E1593EF910B1750BD29BD0DCF35890311254BE990D9E4B558753B34600C67F2
6B24E701287462CF8A7CCBDA97CFE5060A8C36F8CFFC8A50555C576B443D6556E14541F7C5EF
1B6E11CE520946F91918E10E90BA750FAEB158A82317039AB53ABFBE65B0D3989FE4128FCC22
124E162D559F03AB07E2FF289087B48582428CB9B124BAEF00A16D4678C0708BB70F692F8ECD
4D417B8DA0371716D3B5939D56D8AEC084CC07D0FF21A5F69C1EFCCE09FEE5466D7944B1598A
8152EA86FD11F3FD1FFC2D0BE04EC6C36CFC39CD29DF6F32E4A030548333EC9C9ED69471A989
368488364FA7C8D83992D35E01868114852B9BC5E66B43BDA19F82102261426FFA730C327C16
A92C2D840BC951183A666C4761B2383EA8698B5740671142E07B5161B7988D39239AA04934A1
928EE775D311C59F12D3BEEF3CE7EC9BF6DBC9DBBFFA124AD23568747DEE4AFE3310D19FD2F0
31D782E4FC8980D315FED5BE69715AE90F45A26D5DEF008316DB5237B6254EC881F5F42B22A7
70A9998430DFC54E223E1CB1F2C3CC21CC968C3A9CAD2F935699129A0B05E76D7850FA8F630A
6A76B6B428F022C17F7E72A0AD107F044CE76574ECDE1F674DEB9DFCFA5C860F199490958B06
18F599CFDAC6B2FC5040C32D1632428D250F97A5E5C686C2767808C71A3D6E86F619D651EE5F
BEE3F6EBB220CF2E34E3D0B7B9EC38F2B0FC78085867579D98DFF2DEE6ED400B19E34237FCD7
5BCB901F2E6A3DE5D721A239BFB003CB4F5C58DE63E8F7F8A6647C06275236ACB4C1199EF950
EE7CC5FA7B0CBD4852B3062C1CB39137C29289A42CBAD2BEFB0116F948EFA5637F75C0325848
86F85008300C3B12E01D9B15E5EFF2D44FBB3C6FF28694298FD8F8DFA6817138DD586FA00D0A
D7EBF5CD8A63949B54AC4D90FC8863490561EACA5207259A76E3EF1890A2B59099C14BD58F42
CF224C34F1305F4E30E9F12E7AF0519E80938035A2728D433D75211C73B9740EBA4926B9676D
874E41953C4E59A48579D3ACC872952A65ADE2ABEDD6128CE9C40B058D126C68EA0D40B0A081
CE1604CDD5EEA12AC901CC12AF8771E39B66487A9C94B35D882D46C5F3C43BE6AF8654CB09EA
74A24A58CBFF5A25EBF7D98E08DB4CAE7D71F112503FE689A27D75DE94B94D7F0A8F6F4F9CC8
29C1A441EBF4A22A85FF6479AFBB1A4252AFD7FABA9B1CAF518F1A2C67392B44FF9E173A6621
8C1DA8CED86B17861052E3F9B758D06CF8864B7B8B7B55322A5E50629229FB515754697C0269
41F7AAA8C6D0AD6682440A4908BDFF03C4D413C3A7353F6C9275788610F8C8340EA671506F17
4EC79EB0EBEC7BE8E62470601B32ABAC9AA3E2678367063A57CD950349635726DB14DE55B488
8E481DE009CCE2676EBC510CD94A12ACDA187D096ED6417AA1E8B781299CED175C4243EE8D51
E1AC2382FFCBA41F49D19F60761052E59B75A2D0D4CD2EA45B1859CF449B7DB95FA7311F52EC
28A8D028D2343A958DD54500756D2CC13BA81E72B69F01DBFB636C9299A2F0D3A147740AED1F
D12C59B2D7D8F0761A86B140D3545F38A21A8D6205A57CB7160FD7C5971266FB21A518CFC331
39AFB70DA7485350EE8FB0134762604617AF0ED255F06616DE76569F48A2474D7F56A1829DF3
0034F290B30E3F2B34C433C11C1DBA265059490AD1704DA42526125EB03298F86C56495FF67E
63B06416A7B4FA2C2D086FB7E9A7EC218DE891051219E566566FC1B9C16EDE9FD2293183CD29
16E3572B0D770356EB2BDD7FD92794C270D364D12D14DB02C65A6E6D636C8DC0150372FAA09E
488E28525048EE8A866FE1ECC868F6059597225BB1C588A12349996BFAD2F6D0131F04185E1E
FD125A2B4C4B8F2C32B6A307874B0D94DAA68CCBBF71D8427FBE1ACC6B3B279A52AA66CD6F5A
5B1E3DE70523ABA543F44074A6491ACEFBC6DAC617F805F99CFDC01BB5DD8500265878FEB2D4
E75BC616D30F63D11EBAAB94EA65A4BF64A484210A08C0604BF0BC0275899F5AF6D217B914F6
AC9AA108F921309F9580701530CA11E8B5AF77D22767151FC64BE8AA6E4EA7B595E7AD726ADF
A2872D007EBBC41EDB3380CED9743A88424A665E37B941DE405DB5BDFCF89D4F8BFA6A636C97
3254709C81BC54570266EE5FC66FE4717CCBCA5CC309755E8AA8915E16E4C3D032E2D295A2E3
9F81AA5E712A29DF3D6F1DA12B51D414E60FFDA3499CBB74847210196C06FDC32A42E3417319
8ED7A9EEE1CB52E97C221C79D0BE506C6C8B493EADA00E172112B0B525E9EBE24A081518432A
F7BE557EF7F37D1CC2DF1E86AF4EF353E8DFD731EEA986E5C203B343320BC3D35F4FA4423FBF
CBEEB1BC75F27A40F4D9F5F5282828E9545EF54F5BDED9915385E400BA937594325973069070
71E72887D2C648989B7A4183FA3E750FECF13B04FDB5FFADA6DAC6DEFDF7CBEEA85EB154EBAC
F8758A185B3EDE6F3BCC0CCF0A878DEC6D1121198361FEBE57819539E575A6E0CD675A3535A1
A245CCE669B1C31D3E87998A956EE116369CAB04EF8506ACF9E8BD2E4E43BEBDC9A067C4F1AD
A019503E9725E1C44BDCC4BE132F5BA29B56B7E281400019A9122D02D49C768346D1B7E30BDE
6E184E0107507C10C132939A052E6084B66B3A30B6F4E855D489F12C9AFCE7714E68869683A5
C74A5697CF1B4D4B9BFF4E9098E98FBBA712E4E717EBFE6BA439CECD1A99F6C372D264A4A255
C3B99A41A2F04DFF796C9EECCC20AD43B5002E8E3CFD9F09831F4F02F9327E23F291C755D3A6
E57D012F519FA46A63B32FF9A98C3640517D077EE1A472CD000A80467B28027AFFBC9904D19C
EBA6FAC4F1EA359AF2F3142FCBD6C28C1F2B2DDFB1D6799888DAADFFAA52EDFEEEDA38F3F94A
79C79507BDB7782C779374A9BF2B0CB7FC5A216CCE50B8446FE894E9419E3EC6F37817CFA6AD
52434F2415369128209778A9BB1A81EE08E4F0842BC8CE8890636D6144E9BBB416344D9DEA5E
65719B332F66F9CFEDA829FC0AEF7919253ED138C92C0FF7BA23BA9EE1841A4491ECC983B1C1
162B30B75F8DB608CD41FB8FA402AC96CE57D6E27060CB88BCB47FFF9132B63814964E162EDC
F06A2F9452EEE25E1DD7340FBB273F1759BF9FAA1B2D252563A97ADFB26412C605C2C87F5725
753497293A53FE3B708D2394E19BC998AAE5580A62BA5924A00C90EEF883A69C3310C64E52BB
C41B70B89DFEEF80B73556FAD1D947A079E8D0BE5BBDBBCC689E6C379F5F6430E44D937696CF
99C6F3A226E27E567D945BAB4997BA2A7C04FE4D9C2CA4691B687B2EABE5188E302493326FAB
C6B5876541C4666A26B3B65C228AADCAC6BC98760F3D3735B89B2A2E3D43FC4CF6ACD11C96FC
6C3610ABDAAEB5FD4C7FEC50474BEAF06684A49B6B245956FC2936A68551DF931353C2939326
36FDF56F0DA797EC113DCCFF2E3409557028151EEF5AC29077BB032800F10E47F79CCA5C6F5D
D75FA56638FA4E59A085532C7D830808B122DCA20D9FE537A04F5279E6F96AF0F0D180EC5243
0438E8CD1A7C79CA9340C0639367FB2AF768F36637D67F7DC6C71B14DB7A35C567A66E460EC7
0B91357D13AC281D18617A861AC04A6B73608467999B1DB7D06A52832482FB4153D95E6AD9A9
885137C837BCB0D9F2AF4BBAD66C9AD04265A9BFD47DF89D6E2E990DA21CAA3883B815F541A5
9FCCD6DC47830E5E32AC631EB16E1784D94F5A31523D31509B4FDA3F13CB6D0535C7B9D5FC50
EAE72B74C5596E271CFDFACCCBB66735C67C32560667A2AF34EC48F09C574B30D4510E8BEF41
E6EC0DF52C2B26344B9EB25501BC1207C24B8844DB1852366A48A991C345A8B1484A19E7AC52
BF541D2F95EFC749AAEB3859E9030FB12EA35ECE6739FFDFF7A6809848FE1C04A6046CADB0A1
2F541366B97451BB8D3AE48E96B7E97B5BBE5ABA1B460820B24115A03DC01721F7A423650DAC
1E6C305FA5178FCAB92386687B1D1ED0B07ABE6E80A7A46143C05D8A9C8976FE3D1761C05766
12CB9AACB370ABB8352694514954D538CA0F19197EBB5A93A2BB940FC8B5256B183C769D382F
61B0AF9C9A98FDE7BA8BF56C4F4882E0209FE14108BBBECBB8338A768692CE2499F2B612B6DE
3D617D16B5AA3BF42ED95A2B2BBC438461FF8136420417E2CD2B1A8FF07F1FFE31A9DC926D59
B968CDA1E6946260224CB22E598B1452AD408C56E8D085F90404DEE4FC07062C72BB12564162
33385EEB99F2B67C5A0D6B1044D29D972567AB47FC55BC918A704DDC2F30F12A148E660CB724
0A412C6FCDA1A34B7B8AC1025F384C41CBD2773FA11A868349DB8EB97AB311220261493A57E2
D48A2492A23F0DD6DE1F1A3D84F4F665EED8A7163C7A339D669ABE07A854E4B614C126CFB10A
E94E76E20C0B855AF9E96C46BE1DCEDAD02CA27692F792AD423135E4BB034395C71C6A87BB23
A549D63823FA513320AA22C24CB1EB499F150BE279199BDBE09FA0E5D2B0394FED0CD68E13AB
B329304424D14D1BF7C2DB7D5D78F7A857FF6FE7A9E121D3BC71D3E178779FEDB2F966A92EEB
6CEAE29A21461DA66535E418972DA8337358AC715E50562508CD7330FFB465FCB613BF5AFEAA
2D2E13CEF53DCCFEC3D7029CE1088E73174A9D226E174AC7A80EAF60CFADD4BC51F934F794BF
24AEED2FDA5486D883BD597EC42D4201B49BA0F89401129B0094188B698D09B1E82E2898E1E1
3FAFDE14F40E3F7B8E5CC25FBC45F123F48FA0D0A7846D4F94C27CD4635C8EB988C92C03F824
FC4C0E7DF36F0E01D36B4349FEAF75EB5D8C23E513E65F247F0CB86709944007B62313F4BFD4
E3499B67CD55A3DE0A1E030B74BC3A97B7D9AF2EDFA06A41BF4BBBA292BFB500255247026812
4B13EF6135E45E213C46AB4BC40EC5F57FDFFC62233A1D294EF1A0984F4399C925B42A2F597A
64044943D0DC84247E98D231C2D35986C58A0C62006C1E4C0D6FDC531BDF7FFF5183DF316D61
185BF17326E745C5B533E0B7A51433FF5691D84DF17AFEBF80303F9D5F05C797B3E767D788A3
BDD1191D7A6D576FE079784263E782CC6B284AE0D59EA5D60842BF0A7F55CE33067076597578
60AB8F0609E46E9B4036DDD034F5AB39D1B0A639BC8BD55FD4C800CF360014D16BFD3828ECBF
97409AF47EA32B61F162BFB3C58DCE3039692C566BF70B2A8B6F2CED7479DB7C0FE286EAE554
B601025D57AA3F26F1F6E85D17FA279899FB61BE82B59F6C70E0ACC2E600652304FFEF3E6771
C348E2C088F7837A7CF37CD1C74CF0B78299D26B5EC1AE192471FBD996FA3FFE6169087957C9
50B70C7BD174722FA2EBB27F6542F526D3D0842F17449389F3E6CE0B5712CDC5B1CEAE6C7776
0B8B41E8444FB992928844B224F4FFBE0A4EB44027E0A75E74DFADFAAF1566F957C1999F768C
AC8A735F17DF653F58BB9BA4AF0985A0CB32FABBE787B9A133B8AE7D68C1B41FD3E138DD26AC
083DFE79A8C879256E5BBBD14E7B31478E3DE8ABA60893ED06F2C6479445644E795F46A9C95F
308867AFE83D0CB1DDA4C68E8634DA9E30694ACE6EA93AF1D1E9670616A7AD444F9B6CE89978
062B81346D81DC0C058F3740FBD591408A8A4F6EEBAFB5D7772FEE8F467B83713448DBDDB5D0
90E6481BBD8636BA2FD30B79E9AAE4A98E673094FA6A597A8F0DF0B74C9BB69AF42F5FD4DB7A
0468409A39EA5CF8D4882B9606E881A59A729EECF60339D5225090157843A69CEE675AA56785
8B49FAA306D8A8D6BD630D7E38C54E88CCD548F96B22E93F780CCC6FBAD75976AA2D966FD300
429B03F166E241C575A0469C17E427ED8502CE6A49A8CE1AFA36D2BB914A2E0F2BE4B2794D3A
E15C8E5914B36BF9880B575D65B86C1D620B3BD6F9587EEB090CCF1AC48C73930D76614BDB37
BE7FF457AD7E07D812D10C2E425334E0E66F83F024F2FBC764F7E9C9D07A35EB9297BC7AA519
14BAA5055D2034DDC15AEC3EAC9311D99A0B9DA9DF9642FC4D5CE51ACCFF41402B227B0528A3
4B6FBBB1F9AFDCE1706BEACC566F054B3BFEF75D735D5C92656AA780E9F78D3D67933C74BB7B
7E1A3BA96BC716BEFB31099771D1348611184BF76E78E0B75655C18C42DFD2B39F3377633FF4
CBE887574EC8AF654E91294504A59D04417F01E8C6C0EC71802D74F55020B6D15AD0333F5F50
4EAEE5C47BDA9E373C09581B8DE96B4E6FDC76A8DD8F7B4FDF62DC852973B828F2F4FCD97C90
17EDC5E0A6BDF87511A896327E39267E86C851C08317E13B413C7FA7C4B180244D1A26524368
621142189D70F26DCE33CE009EFCC33BC35B211C67C9FFD68DE3AFDE61BF54A485312D6D66E1
6BA9022B97C73D77ED530E606F54ABE858F2210821328018168BC89B5D1F0EFA0C02E4C2CA7C
C4B2BB366131DDC427504AD454F6E8A314D9A5A4994F21607A2991083331F559B29930DDF0E7
CC86A2DA421AB5E26341F26B5C9B9F1772F0B244B62C4686A2813DE622267588C0E5DB3CB458
D2C490768FD6A0AD83DF55504C3E791554FA56A474C44A26256BA539416ED3BDB54EDC8A3AC8
61CE565A334ABC80B8DB73490595E01986B45B0D82693C41DA5BFAF12B9EFEE509F25EC7678C
C1E4EF735FFEF5158E0AB72DC3939E4F361ECA40DA40368D5516A55444957866029259BC233F
C3F000F54CA33E2B82C999674B22725990A9BA8DDDA889F8DCA18A64EE31C4C82DB2BD653E55
5B147536E03C8D550CCDAE2E891D81772E10A1FC43DF9A600E025E028704D40AAF27750C81D3
F0A8E2BA60FAA0F3F4F5BD7F66C690944EA6254A33DF2A503715510772F9D8822EB0DCD03FF9
2500374920E0AB941100569ECC2C26C393DD56EE48BC914794696A4211212E8A77B1A653EE24
A02BFC350E7E8577FFA1FF9F11B587E61C08EAE8D88B073B780F5FC2FA97F6B5DC9F7439D84D
3ECC2C67B8100EAB30D6CD8F07F2F2426749A47C7EE77541FB716463F8703B6BCB80F5BD066E
94CA265473CF95D4ACEE36D05CB22C83DCC8B27C7B6BCDAB943C899937C29FE456D9D71B748F
1B57625597D7EF30813823DF79B8E368D864FFBB72251DF04F862AB1D808E25B506804443959
3BC6A7DABE86E0793C0186D7DF54BBC6012FDE7E30C4FE5DC9FAC9171D62CE801C5B77540930
F5604850AEB85A13E06620150AA55137F66E6DFC97EB36A16A9311A97039EFFBF3E5080760CC
EB073475C1E9B07E1E23FE1F65ADD9F68EAE159984DC1BE07365EA94A90E2305A90D33C46245
6CB031BB031F0D34B570F42507560AB26AE4B64772CDFF3034681B7E3CC6B610FCAA65187436
00CD4889AC7551F101B927F16188792AA47EA95BB05E2EBE5C96E92CBD487106FBF63CC9DF2D
D0E0C2339402875887CBF2DFB17C3E32E1DA3EABEEA3EE9CB461A7898A1AFE29609E67AD6DD5
7C91964296FBC5F09F4DB2C8315B1F7D9D324A8F745BDFE3EC7903279D78DE6E129D81CFFC2E
674714666791C5A6DA8484577531BED634A6F7EA50448E68D959F743279B9A80C8885CFEE79F
47DF6B9196F79FA4383B8681ED4754F901BD36C5A63FB1582857254DF71516F53D04F8617898
1F3E9D10558C4C7E613754D3CF26957E0AEE795F9DEE25EFA913D3623D98C1F96E0AF34F67B4
306BF5F593A96ED074700673DBECDC9B2BB27558525BA7544029DD9DB5828C6D8E563B5BE801
3E96131B9E2B11D67DAF49A1ADFAE1FC536F4DEC7C75DCBE0D6741697FCFB8EC8D2D3DC85FBE
8225A86EAB86652E0D32A00E59985E495D975EFF48812495EFD19DD9CCD93141D361B0D1DEE4
8ADC0611D1DE2E8EECD62FE9A162542BCAD738167AC417A156212A8229EF17605EE9A3E2AF8B
5795784CB576C5D2C8688A849E2F04B7A2310958CEF0380AB87E39F1D0270E002A11B97F866E
77C1CF7AAFAE209A57AD12DB90DB20026D92F123F3293ECA4AB07B86CE5A9EE650D3D1491156
A6199132B271607782E30F03E4A333E5E0960F798EAA25418313DF13C5D4BB186C37DFBD0392
459885CAC59FE71D22B1BA70083CC6D81F800F1033FE0A250DAF09E03CDE1865FBA52D2AF2D1
FD4072AE40706C969C1BB778CC4EEB3FCF993DADCA323BA2C6B72FC9B2C4679B9868B19A7E58
40041BAA7629877B130A05D1594C855B4853E70C8A1D1F58A20438C39C1E3800FDBEA47EC323
831783457FB0BAF72C02F0EF8BECC7D5940CFDB008CD258C094980C358471A2C6102C83EAA60
5523C535EDF3A96E699AC6627C5DABBBEDC9D06FA6906A3E524C2103CAE0E2DB5F926A1FB5A9
ADEDF9AA8663B026115791B810FE0EF2CC1E1BE6E7FFF7DDDBD27CDA85A34B3548B2129A5DCD
9071BCF917D9C6BFAE79F41DF7FFD4303525FCEE0F8D47179ACF13FF109E748B83584AE2C8C5
7FE3392653DE7EC742918F68F86E4694A8C9C3115A9E459DC45557A492DAEBBC306B73DFBE5D
27DE382E17AB54A77475A79E38BBC97FA60C738C9B017BFA6AB85960F34632C6010E321668EF
6647698D00DA3407DE9599736E3106D8C30A13C63D8B447506768A6771A3C18C7028C1E28983
1DBADBDDC8BABF7F5D2FE992594CE0F01ED186A4226F8B312329D30431148743E29A1C4E81B8
DC2290CCCB1B1781A397D4510DD2D08C81862C66353CB95DC06C67F2D783F0826CE879CE8BB7
6C93F57A64CA5EF9A563470B1143DB3ABEF694645337284C1EED1B94A8EB67F62AF99CCF1263
EE69F09109AA7AAF5F39A9488C7F0A1B3B59CCCF641B0789305B3E27B6DBC105C385B06EEAB8
CF7BB5A6A514BD597A401590DD3D8DA4E0C291621D9F2D9964A408FF77025134020215A605D7
77D1E509789DDBB548DD22A7C5A0C9FC6F2B84F9B94067AFD956AFCA3DF219F51671692A7EB4
8B0E91741BA2D2F3F533AA458F7C373ED76A155C18094E372F8C4766C93C33B142C87068E00F
9CB93ABAE9291F33D1AF2560892C50A3EE480BC84C46DBAED662A4BD34774E36310D91BFC3ED
B9BFF3D0061C5FB6207042680713CA4C272126A4D40352320CF87AA4C0AAB5B77E2B53792F62
6048BDB646480C5FDC25725FB6A11424D3F521D72730490ACD0DB15B91E94B11CDB8350BE714
1209FAFE5222129CA80113D1CAAFC9E5F84269080AD8ADD155BA2307F82D8DA59AF65A328A81
EEABA59183F6F12B9AD4EC9A10EF0732ED2F05A3BEE8C396B3663E993B02D145A5EE5F66E30E
CEAD5A7FEBC39BF46EC8F6C4CF2B31129084A58664C4A4B413F99B831807561415A15E5EEC49
585CE724128F53C19786921430DD793960103153BC86F58C760132356E51BB62F093B97A4ECC
7DEDD70427F00B45C644C523EFE1597912C4D9F53FA7E8FC6C3608338BAA4637D6EF1EEE30D1
CFE8DF2545A07388D8376499566AEEA76CB191E8DB5FE05C9D91622F262BF5564ADC064A5B3C
AA5569EC5233DE0A488CB544533FBAAF602CE67E0B09F9BBE7E0BADA637D26A7085E80BF5DF2
E06690306186F13A400B726A9BC0021A34BA050079520CBA61CC3D3C61DB0E5909C2FCC82E31
4DAEDD2228D3D4173163FAABFCCE8C4ED96829B0289799755C4484CBA8FEC61C3F53D2319010
62677888699BDB42672629733D4FB910C73B307E8DCB837F53346759455702F04A42CC42325C
29D16F4ADEC550CA0CF5C9B7EC60038D7F444883FEE1A93EE0673F67798AAA71AB3B1EDF95BA
0DFF0F45DC9D6E0588089553A091962BDB39B2D19B9395380DE4D8615F054AE7A1D8B26A16B3
A0611469ADA90C9A3818D08C89A7CA26B0CF98DEF23C8C123977F2087107A1550AC33C50F076
A30B84519EB46669EDA19728C6F4455D41DE791CAC6DEDA07A108670972C428438719F847BD6
FBA1CE8E7101E972A7D5924E749A2916FBED44BCDB2954510BA71142D7708B38DB6DF559823C
AD34881594717BE8D205679137747AF78A8AFB389175B5826903CD5819726980A7981098B02B
2F4B47DCDFD89653538327E431B843B4FBE0F0703BC3E211BA7BBD965B0407E31946757D1009
BB2EFF7E611654857FC11756351C0E2732BC8B99B20EC5E520AC9CC638010215CD5D7AAC58C8
BC907B6010F6CB74396B7486C0906F9B879B67814A23FA9E89C79F2019A935125EBCFBC931BB
9EEAE79ED464065D458E49AA025660B1543B0588B97C0D755430EFB05154814F5FCF0E58F03D
3DCF0C01197A4D4B1D94B0357CFCC6B6D9BED2F84C084AC953B3B247B46706C71E8BD717B93D
602241B21096C3E6B271B758CC50F2657481ABFB0A80B54B0D2F0AC2B14D0F552815885B2EE6
399ED0A9A2D3C133305339D97E44CA08D52C9071B8F34D06B2DEAD4549C591719BEF6194DEBF
8E7064C18B15DF49A73FBD1B32C1F16413F462857A76345A462419B74DA65FFCFDA65075CF3C
6201C6710BECB92696653C0B927000B26F5289CA6FDEE0EC2C39945ADFEAAFE397907A92D266
EC4568635EC21FB10C18BB9FF8B975ECC778C77B7E8E66C9D508E23E136F7B1C2E6E03AAFF8C
E77008005B13217B9293CE534416FBA358F1CD5CF26314E4E6880641D8B987DC504CD4F3E384
06E63B8EC62CDF13D0C739F60799AE269706761BDC78A9F80F726739DB2C211949BF1CB2F947
7E17227E18D43A875FE5ACE8446A887A14C77D01B5C9FF11C3AFCCD91C2411072632375C3F99
8343651BC7F583ABE03439CEBD67BBB3335B94193CB3CF36210C431A202B12EBD03D1AF9C6DB
B1F255D8C101BC17E301B4D37C8EC7DA0F797767C6EA0166C74411F7A5D54B7E7AA4CD62C856
99F314E11014CEC46FD5BB0C0B69A397A60D4DFEDA87B095341DF659CE1BC3A151376C2E7BE1
1A548D84F0F5777FA0C07DF33068C2EDB144719CEE27D1F6DB1FD83F254BE273BBA9CC1FB51D
B3ACA31D8BBE5AEA00F61C23BA566415E9A0E1ABC230F46E40065C0D9F2F7245C138149BE9FE
0FB69C0B945DC165176EDFFCABF56B9FAB33DFBE78966064DA91DB7706BB6C6F04AD34E042F4
C6FA48B0B9F96BF5CF68253F9AF738CF671AB6B553E23F34B6771E4BF150E6B6B0B170DD494A
8D1ACB6786CEF859F934CC7736A170BBA986EC19430D19B9F090ABADF9AC0943F36685966113
9C7645141E8A7A2DFE554F8397FB10064996783310500165171D8420D1ED8BCE593C42805A2F
9EFCB4B88D09AC7E6A4B23C21A84B94F823CB3AFE754E79B9C77D2C3E29D5D4BB0F29569875D
71D142362E1FAD2AD2186258D1DF52692311F53A608A276F70AAFAB6E301FC586B0F4C6D364B
C2F1815FDEE94EEE51BB72236F3D4B64DCECE6C7B21176CC09E6904DCC1FBDAB59260507D488
5F24270FE2A6F133D47CC2AF2AB27637ECF40EF51D8CC1352EBA3EF27C745663350C4EE97B0C
D24ED09A5BB618024436FAD4BC458A6B259BAE107DA6FDD814B646E95B1F39CA2C7E9EA5B156
A44FCF514EF96C5865DA6D96FA8876325A9F83B75C5D156ACDA42A69ACDAA7BB306A5807B013
38297F76D0CA3CA851F9178168CC5B1ED97E4723201DA85D59FA9E3EC837297AB2759B02F921
CA65072573A35A942DA915675DE04A02E5221B62D9EF635444A37E1686A816BC71F496678378
0A328F17D3F8D3754AD2606524C0FABD57F1D02676154BCE181F8B97CE2B0C0E0F06988F5AEB
5AA15E7B3A5F2080F7347D950D3B005E462336AAFF1504378DEF84AA51AA528C2CD232EF2382
63BFD3388D0FD290DC4558EAF24F56B0F74A674A3CB2E61A88F5F4E97CB9997B380B68572043
4CFC4362BA7B23C804C22793341388502F4AA4ADABE34DE967FCB82E12616A22067947F4CD26
AB2762ACE46046E73FAE30959005EB576A10FEAC6F307233BAC38DE2D70D037F56C0B0ECA2F3
A48D4C0CF69CAE3CE44B08E5B10D3F938131F5F5E6F4A9E211312B04709E73B246639938CDAC
FE24396907B7C5677335988E9D6EA7BE4D7F6850AD924E44D85D494023EF0AF57918EA99A779
34F389A5EBCC42E26B85E47EF7BCC2375DF221BB5E0294E3FFA8A51838D9ED322FB0979FEB0D
26D4E36244F5B0557EF0101B5C3D6241A1EFAB943FD5ADE870AF75E24F25772BB65B26CA14A7
034C1F69CCD38DE4AC79A8D0311978A8134810437E5A04B3363F16D4EE6D23853BC1298853AA
FD9C619279AB747475BD433D2186040A934A0F05B294D28FE45801A802DBD20AF0887B9B00BA
5C4D885643B7A645E990A49A8111E6ABDDBFF944070678E003591249551C1FD79B40795C8CE6
1F8FCF78D1BE0A44A2D32C199E46DF4A734206BD97A0954BB778C0BCA6EC76162FC4222AFEF0
4DB282A73412FFC5EF9BAB16CFFA50A8A259BA0FA1BABDA8BBDE95A321AB4196D58C12D8AF91
89EEDE485B3C951AFE3230189BADAF0652535CFEF04777F0C183489D90CADF9A6553473A18A9
A36EAE70ACD5E815C03E9964703BDDC7706FD7D14B668EA1176E438E49350DC8807A6E4EE528
33C6D110475AE6F96B6318A989B6BDC1D88D28C26606E3D71380CF186C2997E8194513D3F43F
9F570BF9C3CBF688060A12885355038E9754F89DBBD90C25FCC2922F11FF1934AAFB0EA11F8B
DB6C3257D7BA0F8E2AC7365A9FC76D3029325506AE25D8DE203D295617F85EBFA351FBCD7956
11D6FDA7F3BF6E34DF41B13138ADAF0F570BEF6784FFB896388ECC95087E0B7F425B6758D8A5
98D41A87B3F0075508B708675C56726022F450D6DAA8B60134BAD5328A36424C609E99B31480
01DBC05881FD423B95EC9772B9AD22A992062736432C390F55D692C90AC64A1272F3414C537D
FDEAF1BDBF157726C59083DD303A6E1DED50C6F5B94C61E81F9F138FD8AC67B673AB38E5CA16
6611C6726DECC1C0647D6188085056CB939E2B1D66E25BEBEAECE4B97DD342078BAB4867B7E3
CDBD2C68B9E7D88BE56D90573085C9DF10E10B19EBE83C8A1C41F58BE78B93040C928FED3B1E
98F354823619ECF7C5764F2D98E958A375A5F0CA5D884389DE854F91A766295B01FF8CDD420B
D2A52A41A0759ECED87DEAE73D27A1DACB0D0F7E4658FB724BCCEFA08B0C3D5BDC9CDD6A9463
6F8B7B4EB66971E8C599D5F15BAFEB89258185E3E935C15CE57AA6CF4F2CF79BACD605747AC4
EB081FC98BBF61D2623350375B860155B90EE6A159DEDCF7A33604D7E83C50AE7804E9A43462
2239C5A7D891859D31CF7A37DF61BAB489D857E93D5C2C8CAEE4C61E7F4E3316DC35FF616189
7D5529EB2656ABC3367ADAC4EA3342C2EF308DA183C6F40402E231586A37198970612951B383
FBA8E8C375123429CEC97A52B455CA8B384913E1527E77EC48AE423B6BE28F3F8E0FE77F8D19
7BC6FE350D817C8858CE5BABB5A6BC1276F905BA942A1601784CE8E8ED96DDEEE65D9EDE4FC7
D5BC5BFF2FC3A966FD25961A430A063DF3D8766631774C9625F1CAC03C135B6B122D4B5F68C0
659B1B2CB634D067218E127A589F87FD1EC9715443A08284837ED2BBDDE3325B7EC288992F1B
5166EA175EFA6FDA164E8391DE99E4A88F43199C3DBD617667D6FCC2561A1642F45D76564EA5
B0E925BC960CFCA1194F67743B854899EF834404C8596279150CC61909F367EB17924CA9FCEF
E89FCB940710E470A5E7C9CFEBBB8B8EBB2CA8CABD973EC4D8F32DF8A39E6ED4C520BF932FD6
7BA02EADA63CF55F33EC75216F75E29E2D6937379D61EFA2C7F83A187FF93E4F17A66CA3ECEB
26B9199E1915922667CD1793FD0842E6648FF80150D7A0A447F5FFA2B8C36507F7DECDE7EB99
2FEE6E9C8E32D9BD971771ED9D0B3E95190550058FF0E6F80576ECCE287AD895AD56DC8F78D1
9FD04ED854529719471333B1C313A002D8166BB91B2983E99A09812E9BEB52F5EDA7391DA5A2
FECE694761350B089DE41343F04DC45E1B4231F265844CBCD770EF5BE05B2F97434CAF711D61
6613108312D08A9B4D3A55B2DEDAF47CD5BBC2718DA7D18A7079FAC6A7D4F7CB4F09D4B027E0
5629C14EE77663D8B29EC009924B41F873E4024E092DF7343A1864C80B6EB8E4FABFAA90F5D3
9154FC4D14438A502E60B5AF432A90C7A48C523B4267534F171FDC02E57B9EF3867758A97BBF
9CDB99DC41758BAD49A7D780FA0BF66851B52D46BFA8B96E60BE89E4A5E78BAAB8736ABBE338
C1283CC1D2BC3A07F982122A3289E35CB097BE9C27274BDF3ED19EE8628BDB48FD587159E7E4
84F6F5005F22E636719F9327173693810F978816F739574DB0382222B9B717E394DA21A4F80D
5A95C552264DFA0727FED213EEF886C149D392E900DC4DDD0CCEC84C5DE5DFA3DD5F903B93FC
649FD661BF20618BCDAAEFBF9C71CFC11B8C68143068B78FCB3354FF5555A9774FAAE88328BE
D4C4996679E9285A00C12B32757C74E8FEF1ED1EEACCEA315D56DF2E814F2C8D75E80D3836DB
71C5D1CF0055A01C1EF725AB4858D73CD089B3A66968C2604F97C861A7484BE84BF95DBBA43E
A6EA2C455574B715825DBCA643BB023B77D3CEC870FD30899E7788986813915FCD3F909E3D59
6281B4D858A29465DBFA76EBA156B0761180BEBE2A6C218A51A67D400DCE29A3F19538DC28F2
9971A8B01B4C27A42FD9AD8A89B7FA5F188D3135B5567C8E0B87912EEF813FB15C63BC9260EC
3D7A6909D2295C0C31DC77B0A468CA4B7F801BB06A0486470201437ED678AFEC280DBF80C771
823FB23A5AF549CFF74620AB2EE1EFC50EE09F4A0BB4AB05579670940D20F01C61C7461F08DD
8560F5C1E0C73E0DBFC8532155A5F92162F05D19E6634446EEFFB764B9BF4B5E695E9B4D8037
8EC8406C588C3EB7C919BF154BDA4A878B45479F6111798DD6FAE11A29EA1E44934C82E6A68B
0025491A69037808D3FCBDCC7C80ED848EBEC3F7CA954CEC873F4E404A699A7A980BD66E9E81
2BF39C85C55A010D95B9AA147E5826D0DC8EFFAC979ED602F7414DD64CBF2518A5B71AF4B6FF
0F59657D2412B47391921252D0A723DCF2EEE67AB89F8C12D3EC1089DA75F364E4E6E1041007
2144CB14352C56F9D8D180E45861FDD26B68A02B5A86560F3EADF5367D8B06876ED8F79BC79C
3602569AECED48BE6423888D86C3DCD811CC26C29239210EAF574CE8730016A3AABF2BAA31F4
8CE3BCC43DDC31DF81883CA92F2CD4A7B1E136AF70037AD22207F8F5E5EC06ECA4C9EE9B199E
15590E9F59D11688D22CF11060E87423F3E01EF613FC230FDDF599D1277CB7FE6AAE4312282C
4BA8A28D794628136FA0C5EEE83CC6ACFD043AE7FD985D226AE4D91D00218964C161C4A0B147
E58A4D143917A592A8FBBA3215D1E3AF1CB952BF418C9B07A5ECA3457B591A0E9C49234DB043
99EFCF129AEA7A96694BED7073AE4502979F2F0286085B799669DC8EC22ADCA51E92EB0E2633
651E822F4910B716DE01CF09B631187A6B9935D43DCD1C68111B850B7F21EE142A7A48836D8D
E7F4E63D72B515728D9AFA7B11118DAE383ADF97CDB92C17075F437FA0BDF5250C251013B612
C593D93E8F9ADDEB8C03E1D38F56E6EC42C7FDE744866D4B873B725074754CDC10CB0262403B
9740596A661A2DBF057144991F0A1A4FE3E316095978A88CF38BB1B5DD0FF4E8BCCF1C7D5636
9CAD0C2EC29D56A6CD2535EF610026AD120B4BBD5151EDDC7F385B229E79B22121416E74463C
4D5246501C7B6632ADD04F8C460C7D5A505F29BB3F45343ED5D576302FF9D8EC1F400B190922
BBE646CD809A6BF2E0EB9E7AC66422EACFFA93876695B8E88ECA149CE738586A0CAF105CA587
8572E58ACF6D523F2BF3D410A8E79507A0E480AF8C618FBB459AC768CFD240F32B0B69265332
20552D8325D058C2D30B5A437AAC867CB5BB6C007717FF089C65FFA92C5C8D159E0833C54C53
040D448B93FB48B5FF2395E4774BA3764B6EDFA7EEECDB2B9736E5D7E427CE883C67AAB05B08
26CD91AF342E32F2179CB109F2228138978ABB9C8EB9B555C1269FBD12975929E91AEECF0915
D6B2068C7B2DF726FEC9DA54ACBD64AA808FCE20A34EE78463C4A831E33F94A268C5454A1CD2
E05A662786E7392B24EF94B7EDCF28428B52FD85DD03F7B38000F38C4C80BDBDA46F62B9A964
FD0B5B33F3B8FABE28538632F1B229418E1AFD6FE9263CC220BAD30170816AAE06D54541F854
B68CF72E08DFD272021DCE628962A7BD962564C054C0E6AB2742846899F9D0DC9424D820FB28
9EC582BF3B56C48D32DB2768406491C837B125B62AEF198E85D6D579899EE59B53271EC329B2
83DD4C498294A27DF14A783C517288E3B6B4CDEFD2489398B71A712AB154E55499E016D7862A
14BFBCEE308D95509CCFFCED78FF3C55510CF91DA90F10D3203706F0592400847639F47C8A70
D98F48339A3D7017A8C8462D6316BAC13DF9E12A49805E695A1C632C63E223A2799C84DAD656
DA6ED692520DB379C727B8375DF9D548F693BFD9509B3028B1EA529AA6EB737380A4FDE879A6
CC623AE8F5F992523E167791F3D33BFDDE0A516C6901A202A5C154A0E69CC5FECC0B75E61B9E
D91834B659805E8B7BF32FBDC4DAF5520A27D508689F692F1D69D4E0B00DD7AA134C1357DE1B
F8804FD534600ADA4790738325759F35D9DC3B077FE48817AA57CAF862713E617BF7BF09344A
74BD13F118D26D30C1511B20327C460D270E5475371AA26BEFFEF03B66564E0E669724E38959
73D98C7150F035FB52D8D328EEDB5C85E7EA7BE5373E514BCF881C4147DA0C1656523A95B63F
86B3017B93AF76536DC19979B9F617CC855DC3B8FAF171780D352F93AA78C3F25A0AF51FAE91
878FDA9DA3B094876526BF6D68A650008DC13D0F17F8445236FDCE4F725A82AA5403B568F65A
087169993A3E81684234620F58568D2801F344F5667140F9DAF63DED0AE4AE391F717AAE8B56
6347257987D49186C82B911A98F94DF8292DF7ECD76FF09EAC1400B6C34658B9025AC42B7DBC
EFA9173258680D929ECBFAD99CE071C35DD8D34126A036DAB27B3F2A0F4B79A509433784D317
7324A8DBD271401AC904E072ED118331DACC31CF4EE21D1A9D805971DBE8D17AD377FAB5450D
1C0448C6C65FE4E8EC9B4BC1FFA74D7D0CDC6D0CBF0C1F905DB3F02B944281CCC10165CDD730
2F4DDF57865D32D47C8C26FBD0D410E4DEC820B5D6EA0DD6B1769AC0550F15AE88C0EFEDBEE8
4B75949453669DCF1B447821480ACFE750D13F8A3E574F7687949B525B278DB75C3102FD4706
6AFC56C4588A258813C3C53DF147FA5F225E901A297E5E322920F131093304BB9B2895E46DBB
1D020EE684B08C64E1A159A6829DE9510E5E985F53454EC367507D4B84B80E28133254B7B60A
C194C776F734D6E8837CE23EDC94531AD2E46DC6BDC1E921CAB4FF785DCAE7B556706FDED6AB
4763153EC5F4B2E10491E5E427DC327C21B26DB2AC272588FC41FC5490A102ED1C2AD82B0811
C34CC8DB42CE97B4B24E194CAF230E58A04943934351805A9A0C5975E98C0F11CB0AE28C5ED9
8E52CF035F823FD449436B20CC0A913B7606A6FB2CCF4C7A12714C99B60940CCFE9CE26B22D5
DC1FFFA01C8E4A04AF28C9CA3F2A7CB2B33A725C456EFF23BB62B69878F8FB185F653F41C596
C9BB7C7A17CD9B5A07FC405AE7E182567621FA75FFBCFEF42E7373B2B15CAE76D7C07BE16A23
086500A789CCE988CAB9B321CF969A79132544B7D9503C7D30A4C86D8601743449D619A5CA87
879AFCEDA5D16FE6B31E17529D17A95C027D481B6C11FE9477412DED852C15A026E36735239B
F5063B7FDA776C1282B9F50F602526F355AC3516E5DF327C227EDD44E453B27D7074E0F9D9C1
9FAA49D3DE5138498B0569B4FCFF2041977F69484CCB916856DF1F07E40B450C250BE68FFCF4
D159FB8F1208EA8904567BD552116A28A95425CDA95D4FDC06E59449065B65DD2B7047BDACDC
29A66C8FAC9BF2EFD6886FD859BB0F256B21EF2AA03E6EFA6A614B222B84B7E6BBF2824713CF
D214DA92F04543AE0011D51A50FD08C4FE4BDFDB9E184EB32C399D3A2FA71059CFB9F6AE1CCC
DB4CAADBAE20AE4F65BC58334164F127DE5C476EA5BBA3644F2F24F0DBADD3D1E80DA16A6483
64C1BF86D0A76523317C7D4F46C419FA31BF86D5B700CFA640273BBB9D6C8AF13E7CAF3A2510
01F06DC2D4C8F57AAE5A8B4E4379163D732756D3A7B97C778DC8637D06EC36A951DAC426C14A
58DF97D2777E7B45EF2C3F9D35202015E420C5E35301AF195403F3ACE5FD4040ECAE467282C5
1E7A6AFC69936F6D81216FB0B2E3B3DD942DB10D9BBCE24E186AD3D46B49414CE148AFAB9C95
8E7339664510E2CC5624DB80A708A040C0EB2E48E8CC67EAEE7856DD36BA948C8A8AEB120BC3
28BCA0A629FEAEC6419D70CB8469D82931C1B08B8EF46865819F4D6E3D2A9BA5EA2ED7E7221A
ADB2660B474E576DA104AE298ABAD60F6607D9D03C9AF768707D5F2F299927D14BE80E258469
066AD3C2BD0ECE20975A061977CD4A1246E6B545E7E9788BD51E04DFD285F9636C663D7C6AF3
64ADDFD0336C6CD6A46A43EB252D2B72DF3B52050D4C2B20DA4F6CCCB1C1CA85EE1C9A5501FB
22EB7FDFBFD0838F0359E295D3176EC8F0A2A7A262155DD2F20CD2632FFC30E4F274AF926570
85147A75942D1611D5B0407504708CF782398C366A02AD6A8B103DF8E615126B33DA380BC2AA
1160FA63665B883A5A4A7CE7514DDDAF8E65508B2B6FC341A00DE2E976C07A499BC758ADDA72
B65780DD06133027E1D7FAFBD4CF7085091ED9DD98D91E4EB4BC0BD4DFBEBC947544A96F47C6
4E1CA2BEA3E739A65BECDE6B2CF0713743B881F403AA40AEE5A726A8B54659852EA518675CAE
5089758C77C82EFBA56DF329AB46166154F0780319347A050002319438096D4EF7F851876CE4
07D436299F7D3A0FB6E8816C37A028D62426BC615FD635060F1C69E3E7FF6D9262E06679E415
088687B4E65813C86D481C41B5D74E0C208882B13EF4EEAE0C60850DC1BF54075F41763705E3
CFF0B9FFACB9E2922B40AA7209970FA5F3563D7E6E4D3D2249E7E946E97B5FA40291742EF9BF
A2DC7D4E5EE1A25F6D0D930A50262F17F38744D7A07FA9B6DB3C4D7CC96DDA023AE2F3DDC571
FF48135434E354979EAFDF625460CBEA8B65B63BC612E44D05CC3C3FB186403F994FD1919A62
44E728857A54DF535AE149D405CE6C83C96A6DC117BF178E088556E12D3FD88017FD2C031059
1A89077E0D6455E76A3C8AE37B8DF495083B9EDAFAC2E3322C07209A21B5C33AC6AF3DBB527D
C1AE916CBA52E68C2A851EB073D09CDECF8C3AEC94F5728F202BEF1083215895FB76B791CA26
6B925512AD89EBDB53AC81DCA3EF1796D1E91AE23E5C60DF72549D625AD1BA68D4B7B5C338B2
1496653F61F735A9D60C437A6397899304B3EA36BA2AE138A700681EABB177D32CD0DCC8B226
982EC3BB7EC84A831569BB9A3BF30FB4A56D947464B1F7B49DDA4621907F605A238D6C5A1F21
439FB67080A3AA1864CDACED6A37D1FDA3E95EB8E70CB3B78D2CA77BAB36D6FBFF8CE6AB6EA9
78C1C8FCA06C3112FA831E693BE7562B859AAE3AAFDBBD0B119392037F1658D9FF7473B2D4EC
D67B80F2EC39CB32391E41E2F8466B9BDBE8E134186312F0C97F2ACD4EB52F835D00880928EE
1DCA94DC6A6E25ECC61B5E549D1B8A2C130D61EA7A42465F0EF3E3AB242799D2639AE4B2CD23
6F195D3EE06665DC3674C8CD681E0B49C7E5B95E4DDFBA0FC01DFEC2E17A77F16116AD14296C
0825E9859CE22241EFC60ECDC3F4C56D22EE448F8263394CA1848F95AE78D46DA9FE03328476
8058CC5A4CE269EBD36B01D04B772864E136FB076154A52C165A9A0ED6A9415474890E85738F
C1E112B733B2CB78D73A294367C4A6B33D15CCAF851135BEABDA0AE764091A3EA5B65D0BFB32
36760AB084F8C9C16F1E93A7531EAF2130CDB62A8DB7B42040D0A92F2B20DA2FA00A73738BF8
AA9DB2581B00857BD6D781A2C78D83792012C83D4908012347ED651A2FDF54C70D53910D6DC6
D2D278872C6E7D58019E8D04407A1A720FEFDDD6EBD79B98B77A4FAEE6EEE00F2985F8B674C6
A27D04C992B7E8B53A1E621F9D3C66DEE950E1F705D02DDB78A081CFB94006AAC8105F5D3E46
5796D2C10018F65869FF73D7A9ADB035FB37EDFFEB469D7670A13A43DF3CE14D277AEABA3833
83D36460880D924138C8A8374AF1031AFA2654D5A118A82149072BCC38F87096D240B55679D8
221041F2F7934C27D3F1B543B6761CD2D2D42BC27D7C16317D651C2E041ABFC027D3472514ED
04642E58C1E729945761DE2758A438569DDB55505284045153837A29D3BFA889C6AABB26C108
F27571D832CD930D39CFE96814370B2EA5A39376975E378B752E6E14FF1322942114E4119A30
7CEF2711AF296AE3F88D550163EAD08B2B515364854990F25AABB23D975FC84DA81CF63A416B
32AF608508DDFF86CC694A6B668B3F382E3E3AF223623A65AAB3EB16D000D86D663EC6031D2C
DE50D54A55EDF6C7E47B4903C9922BAA00D2C00798CD367613F7549D9873AC4EDD3C2E8A044B
AE53643AAE392DAC91F6D335112C2DD4B188C5F1EF1E5E42457E4C2F2D2A282EA3D2E9BCBCCC
6DDA43161DF8F8985745E86461108E080F647C09B183ED67257381C512947CE954FD786F0B86
A62E40327AAF77C3F5265A47BFEE2F3919A7073E84C49DB01295C730AD18F45364E2F19BEE93
8B7C92235D9E32754139E8C2F64C738A5716EE5BF2C68D09DA48166FB2490EC874C723D6E72F
AB7C597CCD0ED2398BB9D99159E2D4A3FE605ACF6F7A5D4A00BB9156FABAD02D727437448B75
E6F08F1C5F17B251412C2E698CA1FD7D8D7A80AC6C7343CC7CEA23245812247F35F0F4480E10
A1D8F9D8446EE41E435166DBA0CA3B29155146C96C05FF1FD2661DBFD9AD2A7341362BF8C2A6
C10B91541D2E4CB6F8AA01F1C90E118E0DB81FC03048F54677CF96075EDA05B928E200E1620D
EFCACFC777BC76E3C911229C64699560D630BADFFB00206E4DE61E3D06959B2C4486FF5DC7BB
B22C634D8B136077E5062096D3C99B142E2D1AA6C26E58AFECDC55A8B90441C0459140363FFE
8928C20BF64C8BCE4DD15EC806A2AC7CB1DD58E67B69A34B28C4164BB0262FF9267544A6A905
AC3290DDA8F97CCAFC12083485AF20B6875B355D98CB5E45DFBAFD80FD63DD590A2EBE0B0429
2A1D37C906FF3042E608B3D983DE1D829FAA8B658584600E5EEEE90FB0CB13EC9633B148B696
30B8A4617527B0049E107F4F7E14BF421DF26B08BF193EF2650E7930F567BF3A05CF55F3BE9E
651C2273F5DB3C4D08D9100CBF5F5672C702696D823A43082A79B159DFD315278DEDA56458D0
B8208C7FE90808E0D0566CC2A176131AFCA80DC312C9F7E4C25A0E949AA384CE254B885CFD9F
E74E88B40862238868C3F7D1B435DAA876B5875563C3C5BB3B962BAE3F9909BBB96997A76533
95C7CBB41D74347B78547085368A5B2D18CFC3AC56DCD1D9D5A53EA63F4241F1B35C15913F4F
773A48F42B4D04B594F33FF14C0B16989C4354C2DB18EFB3132AC64D02C86EA8198461F700B9
8BE371A968C0865BEE44E8DF5A7AE98B738C034CCF07E1CAE4FBFB8A50C9C31362845BFB67E0
0732FC33378066D3B8F1D69224E627103CB706AA5B6F3E4DEC74445625CB052F5AC48681CD3B
204574A1041CEDB74A51D4D21B37D465593A7E8F7AC1184C5EC7AB9875852D88E15AA1C5203B
BD9DA15C25BF2E908C97678DE40D9A8226BE09A735156D1AA028955ABFF46DA51C07E8E1234C
9FD06F9B54C0E8ABB2AC28721F5CE5473077BC6A4AFD0EC98F4FC29BCFB29BDFE99D931BA28E
200F5D58136F63C5D18B4917F79F9650343873C44F8F9F699A0F5495237E2E748B3E5C3DCCC5
9DDAF98E1C4F5252F0C52D2BC4399510496E4844A6392F984204282ED84398E7C8862D9462FB
AD609A8C85945B758B88E37A2A412380B6DC884BCE142DDEA569227FE306C6B4274C07CDCAB4
B48EC1806E45A27109D0B142FB3C84019F4C1C275E8309696F966705B06292C8F8622FE8DE52
6C591659D7780D424E8ED1D83F59A0289DC59556A84B5EE4BB34DAD12A92974CEF6901517285
42E222B0C32B05B2C3D819A40C4BFAD0E080E60AA633D91ADEB117434C58A7BBB334503FB9D6
85166DA7425F35097878325385C28C2F1B10CE6AF452AE0FE66C89A9426D1B25196D06CB9271
C6E973F2FD6722B1EC18162175A9C00CD155FF3EE679FFECE6889B2EF40D682FA2972EA03622
24A1C43282A08753A5205D3BAEC16DF17AB6F6162F9A61292F32F2D9DA34A45F3DFF377848B6
E5CAADF938BBC92D8553556817316F4F8F8D54983D8D72C2145D4D83682CA5D528867E8CE66C
050FE52B0269FDC98E5B48A185B979B45CCA3D99C870B1049461007CA15F4DBCE8A306D460D8
F6B44A2506FD7217F11B69A0077D3B7C2F016ED954BA5E58C9B51750E4FBE8E88E4B0AD59B1B
9969BB9494CC19C030DDF9F586D80CDD03FDA4D655D90AFCD4CFC93ED8B70C13FEB1B3F052DE
FF4EAC734E8C1FA2B4AE1423E78E529443074F58E3F5D84DC1E8AF60866E49AC96210FB526F1
B4DD10AA19C53B92973CA6E13B60D319FAD574A46301A80D69737B9F60B4466B94F4AC8DF508
0C92A7359ECF6883D87D1BD45037F84CDFC93F9CF0B7D8D8795EA37B8A0CFDDB837D8F9A2327
42995FF55E0C38E2CC9E57E10C5C5D6E9EC93650DC90A82F545E54C66133F9381262E21CBC52
CD865192A781BEDB71AF318DC25239D64CF458839FC2C809EAF85AF1AD027E0BA8BC70AEB164
8F345E7B6043BF59FE71C0B20F8BD21CC93C9A426E80D62AD487A60654EBF0E364D99B90574F
072C52775B239A0DF62F256F44870302D077D114DBF83715E4A07069104876317FBAA1F7ADF9
F99DDFEACEDADB48B397B7EB2A37E190729F6D31474F4F6E2644C697E0FD8836DE337E05A8B1
B8CBB7A5A6BE292FDA3FEE754C5F9FCCD6E4528349392FAC86F7E6BFC953ED5378B7C5EA0D8B
2AFA34DF6360198E5FC5ADFEB120D9FC498D8DAC8644E9643AF39DA434BDC546FD2BCAC23511
AB1687B7943F299285D071115B4CBD650F356E75F478C5505A7FF036BEBE3682C3A00D047626
1791CF08EAAEFA6F9333C66CCF5C9E59C14829B853A660F3FE3CCA0F1F869E3A31D089E373DD
A04D765D25FB0B6BF205A9FD881F00E99113C5DBFD2FBD7ED608C32E9D51FDF6454557DC52D7
2EECDEF0AC2D8E89706809648515BD4037379C6057BB89AC4B6768DBBBFB672329D3C21036A4
804682C6CFAADDAC7723C715842B25B03FA1F12A2291125F34EF7DEDF897EF4A7506F804E337
0814F4B62612B35ACD43A33A3ADC76815D29178EF7B6D2C170FCC1AF75A9157239DDC78A5FAD
4B7B759755F63031B1A7A6F6C9FAD4CA3B4F36E065E3BC3ECE67C990411940787058AA52A00C
51E29250B624EAF70C9E236898B1E2491256E9C4399ED8ED5B19F5941E76F51B8F16EB0A96A2
9FB928E35ECFDCA1BED3B12D5B5CA1D55BB2E4AD69FA1BCEC3876142B7A194388538F5BFB028
402E52505302F482BFA1D6C2492FFF4C7C882B6260215B52279E25E8D797222A2E4473CB30A4
489A6F2C566A79E9FD940BA0E15C52C8044B4C725358C667522E784194F87C543D9F77342757
2CEF02F46AACBB4EDEECC15C3E813C67E68EC8485112A1E19054AE9B877B857D9466E69E81F6
C24BA540A3D716F2E92659D252692C1D5DEF79BBA8C6A7BBE9EAA7CFB7721810FEC93F176E8B
9DBA3BEEEAEFDB577C14D52D2676566F0D04DE6931DC8ADCCB09022D30B84E9703CE37845966
5946CA535D26B3094D1B493A5695DA6DCF79527B841194790AF65EA24FAB98EC08F519743248
FC600029F2469C8FCCB2B27182928BE3F1AA4405E14C7AB842A370E45D48AB1EEEC9168825E9
88147928854FCF974821B19B65D9FFD57333D3EC10B21588F04F652A218D8E5CEC3ED25BB6CD
5EB1789E3CFAAACD95B72455C5BE8FFAEE0636C0788A587C992E6D1FA1E2D5EC8EEA82B6F75F
413707DA0EC878352E92FBB1608506CC3A4D1F676D364524C8B72C3AD5867E03B7642F335B4E
0DD6B59957CAA5C0131C8A58E0F95EC0DC6D75837291A7C1DADBE3F92642D2CD4C0EAB79CC23
7BCB33E4631BB90B0CE4D63A936348B7CC37AA207BCA6410F010890F23F6B3F6DA3C7A0643A4
44D2E3D226C754C1598D72AD25C25BF5FDC1895E6D23B9632646EF4F314BDFFA94971BF6FCCF
20EC37B31520221BE10025C386A8A1B3280BB47FCE113BB4A5F29AB70059611EEAB412C0A969
3E30993FC944B38B11211594B5AD84B0D622255A372F56A150BDA57451FCF52F3DBA2DF25BC4
16759E32B7B19309C1FA25AE1C33D668145F2E645107CCAC86E741342CA4301685936E12234C
8D612F9314090D5C9209F5D154E678BFA3985B03CE6635AB80B8ED2630B41D7D223E6ED1625B
FCC417BBC3C9E5BCA6256260A06923EC1B9D2DA78C8B55B05CADB5785C838CFF582FE167CFFF
88167D7FB3B90B276F5D6F78E919FEBE8F9B58915129CD7AE5CCA6CA9885D22CF7084994D101
B81A675D0314C93041B5DA1899B36DA5DB30676B5F1FC0F3A98A33916B47E0496E3DDB771098
9AAB7642A1F77E5CF5EA22F75432DCB7DD2AEA6FC7BF8C9FA07C7F28F7D37CC13D3586D4EB49
CF579A95DD3ADE1DE06869687639267085352DAA0A19E8F95E4A7E31FF0D17CC87373690D263
4852D465CE0FEC652FB6D710163C738CFB030BD4935EFF80F7DE7D7F06F0FDB1F4C10B07938A
C60C74E442E1F3A6BCC8BBDC7814B6E710C41AE1E157538871AFE3518CA8834A4B4DBC59CCCB
6DA74715ECFA03E98289479C36D00DD0D125B12F63B45E112C7AA1C5E60B986E74E56CF95C80
198381207AF0CF5F17A6635E2AA89293E67D2C549D110A2A57C02C581166747BA758DE5D5F10
686029D7F0A82E7E4889BA7160762431E00091524EA5B12C9D4493F0CDCE0B4DD38EC792B4A9
2B0DC4539A51FF1D613E75D981BBB9C20B3D53400AEAC4970FF843EFCE5EB250C1283AEB8315
73AE15427928CC2A9C0C3B04B7CEF0DBAE549AE82AD2FAB68F5D7463420EAC2CBDF421BDC88F
2A6B10521913C6BFC6258598EE979570E9E555F475B1B26721F94A5462135E9705FA27259BB9
564253D058772483B35A487ACD624B8D9FA02EE6BABD73D308EC29A30CC32BF271CF95B3B070
160E31B8649192444A80DBEB812D1D4F4BE00FFEE6BF7E4CEA75A1142ACDC28EE252228DAD93
7A69B3580830CA904CD6F5CD01977F6FBA3A13E89667DDFC777F48DB2736D78856BAEEFC2E41
C82C82466D361AA2D02FE20568F584088F4038B72E10695253D8E095DE4288A48605FF431809
8801CD4FCA473F8C3316E8FF9CEB463D3AC98EFD0E30EB743E250B974E758E86DF712E13453A
E6882333F16696A670D28AA612FB9A03D46C4A866155D21AE216E7017F06C6459708EFAA13DC
465BF43EC202C8F556945FDA8F0E06A527A368C577BD0E5857F35C0AE8D0401EC43D1FF17760
A7D9893DBBCFFC86BE0747E7E6E07736EF0146BFF75DE5715E45F8EE823070433000BF015DD9
44265CEE7BA9BDD434A1D78E419608A4B19C0F74CBBA354BBCCBC13D0BBE4BF95072C69762D2
318D2E637A918ACA900ED1D59011198197E8DCD7D1CCC1F43890453AF9F70F821234C94E6F35
5E494C38E279E28C60BCC6C4132405B8CD1523A1BD77A4CBFA12C6009F5669AE3363A405EEA2
8E7A28044EC8B461B342654B2C24D50F43CBF0887C60C225409A289EA660B77F2286ACAFF8C4
656D4A369D39875D0F10436857033D2C5AD5E2619557B4F2C88A753249C2DA0552BAF19916F4
6F7F3A1F1356AD2F047B55F002D0509E266C184A77C6FD56071A28089B1082C0E80985242C8E
3169E754E5CAE6AB2EC06B5D8F1189E325485950ADA8A30F12BE6872D8393BA32C1ECD6A80DB
0FDF54919E9A7D9DA15C1BB823881033ACA8C21F3B806722F5277AACAB4A4E80222B3536E50A
2E5BEE34484310CEA6573B48F992D2B361B13F3BBD14A1E65C58B6D71CE393C3F340FF9806B5
4D82C04076AA5A4343E53785B3BED4C8A78593988BF3432A217AB637583E2898257BE5EAA11B
84231F6C9761F74DC75FFCD351F3C4101A69C98877EE17AD11541D7F57F6F5293CB956A7633F
541EAF253262699FC79E4A396C5D3289C3CAD0C31AC6CD59E794C80617E102B306EAD89EA036
85508781C79645ABF8BE697710D4D5821D1512467B66DB602A2DA5E46F646D685E09E0528C47
9C6E9D6A5503B99104E0A5535E0A62683E520063BF2698701896B39D26FE9D2FF2BA0BAACA77
A75FF905B3CAF7C7C8A5243C54469EBA42D0ECB15AFF53770C93A32B18205D2FD601F88A36F5
3B93CDB0A247C4E5750000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginFont: CMSY10
%!PS-AdobeFont-1.1: CMSY10 1.0
%%CreationDate: 1991 Aug 15 07:20:57
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.0) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMSY10) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle -14.035 def
/isFixedPitch false def
end readonly def
/FontName /CMSY10 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /minus put
dup 162 /periodcentered put
dup 163 /multiply put
dup 164 /asteriskmath put
dup 165 /divide put
dup 166 /diamondmath put
dup 167 /plusminus put
dup 168 /minusplus put
dup 169 /circleplus put
dup 170 /circleminus put
dup 173 /circlemultiply put
dup 174 /circledivide put
dup 175 /circledot put
dup 176 /circlecopyrt put
dup 177 /openbullet put
dup 178 /bullet put
dup 179 /equivasymptotic put
dup 180 /equivalence put
dup 181 /reflexsubset put
dup 182 /reflexsuperset put
dup 183 /lessequal put
dup 184 /greaterequal put
dup 185 /precedesequal put
dup 186 /followsequal put
dup 187 /similar put
dup 188 /approxequal put
dup 189 /propersubset put
dup 190 /propersuperset put
dup 191 /lessmuch put
dup 192 /greatermuch put
dup 193 /precedes put
dup 194 /follows put
dup 195 /arrowleft put
dup 196 /spade put
dup 0 /minus put
dup 1 /periodcentered put
dup 2 /multiply put
dup 3 /asteriskmath put
dup 4 /divide put
dup 5 /diamondmath put
dup 6 /plusminus put
dup 7 /minusplus put
dup 8 /circleplus put
dup 9 /circleminus put
dup 10 /circlemultiply put
dup 11 /circledivide put
dup 12 /circledot put
dup 13 /circlecopyrt put
dup 14 /openbullet put
dup 15 /bullet put
dup 16 /equivasymptotic put
dup 17 /equivalence put
dup 18 /reflexsubset put
dup 19 /reflexsuperset put
dup 20 /lessequal put
dup 21 /greaterequal put
dup 22 /precedesequal put
dup 23 /followsequal put
dup 24 /similar put
dup 25 /approxequal put
dup 26 /propersubset put
dup 27 /propersuperset put
dup 28 /lessmuch put
dup 29 /greatermuch put
dup 30 /precedes put
dup 31 /follows put
dup 32 /arrowleft put
dup 33 /arrowright put
dup 34 /arrowup put
dup 35 /arrowdown put
dup 36 /arrowboth put
dup 37 /arrownortheast put
dup 38 /arrowsoutheast put
dup 39 /similarequal put
dup 40 /arrowdblleft put
dup 41 /arrowdblright put
dup 42 /arrowdblup put
dup 43 /arrowdbldown put
dup 44 /arrowdblboth put
dup 45 /arrownorthwest put
dup 46 /arrowsouthwest put
dup 47 /proportional put
dup 48 /prime put
dup 49 /infinity put
dup 50 /element put
dup 51 /owner put
dup 52 /triangle put
dup 53 /triangleinv put
dup 54 /negationslash put
dup 55 /mapsto put
dup 56 /universal put
dup 57 /existential put
dup 58 /logicalnot put
dup 59 /emptyset put
dup 60 /Rfractur put
dup 61 /Ifractur put
dup 62 /latticetop put
dup 63 /perpendicular put
dup 64 /aleph put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /union put
dup 92 /intersection put
dup 93 /unionmulti put
dup 94 /logicaland put
dup 95 /logicalor put
dup 96 /turnstileleft put
dup 97 /turnstileright put
dup 98 /floorleft put
dup 99 /floorright put
dup 100 /ceilingleft put
dup 101 /ceilingright put
dup 102 /braceleft put
dup 103 /braceright put
dup 104 /angbracketleft put
dup 105 /angbracketright put
dup 106 /bar put
dup 107 /bardbl put
dup 108 /arrowbothv put
dup 109 /arrowdblbothv put
dup 110 /backslash put
dup 111 /wreathproduct put
dup 112 /radical put
dup 113 /coproduct put
dup 114 /nabla put
dup 115 /integral put
dup 116 /unionsq put
dup 117 /intersectionsq put
dup 118 /subsetsqequal put
dup 119 /supersetsqequal put
dup 120 /section put
dup 121 /dagger put
dup 122 /daggerdbl put
dup 123 /paragraph put
dup 124 /club put
dup 125 /diamond put
dup 126 /heart put
dup 127 /spade put
dup 128 /arrowleft put
readonly def
/FontBBox{-29 -960 1116 775}readonly def
/UniqueID 5000820 def
currentdict end
currentfile eexec
9B9C1569015F2C1D2BF560F4C0D52257BAC8CED9B09A275AB231194ECF82935205826F4E975D
CECEC72B2CF3A18899CCDE1FD935D09D813B096CC6B83CDF4F23B9A60DB41F9976AC333263C9
08DCEFCDBD4C8402ED00A36E7487634D089FD45AF4A38A56A4412C3B0BAFFAEB717BF0DE9FFB
7A8460BF475A6718B0C73C571145D026957276530530A2FBEFC6C8F67052788E6703BB5EE495
33870BCA1F113AD83750D597B842D8D96C423BA1273DDD32F3A54A912A443FCD44F7C3A6FE39
56B0AA1E784AAEC6FCE08DAE0C76DA9D0A3EBA57B98A6233D9E9F0C3F00FCC6B2C6A9BA23AF3
89E6DFFF4EFEC3DE05D6276C6BE417703CE508377F25960EF4ED83B49B01B873F3A639CE00F3
56229B6477A081933FEF3BB80E2B9DFFA7F75567B1FA4D739B772F8D674E567534C6C5BBF1CF
615372BE20B18472F7AA58BE8C216DBDDF81CC0A86B6D8318CA68FE22C8AF13B54D7576FE4CA
5A7AF9005EA5CC4EDB79C0AB668E4FEC4B7F5A9EB5F0E4C088CD818ECC4FEB4B40EC8BD2981B
F2336074B64C4302807FA25AFE29D1EDFF68FBD0141698DA0A0FD3FE352AEF6618408EBA8063
0FBCF58909B21CA4B9514EB27F9FC7B78FF460D374798DABAB857F6DD422BC7983C7CA213870
1652B6C3901B98B43B641F905F54AFBE00822DD60E2BCEB957BCE7CABFC51F153F3DE4095395
28E20DEE4B8C15E2AEAEA9A46FFADE11A3EBFA3456633B298DEC6DDA6D6CA41DAE03F5C6B56F
68E58C0706D3A97E34FD845F8F2C6126BB6FFB72FF4005A1385A1EF92F2BC0FE7441C157B1E4
AFFA17A5D2057DC2BA87A77C45F8442A36BB895C4FC24FC83BE3831D0588E9D66DC2E71D11E8
8E9F110493314AE48233D708568062829ECB94AF0441975CD8F1FDF4F626E6B0DB35683B790B
EFD89B94894C3CCC5AE9A57EDE5B4C5F71CE1A7C5F34108EF589711E2E4572D90CB501068859
E2E333876FC9251E6A574543E1C2E7A55E186CC9A194DBDA51724FFFE506B0B754666C59F449
3D069431CDF764DD7E62720625B3E02C1403427A93362205A4BA5AA6727E3D486795D7EA749D
AA5A46A7C3FF9EBE73DE35ED38DE2A0E9BA7FD370B5B702E21DDD6A69A6B2E2916A5A93849D9
24B844C3A0334A0D2C95E089BF141DF55E25620BB31DA68962DD3C51A9336EB11FCB737E6906
EABA756BF7B55EEADE38994C5FE146FDF725AC74CCACD70BBB292DAA5B1C60CD39AC60239B12
33579444E8846826D3983B0D6A8C5BE07DFE43961897355ED8E72CC4A4257620EB7E113EE988
D0E8F7947CC822D8563B7BD56D69F144159293E3E2CDED7068F6E3046F14AD559D712D7FED96
740C962CD9EBA9CBDB0B45D5DD9A05C0CE28DD27D2FE6B7169B409BD1E080B32D6D9F2061BD1
B9292D0506D482354F59DB8BD14F8D975B8A30B212F524C8664E5BD9C170BB0488CABFB0BDFD
D18BD44D443B08FB2781840ADDC9BD22376AB814B0429D7B0664B96E183A2675A28B68F1FB6F
88132C796CE2AAB0B9409396552D7C16F6ABF5B85E93B397A9E1CB74F610E81319CCDEEB6D31
EA13F95F792841402245230868FF37BC57995ACA98FCA2DF474817BF96B0ECDD4F42DE20A007
49A91297CB25EF1C7AD56C5D87256AB41195624F1977ECF9246D7B1DB6CDBFCC654AD428932E
5C0DEE8CBAE5D2CDA5F56C16D62BCB93B05BC6CB5E13247F59F321B3B824A73D4261C6A85609
ABCB95C4B14FB51FA0B8826A05696617A2DB092D909FFED178BA62599012D08EE433E800B54C
77C15DCF02086B1F04935F7B79EF163384FD4137391F5E4936EC38677BFBA1B4204F5F80505F
68CAA8F538EB157E9708306A9745D2E2855EF01450E3D2F8BD3C4C5B4F3697A51038011D41F1
6E4C7781B4EECCCFB86EE892AD6E9A2C69C1AB0B11DE2BF88964E5DAE8A3389F18DF163B375D
17895F0D91D4D52C3A5BE455196251EF12B8742CB54D14611BF5227EE52BF8F464EF8860579F
B8BB6191E9AE46F27BE34D732C2DEC814D00FB9763848F847AA9FAA73CE9053719C781C3B3A5
F27E614187D3F00A330C2F76496BF32E924E27ECFB6C459353845D446F642061864356CCAAA2
BF7443515645B51F4DFF4E244F8B7A556EE38389EE3BBF9E69BD72D6BC0D134E134D6FF43608
75EB8838A885DC681004EF4383CAFEEDC688FE4735F5AAA4A11B1BE4D956AE9CBF8D8FDDBC29
A600215C189BC812A1F441FF1CA1FD6C5F3C4013528961E676FE3C9ACA3D44B913F51DEFD42D
D4F67BE410C4152B675731F18315030FC2CA4BCFAF5C5BCADBBCBA4664FCE78984D5C8997B40
088F68F31C8D54D44575ED23533BA3A504C1BC90794AB111F1C011BE57696786AE25551ED73C
35F6A343579DE01675DCFE26ABDE7A3CF73C121B7C33CD3D42BBCFCED99CCFEC4AE08EBF2AF4
FADEAB53F6A2076F8189503DD57F84AE53CAD55D97D3734E706D9442FB175B5CC032EC649776
00A369007A47B17569E32C5BCF5722AB7CE03EDC4DB3C1B3D31A73D3BD274C53359C6BE06BB9
3D0026080B9D76F51DC69AF96C8F73B83BC8CEB5D788E69571EDC574E71C06B3504141D47179
24EFC2CDD8D0CB9645A06922CDE8EF7B297BCFDC0C9D8C65A0D0CE542BAD98B08BF75D814CAA
C3C51877584EDD5412CAF5C69599666DB2E5571E5662B3DA510358234D553A54025C8DCE413A
CD0B4FFB252BAEE591382C0C0A293011F3649508A2C7DAC8F153B869C77D148A0A81AAE057B8
D32CFDA1750180C98F70A8D0FC62A976F785B6F67E9665D1A54C2F591E4B9BC1B8CD0B23E6B5
3CE5EE85995417A8199F68DF12C88173F69D45D8E6208DF7E1315CD08C9F0945FA751B9400A4
F44F1977355C5FAE4EA84342F04AE3E785DEC832DE82B9C6D57835734080DF60C2AA44702FC5
BEA1AF1455DA321341F3613442D63F6B547FED5707EF114B654E0DA6ED340A9372DA4A99A987
CBE785342FA9D2E98789417B87BFAACCD46C16D11B5C6ADBD5619770810A39D74BE2620CD99E
49A9DC91E7E6D0B6AABE9AFDFA8D532FFF1310E0FCC91C0B103340E0F1371FE7801B9EEC0F67
A7C7A26D18FDDADBEF951FCE20EF0558B9F32C560E41A87AD4A94DD0E0F1DC333F6667C22C65
D995B27D25371579458748E078D5EDA6ED9F84ADB3D35547FED29BE03ADB683BA50A9E1CF955
CDA99F95EC45B6B23F43A05D0607CAFDFB9E1D830613C22F1C583A65381CA5C8A736A8B34DBE
70C116699E3144AAD48CFC32405F67614FEAFDAF0106B39EE47B8902B1511665BE23981ABC5C
4E148F6685ECD9575C66DD36A22E41198227E7D7433ED856151154E478D51F5B093AB0A7A923
197864F4FD6AFA7282DA51534B0F9BD0FF070795BF954E02204BCC3B0907CCCA5F3C478F7EA5
402556883EDA2211C394C0D6E921F502368BA96DF89C39B9A36805BC76FA3C3FD390B0B75262
7D8774F66D18A074BBD255B9FB2A2FE94BB30A928243B9F308BB789FA83E6BA7B94946DA5B70
A5047B8D9BD59EEC2DE5A21A7AB0A826CF02CB675CB5C2EA3B774647962CF7DEB01554CAB8A7
B949723EB847A544E8C839F36C10E9BAB10C3E4B05CF6CC46CC6A567D9BAC1DDA8825C726450
68690EC820633567BB2275BD1271E284193C4402D5AE384669294AF99467162E790B3CE41F0B
BADEEE07EE77BC47CFBAA76F28DF5F7B870F95B04A8DBD85454405DFCA87B6B4DC65B3D5F125
65BAD0D22082001D0061F10991F3E1682527EFBC3EE8F072F4BF29F3EB210E403B142B82B97D
6AB9A5CA512E448EFA90F8043495C2FC11730F67949E0F54544094592989D7A1CEB43AFD0BF5
0EF49C81C996469F52451CA818176ED2AA6FF8276030EC931A9CA6BA331A4B463CFE77161410
C4E8EFAF9395F51D13D1BCB2841DF7DB65FA51ECE17B5A321B37AF3215A69E72A74C4FDED676
7930CEA4517DF9A7148A0041F4745E4E594B0219C9AFC5EE8059BA9BBF415302A9CDC48D0460
516A270EBDA3A6997EC4335EDC0F20FF994C69A486316AEEB8584D0DDAFF255F7FFB07C77E29
D58D32BEB7F337E28DA97B8C7C44F8452D9C629C38E03F402824B24CBCBC6B4980559921D69A
A48F593C4791B32FF0C6DB1546E37F831A82E3EC733773310157F50DB7AF0684981345E7E23A
7284029CB27BBC36D2D41EDD1CF0C3E30895D9DE0A2319A746127C37B6F08BB7F9A414FC9FCD
2C17998F7E6CE30C395E2BFC589CC0FEDFE92C659E4078DC7F83E9418B340BBEB23B52D45983
24238EA02C94591014A4D7C12451F7BF20F3F9DD26C515877D6C33A2166A4E433A1748AA192B
C0D33F1C4FA89397E39AB886AC737440C31FAA635676A62E6D3F194A668FD0F8FE5B6A8BA3F4
B4BA2198C837E4B9CA708754CD0804AC78C9218A770AB3EF5765E14A69D14C3367F842B72352
3AB69E5E4FDE7893F99C88273DF486B4080089A0DA5136C59E1DDC48FC71C1E9C8C591E8BE5D
3C9426A657E65FF430EB154E2DFDF4333FCAFC588B61F8071F65CC8D1CB15E27A425ABBB0D78
BC366BFC4F88122C66DB571555B5D6E028912BFD89CF3E0E56C464392A4D505A4F7E23CBC169
CEEAAD218C7553668F549AF2CBF9A297805B3453B7C61112BF8E6325B7569E38F635B2E13B28
AA8F7188E4C94E3E047B6A6ECC050ED9F3A43B131193D84B32C0FF1406B9B66E3627719A781B
676DDACC16915ED237D6B1342F3A9D981D9E96A1A8D5827BF165BB901800D6C900A53271C906
D3D106D26636438E1B5A0C9C97CEF25F0C8B4B5C037C10A9295DA210CDD608ED6E0B77CF2EEA
C5DC2FCB7B5FD0122A3C3A03DCFF782E3C877F210425F9FF99235A969ECA67AA7AA290130D3A
64D6165CCE3AC29C5EE3B4B86EA3AB78373C664DBF6B99949EE56B0BF0F94838701D554B26BC
45C4DF406D9015CD0B2147D338D1C71F7738E3B922291C96DAB5D9230190FE3299551698D8B1
4EF02F5948BF5B5E4BE42849C001CCDBFC06DEE4FF6B12832575D1E5863F1190BCE902A650C1
BF869CE7082C9388A1DAC4CA0E02967E3937BA91CDE0E931BDC07DBD87BF028F46CD00E7A7C2
D26362E0FC0BF267D6DD23E1DB2CF41C3BDCC785F2A8D12067CCF81E1F113DA147CAE6B729AD
E0F85369AD28239F35C7C5CAC87CDEBA07AB233B9321055B972A98CEF27C1B41EC063015E8D1
A2DB01AFFBF0BE01C43DA54A86F199E68432106D252837759AE1618D7008D615AA436341DD35
583DF423EACC1B48D568FF5985145CCC285B2803F03B5B046E7514A8024FD786D3033AF60962
0004CBC2609766039EA8B28086019E4BDA30113CC40E854A159D86AC49E50D894595349E8B37
97239DA96F55B565D5185E630DF0BDD44612DC4E83D31BD8A4372AFD5420F6B379EB8D7373AF
3C91C999CDBF3AD418DB84AE6629D44EB28AA5EE9583686EE4F9435DF0971A3059BEAF8651E7
4E33E7B712174BF952795561BE53B5926CDDE509665488354D5C3E288CA7B679B9B969C9C6B0
44AD882905663D1F5AE476951A637D4125E26575B2CAF43DFE5C6181238D78E0F41F7F798F03
FBE9390561CFAD3F29E9DBBE20EE524344A7E3A730C529A2BD8506FEF7D571AB99A36E136C67
897F7C38582782BD04DC799F8F66432E0D5AFCD239185E95C8B6842CFF16F2CC128B8FEFEED6
95C85E4FD702A60553A254E9EE2AF1A0313A5D2AB5EB559064480B13412085120CB6C90B1AA0
8AE1FBEC261077B9FE65E3FACF4DF582E89B68A4422D0460DE7A8523B51928F1416A9AE025F9
541FB5FD5A9AB5508ACF97EA891BC25EA5FB8C7C58310720CC40B8366A806DE9E4DED30426B1
E7E9D9C145969B2B6D27CFD7F7BB7B2265E79B4BB865B0645209728891A88C68B20E681B4472
CD3105C2238931FD048B43400A9819425A2071367B962C69374A22A06990EA59D0FDE438D552
2432C1BDA7A54E52B594B662740FE6923CD04DC2E7B05748A8BEC182DD5079DD44C0FDE807B6
BF4025992BC6B6F24C2CCFF8385CCD37167BFAC7934E521BB7327D8E88B018877D690F959245
FB26551A75A06E6AD8E5B1C2363D2493FD947431050608AB63F15D1966D6BFE4F1A5AFDE5BCE
8B08E91CF0514B4CE56E1C62BFF778159B77A5919DA5F4619F7A580D6053126AFBD8363082DC
12A405201442BA72742E26C7C8D3430263C9A0EF34E0205065977E7952CBE0FDEFB3902D7716
7F088103CB7D4A508C867077CEEA5D1FCBBC1AEE5F26AA7A85FAD4FA3C0D9207AF49B373F70D
0FCBA87AEAFC7298793693865C156FC0E0E8E7B31AFA7C473275CD08B7BEC07BEEEE402AC272
C666C61F5BA5C1C513DE5909D2998EF7C439ECF9926DB57E82772263979BEFB72DCCB5842BFB
BA0EB1586CFDDFEF3A63F1B4FCCE3894E981D6268A62D1D39F918D4F296381D5AB356450FB31
CAE01FD7F36718C7A54D503EBCB479CA191D5DBBBC08723B8279F2491931D2BF54BA9A93C214
549F66C3C314EE37B5A9951D62A6776E6C7B4989BCA05ACDEAD7DEEC09BA97A0DFDAD7429E3F
480806EB9C7A3865B5A0648530247CCB71AA31E1F8971D9649D6A430BD8753FFD295F30E4E7E
CCAEB12F4A5D9B7902FF57B08B3ECB4593C988758CED4A394E412FD5A132CAC5DD3DA61CA3A1
3E91703702388EAAD89443E70F7D037C9FA28BE7C8261EACBB7AF473EEDB0645BAF01C5F506B
A85813FD1D5164F541E0E85D228E92E60D9BF5C108674C621D38E726D2E219411759E8063C2D
2E64120C66BB2A8F6F00289C3BFADDDFAFADC3285CD6AE1E624A59D7621276362382D2156A49
319A5B1E2B6B6D9B9346A59E1A4E9214C66E17C3EB5A31B394EE2F030C88FEBFF5C659E29FD0
5F57C35B8C986ED1B6FE33ABAC7334FA0653DE6A935CD0CFB4F785F80DEE2D651BE3418CC83B
18B5B4C176DE3263ED6B4F64D4395A48C2C5CF13B8D21D63D85E2228F6373BB766D288CE9D05
AAF98D0848D1AAA42CA0629165C7417E47906AF4ACB4353CFE396B82BEE33EFCFA2531DB7237
9E81F0389A72E0A1D423E1DF66772732EBCFF12D3F83DDF18C46A00297345166F3C3E7B11974
D70AB02EC9629D4AF1F2857FE14D86C9B47B79AD89044CCE0AC09FFA4621608F7AABC07C0C76
60B96C4EE1456B998F509F7D77C9C194A148C48B48738A6A0AC12E50137764914BF6696B7049
C8F13763949F04D6A5302B9E266EB035A11FF5EAFD296F209A3FDDBEB62F1C7064CE0C449A70
A29012E041EDFB71C9F93BEEF2A564FF2D8B248579769A81617ED8DE4F232577E0CD2CD650C2
DD3329069017B0B427651E532CB6D7602A81BE2626EA6AB6D0C85D69BFD8772D62DF7F6C86EF
67C8FBD17F2D2DF34DC52256C72181093E4C876D86C9A66C91A8AB1E01285763EA93EA6B7A4E
6131497BFC536F69B7C02D28E4645CC6FE5D061495512429A1D3752BC565F769A4475E2C415E
8CA4985CBB329D49B8AFD45498CA630C3CE56E7E26CC0C4FA9446D3A402D66E39E3E3210644F
C9A9E0E4445180C672C32734872703910DAE90D102252EB56864F1CB6D1FB8E4A51335136989
08C42B718DDFC4008264791D325E6633CAC13611B10672C263BACF0820F84B7134EDC9E2373A
61C9C8665B25AB7A583A4983D30386AD84EA9C7E021F64C9E54F3F9B3A3D3267EDE3787DC949
BFB2AAFF21B6CECB88129DE3200AD2693B8B454B18CAB17134A471540C009EE8DEFFD2C70AF0
A98320EDFD6909B0B17C3F4B857D1FE5D963EDEEDD8CD3077A2980FD1AB6DD9AF5B151BBF7CD
6B645FFC9C103E45552F43CB401BD5F084116D21C958E1C1450973C0C393F4BA75A9EB1C5438
9CF6C840FEB5BFFF673E058D8738CE2BB8C07CF0B2B5A837948FED64FD7244D5B5C53303C50F
1187FD6B085A9BB6E5DED081B78F4E486E0E17811A552AAFC50A69CDACF0838029D3DA87BFAA
13D89DE7960E332650E5986F940C4493102DE366D8D574776E019205B25F16B6FFED5AEA7C87
BB558497FD216D2937452B62D8A63D5EC72AF5B83E91BB72BD04CB724B4083C60D2CA9D125A6
9DB5D2F4212BD48BAB37FCC933C471245AB99284671F9E3E7E6A9076117F5CCC8D469B929BD7
C4B677DE5BD0272D78BC0434B4A1B4BFF267C4FB588631B1BC3DE1DCC912E3902D96F16B2A35
0775BED06BEB2F1B7B530CE45337F744FE08822331E4D2913849A0890434088063B0307DB4EF
A561810F9C2073B890C67108A95CA581632553F76DFCE780AA175675B186D24379074DBAE021
89DCDFE396A8FC790699C3ED4B7799B30F119D60EA3754549A3CA44CC2F17744DA59E11550D2
B0604AB45A2FFE69ADE126FF2F92CC75EB1D8FA6CF2C2FA2DFB49C1D16F8074A7D7115339E93
C09265B38789A6816B12C803178A72C7C51CF78557D3BEB2D3D5F0A4C53511158145EFD256E7
89DF517BAE8DA9B9B4C494AE42712EFECAB7A7D5BF4668F1FCC23EDAC598CC414BEE707C4C33
1F02821C296725BD4F14F5BC97A15B8ACED9CF5EEA5BAAA216EC582692F7A210BE4F6A41E96C
E3A8C65AFDDBE800E035BF0595C7AC0D12B87B4D409DD6772D125249F273108ABBA0973A7CEF
4F1ECA5C9A17FE3071E54E68507DFD8EC6B787DBC547A90C43AD42856C26324178F2E6D2CA3E
9043188372819D3F02A9125A3BFE766E7D19027CFE5980F5E1E1A7033A5BF236169FDBBFD2F7
3EC6D56375B09FA750EB4741E101241CA191B49DE9C681E42849E23E17B81973E903F52B9AAE
B07855AD04C30DF51C9D9B54F718C7A11038F8DF63DCFE6C2728E69E33AD933A517CB08D3DCC
7681F673B2E17FC38DEF47E2A2F7FE7173C3B6922EB57CD9D7988F6D3A768E56B46AB8C7EB9C
ADDACEFC45E1E245563C0A52F719FCC81C635F159013EFFD5432C697C105CDDCDE49CB5C5696
3CFCC2BC4506BB906910876395C8239C8E5C161471B3A85A353ECA17FC9BC12B805B05D53AB5
BEE2625109ED742C14ED2B08C5D19E7B4D9700D6D3191358D481D2C0C74EE8BDB1B7C40C36FB
B823E5502F9ED6367AF146BC4E07B428F90B1E42E6D470958FFFB5C863E73B1904CE37B9A8E5
90196BF43079DC61FA5BACA8F312E8E8A9B707DBF255BC5B3DC1DF58D374702DDB45265644A7
BE315FCA2665192E5DAB08A6BEF085AC370FB81F2267D4D1E05BD8D69BD3D01A1498020A03CB
BB8BB7A095F10C9D88DA27301FBA0AFBA4D3B056D38EE6A6BBC532B464630BDDBD4CCBA50C2D
B04E49AB8E596923BA3495E7566268B226353E7DCA7B11F28E795CC39F974F426149E0C625A7
EF0B4CEF3E3A5C0A964BEDDC2AB981E564817B963022BBBEC1BE0FAE2E05B6F5F41648FC17F7
9A65162E31A88D0ADB71557142D8545CF2F2EA1A0362E2FDE496923A87C8578D5482C51C52BE
0852326DE3D75F2C6C3EF3024EBEA779DD63F39BB8E2726A7B49A901E3BDDF9586DE02082B13
86FB777D9F09DE377682E14AFDDDAC3E81F485B21CB2537130EB6F69A77B87A702E24BBC2070
6467E82621211300687F18FC809E976FD8EF3932E5213EEBDB9D184D31433B353CAC68BDE9C9
6DA802FACDD168E79491070754E5DE227FE2DBA96C51C16D8C8F0EA9B302A398B2F9491562DF
08AA4C97324B6FF2FAC68A5D079AAC79CF77F0249A0D1C42F441BA372744951077F8DCF83A26
575EC5A87AD6DD4F95EAA1B7F9393C27ACD5F79CE6031E808E13A55C3829D158D1E59E177FE5
0E87F3CB39A81F14F35645FCAF56EB49F5EC78EDB848B396C72F5D928E3561240E2DEDACB37A
994154940F412456119657381B52EAEBD728B026E87FEB8D7EA1EE49067C5D6BDBC56C578728
820D583CAC747F243F6F4A59DCD5B91CFF0232F18183E8E25C76A2C7D53E6823899D43FDAC50
4221799C56EA08F26BD03501FABFDCF4CAFB9E7E2ECF335D8C25F99D40D91B8C93BCEC6B11ED
9671985B8BFCDACFD77CBBDEA246417FFCE021DE54FD0AE4CA7AA19A9458426161513A0F5D7D
4BE2A6DFBB4D6D060E5EFB596F76083B53EBDFBBA1EEB78137466AEC283FFD78BDB6DFFF9748
E47A24614104CEA06D88693EF2203D8792EA5333A697E7B7CB488C01FD76AE792AF0B8F88F02
7CD4BC3EE5D4A09B968DE6B56DC55419A716DBDDB733F1B86A27CDFB8B3AC29DA7613E6D9042
CE9F648A058E2321DDBC10E3374366D6BC4CD910DFF41037CC909580F4650338C9CDF3EB01CA
E0D33DD1E1B41524E0F27A77337BEBB6E91542F599C9C7A1A4551D90537F985CA14DB562DC34
A07F072202E86FCED29D1181A2B1D57CBB62BF6E5E7702A00592F8B018A12C826E569B7103B7
8124D887F03A935B54255DCA6A01F433308A55A71B305EF69ED070CD7CDA1AED6BAB529BB506
970B92DF62DE28C05F21C5FAB79AE4BF3A8B2865C408553CF4CC12E3DC69A0E3A683A637D2BA
187CC5C615056B1853B349A1B88EEDCD9748FCBDDAE70100551ECF0B897A0CEC97A456FCB787
49F74B25168181B75AD5F523F4408BBCCB011D55B83A63A0D96052FE523DD891664A613652AE
3A979AF585C69FC4C34CE353AB52C5DF99D6908E1CC86D89CB6A138F42FA4D472C48E334F334
9B2C47DBD9B6B6A92004B7D3C994EDF5B17F1FDDCAC72F8EF393838BF5280CEF41B803513605
381637E38638004FF04BBE10C46A8135E0B5DB123C0F2F6453C0B648124CD0C7E379742950E4
B7CF205BED93FF6C0439BB3BA0DA7B9C2C9FEC48B5E49E10F944D2F499C6FFD3250F8F7AC82C
93EE7C6B63056D1278871FED6BDDE70B1530118D556696CCD90FA33010B35AC56176D0BAF342
AA846BF7B1A95D98FB7C05D56B4FFCE922F6DF7A09BD8802CB536ECC23C89445544F922DE501
700910AB28C892BFB1548C48FD3D9B0BA4B5F5CA44DFE67A8E2D42FDA79F9473FC6EA646483E
CEFFFC0254E3F930C4732C8AA392E4AB4E26064CB1A185BE4CF0677CF1706C4DC8BADF32285D
6D02D2C4806B6E0E2C5C2884F30EBF9BFA16BD7BC9E2B779173208C156927D2848DE30A5B3E8
622528D9DAA63E06D14E2E368FF5331279680849F8D9B5FEB448633D444CE06BA1F3C8831018
FE7BB9ADB9A896AA75F9E489E9B88342E424DFFE90976E4700E6C6EEDAE9BF6280AB78CC5805
93347841BF10EECEDB86AF0CD461336515CE50989396665CE975D1F1CB0BDC36B619F67CBDB7
B090B04F447463F62927FCD0E1EFA73BA22063732CB8557E27969D5945D8E82F4A5ADE094068
6AC760EA8FFD127653F954F0287C74109997F1B26328FA9556C42C7B01F0A810194A9CF0D716
D252504BFE2C2707456A4422E84AD233F4B32DE1A825F72C45083C7D7742B6168565D48AC1D5
2F9192ABB0D491A9A0A9416420474D9EAF1E146B2EF1F703B2B33838C4163DFCF8242CA6578F
37CDFD4144EFC3DBCE88D3754AF1765E677D670ADEB2FD2DF7882A4BBA95FDBAFCB9E09B7177
CEF80B03DE222CB6070D7D7E09FA2297EC831D561A2069F6E95E9EEA70E41B126893ACB834B1
778BF4CF338A63F53E4828D75ACC76E29EC822866AB6C5756BADDCE0E3181837E1F7DBAB1405
DAA2231B88E176444594000F12C8351354F3A5722E9E4C376B983CD441D6D465F3865C8111E4
7604C61A04CC59D185CDC89933B13B3A9A15360AAAFB18008FB2048000622905641874659693
57164FD31ABAE5FFD1C7210275EF0198C74BD7F04BC02F9012A6BF7A8B9CCD76D4F449DFB3CE
7CAA4FDB6E04DB1099861B53FE6A8497AE454438A0099C7F14AB799B9E8337128ABF5C523F79
49E9931D233E8466029DD3B7CE86298700771876032656034991E213CFB22FFC1DCBD88EB6CF
20EED29B983BEFC5889A4589428151A249BF85A7F38E5F70CB6F87A706A7A057F63CF366AFD6
AA4A481FCF7F848B650CB9442EDC33673CD98F8F895F4D82DDEC9AB457CF21EBD339769292E1
D17CA465997DCE5A6829C57392E08C8BE708ECED1A9AE4786EDA0095A05014D4AEB167C1D1E7
83F9EBAEA78816BCD4AFE2E5D356A30828E11A5641344B3D46A3E8AADCAF22DB74FF57EBEA7B
779B7C5DB027D6FDECBE1B0DA2EDF3219CEC627E64CB3142D303027F74E694A983B16B33FF62
D1B0E114CA59B30D2261AC4337DFFD0273ABC09B955E740E6ACB4F20969DA27883B3C162810F
194A9537F13E58865F2B4611D8B9A9C4A59586E583F9BCA6E8684C982FBB42AAFEB00F6A2428
75A8D5246830E5D9FA8B479C36225D60C79390094C3820D9D20483BD8B28C5979DC27905528F
F829C14E346511BEFCCB0CC2DDFAAFFC69FA01F2DD592B0A554C8BB1D3DDEB53D871DE3048FB
9A816A40A5EBDC1EEF6725B59F6EFF26E4DA46360D4BFE49BF623955485875028F78DACE31A4
B8F4771090B36B82E0E91C9F6B63DEFCA85E751F3A1E6D47FD674B6B75D34CF5D230012A2A02
EA49017E9AE4E22440C836923450A7CBFE44FF5E90D9273FCE99A56CB0B4AE070410144DEA9C
75282AC74C8D426C20B54D48BF5E893D9AED7CCD4EDE4B3EBBF29320E9F98E36571E545C09DF
06B72ED2DFDF058446FE62D7F591326F7A0405718B97692CAC9B02D77A37662F0BB150102D5E
820309D5E1D4DBD95606111A4C5D0E606F890732383B96D58065880C679C4FCC3F4FDEB870E0
022EAA40D367A1CEE2E43C31B0ECE28481217A77201B361541D40C4C7ECBE26EE0263FA70942
A9C4F90B986284113943E170F7C6283447E8862701E31BB28A72DEAA7669688BEE2939086378
99339AD8C2C1BF9558B06446864DB50526FF514EBE3122A3059BF27307F10BA5B44ADE0EDB6E
2693D7DC2B80E1A84F635126960FDD3B6110E84922D484261C92C8055314E5A2E8FB6DB0A904
E291714B4B1D28E2F88734343E42C06ED7DFF193B1871B028E7A0AD51249B36258C0EF6A5165
F5B7AA3061F0ABD6BE779D7E845D6606C9576314C04E98902DFC7CD027934BFE804B12F01E9B
5438301E280AE84371CC2BECAA06AAC7A65BB6B3F7B642207D730AEFFD55ABB33B8FFE0FE0C7
B16356E092BB0360FB94F1E8A2FE7FA999CA66B6675025CA605A65540F6D5619887D7E1A6869
2B76EF901AABC5A15D529F5BFD446E04E95A1BE213EADB545806854ED5E346813ACC82C927E9
DD5B45DAA1C1D57A2B451FE91CCCDDACEDE657B9E37D605CD4D6001FAAA843B9EA84917602A6
7519B99DFCD39DA8DC60A1DF52A0A0C8CD35BF9069C1B8A534B4EFAAA4B42E932BC61FF11A84
6190E9BB2111D13F08570DD9C9934D0C1DB1EC459A3BACC8F10BCCAC2BC8270B7774BD3065C4
D146548D1959395266F420EA71C05EF4D37ED0EC391890BAD4D686D3D0994B98B9A2629C2B66
88E453167FC651BC70DCC608B453FEA208329E9B93BCAC1A7C9C5575B43D32708079AD2FEA25
DB03A13440388F8A4BF9C5D9CE42281284C0A1FEBE6B7BF94B58257DA32011484398DB2C2856
23803D4E578F30BAE73A57D039A2CDF56BC2A625CBADAF7FDDC7744E8586D8CAE909162D2A56
1FAF91099DF981C72617F43F1E8DBC986A1944B370DDEEA5CEDEA04C704BB45227680EE2A7A9
1D5F71C8B429D5A1E22C557932A19B669A6F7D60BE8B5A1A08538D5396492500E8A30D8F085B
9F1613E18FF8511D8F4ACEBC9DBD742C6F27AF4B62026BFCE268E3239ACF3CD0C54176F1839C
9CE2618F5680353A0D234181172DB3A14523D69A204CC7A5EA4A9CF1D78275804D60D41C364A
8725CB1B72759A30DC5E2920B76E1B486795CCFF14FE6615700ED97A1BD4CB16090CCD430640
36FC003368B1E949D23BE8E7CCD7F4FC6F54BF25174B56B42B505E99BAD37A9868A92C29DDC3
29F1D5A84806B9382870B3908CA87C3F840341E45731E5B7EF5B066AB120DB45D72B0E444BAA
AF4E948B34D354C244263505EF3FA995E2DC1177B8EBC01A6E2C7AA5766CEE90D3AE7273D569
87BB665A43B4697A0EB98C120EFAB3C61684520E148FB5227939D6208E30CA72FE0D661B9792
C8656B44986ECDF77159F0ED52F695DCE64595A243B635A3B4D328F73D248E1F8D8244B2285C
B5F6374E32B2FA7F2E29828E177F81938E2AA1C70EC9226DC45840F8F7CE4A377D32FE6C6550
61389B70C4A5AC6D62FC03BDC16B1C15A79DBC46623501D263A948BCB2747E85EC1D0DAAC606
206398A2FC008F369B673FE9C12A1D4D06D80D625F2412FD8912D625F182307FA2731435CDF2
0C944C2ACD5094A89530A6CF54BA8D347B3819B31ED56C55AB6CFFA8C8C3C0D3C6034FBA9FBB
373F08C76E79F50400FCF3D1F65CEEC11C3623706EEC7ACFE84B89510867C0B2FA6F25996733
E4CC394872726138D7456CB398052F4C03705E27BD85EE755F1992D1C6D330A95B6D208ADC76
D4CAE80A78C75AF6AE4976E564F859429ADC4DE87D26A9A6277E14016491D69C6B9368A6DBF7
2C68EE9B4B32CDBB6A186728B354B347DF5D5F33DB9CC2F757B113EFC0FB491ACDBCBCD70D0E
8E22322E6BD3336E642C6C48D6DD0DEC32C39D6E786A99702B83F644E3039DB0BC3BF91918E2
41A1D20AF0CED35FBBCF8892858762FFDF4D855DC043CF348F64B9F0EC40B0D58F1A267C6567
8609A29E8508F0F5367E0528845F666D3DEED15A880691675C9977278FE5A0C75C97F10E201E
97D255C40BE2DF023F3842ECCC0F474782716CC0697D2305D2894B2149C94ACBD4DB97A8CC49
317773662D6533D2E3BA293FF6EC3BF29B897723B200DA0875803B40FAD899E953168BDEDEC9
75D3461618652733F9F1AE97FA05454DA0C39B27308F81D6624E7ADD0E909A721B0B5B87C735
A0F81402E1BDD37437951BAE5735BD2D9C5A201DCFC832893AA343A6E4C8F879BF7ABA330F71
AD22AA121C49015A6E1B4DE63337C3C9B4BFC3E8456D25309AFB76665AF8D3558841D95E1577
87426288F3A108CC0388A47FC77672F9F837AAB1BB03395208BC7800F59D883023DE8DE4984D
3550AC1E435A4A9EBFB9024FEBB3997847FFB5AC94EFAC7E480B15F49EDC4E1EA47CA691AF89
E372FA1D51A68D417DF4D7011D8B129191F8CE9BFE2D80FC9391E51539A8EF2FACF34C91BCF3
C5C81BB7A3050E0EC13E3CC2D03387335B307D3CDEC0D43A6C2F348C3820CDE916070CDCB485
D1ED73B708BD083E4653EF4F4D1BEB104167E5C53243C72B5DA52CC360602297B86B012DAFA7
BB0D762D78D7AC49D84DB797D4BC25A89309E3715BAC2970BB31C959221EE2656BDD93B51D43
0644E3EE633EEDA51E1AFF403FAAF247B15DF007EEE990B21ED684D260AD6B76028F80D65884
4D4E8BBE91DB43DF55819FC456B9402805DF67958AFD45DBE94E54968ABD3AFD2C456B785092
7353FB25A936D9D554A21262A3CAE1692F978F58BA5DB38A55548529695BC0A455AFB4BE3128
FE733C7234154F4BA0F00CE4ABC7C240C9283831E9A7E0BECA118792AFF6CADF3FA74A572F1D
B4789FA83E7E9881E48568814E40E4235A2ED72E8FBDE71ED0FD40D348F66D08E56256B0EA0B
46F54720DF7E39654B4B7B23CB4863AB341CB2045EF7A71A9AB550E1C14282FDA3B60D306906
09B9A2F535670C9F7C6062684E1062BF1B1675288E002412AE17FB3D63125C4A577D3BB97C12
F4CD925282737CE2DA3C2E11733BA9B5DCEAE115A0EDB3ACB8BDB1AC0F687C829EDA0022D654
DC3D051BB7325CFB66F96C7ACD1A8BAEF2BF65C167DF291DF762720D39904AE50708552D754F
8F43FC2D5B91B632D2BAF70C67D3AEA5CE731C380333E66A149E46B32412163C743D128F52C1
24CADFB65399355B4BBD4C0A3FA7C02DE323911051DA20124B77AB931989A74D584C0F6126E4
31C6DCCE725FE72F83CCD0CB35F2AC901501411270FE902BBA4E6A4C1DFDF12E2E857221702F
F0749C495E170F01578BAB3827ABAD809BFED83F6FFB243F40DBED47F896DBD37CDB7D63FD08
673E13DC24F4052E1551BCC080685ACE8D3184AF5A1818B4D48811F32DF210C8F36FB6A20C9E
239FA888CF0EE5BD1A87F15C3C6A3E459BD006A69D2C027A09E83541D4ADDBE98FD665AECC35
C311871A4A67FD59EFC06B2CDAE51F00659B4C4F9F79DD824485BC073CEA94DBD45CDE541355
F7244F5B5BCC6C76D82FCD1CAD3E2D08175A375098DD8157B3E30184658EB500E224782ABBA1
297432CC25FB54ABC54C8CD85667DD42BFABFDE7FB7A4E83107AF3AA508F9B20650AB6D01CCD
AD374C67F31A666BC1F505A6D94C0C94E4E73EFF7D57FF69F4F145504F60A032109AD829EA90
EC25B66869ED39434EBD3154E4CE7E044F01AB126454339B41193FA9618AD7B49CA2A9B2B595
684A35A5534CC19A989D5F09DBE09830284F895A4876FC5F7920061B06CCDCCF168D5022CD6E
AFEE4D796BE4B9BA38C0AEABB4B195B81B621843DB7DF74790FB46F5C07426C8A4FD0D9F99B6
C0A26AECA5F89E36FA8DB06884AC9A3ABB1AFF9C6889BAEAF13CADEE3F0CE80E00EEA152BB64
85BFA7B5AA02BEE1905EC4F666449CADC026BA91B9ABFCC5C2002950D35ED46575004D566225
82500274E2ABD691D0013343966037685138B76C4218BA60855DD1A35E4505273C2CEA443018
DB1CDBAE7DBBD948C96F5DB10BCA8127CCCAB09705EEC19399F31F3F8AA774BD4EF950ABD0C9
1975B346E7CEE612B6A4FAB61E6CDCCDA47B51D499337B98B0B6EE8973317DEC69E6F1564868
A50EFDC5086C806759EA40BA0F036E86C8E76A6346609A7D87C6FB2FD5FCBD9B1744FED5F412
E3DC55E519A941C4193F66E6E4656D04BDBFAE608110803F9C72BA22DBEB7AF2068A1425EC76
E6574311E3E1200DFDFCB4A0830AFFAC7809FFE3404AC5EE8ED43BE8425C1A13904B1F9D220C
9A9A6B9295AD0B13BBD63E1AF6AEDFE6F54DA8AC585B2FD53AA94B2CB65377D10EE13460F6B3
08BB6B3476DDA5FDC5EE7DA695EF118D79051184BBAC35EE74D6F046F17166E0F12604157979
399734F16985182FF1BECD19131570B97A817C7467520EB148C3E2887020F8C09CEDE0A54A25
4E0311A504A411407EA89C2E916F60F32C4BF8456EC370ABF03D1B2D95C991464EC963368441
1664CB33186BF6F897706F7C500A9D0AAADAB811985D1B741AEBB6593FBA0E07E004E86D87CE
A653B87CAB70900D1915CE3D19BE1969312EDBA894C541F1227586721DC33555FB28E81307EC
F93F164399A58988FBECEFF7CB8D1A751B4FEE0AD6D2638B97016B2DBB034EBD0528BF06C08D
E822804EECCD4C943ABAB45490FE47DE7584C569F9789E8C1F213C1924D196C63B3D57DF4385
FDB9BB4D584F6C4B736D32F0D533C3699E90D1E54C3F4ED914A788A0C364F7D5571EE6F61D85
E5CDF8315FDEC93DF38BC0C7E5BA9DAF885F99DFC9262F77BCD3137289B43D2C433111E8937B
5CBF3941AED5FDF09ECD0971144E020FC64656C88A01F9B749770DA845D7F690D1C12141C7DC
8724FEFBAE909D2E5383083402BF005598FA8B67301934E98FEED22625CC852AF51E7C647385
A14B49EAD19C2BBAF578D35943A3B8CC943A863187AA79836CB71DD8DBDE642E1813FF3C21C0
90F3A7BC39AAA1F5242E8BF68692A567578A4795ECF926CEA68CF77CD6B6520367BA3C98CF22
D618A2764323297D1F2E210637FB6CC84674F01C04CBAB1295558A148F7F94F64900596F834E
E0F333DF86C59200992C77DC32EB5091B7F5E1061F75EE9AC11D4F7C18D975FB2AF04245638F
02FC7475556CC1BAC14F33D0F36CD94CA20CD24AB4B587B03D968175388ADA63FFC99E11B340
AFC6C97381612C825A4EF6201B13C813BF36F5897E6FE3D95BAE2BCE401CAF0F9D7F1D0729D5
0D6496CC99DBA29E2300A5307420DB31875196A26DCE6B59453A810B704FA8ED0E654B02C36D
7D3D870DE8CE82532009C4E9F93921A7B088EE995060AC598E84F5E1248864269A2358FF4463
A50134F113431776066909C2B52CE0114D3391142F298974219ECF3506BA1830359D186760DD
C7E42E376A41B17ED88E6C429768C73F52095F491784661D89815ED8B71ABEEE1922DFAAC7DC
FB2E427C480A235F533F523C7B4CCDF7D3E3E7C73BBE89CA8B04F89BF496310792B445122235
F55AC0660CAD4476ECAB30D3FC774ECB381ABFF4BF4E50BD0954E240AA7DDF07924D53BEEC0F
F8DC680A30F8CBE921F5BCDB02BA1CAB4C15143898C5C6E9DB4B88818299C4CE29F78E88052A
A3D4F68DFD93BFDD1CD6328AB1D2C2888FAEE513E922320FF0C084E617BD1EEE5442DAE79108
B34835214A330742AE9F99ECE561D29B09F611EEB154B1498929A4A6B3F09D63461489AD6EF3
15AF77054026DE9F8120FDE0BA8012710C75266B9C310D06A842451C5A2B1AAC9433E08CEB23
A872593F49C0397A1AE1A6443E4BB99C1E24AF85DFF91C97D4F400B3572BDF28174C5C358427
ED6CF1645BDC283910C47C8C5B112802E549F1D60E96C7FB2CD6F0648F2189B7FC0FA2652152
CDCFCB1B20367A2033AD1188576017E0F1272E701A5FC7BDEF08BC4104D728074573E40C87F1
A2520B3D02EB8CB23CBAE6449EE78BB857E3EE7FA228F91E8007B848E309B38873EF3FE1212C
1635404DB7A0BB06E21EC03E9BB358643F9E9972015362C58BB56BAFB7FAD31C60D0DDA2A30C
5B5FA028896FAAF05A73AB8610BC521DF0226A922DA532FED3E6619E58D9F76F3693269506F9
CAC08A56B7EBE8F9C8759D617BF44B03C2510C6235AE30109DF7DB6A7A391342AABE9D153366
69F98D88DFB213F19140A52BD39E2E66BE39BEFE92B98D7271917610BCC240AA5EB2406570DA
33CD0B66FB032241BB148A0F200E3937ABBACC878C934BB65A41D01805285754E9A3FD0DFAE2
2C434D1D86783EE2693D3FFDDD895F8FA00F83417BDDD173E11F9E1E4119AF293F58B5DECA41
B5D6F4AD983F668EC561EBD5F446B84FDCA10865202528F60BC54003413AFE4FE3E89FA6609F
2F21DE8D5AE7D701FD349DFAE556D6EDBB906DCBD5B67EB59B2B22AA1C26726A069F08AE407B
6AA179E313A4856F5878007837D6771DA41AFDC5F9C341F5505661DCF8D7E14A16E9AD360685
7F67D8E9C62E41E5A505895FD0386DA34679735DEC0E3F71385009C45C1D2B9FC124FF7844AB
CB056798CBDD336AC5462BFA9C012966FC34D9628F962285857C14FCD4FF243AA312F6177937
3915880BB730E4F075DC14634C01317641C7E1C3994B40BB1BEB74DD2BED0D9D43DB000833A2
ACC8A6F297DB5E7962430CC727C03462E63C2DBAB60F6221BF5DD3FFB0DDE89EF98BC1A5C6C5
C59E6DA88A4DFA99F5DB8BAE29F26E34B421E7E74C2C05A8457F605FDB727DC1135AB363E3B3
9CA32B2385BA24C78A1E0C83D42C513E3383B28D9554D2F5DD6F4BA1FFAEDFFB8923C183E35F
75C57CF48893E4CCA18087CCF8C84795F8A31839EF6F6CA25CC154F6CA3970F60126B252465A
76B1EAE8B240FD387AB315E1E710A25B339DC2C0706DA7B1C47AD15D5B6837F7DBF5A95E98D0
EAEC6C121598076C6BA66E471C87F9947929E01B386BE55EFA5E6067CEDE9F54B0B278ACC43E
56987848ACD559621B05C67228622540EABE7183DBC1305FCA26654D9BBB734355ABC4AF90AD
7A7406D123A73695F77FB049B0CDD25170D8CF8F9A892D3636FB152688153F58E333849BE3E0
45F8E18A4EEF42F191FEA6F2FB54206C981FFCF827757A22E75A7FCF21459E7C42FD5194DA16
D0A33B32318FF5122EEF24C81D4C3B9391DC8D209EFF13FCB43FABF1FC67A712A53756EA65E8
1AED88C0BAE56CE5DB00F2F3BBD89AB87B9D4C12F35FF1C95D8F3DBB7AAB138E3C387C135A32
F00FED1C25B0F96895792B4F0276C3E2D702816D4A686DB2662E06451A3E1C3A5F6AE239B240
505ACD4DCE12BFFFE205016956C6D6B986D2163AB20EF7B02F27F9E0F3518E5E51D7B8A81B6C
6C0CE8A32956C435D20CC226D0F16C91662A32D05ED7F66B995F3753D05B91B030CDE048D7C8
2885174A896F22FCBE7625412362C5D6A664D9BA41504DF972B79C442B5232B8EB90DE4C29CF
BA9EBBDFE5B37F91A630559F797C22149AF8852C5EC4AB945C8A042E5DE43080684F4908BAD9
69F290A1CA1FA0E916B6FB802C7B15D2A54C8AE8E4EDB91D926DC622DD5E42362B4BD9266222
21607EB032181D92A5A0666424921456F2198580910938EBEC7902B759EC3B66A10C946E53EE
98DD1D28970D44818C30C76FE735F2BEDE5526E47C64EF7D0D74C7564DBC64298D270B264658
6835DD7E6255EA99C66AB9817F4093FD2E219FD9E67BBACBAC0A9D3E678111BC985151D46E06
CB7B326E767512DCE309A0B40AEBDC854EE7A3060CF8418DCDEC028CE80577FCDCE3CDAB46CA
F8A84A66E8860A034A390B444552D669C1C1BE764711367CC71152101FAF804C36E90D4E1BCA
D89392929F998314FFEFAAC52FF96439F19C20D2EB9148BC6CD80C8B5624CBA39D84ACCD5525
23A42A4301C7DE9AA5637F717C46D0E57350BDBD4F0ECF575F19FE94D69C213777FB5ADD543D
485B47F3A76851E8C57AB9574A00E9A99641279642105707D75D97FD49E4FC53B79EEB0A8689
E88097CCB46CF8497977406081C7EF28A2E7169589F595997348991FFBBBDD8DEE44ACCB0C98
968A5814783927350D73DBFD9AC11A9F571AF46363E6709987C46EA207622FB319FD5519E7FC
A3DFB9F784C1ECAD5472236CC2790015D4CF9F410004EC03AA9C247483F9134E742AFF8E3D7F
62778DC6E9CC87469D083E9849490B66FBA43769044FDAD7F59EBAFD5B07A7FE75F064CBC81E
F7023AEB4162A787F1C4D4005998D969DE4C7ECB3A67861CC5E13F56F1EA7A4EB7521CF0E282
F513803658CFF5FA93EF5B15098FC2941FF4E0D6E2DD9CC056BEEF2C4E15DC0790291D385E09
1D2CC377FF252EBB7214C2CDC948A9FCBAC418A93CEDC58375E3DC347F872DF735D0127274DE
42F4E3709CD11CBB6A0320647CB97AE4531FDC8CE56ECA5CFE4DBB83B3C71BEF715ED3E0E001
F497042D7D9859A0FCFFA87D37FF66BBD4C420913CF0600FA055C3CDD6379C8DAF78C8A03267
EB381B64796CDC066833EAA949F74B0ADBE615F62C0517CE582A1DB047288C316A2B501D45A3
62B46CC674C913B8980DED11D1462B8C03EB3D93BFD47D33661C4FC89E49ACDC09DDF08B32E1
4F876BA1F0CE782F79DF52F10671BAE136A9B6D5120A011594F22864BC61600575D5D958678B
94D71991D55E26263141A80C091A2E356B9DFC5E718D0833309431DD80F5DC39AE470E1120E3
0A862464C96C1957C2CAA9DDB5FC3D1873C08A7726DECB5D73711461508D4F0EE3B3D9DE4BD4
24D60787721A2AB50ABF2F02AD9FB20E483025AFE53CCA0A54331ADE5D5859D3621820CA0E2E
3E7591BF4BC2004D0B5F7EC9A1141A36B0F1F9E32E46EA6C6730DE24D911748F83710F8A4F02
A7F5CD663967DAFAA7BCAC3E29D900677EB2351CFAF46A773D363CB7D48943E1E245068B8F4B
9434EE8F820B79832A8DCE28E3E36DBA17ECD3DC93F38F6BB4505BA7580B186C818A251E38CD
7DC03FA7EA1AB8D290514909F1AB56E1B2C6584E86EF32741B58C79EAEBDD62F7864C19554A1
9FFA1E73CF2C75D00C903BABA7E117E56B5EF27F53C94AE007DE0FA5726174D691F0CA7218BE
E50892C6CEBED4CCE891EFA7714804AE54761D8F0379B063B8F8037A0B488A487FA3BD0D4B16
B34FD4B3E52646AC3509C5D4C7C191189FCEF1D1131B4DD9799DF6E8A556049E28C5ABD4216B
6CE52A1ECD99432D8316093235BE3D91885DBF346E18FA2BAFAE67B650467D23196FCEAEF414
8A2D9BA1F44B3B43563450F006D5767D86D942710A820EEF0BF57028B1F1291C69118901B5CC
99907C205C919C81E80ECEB1BEBDE1A67CB21D3D7AA431E0D1EDBC1F4DEE88E91FDA97DC4C2D
49215DD18458B42106B452362956D407C064E29048513A2CD4A534062EB007216961ED4566D8
CC190F990662F6C60703F35F0D8D643578E8205D1FCB0119C20D43BFD046842D885885127653
65E7A007E770CE8E8F5B20FAF8B602E8291D93A7B56F8B2E5A952BD803C196AE98C27272BEC7
9F806903EB3D3695782940138CCDBECFCC06B8A46907159095CCF0E792EAFC60435D33BC41C8
A28617BD5A5228172CA784690311898BFCB7A7B22CDA56A53467E6421C413689CD41D59A3FD7
FEFE1A8420695909716B8ED59AC6C3C83F5C0207463A369C369BCDBE4A9C35A49301C952664B
AEF8BA31541DF5C1400B708EB3653AB8F8A7DFCBA52DB26A43CBAFAAC4960E4048EA7D164BA6
ABE831276534750D13251D9421BFBDDAC7E3A6C61948333060390FDB5DD7AB5A42CBE7B00367
5AADF5B52D8F709E45F66593B51519A4B37F8D0408554DD87783C103C31186E170788E8E4D5C
2D1368D35C90BFC155335AA4585F371BA0D2D36C12F70CCB54DD316DF4A5B928CD36921BDCD2
80996FF337E7AE9C4C0DA2ACB795614ACCA8BF9C5F5A270198A99B0BA923C041E65D34D346B2
ACFABC9A68B059FB4EDB2AA741A93D768E5FF077C0CABECB321866513057B12B25613F5B1B34
78334FC0FB18085E27A7361092F84F475BF19FC88CB9D9BA18AADC63AC383CB8266E01374F9E
A36AADC06168E4772D6EF439FB8FFF2EFDDBAEDD8149168F8525EB7D8260A1E9165511AB194A
91CF9358F1DF26499505F3F2DFE1FBDC2E28C0E5CB48BBCE6D03EAC7A02AAD6DEEC7FE18703E
6DE77A677E9C2D6D56EE24769908189E8ACE09C55979830C1DEB6D7D00F931888C2450ADDFC4
15C25DF4787597D0E6499D3ADB097738BD599479CC4E3488524983DBE2BF7CA9DA2DF888C2A2
4A92B597FB8CB9B285A8201AA1BD6E3073C6B4828984E3EAAA4123A0C9053813FC43CD724BCA
03CAD9E401ECD7FEBC2C9D28363BC8F058AFE54E479D1B518061EAB166EDA2B3A0BFCB5DC88E
BA7AD44AB66A74099007FBEA682E45DFE3E6F36ED2F18527AC2A3443897F6E1CE8DBEE7E03A1
C2D78D2BE6A6E7C6F43B828AF56BD8A86EDF9BFFFF971E1A9D56EB626AA2F112324A53AD874E
1B3166EE3AECEB372893205D3F147209C9DE0BA3AADA432773E150617A6B7E4EA8E636F99BE7
60B74902FEE6ECFFCFB1E039BFA7C15E9416CD2B5F0EE6EC50B42351B95B18BC1451F468092D
4F08477516A287D8020C67C29D0CDDFC48838C99B8166C20202D3F5B8555AD9AD5DC2CB946B6
B97FB0072EC9165EC95ACBEB8603D7DB6760B9011A68000687ABEF5966C357EA1E0F94767E2F
601DBD9F9FC01699BB0743B4C369B7D2B009CAF12354D81F73F1B1FBA08623B38E106CB11FFD
6E7A2B88F1F5C5C9380EA7159FF41591EB7E67FA45E4C4315B4708A5842A75B1B9C1CB4AC492
C26178CB5DA50F0E9571F9DDDC6E223B34006EBEF59549CC34548F815BED1B123B012BD2A6EF
67D97FD477B31C7F626FE9826107AA9ADEF80C1A36187E2453562217478157E3B0144158A69C
658517D4CB79600C700A2509EF75A45AD060D0294AB4BD9A5D2CD590340B79D4D8408E856958
D0F403F696B543195888A2DC7CF4CEC3A102814BAD5C169C3C911CF7AF7858ECC33716870D2E
CCBA716B87B796159490F25C027D3F04717F355DAFD0DA4737B7F72DAB5D1CE95D11B4A8832A
E3563F41BE06ADA6F45B38EC1BBF9FE0525FD46F0112B5CB0E947A701DAEE6664FD426271BB2
B63E4ABA8FC1037F8BBDBF97D3F1EC8C98DB89B3AAFC6D597EAD9EF2347CD5B3874138BEBEAE
BB2690B8539DBD000922A141A7A6A2A74BEFD03BC165CF3C7C3B3F49552193A9B453A37D4F4D
0D9B8DB8896B27951EA7103EF7FCD483097A7997AAAC483762FDBED0FA53FCBFC245D32740B1
759947C74E3B19CF333F30B131A65784863F93F8DFE7B7309BD5D5887E943804C3B3B8C3C4A8
94BC3145AB7BDA6F33A0C72D5F70BD538EB8BDFA06FFDD053E6152B10A2CA929E9572783B01D
307B50E86A189F747E690DB2D0B3AA5590FEF074A2515F9DA7635EA85771B45EDD4A5CAE324D
81877E0B6E5C2157C03188725BD5924364E0A12350855E3B39C414127A33361DAA5BADDD1D50
5F386ED72E80CDAC8B0D9CD6A92C687F913D617A9295F75DC3C4EB08AE11047AB7041DE8EDAF
E7DE24796CCB9D44640ADA774FCDEB8244C6672A4AE9B282997C5606423E149C4553B9E3E23A
2E03501A5A8BE7AEBC3C16B079C38D2A0690ADB258C414A44C2E080FEF8198107FE7B2A75D89
B4B097E42AA237F789EA7727B2B4BE0378D5DEC71E7062B088A76E92AB2EA36CCA35E39D8364
70B3FB7A7A1C07F37A9F37558C058582AE3F8EB48A11F9DF0A89796785D238393580ED4D425D
B670687973E30EA79C5F778B42BAD782152CFC55E0D4E9B5F8F57E7627EEFBD9078A576A57B9
5E676B0CBCBEACC8C685716E7A925BB69072C9C9F94724E389D723EFEA841DAC245B613A3AA0
C6CADEE8CDC90C7881CE3D7657B16594740CC202D4E809F38F2CA4B219B928C335B51705B957
2459489E1C176FA365D867A723B699BE25CE1B51DADBD150A5CFC7AF8F6FA901B7F32BD2758D
A52601332EDD0E1C2D334B5BA3B85CCE0F17D8ED535A8E4A9E6DB4F279F081F2BD2BCB319DDF
5E4A649EA13F6702A431E9C6509AE16F361E702BD804FEE570BD4FA7205B3B2531382FF34E8E
F8C254253584CFFC2E955CA1BEC100A9A0A42D3F1CD1DAD265F9364D1CA695DF664856D6240A
46CC6473F64BF2608E21A184A475AA145BD925B00ED5CF2D4E845B3764797F3BAEC5FAE70C5B
AA6721A0C0571F5864C8B2B2B782A4EE2DA6A91BE91F0A90C6D906103B07CE270FE326711A37
F52D3971C7B23EFFA647A2131980D6825B3DC2E2CDA81D696F9F84793FFA99C6B732939B09D8
11DA361B87FF76CD0F93C965E5292B7033870C44A584B2D2D5725F3C3CAA3713BEB980741DA3
DD6BBB035F2B998D8CB26FF81E3FD3BE87DF7501730B30ED40A1328B8608E0F0C50733EDCC10
AFFC4960B25BA762068BC7F64F878E2641D6077EA532761DE0DC35195DF0F32E410C6BD0227F
737E9167FCA17314BAF216B1A8FBA2DCEA54A863C384722376E8818D723F2EE9BF382652CE2F
635A30498688A711DBD62E9E6E40899A848BF8C35F9D5D5646510113AB8630014D640EB1937D
94654050B59DD22BF74B0C8A116EC54A108E6A6CC82E9874B0BE04191E9FA3E7F2072EB17F72
3FAC1BC71006597B99794AD61A993C36D1E5250C996D380090366F1AE783704041FE9BE38195
1C34150BE82DAFC805D10F73B6D0CF5103FC051DDCFC5AA91F5D7E8CE73C39EF9B7B0699CFB4
0943BF950B5E6750C0DB54B476CEE4719AE515E40A8EBADD57F80A6DF09EDEA191B00DFF801B
2BAB79C5657588ABB23584CEDB768DA618BD0B5D295A128DE877606D49A12FA73BC9DEA32310
0F2960C76E6E8B30401572527611119C3EE06D3B34CCA355B4B202682277464C8B6B197BECFF
0864FEB01BC53792AD1DF825A73E5F92B84AF103934A985D9C65A24FBDFA960325C7A73D2989
ECAC24CB3F8EF1C57EF43DA81D0B64A5306837F4361D8BDD4CFFD94D6DBF7A5F5342464205F1
B5EB6D724D9409ECC3166F3518B501750E89A9B7110FD7EFD43AF3C32E7B93BE8416B7A540DA
EE25D1497DAFBE6D30995C0643431041D5B1272BBD2CE5FEEA317B42BA7E5910F75A91525C80
DBDD061D053815C0B251F1BEEBEDFB1567632C46D647A745A2DE0AA08EE35FCBF4D3710C8F5A
A6A9E0DB9BB0962CBB7E4177EF3FA776DCEFB988833B0CFC39C8C6B7C89A713DD018A5D35126
4DF859AE5903A5757D5F039B3D65614F2597650BAAA3188D1AC6A8BB1DDE7DDBAD1EF9C4C980
3A3148F3F4AEEF706A7094175DDFDAA29B5F8A012FB8CB301450B4E78B58259DE6503679955F
5509F5025E4C799C55F0CF271717A296B096F03105E61DCEBF5D24698A96BB364AF38BA20D11
7D59E86030C17A30AEB4B1794A6D72E2B62DA0DF92047D6985DF1BC950BDFB38AE13E612E183
6DCFEFE4003A0F3CBC1A7C3398C0EC71A8AC8DB32BF58969635E46788A3DFD65EE12523B8FC6
70A727016094B8381403F7762D6E4329319927DC1534CDB25F620D3FDE4383943D9942F75523
CCAD080F5B1CA86159B6956CE56B5FB8A07B33451BADD7FB9ABABB37A10F04B58559BCE193DF
AAD6A9F7763B11167E0B899B5B6E4591608E6B540A81CE22AE3C151A215F316E89D2D4F0FD87
D0E803EF412DED542C369615852466961517B5C77DB3C39ABBDE32E1F503476A8326FBB08A4B
C9F04C202CF5A1896BD05EA8BEA583B10E5B5AD45963FC490BB9A9636381DFA47B42132D80CE
66F4BB1BF889DF9600B08038C1FC334E69A76D7FF65144B9E48D939E5497DC67D5374C4453BF
B1A9FA6C6685F43B7BF9AC97298A3320DC74BBCD9A432B5D8F8F1CDCA9DCA04380A2D7B024A9
B0E2B4EE3E1325B3C0C4EB2B8A20C97D5DBB73AB15166DE381F7F83283F69479EEE7CD091F8E
4D6DD13C2E78E12FC59042701E7A3BEE3FBEC32693FA48EAC541B85465B9C62D21E71E463654
1395D0EC9846F16D599B28E53BC109C34F17C2A85FAFFAEAFD20DD89D53CF5638F9978618B61
0902E38A9E5A5D6C5B00264D30B4CBBAA2D511646B2CAEA65E716F31B1EF4F8CE618D9E61DED
2BE5D247D4E5FD9C51819F2FFBF3C6702210EE5509C942E781DB52ADB4A65F2DB3688F419447
0F33AA11384BB47EA644E48BC508F8C4F561FDE0B5879FC642A7A9E89F94B273892DDBC44E59
DC35EED991B4F4EBF0C9CBC525C572CCE29F3C7EB313D067885368C2EE54760A151982FDEF76
B90F50E763271B1FB242038148631DC2BA1A3204EF1206D0AFA7B78378AB031F9069B8639FC7
40D165EBF123F69A5F0DBEC5D7EE2016E262FA4B611C383E2BDAC77812774DE0591248C23038
B9CCD681FCB91DA754279FE274DEF1F3810617559F2EB5EB47FEDFDE4B5E6DCD68951E685AB5
06EFEABB70343C619507C4B78CE07D198413323BD6A4A33517EEF599D6F71BBEF63FF166D35E
9D2DBDEF74EBB3CC0A316D11167CE2F226F9F1FFDEBD612A2452934CDBC9AD1FE8FED8406FC8
DFF39820D6F74FFE9B4B70DAC1FBB22F5ECEFBD7591DD4365CCFD300AD9544C492A899173611
CBAEF46FFAF6F94367BA0FE02E198290BE926B80D9B626D15A0AC90D5C0B2A28D55D1323E0E7
FB203AB131D783F6E3F878D1AD7FAD7FACE0A9A91566A636E6FC041986FC25E6D59FD6D535FA
42C1952E7C0AB503A57DFBCA3ADCACF5AC748583F112F3EE9DE553112AD7ADDD4C15DB76F3A9
10058AEC9DFD32C233D5B9498C33E7BD33611EE3DCCE65712DEECF4670B51AE23C42E2512B62
A38D37201AD34EA9ABE5F0B99B223DAF1F96C3C1D4B2EF67FB0CE63B4E1C6EDE64A5D30DD3E1
0A6D4B92CE81C7DC1EEAF96F1F1DA540F94D6C4FDFCB72D408647A4877B54BCFA2626D4E110D
E46938DDD15B14A4AD6F8044B7AA6371CE2F2EA1CA4A13ED372CE415ED370F5C6B2EF218102C
1A338C8C4D6004F4962065A028E68439AB20120B5846EE1B66B4396C8F3C73B9A65754D7CDC6
A5AA7E5B4B7A179AC0AC55346E084A7BEB4E344B817E1131C2AE566AD6115AEB56C3169DEE98
C52EE0AD6F4DDF4B05FB7A6B4D672D1328B539DADE8945E8E39873AC6331727D144AB149BEDE
92D7CDA9FFEDC8821A61726ACD8326AE6EBE5FC4FDC885BC16B1D1C22C757B8B594B29AFFD48
981DB54370FDA73FCFAA30DE3ED760B144404F38A4AC17817E52B0856ABE4459AA3721BDFF5D
2751CC876C1BB1FB64C380DB6181E2F3729F4AEB99C49B3D128D2661B2050DB77992E189DC35
5BCB9D15A819D60E831038FFD66708F50B2CD66B62BB8092A13D012FC70C815923E08297C7CC
FAAC8EDEB41A52F041777881D67B19867C4B766C5BA0D18551CD1471D53489D807286A6BFAFA
46271735B699E48807BDA0C057CB88AAB5279F5E6F7ADFE5F34BDF3C81A1C5C83DF44D07CBF5
464A1E0A8F0CAFABFDA5992B64BDB9C13E743F44C2F4AF0C9A69503B14D0BB12D467F62EF24F
8EC8BCA1A1D2E4FBDDC856104A67946D4A87C08F38AECAA481D401A98C488E622CF8CC0B3205
1AF70DDDB4E73888FDCE173D8F5FA75062B974794E9FBD6C3499A3333DCA75C681C38345CBF0
75F6B8F49788DB4C4DC96B93F7A166D33BBCF7BD27778ED38290A439C1974AB944D04FB6151F
DDAE7C736F1B0A21DDED2DAD0AEDDDFEEAD170E750F81B750ADDA463B2DA2693BA21197C9625
1CA59938E82E5BE892C6C659605C1558A6FEF114E30F0FDB712BF1DC93F2F3D876CF694C9FB3
1622FED5C30CFECAE5A637013C3036CDE5CB296A8710EA0141C47635B6758756CAFAB2A04B92
05564C82BFE89649B1DB5D5F255F925C754A4C3E81D0D040F6A5CD9B28D071687377437A47BD
692AE6867C940BB2CBD3E93EC8BAE25406DCCC2ED43D1F3906E39FB01E1057A837F70FE104AF
10E6AF578B8F557B4522D7BA0CF1C553438B7621921D297FABBBA97103E7F6BC35E48F745AF5
A1383F71CD46EE88A33F3989795F802F0CADD26839DF33C849032D7ADF508880B4C1252BF9D2
3F025344BEBEBAF35333E02DB37FD3F64CA9F17B789D55C7CE6DF7512660D4033C85C44B7144
46D9EEF2839E3D953F81BBB8CCBF7F4496E197786F43CD1CDC39602C40B402B7698E2080FB9B
217433D390BEF7A1B637EE1902D810B11BD1CA27DD4FBE2C58640A91B0229FA8F4C45D5660F4
72F10704E9B9970CB77CB14036C4D8603098B893DD139735CB18945BE26755506995DCC27E9F
94D1B63659B8399E9EDC933DE2E3DF9D113C1410898E2E7A2E40736A7FB7E9979FB0B5FFDCDB
2BF0C4D699EEC0B3D55B26A3FAA6C9E9D06ADB9F4CC1F14B0708986DD9F86601CC4CBD392B36
6F8B650B855919C8FA8BECC44E5B1DE3DE2453FF62E0EEC0F0CF86D2E165F1145D5E8C2EFBC0
9D96F537505EB861BE6D21E9C054C39627C804F05966EC1DCC8FB8558696EE825C11BA95CE2A
7EB40507EA5FA7DAB4DC07BB973B935DF8ECBE10DCE441B82E982FF92264975D92C6A4C7705E
90585A308CDBEBAC9B467522015D492B0A705C10F6C195196AE3C532913ECF9BDF3389A957A1
D6F552BFEE7B1F9648915AC3542FBB1A528CEC05370B2BDD7542685A8E4ED35BF2B8772EBC5D
A1FB2E09782EA61A2B8772939F13531140277AC633BB0AB6F2D237399C78CA8DE0E2E271BA8D
DEA24B3ECDB0F551107B3220E2C842F8082A75DFFF85DA55AA2D40518D7401179E6BC7E033C0
92E5F71D8A48F571F7C7CA5B6D0F5E4A109F39AA559CD30EF032766F692E47BF0EA5723C7758
A1392999A28F042005B7E667E62A09CD60F807BDADF794076F23211196024A47580DD9739FD1
0E53D04EE4EFDDF89FFD6E07F107CCD9634874E156849CCCF624FDB9C85145CA2057FDE5CE44
8E4510EF1B3FEF2A57E0125B37DF08CF935EE8FA0BAB7CE745C8CCFDAD35CA730A284C1DB31E
F26ED4B5C397DDBB2A741049A120AC4D8FA9A2B91D3EEA75D61B28B19FA8789DC945588F17C1
4A81BABD6E0E5487E2BA1AAB46994D69F7E5A928CEEC73DB5317B3D58033895595A1A2188E45
7C1C8845CD7312029093574CFE59D8C25DFB577C949A5E4E56624BF9942AE6F8970A1BAED98F
135CA7565393E6C4F80F1A81930FC3F90342EFCC0819DD02CF88343D4955670DF65B59AB5F55
4BAFBF5A9404241A3274A7D2C90A1E49ACCFAE2FF5D9624E708A99A4C8104B76F8EFBA7A4753
05BF47661FFB2FBE93858CC5039B3279626A7F7B9A1E210662EF101252FA4F38DF01407F143C
007DFCE4FD95CA4FF7993FEB03B7CA5A6C1B6C770D684037AB195AD689100484E7D044834519
7D16231C3C129A3372574B1D261B458247A6604A8C3842EC7C6FEA54AE1EB01B6E7E922F28D5
6566CA27879BD0EC14C7DF9562BF8F934321335C26C8AD8477DB8CF0E267CF8BE322758CA333
7F010D2CF9C2C9BF88B51ED703E036B0BDBBFC3F92D7E0B4601573A0218552C5215532E9DCCA
D95BDD11A0A9ADAE050C87364075B8072F819F49464E1BFD5EAF51EA922287EE507223F017C9
E898DF5E29F57AF38DD390F93F425BDFCA14492295773B5AAB849002C613A2B8BAF474C7FB1D
BBF6B1599EFE3EC5A49F72A3B69F1F9073A5CC06E2B29FFFA1B689BD8FDDBA766254F68B1D85
C822EC842B897CBBE246CE8CE8BD44E718B10E0535423DE475643472152C4C607486AAF92A52
574BF6465DD6231305CC359045D3641076DBE7D55AD508D7383E5FAE63A768AC188DE72F7F29
4211E87A36F2F18015A3DEF4CC333A25926989AD4CBFE49FB9CF9FD2D9BD167117882F707842
DC72B1932492BCB7062D86EE51437B696BB597F657D482CA902E779B52C727F02010A21C3D17
F1750D4669743288DAF186CF289C59BB4E0AE268FC305ED2CD69EAC3047C1AB6A6751DC634F3
71841623B74EFC893094EAEBF841AC1F5A160427F3D810623098C1F36E0F553E51A11B0248E3
2E1E9B3B092FE2A6B785BFFE8BEC4F8BCFC164B5D7623C123C8C2087F256E2F9D71C363CFDA9
D097D8CA2A02E48FBCC9BFD5DE8ACA3D8461D78FC95CF53AC18EBD48E959E44B1039E84C7426
576CAD6FD4F07A9A328E86061E8DABECD9D87328AC532096DCDFA647DE1C049FA27EE5BC7717
22195AAA84338E6D63507BB45B560220FB24F93DECE0FF3B043D1912B28D4D913888E424E6A1
E139FE7A7DE79DF5DE84E31075A132179ADBEE07F794B129DE7BF93E2B45BF0100949B359CC2
EDF8B9701B4067DA2AFB6AE00EB03B79F2C0EF420B42D9FD22AF9FA5DC68BAF29DD90BC13826
2563BBECB07781B9A9FC1A98A53F9036B10C49123CDAD4EF342C5C0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginFont: CMTI10
%!PS-AdobeFont-1.1: CMTI10 1.00B
%%CreationDate: 1992 Feb 19 19:56:16
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.00B) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMTI10) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle -14.04 def
/isFixedPitch false def
end readonly def
/FontName /CMTI10 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /Gamma put
dup 162 /Delta put
dup 163 /Theta put
dup 164 /Lambda put
dup 165 /Xi put
dup 166 /Pi put
dup 167 /Sigma put
dup 168 /Upsilon put
dup 169 /Phi put
dup 170 /Psi put
dup 173 /Omega put
dup 174 /ff put
dup 175 /fi put
dup 176 /fl put
dup 177 /ffi put
dup 178 /ffl put
dup 179 /dotlessi put
dup 180 /dotlessj put
dup 181 /grave put
dup 182 /acute put
dup 183 /caron put
dup 184 /breve put
dup 185 /macron put
dup 186 /ring put
dup 187 /cedilla put
dup 188 /germandbls put
dup 189 /ae put
dup 190 /oe put
dup 191 /oslash put
dup 192 /AE put
dup 193 /OE put
dup 194 /Oslash put
dup 195 /suppress put
dup 196 /dieresis put
dup 0 /Gamma put
dup 1 /Delta put
dup 2 /Theta put
dup 3 /Lambda put
dup 4 /Xi put
dup 5 /Pi put
dup 6 /Sigma put
dup 7 /Upsilon put
dup 8 /Phi put
dup 9 /Psi put
dup 10 /Omega put
dup 11 /ff put
dup 12 /fi put
dup 13 /fl put
dup 14 /ffi put
dup 15 /ffl put
dup 16 /dotlessi put
dup 17 /dotlessj put
dup 18 /grave put
dup 19 /acute put
dup 20 /caron put
dup 21 /breve put
dup 22 /macron put
dup 23 /ring put
dup 24 /cedilla put
dup 25 /germandbls put
dup 26 /ae put
dup 27 /oe put
dup 28 /oslash put
dup 29 /AE put
dup 30 /OE put
dup 31 /Oslash put
dup 32 /suppress put
dup 33 /exclam put
dup 34 /quotedblright put
dup 35 /numbersign put
dup 36 /sterling put
dup 37 /percent put
dup 38 /ampersand put
dup 39 /quoteright put
dup 40 /parenleft put
dup 41 /parenright put
dup 42 /asterisk put
dup 43 /plus put
dup 44 /comma put
dup 45 /hyphen put
dup 46 /period put
dup 47 /slash put
dup 48 /zero put
dup 49 /one put
dup 50 /two put
dup 51 /three put
dup 52 /four put
dup 53 /five put
dup 54 /six put
dup 55 /seven put
dup 56 /eight put
dup 57 /nine put
dup 58 /colon put
dup 59 /semicolon put
dup 60 /exclamdown put
dup 61 /equal put
dup 62 /questiondown put
dup 63 /question put
dup 64 /at put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /bracketleft put
dup 92 /quotedblleft put
dup 93 /bracketright put
dup 94 /circumflex put
dup 95 /dotaccent put
dup 96 /quoteleft put
dup 97 /a put
dup 98 /b put
dup 99 /c put
dup 100 /d put
dup 101 /e put
dup 102 /f put
dup 103 /g put
dup 104 /h put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 108 /l put
dup 109 /m put
dup 110 /n put
dup 111 /o put
dup 112 /p put
dup 113 /q put
dup 114 /r put
dup 115 /s put
dup 116 /t put
dup 117 /u put
dup 118 /v put
dup 119 /w put
dup 120 /x put
dup 121 /y put
dup 122 /z put
dup 123 /endash put
dup 124 /emdash put
dup 125 /hungarumlaut put
dup 126 /tilde put
dup 127 /dieresis put
dup 128 /suppress put
dup 160 /space put
readonly def
/FontBBox{-163 -250 1146 969}readonly def
/UniqueID 5000828 def
currentdict end
currentfile eexec
8053514D28EC28DA1630165FAB262882D3FFD20326947B1065649B533EB5E9E3A88A87FE9879
18A687950B26F647D6E08BF14D983ED1D4A8CA1E2DA8D985F9442EB916F5B6ED0697AC7C33E1
E36A3BF460D34CE45F1631871097CB04F18E38894CF4AC1538EB19481311D24FE3BE7BEAA4A3
730E8B4831FE59D6D9CE2E46116B629C7BA2F9CE3ECBA2F43BC162A5A077CA1B2882A42AFDCE
C3F4B75B5D63E0BC8E5DC95257766D8EA467AD9CBAF47BE60F797580CCED6884B3A68F70C91F
4FDF80FD00ED9139E7F480DC3A76AF72AD9B434187730BDFAEFE4CBFE5C7EDCAAF249204FD70
3011932E5A3C27BE468B7DAB69DAA18DBBB6335AB8DDFDC607961C7C02582763FA069D43563B
A17704029945CF42FCB19CF78C51DF0EC4D851086D43C1AB38E865EF36865FFF3A08B01CBCB0
70BA4893F7482DC7819AD03D337E520E7D8CD83BB8AC7AFF4DF36751F4F12AAAEA2B6D7260C0
9A26E987C904003E07237DBCC4A8E4E85CD3259F40D3CAF55C742CBB40AD0DB1044C20A4F122
A63F7B811D945BFA69662189CE4D089464D2EAD9F6ED60B581B04114D5D45E97BE27A5763515
4E9B8464F2A0DF18DA855EB51B8F64D3054B0B2E84621F025A0776D16FEDB988A43D2D64C327
68DD106B9F541AE8E68AC0BB7399E16F4D4BA074B2152D0A4E9B5BFC21BFA0D531E28165E518
FFC054DD4ED0D74ECA079D20E79670419F92E03BCBFEECF3554D661596F6F29E12170804D15A
250D917FFE7A8B6E8FA530471ED97BA56481589A65CA13619129F1E26AFFE6C22F0C38540F8C
E37EFB6E9E9B60B51A5A9CB4454FD7C7F92F2F9437159687AB590F35B946A54491A7739C9269
E0F1FB48B129811C82EDB3171CBD5105FE65906974DB8A7DA92F4F43DC7F6B366981146D86D2
3613A0B38D9D6191DB9FEA0172E982CB1CC50E382F69DA1B377C1BE9407F88A2A761B56F3984
67A057F35D18C01CC377E006182C891EC80272E22E3A5C7123CD27ECCDC87392A9FDF63BB40F
02B7649CFC53EF933C6518744CB89CBBD437830EF5B1D58B00B67BBCF4426DC1E6EF583B0B4A
D3AEBD741E3FF0F729AE271F032019B1E7268043FD215BE590F9CF24DA14A90F1683AFCBA800
6CEF5D5632C2481FBC1BD8224E8952DEBB7C4596A237E5505AC143180956CA1F603EEC70CDB4
A33E1C4CA1744E08940CE778E246938429E09E84F5D90F2822272E697A2B4EC52EC64D678F49
D5AB137C105A467B7C4FB2B599B8536726935A90145F426D2F022DAD53995B991E97744C027F
A0427CD1117AE246514032F3FBAAF6FE9B496D6A2BC8BFB77040D26EAA434609FE89C1FFFC3D
8081B8663582B893912B7C7C56E5753D23DC2FEF5C3AEFA09929F7470ABDDC99ECFCC44C9456
5201A19B8AFCFF6C98BDC87E6A7900F980EA0020FDC7ADBC97FF99578B809932DB7B9B6A7832
222855A0A586738DF9357FD3FE15B89218BDE940DC77842A8DDB973536AB81C2764AAEFED023
A7F0A3090FB38CD8D51AE7A65300CFE08B3574C621CB1A9F8EDBF84BB034A399F6F4237171C2
D38DA96707E2DAB287F025A8D50C192A6200C771DF9E79EFCF03E92C0EB5E66AA1D3A0AF1F40
789D9EC825336FB0FFBA43BCE0F388E21485B432E9BC85AD56413AEF3AC49035CFC5D31ABA69
7B505385DEC0D36F76849FC55012616820E4D2ECC1E05A16A98438A966526344DCBB7FD5A355
2EF61AB1CB2027674AAB594074DC7B4DDF7C815529B9ECDF39A148D855940D0A60AAD8F7A4CB
1B8C1402BFF8AB3EC10D088B6DC9B57E047CB7E1B66645986DC6C9736F707ACF15A687E04A8B
D48189A4933945FB77522F1A4DF2A56479FD4EA1747671E0324590BAD27663DC32ADE591EC57
A1414B1332BE3EDC56D6E354CF94C1D793A9BEE0646C69C414ED22905F413CFA73F9291BA0D0
BCEC956B0F15FC29FA7B50C20CBFE3069F86439FD2454652C021183D3365EBB8A3632D338A85
D22BBF99D4E26AF8F5E9DFD464C9CF24FB59A2F5D08CE669207684835106491628AB823F335E
3D035C72FEEACF1B1957AA65F100480AD9D185E042E5732F86A8C1A74D3271741F115B15D54D
47CA2091597340C5165DE89E3389292B62F4C38D90C19390AB221460976A3BFBEA7130829D3F
749E5E555EDE6485F2045E6736617BAE92FD4B6286212DEDD3A130257A26C96B81B73059373A
B37D1B5FEA8545E584B28D8D9C943AEC6D67C9C33BC448F42C56264CA8166302A6C58616C4E2
418BDBA38DD8059838A708E92A1DEAC20FC598D6B1D59D910B8DD3C9D249D55B2B61880BF682
A3DD3F28CE356CC554AEF00887EE102657670F51256DFD60B05937F2B4EDB62000588383AA24
5AE98F52EBCA209BCA0146A1BC9151106661CDACE63C5F043BB7C17DE121CEDBB2CEAA3B7537
7A842C58B8757196C529C828A5B1815D7FC80B98304A1FBAEDF32CD0C397F4469F42D36CB3B1
CF29F93FF29F6E4208CB5505F08428508CBEF9C8820310277FCD3E3D69210029606738ADF321
480B677B60D9AA7A1C3338B74CD5208B695EBE12824D05643257C55176931FEB01CDD048B787
0F1CA60BCF68D3BBC0DBCE536137F191FBD51FA9C55170FC801F6DF907E12C7C84704481CF4C
464C0014B93DC2B2F3346420FC8698B3397F567FD7B7A12A88BBDDF910BF6EA1EB7A1D45893D
0D50A0DF8EFE2119BC1DE67AA1F8E37B685DAF05544796DB85043111C781F18F249D5C89F463
3157B5375E46524DD71E1A373C984F7B273418F3CF69E085086B81F0CE832A74407D4BD3D57B
B7692DC8313B5ACBF58288CF188509DECB393C91452BE861715591ED61BE38953264EE1FE854
4EDB10BD57576A42F4ACBEE31709E75F4B5E19E61C9EB07D0912ACA3FF457E4B7DC75A7F176B
5EE402CFEBD3F2AFEB06F55709AF93320CCF02343EB4E06A98200A4B8BC6A9B284771F239CAE
3B24E69BF3580EE9530CB0E5821E2BD42BCF4DE01656F02EC010FB1436E9C7420E1C9800AF06
C384BB3D13418B406330C755EFC0E390A25AB3EB067178D072BBD883ED6676BAEB11BB627D6E
3AC6DFD4EFF8D1C74216ABBB2504E0BE03FA43574FB09D0639CF4E1466C799486EECC518663D
2529AF8F9E9C01867962C5936AD3F34D9F62151A3EDFAC604859745C8BE54B96B9C9A766A589
FE16FBCC9463243A24F769F16B4E0D979BBB27D1CC41ED8088B5D5D39065010AD56E130B529F
BDBB67100EBB288CA74A4FF762FA0D4F4DC509D2E40E550A6164C20D89D9716E44ACADF72C0F
75B44A025A3748BFD1C2413F444420DDD4BA0F451CBE8F70A848C7175530BA97BA140B88152B
733E59842545B1058B3C9C3087045FBD7CA16C6A7D35EC93D9F4020AF5CD96164103C60A8FEA
B77EA9589A6C57F0DDF087C37D2F908E3ED142614B468C2C55C1061507993ACD42357D8DB592
260C6F387F3E68F346BDCC88AD2EC3F42BC9B8BF3923066623E6E7C603FA509FB89D3B6AEEAF
2F5D8DBAF5883766FA5FFB70632D1DFEAA43BBDBB479C67CD9101C73364360E07F71CD82C0B4
384A671FFC0B54192CC4E4D200BC108E94F27BE0D95E96B4A5E2A4EB1B8A1CD34D37BB15D3D8
95A0E2E9D1FF377A2EEABFC9D79E37BB4526A97E25BE20ED47F48919D0C8FD08616F28E955BF
C850A75BEB2D9C495904690A16E14F9C349717A60191C1E3597273C7725D1999CCE450EB4018
7987D12A073A6F7B21504D6E352B005F0B76846D78EF496664B7688E340296E6409A0A514618
19DF537F25411604DAE5ED05D2BE1C84FEECF8A4D1E6979A4267DE24650F91595F5CBD8A557E
9D76BF0C0A012C697454B7923706970DAF97BEC8D19000FC6D9526896B0A7082A3E467DC78C2
4592707204325A38889B381AC8AD33BEB76B0E6F065D86A6337E2252359860E2EB3DD8EB957C
D853FE1397479DD2AC5AF33E26A3895CF08286760D20552A65C9559B99CD1003DDA16CB0EAA2
35AA8894339CF6DADAE0AC5F0BADB255D9C9F9D480B9AC3810959E13D736AC95BA70B5B810A5
7FD0B6E986DC38DBB70A6F81F90A5458716DB0D3E121B6357D36D75429F9587541D4493D5298
354BB2745D6148314338C2761C4E84FB75EE364F44384D9B03B81C90F6D35FF36BA9296A7B1C
03661D7C4BEDD5E88924692F98E3269ADC4368A47E3729CE298E0A86A3DF13AA3754D4A59048
DA3AA3B2A48291FA5358F1FAE1E833E3FBF6EFFDDB6AA644BA2B7F1F4EA616A05AABAA9F7F05
F9525964A3A82BBD155C22AC47D00A01A81F5B85C7DEDD04E707AF0B01BEA577224814281123
93C8B2FF8181CAFFEBAEEF47FBE8D24B5E906011F1FD208B2A14AE81A0FACCCC85A7628FADCA
B755A3BE8C0365485E2F8033FC40AF6F2F93A55366EDF457591FF993EA13BA6D12F31ED35385
EDF1FD7A9273208B118D2F105F4B2FD0745026F3133F78F624FE464061CABD65C13D22F08CC7
922E824F3244754E97AA93990FFE77D9ECA348DC30D7865A9AD09E67394A89536FFC851F486D
541A52CA40BA74EE0B312CE09168116A7375A426218224E725A871EBAC32E672718803840A5D
D03861B6CA4D6BF8850B5A328435D0DD7DAA9DE329F123C1B658FFBC41DBC48F5E3160BC6091
3268DB289C3431B44DE07027E6FE9C079DD3FE1864A58AD2DB80F3E4BBC6897CE5BD288C2556
B1B17D67021B259C4ACF6993304F6AE48AE0292E8769A5D6BC943970383715F2D03F8D5956CF
8C86C0EAD6CCD278E4C415350AD8BB589466166B3EF12A36037BA29C14C387702C7EB301B4FC
58E8660F3738949D98E6A5537C4310992D7B96D7045647D32B892273F5ECEBA013932F923BCA
AAC00D62DEB318DFF3288D73A38DBDF8B40F690EC4F246056E8869193F03FD2EFB8860DE3BE1
A30FE9D642A3DF5C59340394213CAC491A554C33A46898E797BE1BC70E04B586367D451D98D4
3F48BA27E21A00DF8F0792967BC7B7F6483E55C7D917B11E973F65DD003D5C732163D291763A
6C598628F789D4866B841B7E4321109277FB32DD682446363452F494CF0067D159C16352D9C2
60AAC8673C74E10517FF30F4C0C4F51CE71D2126155E22ED3D52A523DF27E556B0C1B3523354
6396F9921B62FE6BF3592222C9A868F6FF989C1E86C86575DA51D336CE9ABA13532A59C420AE
9979EAEA4DC665ADAE56B7C1F4AF84E9C5454E17AB14C6FB7E4BC58019DEA386A294B2F4C8E4
722BEF99833C5E7EEC04B49635496B5FC7D3D277B8AA40D9E87F154BAC8434B86332C628BF0F
B2C5B0225DF39E5EB5760E19D21A7B899BECBD9C189C088F66651E5832DBE898DCD0B0D3E0C4
C0A7A81AD20EFD8F2ABB15010856DB816C72FCB7518839DEE4B259C6E88B9FA2B7FF3DCF2016
15D0047712D8EC796F99FA5D4FB2500F879B9EFCF03926C2F43C892FDE4B954FC5496E4D1A11
66AC197783FA28F54063FA50EBD85DE2A5481C387E9DBC573D8604642F932775B37949E92410
E339AE70A74BF7E83990E4A29649E2E4F9DCBF8E680F9B5E5D469924983D791217D043907B52
F8D3B3A8F80D1BC70CC13A00A1D60619E886593CE96331EDA74F52C79ACD9321DFA9A2B14740
6E937DE49ECCA2B605D7364AE9C9AD75DBAE4DE32033A8C7558ACFCF6B7B616DA13BBD800EFC
CF68441503558C1E42B894FB730197B63D98F0FBB1573FF2DA8DDAE506FBD36F538FF7B84525
0989B8EB42290238DD2FB897F223A92510F6BAE5240C620D32F408F41B5043074C267709B800
EF5E78BC3A07083C74A7755DB20F73AB7EA69BE17674632CF4BD14DE5B5EE3CB2CAD485D7C57
73055D8AC16862EB87A584BFF94DB2CB3ADD7B7A3BB91202FA30903B403D7052FA1A7EF796E1
9C89229FC8E5B5457FD7FD56769A4A21A7A1D77EA6BE8FD42CE82D40F0FBD7DCB53E1DC0B2FA
5F9E55646285019CA7A780D6B47820124A9340669C6E5DBBB42E5E4561D068D3EFCCF308499D
3D4CBC3105FE9A03122E3E78518E6DB513AD56D20994794FAD9118EDB8964E24219E74CCF25B
4FAEE0086E487D7FBAB394059CFB6695D22D58387D547BCBE98D88F259DCDF1B2C2B68FDB052
FD1116D6B584970A7F8765E82BE89F08EDE9EBE22D24849593C2166A2F35CA1C5C423E0AB955
A87168EBF31521A06D5E888F15A66ABF2678E55F5998E868A14967943252DCDA93AD962BEA97
37A91E3AD4881A41F8D9ECA94B0A3F66A29DECF1A5154E2DA9E5F921484DE95A433354DD8F54
48D6C84B7D8A8B4CCC5A9FD2812C40146E1E34F049E97D5FA12420025BEF27EE4EED347816B2
F8BC817282011A9F467654D7D33F0ABC190634978931FAE58288F66A8D057AD853E6A1877239
095332735001B0D3A387410D82F8B150F5757E7FED55008556F8DACD57376D64EF29D14F2606
DFB3B35CC3AB3D78CE2D9FB33352D5CA2EBF74204CFDDBC3E2A4841934B14CBB3C1B55D6C68D
61087C8860AB978530CD76AB5778D854EE0D480C0622876701E257081B1862A0311ED3CAC02C
90CB20D0FE5ACD34A5BABE578D188E804FC6C27511A5C8D6AA7CC96E244598C7B9D6FDD0F731
20926C4436B0D0E6D549DE336C308355BC338CD10A0F43CACDA8DE545FCC4B33EF64C1125E8C
CF9CE2AE9FF75FD93EBF6FA54A53EC4D13613B6F26F8534B8C829956E73039B5146FD549129B
40ADDE993CEFBBDBDBD029F96C5C4B68F9B2EEE6F9B5972053BDC16590FC6CFF24B8ED696BDA
5019A47B2FE78D3BBA20AEAAF10626A4536B43A196B6709D03A0E46640B1003979192F3D3190
458AB3FC9BA4E05E840409657C3D12D160C359BB902F7C090557AD37A72C04B7D39BC261FDB7
ED03D1F72932A8E15897F4871E852967BE07A0A41636E6E860887DA67415764AAD5E5E1525E2
4B6748823B012A0B7F78F686423382E18A8BB0908C9D6A3AC68759A8D5BF2BED2D55142C7F52
4B2CF5C7E699CEC25525172363EAE0132284AFE68F36D39F52D5E25C111F68237B41B9F69539
72E89CE7F43FF62938CE5D51D730D44CC79AF928D5FFCA2A27D679174D21ACB0C6F0B97BB119
6658C28722FF78EBA6033756277B14352B7349D9DE3BCC97B990086227F002BE7E5A930581F7
6A5712B0A8B4586F4149F2E46E5A7728B708BA5EB0388610EDED2B66C0B48AF87565CF9FC1C2
BF488B141981B906A938DA0A1500A07D149C336B2563BF25F03103FC515224C45EB8D05C3AA2
B9D1DD5A3753304FCAB6BA868C21D32E6D5B26ABDE7EAAB5B0250AF4F2F4E773FDF134EA6308
1405DF0E1C3E3557C8F94B242D6027D3D186A2CBB0867291D7135A3A80106193EBB57157FEE6
720B6E4E4E13AF432B1C197DCFA0BEAE1F6A7912EBC096D22E8B48D483A4DC1070FF8DFC422F
A1971834C27FAB2CEFE8F811804DAD0E8A47566DDDB6157F766E21847A79698BC8616B68358B
CBFAEBBCF88730E753EE02B2AB3C4D2F5D13E67C5F24F74C2D6B7C06FDCE184C7AB7478A3AF6
9CD1600B258CFD04E29E8A8D90782CA96740AD6FD48590435C47394EB7F73D0B213757BF50E5
5D9003B5F53E2E8DF40BCD0FA6B5A5B4A86E710161BE8FF0C0F4EE28A8119F1AF1A28F7638D0
F76D86B2F99A3B5691C1C3106BB4A7E254B5422780751FA1D76D8EFEC2A1C3275B98B0E3D595
24F933E4CFD96910E59082C59043AD8EF6802D99E07173F306290BB5CAD4B43B4F2786296359
E445DCAC16FF085ECB5EF331CA1BE4FD7875DF302A589EB8BF11D1A85419FDF10708D0D4F5A8
CDAB0C7F74D56296A3FB3C8D7CA5F80AA19122EADCFF9711E7CEC929B30B2ED69535CF3CF6A3
D7373D65ED5FBA3E5E4CFD14BA54EDDF0AA35867CB7ACEB44D12C3CF2909176E6219A0478F72
FE393C34B4C0B7F844AE17DB5AFFF0B216539365A8AFDA4616A202A10F148532BEC7DDB5C089
64BEFAD32C3D240D8080E3948799A5C99EA538CE687DB7093F151C0DCD4C810A83733AC953BF
F76A0988B356FE694FFD6371E8ABF826269EF1FE6E1814B09D99EBF4E5A6949726B1064F16A5
D00AD8B86BB7A5F9B3252E4ACDA4DBA523F5D662E116C02C70088D8C6F93E3747D6E950D8BC2
A10FE920854D32DCCD9CD1D07A730CB2D02FF7134155FB2216ECE0E586BC9ED91EADAE541C2D
27F1E9FE1150F50E1860AC136674FDC9FC0C2BDA554269205458150EA28A3228E9A2A3372DE9
4888D001087F64CFEFA4710735621D6EF35228EE3B257F2C69151F6E119038DF1643C44850BD
C04FB362276EA0E4FA4FBB5D635F98F4B1A0F9B070F1A38453FD6C651F0F90EE471148628FBE
FFA386BCB1E6F63366EB7FEE4920776995E90E0684E05AA0A7EC40D727F4E3484B02A3E66CEE
07D18F115ECC0ED297F958E123298795150F427D12AC6BDD2EE0089FF6910AA577889C668AA8
BB5076EAF7609FC498C6C51D4231AB6B2E2850A51B59F94FBBC89206CA91FE9FA81AA9AA5D81
7AE5AA9A45A6FB85D5EF47492E95B9626C1FAA1F8DB33E8499712992CC43FBD7F2570B15EB0B
F1DED971B2EBEABF24240034BFDABC06C5851E828980DDED018316093EA6988DA1F76DF79CFC
90AB99CAE0330B7F2DC517F7745EC3BA7096D76013D53F093D1C21A5D475ACEF361501A97F1F
034802DC3954294BFBD0F9BE301714D958D81EEF8A0872458529A155B0C79FB4685DDBFD2FBE
E420EF4CE6442E3475211D10E50B9692DCD25E5C5473A817237552934848BFBE48347E38E0F4
D851E0C3374EE6A7915C702C7273050BD74A118FD3E84E0B45B4F3EA30F0AC4BC4689DEACD67
7DC7AA91E62889515D52AB416B38103308A7B301CA32E28EBFDF6FF2BB3D93E93AE5A40E9FA7
CABA10B5F934387FB0CFE936F32274624A21E87D4556022CA7447531307DD5BC906A7457C696
C7835FE81F3783AF019180AF5117B21ABF50EEA2195FB8C26738CFCF7065DE53F9E5C29EB097
4B70E9DFAB6EE3A342DEBC28F95BFE393037D80B3E027E8435CE534DF47C97D9506889A22504
4C018B53E519810AAE47E69F66BFF8545FC0EFDA675D3B0D9A4055CCE2FDBA4EFF27B2E638D3
12FD1F49FED76FADEFA163E01D3C7C244363B57D78C871E9EC5579BFA2B0D9A220A172E6E850
DED5D7B8D61ABBCB54540F23766DAC40293F129833995EFA7F52CADF88B7E00CE636CBEAC6EA
4A8B00E7925B0D1AA5A4CB818BDCA2E70E37161F3E717FF40FD6F4FE77755F5107B3579F262F
B59712C1B56324F8AD7028DAE5112926DB9ADA0C28D7E8615D96BB8ACF3FD6546E47FB2F9D00
3C52C5175EBDE4DFC9E0DF447F4A8B5DE9370B4BF4DA5A84E435D53E28AB75966B41420D4D07
98B8779E18141D042351179C8EDE08307509711EB00474B6E4B12446184F4AA94AC5327D5B0D
2D3D20B4C4C135EE91B9E283ACE06DEB9C1715CA8B78CCE477131AB802E9F5514A82D55FD125
A93FFCB4385843D91C56AC170D442098EB5F4CC728AC8034A1BADF5390F1D53923A0BCDBF36E
55938B45F2D9BD8B10A7E5F5FB3245BACD83E9521CD85B194437A4CE9685570B3DA825A89657
AFB6A68A7AE6ADF3EF5D92AEDAA420BBE86B7C671245CB98307159AF74BE629A8F46476BE63F
FA1628377D256A86DB6F28C9BECC892C2406F04FE381BA5A253829F4C07EBA8AC16BE5CB46D3
E63F1BAADCCE269C66133BE8CC60BCF6704721F6244CA012022BF3482C5B24C9DA23D9207557
8EED35640056DE0BC4C36EAA208D6FF1CCEBC602603EDC85EEE05D4DBCD6791156F6C1731231
E77AA5787240F70900CA7B8718CA1FE9BEC6F8EC59EADDAA18182181261815602583C85EBA52
4C7C18DC27C3A4E3CC14C7DFFB2FD1670B36F2F4D38590460DBAA3B6A992AC133605603AFBFE
7226049FE41E69F04C4A6B2A01D06F5519B55921F820D1A8D12F11A24C0323C35CA2025786D2
CB09A5AF4E3C2DE113D18FFAED07A354B72F2190767FE9A06AB3E9A88F8B00CBFA3C12B82DAA
7B436E20AFD8148006AE3E4968C2D8289F41CD7D4FFC61EAB1A12B60A3ADFDADCED9754F64A6
48A458AE66F5A44737B8D16F436321069FEAAB9AE8B0C10750B3C400C5C827BF3674F0F34213
2F9380ABB9A6EBD54E0E800840E24794EE8E3CF6C75AC62BFD288F05435340AA20425D1A9B75
939C627F825DE6EC589F1E40632C49379345DCE3B3A4966BA4611DE2342E31E79B25B33DEA83
08A96D57369CC8570E31DF0B9128B25A21B0FE44C4A61329DB4E50A43981686F9BB3FA50B4DC
DFF19BA5B0EC564D94EE093D2DBBF135840EE31041AD4B3087FE733B9284B043E396535D0C2C
8987563C94E25F0553E1656E0A120685FCD1042A292C68254F3BADD5931398A725A13641E94D
7D4DD5445EC0C6B52194AF70E72BD7E1FC98418CDAB6C4C4684037976737FC783230E2812330
FEE33D693C37806192F7320FD35A415E7ABE07BAD0E1835EE01BB1953F50B636077FEAC98734
4DE0320EC693926A09A77712C8E01F1FC2E71FD4CBC088CFEBD6BFA203DDAD5F8F6D5CFE945A
635AC949400167568329315A02EC5DA3EC974EB10BBE0A050FDA62F29509734DAB2732E32560
9B85B7F6E72037375CC51C78304950215512966D69BBEC4575624074244219B2EFB7AFB8B5B7
3E95E8DD8B71189EF22837411EF1E1FE4A3B07F7CE3C26557949035A54316349139CAD64E170
B4301A92011EA16A3A5026E724F3D35923DD7F9595AD506B8D1ABBE47CE80846838A29BF7E0F
6FB8ADBF7B27E1D03B98E487BE18D1F5E374647D0BFE3B7A5347586424980E645166D73B0DE4
AC6EADB5680888D3E9D460C6831625FFC7C1FADE5AC680E00B6E5776680803A8FAB59DB1ED33
2B48F8ED919AFEFBBAC7CF977CBF3B8D5EA42AE9D24AA6F61D86CF496473FEBCCFC23E618885
D37D1F52D4AA63C1B0107F4444E85FE8D7A2F65E3183A026066444132CED223F436A33C0FE14
30960114978F32EF956D22AA61A7C0AD7A31785CC40E7144482277145878AC842B2CAD5095E6
1F1036C32E9DB8E771CDEFB32E1EE3D0ADCE43CB1BD8A4CAC9A68199AF84FF4185AB3E06C302
DBA3AAC3BC39A8B34B9815955338C6768E90819FDE9BCA59951D8150356F659F666DC08DAE42
B79D209CC2C305DA85B6E5BD4D471128D0A42A2FA4830C3E4BE1AB4E5754CB127766F80DE2F8
DDEA4A5408C6D3D84C357E78A6D2F46C9A3E376D01A4CF5458559A0BF1BA8B74B444294C6B09
7FF3EAF29A2853C30ADE3DCDF303AA4A3CAAF6728113EBD143B28EFCA63F6BC75E84DD59F823
F62562ADC55EA78031A27E95195D79CCEB5197AB7CBEF883BE62FE3A9390A0F4EF2A2CE81679
C8D73E5329A2C384A2E540DF0A88EA036835B03E17A605F1F350F0D5BAD65335863671CF5F08
776239DD1B623897751C22EDA66DA46475D0420DADB20EBC5A7F325073D00AB388457C99FD0F
90D1AF23394CC47CB8E520BAF775B53FD32573595AAB699FB443F766319AE602064858E50B29
DEEB433427D44C06F7BB6F34F7F85F671B9BE353A477A6B79D8E03BD8418242D0E67161B453A
5A28356BB9A8D9254DA9EA2847A26A8AF54640C65B2D84987038B16A232C40C4CD0A6C12B27B
801AE135CDC3A3B383BD511B42B664110B632A822827C024B4E390319845CC062CE0C339C718
C8179929DD3C590B8870B2CB4A1FB6B1D244DB5991783437AABC5E0D86C2E2BB4A57AE55C0FC
76DFF34D9CE4F9DB23099AAC53901D436A4B0A8E067ED08737C79B75D9CACE67325006A9BF5B
D158103C8078B901170FC86A95BA7671197527852E6FE1540D7F44F369CF1C204AC545A2E704
AD937B06F5ED870623054CFBB8F04ACB4ADE6ADE3FF71525ECB8B0AD69D946E9CD1C160A39AC
FEF4709AAB5F58FE637425B4C01F3AE3EA928F5A478481AF383CEF9EAC1BF1EA61A551DDCE84
48791464BAD9554CE870FB1E85F8C40579BB4D3E2CBBABCD1566FE49A2E17F7AF5E6896C2737
C8017829792CFCF9D753E0D328F96EFE2743CD3F351C7A5E7F76F7EF5C5974A172B7AB5EC867
7FC561CF78E6A732FF636E46BCDFB88B2EF788908F55EAD2F0C7889A22DEE98E56324BD89952
F6D389C98B3287FDCB14A6A45B3D9D3699297D97D69BD8CF7924D94FB0568043773A9A5ABA62
09900F550E82CA6853EB148B537B4F75F33DF6CB3BB0DE3B9F4C117D9D24654235F5EEF54362
4CC358DF759E9B9DDAA3E803C026B82E70A13FC633F0A6C3DCEF51F0B33E11045BEFCB233C5F
9EF1672699EE26A19765210D4CA63AC280231E062393165C2A0E98A0EA1B68B17B88D7B98279
6E8B943C3C889090CED654A29B0F6AF0ED78C8E36A5B753B18F5A571BCC68D3ECBCD50AC03C3
1B888E5D3DE12CC4149983AECFE36E2C3ABA05A3FFB4D0D05676D7CEBBAD026905841F484B90
E582E551638623876486AC664E131DAD613E02AB76F6F9E09390A864E045D567E67ED37B2076
540FBEC8F8B10CE78F1902C3582D625EEF170BB657A7F47A9AE02584A15ABB2607151563ABB2
0EA91FEDD2FAE81101CFFD5CEBB2B538AE0286BDF6C0144061C1283446AB96B4C1CDB8990B49
4F347D3F776EEA433FAC0BC2EB05FE18D8E7457E1AA6E685126CB494B48F98399190D70BEF9F
47573069D1664E4B0D8765A6C5081166C5A8BCED01B7EFA65EBF02839CA4123E9A8D565AA556
4095483F605048606288F7A26CE3A6EDD7E9109C6078431536BF06F93345329B4C7EE3AFF383
726341592756DAB03E82BE0B30059BEBEF482F3E2DE99CEE46421EA59EF355861E002A44E0FC
A5A428336488F5B0B035989F7C569094E152EBCB52767A1296B72409391BFEE6185E10A29733
226ABEF840D10B4F028F4EDE303D245601734B388CB9717C4AECA1C4391ED4054137F6ECE8A9
33444E2A03F67985EDCB1B248E34C0EAE44F9C22AE1C4C57C8F6AAF83141744E81F86E3B952B
0D5045E9C725B23F696B79A60F47F7106F53E331C19CA9B3E54EF5DA6478EC11537572947185
3591F35BA2804F36982CD9A7E5A5963B79B15644CFC15913BE4186BB64BC08B0F4E7863E7A5C
BBB251B2103B5E8322CDAA3A91D7C21455D7A02FC29EA9C9E1C8F021F39931A07080C140D8E8
A4AB3476B4009CC66B8A51E7C161DC2E716472CEF21B68C2E5877FDA42F02895E3A7641FE80F
2EED2B26682BAD62F860A9F149E17A7DE263437BC6335DF4979807EF19E4129459E2FE0136BA
F9775D97A1DDD4DFC2D555695B59205105F096C80B52D4969551968FE51BA57A17F86177038C
3E09E53B8BB5AD475EB70684CDD7FD7B7746609B4353AF0171434C8050CD2948EB7FCFBE73F7
35BE287A5CA4E83AF8B4B26D9A939FD613AEF0F7B6D4126E15B0066F17DB8F57A513FE2C8F7D
5AEECEE35912F25251E8853EE3B0E5A2FDBD9182A6B9C99BC19FFE8D85DBC7146C5F8A8859AA
CF8935B1A0A2189FFA3A4118F1478BED18AD6FA6AE328FD6B6F9E0DA13682D4525623975AA54
DE675E235A4E435ED2B9CB7248B0B1184D590988C9CC5C6C8C118540C67B7885FF522AB4880E
6E6B9C2B6FF111908C62F656F99C6904B57A21C049B5CA876931B05BD1B554E818A1751F62C6
7AE918082F25BB8B4AF8E9186EA7BB7769F924F8C189602BF190ECE0194A25277962C38E0321
F3095A27FB7DA0614F717C2E0A575ED37EB80D6B38AB8C09470D64BB28194F05AA151B3A46B3
71EF51E85C73FD3B9E3A7B476F9A21FFA3BAF12DC5F4AC4CD479795A2CDE98939AA074A317E0
B553267028940A5375A7EAA9A1185EDCF27AA619301751477CC3F672A3D59F6BED11792008F7
341A8DDA4F6BBF643A57ECECF19CC60884DEEA925C1EECAF3C024EF16B09BD5E0B6163CEFAE7
94F61137C44F1FCEAF3140FC223BCF203F663269AD41DC27C04652FA4070B9BEFC9AD37EE79E
AE5E9D703D1E05B9A1AF54D84D5F97607D147A77F9B90FCC5ED6626D18E2296654634CB36FE9
44C321F1D1A10B1AFA8E7E158A32322B966B0F8ADA060308378FF18802BA6E8172D239D6C86B
2D5F9A159B13A29C4DBDB19E2D6EF3502230A46D4468172D8C2497B4F03BC25647589252623F
011CD0B852061893897DBD5FDF7F4282751267AD7D4914A199CB0F046B194C6277C4EFA5BF43
05F8B9D6E97897397E359BDB4CAB04BCC2A69413ABD55545D4B47741FE9C55BA58B460C6554F
00E57AB516B02EA6296E3B8A3D7CAC22D6807280F3E454708A2DF1F9037514CEAE8527659EA9
EA852CB07CE6A14745384866B2DFF0AB77F6BE544DA12DAEA95824C7563A56F24BF8DAB88093
31D11108CA50870DF03593C421D229497370BF92FCBCC0AC9B5F927322B896D96FF6437D6000
6732B9DE9DC0AC9DDB2DE9D44F7E9B92A93F5E36F618EAC8CE21829C0C094FC061C8428DCE42
C028B1CDD84980857A4DF74DE564B20FC20897E79A496DB3149848466B8A6BC493F3D4CC6D33
5B57BD84C9DF116A6FA286F7EE401E7312D078AD606E8FD969B69891013FCD1FEC68ACA9E3B7
9684EF7DE656DE419D92A46DED2C43EE1E3E23DA7FE60029E1F1511AD8DB52B2589C7618FE8F
2242956F1976E5C174412EA691747B4F1BFCD3C23A60A298B99ABAF7F5B491F254D90D40209C
23D0805128AD9506FE9ADD32562DBE0B81F2CA21592BD5E739EA8CC4D66690253BB5F9D3108B
9591C3906EEAD0C837902E28D45A68E61971D1706F40BF09DBFAAEE3579F403FAC996449E1E6
C75A24F8143D8A5B8BA6808555ADB90E32AF1039450F1A5ADB218825EBD38411EA7869AAC603
E46E14D98ECE5432098714D5B26B353DC418DF386549353C4AB62BBC637FEFF4F3D37AFB618C
6ABAC8F6F2DDE2EBABBC838E388BFF532938CFFD9EF0368A0601DD5FA4DAE6A9E866D9AD9EED
A0FDB4767712518EBF3C7063FCDCACC116CD5D3585F52AC01B75DEAFA649A55FC114C2D6F568
C23B54C519B19189868B74D5019C643032308066D410977D5866B582FB82D6FD8350B123EE17
F24F2991C188F9C7B6F3B1A62F8F0BB3FDACBC48329898CCFF62A17D015336B0AB0D97BF3EC4
6EAA032A9E68A8EC0F84519950FF3030F88DDFC9342B5804F3E2EEBC2364C6640A10C1727105
AEF24B16F0CE008B4E9E669729CE5FFFB2124F4FE459AF66CBED05AAF92DF7008199A6904D52
7B510E54CA090441DB1AE6AE16D07AC5FCA4B3CDE7F89AF905FF9F87B8B56F4A45F653026066
34BEF03D3D5F3F24F655526CDCF2E897D9BEECEA419F0B8F36D83D42E14F51BF109A20E34E1C
6BB749D94101F4A59D0B2325AA66769655AD84C98240920FF1637EE4F1C026D06A0FC596D08A
637E8E87A48A8196AFDC361B0F84CAD1B2128B9AF38FB6B20B5979863DDFDD5673BF8F821D5F
64071838BD74742548031F16D5B054425EB649CFF0D130381048C7AC73FD5D15727BE7218882
19FF85A8B0654171835D937B61DCAE579F293CCDD51B0BFE7BCCB75E7EE1F2DF2CE6853539E7
CD74B8B1DE9C1562897A4810689A246DEDF8D702094408F8B6C62233F5FA83A379B3376B1C52
F35F15729BA9E65EEB7243A484CF7B1EAE66C20BF4FB6D95ABC1D72B3CB95D00934B8835D057
6C7E75D2F4766296DA85E684F82368DCA018AD9BBB2724B4A30C9E82F52961B2309C158A4F57
C85F898FE859375051A77A887FA4BDC0EA89CBF73DD8E6FD237B401424C2176D63B329909A50
0DEE911C7DF297D9516E04444CF2323731AD408C2B1D16138404DFAFB9AE239B4DF5475078E4
B8F201948C46776470C397C947B32215F5F4055803D382596310A776DC28D5B8F09EA2309A33
5D97A4DE952B8406F0135F3C38546D9D0BA146088BE38DB7FC1E9FF3B70C21FCFAB4C6C9F9D3
7D61EDAB276769538949DC39238D1EEF3DB92186EC56865DC0A9D69550547074A41C9A85080A
DADD7FD96E23687898607A1AC8EDD58FEC4156587E7A41BDDA6377F0C436AD70C53663566C41
478B8C41517A1540A0F9BDB924D64F07556892C569A372662641016E2321FF875FDFD236CF98
1531AB156E2C793BE3E6354F074BCDD21EF4B7FBD9EDBA1D3DF52F80220D4C697497D6378817
B40F6CBD2CF458B492356EC2F171D584055FBE7ED48223596B6E72EA9003F1219BD79E05329F
564BFB6DE6A6F62C8838CFBAAA0054342DE83D409F7F29EE655D18DDC3DACD2A29B73C76F9E9
67365D3CD235184A268791343E09B7A30098B3691D18568579B465B13FAC70F7392A8BC44173
137E1F3D2748E0A67D7E9FD094E7AAEAE28D1FCC0D83FD68BDE7CCC21EC94E932D333B8A7623
FF1C3F69E9212900BEE3656124D0856695096DBADEC466D3DC6A466D4F5D5C60BBF3CA100581
36F453AD02474305F6427E6738C2728B446A0A6953C3E10BFE36DF5F3A3A447657FBAA426F0D
BBCB0DEABC57F7EEE5D3CCB0937C7FD274192680DD79423CDCCA30BBF1EB2767178F8372ACCA
A4E5E513D4D9BEFBD1C367BFB3588E396F0786C730D97F8BA01C5E060EEB124ADDFC8E68765A
AF36768C1BBA0D7ABF871E43918D15636746D0F1E6AB2402DE58B57EF84AAE228D74A20D8340
B210496D69C3A5201A3233C324B03E53F591B6238E7367895BCE63BE3A16504AF90C8C042C83
A73F412A0B5EAB7F9A5BA7D112ED7D279A54066A8127F349053AC44E2F72E707D76CA68AD5FC
15AC3C31C1681BDBDF289C1D0BC2148699D02DA09CA4051A71FDD63A772990E58D4E97AEAE7B
20DB14643CA84604B4C692F23BC1630D516CE939EF865F7C44B8C7A182CF372A3B932B1D3014
58797977C90B57C5E12DE0B62A8D664C699182EFC6B13BD762D4C713A85E7DF5BB9A8207DEE3
C4959E4E4EA330CA2E5274725E735E485569D1EDA05F5997F16F7D5EB2947529CB70670698EC
06FD3FCAEF47AAFFA1712F5A2FBB7362EEF33E66F0493C30C0383CA6C3BB1AAEA99BA3904BA7
2C81F8E3D117B3A3603BA3BF9BEC83FD7820E3353D9666009922A40ACD570B752F58533C8996
9B08308A96E11C4ED57380CFA055CCAFA9558CA0CFDF832F0090580C7BD5779F8C1A0A9F0561
6384D9C885D1547F38986876971B2F5BB52871C05045E6514AF557EB57C5B2E86857FDD30F74
958EED440E691F004F51A5A23EAF9C03B2AFB28A6E16005B928EE533AE50529FF4D58CEC733F
C6D9D6B9E235D5C39A8EBE9668C7AF0DCDDB318020E802AB5B95871B644FEF014265A3536D3F
4489C1A2BECF8D5D5D2D6EF984B5C4BA674C74ECA262FA2AA4A4B7164B04B9F4297482012336
12157A6BCD92A7F3E5B6F642135F344351A94EAD13A912DAE64A132519C58D68AA11BA75ACCB
A26F84E0CE0B8B2DB3788327C615003DE8F723C6C51549709FAFF2C7DC76F773C55A44A26884
5D7968B52A7B495E93B22F128C569C23A29A5A662C939A16BE08DF74E525B40473EDADAC4DCF
5226409F9982E3F9F28B9F0CD6AEEE91EA3E41453BDB07E84A01E165797B7E0C88399DCDCC66
6581B746ED63D1B3FDB7731A98C2708DB56EDD25E6097A20094A11F79880CD47DEF83D4B0C0A
BB991DB8C878B0874D099D7B5555CB668CD5B7BFCD2CBA76852F0874B906B1FC95616FE6237F
40D3FD63E29F593A8842B151221E63CE8E9AA2080E5DFD5E8C1959F97A4E570FE6CF8234EC4A
961BC15E46789446ADC12CF9D3E9DAE345230941F924FA7337C3585860A2870F388B14B29B76
FCCE9BCC0233EE7CE39A242B0537594D14288C00AA67A08443E69521452AAB22575449C2EE80
D0393ACD3F7C9378B4E49A5A4D0B707DAE8502791EBAAB3CEED7F2ED54585183AACFA76DC3CB
ED28699CC8638293A2E885BCD88EB01C6E6C828C66F42F1D534A63B8606DFDF1CE4F8823D2B7
1DC2E9CDD74703EF1D9D1EE0CB7241505366136E256BE79C31EE8990B0CA49CD2729A34A92ED
BE12A7738CD2E4F4002C9F6DA211D57AA3D713850239DBEB9AB648BD9D195B1741AAE2F1386F
E88AE159B9E996E7D803E0AF11008B345BD743433F080E70A1415BEC71CA6C331A22629F80A2
880E7B112C9B6444E146566C9DC14C73C178D41F99CC78EC9D106F102A9C6435A507A2CC7C81
B4FD18FB4099D61D0228B82BE3755659968DCC18005EC289BDE509D5A98A0317150A2C8D5CBA
B353BF310C39459AF38B3B6532928C478C5012AF23CA4B834B3519575DDA13BAD7CE1BCFEFE1
EEA9CDC76B5A076B14477C2EF875B310E9A3594A6DFE2A3AE2858049B280FECDFAF2AAF1AC77
99757A833D0770974495D7094F1C1E4A91F51978E49014DF917E74310CA1C70CDD6B4DC90420
33391B960FDC9E1945D256BC0F9DED7EE9235723A80BF0D51AD4F2F7E8AA91EC22CB53E485E9
35FC169AB85BB1CFEC6BD3E7F234AA6FDF26042C90E6A3BE33B3845A1C9D8967A752CF387BD1
7A76D07B7587E3AA378C07F47E452623FCD2C144723F5E40DEC0457C6E96C39D671484141AEE
45579E097FDD98BBD391DBABEFC70054B0729AF2678687D9ADBB29FE3316D622B62C27C5CAF9
4FE9843DE8ED1C21C9CE728C83248D77C6067EB67F12938759D82D41520A65668BCB3D45EBFA
C664FFA0D2A0E7BBAFC03F8E849FD08727F06C24767CF30CAAD10F7F18F2E15E2AA8D3A3E49A
020F70CC20919E8AA33F46681F33E1706CD396F9C7C93A19038E5930EE5104A48C3F9B308E8B
88BA9CBE24BD3F26730CF157637DC8720BE68E01E4D511FB5C176C1C6EFD57E304A67FE102AC
289B422D7CF3FBD39CE39BAEB79A0AB979506460A29DB8AE1A2D90E9571081D1FAD999AF409D
632EE7B87E33157362DD18A086AE32C83AB8B960053B71D41D6B72523930794C2473DE9856D1
F9E889FDFD70A1B7D9E887CE1FF10A2DCE4EDECDC9C0FA1F56CAB503F54461F3D3FA5CA082AA
5E28D3CDCAD848BCE4C379276944C42AEC1D7E6C447ED4FD70BD545887F01CDC53C0E255246D
7496B987383E162DBDC1DAEC6CE801DD3193DAF1DDC1DEB9D982E736226A601FBC0DDE4D7B56
5BB1E87879443209517C058F68B9BBB48620B636846DEC19B8B2973B88A53F8B2E2C4EAD40CB
EBC4C217612ECAAAEC2AC077E26E4FCDFDBB08DE8CABAB2C0FCFF66A040B9CC79752F1EBE58B
6BDE30FA17EDA0AA8709CFEA344CD1AA650A08DF25D4D16F6ADBE2135FFF9E7C903D7B7E8944
CD49F7612679C24DC4992DC27532CA3ACCED63CC6991F072875CDC4D1434FDC927FF15833CD6
B195BC1286CF6C34E3E0E1C7B00309D7F5DE3E24FD3B4B3BE0EA637A337C831903AE4A0CC7AB
6C8402333E66703FD34D1A67F580A4E63990C88AAFFC93CB6B4C9D985E39EA248AD715A853FD
7DAD6D1CBAA35019A2BAE759FD04ECCD4AB9705C2D22522BFD7ECAFCBF5D185C841DCFF8F141
458574398E865F5187A383B9172B85057D561B2515FF9FB9ECC617CDEC6F6572BDE8983939CA
5F47607BF5A5F6017835C1265EAC50FCBB54D7E122A9F862DDC5FA00CA937D4DE4E0A385E752
C1AB12570B0CB3B56AA751EFA9B06557BDC4C2634770B2DA7A4BFAB3FE332262BD6C49927CC7
D433AAAE9D0E77A06A4954A3A1E75C0F037163D17C4984BE3930FA529833A3C6E12433EDC336
24350B2EAA94A35C85FCCC1039C03145A77F811098013E850B768574E71287C35DE5DBADFAC8
4B34BA3DB23DD1110956F415BABFFEC9B79A1360B67A9A22D75C5D2994A81DD54D38630F049E
C4F0CF38C692E0F7A372EC2562648AA5B63ABB616DE6041CE69EBE2FBF2E1A4EDAF57DD3378F
A1A445E64A7900073558888857FAB7F83CE9EAB5F020479F6206DABD5E756A481E4DDF0A6446
34F63F796F3C062D4968BB1055279671DD762730FCCFF930CD60053C9F33A88C73F255254986
B3055B66A36EC266D73DE57B2AB53A079031EA57E2B10B0FCB2843FD5A1B7AE569C351D7A28B
0932EFC2F6FE1DB4C34569AFAE364BBE8C323FCE13190E6B21E6210B34D4892127D0EB8C617D
BAD3AF3EA4CFEABA4E81AF57F6393C703006485397CF8C018A654ADE14BB99A8280028DFD8F2
F1C97945EC437026E2000760D3FFB033AB8719AD5924F37E8D2ADB1AF1F3BD9D5FB84BDA304F
E1A47F12A13E79FD0B268B309D784C6F874D5ED89C0B8C6107A704F61B9489EB1EE372285876
83DC82FF74FD98CBDDF04BEDF35097E66154B7CC2130927C7A718F5F4B4338B2EB6FF0ADBA99
0B5E94CD21265EB13FAC95B9E976D1DF8FF2496A60A81B9599B3A07E5B3F074E201C46D7EBC8
C2B36F8011409D5D8430DB5267F2AA04EC5A000DE223D356574042C4FF128D902F1E1151A731
E54D07DCD0ACF614B19AB51F651C324ADB3D8EFCE74B3493F0D6E56D4248CB06648C28FDE0A6
341AE2792D29714C66C4BEBCA0A520FF3C312C67E442A9075375878C20EA6766369DD30647B9
36191BBC344AF10636E49A4AC2E45D2680366CA41A21D0E5DC1EAD87A13E1A0C079F396230BA
CCD2C4CE3AB39081651CA121F35B285CD7ADC2067E121C4F3EE2AE45FA8EFCB563C6DA895FBE
84A0384AC9787D8C4A3BDB6E2E87A58B9FA4B595FCBA204488B377404DEE50823EEEF2221F1A
C0AF2AB2761A265FE2C20D10E21B6E339A1D3A26F5B4B1A99D316C8CFEA7CCB52442D26C70E2
2563062E982BC256947CCF59C3E09FB1941D7B54E0A42466CF642DCA91FF9816E6F406E0F0EA
23ACC1959DAB7E7A8AEAAB05C2BBD5257B01CC8F0F111CF7360AC192C348BEAC6A273DAAF64D
54AEA7D49D786F98D7358E483609319699A1FAAAAADE42826EE0B30D277025161130414ED914
AF741854017A405F22CD4ACE4CDCA0833AD52F49142FB4C03924023CEE3F2489BB3CBE03B122
19B9CAFD7AB8AA59AF3239248BC9EF6816351F9AABF77792D7197945F00CBAF769F00005A615
B83447E173242A3BEA79E21FC28B383541388AB3D342EA87876F2CB55A02BC333A133FD05F47
1A3AB493674F17AAC890F14450EC5708063591FE5E6912E41F971362180FE085706C880ABF1F
BEC092828608D1EF6C52D01A9F16FC32C420279C559BE5C673D2439E0D774648EA9EBF4D9A84
13E9AA815283E016FEBA6293838C81DE8C3E522AEAC857E4EA7891F81DEC06168B4A15E3668A
61B924B8EA6FD11AB0589A5D2B6AB3E5F50BD72BD2C55471C19EF542E278F3874EACF4B2C2DE
312C6100A3F6064EC98747C366874E2233E88F201098F75D4C275B2AE0CF6809BCE3892ED3FC
DA718AE0F46EC1B624DCCBF6E84024AED20793FACF0D1FFD2775C6D6922F9377B1E79393F7C0
775F2455EDE1A4DC311EECB9F57C20599E469C497FC23DDDA0D9DCE6C3B036EFAD121522C580
31235EB8FB69FAEDAD0715E69EF1EC9701938DF927131C39848BEEB9FB862D13B8ADC13C86BD
963108F816A3424FB414EE57B3C7D8ACC56E8AF2EE316DCD3E04C6271D733DC9277729683120
30D87118E79006DD5AADF01BB94B308D6FECE272BCA13C7CFC41CE3C2FB964CA42599C73AC33
71BF648083FAF1D58F55BEB093E4A941856836C7B5B8FA689996ACA0CE9EF5E14A88DFD61853
2B692006A29EC8492F21910616731664C6629D5F0D6118BC6EF45536B987C0060A12BB18787C
14174F7EA6A16759986D2A279842FEC752604D479B74DED432D712CD3EEE397B541521E21F7C
3E5352CD5B98C4944FB08F9B1BC70F36288C273D1FD74B7A9A5565EA9E69FB3E4739A586858C
865122210125AB07E4AABF35AF7D2948B8B13F69499AEC43242457B93FE382DB7DCE515849D8
B91C96EE155BCBFB2F5160986EE46AE7EF74FF7870675B8E5D22FB8594F81D096A967185FD96
32B2BB96190790E203EF5F2B0772E456F981AEC9DF29D7D5BC5AADFFD9D95D0446573859EE08
6770C307B0A174DC9A5B9EF35D22DBF191FC1A2DFD554A0F8685A09D731509A80D2BAFE62989
7CFF3B8476E6904A16A99393C66D11E8CF7A5B7B195752E0523A743AB8CC4F3283A544CE0D48
5FDE0773B2E364D77519F7D1E9F822980C6593B1555F2BFC8398340C7C4A5D9711C20A2CCC91
1D72A669737548CCE5871FF08BF72C8C38E4645E5D4E4A10687B7C81C55DAB8D7DBCDA0A1C70
7AE4029DE0FC02378DA19CC5F818BAF6F88258430C122E6863238C0D3E027C3FE17E58083254
83AC041EA5331368879ACCBE672677C0D91826F066853E5CD2542E035F6FEB730EE21EEB7983
DFEEF31B1C803A4715E0BF3CCFCEDBEEC6F312F28F12C56739CE813F9F70649823E5A8AD5C3F
5B06F82231F02D2DAAB589ADEA88520C2B5FC2AD7610C5069C0DFA2E4D74AF220E665869798B
78C3E98EF345D16C60641B226F7A91AE700388A85F8933505BC0C3DE00944BF08A25B692C6C7
D9F46EDB6ED4503B187530B3B80198623B4FE031CAB4102A3B99CF68123A38DACA0E49B2AF73
362A601BE22299A166CACED06D3682820F3B97A546A093C9BAC6585CAB716611CEBC87841700
88E5FD0D31596D6CFEB292EDADA2B6C3397041A8C972EDDB817ACA9139F6C4B82E0D39D11CCC
87A191BD10E23EB94C55BC72F4758DC3240442DCB4A1D2C49A6A05256A22DF07703245443597
9EF2993370A2EC7D6A46E832FDEC1F425F9850535E34000440D72420263103170EA306B15596
086D2FB6DAF78202B2E7C7A82A74627613521CCCBC4F378E7C66F38F4947641FB07184F714D6
AA5EA036256C686948FAB99043D6EC0E5F5458C376DC98264E8D38BA725CC94753F37DFBBB15
57BB10F9B300BC91943220B4C2F20A43041A60C978F4A69A9536E02A8B088206391DCEC3B1D9
76C0E18642B3BDD7513757CCC85FBA444D3C007CC7CF3F9CE68B75B8BB43D3CF74D68DE3F789
19BF1DF0E6AD61BD6B3B57571C72E387B61077A28BD96087C28BFE4450696DE44EA50B375EDD
76840AE0BF7DF126F2A96B1F2C22ECC06F49F3B737C89256961378D6A462A201AE88A3DD9930
DEAFBFB4773AC710E922FD78328D0A7C1BD057381668A74F988BDBD94B3C8132C344C527FA5D
27D5B50AF2D9F809D665E931C1C8DCDC9ACEA44D76C2F8AEB30798C16A2EB75847E1B39A59F0
4D419F08F4281DEB5557A2D53492861C75D66F48DBD409B8DC951698FBC6BBE88D30E174784D
46A6E11E49264D19767C2F3E2B192841FB15BC169F2E37E6532BA7C805FA51C62957851F1E85
49C400B22DCE93ECF10861346A6532480A3D869186E42784FE0372B15FA990D9580A64910345
2CAE1B433A32BBCADF600EF2DF4A313889CA84749149239CE69B1BFDD816D572C359A9D83ACD
19EEBFB754D8A075876AA99E5C86751542329FC61D247D094094019E78B0101C865CB0F51EC0
F1003D5F23F7BF8BE9A53DAF2B6A00B0C138AFD94412DB581316BCCB2E294A1CA794EA15263D
C759B61BB45E14A2C207A1AA2577D1D64E2D0C515B10EA68CD9200401F750971E80D251A7487
146A8AC453A5F809532354D3A36D612E3B8F7355D566F54AD4959D9207338987026DA48FC975
E43F8EF1595A56FFD4066258AB215E1608867C2BAB3006D78D46BEC9774884B1A958DCA0B0F7
FFA98C7B1BCFE8699E64A044502ABCE20B997A1B87B605DDB977CB7C66FB2B7496180390B6AA
C711A63557163EEFB9F5C530451F70028D83509091497B388ABC1CEDBF30BB101EE4DC8AAB1C
A4623FC6EAF5390F361E0DD80597C6BC9E8EAA52DFFB1FF652767AF4148D4F72C2B5239627F5
2784D54145D325C9545670EBFAD118C0F16AC402DCBB299F204CF42B7017F0D3CAAEC74620D5
AE7A2D66130B4202391E6FFFA18F3CC2A788127A185B4A9244E0E06F2EA056A3B377225229D6
FCBB56DDCBD32DBA30C613FED48D9890BE8722FD441DA56545BA40853F12ED9B596F999BB145
0F42423EC3ADA8DD8BBBA651DA6026397A46DFAD76888F612F6D1B7E1EEB959BBEC22AB7F4ED
B6F8DBE76F162D394E61D225283BA461502306941DAEBA75FB6FBACAE056AF835B2FEDE6BE49
6AFD3CE06BBD8A34F77DE79CAB805A1F88241990D2B71DDCD53FFB3E536A22A7460A57CB8909
B1DB369CAE328564FC1E68E094A275B9D6A69156C1F1F52C251CB338D36BEE5B11A4DC3F83E5
35F91A3264E5C8E4F086B42B613F575753EA3D708A5F1AC195960BBBEAEF4DE6D1C58C45E6A7
C5AF1840CC3923B1A9DF2CFABCEBFD1F1386E0C61A1576CB7A348950F7556E315C255678D8AC
27DF7503051883B79A00D40E8FCE7B14A09A66908B367882CC808B9DEFF822DCAA1E648AA63C
D984A5055D931D0DD82C3C65ED0A3EE3DBA7D5516BACD60A2DB25633AF6F864B307BEC9356C4
99422FED8B8449B142B4D12B0637EEB82BD5C3541537DB67B099B33A0407E988C0EED630D7D8
9042D25761A26E3C0A3C143C037B43FD10E01B759B07F4E7E92177CEE9AD78CFD7509B7DF136
EC05B5F373709D72B69EDD9FC4029479E77794D4A15C2DCD29A26AFB22D60185A9A57A4A0AD8
3F09C516844299CBD4CE4159CD7F9C191A003ED211FD86EC3DCBE38C6C8DEBBEF252229570AE
416387A4FC03ACD075EDB53989692FF3BDFED86E217EB9DE4F656B143773FB7326A2B44F1370
7A2273B774E59DF0A6DCAB9DB93D305B7DDF8A73796F8CDBB683B44BC63C15F8913A12ECBDEE
3920BD0E9A0FC81A97B59F5DC7E2B49C993A2D9CBA28D5704E15D702936934AAFC0CDC7447AB
F7C2BC61F73C7BF1DBA55853A12705BE08AB6792ED0E84F07D86C53F2C22BAD9128013CC622E
42AA03A1BDCCA293A04B5F73D7A76CBDBC1F32B428039C3739FA5A1D75A84C29894833E77792
DD0FDE2C3CA782B634A2868D9C1218DD8F6B1806FE6D3DBF1CE9BE27674A3EBDDB38AED4C087
6A8D08A578977BA685410084BE04CC507AEAD5EAF285BC6A6E18FA2D6127E38188791363079E
E07BCD68F53372CDEA2F98B9EDF558124C7047DEFD116E81DF56ABCD1668038734DF84F293A3
387777026646397E36F91B8E87D2DDADBC8E2738348E5B55815A5E060886AACD2515E71BDF94
589618CDC6B17EC6BB957246BCAD2F01009A8CC370BB18F389E8B6C9B4588F4F6DAE619898AE
0AFA7B359699E04DD41E73538D3CFA33437F3B97DDE51D5BDAD00C22E50E5D94315C45B569DD
9C24F2ECA30144DBFADC451C508F0E85DD9A6EC2878F06225359649AB459D50072A2D11E4F59
301CE94BD672640D3E3E6F58E335B7ECA974837CC0B5263E29D34C00B2FA9800E6CAD0D349C0
BC1CFD584CBD648BB3EBC9ADA8456D0C097DCB81C55AC72ACD223AC258F221141B8CF5555B0E
30DB348599139E6F9E7ABA032ACAEFED86735B6EC68A0CC9AF40911673896F8A53E68B442953
0336E94DACD1024D022970466091FC2DC415D5F45DE6D9A92180E0EF69DA37E014054FA5B164
155AA990E7461D372129C953413091580AA43605994E8FF02D5BC1E54F14F0A54E1CD7A51919
5240B2D624DCFF13877BE38A668B1856A0FF96C95C863BF1A84CED2B5B8AD7E2BEF463D74660
8B07BD3D0F3B315E0234EE06C78847FFBD738BC0C484F59A40E92F095C8EA0463A2F24275F8C
A2ED85C86FC092B92F10B4A76E303C0F359C723FB5F2831178B35056DD45D01EFA8B73577467
B9466EDC9E7D1A5984A7FEBA05A72F23DA9612A6330D9D26220F90366C564C1846571790656D
ABB3E1E90C9E6F82D974464FDD45D0BB9013AFA07842297E5735976DF70A3CF4A87B1B02C96E
4CFBD08A56391EBCD5453C9157199F006BE605A102B7E1F89199BF164B8BC15FA5AA18FCF3BC
787C016AF848697318A7A84DD40FB4B790F619243A48E75BB637641B5BF5601A7FA5A28D716D
11DCB9A2469FAF63F5448FDB8457FF2F30488A129F310982824DD303FB957DF6C783B8F19734
2C8CE62019F2284AAF444C7D6DCCD74411CD84C6F18C07EA34388C1D0F15FBBCCEEF8605F731
BAF5A006EB1E6B34CB567175C9FC0DED63DE0C466B4C35D3AA5F9FA84C50FE914A8F7321C7A6
6AE9215D079A80E8FAAE17E030FFFD006C54FEA36DB19EEC4814E26CF875F4BA2005DE4EF84B
ABBD55C667DEEB8D5D3D83550E55B98CB00FB45D2587B1DF1A7F428184A8ED78D11DD2D96805
9B406C19303759E127397C65C4F546F7000100DD311AD2A38DED6B6C692F5431B34129EB9361
C1D190BF753E807B09831E901DED093A88E6624CF0F46BA8D422D1750C43E4CFF9BA6F76BF66
17CEB95FDF8F064CAA8996E5BF7B575EDA82D026BBA76D7DB5F54F097E7AE63663EC9938A2E6
031F94B273BE9936E69992753B967A42020C6140C5FEECC5703E5A565A27CDBE67617FFC7912
112B60C21262A92DCFFD31A4AEF1F00097958114317B153BF93F8C24B5AC9A6336E7D65BC42F
5A68FFF36A3A56260E4B9E7B655C5B9709684ED04D8CBDEE8BAFC1879148BF81A180B0F533AA
CDD1F402B7A82968117002AB1E7A4E4B4CDD5838D7C0572E0F5FBD13A1D36549A96A7C42EE8C
4D6107E984285D89A18BDC711616A6C68B7A92A2A4DA76F295C99D2E5C754160EC9A51AE9F7A
FFA41547B0EC4210B92D59193B81A973D9763C73661C1C7FD830EE2202A88CF2B6A79D438B53
2E1714D9DC2E3F8298EDD522FC082AAD25C3CDDD50CD1F132AF308874C1A1904E258098CD371
9BF236ABC9AD83F23BF276D48A13886F18857AC75105F0254205585BA1322F1DDA52C1A1A76C
18685B5C3DF7B59EAE4E55D87266F67258F14B700CB20664FAA502CE8420088CE1A316BA16D8
2ADBBCBCC4DC7F817DFCE3FB21FF498FB5CD956607775FE34B1FC20EC21676E3751A579B3FE9
DC4B7F7F99238898EFA6B10495E64ED9804AFE667ACAE7E8E1D7EB245163D0DDB4B74F755EB3
8B0C615B1B8FF6D1FB6830A1667810156129EA8A101B101046CAA3F7CD60E46D55BB2814D724
1B2590E151A05F234A3737CC0DDB57A6E3C8A4ECF0DEB12A8E78FD22B6650FBDAA1D6B342B23
1725B5E9B5C153FB08CC7B692FE7A2BBCE04651D3FD06DF84219655140F3A46CC167A9B56BED
00EF6981864B99057438C58F476CC445D5A1D2A0DC2BEA86DF1C81704179CBF01B843BB8FE79
CC5C6B1C966A49E61F6D453D448C9A6C1E5AC1356A67CD6C7E351D9857320BB6369A01F0D1EF
ECC718940CAB37677E9F0E37E53FAA3DE8C0EED83071AE6499663CA8344F9359C2574672334A
1255F39DA556F5DD732A4E5E071D62C136FB70AFFBFFB0F8AD749401ADBA3F45D810AC46F4AD
4AC7201E1F15BAAB988A68C73E56A947E3C5DED28500C863AC2162A766771993D2C8D4BE69A3
18DB19521A39A303F031601535DD9741B619ED86820D586618A9B44AB0BE6A4642F9E5A11551
ABCEBB1068186B92AF140DD243645F3991B3553EFCBC10E47D13090E2F1D683584C29CFDB55B
8792FD23A55553ACA2A0C0FDC8AF21DC1BBE322B59515CA5B41A72652FE904200CB5069A09FD
A144F121E7626D14C5FFD64E347D9ECED3211E71D620D2D0BB417C35F7A3437A06B4D25C9C54
0923ECAB9CF66234004827FD0904C52F477196FCD17638BCE24537545DF99148B19040C86C56
D4117D17FF23E01608DF1CFFADCE5376B51E3F8CDC3E5E0426C1C7A18FB858EECE4DD124A6F3
538E94B4B7F81BF87E676554DDEFE1ACFAD2B153676F15837EF9CA70678C77892ABEE7073CDD
353D35C351CD6FAC1E018EB5E26F32414831DD937F54F259A37F0BE85E510C1DFA2E52AF5020
B6CB17030ADB3DDC8B767CDAA84F78D00C92FC1EE4964E30A06E4B06CFDFD690F16BE59212EC
78EDE080D967FFBE3E7DE247E26F95ED65C8F047F049F555CB44F62060DBAB74B02277FCE39F
B093DE6FB2E043F7B9BB6CE4800C03804094E366F32379FA5C6C42B37D60C5864840E7101DDD
D5FCA36C2C3608F8199BBBFF02F7240722A8B16E2976998F6242E71D9DA971A522689D74B379
D0BA2059EF1105414082D60A09B518B36299EFA56432EF75FEF406CC7B81AEC55714C42AFF75
0DEEABC6233244A88E374F91C0581B84CDE79BF2BCA66AD00BC6074F4B0641751BC98FC52F9A
564B9B534E9FDA14A524956C12A4A74CDF8AC15371A4D4F75267FA5AC6F16ED895EA6811403E
576228E4E09FB5FA4CC8275241D1AF5533A0C9E598B1022CF78DFC144AE402D957BBB5A47969
BB7392DC9FCCB6D8947B5C5C2DDE1C98BFE6B3E26FB0B3618CCF74773388289D7943E144BFF9
CB5A4F30B23ED5F5AE2DB62F08F6E50CF99218E9A33BB82ED72F12C62B5D7ED7AD7375A77CB4
CE52AF221144BA7F9601EB8DFAA361FF21341432B8FD8B8226D1B5A2245F7356B3B84CE2D9CB
9C5EEB1CECA976ADD0592F78BB8C4D85E2D5C6179B30B3175B32F0D1F07F37114CD475FE918E
4DD983BF35C7F5CCB415CE41C071E10D5FA2C5B2277071539B6119028B41ABADDEAC18300A79
25FE207ED0697582E76EC0A60D2B6A29F007F7243B94AAD34FB0C46711C15A2108ABF238581A
5AC32FE07581261B47C375B57BC7F3AD6AFC71D80E6B5514CAF2C57BAE6D519F94BA2F95A9E7
ED06933113D29F48E625EE414A22850E5C24C768BDABAC2F5E5C4F7024C42368B5E161F27590
27D09A0F01177B756493BD4D453C4445C8A17CB42BF88B7ED5B0F34EC4D014EC373CD226299B
CF096D059E8065FDDFBA19E58679EF30CFB577FF360E8C7BADE6303C599B8A5F5C1656BF651F
8CB9CBF05912D1852419BA583F54FD5F63ED121871DC1A5E040715CE5DFEE5C7B412E65AF9FB
D38A3DA859DDF75F512809920948CDC124BCECC6D1B18E67B75CA8CCEBB488BD8684153DD906
6C7C92258D135BCC751607AD093BA50040A3CF04B7A5A53EC4A014D8B7FE016DE9481EB50F01
3694AA4C9336E122783CC4E964BFF0638AC69D2A174C2A39C458FB49E024A057A4ECB0A243F9
B33E2DEA9DCBED379CE14E8B66E72F3BF0598CD55B2A256F6B8419218E8D56512B57151B0FD8
98BF7C38B8FA6A82CB4EB965C8DAB45E80302D6DDDBA72029AF77228FE296D50919A280723DF
A247E0C636CF6D1FF3A7E8F827B5AD52EA6282E4019CF1F01A9D09833F191C2092A8DB728451
F0B0FDA20EA34FA0F2DC3580AE0621A7303EECDC7CFAEEB307F2220199C01CBE42F27B67DB94
DFFF4EABC96828A41440177C5DB6F190C0B6015273D7F28EA79383D33E58F20290EB14B7F7B8
FCB6A4FF0AB89FCB001A26A356781AC30DE98F0F9A62F39EA367FBC1E4FA2FAC9A130B3357D4
726083F18D5E8961C52F937712CCA680CCF6E361A951461DB1558535C9B5DE9F1C8E153F8815
82B7EAC247BDF32D018129D6F95F9ED41E024D531C8EAFB376842C079E09EB9C44DC586EDEE0
2E335028E89C9DA2ADA468E9695B0B5093E88A6957318B03815BE318DD109CAF3243914CEF32
251EAA13815B23020312E3D17029F42D736A2D2CC20E8D64C5F0D0C49ECF4B1B769CC03EE45E
64A41917EC9118B9307B0CFBD4B1B784CD58E2AA0481CA12567BCA6BD3BD016E2FBAD4C3B8B4
FE9DCD1C5DABD829F6C908EF9B575F23D67AF3B52A3C7FE191BAECB8C3209D4E50E3A7445936
8824AE7DC4B5DC52CC95C765B79ADD7C93968205707963FA987D90F33A41B7C3411E59A1D125
BCE6B22F58A537899AFB2FFD2ABF4BE0A74FF60DA0046B0A5A641261FB23400CDBED14124988
D8D39640B84E950B6E428113BE2838B81F99E09F8E432369DB29B68B7131DC489CD5AA958354
12EA88CD6474C9FEEE3FC97AC2D22A583E52A2632865383DA3DFABD96C7FD5D564BF76B160BE
F8B29737B6EA0A8CD493CF109A5F97BA1CF042958A0B5AAC40E42E963F331D7F63660233F45E
3015FEB3FDE4F960B8FD7791B4608075AC660317BCDF368BC7A08A584546C27769E695F18704
83BCA4E34D63F606CD3EA2CCD8DE3FFD00DDC952603A4D4BB6C3F35B3DBC3CBC0278A270FFF9
C73189B8846D7F67C5FE81BBD38432030DC0D1B58D7B73E1D87880F96E295552EBFC732E6156
2878B98575522DDB4D3BB3F2277BD1C822966465A8D6F9FEEC6CA0B925889DAA54C7D845C0C1
699194E1D238A8FC90E0C61EF1F7D29F86AEDC494FC3721ED813691E781223F7CDD16BDF1819
A11310696B6357E27EF4097E09ACA4641FB55D783591C72D0D51AD8695442FAA58A0C7B96C1E
199C6EB3064A1024CAE27A318A9931D7DD37D983AF159F5B3CFD45F92F54F15DA5D1A3CCA367
39E189C61436011974D89140209769E6B42BA729E115EFD02C6DF250818FE8FB91EE9E9698C7
2757B030CE4FDE201A69FE087FC9258058BA9C4D3DAB0B2481B5457259AE608C114FC811E33F
1514057F627556E6559354A8A660500CA2C95FC6608B4E067913C4FF08FDBC69740B2F2E2273
2CF091AC243182B5E20BCD0F3E77AE13B129297E4EE30762CE27ED963F1797326A39F70C9D58
EC4814F9922D19F8B12769831A710D7E825FB59C9C7DE4EC3ADD20D426A8356B1B7B03B48FC6
3630B5335EB9B68D3009C7686BCC986308CF9F23E3E8A9CBA4EC9F232D24DE48FE83C99B5F46
C0FA712EBB8AD4260E206BEEC28D55C1E26440EFEA87CC3A592B51E3C3415695D29ED1D3198A
C2FC61330B0C123B279C265CCBE40C4F0B1242E94B354281F26A1BB0DD70A1D7AA7F2452F2EA
3FE1DA9EE43ECC38FEE27F53DB6D5D3880154014ABB1023E4FB3BA5458FB0314176E2DFDF445
0282C4F0D8778A5BB3619BCF34616339812956C733BDB6259ADFA887577840EBCDE82E3D4DBE
B9294FB2A8713C1EA655EACE31249BE2431DE1D2E37154BF64BF99437DFE26DBEE3FA3051D10
3C0FC6F10A51499AA220C7B9A23125DE41FEAC02B74933B0B1F328AEB4906239BB13E0B24F83
075771870F01B4F4A970B075E5BFC1114552C22996286D9870F132FA9D64704BEB931F402B77
EF645665DDAD5EFC9D6CAB2096CA7CA4B5F4647B091BC893A70A1AE7779DC004288DBB2326AC
CC9FF6A71FD892C58C7D69786B6CA0F5FE35DED10AEDEEE6286481FDD88F044567F9F1E372EF
832FA7C2906F96EFAB72DB5E62F8ADD0E7CD6523F6BE7FF913BEC986A00649D4E65049EB9502
EE1B35D9B016DDD80AA2795F880F38BAABA202FECADA6F67A22A353CF65242E4C3A0967AE33D
0C9660A7DBADB7364B8678B3196B1742DE4668942399A9214111010AE224D61FC53A1FF9975A
FA8A588E434B69FEC33F33F1447DB75E2983795A3E2504FA3D59FB4462BCCC4DEA6A6797F792
0E04CD8F1213B8C08FB7D5DAE0657C096D9C2310DA574391716DE57AEFE730CB13C22E560D33
5C4708ADD66B789C08C9149F33D5D9D67FC6A6B98F92676D736C27D8CB351F85187BF845EB25
E50F68DB14771A7EBE930BE6079970859780B3C04A291461D2F7F34E31AC0A99C8C7D5EF7A65
0E067ADFF7DBBA16F8D987B35C5DABEC96EC16EF3657A9A67603C9B8DF5F5DBCA20E0C2542E9
7223F83295A6758EF54074B4C178C502318F4ABA81FA3D5E4E42F30E959A7A6A7D472ABE014E
5D3B6332C6CA5BAF3D028161E27FE8AD34811D12D394F08EBEF835F1D24EE4DBD8311398085C
790D4FA6BEAE0E82136B78439ACB61085C19F97B083A3BAE74ECD65265023556D41B4DB72841
B077F190BBB1BE10EE87FD812314C95A42490DFD9AF59B5F728A0CA112BFAB781323837664F8
F61D370B86C7386AC024BBCBD7B8402396A9AF17A7B9A601E03EA98B2050374C3D8A5A393ADD
B28449FCD667E09F541BB2AC3D8D9006D823C8CF4AF6D30F250115437A583CF815038BB1D47F
BD82C3B2A666D947EB9155E6843E74B3EF92F7452EB2AAA6D7E381AA76934E018FF2A33A30CE
C26663C1785344743A8853D0E198896C92858DF3A6894632817D7E8DC03FF8BC68DC355B7158
1F6E9740A0CF7E06E12CFE531AE872FED8329C3C75FDD2B2B2FE2642342DC7AA1C1B4B404CBF
BF22185C6C20239A075B7DEC651110A253AADF86E8D9A87F5C2C3B35BD60D7DBF44040EE96ED
65E9C7A3E69E25695C55A197BEC858E2027A59D6C8057A63DFC276BA2716DA969ACEFA3CF837
4BF4997692D00793E46AE663EB949E726CA39B42F999FCCB5D8C4586380AA5D7B7A2C6518603
2B5CEBD8CA1D52EBF48B48F7A4E1EEE090796DD37973004F20C04785B232332880C0F845BBE4
0E1AA7279DC85780B9EF863D9B6F036A2622684856CA0262484ADAFE8F19EBA3E1ACFDF56748
4E8A50AFB36BDCFBDE2A2CEB59792B1124448CA7EE428DBBA56A46051014E950F0C4E9B1FD13
5DD445AA9176C41576A9C94E03E91F4AD944876C917CF8A80927738CFB566CCA7C6D1E63F3BC
E16F03F752B27F2446CC13E212A9A492C2B9D434EA054DD6CC5E5C896B2F326B0C356C0E15A6
26AD11C953C62273FEDDF4249A1AD770FE2EE39E901B3F54853050C1055BDC69805127BF8327
F99F5D1C3E10EEF3397280C7442F8304A3295C3D7EA1A965E1A3B5CA17FDAFE9BFFE9C1EAFF9
796D4C1BACFFA065779164D28F4F09F29453D9165DE14F1CA1D2AD02CB51F05FA98D04877BC1
59B0AAE4CF2DE93E26DEF60944D25E190746E5A661C25B33D9941C30CE1C99C9C471625A429C
F69CFF9697383316A269E48B435EEFA2312D5E214E69E492A3E7BD429EDB4B56936A55CDE475
B576A849B81D798B00FDB9A6AE9D3ADC6AA58922E59FE95044F8284FA5ADAFF30DE88D484F7A
015B11D35DC50D9B454D6D169C3E251CA0E4FCCA8BD08D3B72B48E41EFBB7739DB1355A3B128
6E604EFED37E2F6F1FB16B688CA0DE86CACE2B6C3A10881C1157B772C89D74B3E885D00806D2
8C06429B9619DFB61A0492FFB491BC299E0EFE4EB37F61C4CFCE9819E0ABF678A02296233AE7
A4EE46ABA2377A22CEC36C2B6942EE227AB674DDF0182F6E54246E40A82948C7783913AF87D0
7EC0D21A82C0A3888E6F0913B2D41B64CA32667137A756691CBA4385F409B51150B43174FBE8
E3D903AC09912FF4821DF6A4E415D849DFABE544652B7CCBFB11B1E076A1BFF75F80094CC71A
178098082FE0AC069C234475FB052BDA47B65BE3860A05FB8E0CFAB1674D328F4B70408FE21E
91D3AD01A300446624833076DF98407D002F0EE7D948CC5A76E0F595EE5F1E8AB7D712319F08
FDD3B923870B0D4D0BDA7EDE7B8312522A2AC9CF50A0F4B50730AD4F64EF94F65F66D9D124D6
50966912F48C010B27214C26D8E09888ECAF4033E17E0E57F2E2AD2D04A5197C292B281E6894
9BAB3253BEFF0BC08B90097A93A1E6A077A54CA7958DE9491E10B6D272A5C76F9EF7B1A19320
858DD866E1FF46E1EB4A73E8F4F54F35C5BB33236EADCA1223D8D4227510498EDED173D78332
09665C9354DC9F58D837B666CE337C46AB0636B54793A5607E6603F5A807926EE0AC9CD2F138
68379DF3580501049A315CFBD9A4969D274DFEECD0B14304958FD571FBE2E4017B8A27853897
14BE4CA12EDBE0C0EB78BEFC76315AA8F60EACF53FFDB1D3F59BEFE9A89884484780772B6C24
E5BCFB06480D174CEA4BB5A0EA9E09E05B0EA39D5AD05F76F58BC9B57E96AF05DB72087FEAFC
32845684F0BCE34A303BCF991437990A1ABDA527256AE23AA1831D416958953226AC621F8430
2197FE4FFFF024D04F142D820B4F04461E2D4EA6787AB2484338F5D685726C9A9A9208D0D9E0
15588CEBC34190CA66556323C4EDDD2440480C205259A1B6F70CC95A0F0710EADDC72D4BE536
E6564D30EFF592B069762F924BA012DA684306B055A03671DB9B0924472F26266EF11DF861E4
DA81962856EF1BC4E989C72D475822734C1E3213CE7D7EB82CD1B8E9DA40D2CE26B476E9C716
14EB2936471196B81168F8B325222E545BDA1592F2C3C84A4FB9F977A67EE586485152B9F7C0
7D828C04E1C9B7ED189903FB44059FBD129491FBF6FE6B8124D666DE63A37263975174524E41
93D0F27CED49AF87126A7F7FC4F3F91C967E8DF5EB14DDFEEAC7C928FCF2A825D7FFD37907B7
46F313E5EEBBBE9B9BD9746FB41839CDC65BCD4DA7749A5B175D9D9CABDDF6A73ADE13261E53
3D3CA5A7BFF53842F7CADA3B286CA81DC5910B1D9B397BF711354EC2AD02B59D64D91EC6D5D5
FDC3A627C94D3E17F990B080F33CD206E690C05A8DC51684A659376FA6C3E411C24B701EEEA0
F77D3B95526D4AD25AF4B8FE1341A6037C25B10AC4851C84BD0F3855BEBD6CD10AE91050B027
02088E931CD96B6A99F3307CF11AD651B0FA04F917FB4B3739F66D63023E761611A9D300071D
3422C85D7EEA134CE7F5FD6D5C202A97671D1C078B7CA8B3805DD21B22BD5518C6B803008973
F42157EF1CB77174CBDE8823F80336BE2F5C01FA5A588802B245CCF6C1095E30AFFAE3D0E99C
D7A1BCDE3582D2A3D355340E36943DDE7F764A7FE4B8321545BE04A8541830F50E58B7236438
2179CA6393F5E819B1DC84FC5783C92746C614F5C91F5BC180A896AF5093F46790966AA2CB68
5FFF37E7E3338997624D0F9DD447634C5DE26473606ACD6DBDCF1E8194D1596AF4505DDEE0D9
64DF9F9D5FABE81773BDF623F3A03A7C40A6255B303EB9A9536E0711CBFC90F292F571988DED
C33661685A49D19009525BFDC2FC4DE5889294F0D77C147D41A45BA4F8E43651154266C38839
BE304F9DE6843AD2D6840138778056575BC410B21E7543654BF0DDDD0A732D540EAF7D5C383C
B07F662F009CC862D9EE2B272ED4423EB4BBFEDFED2ACB7020369C996C612AEAF3447162F90C
E2083977688AC315AEAD5C57F73CB8F54523296B261DB64F1ABF926C687B7AA5F7EC2472AD04
98BB0D4382E57C8DEB9CEE5ED7D3493C7557AB9C0E875181750EBF307CA650A66F13FC03A49C
CF2573279A9501B2C0457FF0920ADD1E10E33B3EAC850A43B7D3C8D98988BB5117117AC5CC78
C434CF31F5074F2E2566CB519E0161FDA2BDF63F04E7E2BFF275208C2917923E0112EA910429
76E26D50365E9DAF859E0C7BE9DB46ADC226F0AF37EF7668C4901B9E7F0AC68288AA765F78A1
D2646C7E50DB75711941A21568E64AC109F5EAD56AB4AED35F881C6E24EF745D8F571C07C660
6C54F63ED9F8547C0689F6C9EBB770424390DEB4C3F851F201AA87ADAA8394040522A55800D1
CA8F6C9722994869623A94AACDC6D8EBEBC34EF82CAB787BF35F9AE176D96F2644A6CFE3FACE
3EFF5F5D0119FA9231578CFA5775DEAD271C175498287AC58C7326CAE5E00015BC02188DF6E1
471720F04818A47679ADBD5A6FEEF79CDF1242447427ABCF4A6557290F8ACAB7DA5F0F9F8C01
33725D75728FB1855A84B7962ABAC055B47FEE71672EF81C3B04781ABEC2B6C22CCE2D680746
14363903199A46C9D7ECFFFB73129E2FF044766A85B54F3EA13642713A0D27C6A83F61B9D31E
BC98B29BEFC79DA3CB58230DC5CAC5D0F9C387835E0018403F0DCF8A18710388EBC37AA1C016
F775ADAA6657BAD29C5DCF2CAC2CD9FCE27D64ED247EAEE7ABADCC655797E05D18EA60D434FB
1C23228FBEAE9C973A3FC592C5C0E61FA72EB5F7221B4190B7337C9279F09D49E74BA3049071
96990E9E9C2D4CE64BEA214732083FD9F7C4495A2BE3A63D40EAA12B7423B03104E9119EFFAA
C0064D86828E5CF9BF9E14DF4369292F0A59AF841485AEBFBAF378E9B52803FD51DEA582AD40
8E7CB1ACED2083F7C2E8CA017C4BA4E25CC46D7CB7E5895664A7B55CD0DA11BDDC6FDFC5E229
B7C0219C939D857F5CE4FB70D643760DAA0CE0A7B3AFB658AA3C93C41604873FE471B7064383
6DD1610B7CB9A045187E8EBA00DEAB7CBEED5ED430167519E1E8CB10D9E699987E0B71006D6A
62E8A5DDF6476BB85574A752C555309B6C9B722D924AB1DEF08F835E7303E2DD99301D1FEF41
74F4C098F282509C9D4B2C791399CB17D6060C1C0534A2FAF9F38678A59C28BBAE714899838B
A844CC308BC59415A64CB477BE52E8F99B1D18152CF300844329E61B511846D5EE5F02A611A4
CE11DC0F0F2E45FA9A3839479291C5AF0979FFE489CDAA1B42D28499AFD966A0A1FCA6740D5E
E217E10C0175469504582CF44E633199C18636DE5924825C247348B6ECAA36EE8BC620DA7597
0FAC33CD0E98904465D230B64E491637B7E6C3DB4D294CEFDFA02A23378DC81C5945AD36B8F2
F81426C0AE1C46DA56D3DDB54A3908868E868E1CCEC945D6849357A6D196D9CC4FB967B3CE52
3C95A84778DC7661B9E6C9D43B9DA85A8E706D71D5F8EB2FF2F5A84EB1B562608C0AAAC846BD
71471D84FBEB5A0FCA36D8E3A0F640552A98793E84B4F5568281696DADBB48781F23B2E0E687
DF38E4955D53F0FB3843489E826F7E20ED51D2A3EBCAF564740EC108AB27DC207271F7E63B37
991FAE2BDD8744A6304AC446DCB28279450671A8B00558E04C7110F878910E3E7C9C61EC79C9
65462D53F00AFCD3B4EF5AB74D5BE503A1FF7305796774B9BD429C7711505D53843F676371F5
8A5F2F6AE8C16421AFF3A455FC414F0B4AB198B4A9F7B27534BA01DEAE761FF6506EE5899B42
519BD46F91F6AD2DF528BC9736576BA9AC2D2FE8E2B4251E28BA44128A55EBA524F99F367B83
F7BDA7AFB8C531D54A197916584547B79AE434BF9AF50C333821453E1D4841B9A576BE1E3687
07B8637A493CFD11318797C931366B38AF77B9BF64D128A065BDA50725588C6E1AAE3F6EBDBA
C8C7A3950B3FAF007C40A5D597D96580BD75FDAE0053CD8C62EA7CF631ECF3A643DE3DABE021
2CB7670FCC158C57A78D180045DC5660362A3F17739584277EA1ABFB6181B1517395C5E5594A
584E64A43DFEC71015F160886547F70A1D892DEC359CBB9DA5138AB29B5B1F8E56C136632A76
97246EC79A8221061CB212FA3A2A03FC38F55FD8512E327A6F1CB8E72881EE1B2E9FE43A6F79
424560F1D21B08B9F76873149DEAE9BE52ABFF904CFFB15CC603C7497F850B189ED11592B339
926CD928F8AF76E69829B2FCE988C6613C36D09AB944370DE24FF0A448BBA58E0CB4C7B63B25
20658143FFB8A042C40380FDB15693F4C49725C9C74ABA8C3C571DDA80545E2D92F721160877
2F49DD3FB42465F31282DC0E62DA7CE2A1B40C0868BA63026BBB56D35A47AD9A0D0E230AA7BF
FC4B4AB1B5069EEBEE9395E815EDDE1BA254A80D8D38C7073E8AC15478138ED4A22DB36D9B4F
DB930ECD4A3FA98B87B9D542505E5D0C993A374D8223C40DE43BE22DBCFC425CEA189C212A02
3874DDFAF5A1AC7F5F4F3A80C34269A6F5D7833C8F30E21D5BB548BE792F7D1149A94174C69E
D90DA8B84F934634966B70D0465C1C2E4907A9AAA62459E010C1781A207CB49079A2BFD54372
1D8721ABB895BCDC58B96BC6DCA23C3930F72D1E6A9A2E61713BC3F2B4E6652F75E9FC54EE24
60DA11E071C968E00E9C706E5779D2601D97450D9FCE65BD1DFD4F5BD846625B6CA43877F2FE
6963728412EFC91273AF66AC82E95C79B4E0A949DC88D958BCF50F052D620B1FB8D3425792E9
C6388A42A31C799F31D29A4BAF8260E9A833C98153C80614F22E513BEB9430315878E6C3BB66
0231109B6E98D2ABA44D759D8792CD01B86071C2BE8162E31EDDEDCD1A5270889CD0AF7EC1D2
1D1A4AB2B6026BEE062673E1B74708088850395C7820935BD447898A1EA07F3D23BA73F662BE
BBFB2F45ED608965D9E77432BDC514DF5F516D0316DDA35321F80C03926657E9A16132EF6290
953ED59CDA152C0F2DC38C275A675E2578CF870A448FDE7D73E679AE61E6BC311BB313BF975A
E7648EDF1D084FDB3D61DC14BA882D489B2E469BF4E31EE93ACA0A9083747EDAA559D59204F1
CBD22778B5A2995F4328ABDA61E77708052B80F2F85FA83A3A3EB61C2114B597B787D286C9FC
FC594D7E1B597CA3A19D95D7029B81AC8338FBB48A8C63D903B3BA18E17A4B3F4404B6CD6356
9ECC2EC3BE18A5B5F435501841E8DB11637DBCE823E13F48D07732B991412F1043DE7323E4AD
7FF80262A845491ED2D6F3305F4196E53AEBEEEB3D1D00EB1C8950B02BCFFC1E2AB41AB270B1
969BC515D519A69CEAFE551F3A1C96E803EBCF2FCAA1945BC5256B774E298711ACF5B81AFE0C
8051D3EA70579B2CA6476244BE68211DD20A9AAFCED929E0B817AA845E4C0F6A26F3119AEAE8
B04555F5D6EA3F7A49D4D7470B6D29F1A2C64BA1622D7EDFFC622C119A50119B7319BF947765
841871026085AE10C87D4F3D4BD5B837817FA725390E523F2E3F4E052F4DA11719D75F9416E6
8B36CE1517494AFAD0E1768817D39E7BCE4700AB207086FC8230F40000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginFont: CMSL10
%!PS-AdobeFont-1.1: CMSL10 1.0
%%CreationDate: 1991 Aug 20 16:40:20
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.0) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMSL10) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle -9.46 def
/isFixedPitch false def
end readonly def
/FontName /CMSL10 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /Gamma put
dup 162 /Delta put
dup 163 /Theta put
dup 164 /Lambda put
dup 165 /Xi put
dup 166 /Pi put
dup 167 /Sigma put
dup 168 /Upsilon put
dup 169 /Phi put
dup 170 /Psi put
dup 173 /Omega put
dup 174 /ff put
dup 175 /fi put
dup 176 /fl put
dup 177 /ffi put
dup 178 /ffl put
dup 179 /dotlessi put
dup 180 /dotlessj put
dup 181 /grave put
dup 182 /acute put
dup 183 /caron put
dup 184 /breve put
dup 185 /macron put
dup 186 /ring put
dup 187 /cedilla put
dup 188 /germandbls put
dup 189 /ae put
dup 190 /oe put
dup 191 /oslash put
dup 192 /AE put
dup 193 /OE put
dup 194 /Oslash put
dup 195 /suppress put
dup 196 /dieresis put
dup 0 /Gamma put
dup 1 /Delta put
dup 2 /Theta put
dup 3 /Lambda put
dup 4 /Xi put
dup 5 /Pi put
dup 6 /Sigma put
dup 7 /Upsilon put
dup 8 /Phi put
dup 9 /Psi put
dup 10 /Omega put
dup 11 /ff put
dup 12 /fi put
dup 13 /fl put
dup 14 /ffi put
dup 15 /ffl put
dup 16 /dotlessi put
dup 17 /dotlessj put
dup 18 /grave put
dup 19 /acute put
dup 20 /caron put
dup 21 /breve put
dup 22 /macron put
dup 23 /ring put
dup 24 /cedilla put
dup 25 /germandbls put
dup 26 /ae put
dup 27 /oe put
dup 28 /oslash put
dup 29 /AE put
dup 30 /OE put
dup 31 /Oslash put
dup 32 /suppress put
dup 33 /exclam put
dup 34 /quotedblright put
dup 35 /numbersign put
dup 36 /dollar put
dup 37 /percent put
dup 38 /ampersand put
dup 39 /quoteright put
dup 40 /parenleft put
dup 41 /parenright put
dup 42 /asterisk put
dup 43 /plus put
dup 44 /comma put
dup 45 /hyphen put
dup 46 /period put
dup 47 /slash put
dup 48 /zero put
dup 49 /one put
dup 50 /two put
dup 51 /three put
dup 52 /four put
dup 53 /five put
dup 54 /six put
dup 55 /seven put
dup 56 /eight put
dup 57 /nine put
dup 58 /colon put
dup 59 /semicolon put
dup 60 /exclamdown put
dup 61 /equal put
dup 62 /questiondown put
dup 63 /question put
dup 64 /at put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /bracketleft put
dup 92 /quotedblleft put
dup 93 /bracketright put
dup 94 /circumflex put
dup 95 /dotaccent put
dup 96 /quoteleft put
dup 97 /a put
dup 98 /b put
dup 99 /c put
dup 100 /d put
dup 101 /e put
dup 102 /f put
dup 103 /g put
dup 104 /h put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 108 /l put
dup 109 /m put
dup 110 /n put
dup 111 /o put
dup 112 /p put
dup 113 /q put
dup 114 /r put
dup 115 /s put
dup 116 /t put
dup 117 /u put
dup 118 /v put
dup 119 /w put
dup 120 /x put
dup 121 /y put
dup 122 /z put
dup 123 /endash put
dup 124 /emdash put
dup 125 /hungarumlaut put
dup 126 /tilde put
dup 127 /dieresis put
dup 128 /suppress put
dup 160 /space put
readonly def
/FontBBox{-62 -250 1123 750}readonly def
/UniqueID 5000798 def
currentdict end
currentfile eexec
9B9C1569015F2C1D2BF560F4C0D52257BACEE583A5C939393E012707B47E0C1FA47D284A1EDC
9D01A497D772BCA8C543388E6DC0D1E2C4944740470E0914F65EFB0737B0851B2BA713A9A00B
36D07DA6BCB52920B9B59EFE587734027A3C5E6566AAD332FE6FBCCED1417802822A3B81D618
7875263D6BBDA04BBCF6E4870FEEAD60F104BB3C5A766610DD11AEA64A6B107B0B04439FA288
8B8CC39232BB83F7695ABA81F0260CD5248B9E649CD800BCB325468C79FFACB9CD3036F2ED7B
B65DC6F12E33DD6D45B61272314F98990D08C0F8274E999F4B46AF4B5C5DA923683C960FACE5
0087915D2044D7211A18E0C22967EF89552662BA990E2DFB9267E09E354F41E74D44BD80A2D9
05D2EDD60D8829E820C6AB0FDF322964C1ECB6569818A465D5266D3366D748B412446E602F0C
C52F3CAD2213FF6AD92C04F6CE8BBA94890FB44EADC41A0C42EDA4FE9722E6D4B17A3F6D35CF
755D0A1C90D0C2033B16BA76C456137ACEE0112E35EDFB7206A9CB18DD9274401C70C3039059
A583940F44CC19FFED32940FE8203292E103D2ABCDA173DF85995AEE98BF4A1F65EAD55FB80B
C0C737589FA10CF51999C634E05D80A7DFFB61433BBDBA17EA9A7B92F763586105C8277D6A96
1D092617C64745450B7DF4EFA70884F6017D9B0331814CF702F1140425EB8BF4C269EC042FDE
895A7F625C4832C1A143A14ABEB798E23B59F88EBD1414A66520435A4C8F5DD7A548A7D6A2FA
96F0995BC0FBCF91B1A1EB711026A99D2404B2103BB3626978385830A00A02B6AA820CF33785
F7AA45E267E6EBE7D737DED351C1D4E944733FEB30A3E6F81C1A7B74DDC9148B46B02A525539
C54A7EB25DEC18807557B6EA94C36DB0C91121160F61BD37CFF40BB2B11ACEB75F146BE38109
DAEB77803D8F580F9086BC460E5C96F764C1254E36FEB59F4CC13C5324B005B6F6841413C8EA
B7B4E5B72AEAD11EA0263A0B48C3CBEF08D9B5E189B29EE33528A11EE8AF3C94A3B9FB78D072
BC94AA937198B5AD852CBD82C786CC2716CC460BFD982F678B878C63A4D86D72358F53C5E123
5A2B60667E258580BAA99E2EF0E686A3BEBF3DD92411AEE590232CF6883E760FA271D7009E9E
23D266E57ACF2CD8D58D980C95CCC8786F84CB36C254769FDE99B1255E27D8736B6810E047C8
3911E082A13343E7C192E15EA50199FFC0D26AC886CC0D57E50D1EDEE1597FBD16A7AA661C7E
AAC62E09775DB8F10B7ED4BC31F714DD7F69C9229FB85CAC4591A88BDC376119D1E48C1532C2
D2F3EE465C7F6A2F797C63AF27D967C36D99E976590EC46550A4EABE857BE0131D4805C7B6EB
9C4953881F21B921A11A53D361B992C412726746872B1AFFDF6EDB0E4C7B5E9C61A03BE7F61A
5677753C51EA6A138E77F6DADBA32D1A22B06FF8184EC811E3F345A090E832F99DB19E98C752
69D157D54EAD3C059DF5EC1D51DD43C684D4E73DA01B24D978B906CE8300D3B0D64309FD2344
02168967E88FC59A1E2E8C0CC7E294D3BD8AB9AEE3C53728F3FBD6091A100A06C7071A27E69E
8ACD27591A060A3C6418F863E8AC6A53A7C83109FE6B5DD44918EA83196D02A495119D8EC4AA
0BFB3D475A449BC0E6062E25AFA16F391EDD7F4E31BB41C96AEB9456055A2D0E5BB63D3FB71A
DFCE870CA8E4462F08A5302B9F456AEAFDFF6F2F0BB9F2D181BD2A33FD99500DDFEB64756308
8235616DB75DB8DCA428B4CB1E8DC19A797958D890885F78C53D3427914899652F3ADD72D170
68113BA323B138BE7CE35C8FAA2A96E2E31AEAAEA9589E8E7DDEE73FEF10F3506EB8483C1994
93E879ADBB0C6F97C97179297083811FB3079150F94A2A69B8A2406641643523B8CC7F5074EE
14681D43F01993B508E6CBA6D4006E49EE526CE54F78274DD0EE40ACE068F1DEC7CAB0283809
614950BD6CF6AD5E0B954461C0C2C55AD2125E91A8D8A8C0C57E3F43A513AF786A71EEC82BE7
C8E2A9F54642C8E645B76B3A6D11D02AD91DDDC910FFEF08F7487E1DF05447B0B81AB31B76BA
F6067546554BAD268496252585FAACDCAEB4D2C56628F14056E88DF12584627B5896B695ECF0
AB1F2B2C47360B758B4BB765195369BF7603166A2C4F0811F693FAD575BA2DA2E666D4EC8A99
2197DCC4D4727C296E8F58E0D778EFF394B96EBCCE6F997369590FDF34547C52EC2049FA6781
29108BA1369CD93133DC5ABC3CB5B600A8306283DC2D3562F6C45A5E7EB6F8E4A4B10B090322
700653594B3AA15E50CA22A3F35319E18F25EBCB293197098C32F09F83077CC062C9D4313E1C
551D25BEAC502C9B0CF31FAB4FB7F2B24B9C3F21018DD790AD0EF161EA9856CD0286CFB8542D
12BE19704F424C0169FCE16501FB11241708E5E6BEDB8FB99134D2DA80BC08344F978739CF44
1996A23CE6F26E7DA1C171D5D1CD866858324791108717B8FA2FBA1BCF02167B2EFD8C1C7EB3
EE591550590A740ADEFFDB42424E5D945F852B356A2B03AFFB91FEC5B3809C4C12A3750F6BE5
99E0E87C2168EACF28796C6B5FA4C9F5DAE8238C518BAFAFA41AD1674B787118F7FA245A8EA6
3783F04F5377260B164D8FD9ACFE219AF8C6555939BC81B37DE0D6E8C2F34942FC608594888C
3C555C04515762E2B46AA284D0F016A7338F386D3E7A3769A6B8792D3301D46C7D95950BFCCA
C2F89B8E97ECD518445510ABFF088ACA91A42C77FC17F07E1FD29A5390E1DB91A5A18990CAD9
D7B60E449B168B117C2409BD4344EC84AC4C2E0E9F5BE0F3A065B762987C4FBA75D3BA32033E
75D5D9EF2D2994C075639082FF92B9F13BA951B811896986961BA607A228427A4DBBC471B2C9
6CEFBC7AB0DF918698CB8B8220CA3A361ECCC83151E510B844318F3A80E19E8DB31DB029D232
E54EB5F6AF14A1F4C96CA565438127A7F7408C541147763AC01BD25232D5428987A996EB4BD8
3DD25A2D94A77D258E12720F566D778297AAE5B3A2BF84434CAAC48DD4BCA5C23BA925AC17BB
C7D895FE5566590651C16CF1B7DFB661C40E5901E9A499E1E6115C50A54781038F4EE6712787
3E572D639F8F0FE940C3CDFE4E278726AD0A351C74ECDEDD4E881E519CCB9F914F9B7BCFEBE3
CA774E289F0B5458473F6299B295B184F412413A6F92ADC218DC39BB10C180EC7C87FFF7CE34
0F20D31E8BDC158850A84FE07966676408B9BBCB608C36F4770BA91DC4FF282F36DD280415E5
DFEBEB49A8B9A3E66DBB5121C041D348E26D7D5A451BA7DDC7939F027B1F23188AF16FD592A7
85F14D5AA453345471C150D8C8D5762061AAA58C1581AE4BB20D950270EEDF7E5FB5A1CA98F0
95102E65B059194730A0C7D857D455100DA7C5BCCD099485C7AFA4C26C192A5DC4B4913B045F
DCFEEB3D4B2F5BA9E6EFCA196F84329BAE07EDDEF71B43C19E88B579E1645B5D78CA75F6ECF8
19BDD0ECB870736E41CB0851916CCEA25B96CA534CBBF90AD2731CA1F0DF467FC6F79C01A20E
978C0BA87E2E8AB62DB77E1DC771CC46B59FC384E65433F95A6BFA2E68BCECD8D05D55B2578D
C48386DABC11CF6BC9D0F745B6715754AF5B0A1E27B5DDC81339F7492944F1EFB27044AABBDA
DAA8F398FB93BF497178D827955849BFFC25B51E2D79C0B06C58C316DA6A161C48271A367992
4012D2F654A24C4EE9C85C4EFC7F8CEA0B634C1BC4006EA846788223FB4520871400B115C941
40F0C025E60DE4A6341BDDA6F2EDAD1AB9B708D7107A6072B9071CD407A2E9CC322C673E2F54
89C93CA7F1A8C3971304860173167F57909035CA0BBD66746DC06821D14D6288F65E26A9B3EC
38F01D834E05DB50DBF1E3F495123CF41528BE7889A591C473F64A38410E64AC935FECFA03EF
A70895EBAD7A8FE077B78E4D5BDAFECC4B947E9B8673E4E421C4810ADD96EC9F234A87CF2CD4
11FD3F5544C96F22FCA6E8BD13F504DA7B5233CB0C91CF01DEF415D05C5851D5F68A1D6533F9
1651E236DA5FFAFB471BF904D32FCC15AB2CE83AAD14492B78DA24A8B5C7681837268FA3F568
FD9D51F9481598D750D55B34042698D798190106E717C760FD2F01CEE2E18D7571D3444CE4AD
1AE6517CDC98B5F1E57BBAE31DC064E1D5AC5F7B4759B8D9F85501278A52FF39720E2F617731
0B345F209D3CF1BDE450075AC8C83BB9466C2E86E5A109684BBD076030869C98885EC4B52100
A32AF6BC9CCFE8489C804F1B27F99292897213DB6B544BC74CE47812790D2A1DE19791DD75E7
49E1347B8327DF9811ACEE41A88C2F55C205C5E027A77C409E8953F25D5AD0BBA91F3623943C
8C8D3E154266CA313B86D1A0D7DF58292627DDC133F1CCAA287F06874B3DA26A5CF48FAFA205
39804EFB410B639E50FA1FE22D76A78EE2B66A00DDBD1C5F58F98D9FA31A88FE37F4532AA007
9D2D2D15A88D1AA43D95A11579D643C153B7AE0FCD7E36D3B48E2094DD252E331DB5F807DEFB
5CA4A2C11479FC64ED666C8F263225B56975B6975F97F3AB3BAF1A25383FFF31DC70D4A5C44B
FD4E04CF463DB1945429971E77D04404B68B371AED13920E4BB261002F6BD5425F96B382E2B6
E7743F7989F5CC4DE43694A1CD0DE5E7FD32E3DC9F705594DD7FD7AEACC24E7555DFCA7FAFD1
69EBA46FFB66DA068992EE32BBABFAA426AD3BFCA46A9336CF5C34FF58DBD2E483DF67224D6E
E510BD157617B2CEC6FD525584006C1C43A8AD7E3109DEFF944BE9B63E85C39BABB6D0A2DE79
5BD98817C8708D801884D1151CEAF460A68AFFF88D2337F3DCCE339F9EE039B229EDE0FDC588
E8347FC529176E97B767F7E32DDBB4BF5936C7B4010116B7BC254431EB65002CFBA9CA5F24ED
5E5CF504DD9F3855E0CCCD9E6E782F02AB663ABD3660D65F0BB8D8E5730C2223F896BECE22CB
9F12A93BF643EB1512280BDC2835C2F33C758E37D71BD43694A88F7484BE9EF538E2E22243A8
C76CD2D8CAC7C20501BA3B3727A756E7A638F60B68081DD742E847ECF3FE02FAE9CDA962BC6C
F9A9FB5F48BF580513FA9C31B7CB6CFA0040EF6D37F7273BC120919B64CA8ED1B5C850544C46
B633C735FCC32A777531D014D3E01893B8FBB03962D3628157E777F802D98080F97730597C0B
E2D576F1997F26EA4DB1462263429C633AEEE66579D00347DAE5DD57D2FF1AF1785271DDD2E1
C32608F129DFAB84277C68FE2935120940252E877C1D74734C24366C136C555B8EE218F31D96
CA92920E9C26EDEF3A2948F57973ADF8E3176A48AA4AB8DB74DD8FA7E0399FE0C1ED0E758B4C
463EF4A93F309DE86A37DB4A9B24DE503E9AA4E97615D805E62E7BCCF9DC6ED8BFE33FCF2188
D35630EDAE6C86C4A52B41B9878A77FA17C5A0E2E096FB2EEDC4E57DD3CC868E169ADCEA2ABC
540DAD20868C386AD4F86F144D5C569830B539815A4FD5F0B429C8C0134565E5493C1E6C53FF
E60EA9DBCE84ABDB580A063B74C8E7D57C50D5CE7810362BFBC0F779762BEA1540EBC452FDE4
9A3AFFF755AD6FB3F0598DEC964CB45D6FFF3D6C503A9EA0E36BDF33319D99D0B9D998CF023F
1FEC5FF0BF73700BE310634A48D6561C03B7727E2CCCB825205AFF0893ADFBB914E95A804ED8
D29F8F6B32ECC2B7C2582294B39EBB9709AAA945F2AEE828825A7C8720BA676D6C91D451C0F6
EEC82052D72855365538A8F41C01DB81AD1F5245C48DE460546322D3D63BDEEDD85F0A177193
B8D32E6B4E92326AFB32BCCCE0F8ADE174BCE5ED5DD2E6EBF1B878EFEF452BA4C2CBDFB50F5F
3E269B0FE8C57ADD23C74A44C0479E570C5826F0EA15611D1498FCD7F24664092786A7B15F7B
3EC0AC2188F0C1A8D6F4A1B96C73D2B1B0C62E679F55712AEB7DD13265A54B8413AD426157C4
F032334C69AB7099F50FFE35A1C8128BA054B5B87F52A21A4AA78AAAB56FCDFAE341CD1E5129
0887F4BA8BE3E99A2E8A2C17CDB412935A77356C25C4E23758E0527E130AD3B91A2DDBCBF44C
BCDEBC69967D7BA2A1A4B24CA5EBC0E58D0D2869D1F5002CAA9F92B77CB88C8C8EC5C65E7792
58D1C234305BD8288DD19D97011BA641333D65D6DA23BD23B932A5B449B33918CC32BE8A2C77
043C99B20FF158BF4F62B0BD6F6E00095C54F4A69C408C3C484499870381D4731883F3477596
A8678E6DDD8E92E0244DEF2A0529FE21D0CB1000F3E8587283D229EE7DA055A8BB235DA0248C
3949B17353FCCF81881B392A6A1FB089558A2F2CBC7EBFB334200EA31590B3E556EEBE1F9F5D
DFD668559B8AA36CE74BA5003418EF25791D89DEA9FD53DFA38955FBC6EC0DC6B201D6B39FBB
34157C9A46D6C8AE42295DC8FE150A13C63E5710612952AC0504FB52F0B6CE5BB5762E7803FA
3B5A0CD0AFB951CB9D682271783B3AC4B62B2A89E50970A5A74359F3996D6E5B835005302A6E
736716023D5FCBA51E7BE70F98AB9FE5C0234B5208B6F79B463D4FBD73CA41C69296B7F845ED
85A962783BF8FC84867404002FD380257B5D86BAD10F5A5D20718B88AE6B0E686AC47575F585
8FB3A57FE6C65E7B7C6FE7A92CB6A00CD0056AD3BDF4AD9A05E94E875714CE8574F8C9295D3B
0C70535911368E24A0017A5B9DCC0F96132ED3939D7FE40A14BA042FDC46E9B00BE39C1BBDBF
A6CA94BCAF4B19ADD148B1ABE84DB726647C7B5EF5AA5B61A57165EF07F2A75AF1F8CB7F575A
E9586A9992DBD311C099F7B03C04625917B1F0A106124A5D31D571A1AFF6432F0CF6B2506030
6D6628412543083BED6D43E871DFFAAE6C286581AE9EEFA415DF0F6292C92A9C93ADEB1C9428
3288A2CCED9D52E7B2E414BBDD9C79F4C5EDD30C3617F074F5C99B93641A014ADF5D760F6930
9674194DE107CCC21736A112E5E8AA039C5683A26DB8080B9AAE9320FF235A80FF8C1417E819
8CFA337B543BB29B5AC738F81EF9725CFD81209C18B35E2013E5259D9E747AD2E3397137F799
17DC36ED1238B1315021BF7365263CC8570BA647894D0816FADE8A49F953822210F74E051A41
07F4549D8626DD1E7E752EE1C2E64D8E587BB54473A499CFDE3443575CAD85FEFF04629D8262
1FA99C5A86F68CB526FB5F70AC5E2D46C8D2039F4CCA16CDE3ABEE0BBF251631C65858B1D4AB
AAF391296A1BBCA4D893F50ABA31C70B3D93C7CC5E5892CBD3E6B08EE368A4F800436674647E
F336279581E99D6132FE670EA6020FFAC584DAD29177105F2F27050DF6A5766916307BEDA561
44385BA2676C990BC5C84B3BD1CB6D72C7FC78921D404EFBE0B18F79BCF997A869C6714AE509
5B563D99FA2EBEAD37943E60DE71279F5736A3123A42608A71B417B45E0AF2439C7530E8B375
2C9992E5B86719ABFC508A8C340ADA6616B76506FCF186B608BEA756D9302DB8B317AB46FEE0
F1C81BFF62E0E79C35A2FC542FDA21E017EBDF74EC7983D267C4CC9CECC0C6AF8499D5ABD25E
34559C6CAA96FFA6BE9C157ABD47B08F7E9527C52A8D52379DE137891D3A9F16C157099B46A9
595E517344B0F175B810948AC9A19E5984B0A75928417AFC6C1821116DFB702EFD72B8604A2A
618545BD8F9A8033F2C2674AE1E160C4C5966D94E99AB8DA360C6B2396238534283B0751BBB2
1C7A33E9C988C7E686B6AF18050531FDFDF7C07FE7B2AE9F7F8B76E6314052EF15E109A98D5B
A6109CE8CE1476EED0189535B4830C30D98F4AA3A0431EFED99830A44976EF9C9D4E6D3006DB
DEECE847774EFFA556CD66269064F999C1C3FD4D04B0225B5BA9A19B6F08EFD1B897097D6B50
3EF688C19AB39E73B73560DAE3A5665CD7C44A74E66A77207D3C628CF64688261115BA4C8ED7
870D40C98AFE7C39985053010F7DB7548E607D4DEC5647CFB4008DAFF783844105AAF6735EE7
302D82CB1B612DF8CC7D5E3530C2357F29E3A93C995984C2BC76E9D5A0B36D40BF0B57236C76
826208FADBB6504492B0BC3CCA7F63736CAF950F51426D48ACBF5270C2EB11D4F0B2E827CF96
9C76C470462AF179AD4F0B104912F668E9F013F17001BB15D81C157FFCAC211DAF3BCF800394
0D2EBA3A5DD6F0EC53121D4F06857F612B1B163837FA52D4E066D395CB5C8D7AE2C0828765D5
781CEE9063FF2CB77F78638C37403CD5935BB21555670A4757FB84D5E3AA14E4B9FE5AD786F2
349E667415869AB542D3D60D69F3D9D10940AA7572CB92F7F180882CD731793955AA135BACD8
60F03671292DDDDCC7F3178900EDED9F048EC8991C61791A7370788A18FFB35633784D40FE07
86523EC15014AD165081AF052D7D1B8CD6876B7AC3689499D3C51EBF0CCA34AEE9E9709723A6
D2CCFAD099A5B64E799C7CE9859BAA596B3F184B8D65DA85A2255E73CD46782D03FA37A90280
023F4452948195EDBBE46A26412FE743505DACDC4CDEDB389441664E16A5235E48E5AD6383DD
E23E70FA58ADF16B95EAF4E753A77CCECAA67DCDF0C976187195E7BE0F12129FA9EFF7F4674A
55D18C9FD9254CCF9C49698ADE847200763206EF9189022292174137AD87BB36B9C4CC3A6FFE
57AF44ACF5C571E24F1F069C668D24DBAF04398A99E840289C183D9A7DD08BA8533D96165AA5
69FB085C8DB0CBB4711828081EEB8C0D72982BD87BBDAD292E66C859BED989DAA18689BA75BF
1F60FADB48D5810EC175CFBD58DD3D90FD9125FF38C7EFF3F4AE259686034D835A4F346A6AB9
AC3308E175D391E0BF085280F9F09B141D15E8B7011B4232681ACB895471AAEF96D2AD3874F4
88860E55BE833C117A3DC75AB6C200FB4F0FE69B590268002C3ABFB161A8DC3E31546C47E2BC
5E76B11EB3DE74719A209D9BD29C21055281C72014A0345B3751A648A000C00D5EC26941233F
4AA777CBB50B32FD943CEEF3DF54B848B8A867E269C718FA9AA7953505FA23EC36FAB543EC73
F461D0E3348F8C7428541BD5F0A783A53BF6243EF8EF9FE97265E297A4CA9C1D41A3BDBA5D11
D90FDA33102AD81545583A56810DE6DAB59D3615700B2D61E20D54EAB41FE56E8333D5C1CE87
8F94AC2A91A90335246A93B22F6645BB9CAAEEE67CCE6D188ECA9F006395316FE7CBBFF4A1F9
B8587327A06A06D6AF07CD358AD81638CF842A5CDBF234E0B4AB6F91411ADC5FEC43C434CD25
98DE0446981F0411215734ACCED6F9BFB10147921E4B1169CA68D43114E30FFC5F4F80CE4819
45A9B7D3B7AA30357964F4468A4E330BF710B6117122D954B62B3A7F8569B04306C8427E557B
5CAB8610488EFCB37C1C9CE9D78A8BAE7B07A845D273BF728F1E8E8D14B945B66D7ACE6B5FB9
C24470DA154183B4270D2D26C34BB4FE1F0DF5D89E7CCEEB1872B70E5F9165250B5ABF91FCF3
DD0163D4977B5D6760A78E02D72CDE1361967A139E77171BAF154E5FB7B0A08D7C0CD1FB488F
86FD03A95E0FA713FC32D0F32EF64944E997D994F05C39A7203DC192698B9AE8853BC335FD0A
4DFDA69BD76FC3BA41A7BE7849DDD8AA2E36D50CFC3F546000546E9640E97D44350B8141DFE5
07407BD20301B17CAD9DEB3DA9142F1D56C9D3D692A04E1B193666D134D94DD83085C58A775E
DC226D7AD940638BB1DC9242EB076369E255890EADE45DD6F8062FF43DF8484823694229B0F4
A70F7E425EAC964B4E273E0091295067E33B84481C4127465C94E0F26CDD2E614186F2D0E327
ACA479C3DB100439C88BC2E1CE46310EE078475CE9302ACC45A3E323147E564DFA490AC918BD
EDF874CDDD887ECD24236CF24788B267C9B52E64C39DBDB2817C92EE2E3A72706A40F0D8F9C5
DA4B7E16963A69340E408BF251FA0C7B11ABDADB8518284420C8674ABC70123F19DF8A0D28A5
AE3D5F4D8C2DE9161AC00EFAF1E66C2A4D2EA1A2FFB54A40F5380804E5E34BB361622E84174F
A7471F76C7330415B8574173CA3887514023D407DC43EE656C8B48093CCEBBA03747E6186681
387A168AA48B64EB48FB2EEDF9EE0F8C95B4EE935D0E66A23E84297E7C6249E50206C3C64FDB
8E2F036DE02379B8B801F30FE90E78E36BCC805719153DB07CD4719F4EEB97D9B40004415CDB
1318194FEF144EB72B268F8CC8764BB63E7916E8DA3B9F970A71505AFB2FEEE7F286007AEA30
AF43270BC94FD8796C2710C228589D68AB8E851D286E5B99A71A957DE219B8AA930BA8C65E97
E0E2426B6EE723836DA8BB560CEE060E957ECEC44634C1A7F7E989D82C80D824D7FC296A9570
0273789678DE2BA11629BA605D2A7E10C6BDC6D5A4176FD501A8E31291FE3E0A0F8B0CC0B325
BCB55CF5A11B44E083798829E7CD392B1D256147615096B4F0B3B0C7A1EB610C4FD055E13C9E
B356985B3494695DB11EE90EB581131B5F62338D01616B61FCB2C7E457A6CCA2289912548ADB
6922BD50C5DF753B6C1CB7EEB3338B790626AD94C09CDCA2FF6D7047F6FB57E0E3BC52D06348
E0A57A0B2B7BB6EDD2108E2A7BFFCACB01BA05C759CF36CD3D2C373CDF0EFCA0D74D6AF1422E
0D921AD574DB41DBABCDDBA2C7A8F89D4815730140FCE853D031744BFA8FDFE820858EB7DEF2
AE75D1895FEC5B2ADA98EF794B318F03E679FA8D65F4E6587D450DA3514435620FA67392FBAC
160B8E442497294C5FF530000882890D72C614D7D0B4CE5DC1C6BD52E3CB08437EAE8D1351CF
C13021365C54E6A8B3EED4F8119FB8798D42620EC21EE29CD8FD32F8CA789EBB13189BD35EA5
EC489A7D7B06502CEDF7C8CA52BE6CC6F56F797FC5ADAE8DC28652A02C10DEA7BC697434688C
1537A5AE5FB586403075FFA5CB19722109E26116AF7DDD935A4D7E22C1BF62F8B2456698CBBD
D8E1C2967D10FE84E07D08CAFE785C54FD380EB0AA8258369C72FD6A725A702E3DA0DB170E10
83802C1BD4783EEB55BEDBA33078C9EBA22F445063D5E035E04040E6E7937A3C6382B107222F
7DF04035E1E212CC2308BD871E4CE3CCDCE5C9EA2A09676544D3744E2AC4F657AC0D2C178E29
45A289A352156360A49AD007E4E0407A42F9648D8C402CAA1922D437D6B1B5D1562DEE4DE0A6
F272D802285B2F8F525EDC420C57CFF52B3BDA863DD6E1236A0AEE3819F3AB71F30AACD9C566
DE8BE9880A6FB83BCF75CB536D64938D5CFAD3FEC81543A5E022A4A68406566C1778D624667B
E63A7EE6940F2007B8025DCDCC4541FB1169164EFC1D57FBB5C62AC2586B575F54715AF66C00
75B349EAAD2E9DC759A3EFC633E25704C81508F28C46D3E5A3061D23D47736455A8C881AD2FB
FEBEFCF8A943CF30548B3F33B7AE45090FA0970878459E88A029F2FFD8FDD035098D60858F9D
C8EB23F7C70A5AA9D781869FF8516F0A5D88B528F803D27D07EFBE58E9BB6639518A9B095EA5
B41ACB21B0C9ABB17F0E4010626BDB07BA23945B60BE41967BB9DE12EB643A1B837E0C3B7CBF
93752E25E7C7ED2A2A22ADBF32F27CB7697DF3025A55334B5B5F0CD0FA786C574CF6096627ED
D630F20C107D2BDA0BC4B751C1121F2B8CC281264FA63F6503EE9EAE66C1D680DEB76A5A312A
21E84C6D40AF5ED739BAA3CB9963103BFC326CC43B5CEEFE36529597760643305F306A9C057F
477EBE0702F3C5572CFD96CCBC76210B043A4EDB6D612CD7E86315E21EC2A79C7881740C07B0
F8B3B2ED860DEBA53BB68E4160FBB41EA13B2A013DCE531E6D824F72B7595380F025335ECA5B
EC0AABB3F3A6A40A90FDA324C844BF1DF7546A6A0E0FBD64B32BE7985E5F75922D306577A32F
6D3887EF119391DCA7F923DFDE861D637F17598CA17B80C61F44BA1FBAEA71136E0FF482814F
E30CF6AF086D087B5AACFBF7E87B3C92B6760CD836DAC9C61BBD0E9ED174D79F14BBF0611FDE
6BCF3D78B7270BD867F1E63BC8DBF31534B62F80E81471C4063F144C89A5C30964B4862289C6
463633632C25134F82B7CB6B0C4CBA290A2B9FF27C7329ABD9C766CFCC1DC1A249272441604D
FC41515DC472C5944A7D574CD580A174FDEFCC0814E87BBD8DA55EC796510807EF8C6EF1E512
FCC978A8A0608EECC26C89C090B2FFFAF4B6865FF253EDC5DE07F329987FC121372B0417B124
6776D18855EC98C4E36A1A56C5F0C76B74D6C100216F52D97F17F02E32F10EC2D20FCC5BA70A
9976431CB4BDDC31D264A65E76D19DC76A837EA5B63B1B79F2855E2DF1B53037FBB31F3CC08D
26C923F1E9AE67AF79F3BA42BF854DE1B051B27F960825E1CA37EEF05C4C367A370DFA9003D7
9556040345A7714FCFD13CFE692962510A7A695330EEB2D54D915D15863CD2DB1FFCF124722A
561B73DB6ED6317A43EC47FE0488E350CCDF7CB6BCDAA9CCCBE668F022E46F29C2BA216ED09A
0926A35CC5428F1922B8C50714776C11032FE4BB39C2BC87EBECC94BB92F6301A43A9B69C71C
E01D9FDD2154753BDD928BE4F9BE517A047882C4E5E9338B34C47D0FC97354634A5D6AFB1D15
CD368B3AD7BCBDA8879977BE8ABD3AF0AF29A6D8CBB26E3D25FDBFCB8E4E92B6CC55838A3BDA
638FC21F10E535CF5A8688FC1CB45821AE4CE3DA53846B320E3705AE5E269D67C81E88E81633
FD7CC9B98BA631B723568FC204B6F119A82C06825694D307912D72FDDC346396A800E9453C9C
8200CE35A34C188E484D9ED8D69F4BA2CD07C3AD340BFA518C4C9EC80652A2314766F86FD820
33F77BCAA573E29B0BE6434DE1CA29E11629EEA6E35EAC754BAE39C4856AFB3D062947303FE4
57D28AA34F0A562C93E5C51C6C09E07979BBA00D495C40E5BA2126091EC3B6C3551DA750CF12
5F3B889A11E515863C90DE955617B4BEA129535E678231311D8A46DE332E674FDB9D459AFAF8
D3267CDFC8CAF0C4A0A1ABCF87AECE388EB3625F5E36484B3B648344CCE1EB5FACC781C7DBC0
D29AD03E7A9F6C9054055F95CAD9999BA1E256D00D32F9E3537B0DF314F873ACA8492F273732
192F335D073B8A3EEB6656F88A8C56BCBD37ECC7F459977044C04F9FF7132B37BDC7365285A2
D09ACA1242112DE8480D054F7F55E66F9F8454A074BE85D190058D874B10824A8ECDC4B36782
0D43EEA8CCA3296FB5D3B507D51B05F7D40ED134F9EA7DE8160DB1759595C645114C24A4C428
5DE1696EBF2C57F4C7EA2E6167B32AEE422C077B49795888CBE5B093E684111FBF3777A4B32E
8160AA43911E8069136D27137AA555494B8833FCD487F0CE8DAB8CEFF0565050818BA634AAE0
7D7847DA62B1D73F33A98FFAD21CEC7FC3309BA7D048794AEEA3DFD1207E8A9F1A5F8D94E493
DD1CD58683FCEE8EDC8B9F14B02CF1D3760601F5C04D2CBAB09A4A99572B98F0B935E925AEDF
E46B01D7BD8CFEF25820705A9550EC734C42E235887090746B74EFDC6910C2BF0B2793C7C965
5D09BE751BB1BC35CDA8A473151A996B513D42CB889BFE8DAABE0560B4D36412064D54168066
60CCF64F51F0C49D9134E9C9CBAF5EC6BC6CF8BF6F86D9E653CAE648EFCC920F8F69185902A3
2D4D2EFB809888DB21F414E31DD84FF445C7BCC62B5797BC7775B3E01E90AC60AA99096A26C3
3214C790DCE924A9912E5EB02A60AE9108540F8B6F51F360CB2891FD49BA945B3468223CAC30
8A531F0F43892BDE186AA3C88F987C82BDC98B243150050E3A51AD335E2F3319323BD790E2D3
28D8C5B56222B68695B2477E7B366C90394DDD9D5CB5339714F9D1FD38421272442A45FE0FB2
017D8C79E681C19FC5274E489D2AE3C7749053DF29EC12256E42FB322C2D9BB5A3935B167D5C
B963A0252792F800C705A19DF6BB7CEFD8DF4C36C26AC08DA3DA7AAC12638A1A6E4BE489B477
0D106A701EDBAC5B2966CC49E4676827A7E45431A76664BFF1E1F729AE3CD94BEABA0D14DD6D
70C0AA3FE63E9D3B70974E4F50A74D8F077FEF888C51E0108C25A68AEDD848356EE35362D594
38BADCD849C84D77443D0A731B6B234D9F390658A71EB844CAEF90D668DF751FD82259879A21
C0A88FDF718E9F45882C9EDD4E475298C9090C45DAD25385D4F5271043F6E736DF4EB0E9F30C
DF0A8D043AAF0914E1DDCACFDEA4429FB397BAE765F4E01D73133E3D263C2D1FD33DCC1FDE28
94FE7C1C0CAA25462C6D013FA89C16163F05D137DC53B85911A4F107931C172AEE16314046F8
22EF3B0F183658B8A5ED13F9FA9B440D19D629F50C029D4054F9C58F12B58B551174C89A69B6
3050E4B6E6EDA5983BBA2ADDC8F80A2376640A1104BAF8C52AD460546481DE6648968A3E3F42
6284DF5E3076DC18173B4A870FACA3D6DB770776B4972A2E32B251C4AEB1AAEF13B15E3D9E1D
63853AF48D2113422778751790983BEB11C743ED0C6EB3A7D77D2BABF651440A27F91E891124
CF15284A64A876E3C16070D06451AF8C18553FD09A58378C05F6DED30A4048EFE67A85B50A03
48E862B93C289A4B0E087A592EA18907118AC2617C014959C8A36E492780114F893306F715C4
2886D33C9AE2B799B0EBA8D79D291C39CEF2E6AD5D911986D9E09CA2BC78BE64806CE49522B4
42A201EB57652DCA969219FC92A41EBBCBB0055AB8D1A911A74DA5DE63971B44EA61CBBA0CC9
D2135791819FB3D53E422EE1881549789A00C7F146AA676CB9A318F154837F005B18E4AAF199
F2BA5EB992C79B6A19D065A71C28CE7372A0F35517830F9CE98A743C49D7B03B1F3723B78B09
B6A9049FB83A2FCCEF599FBB6A0648E5C7B430B5B1B6337ABBF8584CB8BBBDC0D3D41EBC8E3B
9D5D3E3244B3CCC55B81B8895A97535DD5EE01C54748E6AA0ACF73D7E1CFD6DA3A957D68C701
E21BED2A7CC158541033557BC8200D6E013E6F00FB892D4F02956B2A8B7711C02BF425B82507
136AFA64715CB899A47BCBBA0023F8017EE019980F179551A854F71A7650B94FF77EF546EE55
1EBEF478216B9555053EF8139893CB28E8AE33D4EAE9DFE01B8105DBB9179ABC0FD28A3C365E
3C24A3A78C2CACBC1211E34BE6E8C6E9719051F76733C810A5F5E81D9E536D81EB3E33221123
EEBDFF127EEE2B66B9A3F704F5C063EE0DB831E41E663EB82FF6C59D17F64FD618C939C24D95
8EEE16FACF394A1F9FE4E869676A9D83FE632A9E68705CAF87A93E80E3A8434321B5E37D01AA
E483A53537DC6A0D244B1BB9FA06A9B2D351AF8D4F1FB2DB78BD90DBB0744C20BB261E5E3580
B45BD723DC96D23CD22855F7284C4B3B0FC44EDC2301ACA114D2623ED39E8B28A77C0E847B8A
D4BDE12670D4B70B7A5E058C8FAD82A5E6586F4C7EE28029DD41338C1BA13100644919F25ACD
C4982AA4B1F1ED1BE6AA731210B2A124D103CD10CC58B306C10E3BF462FA279BC89861FDBE49
7643967800FB3FEFE0729A2C45F737F4744A7B72866D211661A189AEECF45CDF903BED916371
E1FBD6FA0BB7B3291183ECE4795776A77D00B3F6E506836D590E5506F5DA290F58DA3AD79A94
00013035C955019F33177A9C4DF53DA7A73E6382A34127C406456477EE517400BFD6F0EE81A4
DC1D4F6B153ECAD3AD0977633D5F899969D3083B893562CABEA9C661217D73439F9E01A1CA3B
10A4C0ACE022AD216641169F79093F785BE5A0F3BF91FD9D83DB8775ACBDCDFE88B4DE606F78
DDF007BD6D5AEBF3322EC3390B0582AA13F0AF2CF702AB56180B3CE019A9E0F65B710338A1F9
2CD87FFFB0499342853F9461C98C511E9CFDB4305D86F719A124CD13445FB8AEDB9C994261F5
3EE35076DF2DFA1A1C654F4F51FBD5CDF7864AD45A69DF8F40AA59F571B320C63BDDBBF05FCB
9490ED00D673E93703B80BDFD08F871A537979A9D4CB548E1A63887A92F63E47072693E76BE8
BB104126C38111E542338FBD2A0AEAE441A9CBFF971E2EC82D17AC3BB65C71FAB4ED5AA611AC
6A2DFF199D29748983D46C122E3BA0341D417D0CEEFDB49452A58BD4C57E54FC84145A497246
6861E96804CC2A792F13AE60176859887B61729EEF07A3974BB002E37713DD9E82B111F7423A
F9F4B32AAC55C39BD88FEBD23499116E6BCC300027FBDE7131F4A6955042CDCE5601ECEC093E
BE98DD6A6009CBC661CC5EA17791EE064DB5A00D307FC876527C28AC03E6922EF361726AC2AE
F9BDC6067C2601A7E4C64DCFFEB7DC6368CE4CE59413A8C41263EE47D081602074BABBEACD2E
2DACFBA4E0EB822692F74140BC3459D6F772D3FDC2DEC09579E45353E4D6687FF81CFC85DF6C
F5C1D43F8B7635A2AF85A6E853533643DA76CB9D9B8D06B14B9435A1D165E6ED695751C84F24
B72E857C6F67A6F7FE322C473A1CC6A789A2CD7D76B116FFAE837FC7522D0824756A3403AC80
CC1561729CDC3B74F36720BF292C53DA41F55D3D86A3187B597036025701826A02929D1D0827
F3799DEFBA6A0331D2BE5E2C1E529FA8278A6A46DCC9551DC74582C5468CCCD9E1219BFF5AE7
FB4D5B434C9310FB18A081CFE4DA6420A109856D37B404FCB373FE72636A8E07E5EE73A3E776
7E71A0551DE8875D8A1DC87602F5B24EA06689D3CBC3C6528953F6608B391E04FE7AF62D39A2
3F20003365E804089BC952E1A87F44A458E3C54228D10077B021D7E3F9D92CB235FC6CB114AB
F793950D2E33F29199F1FC39E7E9AFE0DD1629B0588F67A68FBDBFB32BB9D0D73B75D565CF1F
4EA45F275C7DA0E5A637C6E9EB93E805BFED0236913BB1FF75B2F690BD0900EDE2EF180FA760
F43586397ED8567F35BEB11D12598FACD994EFF881F4D348FCE3AD5450C51EF9AFED4121188E
128C3DADEFEF49760E2CDAA224128CC289AA150EFB6C0F61476D2E05B1C12431867E53CE1D9A
0EC6A0E2AC5EAFF80D76BED553F71E7AD5612BF9A8988FC5662DB82B0CE0F46509527901F4DB
8ABCDCEE984035A5EC76EBD552C6F81B863368EA4095ECAC9C8E8F90184EA23096C0E5ADCFEC
2F80C9DFFB10BD5DC0B51E029AE718522957D4C85008E7BEB876511F2A7CC2FE47340678D050
C725188A9E9E24B89CF7D0772E9DD309F9B944BCA68DE36FAFDB5114AAF7EB75B0504D6BD953
458E3C9FFDA391FDF519F5A7A0D8E6661659663012E1656CE9D153628C7FD262C0D7A6E78560
56D44A67B7DAF19FBD15668576E6330E4CE8A48BD6DEE0741E5DC2ADD67D67E8BCFA69A94978
2E57BE3C1BFB75CC5A8E09672978AA5BE0F1CDD03319899D610E6B9668091F3BAD94725703BA
E6B08AE39BAB413FF3E08A3582ABDE26CE29E0908E877981BAF319830ED3E22F3D7E77E7D8B3
08C145067B1DCEBFFB700AC401CDA58962E4D93BCE6BA28344D54E39BFEBF0C5BB4EDDBA930C
A1A1515B2CC34AC00DEF0E935F259F40B4FDBB15C48B07FF22CC9594CBA7AF7E564D64E773A5
808BAA33050A95C6CFC1B14ACBE2FF58E2499DB21E785C5724B49CD825B901D0D2E1EC9D8BFE
5CB6E0A12E66FD0F887BF25B725C902FB37CA8DFAD8CE76AD0CF2A95496DF39E7E2ECF228611
68C47540EED09B9653B84FA84B3363D4883FAE2478567F026976EC7C6C19756CA62D83CEF310
130B6F230803A1052E1C59A3938D9DE010C20D578EB38F4CE3F45E37389C4989896E96EAFDDC
81D52102B05F06582C7F82964F342DA0247E9E2D20028765679B269C19E6F54B20B2B480F5ED
36C240D8755455875C6029CD7EEB170CF11125BAB8E788CA4FC21D6703DB98C91DF9F01C1296
7F2058018E2EE87D969AEF73256185DFF11BA33864374CDEEBBD25B6845679EF849F129A1041
FAE3E7690BF5EC50F0E39ECA3387B596CAD088A11DED7B1603A7BAC812A8EA932E774B6D4B71
FDEBFB4331F39DBB4D612589C45804FF2149B8BD95DC818379AC0923AE6893585A026EF40E00
2A81D4ECDCF1443D80CC34D2B18840B01271FF2C0EFB19471B875557B608451133702A9368B9
D6526C6CD65FE6DAC861BA625D30ACCEB59BC4857968BBE7D16B59A919C27E3E6FB60DFF5609
172B80EF520F027AD1F3977CB727F89883DF5FA39A0243CBD598C759B44D58F3A33B5DCF00F0
A0B759C0D452F04DD62575689ABEA0ADA1E2E3DD7208708A1119CC1533748E2D704F4E552B37
243AE84D2B8E9E42B19A7B8284FC0C58437198DA2145BA405E81A2CAC2C78A957F173A6D490B
9FB3A96F24913F25C757EA9E3C67C893D916FA4EC2C2B400FDFEEB5BDF219FDEC7787CA873FE
C1441AD6B064951836CCBB22A23B4EA90BEF32009A4D0B6B5B7CA45A9865DE0FA04985E2790A
624A35098FC987C5DF6130134E1051A71F1BF31E75A9DD48A04F807858D19C114BCF9CB9FD53
42CA21DFA3857B3A4E8FB94392F5C73E03A6439B1BD7B413847306797F56A71192D2EB9D8FF8
91570B816E7CFF7FC612ABA9C9BB8F6B4217F8434078B0CB6BD4CDEE9FD78472FB11D5D7A0FE
71DC21FF44FD587441E69DC98D1CF86916D6FF078EE6883F36F53892782708EC1BCA3C41D524
FDC1B7E97CBDACEEC2DEEE2A2641979B583460D19AB369B48236A8A1065FE64BAC0ED0FCC0AD
7122CB8C3331A59392100FBC0D19C235164D2685BEECEE536FABBA39B941965EFC89C3A565E1
7B9739E48A733167B4DF46A74F00617373D40CDA19F23B566A55F565286565BA74FD97D997A8
E9218CC10A5FB9B6E98B7171C14955E644097A8A8737C0DB65A00A14C5513A0095B1F6961D9D
12E5FEE1F2906098458E2D1BDF059CFF4BF0209EBB3F3550423B8F7944600D78D0C0D28E35AA
C7A28020D4674A252A06AD7FB419448E96EEB3A038E6B302EAA25322B511B449FF2B310F3651
EBEE9495FD9E5E87EE75AD8CCFA458D9EE7B2838DAB856FCD22E0253F49DBE0BE67FE42C3724
112E653448EAF8AABED801841D8A18857A5AB461F6D8A68BF67AA424D8D3C7691580915CB870
BEFC3B8F7954BF80FDCFA52BF3884C8CFB2BE5AFB4A367D352572D65971663A5E0F3F792FC34
A3F489F30E463E0C777E21A333B020AE0D797097B782B7B3FB0BBA508E3C23E7283F28F752CD
207BF9F4476F525AB997505561C49F5A21DD7AC7871BBA3AFF031E7C8D5C57EB663831054345
291D64379E56D1EB22A9DFC370B155BFF179925217C8551BFE05A05CDF4796BB33C4C56CCA99
B0953A9857EDF711480D024F1B7D8C92DE8D45EC5223FC5EB8A8947FC60D697ADF9F26BD04CA
8059C8D094112EC6707D4F04E040B5DAF82722AB36DAC3E8C14B90BF60C709A95588B75621CD
41488E45224FE4B5AA790FEF59B40057E96DA269685D5B9833A3EB3644B5B55C05CB0BDC6093
390CDFB650B07D8F63D8B696FBA5A5EC8C6C6C5A491861EB9DF931A8CEB34FEE8515694BF4B1
A54D0987EC4EE3FB102269BF6F2C1B7094A28DC47B73A5BB4E9BC28AAD00BD8889FCCB0CF152
DE16C584810572034C71B03D3CB1642D427D944766E842F0829B412C0A79A193B6D448C3ED0B
3EB0859AC2D7EACD64CB8CFE254BADE0642029AFA2DDA74A95DF07727EAFD6903CAA49A2C092
2E070B88C71AB787D7635401C9ECF389FBEDB026BCE47874EED6AF233842985E05B6A4D91FF0
E7EA1A203886B25D73A9DEAA231DD549ECF2A35E99F7D31555858BC1E012F248DE711E15882A
7CB3EF37DCA57F2BEB5DF90E8FBAFD429B2CF8E4F47F9C27164698C7B6967B69D32F7EFD03B3
1D076184B8949BC34EE548C5BE0D11B4403EFED30DE46201B40473C73DBE1B651CEFDA5F79F7
9B407BADB5C233750CA14DABE25858AB4E615336E569C01E45E071FB1DBB97866A56E1547028
566A938A7A67F615DDB69977A1CC00774280AD10C1D49ED41A7F2770DC213D9A864AF2E6DEF3
20DBEB30D88CCD5CD5401FDA993175738F4CE088162C2F84A79CBA23F8FD34A0C19225269F14
03D2D0899C69625EB651B3AA2CDD2B23060FBBD616F63E3105DBADA88F185FBBFFC29D738E93
A7A1DD3D21D56B05CF92FA8AD6BB4A18777CC8318CB216E09DB238CF7257A4647FD31CFCFBE5
B129E2A1CA5CE3627FEE9067457B1C76A665F6C02F0B24D9851E6D1F7BC8AB716A15707DDE5B
1BE727BA6C76B7EEBC7247A68960E26F9E20923DDFCD970A1C5FBC7254A2598B4DBB8EFC7667
FB1D5A2729BBD8CB35C5C34DCAFDA839F6B9CA0CC9D619BB97F3266B7961AFC24D794BB9A1DA
9E8193AD202A8C2818635F7BB2F40BE6CE5F89C516EFEE7930441AD73AE5789203C5CCA91C43
6820BDCC8FD95E1368A5B2584B3FA0794B4FEEA3C6C2109AC8C49F4BADB83965720DA2A06E96
24E3EC91B54B563369B83BC032610E8683DCFCAE0F27389A68879FB6DF81A3DDF4E3F30169A1
F7E9391176AF7B1DEBB3BFC35D9FBC41A227111C746E112915BC4A2775D4878ACAD09FE95C8B
7A2577B9561C106CC64A41A5C9457C5B46BB627DF5FCDF40F4B560F6570ED1E8F3B74DCC08E3
7259646714831A2D8BECED2BEE7505AE0239B6F5A66166239FAA4742DA864DF672949E01C9C2
DB390FC6080B9C98369679FEB3CAD92794AD0F54CEF49A6C7E5CAFB8EE4979C6003EEDD89B89
C3D01044E96B995A5BFDECE27A9BF22CC5019A26339950A9513B10691785F51551C2A3BBEAC1
72B4727EF5B1BC2F9FAD735BC06B95D4B22D594BB35932EBFEF502DD05911FDB2C94F6A0EE2A
519F2BD7F80AEFA0510721F1C2C976875C44EA32D7F897C10EFA968375D45BD97FFD9D5040EC
0B4EFEB802102208F2E2E8378BE4BA6FAC41D670C2922FAB9A4E43CFAF45E48E0B275406C703
625649DCB26068414005389E6666DD3F789E42A93CF4B0B6288FC46125FA21820795C8FABA70
798BBA7F6C5CCC50F320568B81E00D980327B0DF815928BF01EC24A54ACCBED6B8249E2086E4
93702F2CBF898EE7A7B5CDAE0862DD0F9B24DAAB1EF6103DE17FA777DE555F711B125C70BD15
326142F638238131B77E996960D4D011E8292035364F012C3EE54C5B90FEF3C17DA4472C6471
7274077BB2A8309A6DAD4CA45D9547E1786AD2C1552BF483D33F7E2747CD494B06D23EEAF598
F6FCD94C50C849838006299B4E2CBE9E4FBE4537BCC78888FA324C52D231CA5D500FCB53180C
1D3E48C8D78E1C9604277E9638B79B9055A7ECB660F887907EA5DD8D06A2CBC43E1D1AFA3D56
AECA021E3BBA63C047E7570CCE232B991BB84A2F36D9B161C79EDADD1D9CAD3C27A36B018437
D22862314012E2F44E8BE6E9638DB84E5C35743EF2BD654E47FA1A8AA7150ECA9BB984E745B0
ED168806F37E28BAF72D2AB872F812202C981D2CC7497D5E75888F69486A071807B03C6442AE
07ADB38426AD611FA73784B73C940D0086C57B802233B2184FEC8AA5A1168109B47DE1577A6D
7229A51029A5F9FB4AF863D3FBED56B66A7078A5ECC2096029BE79DBB55CBB13B8117E18BD4D
2FC772BE30786D29A4E1B3B67CE1B2D6F70865AF781C0E607C7B893EC859179F70F99D14C940
A4F49A5FEBB24AA35C3DF4C5D7A4C46B7ADB4E16283C5B362E7915CE0628AEF257842EB320DE
2AA902944111ADBC1FBFE5B9C084E33FB16B72FFD3767A29B307B6048CC15AAD6573920064AE
5C4598C093AFC67002F7DE9C25D727E6EB6BDD528C95EADA166CD721EEBACC95A88EF8103F6C
096EB2078C617F7B9A26A61277DE67EA8912A2F5EE8A863E152A2EA2F8B2AA852C0A94168F70
C5FC97F531D52C0DE9588F3A5BA28B69BBBA2770C42E3387130CB46BF84FFC85264C4C408C05
DC30ACA6C4EA6E27041004B4E9DD1105ED7BA8E1BFC2BC5FCF60E158B202F47D69BA2AFC12E0
E6ABA502C9256D7DF3112A91738366577D7706FB06DEA18CB0581FBE4A010B182BEA14999006
A122AF79C8DE0A8F5AE1ADE4BAAAEB74DFF512C57487A5C55FEC2B63880E9102D2BA36A51F0B
8B7E782C01269C001A7366DDE7539DD631D158EFF62DCA40B433311A5046CAC246AA4A6E22D6
B8C59C15838A348205C39D37A35559DD6E6A165D45519723702649991A32794D53CF3435D3BF
F8E0D7E1380C59DF125CA55CD1B50FBE5F7623BEB33CBFB6D8E06CB7F242AC0BD2EBA5B745B6
5D8A288CD3B527E5D8CC8218CCC085B6B90D81D398BF6AC562B705E94F56545C538A22B79B91
5CCFEB125212A7A48B509A14872FC9749906482A97586DA6376CDA4FF6B97552E2C75AE50AA7
E651DA1140DA4B574BD8EB7C7C310DABF320FDB39374193F6E8F7FA212DE7F792C77AA5B3BC5
C4BBD419685D7DACA2D58676828214B10FAAF8ACD7EA0061CC2C22BCFA02415800BE52DC9384
63FAE05D6AE424A483D4FD9CF66DC9F8625FBA92F3066CE319FB0E76830A08A075D6811BE320
F0C57D5C9656CC607E3002BC2D091282E9BEB02977B07D9AE2F05B872480C56BA9602C2A4122
9E1A4AED07063907449E4C9DCB0C02B4D185CB74E4C7D7E3990AEA195D34A13BF4D06762B029
9DA48AE8E44F04AFB36D88605807B108EEA5C30A270C9AC1AB34406D545ED4E496D2FCAE02F9
AECEAEB4DAD787E2376EA5734B86CE2CF93D6F3DEF9A631DAA489427E2A4073ADD1F923DD727
09512C911323B4BB0A946EDA609ADC6D64EC631B8416824E45C6F4D0C0BD6B542E3B05980A3F
5FB0604BCDAF3E9ABE32028A819953BBAA7EC289C1C20D52E6135EECEE37D5FAF7BD7A4FDD76
4311911BA70632AB683D6BA7DE878217EA2A4DA8B9A7795897A1200664FBF15AAEE5EA03307E
3F1A666F54E4925ABA46820A429E6AE50531FACA7DF68EFD7393845792967D3595112E49A325
94865B3C2041F873688ECA3914D5E23D9CB13990F25D16ECA6BA04B93073EC6034A7A3A53FC7
5A44216CFCE89DE11B9DCBA67D01A313555761A3D95AF9CD4D71E2A69418517465DE8FA030EA
1D66E4E070DA950842A1953E54A3C7D589E2DFA503FA4CC5BC5205A9676F581764F07B99D37C
9D9700B0C99CFEAC9BDB1488107A06AD4701F385D482562D7E7773C6913FCE15C3CC5F14E670
7520FE31833F4A80D0CFF603295B23C54E75B963F5A95F2B5FCDA65FD7230C3D57B23B81C62D
57634011CFE6DAA959941B03FF0DBA3F49149951B3863BB98185E3FDED7979E22A386289EBB0
ECC33B30C543D40D4EAC093B2226870249B3FADD8FBC4281398153F1A62EC9CDB3794793E19F
1DA5AC996D75143D931E22FE99CAB83E0D370B755F35B1B826AAC1E473B3CE00BBEE4074DE62
AE63435585B041854BFEE360221E566BE84BF7DBA46A1BFBC92ED015BCD1ADF1563E23FCA208
DA7470B836B5367B317AB7EE24B41E1FE0AFB91C9A81FA37EEA89C380CC7B93D6289BACE012C
B6FF57FDA6EFB360ED7D4CE5E95DEF15060B2AB087FA6AAC0D7148C30041EDB8C2B3436D4204
1EA6FD75A7FFB1B1E7AF1070E5AF5D4474BCA255046D2333963C92767EB7DCA9E42C67BE10C7
CA045164B2A3DD09EC51D4F85CA0BF63CED90D007B59A9F67DE9570BBB634B977F9ACC4F1558
018757634B990E585636ADE03E2608C32103DB38CC8E165511C6970B40395E0BCEC682D874E7
6FE3BD73690E999C1FFEA204968498C0418D936F22FDBEED39F0B0290F612977446D2A630511
9917DFBE4461FF46EFFAA47A3A1BEF21C26B185114F72D33E3C8F097466F1B623A7082FE976A
988071C6921518B42120E33E9099FA98BC341EFE2E48176AD0AA0F77A5EC8F822E81BFABE622
F5926E81BA7352D39D9D6FAF87CFC07460C1B17B3301D0F75AB8AFCA17FBBBB98485E6056566
2C32C34E091C472F4BBD5A145B4267003AFCA53418B60FD1DD836806E9E357E96D1C1C26CBCF
26A0C54EB70051CC0815C4C7ED7D2F1B24095C2A55E79D841531AEF0751A13C8BF6B01D00892
22BA047D603D5A8694BE6A6DF54489A90C04F2B9AD1B9A79FC5DAEDA36AEC8E34CDC9FEA16D9
5F2C510DC1151B63D4DE7A16F2C8A6095BAE51A4987174EAC75E538E4B475FC8F8AD73408A10
7340DC598FB313ED24D5EABD8DE013C4BE0305EF5BDB33EC7929D9DDD48958D4D154E3B918B7
4082A2D6893966A394D27EB8EB63451DCB7C7AC2F28CC496373F53C837D727BBE56852C185A6
9530ED11783E11492AF5575566E50CAEB574D35E3DC15051E9539BDEA7EFD32DDF85142D1FA3
E824EFF8301C6E36C4996F81846426F7EE6F327164245D84CE1842D021C729FD2B18B49D4794
CD5AA5DC0A36BC5FD1814B82CCF33A06BBD218C6118E5AE606196E287251A9CF85B35C6DE359
77CCBB59ECD183DB154D855DE416235736F39D355E776D8C27A01A57AB948EFB85DC4209FD11
C7C36719C8D3140C5B60649A0558D7FE3B3CA665D10566A57C48D1642B910945C18D0E1DF3B0
B06E56A6E260C9651010D077902637C6BC643EF05E0193BD98A84CEB16ED59FCD75E0D7CD6A6
EB2D2DF658AE486C065CC9BCB2C846C9D86C63A57D0A5593D2F79B8813CD2DC202982D07644C
5FFB764B543DB614A454ECE810F51779C870BF526680809D0E312CE3043DF638353749A4FD7E
1FC03853A2D7B03C746F151840454A0D0ED1BC2C0D9EB6361B5CDBD4AB588FB060A77B22C671
643F3D7022FC1795C79F949786874A070E9B22DE73612B09193E35F6C9481FBF1A521DD21C77
7AE537994176F96C9D9386D714D7DF557C4876DDF0D0123069AB873161009D620F32A677916A
91DD4C7017B55419E679C7B76CC0D596A717205B923280F05FDAA872855D97DC601B6B0BCE14
53669846F722C054FDC88839094D1C34E86859537C5EDC4B49C8D8DEF7D88FB23C6ED9E8D2EE
2020F9F0437B6C2CC10BF7B069EEDB3ADB29FB26ED95AA8DA3ECA644CA2DDA965E23068B40F0
A3348C28B086E88A8E2FD5C0DD2C38DAD55A875E80C6FE2B89F02EB4ABD59864AF87D0786D05
F44D5A70484462A3CCA42D73149BA69C3888973FE38D81F1F0BE92B358040147191ED68BA395
993B7C750695B415F0C8D4D41919FE52554F2294D58AA8B5C8A10A5546C1FC0EC969364178A4
5A39C7409D2D3F0D63DA29EDCACB1C842B5DE000BC656FF25A65CA7509A04C8C663E408C660A
BBC6BFC29FEC5B21797FF93FC0326E6E6949EE8A57F10FE68BF036093B3246DCA2F186AAE675
05ED5131D21762916B9D33B28C7B005D8F1E27C7EBAEE959B90B56166D6C84881BB4ED570E89
15F708A20D646FAB59FC6D677F29414C06FE177200B278F5C4BFA0E454F86758DAF0EE806071
93CB1BDFA481CF62C2D03104FA17750E9308B36908D0D347750B863FB377DC07E669ED46AA3C
C6839F8D7FDF4CDD80A74529BE168B02D29B9BAA88C3D6651C4E3FB4BE09D73B30F4E9C418C1
8568681AD8A9B1565E47C0C357D36BD7116F99B0160A26648EEE108915C44D435610285DA064
9EB6477A76CED18D1B2953B542B5FDB47848AC07A390D8576706F3A8384ADE1660872C944BC9
EC50CD01D6D530538933F117FBB88FA991EE92C07F59CEFD51BDC68668FB0E5FAE1010DDE5C3
C8B8B28B257C37FE98700AE8CFD6ACD2CD1F85F1C7545382A709714A351EF0F1B852B543F86B
D4B1D894662EB0FCD74A6A582A8FD4069F0DD403C0D66909C44135B38E2566EF972CA301CF18
2F5C101DD0DB3C77819585A3DB0D37847DFDFD113DE80A720CB0C0C42EF0776E68C4041DC248
E01A0CCC112BB636B47712AA5A9C02FB1214BF9417B413325C36F4B20BCD7C323C84299EBF52
D238F32EF83ED5FB9C7CE70C289BB6B28CC40ADBCD4B325EE6ACA66963244AF021253A197232
1BE150767826C0CEAEF5D56D8C5682C71978B3E2BC078C9F9BFF661913E30CFB4B87AD2985B2
323E7867B5C4A2060B3EDAD8C26FFA843B3EFA6DA3EFD604BCFB47AC62DBF9163FAC2CEB295E
61115BFA2A30607852385D1E4B3F6E75FCCDBA36C5BE91BED15881478E53761EB91DD8A873EA
BF48C564CD46100661A1FE1609953BFE2181C893C99137439C55B34357AECA4AE55D8CFD4313
E61DA972FD294B99ED3B516AD025A8E91FAAF4048406245D4403B588AA9F4EE013BB7C9B3161
0BD3F653398511039EFFCF061D09071433CEC17C29A8D31015FF9B609667D320E5D2079F30BA
0B439C45F3B0CC63661D0157D80FF7ADE609F53C2CF089559DBD44A5A715FEEFCC91641C1D2F
B5FCE0A88162EF5417C3C828CC6832EB3EF953E9A06708EEEE65C2F4E5D146BC178CF476C2A0
FBC7B70601533535DA948773580AE24EAA9122ECA5EA7641C1FE5C5BD93E2A4B16EE0A26F68E
ADFDA9BBB488D640CC9F7BA0036614994E3AAB632C2E360A3768C6D0D5D5BCEAFB9DF338BB49
61E5369627FF4BE3E800406E11668F13CB082E57CE2DE207B918D7B5283AF96CFE75AB736B85
33EA8C5218715B59B987667F49B34D78ACC16D4C6134FA5AFBA0C12A7573AEB9AB3EE8B95CBA
E8EDB16D22A7EAD311CA0AA63AA5AE2FCC5659226971EA0A142D141C9414766966AC846A9121
BC657387AB15D4DDD48BF7D3FA223A1305A31EDCF0FBFC0D064B712D9A818E6A7C793831E56A
403F06F1086E8237094116B0E50EC7F62A965EE389240109460C407FA4C0AE572A17591D10CB
6019342DA6D4935C9E9753E20B58244AE53BDA788641CEBB4922791FA9B489A8783200D713C2
90A5ED8E216087CD37201523851D34A13F8B0D87A9B1656D9D2554FEEB638A4F53B4AF41314D
C85439FC1228AC342EF74E35014B5D00B99E1CC1255CAE3E07343645B57B5D39FCEF11DAD18C
F13361BCE148F93B2938F1D440AE4C7BABAE03AC75A6E0D259BCFE9F2AAAF45803C26BC06457
C6F2D7C9E5ADBB2C755277526213CBFE402876596DA525596AFD668888B84562297CB3A79331
8895C909DDC76654536109749D2E34D2D75646ED9396A8F83F91FBC985D97FCC03E523CD7C49
CBC62CA1BADBDA4910731A553BF805560139493068EA92E961890C197FC80536DDBFA500E158
D1D62A19450052F7F23C96865C97E683A433F19D62E8713099E6C3087500F2420EEC9AC0C5B4
697B77E9D448CE61514CD9B77E37F25FF425630F5E225CED3A6FBFFCACC8062A501B0931EB48
95D76DCF3F7C2E8E2CD691283D105DA62F64DAE7F4D6387AB8D9BDC49AE57A500FB53CB0A2AC
2B98B9E698B7115B7F2397E967E7FC8A5711610AB852D2A3B6FC1E367F5C32166ADD7CB15E9B
E963516439778AB4CD95854E98C9F7FCE4A260F004567C6C8C5136467CC19C6DF152D4BCC386
3A819CE684F8696E39C7B2B0BCEFD72211E8CBE71C5C6705819C7ECF66BE32F58A01E28954FE
D3D94F2D3895B12F130827CD467F10040F9A6399B01EF2381BE48764566AE694385D06C5683A
05F4961D8F6E052E02A8433586AC2B93282F4227E6BC1D3165D613A78F6B8D05B7DC19C49684
C76408CDC25F5A6409ABDAD97E61F03782FDC881F7F2AC03E5822E6F14BEEFF7FE8567687B3A
8B3E2A3A6C339C84F69F6F49980ED5C7719F372BC205478BD486DC4C8307BCD7E2F9B2244A8E
F9D9CEBB84C61B8D37261B5C08FE431AC682E76512C5070E155F0FCD9344F3109369CF83BEDC
17EFF3E1C0A4C3BAEF7EE4066558667D5FDAD535DE80362A9454CDA73DFF44715192303E0D8A
CF7279B9289FC09CCC90663703D680D66BCFEFE856ED7FE1BDF4409B8D560BBD053ACE898423
72B1ECC8C7D780A8D647DC1273A22803A055B5C45F6EA5A8DE5154EBB299BC8A5A7EA4F7DE2B
4016BB22B2DC8B773E57D78556DB34F1D690E207E267794A44FCD6A64373BEA8B94BAFC7697E
C23A563399276BEB20CC51B9D395963236C2AE01376FB505B2D5DED6DB0E322A6D2CC9300990
1000A7DC5BFAB9B18BD04307B5724CFAC9037E44FB1C66E682272DD047CD78D63646514BBE21
86528D4260BA8AC0AEB05EE03C3B48949A298FA25BF44D60FA268864A4FBAC37DC5299BA8CDF
CCA9FDD7B64F4978FE184FE745610F2C9302D752831581C27CA4E04456E50920C9D747ECED57
A80EF4DA1A5246E35BB607DD117BFED00684514FB6A3F4FE9139D263C4FB8A98AA314035A0A6
73F98B1FFE5EDDCB663E762F0D97FB1EEAD0191B23B708041CB916C9DED0D069D81A356211CA
2EA678E5D94BD73689C4DBC6EAB71D658A20EEC846E847EDC852DF7A4C1EE3D24C89B34AB325
8DE41141D81A97224661B6C386F1B1E75972E8206C1061602F50CD7B1F8C96EA70A4E2EB5E79
C17CA7D3AF2C55987E90233C324813580D71DD23A821BF78BC557D60E19319DB3AB27896A757
EBFF4CBA7F5823B2F32A23C1BF1A41C5D4172BE89635991C1F6DCF7E920C2DCE3154E6DEBF06
18822875D3181CB2050F429696481CCEB775B5FD4ADF7D970590CC6E323B44BDD981AB31CE8B
FA58AA1ABC3AB05DAC977C74914CBA5620BBED4C48AF8B0D5EF351E9777B5E617E9AB7CB1483
80A166625E7749C77B1D7F1443BAE8B3FD262F53A9A59803617BB08E4AA9B7DE89BFB1DF1AFB
3ABB679F8A6CA32233E2A2A085EBD38DB28CA197DE55CC0B0131519A57A24886DD3E6AA49D26
7A54E686093A2F5A6C0EF360EFF07F29A027A0AB67CE26E6DD3113F443A6D9A0E7EB6CF8F7C5
3768471FD6643A1EC3D62D0C227690575DFE773BCB38F5D1414FE450F2354D178AA2C7D6CF9B
08F7242D03FB94C28BCD1D59F2979A9C586F208D148FDA27B5C3DD441E4F0C8BD8FE309CC796
81FB0EC929AB8DC26D4175E0FB6FC6020FD74C79290B212F14297ACBBB9EB97C6ADEACDCD2E7
EE063CAC88B43E031E1977820CB67147DF66D94916EE9B1620D62870DABCF17D270C385F8DDC
DA288A7D1829F1D2F9885A63451118B8CE7B8BCFDB09BE6D16BC6E1B8D3112C2D667351D4DAE
2C22F5C0D05A44B305F7BE0270BBA58803D45402F637DCF0A9EC73B8F36FE1D883C318540FEF
A8CB7623CA1162B813E2D092E8DD64E6BE418E3B6C57A711D9B2598DE1D0C1CE7FE33C8D1CC3
2062B3E2DD084A34591BC28C9C6B039ADAFA531C038C681B4C756D7F5E5640BA49C60A834F82
CABDC7C680517457410C6AE9BA06C236764C7FA69B5C8DC15120382A5DBE48DB0C61FFFEB654
25DE4E3FE0D483B311CB9A79B39AE091BCAE2ADA5E472C1D3B3B01DCB45880341E8AAFA7EE86
9C1322FB9D1FB44E3E6238D22A6CC81A94AA6549D1C2E18A5E38356A95D789106A019449261B
4ADFF9537351897ACD8BE2BA22EA3962888F26760DE96E7FB40E5573503D35F73484B41A2E27
458EE0CA07661151B3F7105057ACA6C4BE383C14EC320E5D779A05F51A8FEB66E926E12BF40C
697E411982D3F3DCAE665BD69691F7C2C757C0402A9927960C29395E7A288732311C2AE44DC4
3EECD68CFB55168676D316FF50F7E9FCED063708EFB3094E8EB27D6BEBC23F0172B158CF5664
0CEEB2BE322BA263C46E6415E2F680BF73CEF3091D82C6880746987EC3F0610226D904DCA8D4
5BA3918D807D46D50124ED6A276D0AB71C55980591F3E9E457BFB239A6F301CAF977AE8BC3A9
63CFD912A99E5380E675929FAA0398843B1C8CDB9A76CA5C32EFD17A9FAFA119295428106E59
ED046BA23E1A086E7168F2E62CBC0C83787D55292545E2FC7765A8EB7DD6B0C4C83EFD177266
F22CFAAC05D4EC307C8A329134ADAD218E786689C4668CBEC025130972D2ABF2BB611301415A
27CD13F2FB38A6D534491CB1B06CF3758DC3DB11B944E31BC7958DD35F7062F7E7E0B4157D10
56A250AC96C1ABC44DA1B9A0C85A17804D124523AE28DFDEE2753B7C2323D64E933D515C98B8
B21F83D2F1F2AB963B159850C87C3A93D2AF45582FA3B2F7E7A5ADF743D1720A55B0E9247F26
44FE0C470B337044363E19C583E0CAE7F0D28A46F4B53AE6F411E3466919CF0D9E4844CE2405
9081600A6E07486D3349415D42F126DA8F6350A01FDB437DE73568A6A391E9705397F46F38D4
A07623EBAC5C6908018331477C5F51D1FE5B08DD2EA49AB4AE25C3A8764719E48CE9312689D5
6965EF991567A46440DAF7755BE5B076683B76E0F5341D208A99A1AD21D8D88147990945B2C3
11F81951CACBB6E1B3B85AC6E594CF79D53EEAB974F9F4AD3739AF13873E00B02E9DB9D7105B
EF02503B335DECD23913040D780996C9FE162E6B8DE40DBFB963D5539FA64B0B102D60A9F713
3FFAB1270BD688017D5912218EEA15D5E8E010AB98F46630DB351BD27C54FEE26F611C88BB70
93ECDCA5C704B6BF5E825F023361117F06EA28910989863FD9D7B4628887E6096F0D9E4578C8
D2C35B67C0F378EAE5A84908CAF59095621E708F12F7E32777D45BE7B8BA9B71D1B9047729A1
24D973AB1F0BE5A5037F5F324E0D6AA2E7A67FC9BBB684172484459BBCBD3F044F420A59943B
01FA28E8EAE00C24D22A9B1C5767E5F387172C963637BC2FC1D67048C31F6DF12CF5D2D82A3B
384AEE125CF6BD69189C8EE6DEE342B231E1CDD31837B44F8082DDF7C69D31CAD02944941CD7
B65B574E5491AC45DD3E2245C35918C59F623270963B0A8C7324F11095BBB4B996CB46BB10DA
CFBBC13C288093649A6EFFCBF0B8FC0E599AE5FEF536B76CA82110B60A9CFE6AAE63561C8E1D
D62E82138DE27FA1C09EE6B17233A54888AEC96CB24F7102669881C5FFBA815EA2E5A6B82B28
BE5F79707D143E57F998697E21BA3DB282FD48F60F97B8946D994532F60CE47E2EEF194F68C4
599A625ACA9CB0053570BC6F1C9F9BC118E74DACFAE7CA5AC6F7DAF6A87DEFBE708A71F0287C
EDCC4D4636F1D29D8D2E37A59CEA504C0F4CB7574DB912B44094575D0D58BE147AEC8DA6CD08
857153BBD101568D01B1C3113A8E07E47B18CB70BBCB01409FE4C29C82D857DF1A23BC0AB3F7
60ED275AEEE0C77DB49E2DBFA196F05BA3B23A5D6D2E88CD35F20044A1FE077E67F1EFFB3FAB
B138BC6979EF93FD6E6C3CDADFD3C4EB6AA21C91DBEC73B25DFD2E053284DC6137960F6FA11A
CEB8D57E49D173587EAC967CD9CEA22A19A24DC75B568318077F591E12244731E8F3D088E0BE
9E7E6D5D088282C6C1FB678380A865CB4069EDDBA83821E8ED906EFA01AFE5B2DCD5ED968AAC
45E6725A45BB16487C54E2C2DB77316D4E7DF20E7EE2A673E22DEDB75BA93A7BA64558915248
0573177EE37E91726C3F0A0184D150AB6D96B585D137494F350DD8673DF86E67E60263BC09F8
230112B6A1C493B47B81DC9C547EB0322FB5668B524193F5DD31692E145B647979A00DC3D6DF
D1369F1AC0F3DE009AE9C4192DAC360CBC9AAEB2E8D8B2B3FEDA5C31728E9247F21A9FE38E01
5DEDDF37922AF9B6F925FB9B2B1C4C9B2313C2F0EC9174945A992992970F703E74E730C1E064
D46456492A01A9DEB98A812C96689EE82AC21DD35541923144C5FE63630452374AF79A8B2B30
DDFAC7290092436E0B83AABA36F691EFC5F1A4779AA97FEFB999BDB136C544EBD586F45C9F65
B8F86875A9E5F83C01506B87704454A709F6255A530A298B4084C614C3BF2261C270CC46F7D4
011A9E2DA7B5E178CF82A0EFA49DA239EAFB101FDB64D7E9FF291484C2B47F8566C566C70E65
C1DD39383A25270FADEF54DF3582F415ED1E677720398B3F0279B2ABD7DA23E436FD8FD3B0A0
3B561140FC402F15CD911A8428B624AA72B605AD24696242D975D1A61A3D2B9BB3DBD61E2AD8
F9B473331C9440580C7F9858A2F3AFC73A202760E922DFBE5D1CA92FA95DFEB87398B41B31E9
C93C8D0473904520C05787DBE0F7AEB521D09E1D2A1B207AABF2569E52FEEA23645E1373305F
728A4208878F74BC0CBED5BF3A7CC248D9B9188DD63BC0514D8AACE61A1719D2FED0B54F6B49
A5D527F72934DADCF2B526A77BB081548AC134E3AA341DFAF597E254ACAA465340B9D680E3C7
686A6ADBA48115A2BBAD51B843C009EAFC83D9C6308F73E9FF16D9DB072C07B72AF1C5FED163
2C2350BBC268646B44040E43E8047BD65DDC8E25173134C3A2F56ADD1A32BB7293C0F18D80B8
6107769189163CD29DF6D7DCA78C33547386A682A562AAB6E0D586CE8E950F58997F7C1619EF
E447D3A661BB7F708FBABE63DB2DCA42771286DCD39C218F04059076BB6ACBA068BBC51BFCB6
890A3348619F490967161F976C2F52331D8758C31F043236CF2CCA5A77D0CA769C1698E5928D
8FFA2D071A95BCACAE3E335282EF698FCC440266DB09440F8A829AE99A1CA03E8708C68436E1
A7AF28ED12D5A55847B2E3F759BA638B5412FFE0499AA94FA2F55C2C5B1FB235D6538D060DAE
DB88A804552C92499E77AA473E1A2C51A45A328541667CE76905BB91C2A3F86F9DDF21C875B0
FF349EEDCA2CB28C1E0DB3360742DC4780C1107EB3DF5BDE81B4600AEAC642A78A387DBEB843
52C9614DA6856CACE1A4FA4640B487B448E63FE7E567F14AA6593C8404BF71475CC356EC6506
C740A5537AA47BAF743412F431FDAC842286CD399855CBCE1ACA5B60A9CC771F28A31B7DEE39
0C7B5B77DAEE9D88C39198263CCE4FD202416DC43F523B5833B964B4CF9569BDE488F15BCAEA
ECD971457867CF607213509D18AD79964E47755EC4AC3D2346E67783C75A17EFC568C994C850
AB215821ADFED63454EFE286F217F741CE02361D79B18D977C78126F2536E3E09515188D4B73
9E11064AF5BCD86C45265782EF88488E6066C0B71A33448E6EB442ADFEEE2BC099B044B2335F
3D547545C6E603AC52E58AD347F9012ACF774A4B6E890E35643C469F50157E781E62F2CEA726
DD5FC10CF951DC17DBA7FB2FB6DD640B57319E247C499B7F6F075CAA26B230ED959DE657C2DA
2567C5453409ED2377D23AB36750E2063D63C14333FBDF27AE014A2CE001DAB27D22AF54573E
04C3CC0E77AC27FC21CAAB89CA0801D1AD357C3295E952954CF0A03E9D45382992AF2EA70A33
E94681A5E405D22923B991FACFA2643FD07DE00F0B5702BE9ECDDBACA40300E49C8A00EB47F6
15A8C6D79156B074B0AF9A67C9C34A6F18FC7E2C075DB37979A29A4ED6C5BE5E1DA15C4D7671
FA1EA5181964CFE9B211D27B75A370C9351B95505B54FAC043092B65735FF0BD6A3698241DD7
B516C058AF52192904C35E9BAA3D5D39D6318EF477BCE9D0CA2B55DB8E192D1A3FD3F023DB46
245721A1EF8F03CD710000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginFont: CMMI12
%!PS-AdobeFont-1.1: CMMI12 1.100
%%CreationDate: 1996 Jul 27 08:57:55
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.100) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMMI12) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle -14.04 def
/isFixedPitch false def
end readonly def
/FontName /CMMI12 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /Gamma put
dup 162 /Delta put
dup 163 /Theta put
dup 164 /Lambda put
dup 165 /Xi put
dup 166 /Pi put
dup 167 /Sigma put
dup 168 /Upsilon put
dup 169 /Phi put
dup 170 /Psi put
dup 173 /Omega put
dup 174 /alpha put
dup 175 /beta put
dup 176 /gamma put
dup 177 /delta put
dup 178 /epsilon1 put
dup 179 /zeta put
dup 180 /eta put
dup 181 /theta put
dup 182 /iota put
dup 183 /kappa put
dup 184 /lambda put
dup 185 /mu put
dup 186 /nu put
dup 187 /xi put
dup 188 /pi put
dup 189 /rho put
dup 190 /sigma put
dup 191 /tau put
dup 192 /upsilon put
dup 193 /phi put
dup 194 /chi put
dup 195 /psi put
dup 196 /tie put
dup 0 /Gamma put
dup 1 /Delta put
dup 2 /Theta put
dup 3 /Lambda put
dup 4 /Xi put
dup 5 /Pi put
dup 6 /Sigma put
dup 7 /Upsilon put
dup 8 /Phi put
dup 9 /Psi put
dup 10 /Omega put
dup 11 /alpha put
dup 12 /beta put
dup 13 /gamma put
dup 14 /delta put
dup 15 /epsilon1 put
dup 16 /zeta put
dup 17 /eta put
dup 18 /theta put
dup 19 /iota put
dup 20 /kappa put
dup 21 /lambda put
dup 22 /mu put
dup 23 /nu put
dup 24 /xi put
dup 25 /pi put
dup 26 /rho put
dup 27 /sigma put
dup 28 /tau put
dup 29 /upsilon put
dup 30 /phi put
dup 31 /chi put
dup 32 /psi put
dup 33 /omega put
dup 34 /epsilon put
dup 35 /theta1 put
dup 36 /pi1 put
dup 37 /rho1 put
dup 38 /sigma1 put
dup 39 /phi1 put
dup 40 /arrowlefttophalf put
dup 41 /arrowleftbothalf put
dup 42 /arrowrighttophalf put
dup 43 /arrowrightbothalf put
dup 44 /arrowhookleft put
dup 45 /arrowhookright put
dup 46 /triangleright put
dup 47 /triangleleft put
dup 48 /zerooldstyle put
dup 49 /oneoldstyle put
dup 50 /twooldstyle put
dup 51 /threeoldstyle put
dup 52 /fouroldstyle put
dup 53 /fiveoldstyle put
dup 54 /sixoldstyle put
dup 55 /sevenoldstyle put
dup 56 /eightoldstyle put
dup 57 /nineoldstyle put
dup 58 /period put
dup 59 /comma put
dup 60 /less put
dup 61 /slash put
dup 62 /greater put
dup 63 /star put
dup 64 /partialdiff put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /flat put
dup 92 /natural put
dup 93 /sharp put
dup 94 /slurbelow put
dup 95 /slurabove put
dup 96 /lscript put
dup 97 /a put
dup 98 /b put
dup 99 /c put
dup 100 /d put
dup 101 /e put
dup 102 /f put
dup 103 /g put
dup 104 /h put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 108 /l put
dup 109 /m put
dup 110 /n put
dup 111 /o put
dup 112 /p put
dup 113 /q put
dup 114 /r put
dup 115 /s put
dup 116 /t put
dup 117 /u put
dup 118 /v put
dup 119 /w put
dup 120 /x put
dup 121 /y put
dup 122 /z put
dup 123 /dotlessi put
dup 124 /dotlessj put
dup 125 /weierstrass put
dup 126 /vector put
dup 127 /tie put
dup 128 /psi put
dup 160 /space put
readonly def
/FontBBox{-30 -250 1026 750}readonly def
/UniqueID 5087386 def
currentdict end
currentfile eexec
80347982AB3942D930E069A70D0D48311D725E830D1C76FBA12E12486E989C9874C2B527F092
5722787027F44470D484262C360CDFDDDF3657533A57BB16F73048BFBBFCB73A650484015441
FDC837ADD94AC8FBD2022E3EC8F115D4B4BB7B7F15388F22CC6198EFE768BD9FCEB3446EE4A8
DC27D6CD152485384EF5F59381FFDA43F2D20C8FB08AA27AB2015B774DB10DACFDCD33E60F17
8C461553146AB427BDD7DA12534BA078AD3D780414930E72218B3075925CE1192F11FC8530FC
D5E3038E3A6A6DB2DCFBAE3B4653E7E02730314E02B54A1E296D2BEF8A79411D9225DAD7B4E6
D6F9CF0688B69BA21193BF1495807E7BCB09B7064E91FA0DED228E4209AAE407A7AACA60B107
6299AC4ABD23EF02F108765F0E3D91F92F3AFBFDED372FCF6E4B1416901517DA8F2FB3C9FE7A
87BCBE6FD36CD5B5823FDB74229036A63C3346A1093E6B1036902C1BF42FC317C80ABF04020A
47B344C36DE42F05C490A0FF44AB6D5249E9F552A8707BB7661E242644814001C8430EBD5E5F
0B944CEB666EE64359D663E355B2F17093A964139D17287F6CA6A024767EBA4FE4873855BABE
2F07B91560F68300B06DFE27264C163195D446980C35BCA0B48F7806626AE72636593A05BA40
3CE1C0F8B2CEA3ECD586E90AC17D034BA4AF708304F231313459FBBBFB97D4834D0395754AB3
F22D6495D2144087D448616FA1CE27BC50D346543287E3860D99B433624119BB9920A2113604
C0E260FD275BA55E0FD19C83E19ADDC3BAA1F32F6B7284038845CCEE71A3311DDB17B84975F7
A984BED7C6EC2A06E5B335A763D081C6273F86A46632FD9141A27902074FC860DF3A2EB59B89
774C767022DBB577E30DA128BD7706A43AF886D0C256B50FA968EF06776AAC0BA5387E9011EB
2334C1F42C090F06A1125C207EA6324E87F46414050D88004F564EA336A05016C7B7569E633F
7B7F1428C5CC47DA7C875218D4A1044E26A472B1FB52CE63ABF9B840B8F8BA45BCCFB65367C8
75DCBE1B0ADDEF3761E296DCDA097E86467463CB4B29CDC95ADA06A0476D0E5EF9EF7BC53AA5
3ACEC2BC5E00D557829294914BC7F823EC0729494005A45A1E1C68077EC42CBDA7E4097E07AB
30D8208B1DF2EBEE1E09D4EDC9035566A2B14689F0D5A5ADBA565896797AA61F06AAB496F2C0
B8CB2B37A35889DD87803AE6795B23AF56A8942EB93AD6F76EF05B3805BF383FF4575465A842
E8B4D5BCAE363EEACE407E5B5CE83B678A01249736ACEB146B9D4CB91B488251AB190026902B
DAC96696DCB3B3D7ED4E8445130F4A63CF52FFE8D10402CAB38CCE75B08488074EE90A09EADD
649D834E8019D6245D65C701571C3411079E05C2E424AC7385B659302DB5802D10F7CC8CD9F6
EB6BE8994D4FBBEBB2CD064BF655598A1AF5CD5388A0802D8432345A57ED2C2E95492E3C4F0A
6EE1C5D9CE849D734B572E8F1774A46336B100F563EAF84082231E6BF148AFA5945F8B51E70B
FB79E76A4BC5D2C152B1550C6CB6538011B31D5E979F30BB95D1A6146D6434565439388FE815
F560576B71D799F6DA1CD8A373A685278C5988DB3F0273B00248FFE450C14E2CC53A6BA589D9
50FD2E43BEEBE4E35838349CB201DD9498050267F593D748EF30C1AD484DB11539CB706F3C65
AFBE7778ED4470F51B026618A4A5FE1C7A9D93A5625226F4CF4DB4DF6BE1D1439003027A1CA5
DB1D288E109690E5EF1BB3D566F3C86302CE7501F09091AABDF84B8C78F71348F36170BE65FB
CF5161148D69EBC91D28CEE15A3B44AEC6BBC8E5D6CECB8F9A2DACD7B66804EFFF08343CD925
A50AED2EC2C58C72FE198A93DED89695C15573BB95E4797BE8945D5DF06D1E0690E1DECB104A
A9143111682831293FB6F9F781E9D540C5E7F25D463B7B211F3EA0642806A21EC62F52344D7D
8BB230477D85E39A4C63D2D2200716E419E3BC78482F9005A73C767797FB938F0FB985376468
0C984DCEFF25B10C08A5B355BFF4171B107270D868CC3578B7897B88D85115DF75D2661FC52E
C614DB064549F7E7B7E69C93F8DF410552D18939D5CF32962EFA787949BED083525AE62E2119
CDF12FD932F96E9D5D5FC96D51912D763974377B69785E84BF9600A6A946CA8848124CB5EF09
2D4BB72DCA67ADF52D637B806E1FB9477E4BCB24E4780035F8A72BFBB670CB93298167CE1B3F
3715CFBDED1546BA7F974898F03B786B6ACBC9326A85BB29604CEEFEABE9DFF2CE9CD8963B11
04480AF7887FB85E8944357A91BCD3824DA9F5370E8ADA17BE9CF36ECFB861950F9DE73D2902
C3FF5F8E1228E64F190F523248EBA6CF6290A278AB09F7E636012754089BD49AF82EDF9F32EE
43320D24E393658B4238AF64E42189A11EC12E42453A6270E6D70C84CD902289335F2E9ED046
06368B7FE951B1294A17202F6B1BF8857F4536A105D746247407D8E2EEC70C7EA5C6CDC721E2
90A8B8D528BEC8582C35D2A6E6D30994346B5EC2477C2D0D5B97603C8C3423744D5E0C50EA75
095594BB24B9E34C0EA2AE82D3DB11DDC45A77CEFE93C4AA6642A9C76E34F576EF71FD60F41F
3E074E74952BC576E558036EB9892E016D3F46DA3517F884B49C3D69D0C3649C98E41FB7C830
0B18A7148E98EA399809D8201CA9FDFAEDFC2129A232ECFA32D630477943DF448491EE685180
82B5D1537739D91DB3DBCA594915B4255A55352C60F305ADCD9437B029660B36F214B027504B
7C535F36DF74C5BD51E0D060CDE000BD38F60BC7E6CEBDC8C31A63062F7A39CA1CA177548156
0AB53EDEAF31AED9C151115129B93CBE9D6834DF0DAE514726C6D0E6F4F99498EDA5C4625D02
33235FC57436AC454D9B10A08789CE55E4D845927899388441AB73F8A94384AFE061C52B6688
6F1F72563338A4D04114E2F357D59B68359F04823A7BCC5575453CCBA28A9C522E883627F225
B1892DA9337C3EAF3CEBF2428E47B86766AA1EE2DF228DDDF2D1368C63D5C00971EC12ADC6FA
3B4EC682F0B007D533BD2903282EC15E7717B99F6284E76FA24619A042574FDD792128C65EC8
793DA8790E56D7D9E5B9CC1921F1043459BB9025CD882DDA610F7F558281C56AAF82FA978923
6795037F2C385E11B9167812B1DA3C7322E73955E26C292F17EAD971551008DDBA460144372E
01BEE2DCFF4BF4A24816EA4CA2FD9D903838A0CE42D8D5D6D49140CA8A33B1E9085CBE8529F5
AC8401C4E59D28318D80655BFF40A0E3F2ED31A4304B731246BFB7D44AFDA6C2890885596CD3
600FBCF96A95191E8C5C840F2FEBB2C9999CC0636FEE70281BA69FA70B08A92C7E1D2BBB5DC3
A9AE2A8FDF8CABB6B2C6A92DC2E6A7EB6C5AC4CB6292FEC3260208564A0CAA8F0DB1B2AA6B5C
FE7896EB3DFAB600CE834A60465BBA4CBF751FBB98DF440C587132294F6ED1E9E5503802BA9E
1107340F67AC3F37F3C097742E61E0BAA5F5020A4639ABC3B07D603EDF4CC7E80DD5675AFED9
B5DD4CCD35B299381FF7B38F413DA9CE41CFE08485BAC0993EFCD07FEA9E8C631EF2F249DBF7
36027109E752FB25E00DBEAA0C2014C2D8C87F4B3848BDB8AA593A6B6D55CB99D304EBFE2135
25BB3223F8366531386D7DB594683B2DAC4176929F6B39EC2EF57EF1C4E1CBA9736B73DCF25F
DA39C525A330B58BE920654012784958D8C0A5A43CA3AAE4ECE338DB19B2704E653A26842CFD
EE8A313475D33AFAF1270FD57B4EEFC9AC4F0BEC2CF23072E53814DBF8FAF283AA5C883DEB92
8B86E1A3206474D5C75D30F00D50A334E69292C6E0D385641D9FF891292D815A1D365F216FE5
F916842FB8E857E2627B09859D3203A6EBFB98B8E01ED264924B767CEBC5403ED88F382FC377
90842A8959ABECACBDE20B97846602D65050E198BE907BED14AF76A9131D9CB460C601CA387C
491531C23D166BF7200EBCD41ECC3FFCCE117C4EB1F05E1890645629C9767B83995458F7E14B
623933F466944752FAC277187C4FB209C879B5EB91698949AA1E343DFF3D7B96C388DA0E3013
A044E9D254A2691A5139B8FF7174E16822B76C39B250C28FDBAB74AF1A6A79E06EA996A4AB34
49EA126044B3C0880C40F4CBC7ADFB73CC5AB29E7D71B73F8C4D8D9243D6F0CBDCEBA54C4593
E48C600C3729953B2505D78177DD0C65DDFDD4BB7C6DCB2A973C99DB42513B334601BACB66D9
2D9F0CCBA5D566A42489E9461DDD246FD15C57F9836217CC8DECDD6A95E9CB0C66ACCDA835F1
2CA778BEC7C8B92417E0BDA48A04348229AB736DFE324B99996F80DDAC105A0F6DD69E330E9A
8DE1CD32FB3ADB7E0570111A0D08BC9475BBAB122097740B53A360A7DC2EBDD0CD94B37BF686
C84D1CE4F095B32E2EE46F85F44B6E3BB289401EE3BE0BBAD9A158D5B2B1D0645EDC72C8E4E9
B620A06788A0A9FBBBE63C76E857F37ACDA79D431C31D1698D8081F833412C0162BDFB90028D
B30E89265D8A654FF316DBE54A8F1CCA426DB4DDCBE99ED97EAE070BC24A203FEE3296C28AD3
C89B444B3893E882A3D929F283CE822311846042111BC2CD2697E2FD93E171443CD04461EDF9
352B2AB5657C19644AC6E66543618FFF3DE61EB932DA8992070B58D804E6BF94D316500F89F3
122ED3996611EBE903C415744BE5477A8C4117E4F600316847BA54F193743594357CD8481301
C8A88E6718F3E192E07E1368F5CE727C7FEA501C3AB79F83F88D87CAB2AED90F3AE9408F9253
85C033C10B349CC339C4961430F9CCD84441FAF97DF300E7B0693C98083EEAD17D0903FCFCD4
B461892CD7D0C8FD7DBD317DCD9C8349FBC3C70AF56FC189981F061078ADE979A7D8C96EC0D7
96BD51E6BF7F7624C61E78EB045E87E48908A3D2F5AB35386D28E1FE52DDFAD920304060EE8E
24421F5962A6F7FFF72A62C14CC3F4325D69BBB80F097B1B91D3578943D6A409BD3A0A72E1B9
4A1B9A42317CC2D4F55634D8EF89D2637DD6D005B5F4DD8B143C451B1D0682F850A53FC8356F
5B730E55E111D362F977081DFE2651D28799948454A363B626827A2679AB6C8783FB6019EB6A
B5D567729ADC1EC50E69D482DA0D90E087C5249BC7C6C1A7D5C1A16CA7E377C04BEC0DE8C408
08E0AA4CFE5724F650AAFEE416B7E0CE1F8520A03424A1629416CE7440A75A3928FA5A9A162B
E53E4E58C01B97F466C0B42F573E67164A89812FE3D0D7398AEE02A2592FB12B8E8E21A91EDD
30E04F0423700F27966D0202C330F2B92927992E5FE433FDEF2BA9B10EE22E1DA359DD3B0F51
85237F2301AA1AB07AFA4BB389DDB9D1202BC8AFBB1AAA1D8E837D66F0AA7F5DB85E6B959270
6D3A17F2EB9C4B96F4F3C4D891656CDB37A9AB8620533D09813A0F11F5DA5EBF19D271C5E9FE
337D648E2F957BC8F0C150916FDEBEAB4903B861A71695C571B407E639A015EAC61627468A9B
D5EAA936D207B24D8C4080BABA26787D70AAAFC39EF4FCF2EB8A933BE0BC303390B0C48F2B2F
9158EBAE3D3C97686ECB9B2783784E0637BE9682E8CB3C49042DEBAC265CFB046563DE793BA8
AD74AD18F915838B426FB64882E27263B200CBA65A4EFE9259C2D27A26FD55C2EFB45F7C3D29
EF476DC9CB5E196EAA9E7E85E3DF2976751D570E906C26FAD06C72C99ED9040340E17500DE0D
F396F22034E1197A79CFC44D7A7F96C87B074BA8B6DBBC50CFC6CB082D0A393A8E2BDD0C1601
62FE5A200C4173BA464AA3ED63777577F29FE8494371579B64DA3A4983776E9F65A0783C49C4
862EF6C708E0E4913445F696C2365F027923EC02CD6B6381628172D7A134A51A44C2E0129FA4
7BFD89B4856E7EE723C57EDC17C2CBEA3CBDFF6833610605FD4F60E5790ADE33F42793400C02
C30D08FCB2F83E17E2DFA084D0247336E9CECA9EA5E055CD1BD669BD1A6A722C2EA05E3A4687
442E5BD475D7DF4531C1D6A26B407B47FEB9A36892E935A54B037BCA887CE6A1DB38B63222A4
F32E493C992E9F41996B0B1BE3E1A11DB0B75F3E4A0B871C28ADA0BD428A83989EA05610BFF3
61E7B9A3C9A79DE59911668E55C35D5A88D17C4A451DECE10F713C63BAF65109D6AA75BAA84C
3B030D6648582DF7A447A6AD3B14C88A9C68EFDA278BBEC86E7722A436678528118B797E14C1
4FD39670D78D5E7AEA9EBBD7F11F7EC716C4805289A4DA73F6A8D9A9518171CFDA5078C62257
275E7D4994640A512D282358BCFA01BFB455F557FC4A7A14A0827FE76F0975830E2F80D1CA20
E02291C50606EB76E3F4ACF136148F2882EEF4C28EB2A7707D4C97739B10EB907B16B36B2F22
766DB7500E7A2BC413618009A45F3E3E9964C423564E632455D7D3CDBA22F4DCFB642CEF710D
D219ABCDE35F82BAB6120B244BB6DA19D8833620A30630F80F77BC8835424882E2C9FA2B6245
91B0C67C102CF79C513B350DBA95032572DA0AFD0B98615EBEA2B7F4FEAF4471E635651932A0
11586145B59E434F98A09E12FB1E6EBFEA29A4872FF8C6CDDF091938BBCC07AE13216AEA076D
9C4F9D22124EAD08D72ED2485B5AFCDDBBFFEA273675EECC236D14985668EC10E6FCEDCA91A7
0E2A2555E6531DF09BBC7F82A8CE0303B79B1273A67797AC9712692D3CD63789B1F295AE6241
2D5529D4C0B7904497B4D1507BBA5F4518264B49F9274FFEA226B736867FE02BCCCEFDE5F5BE
A6B7B700FF2F46F1714DBA94DC38FB553DE129ED55EE9B94C05D36F9E09DDD6D792FA46D06A7
3B0B2F2C5CAE527467A234BB72CE3E05F6769287304E1C7AB220719BBCACA7A27213688D0B3E
1C05817C1977A2B58C1EF598A088374DD8A4D56D24C908147CD66EC69C0B7CFDDD23E55374FA
1168B7247CB19DD94C5A31FCE4694C139CE9CCFDA56E2388D8CBF003889EADD4F053E1B3083A
7C68652368F38BBEF23896D1B122B2EE87F94F00AB22B3500875A3B24527E837A380D96BBD59
18564078262501F903480CFAEF224601F7A8143D9FC1D23AC1ED76E3CA4EA6E021BECBCC4169
EBE3050980E13B30449D1892DF47D0BBFDBF846436377D2AC575EE07FFEFE4FEA2A212C78CBD
C1F0B0CE6FDFFDDC3D31FE494DEB2A379C37F437669EC1F1EB272F81B982E2986CBCA0B2A965
AF5028863E0F0D9BA50D520C2CCB6E6844E64147CBE7F4FDEC6041BE659FEA0438652E4BB9D5
463388F19F3EBDE1EE1DA15344751A2B19E9B14DDEC1800702A9A0EF84FEBDD21E9DE5D6D50B
A14383C86B69179F9BBD8ADF1829B5DF8EB13B7D9061E3DC2D0F00639B92AF612A166ED1C6B9
2CC42FBB47FEA59CE5953ED34C87CF9AAFCF9EB955382EF6704F58092872515D63A4B2D65846
4A59842E23F47B3876E31A2B17BBC7350AE308859F652A3AB9A0ACB88F37B815B5E0DBFFB6A6
95DE8BBB6D5D5E9EA2A8741B1D561E4E4BAC2AD1C9CB69B36D2D24FBF18F399CC1919A6501CC
5DDCE91F57B8AB1F134EA3481CB22AE36BF4C0EF95A6AA439E1F9C23005B8401A7D790D11B26
1A9A456BE3D2CC5B0D701E39BA0A50185F10AE44D2F859777286104003EA3DCC87BFFEA2EC65
E09F07D71B3A18934628C217C2B14C34330666F47004C5FB57462D4BF238FDE95CAD89F6646A
6CE22BE01E8BA630CDDBE313A4DF6BB771D5352ED25364D81062766D695A7516C3B603F0EF9A
78D194CC4ED49BF9FAD1DBBEFCE69F56EB63910B79A80EF6D46358E7AFCA155830D28536E127
542F9C37D02F247346FC2E4812259383290E38D6C982A0649454AC7B396AE01A57C65D532139
E17D8D6B06C47713E58589515EC5F40DB47E00656DD76C13EC229F75ED7962F2D7B28E33FEDE
7CB67B8ABEDC4299C524165B3F28A3E1A6B922BD468FD1FF57C0983597307B16F763E421045E
61D8D5A2E67DFA7D84633F0DAD76C606D901BFC9D5A22601833984A24650F478B6DE1AC903C8
B45097627DE2CBA95CD0A2D0EC9D80274F1BE77272913405A47682531275FD509F64A9756ECF
CE1FEA7B1EB5B613D0A24143102DFD4EECE422F65A0239577E36245BD7EB1D3021B1258A397B
A61E94115C7FF86C336A9A9C8F44C54F0381E612D3C9D60336E733D120F482F9C05598FA8935
CF0D400375DA9F4B59ABF635AD86C5905A5B3DFCAA59B591C8B9AD92CFEC270D512F83904853
10FAE867952824A98312DD6BD642FF7D69A5038B4996D765AE7BAA71249815DD6D9223D696BE
AF2542BFDFDA1EC77A1FBE30B00B10D2F9D9A2EDCD9CCEDA4D2F0485D45D551356AD911D933C
18F607AA212BE08B92264443E5A93AEAA8DE39F8D683288A699AF5D256584D2CC3113B2AB808
229A9837F84B8C6E224ECB66D0DB565A8C4EE455F75EF3384702B3BB43FF12DC7DE5660ADB6D
5846E7F74833C990D84A8E32E4F4FC3E23556235599FB4E0CC2DA7E0383A3D6A1010FE79B4C5
9F44C16AA26C13B6CBB9AA878FDA8FE04130983DB97BC2424E974AFF12904EC88A6CF1BE342A
89EFAE736A720E89D2342B3AF0CA4250F945441292D9E02B4013C121E53F1553A173DC593D17
A96B97C4A20E83304AAE66475848C908FC713FA29D23EBF7B922ABB2B217F877FCB199999E6D
5D2A7462EFBA6A8FB5A1AA1829B2F1B99E75F17F768EC090CDAB200725FA84754201FD0A68D5
00D43BDFB3398917BE43B4477267BA6DC9AD5E78C3CD8ACFE51E60FC5BBCCE675765E28DD321
6668F93B192BAD3D53E2D0EB98D4F27DED7EE3713B2C96626D91F294282A156BD903F972FFC8
94406BC71D5DD265B69FE2C02F78302A5A21550159EFA31391D8E210121151E9745D5CA6D0D8
67AD8BFBCF9A9A40DA71C46B6EE6B1CFFE3C68778C96B760FEFC82652035B4818863FF131FC2
497B2DB1BA8BF7663800A9DFE8A1E3EEBFDE4913A1069E346ED5D55115C0E323F42647ACDAC6
83664DC38AD882DEEF01EB1B04D0086781EE9FE197C1AF0E6F6167F2B37BC84869FB82DF2E61
4694941DBAFEE1652013759A7F3C590FE845B564706B63D404B5D8945B0A01F9B88D3A20A98D
A3C926904C92B9EDE21B57B11F7143586BEE73499B1123BFF5F559E3CD42F52A75B887644A85
3BA45A6045CDEB5D74FC32A66FD90E4C30161DEA1FBF7DC808C23F79CE19CC86ED8416C61104
83753AEE1188FDA50D780F902D23E3BC0AAD486E722037EBAED8EA35FEB0D9833A5998AEB5C9
0E61FE020E6FDBC0277DEFEF3C65C6CAB5CD9B2B88695EE3D2C69E9CB61468E59D2F7B1BCBA9
AD278EB0F2A36F8934832AEF1F507300110B71E82F4EE7CFE3306AA856EE47081DAFCA1FDDDB
27A16163E2B6000F54384636B807FBFDA3F70D0D8CD5BB6562361D132D1FEFCD781676E2A9FA
1E9C7BD18BEFA58A58574BABC67F4F0F6F86A7382CE998E02A64295EAB48A337FB8362E99394
93519DB11D41D4111DF41D683409DB1D981E903978F6465BF764121755DABEBCCF611DEE804E
3915B9810BCFD2377C26E19219B5E09DFC9F1A7B9C27D823B10F8F3024C405DA5CA6F06492A3
3544EE6E0090BC2F927F4B806019AD45B2D47CDBCE950C70BA3815BD5C4DEB594C71E4BEA659
DF6F0CA4C78BBCE6658960ABB11E7FA292BB05FE91EA037BF05BF3F0F79E4FF2691C5FE9F650
4B4D2DBC49ABA76BB332FBC667148EF3FB1014930C20FA3A55C08F073A188544BB87449359E7
52576993DB1EAB25F28813A9FC81792149609DEBFC3BBA4349BC1870D44E448BDE003DFF9F84
E275334E52C91366004D9605A9D0DE343D1D78A1B0B83549ED232ADA43AD4FC7D4DB01CDDD34
6B5D75E837FE444D814C230C90FE6EDD5CE3F98DBB365F1789EF9CFC0BF0BDBFAD6FE5F86823
1DAD2C9403728D103BD2DCBC02C9246EF14BCDE6A7C849F2E5AA5D7E529FA7E32CA5B28B2844
A93F2884FC8D5FE905981F450C83A53803C8928F870B4FB9FF402118227E8C5CB952394388E9
72302A1DA49D0D2C300AC8F589536E7A0115F1FFD413A243BCEE6854497B2A26B8A255176ACB
44A7A98B6A87BA69C1597CD19C60296EE8827076A004775D069976EDA3C4AE5413DF3DA3A427
48F6EED802B0C93BA98E4CB1647036DF08DD49637E11486030E2FEE2DD40C6B79E08960BB051
65B9EA12B72E5DC6D94B0288F549599BF1C0BC63E7E0CB39AD5A0ED6F5BFFCEC932A05884165
3B7C4AE87D72FCD622C35C44C49FC754438217FBAAA60BC16FC9E057025565AF67F9EAF50849
3F72A3DBF323D1D7A6DE8AAA1AEE726BA3800A46A4198805F943035C7FBAFFA2D09790D174F4
768054E2205045E4520F1E3758EAA353F833F82884761DB2506C24EC933811401AFC75620FA1
38207A2B9371D4EEB5B1A6BDE6423A83447A850208FE54F05BF2D2435C20A33DF95703B9FC35
E5AF43EB316AB76E4ED54427F3812019D707214CE633E0CE1419555CD1BDCF87F65DE2F6F443
86533D626AFC4406881852D075F2D227C83B397BBD7CD7103B5FE9C08CAB1CA45FD07D8BACA5
137B8C287B3BB0E607FDAAB753D204F408D8BED693F99D4E778F813DFCC269F84B0A47B1E598
606FD58914E15826D51B01094A3560AE82E993DAB6B6CFECBC0A6989860ECE90897F3507261E
B39F4201050F0A35E4F1AD7C97D1193BD944AC797A8C70EDAFD7F4FD035A03C1159CCC94B93B
ACAE57FFAD2D83DE3ED3BA231805E321137725912992F870C7ADE3764AFDCB60EA19A4D9387E
D2C45D76A4335BBA8BD87AE5C4D331EF3D6EE98598C3BCCF259886CC13064C3AA17BD63A3597
547FCCDE53D8E1A005CBF93CBF31E77D053605DD182E53EFF89E7C16CA0B9CF7ABCA930E4D33
CA0E1E72FDB295FD586CAB13794B30A334E4F8F844CD632882F5F6107C45296556029C0DC3A7
395BA482AC29CF12EADCB7BBDBA81474E0D553570A0CB6D98E618ABA2EF560B0FF8F393669F0
48C473F39A2168015D74E77D502AB53434632986CEE6DB3F375B267871D7CB01BB51A34CF66C
C32A3817E71E4C392C07BE9264B3B1085D8C1A63C3CF73CEEFE24A4DDED7F5867F79B0A95C76
91B7423B172CB5BA803FB5E407DFB9D5C736E604BCD86F9D9E74544A16831FD4846ED13AC8A2
FA34995A9ED4215C59CA4D2A9AEC17B3BA91CF85978EA1255A24E40FD48DE57EF46A368BEE26
574EDA1600B8EF817948C206F6F10BB2F4DD2E5DEEDAB1914D3F56EFC16CA9E19615D40239C9
79CA2C99BFA3711A9849D6303E7116D96C2F2E760019000737A8E26B8E48430210FE7A2B08D1
98A7D6EA21DB6DD184B9B8EF2133598BDB5311D7F904934AFACEB63E7BB89D9527922963FFA3
2D87FA6B652BE94953DE83FBA87FFC013794C55890947BFC8D6B5911D4CB3F90EC0F9739C098
A5C5B63731F2A97C921680248E4706584906733E91BF8DBDD6D3AFA269BF7A4C915ED8295966
87F8C1847A00A7A5E9C94ED168289A835A8A318A29E988AEB62773DD2CABB9C2340EA4B191D2
D8CE2DF301329AC6FC0D822AF0004761D695D1A94C8F2C9137D58BE9D79FB5F2F9120173AF4F
1312C31C9A18137145F35ABE045ABB69460F2CD8402D7022C1AC112735DF89AFD79A399EB7BE
25AAC7049BC76F3DF3EA82A671701AD2BDAE4B93DDDD8516D71E3A2201AD80767EC7642BD83F
FE59F12CE9E9725D2F16A19514CF3C37E55D4F1B55D704100F44A7DCBB150985C0B41C5978D8
61362D0CAE67D93852E7723CE2054CB35C8E8527B66583F5E66085D2549AD623DAA57EE4F87C
D91166A62B7ACDC9756FAD46FEEA9DE7B9F1AA264B370931F0FCDBC0A01EE30751D35B1C9B48
0D75B50F2D770CD53E95B33021BFB741C0F9989623B2DC26D25130276C7273595C51D45CB2A5
88F8082FB71EAAAB2B0F4E4F109D04174F908EEB4E7514937CE4D15452E34CC1482FD01E9D76
F48E38A106666C2C4C8EFA44F2DA41EB072328AD35E76841E9462B3FF981072D3624D128BA02
E31E107E639FFFF66D0946941FBB8D352CE607CD22F3F47AB7D9D47E23591EB9B646431A97E0
57ED7110B0B871723C82C72385F31EE576B2607BE8E6BD76C498EFC0F915352A7E983B895463
1D80825E45B1B424003897885EA225822041CA50DDE48FE4D056F55E42F5553D451434654B52
E764E05AADA718D27EE62A9690B99D34F33A3F41A68BF89057D3F0EEC777EB18B772A30E9302
9BCE79A229F14DFF1E9B5536090DA9514F6FEAD6F6577A91A3EEB21C1B007146ABF97DA8A354
39D02191CCBC44F74256785A7E43BDF1AAB080ABA8A6EFCDA47311F8586B57560DDB45F37129
16B31E7D34AEA7BBB7080C7CFCAC0CA7C87C0A86B8E058885487D4799681F1E214C36CD0ED7F
7F0B5D22A4AA5F484764A4B3927E2DBA79E5B841522A6448959A811FAEF38172D5B7656C8CD7
5BB415870DAE6E39DDBD1D23541725E0FCCB9846ABBAE3D9522C812B83AC18ADFE7A823734BB
BE7D225392A114AC57AC4E00C2F2F0D8D765FE59ED70A28E73DAF9DD689FCD17BFE3F966DCC0
F5344C13E59530A0265ACA05D35B0422BB7C2899BFBF119A0A88FFC02F9678B756E13D4581D2
83F6184085BF1C747A7104DC485FAE721315A0610B9FA9C60C7C251AE88BBB1CB92A47348CC6
1949B8E8F8E4BC40AE27CFCDA32B5018B8F40877172E8671589E01D315242C172AA36DC33B72
F75DE90E7474E258A08A28A9BD19443E046403A6FBAC095BE1BCC39DB87BAFF7E691B6AF2FE9
3230A79A143092FA422D33DA2140A77401B36755C36184BE3FCBB0BFB64A77D484C074F60BD8
5C559C11ADE1C640691140E9456149CFB924E56AD3D66435DA8A8117C69F695883AB4CFF1F81
AA03595492FB2258CF6AEA9E03923E66B3541EAF48837AD6BEA9C87E3E2C0E595F8E49C7D13E
C3E1905264F30801417237B595A590D1C2558F29723E3B36F8D2AB4E2D20CF3219EFD724A535
2EA36EE67CBDCAEF7D46B01B64A4300D955223C2B33FC50D9644AE6B237BA265FAB4DBA097C4
FEF74EC1D8BB521C51EE63FAF679D8F372D94C1F3093910B58B7B3C5A93B40A15DFABEFC734E
E926458C5E73EC989D935EB849CE575D5A17ABBEEA8FD7B3D49F4C83DB8844FEEC2C5C60682E
B6031570381806F2A414419B843C4E0B75CB28C491F8B60FB5B8644C1AD42D5ACCEA0147DBF3
B1E150C46FB7B95F94C514046FE4956601DA026A52DDFA6D0113F573949FCD4F62B7A675B854
8458B7AFBDEC22E26B8F155A5A9C31730B382846B77622AF2D4EAE72D6ECB385625F3AEEC3CC
64E1B66AEB9B1746AD7330FCE8B307E864D19230F657C27F75CDB7812F0FD5E78A8A6F9CDC2B
AB26EECF2D3340F9DF33A34A7B32A7A8E907DCCA44850E15F1660EE31C04A988D687146E86CB
3A4B844345B54B72B4D062DD563E6E22BA5FDE9281F92713086EF3D1AF48D1BEBFB7B42FE26C
6E24F30F799F28EBBC30CD85C4B3CBF12FE829F003477EAEC472062B3338503D4327B11C05C7
A8AC2834FDC1380E10DE3F424C2058546552089B1907BF835381D2B8A2927AFA677559B14BCC
F4C568A7BA7814B67DC37A42596CBBADEB56C2DA7EDFCDF638FE426416F0689589DB462C6A5D
7E91CBA44238DC81634642BA73E243B713F7FD77016EB939C04D9CACED02B29114758ECA032C
D1D30A641843A9B06DE72EEFE1368896E58732BF5B2716197D53C1DA1DAE6EC8E95BE8781E3F
BD1DA59CAB4AF93852203AA9C93F86AAF64733AC3532CDCE6DD76F3C463BAF5DDBBD0B81D344
5CDD95A41F605B1AF09F6444A4B67E964C2B1C7E3D4527B6A85011829CEDB1011B66308229AA
A48654E1692CD5FBD96420A5A0A54CF5DBEB71F17F9B33E5AB1EBD059E1BD9FCD3BA4E4CD30A
C39531441869A8589960CBECCA2171AA7BD97F273514C02F3D765434A7076D37EFD76854B253
5AF55012BA722BF89BBC6CBF848FE74E61E712EB03CB935191121C7F45797788A01A97FE857E
5773ED8A59D53EB491ED7CB9C8F08A44B03C0F828DA18EA302B59E821A2769C0C75FD1A1E3E1
FDF244BDD85D64E43B9779B81C4478271FAB8AB12F9756B0BE42D5DA8E4F9723380458E873E5
8EDF603A17816277136D8695A68D7314F3E53FE156C8D3A4F28DB1812445E67F893832498673
BA67D28F09B4EBA6959A993EDA798FE05E46A3BA00C1A00F18C2683047EFD4255C5F2258733C
400E8E2008F43AA140078662117B806F6A168B142757176AACFFC982EB36463FCB102E67276D
8DB5F3A61D62D732D7EE339EA973E4448C25C88EC0FD166B9BDA5E18B9F489C85B246947E983
095ED7D30E2E8991E173BA6B0482DED2FBB7594CEEB54140E58C34A579F3CCC46A2653199604
A6EEDBFD6E9CDF78D8441C12F8722F10974ECBEC054509ED994BD0D6B0B3E3A0AE7418EEB9B0
13C99F32F9DD20F08C58290FE67F6CD333D5F53CA6133FB594B51A297DF560BCBA323FA14523
8CB47DDDE7745D419A6F42953044132978A241D8B1B548C5ECA5D1681A4A109466845BF9C130
500592DEFF93918E93F4962354731BA9A2E537B6069C1054776F20D786078FFD8E7F0A7558EE
D62E1C92196E80C301FADF8610D09D83EF79F5DF6B0C7E5429D0ADE1C609FF1AC8DEDEF00EA7
FBC9D4DB5C57313BA9F9E1074E76A6AC0C0BD5CD7B423EB4A1E4895F5BB5C139E03B4D8E5B4A
3BE9C98613891BFC0369863AF0B7A3F16C2730FB4380F6DE7EBFACF42EA816A976C72006694C
AF0CFCBC3619E3488F4D8A930A195C891423E1620F8CECC40494E77769C70EFFB696F3439E96
F0A7F9908402BB1D4A79E9432013F5A5954520869ABFB679606DA06969A4F995D0043E927801
5991D1BA7691B44F2E42ABAD1BC6091AC67BD4A575289F76AAE24C910481392AC2081865D0AA
81A737DFCC31E11F15AE2DA3F65BBAEB8365AAC2166FD30A5AED6F58604C084B7259B932994B
85F4C43D07B8B51B97752990D04EBD4C4E43B7880ADC4158FD8E27231B26AF71C5D337803F47
7C8F45FDFEDD5DFCA4BC02C4AA0CCE461F1C889BDA97771CC1F0AE8DA165D5F1244D364C9A92
D6F509FBBBDA28A2FE9596A175C1017323915D753CBF4B0F916C16D28864DD8A8241991CAA5B
231F8BEFE7D1FE1332D4BB3CD66790CDD66B0B8DBE8D7CCDB8FEBCBD3446E4AE4BCA759D8D69
64457C5EB9136911A80022E96DD20CE7B8028215D79B831DFDA6F65537246F56AC19E9E3AFD4
E526B59E48E51F3E9E64BD3079CD3BA7AD0018D4B6C8DF2F00319312452209947188D575EE41
6D8F7E4B1D4ABB75D5F4CCB141624B12007D415C4D18B6A673E194DECB2BF1DFEC5A4F5CC1E9
FC6B179A37B239FAAF9A71CEECC5C57532CF57181C1E7F375B4E18EDFEEAAAE5EA1E2D9CBF26
D789048EB0E8A9AECAC59DE58258ADAAEC756850C12415196DBB828D7DD9F3A906FFC52DEB8D
3B23DE786F024BD9C40F9C58BF9D6C669F43E4A9078951D4BCDDB2CF7BAD6A2BCCA47B215846
35ECBEFA51B7A261935D17D6EBB454B48FECE0F3EA3A8FFCFB757D180781471F24DC80FB2992
51BF6D0E41E1AEDE304943A89803736485FF808D98937A1FAB46AD17EFE94848365C0BCECBB3
E1BAB1287E537BD166C0DCDFEE7B509A364FEB6BB3A3BA748281CB949653C676071B54690FC9
1390AC12CEDF2B9603FC1EA902CD89ECDBD57AE164FC341DFC38F3964F15B63A5E8B666E1803
8D6B93B7C24E65C82C9CC2A253EB9F975CFC227B6DCA80D77A473BCB812191A826B699FA28A4
CB6758CB385D88542B64F26C01E2727D9660DC37C7A44ADBDCA9F1B0C8C76E508A87659ECEDD
4CABED3C1DF20ED033B119DA1A91606FF725D4D73A38A8C0B44B4CC53C6A70794C22D63D7DED
FEC693F4374766303C29128722CF195AAB86BE58A9BEF7495692FB6BC528882F63AE9FE3A153
F23CE5F4CF0A371C102F2E980391E504837671AC7857D1AD505C29B60CB2D88A833F542FE607
363E3125DEBA2088D697D9961B1488A22404D73049B19D90A697CE02BAF3BD2C0077A71B15C9
6D5FA22C815DC4C25978F3873BE805F69D9D1C2B337CAC808BB1F8C32AB5085BD4959852F9F5
7C0EA3C5E989FC483AF14F6E39354247548A09AA32D9BFDD9D9FB6DEC42242217DD73B4108C9
D47B6D27544D3DC92E00DC5FCFFBF829466345160FB29129FB395D8EC590E0655A89C2ADD203
4EA01AAEC90CBCA8038D2CA8B4C5F4247C918379C00C7F99620B00F54290D677CD8793ED6F2F
B82255E970B14BF704C3EA59310E5483BA3564830CF7F4E70CE28763F78801FA8A18AE7A83D4
9EF16EA6206AD611919F285EA4E14F223C4F40E1BAF0538980DE9D68C65E0A226E39511EF690
61497F9805E1CCBED59AA1124FAFA8EE3DFD4FBF5F8DCB718B4AF88E1627E80D9EEDA5A8031B
EAB89F28EECBDDDE0A85E1734EBA378C701E7AB5D802023C5A32854FD70F503A75C40650F44B
277AD2185149CAEB51C3AD04D50BA03885D07709399147ACBE525A38925E3878366C935D9482
A635211E3C7296B96AA447485767FDB35852D786826D3EBB9BE7BAF76A50F3CF220019A3D5A3
5E0B54EAC1CF3876EFDDE1E218E4234016B2DBB1A70E521E9A32CA3B3DDED1AF16A673716B22
4DADDE391C484F43B9DE6B96CBA03F03BC9A52CB2B9F56277C76A5ED5170D4895086C04B4BBE
97CE4EF93F599B3AF0E8FFBB1EBA45A07F752FA2AE997A3D9A57664B7668141CC8213ED2F7B5
F04D119C34FB2FADB40953DD4BA0936C2241443F6D353C7D64F723FAC645A189B789F8B18CBC
7D4C5382423B894D08AF70298883EDA6A309251C17B67F7CC5D83A44F410A948FEA3DB610547
AF8A28D4CD1D8E7A42BBBA7FD4610C372D1B2943ADC83E4E2C8A9BE8D5E1CF3B30137E7D38A2
A74614CA4E2CD7DEED7AA9BF2351C4465CD0CC2F78DED6C84EE4D71F0EC53CA9B0515FE66375
717E9AEDB2C49F19578566E4C3C95DA95E18BE73055EDF508DCF5B6A1FB414AFA486E7C4CFE8
5DDD518B068F27ED99ECC2D690626F04A4E1A7A33AE5763955991A023B78EB2ECA41C6945245
A48D40399AC799C8A8992EF69FE705AF9D1069A720EBE65DFDE46E1E8C599C7558FA6DCA4CFC
EB620AD7F044DDB6E4437DE358DE669AAF3873B83DF068D187332735E3870BB95941D41CEEAC
1972DD0E11B08CE89CB0704F64E6015265DF13AF8B43620A53D84893E9DD25F71F4380191942
A3DFB0467835CC29A8B8C04D65BDFE9BA239BF469A3646A014E76B0D7B6AD3BB8EB80D7EF276
BE0D8F812D3A617C920BA7FA9D0CFD1C81E4ABE831638CDD28A065331008F3C85FAAFFF57737
D091503BF4C2932F6D40B3140312FE780DCB46A8871DD8414E5D54BB4E7C781B3BE1C35B54B3
B12A2156B29CC5CAFEE3BF0198B2407664676410401918505BDD29B6D369D98FF18A26C78CAD
9C6ED94F67DABB68ABB938FFA462B694070FD96627D0ADA7DC0748332ECD424FB258991CC8F0
698DE2D8D21DBA777A8E4A63C4C6FE680E42D99678D0314E5A2BE541AB96059C194CAAC8C526
3AB3F586E4B9D27C00AF372940C71F7B6F28366F04F0BB4195F1FC96A5D37CA226EE2E1815AF
E24D238FA664DADC051790C3718F7B1E2CAC29413729ED3B3486B1250FB837EB2383D7205E42
249BA65165812181BECC4B6BFF113098E507B2E0E163605ED91FD4298728512EF81A91E2D31C
17EE6FB7A38E6DE02601572BEBA27ECA7DB2561CB555D0299505980EE1BA0ACB2CD0F549A253
C0042B0ABFE55D8FFFCA5473E169995C76CCA4D78802932A1F56B0EEC11FB04C65F350C1A1D8
7207D43F173FE0F3224AA99BC75564D72C8EF325F37133EF2D989F6A93340ADEC5EDA5D7438C
2FE1885C69B01463B3EDD534871C0760DFCA487A2A8AAF24FAA9744B273BAAC1FA8283601964
75F67B7F91C1D78C58FA0A60F07B69F57CCC0EB097C7F533AD5A9D962DF80AB3A54EBA2B5444
5F7A70D2DAAF9110165A52D5777D20B4FEFA3F686558F146BEB33A4F5623407028A3E5E6F9A4
FCBA726423EAE9362EDF2C3F5292C0F2B795BFF8B2F94E52E7F110B805875A32CED3A5F572F8
92FD981036A6FD652914D776FCA43C7799532794346D19A452B935B8B06B1380E1203A64FE53
ED7744C2A6A863376A67204A29922868B3B2E3CFF62F72C22A60D2ECF4F8714260BB106454D3
86404F3CDC03BB4DC0F0ABA36440BCC98CE2F5617E38519EEF3C9B2C430A1F8AC9DDE867EE66
B2ECC80B3B73288490825C6CA91637A6FF06DCFCB31434309A55D62F1A030DA9BB75494E2669
F9DF957BEDE2296AB61EB70F3191E9315A6A6832D271C4867BF19AC92E262A32CB690159B237
989BD66C205601F106BE4DFE3687318FFFA635FB8C540B439A939C96647497E49E7CE8F05492
CE6D3DC037A7420D37905F59035940D212F43983E14624E4BFC180F247F42727FCBB199D067C
0C9E1E9EDAB62FB5F94922A0BADFD7A83FAC18E62DA9AA6EB5AAFC890EDC9DB8B0115CDCDF4F
AB34BA416524AFE52055987BC6C4B0412346FD34FF47CFB7FDCAFDD834CC20D60E6D9749E051
6D466D48C02FB8000186D057D06800461DE8847A1E91C54CAC011B8BEC1F6E6EF93B78A3B6B1
CB6161869A66E3C79F7D640BA2A3F9EA1C177E4CE9F06AC82F8044DC37407C9876F3171A9A4B
0FC412481B119E07D299C39040299F921DA197C7EFC2E950C1E01CBBA30AB7E85CA275F0AB6B
601E7CA2FEBA664388F2F621F7934F1F8E1461B8C62290EAD4F240B77BA8DBD4705A6A0D5EF6
A7A2006950BEA0EE3AE5935D685D13D752CB9E90593A09B285F3D05E9B1A2CE7DAC25E800EC7
5EABF0F3D0B18758B01B6E7766DFA8A2ACB7CA64EFF9B42CF7FF05C7699A4C2A21870C24154F
DBB17569DCCB80A46F49E9AA0A3CADD76B8B91FC1ED92BAF2B2731B1B6EEC11A3E4C25AEFF80
420B6563220ACF67E9300338CE73EC10691ED248A0BF68C542D8F0A10E4A7FE8D0F87F837385
A01B8ECB255778EBEEEA80F5EC231AD83EAE0B42DD2DDDBECE2EADBBB23BCE762F6046162BFF
2B31AD5706ED0AFC0CFBF544E5BA6A3AEC0E1B1A3A3DD8EC92438FA7B66E2F636276325317F8
D07461E29702FA530B9D872884A59770E91C3648727C48C014DC6ACF5CAF29C8C51458E48D75
B11FDE9442737CC49022E9C480B374D73AD2BB80D2E0DA1D27B523AB400D3E71E128FB2767B2
AFD6CC169B431E7EEF34F531E133275509E0B26E86BE9D352E953D677843CC691948F72A6DF8
DA2A86ACB3056CA1687944DF70D56A6851C48B97769A23786FD2238F20C40214AEBDB28FC280
E21464B562DEBFAD67C19FE6453B5C68B46E6E30E584BE3D14B52F929EFB458A3EEF2CE19F9B
46EEEFFC431DBA2C2439B76F50FC06FC78721430E0D5396081DE648772E33BADD4F610A69D0B
C1C668EBBAF72F8EA0BD00026345F4FDC968E5875EB432E55FC577A4B7BA63EC22F29CF3F769
DDF52BFCC25773274E73278BB043B9E455493F061714483BE31DB24742FF79A16D3EDD938810
9174CAAD33734080C68F07CCC9C6D02A25FB2BE71DF035B2C34233E29DF1C2B662879FAFA519
9D1213904AA0D636517495FF44C668631C963C573A62A655D8885E7C204C50633E753B22A507
9408624EE8E5CD8AA7233FB1C0B7A9F5815B0FC4DA9690DEBF4B62B4A8C8D3B1A73F7900A197
9CFF959D1458FB70330784F7CE6C89C1BF7A2E3A526B2BB0CF629070587E923437C8AD6B2087
023B053E550B96F4E4CFEBA86228D4758C3D92AD83B92BFF979B6500A1A9790A43AEB39F8929
26ADA055A2A606F623A9DAB347C8C40EFC651C641F0BF8C3909F1FD57AF97683926251E5D1BE
9ACF6DB22CC8CB3C64411B3D4AE2A238041094F0F6E57CBD019E5F6B570CA3BB75EDA7F1B7F1
5167EA330C6408986712E5FC2250F337531020CFFBDC9AE8068EADC5DE84C58A836AEBA5B72F
E723C6080963FB68A7C35A9F74D49CC0FFB493C372D2C2EB8369A16F6105B0CC6D583FB16AED
9A549242FED2E1A05C9A0805072D30090BC73D0118AC4060B4521B203735A1322F188496C731
3B695B76DAB8A9B367EDA4AA9EEEB88C2A70A32077DBF3558A3C17D9AD2E16027C6CFF034C9D
0D3C5C79B51A58F292C5491B920B52C20E52503A648089FA45881CD62C2C879257BCB3A0D641
6C90C7FB68E3A09966EE72EFE495370FFD97027367190A4652FF3E5C0BC13CFCD9CDA202EFD5
3AB998FD8C43444B4A9076B1D6AEEA18AE71DE2CA91FC127ABA54FB425C2884C085CF4E200C9
F71E971B6647889296F13E3AA3BECE4CC5E961D26E6119E653C82D42F4E2C236A945605C1707
F898908C2EA375F3A9679572145A46D042B993BA5EA446D643EAA1951A0F3612F356FEF1900E
F5F5D6403F8026DBAE83C3954861712A65D1FA16DC6CADA9768017F9F3ECF2E3E2D8A7627CB6
CE22AACDBBF63C1B9E46E9A3E89099AD74AD15FD9E1A877C492E53D78B087C7665A61DE06CA9
3523B2A1187C67627A672B5D912D6CD0ABB9957030023844481E0D2C5BBA533FB353A38154E8
6D946CCECAC4196DD1B5B92BF12A2C300D1BF5720605E2699135EA920DC598817A17469E06A2
2E83963E63BC14E73F44DD19206CF5993F9C4C843445591736FFBADA86DDCD378231FC0299C3
3507750B7E72B4C704721FEFFBA0DA4B0C4BB998E747B12555C4FC2B023FBE7BC88441711217
D0667A54F6313D5384403F1E7FDAEDC6E124ED95A4CBAA5596B0F83B933D9EAE4BE1F16D6017
02477D3D37149BE811C05255FA058535C7D3C30943556EF80F701C8BDAFCDCEF9E520F94A2F9
2E4220C302B9D73090D3C0C76EF28BA3ADC22A409AF12BB9CF3BCA5240CA3D0E01DCFC9C0077
78CD0C08AB2D980910D8FD8D9B6135AECB85E7E3D9DFF94CA9D35FDE86FDF4324B64C8DCFC26
C45C3FD1821951D1F718196A6F04D3453C04BA54DA87A3372C916A062DB9367B2230A6078387
8D0A6500E0F970BD635B271D593F5CA3062DFECA8D84C6C3484D6C81C328058125E7A1E6ECF0
65D23D6DD253AF681F9F65EA166D0081E9E246977EDD32343B709ADC09E59F4D7679010618A8
7D2E57B588A8F7A2B9CBC564116E89C5D4665992039B1058B0BF6C6CF242D0BCC114E00272DE
5102DAC8818C2AC9395AE5A2D5EB6B5475330B512A867AB70F5E4DBA6377BE976F8D871C597C
D686AE04F8915F5F80BFD24350C5AD541E7CF5DD63487CA0774C7FC32CDB31D0AA04600267C0
D04B36A37EEF5191CB3BF7F9522880C29C6F3EAF0367D755AF1C225E5E9F50F92538B2FD1DD9
890813676800BA9D5C8D0E70B12E37E12D7F29BEBD4F064746E35C4CE9F7D1561A4B8C06CDA6
D2E9B54ED377D9E0A6221CC68A9DBF62F39330CA8733FB17D13C091C15BFDEC842957E797B4E
75CB7854EDD3828685CF9E07DB73BBF90218E81B1D762FAFC02B8321B1FDF13B9BF7CF0D271E
974DB4CE5C4A4C62920DCFAFA4F94E39989E95BE3099529024F56586810D15E3A87FBE974B40
B2A3745869B05EE5DCCC67B609DCFECC5BE2CF76B0EA694AD9A96059545628497EBD8912B3C4
7EF28D8B6B416B4CEDF00363B7EBA4162FCB83D374507B12BBE968139E81D573DC13F231F09D
88105E74DF38D8D554D8582534DD2DB85CC9A9DCDF50F22CB355826DEE570808F83D0EB4E12E
2A852591D2DC7AD3FD27CFC9F07E62CE81D1822ADEE41E079D50B56E4833E440E81D834F8911
D0A280FC151FF2C4DB4712B02E21BD8367E235E6E7068DCCC01107BE26779B29EAC37C4CF88A
ED153AF4B49DFA66AA329FADEB5616AA95C088C67E8B036472234454499F6B501017CC7C93BF
5DE2B77C10DC1A71AF3A87B5621CD3B4B8B1ED8B0795B4AB99DB0D27EC028FFE4A3028928646
7512D7484970754C3704C4F257855A61909FD4CB7332E4AD6DFCF9A974D90B97881F4E70E123
CF1E667671E84AFC65BD589F2A1AF684DDA0170CC1FD0F5516D1473A108B99278E809CBD4298
0451F32EB59E50733B28A8A4E041BD3737FCD25F4DD714CA4C2DB68779F98BEA34C3FDE2306F
21DE98FFA7A1527FA7617C0686C80538E4AC46BCE0B3E7D8729A0B8857E013D1505B2A55D035
218760542026294442952C03665CAB32CB9322D6C79CD4FCDD6D31730BDE2975BE9D2783A4FC
D3F2C6DBF54A826C909B40348640BB25EDE171ECE465C1D7B6C6D17C2DAB439EFE8CAFFAB89B
89F8F53066F767EE18255E5774F88B154A43A968073FD1FB64AAC49518160C0B05B2262D2C99
8E2CA2CEB4A294C50F943E853183304B358049AF56574CB2FBE28B0AC1E8DD780C913745A56F
448B355180389A0A9A62F626DB7D38C8A539699919CE67399B1BFC15DF29D2D8AA50E0D44644
41E92B842C366BEFACDA602B4B759DBF677EFD370FCBD578C52073D18219515D624C2C63D4AC
C9F73966FFD4C8B3475823A0C3B97D583AD5CF4DBD4AEE999CA42D537F85F65DA7B0D876B563
6A2A4D13D77455E822DB8F88743389648277E646849723C550189AD6CF2FF4533E4D33114582
CD51BC59D174E65142FF14FEBE70D5518A00491AB48B748AC0AE6936F4553C20EE2F6D209C88
74AB668C7033F1E1C8254250E3B4DF1EDCF3EC7B6D075F8C70A8B72F948390F72AD35AD08A61
BD812BDCCF2491120D4D965B537FBC6B99D050CC8B1DAD9677D08884097DB2271FD2CC8774A5
FE286A409D820DBB2010898933E8DC863822B0E0F3FDB6DE8FFFAC023D82CCB0C6DB6F0780A2
A8C9846559B12606316BEFA9674B5EF246550352C088051E01C9A5953573972757854B61D258
625396EE7C66BE55332E103F9BF2A02F5777CD2A1EA82E948BD4FD34F1C43379702BA518D13B
96D99368F0224512183237C8F32421001C5C7AD10E1EC8DD90533CC3A4FFCF5CC373A0595916
69CFD6BBFA2C7C2BE12373FE97617EF2D998C5F79A45C1BBA4CFBB7D57934AD9208D5A194DD6
0A66AA202413A873AB0D4DF9166D4C359635C3B928628D7EA3F528BFBB36053E91A38C3B6CBA
8E3C9A2694AA59DDE6809FF9B67FC851C18569772240555B88F76F88D4569A7027AFF1880FF9
2F9E66EE8F6557E839B84B80066A6621F218A09598B6163AACF18E94C557A5AF84BE82E607E0
472B37F9AF5EB036EC0F2E9CED8F54112C68B2F35A10DA0A1A19F5B987C32D296F1110283E63
A40035125F4671759449E1D7707C494A3302D24B0D0341D4B93071B800310D260988D9D12E4A
E4B30C311012485F95C1C96F2204520FF5E60692B32770CA9F6506C27AA832E5A52E2B431D52
698DFD007260E81109B773CC3D32A30304B88983ACE94087C3ECCFB850F47545E3663CD7D26D
53E16C7F7461BAADC34C78352B493E213C63C86928E7CE586F1BE4F970BAC01A2B76B2CDBFFF
5179F1D660A1867944F5413808411926D4F177AE46C5AB5486C75159B7222C70F5237417792D
685F69828FEAC8970974EA5638D1A77BD25351FE5545B6A803AFE3118D70642CB3C8473319F2
0159B1B4C81386AAF3B377B17ED43C4FD1915C6A057552CCA798AE60E04B70D881423972F24F
6B721785F8A76C8979099EB306D6A134CEF9CE30CB6C401A17BB1A8598FC5D955A6CB7EF8DCE
9FCC30F1F36D18911DE67B9B32BFC15E565BBCAF91FE1F62518D50347076A38389A7F74AC4E8
6D6812542BBC2024BC06FCA0023D9C35BDAEFF10E48F59B2AEF959204919FE177067F2BADE4A
BF760E8D52B98E5870C18F5318AEF9147B827D756ABC7C96A8422F4A85CC5F51C444F655506F
A8F669ACCB56FC0EED8453DFC1FA87CD76F452FF2E603F915B8E0CB12CEE06D674A8CA98BA60
BCCA4E955C18FDDBF06F041F1EE76641AC9DE747D91239140A4B6D3B2ABF193B9BD65293B85D
89B22B376F1CCAFE615547AD920F9704F22DCD00328A17251A6020C0D7C405820B369974230C
CFFEC1D551C56E351945E58BF6863E9D7EA8ADA9C9AF074E2953B46AE02DFC18BBB47185F77C
A6DB42B4BDC70046D3799F156CBFFEBA41754CE047F15036FCBBA65F509587F6934BBAC1738D
91C380AFCCC3DE8CDBCB4D7897025F1C1B62984ED2EAD6A873071077BECD0A7D7BFEF7B70411
8D2289F8157D85148D6543FF6032154207B840B8810087AEA35458C087EE9E941DAF0BCDF13D
32EA1CC13A04742675F5C986EEAF8993698B91BD38995BDDB9FC7864C515D4513D9E08049BA9
832E00C18660C2869B711D67CD11023F8906756BA83B512D159B9FFA301806EB28445912E2B7
18941EFB598E36D6B07CC0D6BE507DCD532FC2A261763A79C33B81CDC8D358F42550AED3BC6A
81B5AF1E8071F4C7467B74A4C9E4F34AAE28A3936798BF23FE0A01AF575C33DE07D33005BE56
51AFC11CDC5BFD3AF1794B70B2F1C35AED1E40EA954591A5C6A32A36F482A5939325113B28F2
18801A05BA5D7DD648BC78B1391B77677F22A4398F03F8273F0EFCCFEC1F3440C14671AB8E3A
7330D4CC2C9ECEF017095BBBE52E22CF056EF848E4528408FFABF3B6A777800A024C734F3625
2890F86DCD9D72D072608C157B4B188B8E86124613AFBC3F70A84B05C2D0B5CC1F3CBC0E62CB
98378349CAF187D71931130F0339574D25C6FADED7B44C30AB4428B536EF30E6F7D9CBDCF177
8E00171439AEF7894557D081584D24FFAA9A698ABFBE40A686B4DF85AE8E01D3017F8E44F4AC
0BAF459FF45055114EF642D902326EEC7918390B0F8CA10652605A805D21AC343A6F9124BB8B
30F6B7B4600E02E456D81AFD3C8B4BAB813BE21FD2E4A932CE37B4109D4334625D91E8117770
44C814279028167E979F46646B44F88E8D58335976D91ED7C17EAAFD2701B9791AED67FFE56E
168EC718CE363E7E63BFFDB98032FE540A455026461FFEA48A6ADEB93A30A33579069B3F85DA
18F4A36F564E8068EE58A2ACA1C2E6F980BEACE7495EF9912C735C71EB19E2D21647207578BD
81EC47B56A525CFD49121DC368165C78EB37A779557331BD714F018027894D80A2190B9CFBB2
E6C8BFC28134F8E1B5D6B81A98011D70CAB2029348991AAD30486C01C7066DB51ECC80B94540
B25A647A0DD86DA63907F740EC2E28E8EDEEEFBD06F0400DD8FB4804C5508FEBA5D24E67027A
D9B00B5540560ACA90E7CD4059FEB0513C521668481F4F4D47F2DCCE610C47D4E1055FF2A0F4
08E8BE66798DAA1DC1533E3A8029435E62BE7368958BCD21464A688C330E85F652721E78D51F
AA848627A6A4EC77AC2D4A7946E8079EFD34348301F49C7789941533287ECC7C48510AF957FB
8EEB9A908E963FAB3DA2B86D6B27F8C71713293CBE50A638B37D17F5D7F068B37F5B0F08C330
82B72B87986853337AC95E6E52EAE193AFB60088ADBB6E70ADC42C370B34290D1F82C226B855
69DB49EA39AD5B71957DE01E17E00D9084E9CA01845C0DDCD69127ECDE5519B6C712FC1D565C
3F3517B72BEF40736FE26010DAD917BBB9152557056C018A646B73EE74D805526FC0EE9B199E
040C3AE0330D92CB168541743C10455CABE8BD38342261872583D867E5BD74EF352B90BBE40B
AE4F8207CFFBD65E1A8498ECB1CD55646CA1B2A9CA354EC38A15E53618A26980E652685EA67C
F289956D2A4221372143FB29F835484FB2D817EE2D910A9F56079238E00B72E4218E1AFAF670
B347AABF87E5E38DE871C0BE5F23255358675C139DCAAE9D885EC1BA4471F4BCF3F1B9794E88
EE0DD0DD68370A510E50551D7E519EEFBBA62901E290E60439D162010192936B7CCE6F6E5125
6204DBBCFA9589A9B0AA7AF3E62573962A3714AC5B78747BB83B5046541E58A25948B6CB2CC6
0B0111148C49C1546A834C42CC910361986EB9F93DBC4D1B273EEF819B806F29E8FEBB91381F
94DF1906CA7D92BA2CB685D6DF4AF67F4C4A3461500D2A5B962630755B0343140C5AC3FC75C8
13105489B5523E80999CAD4F64322BD555A9C06F7BB447E2656C620F7FC4D381E2B8E2A67416
66623F9ECB5E0A7C15219234581ED24A21B5EEA120C167E96C316B8D72D2A92C93E455734E2B
98B0E37B59DD325FEC1994F84DCA5F0050C74D92E0AFD6A31A2DF2364E73AB2B54117C08EF46
842AE3207C3B70E88023AA7D0DEA7917D1C928252DFB1B09EE673D34E4BD4F7338A44627F7F5
F6F3914A6574A0709D0E9DF55ADE798B7239EF442798C4FBCC06289735722D2B219D889E2A6F
ED824AC4CB429622E1B944E4E22987496FC86D7E9A74D70FCC368D3196BFB9F5FA512F74FE70
A3A9CC7653908A03777BF1D288D3F69281C9986C0B3A1C422533EC92394842AC60DAD1490F65
8D336F9CA9F1B7CA9E6F2F192148BF6F91794249A5CFC71E55725061C7ED18A48BEED9BDAB6B
57FC85EEEEF6F411D78EF75DE6CF77BEF012C45F22D420773E5FA5FF3E4B83015F3BBE352DDB
F78B946A363D1C58B2AE353BA3DB66CC7F56A9DDE6BC979A2A884257FFDBB136CD8300B53D83
7D80D48F1A733FA5F519F8DF0A08009D0C5F99B1BE2273DDA102D1AED76D304A58FDE17F13C2
8FB7DD802687A8ED5D6C06CF3EE7CC0CA88A927845E4CABF5E0225A76B3BCEED4C2C56107605
DD4B9C118F8B2F7C00A4767FE7264D94127A5833C659433D9853C3FEF19E7656D36A76F44194
6547C3869E3C07F9B7BE373E12EE066619AEDAB6F43A3B55AA8AD8227EB1B4B8CAA4C8CA5110
858B30FFAC05BA4EAD421FE31B88DD09E2857F7C193581E6D287FC465E76559807B7043BB999
34F4D6779CEF1B87D6E5EF4A76C5E9130C29F418A2EE9AFC4CC2CCEE9279DC5E78C7A37DA5D0
0338A74CF5F43C73199ACA7150067A48249D79D3859DC624CD173208B7AA805B0AF7E3D77B34
9AD914385AB9A33AC7A6B7A46686F64A206C9D0089DA1B5F14E88C37FB21A0963F6064E4611B
96DDBE66EEA0A7C635AC16F1FDB158066DB65F7E6E195978DDF7B9DBD93ADCA33FFB67A90B66
89FAC7272DA97CEB6EBD380AF79D9CED6915FA9DE1C8F7E1CC9E2485ACCA3AEFC46EEE1A940F
2BFC0B97BEBE096872F179F62C2127BBF731896A51A04A17546D73AD8A6800E2E1E25A56675A
5BD7113F694DD3C2B9144F689A7245D0662C9810AEA97E0986F24892CD4FA2590A44FC0289DA
B6883DC7E5A3FB476B457F83600710D9A9C6D02F6BDCCE009CED18DC4802EBD65E3B3BB7D4D0
AE73DCBA19476DE12527F2A91E2E0F3638540E2CD439E8363BFDCC202B0AA7003F575EEA6AB2
75D6347F8CAC6A46E3BE50360914888388337BB6836F5C364F923D5AEE67537831FA56457547
B48D3D5358A771004A8520A66CC14F24D84FFFFFA452963EB9320ACC3AC91A552690CB2C5CE3
A85B5BDDA8D98931E02C69185DABCA4F81D7CF58FF5DD31CBA75ACEA8D8F1085DC984D9AB9E2
0883A457C2A5331FD4FD5F7E17FB35FCF243E223A7B60499C99A00C5258021CD495A1E7296FF
0D2D082D42094C166EA832099339630881E218B555D8BF2661BCF41A27FE97B33C2E1A0317F1
D93C09BB3BC20DAEC46463D374546DD7824FEB6CF4A64087F80622DADC9804AED6707DC67AD0
AC1B30F4B0EE17A028C46D112F9E16F456211F8C21DFC4A197B16B9DC8741A6423B5D861192A
5FFA4B1ADC0EEB8CEAA21F4867E4E49824E638B052406040DEE67B2BA6312C2DE83BA17CED51
65FA30F2B34590DD5340705C8EE41CC3C592587F4FF95ACBD451510F3076699107A067BFCB85
AC77D80E928BC043E65C1D2E085D17280A4F7FAD5CECA74BAF6CA8991A90FAE70DF9E5AD27F3
8A773A1BFB78BE07113884AF0A09E896C54C42B41267D3D5CBDF2179B7D05EEC35E5DA9F9D6E
D05735F16AFA7B8290B2A2088A8BC8F2808A2E601382B9C2127F1BA0B9916045747993F0C92D
B542A4FE31A74C3E4AE074F92BB1E828BFCACFBD7A46BDD1A64E8D9D976E348897BA5FD84640
211A28C3D9960B948A2B1EE9560F2B399E41E0B0C54BC3BF880830DAB105C56E7837F89320E7
10AE7FC05256E5E70875CA4648B5ED67787FB1C24804389950C28EB7B1BCC922B5DEEEBB94FA
1BE0BA3324CF95764C2FB13EF20CDC3C9046EDD5E3D7CE15983D7127D9B0835B3546AD02B6EC
690AF4E54E8B17F0FC178E037E354D17467762B837611288F9AC543C04005E79803B4D804ABF
68EBB2BA44D2C762DA71E614F7545A1DE87AC789FD93855D920AD4BBD1ACD27AAFA5F3FE08D4
4EF8BEA457E58487EC6FA9BEC8C25F4CCA68E2C070139FC610D639099651EF1E2F77372AFFDA
DA55CFE1E3ABD5BFF14738AB3035FCEF4FA7DACE79EA942499BF4B177DF06DD60F7CF6FE92F0
DA98E433D8AA773E6784220241BFC3F5CC3DC82183D2827CF0E240429FED566D8EFA32C5FE19
5CB88B933DA775502FF57D592173A0D24E15C4498FC321567DAC0C4B22861561FA6B95930E7C
429C869AF3758263AE8476444AFE52EB8763BB23C0A5A812C2874062ED7752C9C50F4CF3D315
85A9F2F1DA9D75B435C15C7E8C5FA71115452C699D7C7D11D3FD2FAF9FB4E20F96F39B319A9E
1E0F3E7336BAFADBF676F399C9A75D13159A2905B7F5E31A707EB833F8EE4442DA03ED80FAE0
AF2AF7F57FD700A3172504E2257CEDEAB4DA4EEE079EBDA6FC610F85399A80F74FE8CF772F42
E67E6606697F7B6C789D22C72DF61862F028B964DB3B3044641777D06ADED2BAB4F0F8C5D707
6175907A007EB4317E4766E6F2AC310FD4D0CDB962599D4171E48E9B9FC7D78B77602EC51265
627079AB66609899D250C9B5E33301450308CA0AAA70A841985981F0B12AC01CF739B7C6CB8A
1D6344184CA72D7F9A5E1DB94B872353AD8BE1D72E36C15D000E321EDF4B899709EF6A4C35EE
454262B63D555BDD32B01000B8C6F3912A8CE3DB7C3351EBE65245A78DDD8C77D6206ADA0F32
51D37ABB49368A5A4FA91D68A4DA3275FD9FE0123ACC017FD6E89A36E8C4FEE96CB5106DE457
CA3B44B3B52AF7BA773273E1B0FD745DDB287CA0616384B3B8FC8AEC3A9B900F8F0D37F9A6A4
DCFFB4CADDAEF7025244B622CF4A237B7BA49A0EE3B41D7B66DECB8017279D8569F9E5C4F4F8
4A5B8C80976FD8DA3BAD1A8B426ED7EA299AF0E761A8E4D5D273E61B1217BC14CC7D55C20A9A
19FB1AC1CD47FC7D45D85548A9856634094A814D2D96352783A8E9633B2FC45EC3710DCBABA2
A65A16EC34F5ABA221F6F0B6FFAB5BE886307EDCC05A0322A1A2FCCB1BCD1B650419F06C90CC
4CC05EBD269AF0CA49759C1B85406DEC0B594ADCDAB8A33DD48230DF93C15F209F8C4F4CE089
FC031B2BA6A3205A596F459A52938830E7A5693EED1B3B479579473E78309329569BE1B0E7FD
486B72F52D084AE936F59A98CD03AAB0703DCFA05073F2864F0E5E72801F3084A39799D9C8BE
580D43259711FD6B8252EAD8CC24791A6F3B8FA4514B9C01CC9DA37C10C7DBBC91D3B8CB53D0
C92ABD86DD16BBFBF344575DA3BE86D415DACA97A281DC657E783F838F6D40DF782AF3FB0B1C
692B8209F84476CC962807871CFEC07D24BE0DB2690017A8FD400AD5914F4F473BC2B71042B0
B172DB259BDFD8330D968EC9DFB842902419E4090F613D2476E7BC5A3E8C006DE2CF2E54E29D
53B1A065D5A7DDC7DC22A9B2B7535AE0EE1CA56214601498920FEF3E5CE1D1F321EDA290CE58
078E01F2296A345FB32E15FB452CD42C9C25F9513EEF35D604CC1E47ADD9F2C726D771D55B43
B079F88166D224CB150D459E59B478F566875AF92E80CB07BE80B693E9358A0E36E77356ECD8
B1DA13240C02BB370C4A96075ADC295834AFBA1BD74AB53C476F28E6AC7D597CF2CC716C58BC
92D5FBF696072508DB76A3AECE9B45D9D8C72783DF88F43E98F6D307AE518EA612DE8EFA61A4
E8518A5F2C31F17DC860FE3514A7100571CC9BF05309AB81D317F1D2A6008E223EA045F5DFD6
16E0FDADB5DD17929969ADAD1FAB246928351C7D4F9AE4324104065DFB3E48536D1658DF0638
C446217534037F601342BC1DC239DB63D8049E030FA9FBAF471CA3568214CE38D19008CAA834
60F51D50F0922838EBC7FBFF2D5562514A7A4693F865BB4DEE9024F03707D4D0610D1ECD1DEE
A642D680AC9A6D14525AEF9A98E2CB1E17A8C45CBE0AA8A47A057A18D62E44807C5473B048C4
2522A14AECE3DC7775B805ECD60559C6FD0DA27C0FBC6282021895F4A3EF59C9EC3C4C0C1441
42A47B09001CA9D4356AF1301D3DF8C7A2401FF7D8A628E0F429A8AE351DD8E0C50980438F62
899040120998F4A7690FB2843260F71A1D764DD5B790539EFB88C9389668E71DEA8B8FBE0B9F
5B594EC7BF052FBAF43633821EC2B9B7E52D73EB8F104764D835128D9012DD1A949E2224FD09
06645276E097EB04DDB0390A3E79E0941365A24A68377B135D783328E5EC46F84291B36E0DAC
C3DD74558EE652BBEECA9059454E22794E8D6FCF93940CA7E4F4952C4AD10C35E953B4986E66
EDBB77466BF03239DC1A01A2C41184946DCF60E068284713DD3D964762BCB58A7658E0D4181D
8D7A72F1CFE23FC2302AAA71C03D921E4A2F2324D97E19B7C6F74352A5C49293E819EFBB9243
346BC26740E472D7649B9EFCF4E1C3BCFC90BBAA8D06147044C017B3642310B17A9FC2CB825E
C964E532DE75CD2BC37CA2A8D281BE7D88603005BD21706A530FF446A80E3B0E484D43044487
D16CB8B4182930F31B967760DD8B453C0D71CB5A45EFA634339806662683CD990754B54E8292
F70F2A09A06AC6817522A4DC69885007CE2FD18717F973F855F38B79369CF7F0BA790465BF3E
997AF50B6F5E486C96430F1ED59A83E079ACA43A6F315846109F457AFA26B570390DD15C9255
CC9FBADB58286FCAE12354E7F8C5010DA3AADC60F6984EFAD4075611D0DEFD5F5F2043EEB694
A7A500DA22188F9868837826BE5A762C73CC24B545A24DDE9FDD799AC6BF0D3E2EC2E9CC30C2
5B975E1EED99D4F9F3D1B6A2AA6B6504FCFA273AF1B2FEF5B8FBC6AD06F8EF01F262F664EEEC
1C05B4872832F55BE3F3B95A599197841F68F04FB1B3C6258EA5D87E33C68B6EC32B6A3AB7F7
78800C6F2B76EDC900CA6900FBE355B8E65CCFDD4BE56BBBDD5F112B515865CD20C297BD1214
999F272E96E83A40E56ED0F6ABB5EFC25CC6D74E0DB6C02D72741108AAF3EC7429769C432795
27FE20D669947DE4A257DC6ADA552C0BA018985FE493FC8D4D5B41FAAE51E0DF83382CE3EEAB
D9F3742FB3F796C37B41F7BE4932A4E9A03E84152EA95CB6FC29F85D5EA7EDFFD7BEFBC9953A
D60665707D55A8D55477961063F23B8701AF3330531875A48E88228FC014478EF756DA14327B
BD7971CD4489015E39C8CD2AE6988CB81AD993AE94995F1CF7162B46678F71BE7EA163585A3B
11FE47C6013CEA210AC8CE590CDA41475E3B61C2854EFD59190B4E819F092C2E4062BE28A206
D086DF6EB29C26655E594DFC47EF872D878980A0DB181548EC9A5784B7A73C6EF38905A4352D
E58D21F86ABB05D83E70EE3678141204F8EDC2A3908DF540DEFCDEBE1DF43B0A6D03C301D66B
8D3733D79410668AD3F2A59AB0748C4B467CBAFB5308DF268016D5015C314E981F16D101D2D9
11B5A9ED70B56D2C31653F7301AE015F54CC5F800BFBB536C2DA80CA2DF48ACA1DF7F586057C
A4AF90E76378AF0A2CCAC5746E6B10BC16019D501289BB799D68A3A92B89BAB83469797F111A
A357D01BD2B623524AD738ADB55E818243127CFF2A33C9B1400985A5E7AE14A702E3452F8E71
0F241F4D0B139176C799B373CBCAC14838DCEF8B174E7F675DD3E2688F46297023D84A361566
1EB93857E9B848881A94ED78DA985A5068CE4BD1187EEA3FAC10DE38FC3B6C8ECF2DDA03A0FF
79131577D4AFE99934A03C22CA30704EF981FFFA3EA894AD6699409F0EA09DDE6FABC3EC8DEB
AE140CB66EE37331D20F2AB927E4283B8C767E10C4F340DBF1FE874C1A97B08BFD043CCC9B62
B1972BDFF67EBF7F3E3E45DAE0F22E6344CC1C89E9169D4F6C90F37740F5F76CA6306C16540D
4788469926B46236D22F62DE509565959550F9714EA9433D4704E27B81231B98798C0F888BFE
BCA5D203CC480B92993FCB4ED21758D98146D6D54AF44DC8626EC46928EF941BB50483651893
B65C433759D2D0347B4219A61EAC415D880466B2D18FD91385ED688A7593F090608AEC4BFF5A
14FCF92AF9B3D1DFF5AD63F8617DC70539F2E142887DF3DD358DAD04C47E50E6EB0379C2A55F
730E70C019D4319F777F9F869BED86505D36D7EB23E568C659CB100D5486AFD3D28873E33E27
6014638C5F17D3A1F193353E251C1C619CE150FDDCD7506847C1FA251C3CD572E3F4E187A0AB
7625F02406F97A2F0B2EB917B31F499EC1D4B5A89E7B5C1DB6DE329F6126652C208C88C74C27
08FAE8800808CF465CE3FBD6C195728C093107C0E148D3035FD5822EA917B3C499F2BF1BEBCE
11AE998DE12845E6F500FC0D5DB06213AC2E5C581B73D50BB2E13D2E79344168D04CF4338634
05E9B1A75A21D4E0924BFA6BD675FF02FFDFC46E593ECB509BC78409C78CCA5317B499F1E654
2B94A75232B8A622DAA17FF41AAB7F469EE1750B43359A90DA3B2C6E7BA86E4752861EACF477
D0072C922DBCBFC452B5E1DB1A41778610E9AA58DBEB33FB649B2E33F8DE7B25F9BBD0E4D332
8031F8684094D1F0D581BE98C2042EA69C701BA70AD062EECD8DBF61644840E8C95D8A4234FC
1405D8D007C6E14D1A68E14B3F7D609855BCC1B40F1EA8C2B41E2C90D4FF7FAEE037FBA5B11D
073E1A61AB03D0F4BB19592B5524894F10F3B7F29B19803CD15B89C594A1A5B5FEEF7445A5E9
0DC3E39BDABF0A97963E2DF29BF8D9D4375F82284080F9DA5BE69810F211DDEE5352224B2025
1C3F8A55043A8FBBFE1E031CFD1D38DCB6C43588D92E58F739875F8E8C9194E5FC853DA1006A
B74FABFA945E4F145E1EF3AC115D1FE242A3381530D171A5A932D881A1D060A64484AF6E8A44
430CC614D8750B3D12CD1576790A72BEBFF217D863BD3A3F1EF95EBDAE08FD3D5259C55E3B5E
89C14684B18833D86E5590165B43FDF869267CCCF305680124F25BCF086364046D03D2F869E1
F2AAE0B34D3CF7CDBE8BB1EBF1EC13C6DD91F459834F497F0CD23C90770655C1CD74A488B743
1B9F43CDA98ACD56592F3F3846A69512D114040A8086B4F5F068BB1908490EB22D4F8BFD033A
D796EED2405C618D32F4D081476DF61A0D3A0CA91832E8B3C483E52D5C44D7512532D50F54C1
D1921748E58C7ED83854420D04B2718E0467B4BF0A0133B998723B12275EDB56B0A21C026F4F
D2B028095E2FD904596285706FA970ED55A7073A08FFE87F5E063FE949B5CB379B2F7B5C7DA1
EA1977175FDE95CDF84123DCE6BCBBC5999CA4C61281109839429587BA0C76047F42F8ADF2DF
368EEF61E6C18DD432B7592C8F00B22C84EAA72CF9B13CF83DC48E9003499FEA6135B07D36C9
150F06178A79FD5BBD0960A8A0E729514DF63F4A6390FAFB12532070D75C75AB3EE9622CC919
D42AD3CCF3815C71B04C14966FD7416C9B7EE234E82F2E7184DDC489603B1D49CC85E86A7495
530F8C09B25442D242F9BBA6C47E97264DBE30B6213158D5E82B2FD86CAB00A53E83F53D7AC7
CD9E6B701D873A4555003CDFEB1D8B9A455EFBBD88E926299781888EB814D8B45EBA8A5C854F
17C03541E5B28C5399C922737C10DE4942DBEC96A4E803AA48D054BE1E9D9D75ABAB659B46C2
5E30BAC982EA3F1941F8753506A02076B26792144275F834221FE32C88A98E0266E3EDFDD08B
7BE24381069F7FA418343236EF117D207D9C999E8DC7E8BE5FC8D588FFB399191A6D060407B4
C94D30548435FD707155803D3981043484426F47028F0A551ED788463227586881256354209E
34208EF3315CDAC8291490C4C91037727D78E9EDCB2CD828BB161D17403B31AD5FB55A6BD1C7
A70800D0B252332F3D0F1AE764945A8BA4D5128FE48416FB2D8521D8774554006E75BB8149D2
792A24E264A445C138CAE70429F4115148FC46A64C1B1AA91035E5CAC7D56B94773E615382E1
FEE0EBA3C020228F1B1E903088A5B4CBACD287F60B7BC530F7E9024E1267B96DF8A0CEEDD429
A291F86F3117969AC46D6675D969A2C8392D00356FD2EEE67C5DBDC2896A290BE1E285342670
35170B245BD6677B670DBB926BB20F7E879A6F9AA49AF1B3CD57664DBCC19FC4E58772C4D284
E28E57346E44F5BB59E75FDFE66C68508EE98B87ACA3CE30C9B789B3E62AFAC20C45F143CCBA
978B7DE18085B6F1ADA0A33F119B09A7F051A1629CB8DB0EA094AC458863552BE4304A3A247F
43C5B0160C76FBF592C5A3319961305C1AF886A390267847D218ACD200948390C14A5B57B706
7915177734765739D8B4EBBFDE8253A1046DCA4E13F3A031A562E9B8BD88E5A4C848088B56B0
1EA525F94D32436087FA34C6EF4E5BDC32503A3C409A75E0DAD3148FB0AA6E913332D6ACEBD7
7C84DB1E4B110EC84109CAA6C4E9CEB0C18093F5E9BB96B6294B820C8B22AB831391F01231D5
2A8CA189D04E3329C94110EC07ECBBA15AAD2D50AA829BA960369723B6741278E39D9B7E9755
C7FA82C1E7117A1620B1502BB9B251782B7966F29D63CED01018741422D821A5D0FC4411DA57
9E7A47374CC143CA5AD4C9BCD2037BC993D94AFBA735523E4BF2488E36DDCD02B9B71AF3826B
58CFBB3D47247D7C560963DF43BDA8C9A1CF69571B29877F1210F13272AB725D27D3F5D0E4E9
7727A9A0E789484AE677A272F4A777AAD4263ACF572480892233A1DA23918B17D37EAC8FE8DA
16F52F1617EDB1AE936FB0037E0476D09FD278C556F9CFD899F41B8E1854D50457CB3CA6CA6B
A8A964DDC0750432B59277F2982B9C19F6824A60ED7945C1C737914B75838D958D2FD8C6F8AA
F6BBDFE6882891F91A2B441DA2D53082324D35FF12C7C4FD2698933654CF6A78FA370055B2AB
078086EBE0FB7A715DAEE6B202516B033567E9DE6CE9235C159C687A7039871CCD726CBFED14
43F99A8194340A84E529EEF8B6C423CF487045F3D4582D9335EC9394362E41FB2312315F737E
56F15AF4745C6A31E05AF56A7361E043EFAB8D5E219D292FB6512BFD552F2E378751ED4E90B5
453CFCD01E8BBD826E328B3D3F7943EC188EF170E2C0B3B5DAE662BFADAEBE50ABE0C3A7D605
0A3D978AADA8A23D1E65D280CE6649AA096704DC2206EE61CDC81E75E8B69D7A40FAF01519F3
831DBD268D116BE69D12D44EE05A6066930DA03890117CCFC9C2B324A93DE0E3B6AEE41990C5
D7760ACC6D3182EF6CA086D32EB717CB244E68EE027A4AD03CBAF40878342B8FCDFA4E866805
7912698691655E8581870BD730D941D662A88A9DA5202A368C9CB0BE0E8BC5984D3D54EA95D5
4A81FE8BE7C3F67223B985A28B35CAB59D28DA662DBA33C5FAAF5CDF8B5140343EF7A82C260F
FBA07A7E905AC89452697690A5A121A199D2970F12E80341C295EFDD17D032A742A29FE30DA6
C2C44DC192630A57122D07A5196FBCD0EB56230971AF33AFFE68A833F583D634EFCA31FF46CF
4DA8DB9E7B4105E2029D2247FA0B575A881FBCD4C37D2E2F4AB7F7A51E1411EE00EDD0C754DA
938E017FA8E2F56297F7510E20BC275C569EEC62BEADEA90537CB47AF6F492C28F1A7D03D78C
EB3A596E6D57C3D86B482D3EF2DCF352038DF4E9EC535E0536F5E75936810D3785A3439B2A28
8CCBEAC100768BBF846D0B8BC41F699703C47C15B26BCB542B007A34B4205AF6C7A7C7145258
D4C506D82AB9F04DEDDDACFEC874EA4947F65A9AB682E0C497EBDC0244B7D7C724C4A9BCDB29
173BF51A054C9046DBAAF2E681BF1426A8564F27299FC64E62A38CA5C757E422251F22FF16D9
823E0A5534076C8F12F586802F6C66A6E2BE16BA97963A521F9127DDBEE098C69DBA32488D44
C259B35C2E61AFF83817549CDEE368F7811DF262FC18BD60286622D2A4EA859B8860BF387A1E
95E0F7B72DB061F34671C902BA2803FBCDA7E06B26C00007153B1D89DCF4C71D2BC86BED5423
BF9661B41962038AFAA36424E74F319C5283A67EE3868BB8C73F9232B8FC8E31D1352A0213F4
03B1D157D6435D6509614C67DC0DAD5819DECAF98EF557931DF953A5662103C7A7F0A868657D
C992E64AC488DC088B0CDF772DE91368B783FEC311BBB60F22BD0C7B4A7F7BED0F240F17F2AC
45A9A2E9F672A21DD41E4B075D54D4E80CFFBBD1DC391DD29107710F08EEBBC02E5A35B7C990
E78F686DDE2B2FAA499F285C4D8E7A10BC48663F30847145827173F9034E0E3D8E03635B1DC7
12573AD404EAF33A7A730B63BFC1D6F42429121EC13EA5D85A4D3DFA5488F4CE10E08F34EB83
C277291A1AF3B02625EA35E931EE4658E73C04A1FF4EA88662EE6C6105746B3FADCAC6FD670A
FE2FACADB3480DAFEABA0A7F361DB527A073D01FC86AB5BE5FBD582783F3D26D1E0D44E1C577
CB63940BCACFE15570304F5518B4D9BEF913DD4255C76335723890F765847A3489F985B2E576
E078BB844F44572BB824E1865BC534572637E35625D4AC31B6AB5596E290D689874A3BE273C5
C1270478E7B925B08ED9E2E63233655625AF6A899BF73CD69903A27C8E06683AFED2E209D7E7
9D272344331267D189556BE3B62F0D2178E1505D20F916F12B5E0D80BB2E67467449ED1E20A1
EBB99DD097B651130C06E9284ECE3C91C5B8DE7B6DB935ACE4F9CA4560392893464DCFFDC463
537DDEFA8DAFE59C0C2C12C58D1E093817D36159B684EF38F45648119EA254BFEBB4DEF31286
9A8F296B5B3CF62538D1F38B9E1C273E1989F734E6F05A35269F082FAD95C5AEB719ADF7D99D
D646C650A93D2FC8ED9A266C8AF3D49C0AD385674EDC63F7036CC5D02C088FEFB44C5E859E33
C5545E6C02178C69052C8E4DAD307D74873102339D631231F981A23725DC85A342D44BF632D1
6474F325A9308FD394DD9AEBED391D535B27C4D0FD2D147A4AA2932A19D832371080AB31299C
910A928694AEBDF4D966E0A1682CD98237D073C3DD6BC19F3E39D056154F763B45A6F192B7C9
71C60E6275F087C4A9C61D26DE070FB94450D8330847B826336A9B1056768643EF5CDAB3874A
F8E64C01905981F1B61E3933FB844702B079622E17D958B64FE5D96E0B4DDD83D745E2AB1CFB
1786C07470474EC53339CEA8F0ECCF4B71ABCB0E578E9F0E9D760634708CEFA7EA5F7EBA4DC8
CD1C416F078756D6237409169AC9780BA8E6B6A29566C3C53BE9FDE79A78B471F05C9723F8F9
0DFB23158F7D3FBD767CBB437D85B1A825C1351108DFF112AA9749363175497638D4B9A2D8F4
34E56178925F00467E77245E1547CA9556579D202D7C94041D41E4DB05BCDCFE9F7483FAB1AA
8CCEE0BBD5AD3BDFA87640D0A4763718D1191BB487C9384841464993AECA21722558CBC1BFA1
E540C1D0FB477123281B2270ACF6207F2075A84C147DB4F45CD3B9AA97D9607D0DE09C4DACFD
FFC9C889B31A211E8D6AB4967E68A90DE86212E23D7AA0266A5759C9D4165C98A4922ADCF6D8
209B82378A4175AC6B91A4EFBA924506F181F1917385C7A1AEC29501CC62473C225214028413
343CAC23EDD299D1627DE6E7CE9DE4B19104728A4876A0939E0DF5FD19D5DB6E8890DA1C259B
54BAFA5EDEC6E443732DF9B40594242C9862FE554C3D0869F7FF495DE0C192846A182C2E80B6
DA51CBDF5794B34978FB8BCD26CFCA6C46F5320F1AC0692FDCA4DEE5E4206841F46BE9BD1EAE
6C131ED3DBF52237120487C30CDAA32DDD8AFFC01E0CEEE85A7564CD3AD7386FF964C0544F62
6B924A1AD77A99C348FF7150F7896DFD839F6328E715BA33891CE00E8F469898F7AD75A626A0
D02C76EDA787D7B74E2C3EA9E018C4414FAD9732ACCC2386875298680D553E6DD873E8219E66
862DF3CBA71410374E6D7ACCCCC9C4CA389F96435064EF577DD391463D67F98789C42326A92C
758B017029538369BD530203A039E06167C536EF17500BCCEF386C77FA7BEEEEA2D87E9BD5A2
72ADD904E484E2D086D8CD6238F58B62FC39B7B53E64895FCE06A86DC2990151BE86D572E2FE
E28F2C6DBBF43B6B3B76BD7BC543000BDFDEA65074309E291CEEF398C7755E73BB502C98DA18
8137CBF8984C341E55C498003CFECBFD0C63B2288FABC92EDBF7DB81A8A0785008C57517B36A
1D885BC80A684DF355077307A8AAC76FC9304279C6D96A130EBE61327D8D4A9BEDA3F944C528
A2C920FC7351DD7BEE534D57FD3D7429C1A245937A86F139FBE86BA87644502234204209FC6B
A1CDD4213CE0C0F19B42B0E5BC4E97182C16069A852C75287AEEAEB719DCF15BBA17714CB534
060CC4AC13B4FA18122E5747F0EC59CF4BFDDBEDA2D802AD801D2AB1E148427AFA2DDD765C17
011FC1175FFD498AF19BDC51D4367AFD662FE538F244374FA7CF088D790523D5886F5A225955
9909E46A887C6B317A31618A4C7AF5C2512F83C7B4E9C441388F8216EE8AA2FB7B18D62E44E6
A37622153661F64C0E4AA570798BBA35187AFD393F384ED35DFD8D7CB9745FE36258AD50E5CE
F99E364EE9440BABD3430230C6788C655871E034FCBE154D5859B78125017D08220D33BDE57A
0744FAD3F9EA4F70040F3A9BE483269B928600AA03CC0FB0EEDCD42731E06A2D7A95F1A8400000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginFont: CMMI7
%!PS-AdobeFont-1.1: CMMI7 1.100
%%CreationDate: 1996 Jul 23 07:53:53
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.100) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMMI7) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle -14.04 def
/isFixedPitch false def
end readonly def
/FontName /CMMI7 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /Gamma put
dup 162 /Delta put
dup 163 /Theta put
dup 164 /Lambda put
dup 165 /Xi put
dup 166 /Pi put
dup 167 /Sigma put
dup 168 /Upsilon put
dup 169 /Phi put
dup 170 /Psi put
dup 173 /Omega put
dup 174 /alpha put
dup 175 /beta put
dup 176 /gamma put
dup 177 /delta put
dup 178 /epsilon1 put
dup 179 /zeta put
dup 180 /eta put
dup 181 /theta put
dup 182 /iota put
dup 183 /kappa put
dup 184 /lambda put
dup 185 /mu put
dup 186 /nu put
dup 187 /xi put
dup 188 /pi put
dup 189 /rho put
dup 190 /sigma put
dup 191 /tau put
dup 192 /upsilon put
dup 193 /phi put
dup 194 /chi put
dup 195 /psi put
dup 196 /tie put
dup 0 /Gamma put
dup 1 /Delta put
dup 2 /Theta put
dup 3 /Lambda put
dup 4 /Xi put
dup 5 /Pi put
dup 6 /Sigma put
dup 7 /Upsilon put
dup 8 /Phi put
dup 9 /Psi put
dup 10 /Omega put
dup 11 /alpha put
dup 12 /beta put
dup 13 /gamma put
dup 14 /delta put
dup 15 /epsilon1 put
dup 16 /zeta put
dup 17 /eta put
dup 18 /theta put
dup 19 /iota put
dup 20 /kappa put
dup 21 /lambda put
dup 22 /mu put
dup 23 /nu put
dup 24 /xi put
dup 25 /pi put
dup 26 /rho put
dup 27 /sigma put
dup 28 /tau put
dup 29 /upsilon put
dup 30 /phi put
dup 31 /chi put
dup 32 /psi put
dup 33 /omega put
dup 34 /epsilon put
dup 35 /theta1 put
dup 36 /pi1 put
dup 37 /rho1 put
dup 38 /sigma1 put
dup 39 /phi1 put
dup 40 /arrowlefttophalf put
dup 41 /arrowleftbothalf put
dup 42 /arrowrighttophalf put
dup 43 /arrowrightbothalf put
dup 44 /arrowhookleft put
dup 45 /arrowhookright put
dup 46 /triangleright put
dup 47 /triangleleft put
dup 48 /zerooldstyle put
dup 49 /oneoldstyle put
dup 50 /twooldstyle put
dup 51 /threeoldstyle put
dup 52 /fouroldstyle put
dup 53 /fiveoldstyle put
dup 54 /sixoldstyle put
dup 55 /sevenoldstyle put
dup 56 /eightoldstyle put
dup 57 /nineoldstyle put
dup 58 /period put
dup 59 /comma put
dup 60 /less put
dup 61 /slash put
dup 62 /greater put
dup 63 /star put
dup 64 /partialdiff put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /flat put
dup 92 /natural put
dup 93 /sharp put
dup 94 /slurbelow put
dup 95 /slurabove put
dup 96 /lscript put
dup 97 /a put
dup 98 /b put
dup 99 /c put
dup 100 /d put
dup 101 /e put
dup 102 /f put
dup 103 /g put
dup 104 /h put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 108 /l put
dup 109 /m put
dup 110 /n put
dup 111 /o put
dup 112 /p put
dup 113 /q put
dup 114 /r put
dup 115 /s put
dup 116 /t put
dup 117 /u put
dup 118 /v put
dup 119 /w put
dup 120 /x put
dup 121 /y put
dup 122 /z put
dup 123 /dotlessi put
dup 124 /dotlessj put
dup 125 /weierstrass put
dup 126 /vector put
dup 127 /tie put
dup 128 /psi put
dup 160 /space put
readonly def
/FontBBox{0 -250 1171 750}readonly def
/UniqueID 5087382 def
currentdict end
currentfile eexec
80347982AB3942D930E069A70D0D48311D725E830D1C76FBA12E12486E989C9874C2B527F092
5722787027F44470D484262C360CDFDDDF3657533A57BB16F73048BFBBFCB73A650484015441
FDC837ADD94AC8FBD2022E3EC8F115D4B4BB7B7F15388F22CC6198EFE768BD9FCEB3446EE4A8
DC27D6CD152485384EF5F59381FFDA43F2D20C8FB08AA27AB2015B774DB10DACFDCD33E60F17
8C461553146AB427BDD7DA12534BA078AD3D780414930F01BDAAE649990604A33AA9EAFFBE5B
5489E5C7C9FF9D9BE01B08220832C41CAAC64816B53BBC087AE4B621D2B44B21AE5E3F7FE4DD
B05C675ABFE30510EEE4A7C874BB57B2FFE521A6875EDDFDFD18C78125BFCA5A097AAD361DD9
4DF46F14026C25EA988194899B95001209CB7009CEAD4B4EA03473EA120E7A7E341D4E392679
6347FDB3A124C29660AC09F4648B313CB58E824884382F24CE08D2EDC686923ACACE1201C16A
07A42803288CD0B946F7546510E95B1FA1CC96F0BF72AA823D8E83D7C68C752C82A54C752EED
2B1E699DE9DB1830272FFBF2F4996CCC2D6FE2AE272798989525EF3B67B0D09BFFCEF749A805
E5F76578222B9C4A8A09B13189A16AB746DDEF7875F1ECF83E568F493D82FF729BAA1E0834DB
EC30A35D3C49C9B10C5E1D90C6E3C8FB737DF5CEB3299D960FB79632F91F257753B4D2E34E3F
54A26C7B950981FB7FE4DEE3315DB63E75B024B4D318BAEC8AAC9CDE186F6D65767DF1DBA351
24287C2E805BC660A3A227720AE4FA097F1D75107441C0A0FBB9EEC17D5516FA03B98756B7DF
7AC7EFF9C7A2364B9F691ED5CB692DFFF9DD80C761E9C4D5D6061782B327302C053CE1CD09BA
0605EBF761CF9B730524E1994E7DFAA956799D522EC53D5ACBA27A35C4D28279617771938ECE
58C5AB664AA00C1BC4EFBA2D15504247A68E3AF0F9BD59A12AC1D8764421DFEF5DFA13FBEE58
F5ECD4DEEB4CDA9FE9483C229AB29460B05559B035C73D6B88F6A384DE0E2DFAE4B1886F91E5
22D800B0AD40EAE57F680490FEA4A2EDA9F8F57AEA1A4315674BE45989C2293362DFBD0B5D90
A523A7B79DE04D6F7B9FFA9F9FF2F2F7A1645E6B6E199C88C8430208A7DF1F8F8839769A44B3
922B18294062582DFB8EB65D087635F1B602EFBD5AA1D63676616822AC40947E58D449F32261
43EFD388F810DB12077F5CBBD8D6CFEE0AD3EF2426BDD29BC2CFF5EF597390C78AE61291499B
076F95738E231EF838D1B7A8B67849CF0841EED6D31BFBCADA8BA9AE383F9C003F51EDA24EF1
EFEEC12CFDC7162781419BB65E62E3F68C7DB49F83D77ACB20C133BB4DA5194910855BFAB3BE
B389D848D0C802AAE7856679DF31113FE859B64128FD104AE04F652EF18E8B3860E444BA0BC0
5DCC11227E2E578543477D34BD8EDD99F20E36A868A7B327AFDA18A903CD24C4DBE23FF7EF75
3527360098A9C4F73D5AAF334CD804BEBEB6BE1E24CD7840E6B3CE1724887746E4B8BD8ED0AC
5A6B573CED9C408B10A7BD1E457AE16A401F411F42D2E57E35A2A07B13AF2E091BC8426E30F5
89B95BAB58F8D5DC2B9E9D34034F16AF06DDFD549660B9144B64406978299C0B964B9688ECDD
B66D004141F9A3BEB9EF7C418E89545F573C18F43AA2E3200EF93F8286DF556B1C8282349FAC
4F351B7F3BA92F33095D9786CFB2F66CE46F120B88A6E836866DD0A05A4BE4C611E25D32ECA4
C1FA3F2BEC2CF153C405C5DC2C9ABA91DD456BFACB2D7025650549E454927FB7F07DC0F215B6
00CB7090428F4BCB4A495C6501CCF0E0F171D9DBC6C799F3709C8EF3FCAF30567524C2EF71FD
1ACDB1C804591117ABB9E8F9AB16A19704A1747185680CACB1375902F4ABB547B838B98BD230
305CD0CA05AF58F40BE1C7854484AEC18A52EDCFC12F893819B94160F128D47378FF286A5342
2D35A7E7DAB8C164D68AE0F5974940AEC4EC48E725BFAA307E24072CC76C4B0FDD453DDA6178
FEAAB21B218C02631D1B6414DCC7FE08C805096031078414CB221F826B646FECF3AE2EBEEA3C
98E76C10F529D4AC720A4CF71D0A3BDE7AFF506E5D4C0DEEB952B7735E91484152B3523FD49E
D9B495D05F8582F69D3D4BCA0482E5D8CC77658C4D9DF370D7A24A26DAE2A8C7A6BC3521B575
C3650BFAAE6B5140F5C98CAE76790CBA4D805A5814513553679CB1309A01CB066F8E6AF2B451
B1C5074B8355D3B84614A8DBC11A56FE2AC39A88E3D604A58BAB849AEB9781D924D0E521DDF4
499D03D1085A5609E0721A21D513121F07E6EBC0E57815C45C7A525EC3751F5F0118B8F24271
D42F467E0A994FC9D6024365A117B761E1049E8EF91D3E25A9A9E46898C4AB239D3D6F5AA425
B03C5752B6554754F4D3240BD2A7A7CA6D3A2C7226935D1FBA7652624EADC4638CF8F61BE95A
885E653270983BBAB4A774FFADB13B16D527A64B3D083F0B289DE3A7568A53509CEC86CF26EA
4CA57E9AEB7673D9400F466F2B5D8D4889E82235A3580C84EE00761152DC80147CAD523627DB
104D48CD2560DDE3C951CF8828D4C9658728DF842AD3495B87522901B0EEB874D3025B66B3C7
152C7DD8AD7DABDDB48E1CF7A1ABA3AB060EEEEB7963DFD47DEBD1342D5AE8640C0724E32D0A
B2A849AC822D94A0D19E7159B4C47CC9BEF85C10F1E068E722068BEA6EE0ACB161A8188CDF81
91A2D9328322B0DCB922D87917CB5787965EB171DB8CD153A55429E67AC86C9DAEE90A31CD54
FD8F04ACB4356B6F09AB70E917A8A9500D916EDFADDCE5884443A7F98CFCAA0FD2899C7BE11F
62AE8D2F22A10917242A6689C91067EA4C543A40EF28BEBC4A7BBA2E17C541F4CD655146639F
F67F5A2D79A55172F95C7746B3A61FE1EBB8F78C5AD4A5EFC3166FF4F8223E514F48755F41E2
4082CBA63A7D0090694CB3D2DEB4E8C2309FF8FDC6BD1AEDD17DEA1AAF4932D26FBAF0EE9402
A20FCEE267B5AC223C6FEE0AA5357C054815402C7CF9AE808C2E391237A1B2A15A107B43BEFA
57471427F92EC4ABED182101EC1D04F130FB1BFF36A2A3C2BA6C4184F718CB1DD9E2069050C1
CA58FEF786ADE0A56CD63CB671B7B9BBBBA6114E6B6CF6A5BFCA204F32AAA3E3FAD926C0B5B2
17DD5FFE78628D3EEC531D24876778FE60B241C8E7ADBCFBA8FAA66119C7992A393A2EBC9B79
0702B1519EFC2D0BCC420405340BEF3FBA7C1CF3C3FA5E3435A0CDB6BD0F55BEEA0BC44FF7A5
7FD0A1101A23D9F7AA41B61DE857737A40B51B5CC1040FFE623B583490830E3A063A75776CB9
4FB88151644CA3D357CD1123F51FEAE5953E6800CF6F2237036D0E201305DEC392DCC534F9FE
32D8A2233A4879330449F9258C7928E6382FC11820D5174836F0BE85D2BE4BACC40BD7072A3A
C18FA136BD08466131A10097C04E1A9B3C174A0353B1A6DF71FA5DF2EF683FB258F528ADD303
4D069782A349E85B38CA468795D0747ADBA2B53AEEBB0086212103352A6C9FF80B04C8B21B04
50535C8465D2C1DDE0A494D6D74BBBB2396C4E99DFBC258A2AED6C472436C532BD84F21CB4E7
8232DD65101AF1779D28ECC5F1A9EF7BE55CB653E495A76F52F696A5A4AE898409BB839CA6CC
5DA7DB458C5697CAFEEE7A0190F1F624DF24ADB4FEFDA30CC64538BC587CBA897063BE93CF28
D52C63789281071A96A1F03DAC3F963DE386DF25564B559ACA5630A13E92F31F3AC9B0FC2F9A
AFE50BF45CB7E371DBAB0B278D813EE22B224B0E4D196A6B5123B270CA8BF5160605B75441B0
3D1E2599A96A969CDC46C84AA6D4B94736C933BB94110D54E28898D5D852C18C4E2A9F893EA1
F34F4720BA1F4DA9D653186F5772C62AA8A0B210BF9B97CCFB86C192468C46780D8D5813618F
2F7B6937A7B2169194709837D7CBD6B7F237C2E106889E18C9B8F38D40A3723D4D53E8DA3CAB
D136FCDE420380C8CC497248B0CB524AFA387235D306AE8ACF8E3BBB7D1BF0CE7207B5748448
AA9B09761254458D55660C98607DF8A08755A37905EF8C526D3BB696946F1CA3AAF32F98EE55
F6F38402CAC8CD83BCE04B1A21ECD92D7769C0D0AC9CFF0B1104467D9C76673ECA72C3EF1B09
09D63EBA2D97657200008AD9D8276ED370D36CF17424CB75E2988AEAA7F6C50720316367B99F
576061F846C6EE85C8A1EC7ED22FC68DD7E1B99522E836BC05E2C4414B65C9E31921766A4A27
D4C6332FE5B0464B11142355E17D550D22B4D9E3D7D0DEF2EC84BBC7ABD3A5DB6F6F49A0100E
20834C749E3C4168CA8AEC82B91598D41C81AE19FCE226C5C88EE3E98D844A373938B7D5A687
E319058E4D1A52CA431ACC7157898141CC7FC4822B943D836994ACEAC450D54F41FEB4561566
C08649128C779606EFD07B2C3B6D20674D64F39348391DCD3792D214631FFDA96BCC01E45C23
9CD6E2BD911709E352A909731049118940F6005941C41827951BA7B38A4E9B10528ABFF2C285
209F7DECC4FD0CF1C26C5D77D7AD6790E73C67E17DE719788BB65D76FC0F61D0825882570C98
2981A3CC1604D5FCDCF01C879A75DAD33E1A8450C732130F2544666FF692A2DCA278E717B8EC
BFB8CBAB26583C8DAF6CEB4F060022CA3C8468CEB05B1634E6DD6ED8F759561219AFBFCF1D8C
1DDF83D242B0CC3D9659834998D1DF8CBA0D53D562C923A3A956266C1BAD118C4C4578880D34
A6404074B4662AAC6AF2F4C9C8FF606B195397B15AD308202F29C6185037F21D69E6D81912F8
3AC57FD1355EC90BEAB3F554029F226D62D5F2E5FA1D9C5B25C60DCE792BE2FF2C0C73B14715
86CF73D0D8B98F94C1E16DC03042664BEBC5114E260EF1B9319A7AAA1FDFDA71A943FF198E9C
148DBA217C32061A458063B0BC8F2911C55F7CA3A67C01B834164A286665434F426DB71DFFFE
23DB26B272270586DDB6CE820A6B04FA8670543AA9438EDF32EE3442F531FADF4915663A3D97
D02D258BE79FE4634417DA41A4383FFE35C2C2C07DF7210C7B767901E61E385DFF7242AC3692
D1E779D6C98705EBE246AA0BC17CF8DA99DEE86F7CC7053BB106E357BEAE7C0AD2ADC064FA42
C43C6EAF3AADF274C06499BBE30C7DBD639DE124F66C61899FFF5926501CFD11D937FA2E3FA3
2A35B6D655D15081252DA57F0356601E9E359903B2321950DF082BCE3750219EF3F74EA1CAC9
27EDA9061A282CA1AAE219BA9BCB79C477C8D174BB42DA6C3E7CAECC2448B2E1017AD7487B0B
80413B2E7EC6DA2FF9EFD0B57A3194D8DA6AE765FD6C1E5362B2AC7B4E26C02FCA754DB2C24E
824E309FC6C3A0F5AE9C723FCF77061EEA4E12A6D404A52D61DBBD5E64BFD3C392887667BFA5
229EBBFBDE6A065376D3AB8E48314912061E7940122DDA2D8ADEE2F637389E5F03849C89D275
903379B0949D679322D20C7716AE258855A25499C0E7F0A1B052B0AB19E1FA6C378771140E59
F28A013704514620A82B871F2309337C20A87C064338982C7A1F2642D69A95F785034EE7AE11
CD4A74C949A0B8983796925C8DF349D4B49B7E146FB8EE5B3B23B1173CFFFE2558EB7F89711B
D270E07B1A61861D88C8E9AFC9DEF32347CCE521B9EFA2006415B31036A049F382306D7730EC
D3D9D3F62DFBCF80DA2163D2E035E8D8C31D17CDE364EE8E81ED8B30B432960DE8A3EEC96C91
54457847C5EC4DAF8FA56D6F9D09430505CB8550A0C29D37029AE2BC42958620381C0CAC3BD3
16BAFD21AE70C5BD9E549B1C2FF7A94C7A23E75CB9B905AFBF0DD06A61EFE5DB5155DDDA0D79
BB7D2A804FDBD05B318E189382A835A8E819B0E4E9B4BDB0FCA344D82D039F7A16C50F08C18A
D54A48283CBA7DAED367A8DC96F7410CA0257DB97AD7793E6F93B78B4B09B14021B6BBE2CE10
5A953C4859B8801D360FCC57258F6FEFF09255E35E60B0466930A6710BA100EE7244CF3BFBC8
29760D839DF1991D92D7D0DA34A93DA112760ACFF209222B681BA175CD5DF809874DC8A98C7B
BA686AF0398FD54AD253350DC339ADDCDCBF239695E2DD2694775F33077E6EB7D5A257AB9E3C
EF0C8B3C135929BD902BE3A8E8852B1655E62FEA58788C754C91C68B65561C6289EC2379EF6D
D790FDA02BA18FD0451C692478BE003CFB5BD998B0DAC2F73024D157C85C2F5B51A064BB0820
6E23C852E5D81211FA3BDF714E0CA86E3D1B3CC4C66A42E5C0B1FF5FCAB27AF94A254F38D549
C0367C820CCF98EAE3FA52C2DD950ABDD6550C2412B4113D9D101E6060DE5E5E68CB882909D0
2DBCE4F6807779FD42C8A46912DA217ECC4C6EC2887473EAF94F37D7568EDA0AC4AD08518898
133F5D41640070F7317C6A4317C40AE3B0F69319AEA335C8AD2FDF52416F52D3533BD91A4775
FA03B671BFD39B54D8139DBB44709A43F25B842362D44F8CC6BE96E456CF57DA2DEF7130BF64
8AF46DD07231672A2D00D8F5702BF62E3E433C395C3EF99039DAE91B672C7107324E4525E46A
C12D1FEFA0A884972A009B7164EE40ABCE8385A2EE5B12CE41287D1AA8DE6B2AA14DFF5A75D9
7445CFCB9FD76F77D7E3971506C84813BF7A50D844DA7B2B7743343DDDDAC10DF8D6D7D05C3E
25FE99391452A4C5DBBA01A528A9D4DFE0D7F719E462DA00F847CC43C245CEFBB9F139A3AD02
5B680CC8ED2F6202F6F14E68722EF9B6728609F1EAE3DC10642FB721370A22779F4634E7B242
34A1E16B339D8745DD7B1666907788BAD4460F1BD54F5E66469305B47C7F01841D3F9F2CB0E0
C419DB5F4015C2709B293C8BE41E4BD5B0EF4EE0200928A2BE5969BF06E4A465E581F52D3337
4A239FD72FCEA7B042C338C96CD153AE2B08A34B17CCF8423E8D72314F59E01E57038544038D
9C66F75A5B647C5CECE9A50CFB704F89E21659034C466EE75D3EBDE216D1B483156E3D017C19
0A62B0DC71BC36AF006EB820D8BFB5351E31FDC5189906F6318A6516C537A59D6E8D409E0DE0
B65ED4DD6FD08242771B95EE667BB1C28BB88EB31B9F7CFBC8F7F07700C899F97DCBECEAE2C9
8932A37CE0B98A66C0C104B2D02DE706E3B65AB49524EED7817260DCA01374D0F39D109DF408
6E66836E9DCE633197AA137D5366386788145B4E5BB2D927AE3EA9B6272D8E1622C52ACD4BCD
6236445B6FEA218AB243542F30F3B9E6C2AA2D6DFFD4E31AC0E64F458C22BBE36076F8E07979
AF576C421C998B51549723132F628CF7CAE98387BABDC26D9C002DF3948704C8E2D1C9349403
514300F721923D77E666B0BE624BB143ADB96FBAD1E9DD6F26603422AB466962781E7BB6D8C0
C50760C278A4E34A9DE1529622F6046BA2D6A97EA2570A4CD2FF2EDBE77657C261706B9FF4FD
51E44F9A33D48C3A0D44BC0D74AF3B401337A522BF51631CB5E51032C54BF20A3A30E0441C8E
A734EAFE35F779D1596388F6F0D2D5D9E9CB8A17D77AA09E51A72340A0C81C714B1E7C9FE566
87908C8B6D6473A51973FE65136053A839458D942358C750110006A283F1B2DF4D594384C9F9
1502ACD2B31D446B1E32FD6018D6E9B7E7C8DCE31DA48D14501A541009A187057568C53AC65F
03DEA75EC1DAB78C6AECA02E92F70874E622A18787197DF8ABD3A0FD77914C07FCA2126BC875
AC498046954417D378F3F65B87988940A5F794246CDDF774D5F61AE75E7CC012307CDF469002
D4DE10D80744628813341292B6AC4E09BA6DEFA1E35B12AF906C6E88756D2F3C71A5BA43C192
CB83ACE0C0EED73F58D4412A29C637A367FE1134BCE8F0314E08A180FA8EFF635BD95D1FFC32
2E612A53E553A42DB0F15FD3F18E2AFBAA5C6EF5FCDD21F147D6D27202A403A404E8975BBD51
53F93D40D2798CA821DC595A357E46D5AD79E8D93E63C8256CED66D3D51F26EDB47639B5EE4D
9D14B62454702006EA66B7D71430C141A3762CE8A7EC32CF95E3208F71F0A8513A4B40105735
C3E7B4E1BF87C274ED324CD2298269C1CCB8721828D5DBDE8C1875FBC4971BB6996BB5B26330
FCEBB91D9C0198175289D863788E98520EE1ECB6617187C5602CE415DE45CE10FF7B5A717D90
E1F28BE96AC8EE2DCED981F92B65FF2ED70EECD785B19B1E6DCC64CF7D58CCD13EECB4B076C4
B96B4A00945CAE7976FBFB514E253261AE3FA0135E1F03E9785421F5BD640578933FCFDDC878
71A9E6BC165950A16C6B04A99382B5F1991CD82069DF6A2F96D664D7FE270816069B8BAD8F12
366F1D8B5DCAE13C7DE3B67D192084E0B3B55F3EE17DB978E2E026A6E7C1FCE12718F4BD1ABA
FFBBC6D30A33B9D2B2CB741D7771519D4886345DCFF867C54FE348E07AD817EBB996F937AED8
04721D91787D4935FE847342D7D40D676C1C7BE4CB2192C1B832FCB27B2054007626E9A055ED
E0AB360EB5517739E2F756D416C962B8A7B27ED92DE3086A1CD05D5480023565190C50D2F9B2
587E17EE9DC38742E006452A47DCBCB97FD145DF15F9653699F73A808E454F05879924F2284C
32C8AB6C92F8C43EA57FE61FC6278E88E7B4B570673824657594EFC71A1E75B99528A3E21BD8
E91CA28D6581F44BF957F6C76215DB28B0CEF44D8589163D51FB364CBC32BD310EE9916A37FF
808B53003706FE45287F5DF47713F808DAAE009A7742BFAA871A6017DF5F992D43930FED29BC
3CBCA69E1BBBB8CDD51B5720984BF1788DCB4E665B880CAA22570DA5557D24E90E0753F7A347
455FB53CCD5FF9C550752C065E6C4018583E64B41FECD7E07CF3D0DE2D5225184B164E4973F6
54E53D8E612DE5B5AA61753111C068A5010AE29993C0B067E0463B99E1FE237D3326AF97134E
2A0492C8B99658D55F37CE1C62D6A6CE8AF7C3AE2F994FF005A30E1CF62A9901F6DB108D8F9A
CF443FF4CB58C5E2C4394D615A8C3EC9591BCF0F46CD8BBB1F70FD4B64E3ADB8E84675C0C0B5
748538E47539DE8D02BB30975D994D6B05DC6C28844ED9885E75C82BCD560CFBE660694190F9
BD00B1BD35D7C25B59B7052BDB507E56ED6CEE98E465E9386F188EB74CD163BC0C0D9406133A
E37001AFC76A33F3470A12B769C4A319AA846552F5EEF093EB25872F8C549A74A8D3E26FB9A4
ABD083F8A65A131BFF54DED0813B71EB7C9886C0567D426A380FF44D50BCE0C975DC0AFFC7C1
38A58A7CA3E4F232A38CC6512D7B1BF6B7264E05E7270D53E21F59C49BF648C0FAE043DA737B
354C2E92BBA6BB1683CF490178F57B08D638626983D2FDCFA8D114FA6FA28F8A1405C9A41D45
1E605FDAEDF968F9777454A27302C13B96851DB850DB6A239097716EE06D81BBC644D2BA61D5
32F3B574EB90B6270E23626D0F3DEAB38486275BE5A9C4D3C7824F015DB1599EFFD4301AE22A
6799EF9137CBE9601A7EEC49380B315558B701F51A5521584F234B4BB681C7AA7A35DE3CC104
D1535C4D0C6E6217BDC149278DDB0DC5345F25DAD168913938884F0F2F31CB757FBE1807AA32
542615C7EACBEF02A3C70B76B657A11B4010316F103AE914780CDB0D68FC2A1B77299881348A
2FFC7DDE814E33B8950D063A298234DD78858B5CD426CAE70D6BB3C2C2D68779BD65079A562B
EEF0D0585F10AB144507B191BCC1378D6C39E9F9B8F690C59F13B541AFCA46CFDE1950BB0FB4
E1C875BC6D4E46885BABE609246ED831FEBF88391741EBC271A3FB1459B2FF188E8154E5B321
6F8D96EE12D66EE3A7EA92FC7A682C2A8A5CE1AD403972964994A7D875A8E4962B29B4213ADC
2A4226026441A0A78117CB1694843DAA734BB00F706231339EADFA57163AD47E2904B680390D
43A03DD66C809516F9E9BFF08FD1356D99906B51CD059A4CC42E000F6E716D6161D7F540B78B
BFAA9B71F8D063714321457055D7FC5D2D6715F36CBD718843FC8A5BD2681FD78FAC8B2D569B
1C85324C49ECDB618FAA1D0D4A1ED480B790C8B91F5F41A94BB7D351659AD3C73208011D9815
ACC432455CA6FDE68617992FFF3ACBF624B115E2706C7B59E1AB14B07AD9CF6E133E96345823
ACB0DC9E741F6EFE209CB421C88D674106A5152ECDD39E7DD7E364285D303E3B3191A835AC98
B0085062C1B6F540C70B015E795A699F80BAABF2648916304D88F5CC6B227172B415A76FD97A
452A20666D041C65D582D8AF60623D39CD56AE8C2FE9248E847AF48ECE5B93B2CCFD44E40363
7344F1647A71EAE6DD93DB79E63F12F6D54E2F221A6FA3E989FDBB31A08B012B7D086F907F84
6F7B4DEFD5DD4280A8BF45C0EDE89FA2197ED7FBA823ECF0204DF48D16F68E3EA6816DAFECC2
0DBFED24D87D215F9E9D47FF9C74A6F4B001A0873F4E8FB1B44F55F88E0039921DAD5F00575E
FB10C1D5416E4C6CEE87256ECB0144B8295D7750091B7A79477844B10A3121AA89217AA83AB5
404272772A3FA4018F99F6FCED80130685A59712E423BCDB1FA71BA74C144F05ECB997DAF87C
2A0E4FE7E89C0F9CA82DADE5EFBFC76F6EB7662B2AFF5C2999979F663594C662F932B8F520BB
EA0B23EA1918BCD6593DD5AF3ECC2BC8C6A8134D2274553B362E54A3689BE99BE3AE7884CE27
D4026E0073324485B921AC1B3A0F4E4A043BA747EF458F75D4CCA667B082B167FC09B9157072
110F3642515E83CF4BEC4380EFACE753795DCC7D8329D1B87673C2D1F1F0D46C3E5196ABAC42
32A7A526EFDE90DCE45641BA9F0DC547B2E748FC576A663878262A5C25915D9E0E46EBC98A5B
CBC2383A79D03D03B9F7EEFA1B96181A08B56C620335C5819F877C1B52A1AE83664B21AB566B
278F3E216686DE8E522BE3BAFA7BD2DC45A2BDB517CAB22789467C683F58F4175A75EF221A26
04E3CE73FA72986A6B6375A8F086E622B4042D285595295BC95CBCA06A89708F25BB050AE446
AE814DC984311AA296B4B637515B1BFDB076CBDA94830A04D7415E85648D8B9ACD75DB396171
D373234034DE22118A612585DFE90207E979BFC630F4C890FCD62C17ED5B05B42FC5F41590F0
E2719AC55205EB81EFEC0A0319CDBAEB8E593F857E6948BF7261638CD9C21B7937A11B8A1AD9
D4FE3220C03499438D0E95244C9B1A359DF497A2DAD2ABB1BCD68DE427D503A16D87B1CD1645
53907FA63B1B5CCEE5E811DAD3D459CDED21997521D566BFB63298030CC53E9D5FDBBA67A042
49DF56F382D9FB03EB8B40B1DDAFBD21A5E7801B130DF79C2BF3808EB24BDB2FE1A4125E1530
B4E4B3978FC020E63A210CC0C1026A9E6EA7DF7EB5903908A41B56F170327D7C48FBF64DEDD1
93427A89C5C9F5C781C00348BFC659D12A8185F6B7BEDE00D8189ED019703054B4B15C454CF7
15FBD38939E9F7695AD745C1D23BA54F5C3833973D5529F2EAF4AE74ABF9B1ECC83FF48A9096
5283A5D9C8C697542983EA09118C8FAB68781A477309A59420110F57437A58C51358226524F1
1D1F3204006BF38208F87977530E4C36F672E58DA728FE388E7F814AE2B3E4A26AA1735EDB14
525D7F262B8EFECBA8717B59A6DC2F0E36CEC8BC1D7262F1E30C7C5716588538E80638989E24
ECCDAAF151164DB4364E081A8ABB9031B11074B8F3A44E6301DAC07FE19D958C769D79D2F0EA
00B9D84FA77B29DA250D16B4D5A3592253C423089F5ABD0CBFECCE1493FA58ED14C6E4AA43ED
7CCA905B947D1CF8891508F43616207E8E262E3B35EA00DA7341FED19C19374E3236A4E226F3
201B21AD68E5A0AF6D936F62A10EFBD6583BA422D2F8DD3C90737483EC63167FBA9C0537E342
B9B5C6DC03627743B7D3ACFF22F1ECD4DEEB1F89A9C3ACDBB26B891647BB16B36F94BAE52D37
F0DE80F7BE722A3BBDC3BE6389994B5B340E2C5B3DDAA2B99F121B3FBAC51655940550DC8961
51507FC9BE0D67D6E328D669CD22E0AF20CA846F357A59D681272B27B20F88008F4D8B7DD915
8F793D05473E75F0302DFF1C0940098094F57EDD1B681548A4C075D0510F1B2B4EC5F058F6FF
D08F8CD51084E9385802CBE514DBBC015F670B6BD587120ECB173821D4DA64027E6C4572A2F4
41408F6C8D12FA159ADCF5B821F7E51F3AEC9572D198CBB446B4D57849AA4353E36D298A5803
65BA8EF4CCA88BE9B6A1058521F568FD4E399193CAF25C5C7FD91E89E30CF7D715B89BC1556A
64D1E348EC0B3AF17AD16A1BDC34D8FEAE1579A234E29D60F0096FDBBAEAC408A38749F05B33
FE7D38F2A1E1C59190D57A6D8A53E1FD661D07AB5C9A486EFF8E4E3085A0DD5E5FDD9DFBE19C
E102556E147E40F28F00A892099C985E6BC49B5ABE8819EC5FEBF2F51C832D4A573D42C60441
42D2EE269F4E9D00AF2738BE1DD308DAFD8C64ABADAC79A528B6D0503F4BE90DC7790CCA4254
8F6C0C8153F35609B24879B0E4E3D53204F70635BE2AEA09B036F9E8D66C9CE34C0A253770DA
BF992CD0BC8279A7D539A92E41DCFFBB6E82D48F1550B7B4E110A2B3F2430AF3A497AF89EDDE
9D78F3223C2628C6542260F9D209D7B14DB949864A097109C2DD030BEB71D26259CFD522E3D9
0167C07BE5FA624758CE4F6DD2F9BB05168443CB519696BB16F9F0177F63E309CD75E160E2F4
60926409D732403C9712A2815A8D53205DFCF1EBD0CB482907813A793DEE8870950F1A2450D7
606E5723F258CD34DF9ECD540B508E368204B46D39D4555F284ADA22FA5C7C9287DFCDA89B13
96B0F0883C5DCB3A7380F304D08F1177AD30F9DF1C91AF24B826394322DD114F90D154A11B3C
0F9FEF7A51A7BBC056087CCE66E8A8CB29A3ED832D26AA06CF54E85AB63AF744DC1FBDFDAF20
77A90F0AC6C4FF9AC47669428BFF213FB8622BBBCD892E268066CDC314491DE3686E7D588928
02B0524121D17FE77090F443EBE624A9293D2D2A74667FDA7ED2F387FA8E13418A30A01E9847
79BF72E1D621B34075283A8F8AE7592C87CAC8617493D0743CAED9C4C060EC7C1D88523B4CE6
ADE8962B2F2DD1E82FEA8CE611FFF799F264A013C918460EAF914D5F850DBEBB4588D7C8B968
134DAE1A27FE61CF03717808E2D5540BC3B223925EB49F303498D212E9C7A019E53C914B29EF
1B43FE3A076D9BE60FB2C6A8DDDC9D6FD12CFD21DE244B29CD672F1CA62B23275E192BF26781
6228FAFFB7CBB4EA0F93B8D4A1E07534AB638AA0383C44375FB6A22ADE028DCADDC3AAC01BAD
A612EF3E8F5DE6004E98611B434E44746596D4CB43F0383A4034110FE43BFEB0A5DE7E1EA7F2
32BD4DDB54BC3787D4C91D07D67B0AC954BFA577E3E4268D576AC9D33FD0FD4D3AC2A51C5BAD
0668D90D133E4A3E46176B082D51658F91F89EF3E66B165B1417C397F0BF48E6CB6FB1A4B012
1217810933D7D075D1F35E2845B5C13398B3F0E6A966944FF39C939272F727DDD57767340E58
663808AD9F02BE01A31D6B539FF8173AA32229DF1566969F3F0382AA4F226BC2A860BB0665FB
72A1C0999011A954465B22D6955A38C73897E164A6D5630885986D0C7D29E1EAC78600AF08F7
D05A18687E7DEC72A042353946192CAE73A88FC31A750BD93BF1BD0C86C24A11F44F91E8EA2E
D77C8BA2642256FD9C683BF81C1BB2102893EC70DA0995734277A0703A568E34EB54C1EDE675
C76288B67FB8346D17E2DE408934F353638321A73AAA5813E287783ED58E340AA204E6FB5FC0
BD913120ADCD5EADCCE3E3096C61F701C6AFB367DDCC13413B91308A88A8A8DE428AD14F3607
0B6406E3C26CE69A6FAE90B3E8A0EE84F28CFE2BA9DDAC21A36EE300192564F79CE9C03B0523
126D10259D3A8EEC4B37A4F11484DB511E866D843A538114EC8F512D253B074345ACB36E67AB
AA65677B230314B49B6C4FA12ABC501E327C89B4DD0116027E2C5E48D8B3F33BF0D27F19D418
50F39C38DC8C514668BBDB60CDE73747DF89BA7D8D10AD2F0104B6EB12CC112DD0DA279AA6F3
A5EA2D9FD41E1B98678E3B69F76544B305F976FFC56AAE5623BCBC7756F6933689ACB649C230
D2C78DDBC7D6D779A1D89BBD44F92F6E277CB8F5FB641B752BD720215694CE0BA83E54BEF683
CA62EACC7E418F5545CB1E029B364948A0C8E8FB312A3F7B54DBE83E54CA2D63021600590DA1
8211C41DC19A8AF58BEBC8EEC2AF347DD5712007E000884EB55F415E008A0ECB0ECE3B3BA8E5
A8CAE5182BB7338E6A430424BB4D1B02062C8E94AF9DAE00DB64BDE19A2718C562E164900971
7F3DB0FB1ACBE4FA7443BF4B20A127102201C92E6E2D4A63344D09E3479D7FD94F028AD24FDF
D6FD1FD992CDC27823B44928CD8792F3978E8FFE8C0D23315D2C838D2E05FED03E9DA7AE6D59
0541DB2BD29406036921108D3C6EDEBE7C0EC057D65DB37918978D3293516E590A6D7A9CA3BD
66F7B10ED5278264A4CA4D42415438945FF57147B91144B8E8EE82FA591FBF042A74C6FAFA4C
DFFA1920C0DB032385B9B4F53594EE261993A05EB151EBF14EEA59FEDD78922739E12BA5DA70
F5747D5303581BBE76CE1664919DA2884FE0E8E89026E32CF0236AE8046114DDAAD6F8629C64
1617C5B163E74F2CFF2033F9D6DF892343B6953043CF89FC1BB0F4B0D64466074DD5A81BAFF4
EEDFF51D46293A7DAFA72B6E31F2C14967E7D057D913F06D9272D2866B901B47CF40F75F671A
22E0F43247C4AA800B4798C11F76F665E2BE64043EE69A3F2DDBB8F89AEE571C2756DD2FEFE4
4DF6E45BCB7F4F559605B7C9330E7E927170A98DEAA26403C12E3AFC095A509FD30C2FA316AD
B89B1CD05D47FD617CC9F9A1335DB9DC3B9A92D6B0470B94622094BE2E1E22A8E971F4F9E708
B01B320A541231BC90DE41490573C306BA8F89AE3FE673AD42CD0DF3EC0AF572FEECE6500871
F1E92B06368D1E19B8DEE85B06E66ABB8545B9B29C5C73AC08231A6BAEABCF21EB5922C537BA
B5D41F9A1EDD103D372BAD0CA062EC7C911632638A23D9EE96F9B68493BEAC9BC88A1047E04B
4B3A33E9377CEAD6B5EB707AB027CC014C4B05A00CF426F55BF5245E892E09D1188E149B6865
B999C8EAC788B4A8BFCA633119ACD1590D4D832927AB7966DE03F0180C9CEAA14F46371DAB37
4ED73B825E861B322BAE154BD8481BFC9D5829065E131940B51BBE8B0B33D06715E0580F6DA1
C384F3F60CFEA43F69E0DD5733EB473FD82036C7A054FBDFFF5074139C44866DE8CCD767ACB4
A8327464ECA92C8F75A6599E1832C409CB5EFD85C87208F2550345A1C2E8992669B4BEDD209F
907FB9A22326EF8030275B20CB4A4EB7FFD98D4E338C8C41D1FAD8514835CE20723E363C27DE
0EDA33A3F32AD08B861E48AD006937F00E46E7161E5F85F80E2F48FDB21CAC82F2E1489BC26A
37D6A104BBF174C5565FD8A061A53A3ABEC8E81E3E37EF67658116525192C26D305BF79E90A1
7907CA6940F2B2E7393CEECD3F3C3541C95643112B429A347973941A01AA9E149B50D60E03A0
4F2600FF80CA302C0E370C04DE81FF68ACF0B59D5A4ECCD132AF4306FA61699E6850D0703607
727D5B25949FA6AD8221CCEA3D1E390D5886F170309C60898C9B003F962AA1BE0FC8238A404D
0637D030434C7FADABF2D02FC4BD1FAB8AEE4FA10533B290AB5395B4A0F08F7C782BD5F03570
2CF648ACA90899CBABD4AD56A79BC92674B259A6B316477F39D26E403C43A2F5A91EA95C338F
3987ED1D7A840F5614EBBF419980698689BC1E24C4342FEFD6FB14D69F0C6C79012A576C4355
2E9DD81A97598F6D7573B5FC5F51F1B20402D19C9CD69BC714A9780E0D6F860572170AEFBCF4
5DC7910D7C521DFEC01B4BFDB162AEF15E3947CAABD0E66420C04C35052CB9B32D3073EAA3D5
5D5BAE74F3740D24770B999593E407E656916F42648026E04B1E8630F54C4EC62176190C33FE
E9FDC8A4FA1A814C0CDC5B1CB0CEF1F652ADF5981CC5C6A8FF1739983161363B2A6BA9805D0E
E92CD6C55127C6278B160E11575859C6096842F318840F4681B9AD238DDCDA218795B33275CC
A265BC912008C68A0159D81F8CD35DF7E58DEDC5EB003FB2C16F14BEA012B8C740782D1DE84C
EC6958FC681E712AF7FC33F0AF557E21412D263689B9D49E958A172989D3FF71FB35953024B0
F8B8BD722407949AEA81E0D53C90A4C1B3646D37E1A71E7B00889C33641B554D906CC354286A
087A3E211510A0224309E75147C7157A04015C02CF9695D22D0B180441365BA1387A24D31868
80D66871D40768E8FB2052A90666AF0B9E2872C8C44842CE0CBEC9AAE4DF1531DEEB1C7F2C65
3AA57C2F7E0DB8788602E5CE3C2D2DC745D8441765672E12D4506414D39789FBA5B91D7294E5
A50F3B1D8DF64F708CDFB5CD6103704B02F6F3C80492DDC7091F852BD227692917E06D62B7AE
E13F95469C5BEB35AADA001595A002B41507DE3EDB7FF56A4E2B4A3EFC448BCEA31304CF68D9
3CBDC17D91E7FE51C64E6A6B38AEFE42FFC967006067673AD1EC4F59B32ACCE3D59F4CB11DDD
62C73D949ACDD9306D8B971C8CC2C897B9579658F0691156C395BC5A8B0AC90145605577CAD6
94540A79C2A342D71C88A39733BD4810A694ACD1698B98C73F7C3DD6B4E3B77EFC6B201FA628
7BE234347178599F7422C74B835D738FEC17230F72A4D33642F9D7CA390262D421AF23CD4B5D
85B9586F1A4FE2EA9DDD499F0F2E83878BD6EAD423AF05D097F93BC0C7450095EE0D41E0B047
3BAFB45A85C9F67DF23A0BC418893B3AF8DA4293A28A215908E91C286C38E1222DFCCE6B1ED2
0C6542F999C684E82B1C4A85A225BAF7507F422D15FDE1B9E692F13F67E542146F26C06789FF
2BDBD31FA54399A771396E73AC5748C643AD11CC8A44F92EB44528164B36F7BE1DDF3AF3B01E
89565D3727A9B76693EE7B853E3EE973D4BF4B67F15A91F079328E256D621BC40CAC8D45A1E4
688ECCE084B4AD28D2A09AA786D23781D596EB5674C4ED7EB1A8F3B723AD7E4920A56AF442D2
1E655D96AAE2DD6C13FBB0B0226CCA4704FA3F13CBF0687F9120787CC67AD3904C9CF174438E
141CD25CC1CDCD19E34DB22E24AFEDBA474E3ECB522AEB2B88B163CD5F08E0526F6D21C3BAEB
7B9B2E8DC551B436715A85E6BF2AEEC33610DE5E2057C44E07F7B5F265FDD9661078C39760C5
366F8F355AA3EF6AEB9B7A66F008172B48747E879E939E519CA3F94A92727B8656B49020A6E1
C9165593C663C7CAD7EBD4CB976D15DE9061C10F689496D086FDEC88BC0F9173EDD29EEFEFCB
BC8A4001D628D7DEB6C4872C6848BFE45FD5F3D169CAD993A845E0685AB409E3B791C4E4DAB6
57308C0324681D4DEDE6344F371573F65A63CF5E0490AE55FB0237490FB1F33AF81BF4AA9282
95E1FBBA88FCB736877447A31E862B56E5D6DE8EE550A25F3A149D91B3D74CD8FCC760B8E742
10CA81DDD825B0F7E087CB91F1AF6DE9D6FA25625A075707567CB99F59DA31B32CA83495F5BB
F381C1646E2C1ECEDE44F5B09DA16E12789DE1A19AE16D6464B208D2DC878694A8C5AD4910E1
30A691EA8C5042873C7746CE511B0D65E901C3B058FE14A5C4BD0F9D9BF8187F3407E22FBFE8
DC9BCFF51A217DDD70E89D362199217B6E1C2BF517B560983FCBFC9890750E093F3503BB8173
33BA7982D8E67609D856D5634305CF767A0BC4AAC478D17112EDE04C0D4EE807C48A699FCFD7
113BBF5381ACFEB58F8569ACDD9CCBB4B576CCB3D20FD7617689F47CC47974365A8645DB6208
CD9F2F85D00262CDFD3D532A26B9104B968CCB3BDBA732CF7DA7112E2958F88ABAB5645099AD
D84D5A8E9B57B12BFCAD31CD2B55E4E4C65798ACA0CA326CC2D83699DE3F8934D807DB584B42
3D74BE293D5D1DF8B058E05C3853C1987BEAF53D1C2C8934E1EE0C742D639ED41CC9EA625340
B889217C03283DD930F0FE28B32E1200814DACEAE5636F9D822C1481A99C223F071A0D52ECC4
3CB4C9011A21A9E41F24FE2A3C621CBBF82087BDA5BCA81C45064DF7ED8545929240A8D1E89D
F968F5B99FBBF8AEFDA604FBEB49474F89BFAC7809F03F43B2084997C45A1915933D4B63BFE4
DCE15228D327162E2487D394B31A187CB52CD3E6E4977FA03654A66643B179FF867252ECC23B
3B47C44B4F44D3BC2F45DB57F0EEE856BD7B9D44696ECE793DEDA96EF82C569D98A3709505EB
B1347A5C9DFBDD229F33DF57A4B91D231ABC6A9BEF04C63853458CB72ACA266B82AE5AC41007
1D1501C251F72611B18033F2A24ECE213331F51A341F7F45C442549383F763E6CD05EB6B8AE5
C753BE9FAB2EDC52C9FA8A5E7B71936F0D6F7F4EA6E9A4C992689D22127D3BC0656602E18B54
A433A54A209B7FA87915CA722D7877CAB4EEBD4F42082BFF5D02FF66C5CA6C4383CFF3625B5E
1D7A7E286FBDD5AFE1573419FD61E6CA3B9EE56E81A489E71A7A47E876AEBC1B2D203458A476
E537F4293E431D8EB393EE2A72A866B3AA14F8DCBBD40A3CB70D33A058F664418475C85CA81F
1C03E57042A3D215955955131CE9506902BEBC9E32F31F8DEBD520373562495766613E00EFA1
EB1A37B9ECCF87036DB234F0A3C4D453945FFABBE5131220E0F0D4A0885E4E15DC818F2ACE29
D5DDF38A9F6443834A8AC9D7F435BAC03C8E4F362DF52DE3798F46D4B2AA8BF0AF07460ED6D2
9BE11ADBA6989E26A985256D73CB116EC540324DD73BCF9AD2876C08CE047218B645E2909207
A0B6496E74D279EC82DE3BFDD59C9A2D0FD10F8B273912B98FE5C20592BD08A5E48C9EE8C0D1
13E11BC1F28B0589290D92462535289DC5B03D99DEEDF348DE7C56396A0E04913B30CD8E97F9
AA523EC136E9238AF835FE9BAAA90B04B6129BECC1A27AC536B5A2641E66D7743E59167C31CF
6A5DBB8D78B22F4F3F7CB443D96F7CF1A11C66827FACECBA4710DA22FB43E5DB4105B2192E89
F3A61581D4FBB11C4772139A7D358611F2BEEBF9B94624A218AF0273E3DBDB13C1FB32E8A881
FD232CBABF890D98C8C943815369C924F7CCD0C246F900190D01DDE52D3BBD33FB139A665714
49A5A5E9625A6DFEDC464C5329C5482238EB4CB0BEB30CDF5F5D1599859DDF189C92659D6FBD
7AE7A28E9AEF1AE05F5E0ABAC06E9EA9BD4A18CBF04F19A14BAAF9DF322D9165F488C0D7F48E
6E7500698C5B214E84030F052EEA86281FEADDEB32E989438F611A02CE21B5DA88DA9F668313
E2AFE3D22C5505D7E5F0F8710479C1ADF2981B77D4B3BEF0B2D71D292C68703E6EB17726236F
F801124296B39944C5821170BDBC889CB9797BB99077F3D7EE1853B600AA6B75E4640A6EF4A2
7414D9A0D72C3A6AE4338B15AC0DD43173B6A25B328D0ABF1F770E9BD0C707A3CFAE2EC296E5
286EB99AE7EFFB9DA63F521C2A78BB1377DDB1EDB7C4BF9333DC85DB8E8B25D54360388A6AC8
87543222421322F4E96C2D4D9D7C11F02E5F3AD60D6018FB00A4AC6B13393D3B41307514B881
38166ED7FBBBAEBCD60A157E7864749534D6E7DE4949917BD37DAD7960DED8BDCBDAE5441AF9
BDB8692F07C26FBCCB0EA38DE3E495C4CCFDFA55BDB76336EE6E25F03A882F3674A0EDB30F90
165C382C70B5DFB90FDBDD054BF5BDB8C89885B5C33303DCE12C5E6A9EE85740F7887C7EC3EC
8920E5C2241EA8EBA41C3234CBE5EB5D0E819F33E3674C3467C53E79B9307090EC7CA7BE967B
2DD3E436004FB4F544ADC4570D9ECC13F49BF8DB8CA3B736FEF89FB2097BB62E6BDDDEFC6AED
C701D34E6728CF29E66CEB031071A6F5EB6631D6B5B45DC7E501A4DFC7363B6DE0C3E9DB0122
C9EFC8124D5B2FA7F3673070749CE63D7A8DB803FE2447A28621974B5F22F0F1FD1DC17DF692
CAEE180E7124D7EF21F0A86BA1C252A8FB0D4CE82CF9A413C371CCDCF191B73524E303C79BF6
23575AE895CB7DC72DDF373B3C3B737BBFD7B8BF38AA6CB748D13DA0115E58473D367FD01B54
C5C375536362A4592F158AA170A7A66AFA3337C9CDFAFE1E58B485A0A0F227FD2656C61C0745
832445C1B68C58B64920C013D956601C71E23010015AFF4CA9C8F74810EB3927801E5D722E8C
876B966521EE819D9386436E44F74FC8604C2323728398184B796F502D9D303770742A016A93
767A4808793E4BC1044C68C57CCA2138A9DFD2E276470E0B74E95BE8E7B315758282F791390F
B401BF0959A06B9390D0885822171A4C0AAF216724B5ECF28FD57DFB31CD18CA3AF35976BF8F
5C9071958BEE66D2FDBF25E6BBC5B237E148997A7354C683211C0261C5C91C44A23CE2EB0C34
4F22239169BBC8D0C0EEF06FAA7778DBEB82EBF9647ADCA5EF1A855F9B4A20A2546D185C747C
C3953EDC129105887CF30DBB5B29AFC1C9BB720290A0DB8BB8F4D0E2CEA6D861AE797E890CAC
83B24AB9CFF7942D455D5309368ABE63163F020FEFA2D9B709C8771EBDEA6DD264553B3F5CF7
0E38C049E9A62EF4EE3176BFD19698C6A378DC5B164481EF0843F3CE80CF9FF77B1CEA8E3CDA
DBDB058EC9C8B54507940B7BEA3489616DB0DDF359C1A2B0CB1A0ECB0CE52992D274BC821267
59A0DCB7FA35F86A3E05F99244DB8D673400868B6DADDFFF7549769ACB0C699D0D492AB12A2D
18469912CEF2E99EC2E0809D629E9C2E70E727A0A2344CDD5D637B5E8545A9E497C55F24840D
0A98EF0A30E3BD26F1D372E722582981F2B482C3989DC4A20EB7C4DF3F13875B028BD6459B23
F000C625735CB2A21F4130ADE0C9E24E50751748B01AA5CD043A155AB235E17AEE0889D30C26
92938EEEF753FFB50BD36B10880164779345DE088E5455990116C7B431547DAA52FED151C2BD
12ED0A8FDCA774DF1928D9B70E608DD4F1E41781597BE465D07DB6992EB0D672401DB4F4036E
DF614B773C1787CB28379FD8C580FA113447CDF5164410B7AAD24910722C19ECA808E1BD9CE4
380F73EB94B7C90DA086D646FA5715F41F8DC4A14645911CF4466C4933F35B0FC3CA053A3D02
5FC70F805ACF4D3F425054AE2A24A39E92852EB0D5314E537B64D7F3D5EEB0C15986E46ADF76
F113E6215C7616ECB2AFE489671C369B6C202549E88A5296A922FAB0AA2AC138E0DEBA913E95
AF9D3897BED45B4438CD76A7B478038C1D5F80B07A701BF3ABA74934D334B674E5F1A1B4ADCD
B28A84051C239FF54F6673FAF62018DDDD74B2DCC9824A0030219C83FF495A21DCEC4BC7B46B
AA81D25F0E0267E482303A75A57E0F07174B30E30D20DB77C22A8E1B9A8A5B8E3CD04211502E
862653023AAB3BF5ED7427792CC9B7557C2A86B2ADFFAAF6C73A0B613EB8DE9DA48A04AAF052
EB642547C7A4A68F5E6E62280C92433FF3F2F6CA8C35FD265BBFAEBE265304C5BEE42DE289F2
0E48EAD175FE7A791C7E4F3D9AD8791898E59CF47CAAEAD2F153447FE0E4EDE919C86FEDC2E8
A4B344DA381CA33F6D2C3FE4B2AD3E7B97EC9A4297E11C3A070D816D3B17D4F38054FD31B9EF
6508A5CF29DC51CFE31E9DDEC94126B1291F217C7BAF06EDDDEE5FD15E35264ABB118141EDF7
24EDA854A07CC060D61B6F7B865BBE70B12EADC484E098BCE5417A6A8451924623776D421E94
EE474E6248DBD23691B3BB5DC79DFD86015C4E504E931AF8AD4E5B31D828D5DCA3CC0ED49B2F
1A59B208464FB34B970B8D078211641D53EF40395D50BC72F0A609B94FEF0B503DDBBD170D0A
046FC5CC2E2EF321C3CBCBC2144DD02AE323E74520216776188BD42BE847CED4E6351BAD2E10
7CF2A2ECC2BAF59C5C6C201522F9EAFEB7CA64729168F0ABD4533B6E955C90505FACC5D85E38
0FA3A2634F7B157099F315A5C020D5B0E4A4E5EAF34FE5B349BAEE4587FB05797519EB3E3737
C3EB68CCD8243D13065DBF9DD397CA3283F879B9E9284F4DEBC0976AB87351BE2B467394DA9E
FB51F9F9BC2559C75CEB098A3FBD7F47C8694AA70A914501454C7328A8ED6E1B37C3279FEF25
A772ED67BDD631BAD05BF42F15773A997BCC4F66D0C9365D202FA5C251B2EBEC85B8213F543D
D477CD2B096BC4B5A08E38F9AB51544DF7E9DE3D2610819FDF2F0DE3F555804459814C560FD8
C9FC2548FDC1C5529ACC7FB3F379644E42BDD7A72A1473F5869D59174274D29EE5CA0CD7DA35
18BB184EF1D25BF08491EB9F6EC2F8E6FD328FC472B408C3906A585F34443C8BD5319FEF59C2
E4F08C6C3BB228696C111516D7BE90A390F79BE04949366715D9029F3CC09388ED1DC3223035
91A6A2A41CD9165E7135C04813C07AF62B0251215623E6EBDEEF870DFB00D4CC2498CDFBEA8C
B6DE599D49589B0AFDA614DEB7D8B11E6369DDA10291031A0C7EF6BF602AFBFC34B348B74169
66FEF9D62B4681503EF346BB277682EBE0520DBB728B15A3E03E1D025DC97D615FEB60C4CBF6
D54A2633F68414333EDF22F1A7628F1C09EC01216F1270EF05D6696FDB961CC11CF21DA6AF4E
E5CE6DDBDF3FEC42EFD105368D4465C8D5B726C1F7251E52321B2EBB8A2316E7471A9EFC5CA8
AEE99BC1681731D465C5385F2752E2A41ADC0652A48F46F2A09390C91B147E199A06240485A2
B1583969A79E22475A8C70ECA68D4DCCD292CD13CAF8BCD94310A6B84D25BD385D132ADC5B9E
EBBE5A701A2FE4568A5FD348BC689676E4896A715C4C0D809E1B719933324D506430712B9E94
F84BF3A558B5FBF8465B458626D7C43317FD47F60F7311D772583DF6554D695FC4B8EAB89572
E8345CA1642F08AC3A404E65D09978121A2242DE8FDFF69DB980535DC3640E83CD4EC40075EE
9FB82BA5F13FA1CB36F55D0E7BF302FA0BB9F0E1D75BBD955F7A41EBCB296E31D4342F24A4AE
0B44F0FC9FE7EF5EDAD138B3A1E6B175CD412E7E877A2FB737CB4A2B023B148193D4D43EBF64
454A70C1728B4F4B8006A6DCA8EA77432A4A432A346DD5327ADED0381449C714077268BD531E
BD2FA16CC331F5B2ADD5002DC3FD06D6C83A047208BF82D525645D4F57EEF0397FDD3839B201
366D4654F1798941CB1531807E9D736A4A22A35AB536D198972847727EB3C57B025E9724A257
13EA871C57FB185EAB6F47EDAAA3E47BD39AFE724C07336602E957B6E5C60207382BAE996FF9
A59C021F2F52787153D694B42A6F131761DE66891B98E7D7A3C462EC1AA3FA66CB576C1E8CCA
61E9E10D5E4AC16C1E2CCE7B3496421EBF04C0ADCD9AB839298B1179DA89DC23A95DC578A554
279C69E566151E482C607138662C75860CDEA52A964A8D5E8FD06AA569736889B256CB1FF0F7
87F83FFAD695656EC76F0163999E805976665723B349A3EECA090313C7598D57400DB216A156
39055A12807EF1FC9F4FC9F498240C9D977FA78E36CF483F676CC59643BBDFDACA56D59949A1
CB84DEF63AED2C20DCDFB5968689EC7DB2BCE1D79D300A6AF4A9CB50AD906FC410AEB10076E4
FC37FD1BC509C22037F7B8DBF0C8733D95D744D50CFE966B531A934BA9F6D5EE6DF802CBEEBC
AEF2F7BF747B33D8A8EFAA29F22191F4F675CD9218E5AB3147D2E0522042A3C12EFAAC92BFDF
9C38BB37BA0E485D39C9D1DD5B39795DF00E19C459BF9CB7A4455A1A0AB6F522BCF7D4B0C739
3FAA6E33C6D9772D8CCB4AE4874ECC6999163C3841DD1EEF54E21843CD7E3995903F2BBB5E45
DCF8AD81BFD4069B1BD68295ABE9C3D4FE28F5CB88DACD3B808F0A9278148D79F9B3B3A7AC8B
344C65D4FCF37B517C64957303065C1BA77034B72D5C048C6586D9F568D52EB1301EE0D07FF0
B005CFD50726D3AD1A0AF19023432F315C93FCAF64E3ACA7029D8C98569989C8B2CFFE3C951B
625BD8390C25BE67041D603136B9870F1FC959A9E4CBC64A8A3F7FCD349B0E04E8B4F588F4EB
29184004E249D12E98DADEABE61D91CF3C799785BDC438C1C4C46BC4E7AB1298C4BDEC98A611
4FA01DD1801CEA5D1EAC4D5AAE3F0DFF73B0028A9D714B778913D4B3A733F9DA599E36FA43A2
A92F4F4C294B2CBA3EEC8AE82BD1787BCC331AF8096CFE42C2F723FEF5984273A69E851A6EB6
C9915C7C13C664855E56C04B2FADD6AEE0F26A44C66D98EB928F261B3E79C2409F77FE09E308
5A21F806E00DB4297659F8380C5828DD10D8025E9708923F90F494067450BA710AC2D579CE23
9F498F4FD3ED0DAB3B29C3AC70AF6D91E3F1796027CFECB939BD2F89420C9202A07F42AE794F
E14741820D6D8599DFFD9D86B4AE1F3928EFC52D9E560C9E36FC9EF7B41BEFDFEB08D73680D9
6AF9F6070391EA61D36D677159BF92906B81EFA600BE7AA5E130DEA9F6E8B09006C44BCA359B
FB5BB04C47678A7BEEC1A20F0A55E46CC4757C91683D0B9970B6E263234CC7AB727CF54C892F
A2DA3FC638A0E5D7EB63EADD59CD99A1192BFF63F91F747F66E8AC5B9DEC88DB12B613F2F4A7
59211D2ECBF96FA1062F5A3A697102C9F777B40D8E22BE613F209B2C2C350A24D589CFA1A98A
5E93A8975F1E37AA0CE6B34CEC576D7E37BD0EF873274EF764447879340DCA1DC9932678CB87
0672C13931DA6BFCB81AE0B9CD88910D71BB5D4BBACDB805C75E08816FB0161B97A0F92F68C9
5B0AEF34B1EAE4EB2A2A264694CFB355F7179833E5B8FD25AF5A9FB6C3F45B29506C14071E01
563194BB9922E8D7EE4600ED6D47FE0606C20C573A3CE4CAF4103416D40FDD9C5EE641C393B7
5DF0C209553E28423C6464E1813D3AAB84B84D78197550F50ADA7EE37EB6AFB54421AAE33381
89C9F315E0A3F9667293013D4FC19462B1B3484F021B769F25EC77C42B95378F737B251E4244
04F273415C3AF2E125EE8D99FEC2971C8216DECF521B3C1ACC792513B369C40DE93A2B033EB9
5BE49362753C6D8B956B352147608D6DFC5FD4D6E5645B960E41AC1FF635369BE5827A5BA98A
0671B4E87A178A7B9DE73FD44430185F33B6B4446CCAAD4475C5379956613FF8B53788AFF5C7
C0BD04065EA6B2EC598A1074606ECD8AFCE6C8F7C4EF2D091A4981004FD95E6417FA6440BEBD
FDF019845C86C9C8C6831A85BD0AFBF6399F2F8D8BBF8A7A5E28FAD827B796E1D29415F8AB8A
5866AF727E3A7963B74BB58865F1DACBD787038F1116E98625A04A457C0E1DC2A42F0CD2DB80
4E3F46DD916104AD1114323DE1F5FC9F3D1D3C277D6DAC86561EBBAEEAC35042F2E62DCB09FD
EFCCC06A51061187A75D8D1CAEFD6B8738F672C2A2D1A6068BCA91D3CCCEEDD5BC93202FF55D
B0DF6563390AAFDBCEF57B20797717478B89F52EC7897D54FA78ADFAE0C48209650F3290B79F
B5A933ED7E0BCAA2C0C09A68812C29C66D106B8D6719B5916122F7EC14804F169DBC43CEB5BF
EBD0328E25B2E96B35A7CB8D0E6FE0A714576C5F602B2305D4EE8209485A38065CD45CCA1F68
0B3B95C5E5B7F333907BEF1160D7B98F6446B3EB5A419B72AA240A526009C9E1A243E868FE20
72C3CB790AC815F1BF832A2351D258C1CEAD60A46216E751DF53645827BF020E14E2A8F54F59
1335CB64EC16B26C452ED5CCFD81B3871D380B689A62519627A1ACC30AC156D04BFCC5DBC764
31AF55CB8504F8A848DF4D19F5634141A6369853A9AE8EF2BAA91050D3AD6E891A62B4DC0F64
7F125DA38053E17B92AD02D4E675EA4B580474C223AB4C82A61A8E51AD915A34BC289693F238
3F5304FF76ACD18193A036065FC90F3F74FF964521E9D00457AECFE4CEA285B62728E21B120B
B84DFD426132B9FF102CA09986E7EFED65706B46DD4739A7D44A290379E3B5A80D937018E081
F7FB57ABFB9C621C1F03A334A6BBDF6A08073E3308D5B9485748756E8CEA0F100C292FA9E712
2778333198B3181366E2F35C8E3727BD68BA143F2A7BCE6715E3517FFE4AF858C969CEEBE9D3
B0DF0B45513CE373B2345BF019FC25AD182D256644E836CEF3FC83F5EE13DC4E57E2BC1BB936
AF8B97445603B6F42DAA6BBDC5A7B382D6F64479C2532F5B9AACD85B0D9199663935B3548D0F
38CEE61504EA26737EE2AC186040AB43732B83DFBAF183FFBBDA9EB41BDB425F6175865C00C0
D8D91CE1481DCE2132160EB143EC76E45B9FBEEC7EB91320C7D6038985F57CCEC56ECBA5119D
31CCDB75D42908C606D550818FA00F884291E359AA0D84CFCB3CE0A322D711AA40520C964BF6
54081D0C3ABF19F36E614D67F0C27096E277F77C26498D6E7D2FBCD9BC765163AB5563354A64
5EC13C93EF7B2009F00C533EBB14C6C8220E6FC2D41D248885D131F4E677D4021E5FEF1AC8EC
742EE7EBE329BE95F3F1B4094CBA33B3283BFFF1DDDBC6BF61404F3C1BE8570D0B27C0318553
5B4E685A312CF5E6EAEFDEA4658E7388132EE3DE6FE9E4FEA5E956E48B4A738E281AEC651B12
A3417D6E1D6BF98326C0EF135194B5CA66682EBFAAEA521800DD38B686E451321744C866722C
39AD0D5C4526B6176289D7D66A6473602E72734EC03E3B88F7CB9A82A8A4D1922E85B0679D19
AE159993E9844008B3723491AAA066497E8739AFCBA1F6067A9E3A9EF4EBC3D18B1CA501B45F
787199BF18141E58D73897605F0A5BB66001B941AD42C8175AB8ECBD77FFA213419D8730C7D7
08A9AF0299650B2F40B07438AD2D286AD2365C71A3892A1B0ACD7F0942397426D68A09E564BD
9F3DD9E4FF5ECBCDEA45D2C8A8FEF41150B0D390C9637ED26834D2C8AAB19680E50AD13729B5
8F1FD1E60F4132575D0836C812C76608F6FAA47CA76CC744D9ED2B2FB504755E2BBFAD17E65D
16E33C9BAF3CFEFB143E4CD102A6E1AE57221F4C9090983A61196CB7EED63538B8EC9EBF24CC
59F79C200B8D87203CE7CC6D5AC0DA2008C5973422C593E8367E69CA0CCCA70BA930FD465DC2
5B35C201C6165D5FA0B0B2CEEA6B02822B4B2DE99E0FA79B1F85D8ABC8E05B0151CEDC95A6F0
762EF425F682D9F424A2FEDF438C0F545155B9A62EA64666E57646406425F59A6396DD449A64
B4D4C7A9D94A15EFF6A1613A8C34DBE77108E9E653BB1D25900A6DB95B46E08906DF3D1355CC
090FEE70B1A377747A45AFF889A69FCE8AD5B8BDD8C4B3BFF9437BC268695461614947C7750C
7942D17243ACFBB8568BDB4051A0A796E4E0E83E2F59072A87BEF5A9A71D753AECD10A7E9A8D
9FB9145200C541396E6176E0C33B3603D9C669FE983F6483B1F502D256E28DCC528660E57528
07B524A4A1CA46C94A29CA1EE8FA77E3E145985EDE8233D57238480A8A65E77ED3D40A4F0C11
E8FD582398B1BF0D6405716A4621AAE65491864AA035E6E5164191433D4739BE9B7216E1CF3A
AEA646194F679CC0EBCCDE96665E55F2C7B5AA2538B59A39F3F969F12D4C5B193BA98CC998C6
9B6C7B37578792208B2846D35CA15C3CE3CD487D92945EA59B3B25BDDA864514D8770E2EA69B
27BA296103C56353AFF5913FF9D0A64B7F9AA68D4DA67851464DA2FD45230DB839580301B89B
F1599F69E73984A957B8488D5A6C7B24A2C66A64CB3E6E57415BD7967FCC48334EEB4D54CE7A
07FB080F99B3EFD39312B60E1AB2D3592A263C832BAB2C358B6DDC09B3DF748DAF2713599282
5123BFACC654FC3015008D0793487C89462F5B0750DEA8D2DE0F71EB88B8470B6B69659522AD
602C218B719F03311E963D9E88FE7B57B143EDC15FD6F32D1AA7DE8021D045CDC66A41115C0E
FE10FEE11E5E4EE83FB5CC856EDF767200101483257C631C23B7D1F12422DD8225FEF419BB3E
100303CC0DC516FF92301CD5C5B600A689EB58B55ED56F89BE67C3B3077A6E79BA76B21561A6
14AB9F31F2D384D729C58B6BBD9A8669DD177545E19A2FB9FB11F0A82121CA198CDB58325D2A
6ADA3F47DBFBB670A98FD82A0D2F4C8605B4F5B8A4114E3E054FA0C579A8704E822DC5ED27C7
4B769D7A666ED48A1224E829A580E84EE8BE56CDD488913F5B5E0B7EFE59DD5C97627E55139C
646279A2E57138CE98FD8FD979345CA0888A29270AD312CBE0D777FE99A1B738C4C91AA2AD5D
995B77CD6C9D42FC6ECB456E1745CE6C95C4DF7B23E89244BAE6F524D1262EBBE631AFD39EC7
9E4FFF0879195078CB88DB1610007AE087F9E326FE1D4E8BA4673141989FBE860BCFC561B199
151722390367C65C6B1CE7B2298F2C6C6A0776C6C5B26FF726677BF04F6A99E56A3C436F0A09
A469EC71E8A58F0211888F3FF770F5C589A8DA0E320AAD03A36555C1370DAB08FFC47189D84D
52791D6CFCBBC9AA147286ACF782F594C314F4659CFA953E4E8E104B90957964338C39A97A6B
440CAEF16B64E04DB2131DCCDD0FEDC418EABD3A9F102594757EF3E29E3CBF69A7BEA78F04BE
300B5DF41BA52E12128E0953E6C2680C53870EE27B4D85BA64D673D03FB27DC1303947C7A1EA
3419AA5EC56B2B47368378E8D2417BA5B0D9ED54F78EE3AC9740DD7E77DC2D0D6913C20619DE
F8E160DC534E4FF87C0BFEDC2938101E55E2E44599F27AB1E344335352352188F9BBAF006F58
082DF83632F1ED5D6EA677294720FAE0A5EEC7581762D4664743487B277C2124DB838B8D73E1
3C62A6003C69CC7AF97EA4FACC316953DDC3770F3F1A5DB4E3AE71BCD1A5150E80BE1DCC1806
8501E74CDCE299E094A489253FA140A5FF8859154767CA07A76A4FFE8CCB1E70C0CBDE5F9F99
A59CD408532DBDC2A8481FA300A732A9BCDA01EED59914479249B335726475695BB218BD9D7A
32B5783835BDCA8E2624917E8B39113245CEBE014CF060D4F583F2E6F00F0A708FC452DB04AB
ED88D49290C6EBE8D06A553321282D3ADEC8DE2D712F6CB7EBBAA3C89E2E910DA121352A4FDC
BBB8FB932B220ADE4EF01A41CB6EA32D10A05E10D152B0650F5712A035E6B4C98A575026A95F
45BA6022E3AF9113246F541B7CB6D3037C9BA013816FCCCAC25FCBB186D8593FA293F9FB3972
B4F240EEC4D60808547748F93C12D3541B058894A5BFA0DCCC08E587574F2F5E23EC21653DC1
D65F6B79EE6FFB6BB4044838FB6BA3DEF1F3C11BBF80548C5B68102C513CA572EE12354280E5
D2B67C1F475DD7C436DDBA9BDD0CA3BCAB62506B58039CE8151084E1D1C17F2B3977C58FE2FD
4EE8590C288BA63AB2871D5BF04686F9B22D1E6DCE04A22FBECD1FC3971011F08CE7AC474229
D659A8AF49AFCA7D70643D18B835063A38D80B11B5A01B5FB7AAA27A2999ED348DE62C49475F
C1B285D4F8F29A658700D139D3E82CAFA027527DE3BA2FEB989F09CD9560AE6810F62D8F8421
07011BD509DA46062894A14C5825937960A6424CC0868AC4912EBC4A13E00E10974729D7C9B5
D2689F92F573546B29AD861900C33C6938E9DA4158D971CF1F82E9122D20E137EDDB812C7F83
4E6C91BCEF7EC57BBBA041C5C7FCCF19CC1EB16C9CC1BC99E114F3C1B40278205C9FD46F111D
786D3E09B54A399574A4E97F874CEE4BFA8277BFE16D9A914AD34C088EDC2A8461D84B4AA348
97FC4A15706093EE21E599163273D9F3493E077E7925B1977F847F714DC62CB00972A47ED786
49436F3909B908748BB1A1B6309A44E0F10D638DF86B62AFB18FA8F319B60CCE3A298094A565
5340A7BCA2E97A12E339295EEDDF250DC8315ED5A0D27104800B2D7D19973C3756D02A5880D9
DE861E82506D0210B1C41CCA79A08A077783DAC1F8CDD32B851EF07470DDE47FAEEE495A38C5
4E33536CEDB7FD12F8FC1CE2733747651F8E877122312B79417824FE0EA42CA128E22D85C025
AA8E2540387B6FF5FC627A25155D3DA30F2499CA76B7D8A1874E4B38D43231A6D4C74EC82047
0B1A8112DC936841132DDACD87034DD0C420C7CD6A82242DADF8A664B43561C2C0F13D324018
47580BC0FED0CD3637031FCA5F1EFFA8C1A838609EC2649CAA2A5608990AB64EBA24B7B2DECF
A6070CCA859AD570D43ADA3EF24DF280DFBD86B4C89CB0709531E96CC969522F7E138D1A590C
56AFD6F8039DADFA1FC3063E6F5B5421FACCF951418EFECA01A6504C6ECB5CD1471DDDB77DD7
7D025A1AE6ADB381D5DEAFEF1E2D3CB7442C934F7D8CFE122858EDA43A324E6E09909068F9D3
74BE10EB263494B7A1F9B29CFA91DC4E674BAC9C90121E083466DCFFED7DCFB8A124497C762B
68677F949B8DFBD3F75E752A77E51D9FE3FC5C0AA6988E15C8D9181A0AFD43DD59AB01BEFED8
3DEDDFE1F9624B1A23AE2ABEE75D74C2CE6983ECC17499C810744C626CCF72659306895F1181
C37627351050C9D4250FD3543B315CF9438CFA0C2204544EACB38642403D630B13C5B8EC0D86
27F1E530CE84F8CE9FD628A7DEBB55BCC0BE2E940ECCA659C377A9D61FDD8FACA3DBF8538728
9FC85D7F822B4AD6ED303DFA2F0062031F5361EE92C88B0DDC3D0473A2C8C8D598B54B9E9BA5
782D7BC7B6E756C13BE262CA6030E12AE1F98CE7FC060B3C75B3F9914EB1829806AF45C0E351
A91B0889B407329BC735C74289273DB2D80A64D9E9926C6E7EE85B173CDCA5CA81C49A93405C
6033E04145208C284F7DA7F9D8D7093D760A07FD48DD92855E0DF2E78347200D45C950A17F79
56F932977F07E81DC01713DA0273ABA5F375FA35E5BACB9AB264B8C5B3CA5D85AC907B8EC1C7
9232BDA1DAA755979BBBE971A9FE00B93ADA37038437FD3ADC8AB7AAB824532B50F34A41264D
E0973DD8E70D9C7B688188AFE0A25B9C15E50990493BBBB36E68307D61F5673B4356F9C6AAD1
167E1915F752EC2085763BA31F3ACD0AE57B1E88A89BC4AF0EB7F701038E1FBBB223E592AC81
E67FE306DE7F9B7B5F7BDFA58DD338496922BD72D835992A660CDA654CB7C194BCFD39459B42
B5C64B4D5BAC18F09DF2C656AFF2079B80EF1210B2A0593531074424FA98CB24626AFDB73FCA
F5C0305C8EF1DE2B25BA906C6E5E08BF235889970C4D9DCF3D747051E1647152F67D386CC6EE
DE511D78BF2929AB0563496E18BA42FDD22ED69224F2E118F97EFED47A407EAF593DCAEF17DF
4748DD079D3E3C6CF2C9E7DE4C011F73BEFF6BFACE576F40A7FEE3F28096CC49B12AAA643AB3
772D6571306276A3277C901F05A2DAC692465799A5A443019BF49CB9FC4885A29BC1141FC242
B48394ADD9135C98C09AB3C4F95D70F9BABC3031DBEC15F0B884D73CFF0CA448B82C0C7D48C5
D2A948DE4C44EB822046094EE9480B9F8C96933CD2D9DF248A4F79F7A6CD7B1F53805EDF365A
99000FAA55DA74C8D00E7A4E68A49CDB94E872C8CD0AC1829AD471A63DF2CB485F6D40012481
8047E2E9F001E9DF715D04FA4669730CD8AB1977A157920398C25FC326446494D410A7436382
D7B4974B6D91F2CAC05C15F6E554B6FE9ACCD3AB3A6B0F143EC82774AE7DE962ED2C8CE1B2D8
592640E73BA5DD9FD4743B7B982E65D1F1FF9FC418FFFC0878BDD2237FD99BB86750F17E5953
60861F4094989F7B127A97B00820FF5B9E0208EAD330189561EB615B84E73F623D43A21AEA8B
08133A09D7B0B50EF1F9439CA0ECFC17CE4CD0A7EFCB3A9534A372238CB9C48AB56032FA1BBE
CBBDA02ABD4FCE5C74CF1A21DB2C56CA2546B68BE0062A6E1194C5243E1B51D1DA56A3B33772
2372A504037C881311B0106C6DCEEF4F5E99F29E6BBCCF69E88FA6B4628091DF4005C7485452
7717CEB0F771C5520D0E8A6E9E1BAEA2B8333056E41F1ED8638AE2B9502444ECAA492B53C847
45D7F25A43DF8A637DBF4270FA0C6ED6E22351692DC37B2E89E73B217F8952E8175DB49CA80F
FA20302D74838B145B0180A5EFEBB76A15EBEEF0620EAE4B599A2FDEA37D95B3AA6CBA4D841E
E5CCEB5E62CF7AD26381AE2A67E114EF517C54ACABBDB05DD9A469D5D844B2D951B1250C9BC4
3E78228FB255F2B7C1369E9CCFAF5F14197936F794E871EAC1773D915610A913C1BE747CA4D1
F5BBD662A88DF31B50C62E60B096E603A38332BDD26199DEFF54025810B6129BA9112544FCC0
447D6C2C04F7CB612F0346864947C0FF26A0C3FAC6CC931D7CC1694041B6D8B7EABB00C28AFB
7E8211D06817A3D83DCB82AA90CBCB7205CAEA200414C77637FCA46BFC2A2D95CD3F970BAD20
311C40B2758172153C56A078B0B4F51DEAD18D45D14F0571E5C7A1E9A52A4147B9616167C1C3
D6FB50C633FD27256D31915924E2BBF53941D9D3695E1B8D2C967D2AE9595324070038162121
308E95453F979916FA18A734D6E38063C14D62E681339714C3E9B118ECFE97C274BE2B1E49B3
B3EF6DCA38A7FF8E4EBA868500CED102BBFA2584D707C584549405EC333E035656CBDE6270D2
0F2544177588DBBBF22B24078711E3245BA1A5D8987B967DA1D2D24D52C664CC0C00BEB0DD7A
FA2805058FA11D5A076692BEE5D9952A82F81A8A35A7B685FCA302614B43AFB7F28D650A4608
4D081204F87C10B4E8F31C1534B3B3AE28439376DBC5B65DA91672AC4BC471CA97CC4FFAD1AC
83F7FB60100CC47F7960AB9F50D6FCB9469BB07E4962785107EDC8A11D7C5939445E9B44F411
4FCC4665FCF7D010BF8645F2BB0C4DB276FF547C051075456080522047A86204211B30D0DE14
8BF9C99547E29880ACD58D180A3C1109827CE75C717FF54FFD0C7493D5E96FBB36305F7791B4
5A491B6D10EF8582985A9917C42C6C3C35481B9874C482BDC942AF2315649518FE9E066F635E
B6B47531A9FAA61D42CD1CC7BBF24D8DC8B85DD65A74DC3A51A8425F47B4A7B69B3679E7E770
FFF200933C58D9ABDBA5DADC0968771F9E9D8DCC4DBF96A9D95101C9F83B6A4AA460E4B67A59
6B7EC08BC4DC207C358352498BCA3CF64E92FDCF31D66481AFBD2FACD9A569FD8EB2F35506A0
08E4C6C954604477495E7FE83CE48F4A1CF3775E10D3DAC8F894D95CA791965AF07F03C17612
F0BAC9E681C9F90BE6A359816C27CF8A8AAB49E0726FAB1E4198AFF4B58944EA9209B9A61714
8291EB523520F22A28CB7570E11F4FF47316A8E783BF55CD9D514068576524BE2BAA8AD1D4BD
AFF26BAAFF65A7F10B913B2959D64E7E7BF01FD6A85850382A435C1044AE9C6C6092CE8CF511
AF992911A3A056B2D1B968859A26DA0BA1931D7CA4E3A222256B52E3A7FCE13DA3A8B8D891BB
6B3A471574D1CD94C08D3F331439DF0B3B628D69351BDEAA8EC7A1414492F2D21693C7599EDF
513D3175AACF5B3D6229F1D47167838C93E2ABAB8519D754D6C49712BCCBAE9AF841758C72B6
345B8FFA6A86C9416036430D0CF66BA152095F9445D30D6B04183E6422167FBADC1D100C3822
3B302A173193F57DF346DAC5FF800F60D3F85C1D0CD61E7313CFB5A1D1A4EB68EA11DEDBABFF
7DAB695EB90BCAC1B0C332C7C87986779F6E29BE75A2CCC572D8EEDE4CC03ED28EDB49FC5645
58695EBDDEC86C2CCEEE1AD7515ECB254B62DC09808674836186516B927F4BF17E98456C89B7
9B67455D3FB5FCAC47319474928015DCB0A7DA5976085E41068E56772E770101D07585780FAE
00B6EF6E66D203B148EEC52A384638B00636B998FFBDEEA2041DB232CA9FD24D6B49E267C6E4
F23DF648D83E5948A361CC3921B84172D727E6C75615A121CA60A6355D521744493C96BC38A4
E9E29345A9FBC0E244E2EE8AD0554726465828E532F606983DA2A6F9A421AB1B9B149335395E
9D49FB36A80C5D7A9E51F19D5A0568EBD9C01A2C989123F9CE33469329F8149914097EC3B84A
1E557A614A455184C1CCDC17C45664BB1A8353EC6C9C04D219C4A58AD1E048027721E766E525
EA9F2CA909E50D9E98731315F37D7A9EEA606E642997CA65D1867190476CD4735DFE89F9C080
E2E21A9045AB22B89A49B9AE04D29EB7E86BCBC38347881656A7543B35B8A1CC1E9F36A5AF0F
2B0686F0176FFE8A70DC8F0AEA7A8A602CD4668AA13EDAE3C7565823A2C3B8F255142AD41CA6
E3849E1381DB533DD664C5CB43071AB7FB7235576029652669B50944F83C09D1312E68B443E7
CAC21D3B44BBA90182DDFA6606181A40CE8A52ADE608DD6979C5BCF5B02663EB211029D1D896
85A0945BD732B46E0DFD66D6D2B486F8A21181B562189D892BE877B146677259E25A855E971B
C11246AC4756EECBCA899FEC5D0C938197C3F8426EB1EEC083B40BE472C925D4D91556AB253D
39906F3447CFEE0DD4484A71DE323F69D694CFB85AAD9DD1F9B4701DA649A696E6396EA4F9B9
B4F99FD84176B7ECACF20789226C65799CCB92BF1CE1008C7450CA1B985CB44062E0E86186E7
AB9073F0AB92CC2F3809A42781AB3DD9C4614E23DD5C46C7F9B0FBEECC276328768B5430890D
BC40B50B863E2BA756E9A44334A32CE75B1E9F81B88253BC2444E11DB1E3E09441D189FBFE44
234B42F08FAA7E2BE38E153E030792716B3E2EA58A41FBB0E4383F8C20AC942BF4ED859B147B
5811F4EDC16482C8D6CCC8F9200D0D9C2044F920B53639BE73CB1C007794CF2964FD703A6477
44793F5CC0085B09E216B7E9E5DC415907EE3B0232B5CB2C624EC58B88AA23F70A77678BA96B
AB458E65F53BF05556D804ACDF3A462DB96F9A3A88C53B9877EFCE00F34E99AB203AE7EB4403
3DF3A682439E71021366564EA5B0D35B8CBDABB87423F9631334AA897AA643DA267DC012C933
F98545990D3712C6D05171058FE57C856D01ED777E9AD97ADFD7753E390FC20E1594F385E617
BDB39DAFD08AB3DF38B55C8553DFA0382E569FF0C7F0A5EADD9C390C1F7353AC0CAC68D5D36B
E24991DC0BC9AC88087533A2F41BA32A17D6D70B112B761B3B2BE907CB80E0293CD898C7B4CE
D1E23D76890FA9C2D6A7BE6CC78EE3A86FEABE7D9AB3DB2F2BF8480B0BE3147A82DD2CAF8288
2EE7A8382E8CCACE81372F5BEF033AF074F21AB3704BCAB6622A8EAC63EA3F802C4099A4680E
80E0207B4E8F4AAD94BA83C27D93F13B8DF59E548FB34944D36C12896D9D9BF72CF473CDA0A8
20EFB2572F704C15CB1C96B8D54B27298DEBC877CBBE2D375995CCE8E5252685DE33E2F5FCF8
C524FA590E5444977668C1BB92F92D91290EA0F869B45F78658D189C72804BB37658631005D5
B6FF1AA7E2CA7B2CFA96277D353B04FA0AA2556CE136A4B4B360434CC37EC44AB995F5E03CF9
258A5D5D35A9D1C33E51375D5B1048ACE95B3B7CE85195839A546AF8F2965701E9DDB41DE2B3
BA34A61A0ABD02998AFFA17857149346BF4E75A42A750B6AF1D2B8D8DAAECA5FA8300D4C15F1
38E62CC089C6312C16B6647EC9610EF0AF2C9C909E21F7C59F9F25D0232C681A127BBEE90D6C
19E41F64789852DF921BE412438E422B7F43E167198E5DD670DC6F4072543E003C7D351FB5DA
CEA72EA143ADA96EDCF91F3D672E178268BCD583FDC288B0771D1214C307232E7101FE8EE73D
16019CD43C7D4E0BE13F730BECDF9EA87A67E128D4E60C2104A36AB5BC411097F89F12564E1D
3BF17D9DD5D587C771D260CDCE41CE0F2F1DF995596651EEC623EA953EF8131D93BDF34DFA53
D25A7E20161C6B509E6C0D1E3BA2E3735B2765D9A69A7B1030A735B55FEE7E3C1539F0198640
59CED218174263933B3AFF5F4BBA7F651B365E27E7B0B36757D8EAE5E0D2EB01522D79193C93
84F8F611FE0B448307555BAAE615D204A407C7D49ED5DA1C14866C5A57A1BF319A2AD0B2B9B3
AC66F93514E87935BFD019FFF985CF0E57EFBC6F6A0E741B4E52623DCA9151ACBAC00D803E8C
66B6608695D88B188365AAAE11F7D2AF4F5151A1697736F90AE78AF147DD43A23B086BB39495
D5153BBBB1A3F1465DD219EB61D5C8E6F791EECAFC8D455BB423401B5DBE3F8A3C9E04198835
751E51E2DA6BE766175519E7CF26CE946310940205FB9928C0FD909764758E215F13DA4EF6C3
3BCA3E7F3EA96CE7C6CAC3CA449EC088BF3C8B54DCC433276DB76C33640CC4848FFCBC0BFD4B
3B0D3A3EDF142EE977A20A10F00EC0C19053C11F4CCEDC0C169F8D06E48B1CDB6F7F6446284D
951FD8E52F729CC16DA6BBD29F9DF9FAA96A023A7D039D4597D90E0E0B3C5A21BC26E4EA0956
D92FBD3C5B657D31E030AA1548810CEF44E42CF2A147CBFA8D3ED2AD4887A5206AB95ECF2DB8
3084CABB539BC368216B136B1808998D92467F3AD676035FAF715CA3A2D0E2813E8A3AC5FB71
1B6506DF9BCAF6C590666FC7A6F950A292FEF40CD5715F88AF0FB4A3C5DA4A4AA1E13BA6BC61
2F13A13D3A524DED5A78C3D73E389229E131D0BC3D58D179D925779E5836D4D0BB1349578EC2
82C37046A87F626B365EE9C35219F317354C9204467E3112F7AA7163E29521CCE0F7F0BEEF19
4DC68DA3409F33A55E86904E26AE8733B468BA029C6E71CB13239CD089710ACDB79F3DEC56D3
FBA5939F5FBE03E822DEFE7CC96AFE87926CCA04F3FE24F5FB86FBA339D109BE03C911786781
7C378D1D40A5670F97F17569E410654FDCDE83FC379B25FF051716E09FED8440BC435F79F8A5
80A7BB94E03B406E41DD8FF58A30CBF30B80883149C18B82C1631FB5EBB5362AD0D78857560C
08F3297BE612C4ED11B30435F99EF1D43611ED827DDAD258AD3E5B4C798420350A28BB23EC32
39675CB65D0CE3E08CAAF16FD943071F19D84A6FF8CA090DBF9A24205ADEB6CF31972747659C
58753B3438A0AF45D092705659BE42C74B5C38EAD7A65ED9E9AA99138FFA75E7F80953B90C5A
0A3564402E0EC23407A8A98353F51C31734BD9B2F239FD65A0411E946F29755D9D1B91C8A587
11CE35C158B28CA5C858F4807FDF26B972BD9E794324F2AFA43412F5EE8C804EAA5D1DB957DD
82ACEB2492F78C175BE221B5AE9E0D7A99057F2FF2FB55D42CC9CCF5866EB09D7C091331998C
693A9D1CE420069B24F0F982DF167372793E6A81EE2B9E844AA9C5EFC1E9B8FE8C05328050CE
E5FC73F179057FEB7A2F843C0A96E22885EBD7ECFAE90EB0D59AE93728A3CB05C966F3D9ECB9
FBD23A5C1288C7C5F75903CA85BCE7387B9C7E473946FB7D46A0E4C9C96B44AD611A4D208F90
270C6F7298EAA515C370F751F8309EB588B8A67521918EE5D8282CE6E3DA1EA04A1C1AE24E2C
C38E65C5ECE92DD0C982C54269EE1E963816422635BAEEC3458E86A821AB0092EA89538638D0
1872AF55CCED338177113B25F3BFAD8A6853C7A4AB4608E95414462EC826139C1B52ECC756ED
22AB7D50C8777736EB07586FA47A3ACCF9626A99011424D78664DA2C61AEE77356BC80EC0238
CE51926DBD899168E8D2794B4F63A6559C03DACC59C4014991C8D7049F58FEA38C9FE012D2F6
D344BC9BE54B40441229B6A8FB636CAA9188BD971E4892ED5EDED000F82610AB0E581FD0AE70
6F5A7794FC75146C4B2E3183FB051942ACCC088EBC4855483642EEA9E1CD17A2DDF76EBBEF29
B96D38769E444659688B63CE6116A0C9300190AAC8C3E31866B6F5D1048B8F4EC9263811B2F6
458978BD8F7D788CB21FFC394F5755E7D90A99533170D4C2AFD113FCE91022580034782A6A14
8391C7CCC4B8652E16AE26C00809DF6028BCA3E8F22774E493916EB9E0C3C3C2FC5752E0EAF6
B6F233C4A5FD689110C4B22FDAC40674C69C00BCE9D5246E7B3579FA776D2DDA7A1D768326FD
5D8B6F7E6083EF31025E17029631EEDC77EE0E3481FF180FC269C3525101577D145BE6C11A2E
7B1EEDF78F003FB99CE7C185A5711D4150F7C3AF25E98F036B48678B443CE762B33326B63B73
87E96878B084B3695B24FCC7FB49A6851EA40AB8BB7AE45C288C3CB4B1D9ACA0846BEC1E8955
4D23942EE66E911426C4EB4422CD6B5F519CB91E969D3F475C80668D4AE5CEAB15DFE7F64029
8178AC464AAE2C8198E1C12A2369D81E2CD1EFE2FB3E8C499D1F45BB2C1859F44DF0776EC3C5
6E6D31E587E6DA50CA97AAD5D8AC1E9EA7E5E7460000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginFont: CMR7
%!PS-AdobeFont-1.1: CMR7 1.0
%%CreationDate: 1991 Aug 20 16:39:21
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.0) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMR7) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle 0 def
/isFixedPitch false def
end readonly def
/FontName /CMR7 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 161 /Gamma put
dup 162 /Delta put
dup 163 /Theta put
dup 164 /Lambda put
dup 165 /Xi put
dup 166 /Pi put
dup 167 /Sigma put
dup 168 /Upsilon put
dup 169 /Phi put
dup 170 /Psi put
dup 173 /Omega put
dup 174 /ff put
dup 175 /fi put
dup 176 /fl put
dup 177 /ffi put
dup 178 /ffl put
dup 179 /dotlessi put
dup 180 /dotlessj put
dup 181 /grave put
dup 182 /acute put
dup 183 /caron put
dup 184 /breve put
dup 185 /macron put
dup 186 /ring put
dup 187 /cedilla put
dup 188 /germandbls put
dup 189 /ae put
dup 190 /oe put
dup 191 /oslash put
dup 192 /AE put
dup 193 /OE put
dup 194 /Oslash put
dup 195 /suppress put
dup 196 /dieresis put
dup 0 /Gamma put
dup 1 /Delta put
dup 2 /Theta put
dup 3 /Lambda put
dup 4 /Xi put
dup 5 /Pi put
dup 6 /Sigma put
dup 7 /Upsilon put
dup 8 /Phi put
dup 9 /Psi put
dup 10 /Omega put
dup 11 /ff put
dup 12 /fi put
dup 13 /fl put
dup 14 /ffi put
dup 15 /ffl put
dup 16 /dotlessi put
dup 17 /dotlessj put
dup 18 /grave put
dup 19 /acute put
dup 20 /caron put
dup 21 /breve put
dup 22 /macron put
dup 23 /ring put
dup 24 /cedilla put
dup 25 /germandbls put
dup 26 /ae put
dup 27 /oe put
dup 28 /oslash put
dup 29 /AE put
dup 30 /OE put
dup 31 /Oslash put
dup 32 /suppress put
dup 33 /exclam put
dup 34 /quotedblright put
dup 35 /numbersign put
dup 36 /dollar put
dup 37 /percent put
dup 38 /ampersand put
dup 39 /quoteright put
dup 40 /parenleft put
dup 41 /parenright put
dup 42 /asterisk put
dup 43 /plus put
dup 44 /comma put
dup 45 /hyphen put
dup 46 /period put
dup 47 /slash put
dup 48 /zero put
dup 49 /one put
dup 50 /two put
dup 51 /three put
dup 52 /four put
dup 53 /five put
dup 54 /six put
dup 55 /seven put
dup 56 /eight put
dup 57 /nine put
dup 58 /colon put
dup 59 /semicolon put
dup 60 /exclamdown put
dup 61 /equal put
dup 62 /questiondown put
dup 63 /question put
dup 64 /at put
dup 65 /A put
dup 66 /B put
dup 67 /C put
dup 68 /D put
dup 69 /E put
dup 70 /F put
dup 71 /G put
dup 72 /H put
dup 73 /I put
dup 74 /J put
dup 75 /K put
dup 76 /L put
dup 77 /M put
dup 78 /N put
dup 79 /O put
dup 80 /P put
dup 81 /Q put
dup 82 /R put
dup 83 /S put
dup 84 /T put
dup 85 /U put
dup 86 /V put
dup 87 /W put
dup 88 /X put
dup 89 /Y put
dup 90 /Z put
dup 91 /bracketleft put
dup 92 /quotedblleft put
dup 93 /bracketright put
dup 94 /circumflex put
dup 95 /dotaccent put
dup 96 /quoteleft put
dup 97 /a put
dup 98 /b put
dup 99 /c put
dup 100 /d put
dup 101 /e put
dup 102 /f put
dup 103 /g put
dup 104 /h put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 108 /l put
dup 109 /m put
dup 110 /n put
dup 111 /o put
dup 112 /p put
dup 113 /q put
dup 114 /r put
dup 115 /s put
dup 116 /t put
dup 117 /u put
dup 118 /v put
dup 119 /w put
dup 120 /x put
dup 121 /y put
dup 122 /z put
dup 123 /endash put
dup 124 /emdash put
dup 125 /hungarumlaut put
dup 126 /tilde put
dup 127 /dieresis put
dup 128 /suppress put
dup 160 /space put
readonly def
/FontBBox{-27 -250 1122 750}readonly def
/UniqueID 5000790 def
currentdict end
currentfile eexec
9B9C1569015F2C1D2BF560F4C0D52257BACDD6500ABDA5ED9835F6A016CFC8F00B6C052ED76A
87856B50F4D80DFAEB508C97F8281F3F88B17E4D3B90C0F65EC379791AACDC162A66CBBC5BE2
F53AAD8DE72DD113B55A022FBFEE658CB95F5BB32BA0357B5E050FDDF264A07470BEF1C52119
B6FBD5C77EBED964AC5A2BBEC9D8B3E48AE5BB003A63D545774B922B9D5FF6B0066ECE43645A
131879B032137D6D823385FE55F3402D557FD3B448685940729E6E22F4BE0E08C6505CBA868F
795093F556B64B808DD710EB936D3AC83E5783B5F7E56D363A59A026A5619A357D21C4E77BEA
121EB24B09027D1AAD93158EDF912940E91CD2F17922B358858946447773730BB19AF9E70453
E1B78D5EDC123B273A979891D6D5E624F4A388F3897E13B045E34B4EE2F5E4FC5E996D354964
0010C671DE14D18B0B3CD300E57DAC0322E59BFBF7B29422230870F5897FCFAAD4B50C7C1C58
EDCD119218163D6F6E5625CCB882DB7B6D09A1586508E8CB642A11C29A46915E4A96E282079C
B21922C1C2E360B487A45302FD22EC8C5FAB63E54B5E844D4B17CA2FFF37C69C366DD72AD029
22C14C0932F65ED03E4219C117962EDBAD2DCDEAA9C10CE8AF38A4AE52E2B377245B0BE19A77
D6C936E7530CC4D0B78D0CC4A92698FA2870FA54F2D8503E2D17B3D52FB2FEBB09F2B2AF0C2A
1892039EBE19A690098799A858E3D39631BD6925A154D161DF3918074ADA6BD52BADDD0ADC3F
07E2D9F15E27CBF7FE8B98C407205C811121FA91E059F2F99322FED63F359AC9DA97AEC383F0
67F23E5DE33151E80F0A88AB50FE8FDAE4A5DE93C1AE2FDCA06150B37246140C0E87CB2325A6
0D2349162AE3AC93144EEE1E665A1289105318FDFE86B6E76251CB25ADC967D3D0B97FE5E279
E1161736AB22B4CA510B964342383A840DEFD38F96A7280E6AC134E48D740607FF2E7804164A
16D47735864DB8456CBE4233242EB3B447F7AD444DC16CFB69AB1E515B3C3579F0E847488107
99D7F2833DB6E76F6AD8C924532F8F5AFBCFD939544BB7DA501D8511E37090F3A56D06FBC17A
49C373426BC6D94E829A8CBFFF9A2502C915E2823AEAE70E39F00BA99F8E6094A024E3C48503
2A061769D653CDB17A06D8EC2F407C4B9217671851529647D0B9F261E39564C79FA0D79AA7CA
F3D08556C66F08EDABC27870CAFC00F0F1828E93929116DEA5F038FBF92837E804DC9CAA7EC9
D967715C97C6D5770B5913C4513DD239F55EDB3D6E270E8D826F6B4D0E7192BF8A1200475AC8
E1A30A8F6B7428C8D321F93421F8A2F707548CB12C6963A2CA8C47FD7FCC6C4FE8CBB31985A8
9A0D0617119A892A61272ED8E264418418F2DFE0F5CE71FDF732F0DBE1DDCBCE2A7B6C2068D1
EB733FFEDB0EF64F9BAD513D3267870E0E90147C6B4BB9F60F99074CE5675F7C4FE9A4735BE7
E6D1081203DEE5A7DF96D68B2AAC736DF07BDD5BF994EC28EBE13D2ED5FF9EA89FC822339AA4
5DFE008523F617DAA3DB055EC593372FC2752BE8FF2FD825B13BF7A2FE7A0FBA28212C389C62
B64E9D156842356743272461B4B56B9FD5BB19AF45607E6E3424455A2ABBF21ECE6E2EAC5849
9533299F5A70391C4B7E9E95AC00A7593334FF183B9515F642EA934DAE6FB630EDED6B80389F
70ED5B3B96EC7C116B1124D4B6C90FE571E0A1339C714126128DBA4CAF5FC2C035579774D403
AB3BFDC134145AD2FC303F8C1FD5ECBBE201B8C93DC26497335822455921DD3B07853CE5B859
36F54745B3CF0AD0523D83B16C132E600FD7DC81B585E769207A4949ED024372D59254EB97AD
F5990992CE479506FBE4A8BAF5B46C8FC13C7C0CC5270D37ED08FCADAE4AF27B0E64080FACF0
558C85048A599D567054DFB290683577296CF1613299E7354B90C2EB4512E05B3350F681BF64
12C688BB05C110110932935913B5F888C20546BD51E414DC04255FB51EC37CD47E975F97267F
F78598952239F401E8704A903D9C8D7B3E72426FF13CDA6D912A4BAEBF04E9C2186290BD83D1
040CF238D04CCE1A1D177529EB8A27731C81393BB96D0858277AD5D0AE1935F89638D528B1B9
493532D7C81EA6020D0AAEDC98CC93F644EA5B5D134B8CD94A5E46B883E1F54A7A098F230C43
7B71049C0B2CA37B72915638F7088666438DB22AAAAFB84590BD7EBE4AA544506E19E547F3CA
E50348674B3CA185B542FBFB2594A687814F0C330BED938D482F6D55DB7746AF7D052BEAA978
2E812369AB4AE39F0A9890DD75B6159731898692B986063985AFAFD8CA08714BD415180ED6AF
DDE8D5719734C74A055FE635DB9B8908488EF1481D72A90C9E99614F973B243AE426DC24C4E8
A9A12D6D5E73FBA4EAE1BA66CC5B5B54357095A72C84C4E5ACC4D90038BEEEEB23E058079B32
05C0C4E0AFC015C650C4F4EB4578BF6DADC04E9228F5C304B2433F8D92FCCAFEDE671F2F1921
8D070E622F0F5A6F3BD95BCE78DDF81FAC393757517FE2E9C02B025B151541060B87C1844B3B
C754BBD0C9F9255A9FEB28B14AFD3B71BD0A916CA17957E3B78539480868375EA6ED93BDA275
D793344BDE7E59DDA118414AD315BC177937E056EE85E41C94C370C5F5B8CC34D334A6085544
A3A2C0AC9245A3AD03C278B39ABE17F945E0AFABEA8F9551460C19B7E667DBF2BBDE697AE880
2196EA5205142720E966449D85FB59B9F711ECAEAEC9103D383F58EBD19E77837C42BC90E44F
0397E073656282F8359362FFD450FA089C6911577705EFCF9537DCB916B7EFB30B4055A6DDB5
03E2983D1BD53482600907D9160FAD04128F4DC6343242E0F33C22286E6C91819F2E760A1788
6917A12E6346794AB66BFCF02043371E13D3F355A20C583E484C94BD407DC2266529CC993243
D7708C22C4EE4EB9DC2AE1228961E6605299201CE90B1B0547B103C4854E186492F99623B8B2
5264C6FEB01C3D9E86B2BF8DF607A5CB944FCFB174C233D843793E87801AAFD289B7FBA2E2D7
0E3E08B121A872333FD4064A3BEFA3FC9DB8382F0286852E322CE17D6FB4B31858AAEAD12CBA
FF2BE948CF19C1BB140114AE65D26101457B1CD95D1C9347528B09CEF9229913D349B5FF5F51
869A7E7D929B82F9736797F4C49DF52B2BB98BD87BC5483ADF1C1F620F70BBAEA51D554A1664
376C9FEAC4470E145C1138F27D16CF6C325A0A44C53A0ADEACB28CAFEF2A5A09FDB2968BB229
16F47193AB3504E23F103A993D67D48F2EFF36C306FACE6870C0216091A42531FB07605C0DFB
554E46660EB27A8503442812EA6AAE3D326A4F9EC58B6C732CCE096DD512A8BB8A8FA7CE09DE
D476B24EDECD9E39F24E0A30BE0C7F0DE109CD0E66196F3D55BA8298C569C9FC1D36FED89E1D
ACDCDD6A5E3E92D5201584982451C378F34EFA407B65F27235CDC570BB7965375902CC5E02C2
354145FF97AC9278BFC4191A286BC58CF9351220C57FC9C4CB450AE57D46C2169999973EC040
53F53FCBAB1681B17D6049F0F0786AEBB41B00C8CC615EB6A5FF5929283A93D22E28050D0D02
BCD0BD18818ED6836CDDA8DCA69093E03658D26EF757319CB1E738D7AC4BE9EB6D1356D9B34B
777E4FF4F2459288500E8564EA13633EAD85E614DD9CCA149CADE40F8D1DE3EAC49B16F9D954
953C19C66334B456260CB46C84CDD7D098D39E90920DAEC6D7A4523E54F6229231F5B5935B4B
BE67A3AB87C2C8C2E539376665FDA5E14AE5F6EC57D1340527026C7B73B99F13E7DD22FAA6CE
A155B79CBE80733A40E24B62A1FB88FDB4154283B8C5C377ED6FF43C975A01366BE13B9A1ECE
A1954C62EBF209D4A0761C6D7FF6F1BCD1196E4080030EB2A8C4DAF3C941F3CD5FDB6EE95FC9
0824F9048296C56B3F787218F3D546BC2AFB2B2483E1ADDD112B7C892FD4BA8B158B579098EB
B44BEFB1B312E0F42F08BF77B43B438A231C1110A56F89BB1E36CE90F5A5A69138B7A8D840EF
ABBD0C63E459021227F62539C056E90C377C9563D1BAA4168EA5AABCDA5DED1BD8E58DAEC21E
20E651E0B783BF605DDF8F786928F7DDB085AF660EC41C26EB4BB70B6071F5F63D7427E3D54A
05F28178EA6A1C00EF8868D1FA78093A91D3E4BDCB4A40C814501456216D7D164C7A82B4BB5A
16220F7BBF07B9D11AFBDE09CAAB3FDBB6203C667EF450B644B7E536B1C80BAFB4B5E5295B74
7A08C4E843DFFE087DC105C9BDD9052BC2D86BEC218F9D49E2CB9618D9D4A3422F6849CCD5B2
41C0D0115DA98661ACFE49E8A8CEBE1ABD00E6662A2D8A9C0FF1A6808BB04D5E46467904C168
C65B7DBDD1A0B5456AEEA445CB22C77BF3F7350B13B4E2423CD11A84AB6834C1613B09BD7984
23F2249B32EC8290D679D14D3E0935AB5CB188D4F845ACFF621EE3E0206E6CCF2AE120114496
636F297929EA214D6416E639B5FF5B188F38C62FF67C969E3FC492237BC7D5D6BF16604C0C94
F2469C67A225F6CFE49EB45DB9423874BE7AC48A009D68D028245BF895C1D00C40592B68FFB7
642386887F137353293F9D506DBE742B322A5AF5677197B8DA6DBA4829F20A02E0F8A8CD140C
76F9BD9C730097E0E140EE2EA2F3C71C714C669DCEB650E87C98EDEBBCEA6A5966D8965AC0F8
DBBB858B77BFAC279AE094995CE9E7D78E387036652B0FB576EF90A777C664C80FD7C2C7B9FF
EB52FFAD59629217F293F54552ECBCBD6F05B326AFEDB82B079D68104CA2660B9B43EEACFBA6
20EFE2B1CFFC84AD5F98AE71D4CE28197A7AB40EDE026A9986F73DD0213C1523112F64FF23C4
0A474FBC44E3266EE0AECAE9A823BF787861F3F9AE1BC0726A47D8F74B70D7899A5A2E40A2D0
B5F8E229023ECC4E5B30F914F3EFFD4481FCBAB37D8ABF4AD3759D2357BF5B7416CF9AE72A9D
0D9A10892A70FC0FA2F2C20CB2FD8D80CA9C7530CC1465D9115306EA5DD4F7D7FF60979628FD
78B6F0D429B642E44CE21929AE076BA999B78DFBAEBD38B0C261BC566C5161119CAFE5C3D0CD
02F149F5D24B241A9CEC58E9E2E9F72A2862E2103D86CE4D93E612CDB82AB33215C2AEBB8D30
E34EDA53222FE67843FD747F9CB1D7C2B4E87D71498A1D5BA282EA5BFB3FA18719124FD46A98
ACCE4BF97E480A13D5AB27689CEED619A8595E613201056C5E137F618E4F4B41B3B5F247D0A9
E786904DCB1E2AF7AE330C11E4CE29B6C75CA748584E83B5621F2321B730221A0A6AE75FF564
4FDF0FBDD7AF0627D4CA801D0EF9AD04C55C238013994B493B6E0CAA0C9EFB6A8FE46E8F120D
1CF4F60453A6858D2F49FBEB90D21CC6A67D2616A506795AD9BEDC96532336BF65679ADEE667
2E8FF95DA69F013D64D7121307B932BF2CA4FF2623DCFA5D8ADE618868D6FDF74FA9EB4B1D81
2C0F8596C9C14B807345EFF6534001FB3BFA4B5CF929767ADE5C5B1628A1EA2D0805E85042F1
E31099EFECF5A542BEADD11B41F1428FB471DEAD028B55BEE01F9429DFAC0A6BD3722C7EDF43
D73A222B883D305847A200043DCAB3CCE0ED7A22A16210700D98EC416164F8C5A8B13150308F
253797903F8515F065034EE7B5C42FA83CFFC6FFBA08BAB2969617C3D94213762C611E8DCD1A
A82F90FFB2E2C0E570295EC8F36352583CC4C9DE7D1DF3E8774EA47EC79FB35FB6EB954E5733
32F582F2679B13E218526451AE5B5C7F0154B8769119E88A6E93BDE1655287CFA8663EAFDF09
C332666E2A14F562C146C9F5CB18BD22B70F98D3D0917AADC376463742BF897D7B1868EFB802
73CD69F079790DC6EA395987786A1EE6D649D725026D34F8A15FB57EABE12757E49F30D2B7DA
FA80AAE0723F905CB1D4FA4C21AA68025986A45A6FCB4812B7B2698910E5FB950F2280E3A60A
0A7930270A93EF4F7929F2ADD145CA87872B8B713FAA428B10A1F419E985E740D2649A29A3A5
E0D691EC7EED9A5251A0D76D6A6D1F455D308BB7324B29A92CD01006ECEB1128DCDF5730DBA6
00B5881B7C3722C09074A51C45AA8C26A3D960944FB062A7BEE0B7FB1D06B5C3F0CE9F283625
2201E0B3121DC1813D955A3D11A3B41B1B1E74A2EE1E84364D05FA9A68405CBABDE0009B221A
BEA1146608A26B66FA93D382DA5ADF94BA248F14035AB0C03EC49458C7AF3D9867682D1B0DD0
66136543EAD160500D49912C5EAC3B24CB12AB6504C837199186AAD6459B320D69265F230AF2
39890F5BCD0720FE71D3CC95295982EDE49A9D4FEF248F7FC3566796769A2A4B205E93DBC034
54162CD50442B11954667199F1C43FBBCA8C354F43DB19C1D096F9186A1B200DA03F81E08DDE
8DCB88B2FB1886D246933B5497EF4782DD56F5A54BA4D8A5227E4E5DE31B2231A26C44103F7D
556054A2D4CCB8F57D7F56DF346467CFAB794EE825F86F3C5E42339CA4415E8100715745C770
705F3156F7C4ADC9AA98D5B72909815EB12B55DEC84724575BD716F0607DE90DADCF41ABED55
CCA9CE2C075A851C9155523B109B6BA66A5DBBFE5159FDAA892BEB9BE909FA491B29A7395BC3
AD8BE8605AA7B57D10BC5F96A02080F39B111CB1D23300D3B6269C3A696363156D3D0E99BDAC
071BC920DA194859865F6AAFF48AE35E558B99E0E88D62F21B7C7A3640DF076EABB7B67025FB
F9926E8C469BC5494D501DE9AA1565B428349511B5A2D3D9DDD67CC6E6F06D83B28857F46244
5F32AF11D71946359A66C9D7E6F1EDCCC0A295688E239D18E6FBEC696C21F5B2FBF01AFDA3EC
39F0A76E4B530528E302A73A75509A1035B4D55035475C984B66D0AEB7F423E4EDAF3F78BD97
35FE8FF17CCAEA7D245C0257650246C90BB99E1433A867237BC222BA0B96D4E332BCF48B8565
D9F00EAFD940C10F1EC44F4BABC9E4B74919039703BEEB805991F1CC3D9D7CC4CDAD755444A8
CFA2AA908D66B88B63551B7196413AD3614CDF428EF48CEA5396B5777C39CD7CD285E9A75ECC
5E028DD5C291E063326BE2421977DE683ECD670361645B6F4495ED0ADA49E2C3A341D1973B7E
C21AB13BB4F8BBDAD0B31EC43B0F6A3268B1E667298D95B3BDA5DAD45D2241D851543FD03F1B
26B6172B88ED6B3A1641D4125AF70CC3A4D425D7226CB034B2BC7476EF5E08A1A33626EC8B67
6A9ED37CB0543443705BA5748BFD99EBAFE17085D1C20A85371481B1FE5F239986B5ED471B21
5F821BEBBFB2FEBD4AF60B53A1ABA5FBBA118C0F121A1183E8D1297DA1882DFA5140469B2522
5CDE835D18462BA08DAC0673A4FCC6172BEDE2FA38373DEBB9BBAB9CE158FBA3D831499928C4
059C086B4CB70DC0F2E48EE03FB4887CBB0B45F8FA04D7EF316C864055D55FFA990419D9A83B
C08AF43EFC14870BB40840D12CEC93306A2355188F9367C512B4D0FC1E039AF8A85E29BD8BF1
BFA9476A3FA2876C58933F713F0B58CCDFC6914D7134E347F2816EEF956C6171B313BA58C7DE
279178B9BFFB30972D6B8D963202E4DFC92E9DE0BAF43878FBFA9A13F30EBE1C9EFA118ACF87
EDCA5E6DE8AD4F41C09F03465E20BE82CE8226395EAD99A8BB871D49E989E486626D73CF15BF
A569F3CE25391F477047C402493A23B55F70462870EBA3A681A8F8D99CF7C2C81C70D705C392
ABB88587EB849662B365F85C241DD765B3C295F0B7E7EF57C7CAD259577D8BA18DF21E664888
EEF38DD5D9F984F9DF4B51E28563B787C8BA7A96BCC3EA9E3A26E9B0A9946E642CB59170A89D
526FD1096B7C09108806EEBCF387FB03959D54B418E76A6A638407ACB5AE8FA4A7A5185F905D
C9A61FF94929D3C2BF0D92717D81B575FFE8D17E5ED3E5197CEE88521AD4F87CD5F57E87BC33
F077C90CD13297E91C49F226AC5A085B73254D5DD3871C97F873360FA05F8F7216C867C8411A
DEB944B47BB5305C6E7B51A9E41916AACEE057976CF4BA417A67E68C4245E92953C609AF2B8F
658DCDE16D328DEFE4CF9EB05DE0ABA6F076122CAE1110EA641D1D886775B5C5908D4C32DEB6
F8537A35F6DC6A4F0E0216E93BBF3AC1EBB21EF00BD2D7CD787C17915788D0CB4062A0766593
1A30C43B483FA325F9F92F45CE6CB060300B818637507FC323EB5C1958FF94C7372726A7B68C
9F83B07036EF06FD57C4D174480FEEB0A6441FE2DE8243F4621B553FDAED2254E9EF5B848F63
2CEA1A6B9F3D2E1EF7F770F5404AE0F4F3C912EE3281F9596B42E01325E8923923703CF60F76
03B7FD89888FAD0ACAAAF1B1A6463A3E73525840E5616D5C8E7F66683F2135F3E4D0EE18FA84
32AEFD05C3569A4CF8EFA471F0A1490B4A55093A64659B9D112EC90F42FA874F3F8188100EA2
F157BB4F9F52A1B60C8ECEA96E222EE4AD0C6B70B2B43F367D4C933F425D49EEE4C7030EE050
DFA7CC6D044CB9E20ACCA84A80B9F1571927E2A312E5A9991244FDB6EBAE1BFCA4820C193703
951BACCF931B654D6BC3851324D3394A3BE41DE2523309D5FAE513F18CB65C9D135C5F8EFB7B
2622B991D8ACEB91880B22944D26909B3544578C19C1DE4A16CB7CE5FD26EDABE394AC53B2F4
66E27ED9FD7528B6F7CBE0C4EEDB4024C76EFA6EEE427598A18CAAABD3DAF43F462C138504AA
D4517FE9A93E25D49314266CBE18585671EC97D8016DC14774CC105C2807E8D79E76613585EA
738B346C49534442BD3E36ABED00E8A6FF0C7BDC021B721E2DDC00B6C3E6F42A2F3C98DCF7DA
A873FADE66D8EE0A21A958C725026F4A439BE96A9405C808649E54177BF01D6026A6B759BAE9
689995DE878DA4EC878A69BAF3C387CEDBD62092DEBE87A063E21D01F632C247EF3F07574282
EC0E245DFEACFDC38AA46171D82616E121BA73B684F869908E65AF1C63A2EB7E812EEFE3C3F4
954E10463359CC957EAEF32A49E1D341702F2DCBBF1522EDDF1DF96F8C679F752C130546594A
5759E7944CA62474D30F5373801F323747F58A04A8FA115AC67309FAFAC362D6AF9548199389
20277628E3771A03D50A13CF80031E63CD4834D0D47C5AC75B7B22182EB95D8DBF64E531E595
A1DC9B5D7D093698CEF3614BEE91F73E5625F425CCC3C4A364BAB995CAFE438D8961A14E67D0
C03D8CBDDC4CC8C34D7F9C2A815CCEAB4B398D21CD45423650D0A19A0AC8654175C7E9A43FD6
599D2875518A431517726948BD9FA0C7FBD59D0A62E979FD9254AF03D216FD75734BDA875F66
A31AAA8F131B49188AD3AEBF2DFCBADEC488DEE91589B08297A960E21B4C472B21BCF55E1430
E313E1BB32EA42921A240917EA08C90AF9CD982444B563C1B823104D34F64DF37742F42D75C6
D6B9214325CB6BEB0280F79723E9A975A499784C59F44FE5C8FBFC9FF7F5643A5BF9E6E0566D
5C3134CE761811A725D9BE99CF34DC682243774E6A13B21459C2242ED68DEA64E24E8DA19F08
99072C0CDB2A807283D5378CB7D087D1B01F92E47D1D96DB42B57FAB36CDBB73E1EBAA81D22C
521A573C18067FC8EA38713C959046C985593AED0DF31989DEB783AAA57ECF01606C675E5ADF
81D845A542D50AFD29C98CE67A38B210EE23C9A14D23043F91FBE77ED190B43EFBEEA41382FF
8DDCA4ABEE4665B67816531F07EB8043DECB836794615F3C334B8734A579FA0BFBEDDFE32A95
389C6110D09DE30091EF2F29A29206047E8378A870D9831DE115685B34066B9B507E8DCFD6F5
A23B5CFE5E74527B30705D010CDC71BD90DB9A9A53053F6B24E65DC4AA0F7DA29D4D66D9DE8C
11354821B14EE965F16597EDBC5BEE7D4683E20C06337CE21FD1A2A5D78FF1E945ED13ACB556
C70F89A08202663F2622CBCF480336B8CE580275514B24430C139284EEBF9FE81CBDE98C00B2
AB9F85BA64E2CFF0888DF49C600EBACADEEC43FC0A6E92C499416902CDF94B318AFF4F6F4923
044EB2EF3A88D0D94CD274F40488309E2A08C10EBAEFEB2759D9DC7DBE2C0E647F36C21220F1
1D88299117AC699EC7241EBB828A03D18A58F8C7AC0839E929F6F58CCB8613D8DDEF8FD6525E
069613D644653F6702B0B097A177A31FCED5F7131F8A3E5A420D6C7684F2BBEF5AA88FD91243
8F7F6D22263373CC04446A640953812419A21793A204146A1296565E9103C1DAA633DBC79BA9
E5504EE0743946C1FFFAA5357ECCD3A269B6A63CBA0C0A9C76BABDFB28B0CEBB607CFFBAA692
360697C69E1EDDA67E12874F3F1260753249307C4572F363033B902FA48FE237A4F65736BC9D
A310CE406AB83059F02F94C8C9384F6811BF649506CAD6554912561ACEA6C1F4F1F2193643E7
5457E7207C55D0160BF194743BA207D4431FC2159A4D593EDE6B1AA19F96ED07CA67505EA417
C85A3AD0F87EABA0716C41BBBAF003881EE12CB4892184828BD1CDDC94AAE05C19999A6F1D2E
1DCE2A94C4C2902522E44B22131192CED3D42A3584C98C2D9301DB14EAE7474014C04AA8D2DE
A1755E5F9037D3E3821042366455AE23CAC2BE67E0A595A033E98462E1008294A00E463212A2
6B4B941255523A3C9F39197151E388EDF193D510A23F3310E18FCD55019DE861208F9985BEDD
65AE125204A6DF7E8233A25AF7AA151C3F8BAE7F6864386FD22EC8A3F5A179D7C70FF9E71237
EBB2217D09DDCC061D57445E8B9665E22DDDFBA4CC18B5A9DFE15224697ECBF4E797E3042AE2
754EF1BB9D4652DA69A07F57EC6162EA26D4650FEAA52F9B39AEE8767C125BD7782D3605E19D
FD2266E7A37B58146615D5BAE6B16633D5280D2CF0234B0114A91DD87AB6987FF0BF4D8014A5
24AE04E18813F88D00BECE288012E8A285214C8ACEB7A5EF665682D463462F04E4BA0852CDC9
8D6982DE873D1EC644F44B7FCE18778B9D8F130584CC3F3A8D7A51035F10167B8E572BE50997
EB738381421A763E96D785AE567981C1430CC18A79B8F57557588D3842795F2312C4D3E3DC3D
55D54A358A9C0B031E91185DFA97E0F5474CC93CC71BA796B4A842C8340360BC584A1477608B
D95481DEA6DB57D819A8F36BC70C09889E2614A2BFF7C74D0D1D09E1454C58F7CA672ADF64D0
ACBD1F9D3AC9203D7D011658E361B499818B4BDAB372524A385E65D4882A442BF53DEF1FB2C7
460DB0F59ECA306C74AED3E29A94796F525E2D5DF9BE7A97CE6F0013C0F39476A7BCF610F4BB
5E83D2CF1A1D515F899C81BBB60646125408922B45689BDBD82F14A2B9BBE1F27254A5D1BAF1
3B2128846E4DD8468CDAB44B9F847D31DEE079DFE5FE51870FFE9F18CAA25A2FCB978A46D747
544F2FE51496D04EA5478B209FBE843025BC64B1CBB0DBD43DB01744C471327ACB3C77E4CB6F
ADD41B9D4D1C0BD8CEB11AA2A239942C97D1F1594F6E4D9CC34285E4DC6F61E80CE1FEBAAD7F
9BFF9C00E0F06091EE76794F0B859B46447CD627DB60142A462A7A3E4403E839DC6D4F08BC6B
50E8300A76DE811EDD85431CCB895AF3045425F4099B1AECDEB7312E84DFDBB373309C9B1FF5
72ADC905A41421A77699C8885879F4939E7EE8888E7CF88EA12401C1154525807F96C6F192DC
5981ABBF512EC4B4092B515A14262519A630F20DC7CEB32AF0A2A10443EF54AC376851A23F6A
AAC95DFC30D0E4CB5E14B5CC323CE4D95D3612D6B19A877973B42F32CC03EC67497E3D9AAB54
573B36B1DD5D096618A4ADD3A1FD077C1B00C7E6BAE8A90C606C979A2523D5AFB67730416FDB
1F28EB72E6F7079B84A903C68942C9A17B1D71C30CCD288ED9781E50212CD06E5EAC59D45034
36E3DF8ACF1F63A8B9A44C8D159C1981168E5C4BF7CD5C5069EFA0FEE41BAC93B1C0E0BD9F12
ABDBF5C8404B53C102DCD215889A49F23C435A962CAB0C48F763245F0BA1E3B61C6A6E305D8E
D49FC181BB4E6DF8483102F70DA144937C8B5205D240D6616F1281E92C4CF018B5E26E74CA72
9A09D355F97BD76563A4D62A3D643D5C7BA4931B5A3E3A8079286D4365DA4E4F63236E4C5E61
F6743472B1AF5A5FC97BAD3D576865E55B3E4F214796C674C902691CF7FFFB9ADF45B6BFDE90
964E83FAACF3C1FA70C53F3D6EF18A8E13FF85EB35843E983393C292D1C4890F83A33DCE96D8
3C4D38B4AEB6B75B50E7EFFFFCCBEBA8EA3BDA064BDE07DC7726113C716FFA47A00D33F49115
4228B6A20737895E365B3EAD997F7D2F9999EE6F4713DD02AF593E6C105A27B9001E1FC7C57A
C408DB6309A6AB2C3C6FC6BBE62588AABC4EC9420A72C6DE5C0554547069E15962A141C4E2DC
4B38BEAD55F8E08F14B9A455B81A5CA9191B588A5E587A1471E9F1B30A7A866B19BBADAF5AFD
8674423D799F515D2B59E289843B98E57F6D5105CF14929DE24DCD833BBD7FC14CD0AF34A8F0
7284049AED310B36D0C8559504248BA11B4C6697D5B74353375163290F23F63B2C611031295B
2A5183036A4DFAF1DABFB1669E534A8BB28ADB16EA52EB238A242757B8BAAF53E90C258AF04F
9DD1B00B100CC6A32390E6FE91F13F675A3B78F5E23646F1448F7D6421C38A58DAB20EF56170
BE71AA9CFC5EECBE809138A9FE8B46B8B30538174C23E6B5DC725F3A0507F944963D9FB47C82
58C4EF8F5D4AEA6A5860A95E0B96943452529441C4C6E8E299DB6CEA80CDF2DB74AC3A89911B
55E225B3F20D3D605979045C72B672DF80FF1F78CF4992816E27D225A66CCDE49F357E2447AB
C6A570003AABF2F770E2DA3F0FA89E9A01AF0BA430C925E8F764C77B59FF767851A7D6570106
FB852F3047CB0AA041110529072160AD8EC569C8C1C5EAC5BA56EA030D104DA9C6D530C089DF
3E37148F4B8B0A005616F946C83A391DD7E7E776FB9DD3D52F06BDBB5CAF1227C4BA74861BC3
AA9A85055EFDBD275508DB8F68BC3CDF69DB4D1F825EED993B84FD63B237A38A4CBD9071D0CC
DAD295F3947BCD1AB385BECC35725F4F287450A49F652347C9B836A8C46A58E044853760AB10
FA647FA9862705641B5C411A2EB69086B3488F4319068C959E5D369FF0FEC606665B6C19A567
9A96138A966AFC86F64F803F55829C8CFC184D20D97F1B625ADF7E260EE89F20987FF29DA9E0
5A4C12AD48B56404D0B2BFC398D5991C8CE5F81E67D71F31CC8A4A6D1EAE0DD4834EAF3F7DDD
6493DE2D1D31606241185A05EA75A6036AF2A4C60079A9E21A5F28502560FEBA1820361A4B0C
2D313742A2E6CAD252169103FBDF7590B38A60C227446E944ED13D91D5B3DCC6BC8A4737D4EB
AC8BCFBC78E243296A76639D2726D968463E03E3BBAEF4CACE746BA11DE8DE942E1AA4AA29E3
993212FD27D3A23E55C731617AD58A98615DF3113A6537CCD5E4CA5EE7715F446C009F423622
CAF9293D9C25EA96CDEA869C00821CCF8E0E146A6977AF4FD1D6CB46D3A96CE4559D7EF177E1
9797615C95C51B2AC6DA1A3E700D4AAA84603E9E9B4B0F2C084CE4A17BB119B6C998045032C0
4AA21B8B4D5A0262387F884D5B21AACC93F1FB74EBBAAC13E092A860F9875B83A4F2BD56ECE6
B63CA3575EF0601F3D0FC09C5FE9D7B2523A88C37C3360FF2E8A3A0D6C6C9E448CA93728991E
F2BE037DE5FB059A72ADB03B1FC85C49A84B2077D6ED25DDED1D0F9DF4F137E4556A9D066927
217488D7ED62E22313109634EC5B291842369E376F2D2302A3D9DB199F0AC48B228C8218ABE6
BE8503502672F984C8A7A97B8B6AF3EE1C15230C5DF8FBBD04D78B28C3CA61F568E0EEC6212C
3DD622884AF4740BAE327F89485685C94503D1D86AAA538110D7C9E520FA19C129BB994E3765
8B6F0D301C8899CB735BED20E929BA4E7B6F3592D5B945203639979C6A459BACD0B84B399828
3F3F8CEE039A3E78C76DBB58EC4311BACB39E1AB2B8C1E65AD657CBA210CEE930CBCCE737216
414A7CD90ABB953F27FDB0991D76A23B8122FE3A2CB26843A4DA6681ECF996E4AD7A1102F4B2
44AC4F6E431BA1E9F0EDDDE9DB9399AA8484917776F256803BA5983A2575D9371A08F2330CC3
44B89CBDFFC5004E00097A757C390984FDFDFFDC459EECB46A2A1C8AA6A1618C2B1B49224E76
0AB2EAF6893219EDB7E107208D95D4D3F49E221994647667DBB63634E327C4DB6585ABB58D3E
B338F272AE572E9217D63CFA8F10C87CAB078B68F124E0537050B7DC1A0D1094B9AC9FC21F5B
B17756D65C05801D59E58AA02C509CCA118CEFD2C91D6735C1DFD01DBF1B36F267C4DB0C3651
CC9F1B325915E23AA43EA1DA505179DC098A3DCB76DF83BE080B733DC252E0A00BD702BF57F1
923A978FAC404F82BF4DDAD59B16883CE7C6A0F84E4A4E58A38FF675335E5CA5D59EA3DF82C9
3BF0CDB775B533BFCE6237659D0B97476D2C14120A35BC6970EA9554FADAD6AA7EA674529B87
603342FAEA220B9A0FFDC1236FEA243892289258940C2DE850FA7F4A14B6039EB93ABE2D6B60
E78D92B66E53C40066138E63A10A3F5D8600A3974652D7EB79C12E16D5D83761AAEE32FBA99B
762B564374B60F3074040D30343159EFBCBC67FD1B621181DDDA4EAE32E38003E45B1A21A04E
C69A3C05EC4A7A91E5CBA3FDB856D8127D9ED6C8E23EC8887D79ABD2FC139B5CB04D181E14A7
43AA5D5CE886607534117A5832DF964084FCE620A465CE886D1A23FF1CB0FB812117EDA34436
5AB72AC5128FA0FBDC426672391C4B61D3E60AF0815DA6D908BC6201F800C705A18A2343FF3D
485473FCA8DEB44D821066FE148D3CA23956C99D0BA4998A3E126A685B19585D7380354E8091
EDFC4E684AD032CB0DEFC5CB076A5AD1E9581E68B3826D09A96156E144733907A23FE62AE723
9871B1D7B790D74D7820F9A096399D9120D5A78E2EAD9D6BACC3DF32888E072021AF81166F6F
EFF32EBAF11A8DECF4CEE3C07E9A30F175AA22C7C615ADA194480EEFF72FFF2E97BB0DCF5DC4
85428B08F173549A0132B396E7FF53B578AE0939DC0CEF80A537B1D713B4D6BFFC987B34943E
ED13E4B723C85252F9561031F3E2144C7B8C8B5F3794435E1293E4106E8C0114A14AF6B37C7B
28F7EBE6D321C4BAB2DD04D08FF1D2EB4967092D52E8E5F1D04875FC7E00FFF8C3E9C7336CCC
8D709EA09DEEF006E5E809CFD7F377FC4BB8992DA3DF88159F1241F927E4701DAAEE33394645
B361BE7A137454A2150394309F69F41B8EAA3274D6E4AC2E9A94770BA1463A5B774AAD448F2B
FCA1D220449D1D3D09BDE0F582E4C09E954ED577F7F9ECDC5023DDE9313D7E0AC83C496472BC
35FF3367B62F1FBA6EBBE44892F0CA9F48FB4DF1C2E6D95F030305694C91E5D2A49CECFA8A89
61877441513E02FE7700CC536BC6FD9622093892353F0A83AE630D5EFFAF0338924E2AC575AF
4E644413C29EAD6C123FEA2ECB5B4B49CFA4042C31F3D6FF535D3F881AA9935E2B5AE265207F
94254C9DAA2E7F8BC6FDB6662722CB19E35E4E10810C43B0A46450E0FF05236C08298E02667A
7E2F4F1777DDEACB198D3E65FE34C78A3C71A542A0223828BD7B57A49337852A7E38BE96C8D6
8B27947476892A6325597AF1607104A3AF0BD539A433B1CC09D23790DCE90812DF84BDBDD0F4
56BE6404F2E59EB8882779554667D48C007C2B6E31FD3691E97F76C06C659FB96A417D2088FA
984981311EC3217A9BF784E579CA42B4478F6530B3E9F0FA1D701D4D8F040B4173C8E1E0CE76
006A644DAA1611446FFAB2B218867985ED06DDF3053684F60B912AB11CE7B3425FF389107859
0A78768D85E21BBC09E3B315CF56F6F3532F3A6B1CA10034B80CAEF1E62C2D91FA0799ADBEE3
240BAC2A24F35015700D938DC7036245230BC3DACAB9520AA950D153AA79A0570BAAC57452F2
C958554992B0A965CCD7BD9C0971B6EE8357E3DD18CF5E6BEF5C74DA84CEE08E597A5DF7A21C
17BED630CB74F2F21EEC8B3C2C6DF46E0FF5D571BEFA8398D3EE38E905222C8E94ACE8612170
1195D40FCAAA271874A8E6AF62AC4D60558A485505F4301959417D3F996526A494A201C4CAF8
4BCA877DA39E1338BFE9EE163E28993545B5B989D5E8A0BA1E1439EF7C6AC1747E272716A30C
CCE34112B67CA53ED3D2379C99E4264C37BC4BCB70118298D281B8056D809B82FEA6994952CB
5356BF3E41D19A2645A0139F44C7179B87174F4B5979B9B6E0ED55C00F4CF2299C6FB6C98010
E01608176D6BFF74674124669EC3D9EC262BE00B9F265C1BEDAEB13895CB58CE214F2D7FE619
762F2F1713A0829D3EB4E7FE6449A73C7C2EF52856226952B9EA375D9FE3E0FB79741ADACD2C
056BE97B93F09BE46C97E2B15B2A3C067172B90F41A8FF1952787EB93ADFB5D139B6E68ECE12
291B23AAF9EA86585AC48C85BF29259F01C2E158750E4FB1ED1F611669EBEFEDAFA8F1E8C285
A1068D065953207897F63C142234B79230FD7DAEC8CF3C178FF691F2D22BC2E17FD20D527954
B08837F88BAAA2878580E49A7D3D4B3BC91A228EA3B176020A049791F50F96266FAA79AA8551
A4DB3913346113ECBB742944417DDF2529568492D96F06360D20D644BBBB0F7136A38B813E20
8DE581E70648686C5C5C6E92FA752D8606B56143E6784E400411E2EAD4933F168C633812B2E8
208B964791DE0951EB3FF55BF687EC958399B4B34F70A80971D269AB955D8413B68E69821086
C71F87C1E60D5E78E721AFDE35380B930C41B72F4E8717393A013723C81497836A6D204368E0
2C8BBE44521C82CA5F8E3120E7ED232779C0544183865CC259A047ECC3EE5E139880FC96F6CF
ECCAC3EDE4858F312BDA343B23E19703A3C624D99361C6900DC9BD1134001F17295B0C2EB754
4939E8572D50F04C0EB75EB20A88C91CFB5CD971A05876179FE794D4072D929423EA9CD398A8
D31B3CB32262800CB5EE1266111E0504C14C1FC08E60441E89E4DF7C91CC5FFB4EACF83D065A
F32AB2366B0C0A844D28C803E33F1679EBDA804AFC0EF4BF320E21919959BE7B060E914F49CF
8A2CA28547DFB771DD7F78535FF95934CC749B5C7897EA9CB067F6D861064CAA233C3538F3E4
D5EAB1E756EFAE9F305B03E70E6AC14E0355AA871DF0001FC80620160DF7D218B64AA8C12802
CDC0CFD2E16E45FEB91D2A74E12031082E21A6CE76593E3C17A251E9B2EEE18A0E922DCEB758
DC42DE114893C36AFD4A6E3F1370E3D66B0CF40DF7B05473DA0B2C446385870327C847A5A052
81BAA0080C36EC65A10056619005B39D3BB17315EBE5187D1D69DBAEF5F89F280FB9F41F53C2
EE00A400CA8EED8E74337FD737ACD8EFD0D361E4C516B11DBAE751B408CC54D49FEAEAA64523
6FEA20CD8C326231E9131D003E74F1F8711C883E6AC50798C98758A226CA85949CE153D4F1F5
002E5EDB1C5AFDB33A3D5E6A4FFE73FDC25AED83C1C83533A5464B5EC8C0DBF39C3785BCF147
A4BC11648AAE5F2ABD1942B0412F5ED98A4B3A5BE1B679F66E0D0C43806A89A349F259DE095B
8538C45A1A14B320ED0C662129C881C6C70487D7EE3EADBDE833C415B992F25AB94E1F6FBB8A
FDE188FBDAE860368558C1049BCE0E400368BD094C1EA808230998645B88163F77C1DDFB63B2
092FD1B772C7AC73B095AB8749E65C3DD040AE17206CA88B7507AB3321231CCF8B2144EA51EF
CBDA013A011E1D18ECD5780A80C262BE5D6920178D2C129F87632A39289B032FA01FD6699ED2
E79EB18B0990B86F00C440B4A6CCCD109288A177E366D21CB16A569DEA5D20A732B10576182F
0EB68BF666B1004DC444960E579AA3FB762E529B6FE6D98E582B90EC73140BC67696DC49ED47
64615760C58E9329C02FCA556E23B11CAB4F516E609F6044FBE97289D4269AE5F78399432A57
5198596B1E19B201078C93D27BD18C8929F145415FE188C35DF3FD3A59A34AFA3C22CDC2757F
29AEA7B1D0D983F4D029E4071896437C8AD90459DAF4FD1FD173925A007A845844C6666CCD14
A9B4DAB72975E36B8C0CE9A63FA38AC0D0697F46180A06EFE2618B27FAE17F16A148792346AD
9C2C55E9836845B2A33E0F03CAEF4850C440BA483230CB078A72DA8482FC959B4EDB01FE8488
B7C5D7502F922ABF8A2195F17C2D3E974D2E5AD09E1E61FE5B723D5A4BD6336A259EA088E3E4
4FCA4DA49E017ACBA3C0D58F16A3A00E21D44F1F26693449D5D382A12C70C7959965479CCB12
5565DA2442641EA18B8DDD83D43F8177FD32298C0B3DA44D436C5AD9B85E47DF64BCA6898C1A
0EE73195F323D8B4B2442F15C7A73DA62009A31A45339DE6C491A04B5E4C383EF66A3749F6FE
7F53059F0A08C8DE4981D6A686B3503D0563A710D91B3D4587C3D12062ABC1210CADABC6F0BD
9C6F46C87C5B4F0445E7253145EE26BA9D839BF45E9DBF635644F412DD4B1738030CDCCC82CD
370587F4CBA6796A2727D3D4871BF0D8CCD867F2A0F32A3109F049AC032601BB5CCA0E6BA807
50F88F1BBF77557CCAFE6FA24B5B5D8FC4941C4113C4042FAC0D2FDD50B304BF290C26ACCF79
3E990B1A10520413679408F42399684D4ADA9CBD5C6660768DB2CE468DDF698D5BA1A73D3BBA
49E96320D04B006B5F6B0387DB59F2E20250E5DFEA9160BCBF855801BF6998D481612D82F7D8
D6AF0B2034C9AFD9BF26E8202D9E8DB1633167D0F073A013EEBF466A4FAA74B6A5055A74932E
64AA1B75A8708C9C6825141E85714C48FAE391D02A0CC9E537A7E11D1E1E3CD08DC693355957
7DF07821F6D6AA36154BD16E3D158DE669351A48CA71603C4CA0F364286D4A4EB1CB90CF20A9
DD2BCD0BE17C8C04098D9720F7F7ACB02EE63EA496E690AF57B02643AE9301F23D42AB02D414
5AFEA48D26118066FF99EF12C0EEFB4BABDCCDA95EB52AD64583C7EA5E54417C2805179F18F5
7A0CDC2C3CB502D4A01E5149C072C732BDCE5CCFE8EC465BD66691E1841956D79BD027535412
031A9603B1C24D3D16B0A3AA3F5E00FC84A30E28C617138828CFC30BC40AA24B94159AC5336E
F47064572B18678738240635FD1DF47722DEA61933008B1022F9A258F47FA2AE762646EBD5C8
6B0C7F1983E306E0F42508DFD5B463E91147B198E31D30BC4A84D45C0631886D42204C196C98
01CD982ABC5387E9288CF00F0E5810C712DB51962982E3A91CAB88110C57FEF58D16621B3D6B
34C7E3FD7FDE1177869BE84FABB95D8F054A96375CB59C4711E5830D5FD13A7F4C14E4F2912A
2A4E8E3072776ABE39D3DEF4A62BB11A3A6006242437BF307DE502BF95EB193CE32BA6BB13A1
F219CA0F7EE76257B74C4DA5F0D7985BBA1A8750808D741C6080C024E78FC0F3BCD2E0DC8396
D434EC98BCC467F739AAC2E9BB78129CA55B53E08B20E35FC13B9AE4762BC784D49FDE8725AA
EF34FEB464E3833F232F5D7B02BEB2D95B17949FB3624836CB344E64890D3BDCF5F459B1A1D9
7E41798A7F5EFD69F9C5ABEADA042F4F42D3C5ED8D50123F7B92CCA9D2C5806A4486032E827A
12F6F8D21A54CBBFF57088495FD86A7956D6C56C3D5B546F69ABAC67F386357E1C524679E62B
AA462AE42B19754F8548C8F7BF74FA0192F53D408DC9C41AEDE772E28BC2D1FC39F5208257CC
05DABEC5F019D5EB9B22AA825D57D1BA2480EF6F1DE82C18106C6047A4E2342A460EE99856DD
DC84D76A3D081B2C31A7820CDF58BA8C1CA26FC6D607FA9EB0EE5D328362971EB10AED06B8FA
23F49C996A1FF7D2A2224B4BB0F7E1E7297C4B330EFADC80A590C3F0C090F532678738380920
7DF928C685C48AF18AD3A9CE962F6F0A0723C6A84D318CBBABC8F763B47CB66E1B349E7864A7
A0BE27796467C403F9568070BF1D1A57EC7E97F22FF181FCA31C8FBBDFE1E4EA643FB5066D17
4381BE4131107072B59A83AF99BEF336B8F72B8658738A84F71C4D7EAD13D28B4E49FF90A96D
43B21A68979132CEADB2459B1107781A64073404D0F81A65EAC799E8E723E3C49CCA370F2A74
572C4B755E1C4F92CB37143954BA6C748FCFD2BC5F780C745B1F0F965E63CF53400B78F84BE1
0ACD20809DDD376D1A9B3C515D8F1781793CE9F8A4E769BB5AE25B36914932B1B0922212E4C2
41DFE0E7C24233AF5BFDC3ECA9C81FFE34931643515273378D2190DE75A4AE5C1B8CBC4A5C76
30008840DDA0E02E050CDFDB2BC5ED535A8E7698B4AB489313F7926AC1DEF01ED849ACEF2859
870C7EE12DB2B0508F4E58268306E709842EAB264EDAF84C93C15FBE45CC0350571C6368DE76
EDC307261C153B88D7605EA8F64EE7B1CAAFB5E6AA8606291D3198C1D3EC1725D7A8E97656AB
5113198CF6FC2B2515BCAD112592FB7A4BE9A281326F045A70BF02188837BD474DA9BC46D195
19267990A6DB0673901158567CE1D87C4FE76823076DE5B2A5C0225B7DB7BA7ED41F0AAEB535
5D6F0AB463CA0C2E8FD24ADC4DB9C32C5A0E3698FED1AF65AFB0183CC582897ECC050D288C9E
15EC7DA6C3EB200CDC2537DA19918D251D52F76E45075B02513A2DDA4548CD65AB129811EB12
C2E0861123CAE229993E9E43346907A4C60DD7E4B73F8B0A5EDDB30CB3D9D5D63C153CA32451
9843F9E9F22953C0916DB5E8D81DE8BC056030740772DF56F0E314D223C3B2836D34D61F77A1
05C32B57F7F1791B119B1D98D5710D4C44977C7877DA90D37D82DD9669F81E913B8AEF9AE22E
FADC30D27FB913B94F8540022EC0554D6DA7D0C510398E1185C2441AD678ACC49485A48E6923
1139CE1D2626A2824FC04FCD35B8E52D9D3D9305C680B9BA341646FB2FCBCCA2B7787FA5DDC5
CC8713D431621DEACC951ED554572AB8020D7CD4A9C946BDCD2F58FE9AB0305C670E92C7E80A
079388C3FB1E85261BF22208A17E3E396D99324D215E85E282A47AEC771841BD13178FB8946B
D6CE634A00D8BE0567C8735556194EBCD2D6B6AC3D5416597840A9FE2E231C8D92E044194C6A
B8B4CA0301788FD2EE4747F48811341463DCD86F4B52F0AB5543FE931CED6D336D6DE4A2E1F9
1878ED8D2C238296752A29201B9CB8C063454D959C8D5AEC04AD76570E9CF59650E2B44B7E48
2B06C150C379EE272B7AF205F30CA1C2B6E30CB0D2E438DA4363A312BB1318C90EDEE938DB9F
0359B90FD6284681FD3CE99BC434616EDB354A62CE2BD42D784B742911003F05BA8BE03D1F52
FA8F0AC9F5879BC63B7829CCC64BE921E5CF2F6240FD6AD7A69D94B6340B818EE64A68FF894D
0AF596DA0DEBE47F306F764548A450A418A1C88875B8964FA725B65C77CCB6BC5939FE0E7625
74166CEF1839CDF76866B449AE2CFBD393E210EDD05D0526E454348059BF88B5AEED05841A10
C894A0C49026E064E385BAF440D7B975AEA6BF1267D360308829BD81DE6DB3D5BD47B66742D5
565607787CDB514F2C4B69FA22F053B22527B91FE4A3EBEDDA1352DBC0B4144DB5DC15AEB3C7
8CCF0CE264C76682FC1B7D3AA2566C8DD47787092AD80185D867DB7891E0CE12A52C954EFD3B
0CE23DC59C9B073685D14FC24A666DF88FCF20D0A93B4B28F8724F46D5368F2C195DC0EAB00A
03ED7A0531408D90884792E82A8B0FFC7CC6D1C2E1AB00E466744407FB81F6B9B20B0EAF2B50
A35EF6F78A9E9EC9D322515DDC6BF058B58CC6C036222F7434A1F27811CC551D36ED5169CF6F
0AA6D58563C8792D5B74F08BFF06189566F1D0C9E497CD116393EEEA1B853B5852F9221967EC
1DCFE14394C5A5C026093982FB19F166DC9F52053F1BC7F449E0285C1B9684D8853F587D408F
1C97BD1D082ABF41AB80F47D189DA6CAAD9F0A416CF040553DCE2A9C853A71151EC50CCC71A7
F6E0A0A9EFF458CCDCFB0D760AC0CB9B0BCE3D0979E898E42D43A78E17FAE3C33BAC5B4056FA
D86567DBCEF75EEC322572144FC26D7F81DC9EA718D91B0892E5621BBAE940619EE3693E87FB
A6BDBCD601FCAD972556DF2E1B0587A7BC8CBEDE01B02E19268F2D31C34712E4F4F29636E3A5
06013A7FDA0EB8C78FE7C2A561CD4F09D162C17BB69A13AA242B8E5B189010058A3005C16BE5
DE8975DC24D778EB03C2A59948C9BF3BB333AE0650E5DF0613C77A15F510ACB08C5C74519B79
C527B36BCE33BF023C9CAA159995F2992CC9731B6AB100604195DC5A79AC4A02D803A18683D3
9D25EBA9E584B3F3F64DF241E43B038C0D3111347CF2B421FB78FFCC03D3ED2A0C94D228AF07
C5FECCBC460541802660C19C05A52CD6C1CFF8CC805D43AF3D23FC9EC8408E73A49C1DFF48B8
6CD9B3104CA1515E98E41AB6496F4CF4218996692106BF443C933DB8A8CC275F5F1602881B68
B787738070A1B547D6EA0520CF599B4E674FE930596C8DDC4D1454B1DF79F092608FFAD0AC38
25A8A3EDB0C97C265B35EAA4A6D80C538BA24D209884A0BAB03847600E2623508DA7D8DA777A
168150698A63F5EA4ECD54309B4989ED2C7DFF8A3940384E5FE0295840C33A078C2860B65BE8
AA2B278185AA977110EB7B9A95BB0B52F1E124975D620E897FEBE57540103C873FDA64B37AA8
F82C56B1AA233ADC9B8864B820A76092E2B17EBDA1876D27B49FB5A1619881935FA499EF75EA
AB18E4496BF7493420750B13D06BFBE1326406C72112F6A497459952C412535CA38D41900180
F41A47FF6859B2B8CC20C4243511BF0386261D45BDED1F8C15E01CEBB891A07128473972DE3C
0EAF60856001E6C966FC1822C5613A8D2D3704AF91C363898BE178366FB56673B9600E2F7F2A
7CAA391181D36880A86B5ED389C7FD49D231E3E82999932075696C52BA761EA299359837E712
BDB5761E8D5FC3E8C5051E8BC673BC050CC0172B9676943426C646EC18C222514D9F21BB37D4
2CF66168B74E6A4EE3CDDFA12A183697A121938BA5D51AD4C57A4BD603092DC42F6E8E15E986
D1A0153977BC89AAC6AA7C5576B3905131D1889C33E313BC29D642F84D5B5DB5D301813407D8
ECE2DE61207F07EE2F018E7CBF6C5C3B504C37400436B711756EA09327237F743D8111C9D78C
A1186BF54B5487BED5F445857EF956C663F032EB59DFF3C4315F960E0F787F6553E11B34BAF3
B0FB6215866C80F47F52F9B67E878024F4C3ADC4C9018428BD04C6824BB1457CD59BB16FEFE2
AE1388FABE7B9C1C8ADA3491E64B6FABA0EB8EA80ACDA137CDEB8BCB39B5D1D038E7E664051B
76E86E4EC718D8B8EED85E5AB8CF85B6872D4E94A76D78C4358E5744023B705FE01D0B1848C9
2235AD874B45C4646E5C393157CBBBB6F08BCE4C6EA80A9A1276D9BD58E30015E20120CE473C
AE89AD929A9AD4E6AA02F3090377853FF1190152E4D285B66B4CD78F29B18F856F460748A2F6
D2B1454D4BB1EE72C4D90FBE896AC81690D77BDC2A0FB9655683131B97C44AD1BAF39A3D8E30
16D847411668B1A56B8F34B40F48DE144330F7711EF447457D7FDC409D56E100D55A28CF188B
D2DD182D29D5CE0050D6CD9EF549C9FEB628E20859C7E7C8D1D0A62D90E1AC0442B0B1AE7093
DA6797BB069D6FA94270F60D63E0CC361E9D95168DBD7F8314D5A6EB083AB1B6B4972A2E32B6
512AA3F8F4FBF5EBBC8EE7ECD5667F0DE7307C3642955FC083119BCC959BA8FF46D7608679F6
CCA0616825AD959761F6E1B8B77C134C33D20B98DDCC20E5A98E49CCB4EB395E6F299A411814
606AE676871914BEA847228F323852181EC68C2BE40A19F07B0617DB7E29DFBEF4DE984CC937
5581ACB67CB727A2FD95AD7954C77282EF61E432353555BA81F4B9E55E4E2A6E1DA1D3265856
769DE6AB519DCF2BB108D5D7A88C6ACA9B613134EA47198BCC2746A35E35281395A8D7E45036
51EF887F28C9FA6981BDE859B5AD042E6FCD25CAF05622B269B9DDC55832267E3276D8A605AB
8D0E690534CB1F5DDC8B22F05C2CD60D1020333CCE9F03E778E0C7F47A94DB9D692E80D19407
E4F287A1FE21C5A507497C2589080836B31E9D0C92E29FFFC0CB3B936B9EC41F3789F900D591
A8A7057284A64F16F5E280AF642A5257728F9667E9D977C7A9D2A4B5F0AA3DA9B8BF44D1F8CC
5FAA51234EA419D31144B7DAA62D51899A57B5F625657809065D9985664404356F107CDC6E6A
C2AAADAD1EAA1491B5196059D0826C85FC2F0CD9320ABF52960AEF7509CDBBAF288D348B84D6
27AD28E4697D8888D5A8DDD5C3B6AE1DE6F24AF231265767089985766ACA72F5BDB495CFA767
3A183BF5EE172AB5E6CB623074E036A315DB038F7F4FD1021C6DD6BA078AD3A374B898F90914
E1E082C38EF669C2BEDA91F4262B350721D6AA0F6AD384ACC92A588FCB79941461FE8C336D85
5E77CE41575CF1E7E233EB10F86A9B1666D5D2379222C5873AB2112A78F7FA5D5788017C94F5
44152E703815C091213CB2DFB73B6D3107E708398B0B7E99E393DA14A2C5D7FBDC76B6DBB6F9
355D1EBC6E8C27C58E0A5A0EBEDCE34B80F0276833B836C142FC8BF803331A9B442F346A3E60
0A2BF964C6CC7ACEA399B2817DD63A886B62C7134D6725CB8D657B1F7628B013BF2BBEB523B4
D8CD01A6D4DCACC87AD88D0FBF8565031728D473C1F56B920334F9BE3297D5D9D13BABEF159D
95D044A594B0F9A5808319C56CE0D271F3655DCBEA72AAFB6275BB036864E9F5EB129ACDE00D
BFCE57356F9C7348E6461043901A12664A19176214E442546CA0E2AD92B4A76F1D4FA8EE2E78
2806429EFD99F730D0A0FC0B3D94146E3B8100A202D20B43EF01D2A7352B6C0D72F57FA0F9F2
C80A84933C3233FB134E545F08F5203AD4E9A86AB08B80A78AC2E622507B6B2B7B3ED0432D6A
515757B02D6E1F3C1508F00AADC3D2EE15B5CDDAE5A3E1E45D7DC3935CF05596147BFF56A180
7F8F6A9C4A1A4780B9EBE18711BD28FE3AFCC7107368AE8F59ECC160AB493D58CA2A2BA7F17E
8665BC548E998BF7666AC6F41D9308A60169FFCB69D4A35BEC6F95DD8322F5772B97A1450947
44BCFBDFF1AA8C9900DB342E575ABC306CB00CF58AD5FC1640948A9659C9806DDD807331015C
F9F35B8F662969B4043C3B2803C8FBF663DC427CC5EC8A3B5D19DC6248576274745B1315179A
BB1A22BD3CD63BAA4C721F3D9E0B0851C71CD890A00B758FDCE1BA07BA757AF53A8AFC5DE21D
0BB65F1FCAA506CE41AD64933FC3DC0105BA561469A752B393354EBE44B6285B262626F0CFD3
89EF8BF3FBC27DDFCFE529F9A158D3DE78A900A9C075B1FBA4A9463279A06E45A9B54D9217C3
6EFF1260E6E4BA1B7FD4CE0B06E60254D5B9112D17408245988E9814B4DA07C828BBE90F846D
6926AE4133BBB22FA7A709B24A760182A3F135186AD6EEA89FC4E8E4CDD22328818C33F7B51D
3872BC59958E2D8E9FB8812597031B800416981EA2BC3D906EDACAC2C3F7DB135DEA0C089E1D
F29D3058649EF749F0615371EC5C33B236EDBCBFDC2703FBABF8AB149307CA265EA2F31020C7
AB90FDE03717D7F9141806EB0F51D8044608ABB461363EDA2C51E2A03E4438164A1ED38BDA6A
0963D5C58B5B8160E70EF06F5BBDFA56362902D8825B7D9909267F00CBCA118D06FCFA297F96
BD2A217741A12C15A38E2C22A6C4075DD242807EC7C8833F0FE3D2CC1D192DD6DEF423BD89D9
4D220BE67EBDC5E051E015E89BB4975B559EC47AB22734BBA890504D2A182C565258DCD6D9AF
F99726742D7D4DCD54C8451288744684D3DEB5C16CAE4A3D5E712E64EF5462B09C2FAF1EE71E
9A9E7D59A36FFBB2F3810CB5F57AF19B803DC7DD74C232A8C16E6CC952298CB0EC833519D900
50A2EF37221DD3C2EF17BA91D449F5585CD67A61BA5E50924B7284EB313FA38E722E40FF8C22
B85614D35EACFE3802E09FDEAE6BD67A8C9F258944C0274E7132188CAB333DA084FC83B01FEA
6960C8523EEEACA46F8A81D5CD76018F26B29959D4586DF9F1D37B10D33C54D8993B64943300
D58C20810D420A2FB777F989E9AF40F73F1A2FE89269BA0F8CF7028363548E20A0F09163AAC3
110EC78996C2988BC20912BD04FE1BB3CD8516E4D1BBCDD2C258B03980C399914D9AB61E67FA
273CAA1003D22A00B732DFFB659F634E236667085830535B9FA3A6FB09DA331E8EC879E5365A
180911204568524F45E0D6777D38BED818968E664FCB5D9298BB69009EDF7D417AFF14DDBEE0
07F23201A728B3E350825F7D30D82601908B47973995152E920E0FC4EB9C6C7F23FCC243D849
3BBA1CC6C48C34F2BBA180D46AAC7CA557D8A470503891A08332F22CE1878AA462D32D0D5F86
9FA4CEC032E385A311475FE853BDFA237D80A3765EDEEA4955C8AB844DBB144684EB1938B7B9
37B6BBDB35C6A240399596AB1DA8B1F8B76E1A65A59AA53E7FE5D99EB4F53EB86B828007AE49
1CBAAE32239ED78EC190CD7CDC81A0EC4B09E9C04DF92733DECF8984A0860D04EFFA220CD882
D27B6E3999690179C4B102458F78F61AB29A339A79D8063F547A588C8FEE8D391A660EC06631
FFF44042C125E6F2F2047022D78CDD3C2722B1CF366971B03CC722698D3342A6F92D39423D7B
73C60ACB78B3846B419EEF24EF6F14F6DE77DB07460D74C31B6673682884BF269FCBE690016B
C966E9A7A16DA643565E7ED417B0DFAFC844282EE2FC8EED142923B4AB007D7FB72A8CDEA682
CF96051AA111B16579E0C9444486525F9CF12359A6BAE88E2CE869A75EBFAA6C35F5DFECC810
B8508B7C4709EE0E8CDE730E984C199A673BA85F51ACBA7508920D5FAE52FCE5089C5439BCEE
F79EB48D8D6701333ACD8FDD10E156FB7C2FFBE0A104F7128F868B16149C7A280C2F53CBE2BF
22E3C342F11F49D2BBE5F7512BEF84FD218E97B1C0B7859F412155279BC80F1F6F1A54581496
B77C2C713FBD5B20785C57A0F4641FC0DF448D5E79F7125EBB17918C60385B79EF4345CDD44A
4AF266AC009BE62A9A6CD0752E266A9454FC1AC6F004704BC53D6414161F40CCB4F4CC2F2DA5
0D860E9EE2274026B0E84E110BE5D7198DB7A3330F02B913E11CA291B73CD0F9BA34B8272143
C96D13138F99C05A24D0F6A75C71D94A10ADBB1A47813307A5EDF32102AD9D25B89A64AB3A1E
6C4B87EC7416573B5AB977D672D9F6DDB48F710D4A4C9CEC91997C655276F25A00A570728709
2A79B33C5B79A43E44E5B175F576791ABCE72E9FCFDFD126649F8E59EC3248B15F262A00DB6E
A3327FEA2F1F9F12DD23EBD73953F8593D303518F8E37E427C122E43A87803EB749C7C9899D3
99E98C44EB1BAB1C0D0A334EC3F5659014F2693119CA3D0FF7E78D1F263E8737175EF80596F8
7ABA98EBBA1BA57615D71C738DF9C2059916CAB7F2916ADE2CEF7F5962D1A2973E83DC17B803
3666CB270942CAA780D57A8ED1255C13F2EBC68F41A850A20F69FA7598E3D978C700DAAEC71B
45542712F6BCE8E043E94680BAE51345C254978AA287707499C7784EEF7212C2B6455F2C30EC
1B0637D6AF1EB17E185D2B0C756CDF6C3FDF6EB8F734012971B13A0CD95F38DFC84C965AF61E
C31CB1830445F84A252423547ECFDA493A2A9C0F75FF5B7844764864A2FA724AE3DDB141A946
14D8B83C64F08DD9327357D58C3FB4B5AD4671866DAEAA3664514A1322D62AB645D4192112B3
738ED3A84281447597A84E0E0D377F881E5E02445EA5652713B4326A29B99F3FD64756F4C25B
CE52A6015538BB7FC519725BE94885A5FB18359EF03D764A04F1B67ABC3567DA01FDAF7C7ECE
65A10B249BA50EA113D5B32C9B0044B01D74CCFB2638BA533E9BB53E257949FE1F29D7112A14
0E0B766A2F3968F35CD0A6F497B2A4585E1A49D6EF91464B8A01412F4DC4D1703CCF5A9B03E1
0B528FEE23FBAE3D419D11956B65D8E9D73298817C207981940C029C67246BD743AB4FC15EA9
6BD451E6C1E599C554AB55BA921EA5FF370EEF85C70B5E877873B376B2734B8E5A855BF00D19
F9B37D882840394CEB15AD2C7D8EE6F50E1DF3682BF863B7CDA4B491464E46E73BEC1BD2410C
CFCED868896E83E230D69ED8E27673E5CF7628597BE47D05139DB3CEC1083AC21347C57D27CB
8B4085CCD54D50E4E7B6F0CB07A26DBCDB7522B5197ADC31E908079961D9B2D5D3CC0EE8055A
D31DF8546E4E417F1488B6477833A5A86AB95F495665B34AE46CF8CC4C33367F462F426662D4
99BE68D634F025D8F712FBA6A4145E8FB090FF5B61CD70E5550209C92530AFE1BAB70B715893
BC3532B9EDD957279FD92142798BA005E3D6C0BC95EB6E451B078FC6B1ABAE3FE77855BD7354
F02EAAC338DBA19689823399BBFF119850CB442E5B7323B356341A4AD204E8E05489CDD464E7
FEF19C5BBF5B495D91F70525675E5591FDB276576D6DF322A1085391F89941AE1216724D6C42
704B2C920AAB2FD78BFB5481098939A0B2C7D1D5CB8AA7AA31507A117E2E9AAE05CE84BAF157
91DF6D594D62C3857DBE27335AA79C909E4C2C571E0C3E1E6DF11B4996B8BC9EAF76575BEBEE
A7C51B2EB327CA1BC7684FFD06919FACD345D01BC3E1FDBF8DB5CDFECF107F7F5D5BE5E7A108
E189A0AC6DDA11749FF6EB3773DF65287E68C6F1FA8FFDBA58B9488186234E9D2B0F8A2EA96E
3C521AC756405853000FCDFCEEA528AEDD5E15FC8598F416456F52EF917DA951A0EBE9E6E863
F6CB778E0A5BE95D26A5D47C1EF7F07C10F2376D1869E05BE6DB2553126ACBCF4870385A1B1E
2FC1625B311752431EDBEAC958BEEFC8576C0FF32A26EA29D228E4E8D3D2B926150D736F13C9
1FABA41A9C3818775A536C2FE073D5830617559F2EAF8EAAEB3929AD970089443F934E1C937F
FAF9CC5EF69DA9E747BAF74D1279C82D37CEE291ACA600DEA23514A55A54E5ACF8805D52DC78
C7E4D0DDC1A3D02772D731BEE16F452D9398043275A551A097670645A2A4CF093EC252192FD5
59A780F79EF21472A10ECAD1542577C352B54256E11B93F267D11515056267DCCDA2C5AC2134
C32798F5706223409005EEC21998752034A3CBC845885933BFDEE7D1CB32FA84797FED209590
2E36BB359E0E79E78E9162E8F8DFBC9796423BB4B98F9A9FBBCEA1DD5DB31D431706D80C5C29
64532ED8AF6510441BE3757F5D9B53B8D9FF2DC6CB4E1F8D1B47F553C8D6D1962E9DF2A97FBA
979FBFB52F4D4CBA08A5A268CDC5A9A6CC40738577EC1836BD04B3ACF76E899655CA496A1B9F
5C9472A90F59DDED0D4C368306F5E3824CF013A7391EFC56986E179C79343B763DA88DE7F1B5
1E2756031154F752F7BC2A858EAA35C549CC24C932DDF0459F4CA70925ACF39065440C6B2FE4
8018D07A0F5F1975CC52CE85F8C7511AE1043B4CB421F5095AA0E1E588412DFA0D86CA55BFFD
F223EFC18D56DC7197AA1E8E08D4BACD388719AFDA2915579868B6B756A929B928EFDA008691
458FCA9FC5086D0FDFA6EDF122606C9ECA9C6D0163DE9F05F97E904BC6B1E0F538BDD9E1E5A3
63969EB55B4CAF47B2A55F27E9DEB5007942D2CB6A61AF76F7E3128B918D8C561C9A0510D5DC
8A8676DEEA7B0E5605F72BBBA35A6A24D6EA143CC8900D9A6F7755501969F25C3CC0F7928AA6
0E70FBB364CFD14531BD0B6B327A3AEAE1FB48C708CEFB4E369195ACB18A9F21177F868965E2
CA10074FEFFB10269E43C95B3BC7EEDE5DFA60998E7FEC6C568433F06EB48AE53D26C262E7C5
B349C64B493FFE2EE11D3D8CA4FF6B9CE4D37F4AD6765D37B3559106E3E80F2946E207523349
5048F3425505466F32FD35255978EA5467FC8FE4F6C147084E7A46C493876F647BD882CEE359
0D5B3EADEB5A72689DD0DB1C3A8B89771CFDF77D9637CB915DF7E0F8B1356477B35EEE547362
E97B58190EF9B3D4F442FAE6E7305DE0356CF604516912F4787EC315071578AC3DA58AD383D0
4840891CB3FA113EC89A2FA43E7CE250176A5DBCB516147CD09F5C11B2FA2C2B2D00D69FBF26
6D9B2E258ABA75883D48D100E04650F17DEFF97BF4C406DFEAE8A6202F56C18310BBA393553F
9BBFB054F5939FCDB910ACC0FB10ED21D7CF7A7430CCF97BE7FC77714DC4A287544DF41DB14D
B5FBF780CF8754FA7422C3F57E62CCEEAD9AA3470000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndFont
%%BeginProcSet: texps.pro
TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2
index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll
exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics
exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub
dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}
ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict
end definefont 3 -1 roll makefont /setfont load]cvx def}def
/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def
/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def
end
%%EndProcSet
TeXDict begin 40258431 52099146 1000 600 600 (main.dvi)
@start /Fa 205[33 33 49[{}2 58.333336 /CMR7 rf /Fb 149[27
21[39 11[54 72[{}3 58.333336 /CMMI7 rf /Fc 173[74 77
81[{}2 100.000000 /CMMI12 rf /Fd 133[50 59 3[62 44 44
46 2[56 62 93 31 2[31 62 1[34 51 62 50 1[54 11[86 1[62
3[84 88 106 3[42 6[80 9[56 56 56 56 56 56 56 56 2[31
46[{}33 100.000000 /CMBX12 rf /Fe 141[33 4[69 7[37 1[37
46 29[63 9[23 42 42 1[42 4[42 4[23 44[{}12 83.333336
/CMSL10 rf /Ff 139[62 4[62 4[62 4[62 1[62 62 32[62 14[62
50[{}8 119.999947 /CMTT12 rf /Fg 136[55 1[45 28 34 35
1[42 42 47 68 21 38 1[25 42 38 1[38 42 38 38 42 12[59
1[61 11[54 56 63 2[62 6[25 58[{}26 83.333336 /CMTI10
rf /Fh 240[42 14[65{}2 83.333336 /CMSY10 rf /Fi 134[71
2[71 75 52 53 55 1[75 67 75 112 3[37 75 67 41 61 75 60
1[65 13[75 2[92 11[103 16[67 67 67 2[37 46[{}25 119.999947
/CMBX12 rf /Fj 137[40 11[34 23[63 66 1[63 13[62 6[23
58[{}7 83.333336 /CMMI10 rf /Fk 133[44 44 44 44 44 44
44 44 44 1[44 44 44 44 44 44 44 44 44 44 44 44 44 44
44 44 1[44 1[44 1[44 44 44 44 44 44 44 44 44 44 44 44
44 44 44 44 2[44 44 44 44 44 44 44 44 44 2[44 44 44 44
44 7[44 44 44 1[44 44 44 1[44 44 44 6[44 33[{}67 83.333336
/CMTT10 rf /Fl 131[83 1[37 44 44 60 44 46 32 33 33 44
46 42 46 69 23 44 25 23 46 42 25 37 46 37 46 42 4[42
4[85 1[62 60 4[65 62 76 3[30 62 1[54 4[62 3[65 2[23 42
42 42 42 42 42 42 42 42 42 1[23 28 23 2[32 32 23 4[42
20[46 46 12[{}59 83.333336 /CMR10 rf /Fm 134[123 123
5[95 1[129 116 129 194 65 6[106 129 103 1[113 14[173
8[87 4[178 9[65 7[116 4[77 45[{}18 207.333359 /CMBX12
rf /Fn 190[106 14[106 50[{}2 207.333359 /CMTT12 rf /Fo
139[75 1[79 1[108 7[108 2[88 3[94 29[140 17[97 49[{}8
172.833374 /CMBX12 rf end
%%EndProlog
%%BeginSetup
%%Feature: *Resolution 600dpi
TeXDict begin
%%PaperSize: Letter
%%EndSetup
%%Page: 1 1
1 0 bop 0 1034 a Fo(Chapter)65 b(1)0 1470 y Fn(A2)p Fm(:)103
b(Real)78 b(or)f(complex)g(2-D)h(arra)-6 b(y)0 1923 y
Fl(The)29 b Fk(A2)g Fl(ob)5 b(ject)29 b(is)g(one)g(w)n(a)n(y)f(to)h
(store)g(and)g(op)r(erate)f(on)h(and)g(with)h(a)f(dense)g(matrix.)42
b(The)29 b(matrix)g(can)g(con)n(tain)f(either)0 2023
y(double)35 b(precision)f(real)g(or)h(complex)f(en)n(tries.)59
b(It)36 b(is)f(used)g(as)f(a)h(lo)n(w)n(er)f(lev)n(el)g(ob)5
b(ject)35 b(for)g(the)g Fk(DenseMtx)d Fl(ob)5 b(ject,)37
b(and)0 2122 y(during)27 b(the)h Fj(QR)g Fl(factorization)e(to)i(hold)f
(a)g(staircase)f(matrix.)0 2415 y Fi(1.1)135 b(Data)46
b(Structure)0 2617 y Fl(The)28 b Fk(A2)f Fl(structure)g(has)g(six)g
(\014elds.)125 2789 y Fh(\017)41 b Fk(int)h(type)26 b
Fl(:)37 b(t)n(yp)r(e)28 b(of)f(en)n(tries,)g Fk(SPOOLES)p
1527 2789 27 4 v 29 w(REAL)f Fl(or)g Fk(SPOOLES)p 2167
2789 V 29 w(COMPLEX)125 2948 y Fh(\017)41 b Fk(int)h(n1)27
b Fl(:)37 b(size)27 b(in)h(\014rst)f(dimension,)h(n)n(um)n(b)r(er)f(of)
h(ro)n(ws)125 3106 y Fh(\017)41 b Fk(int)h(n2)27 b Fl(:)37
b(size)27 b(in)h(second)f(dimension,)g(n)n(um)n(b)r(er)h(of)f(columns)
125 3265 y Fh(\017)41 b Fk(int)h(inc1)26 b Fl(:)37 b(incremen)n(t)27
b(or)g(stride)g(in)h(\014rst)f(dimension)125 3423 y Fh(\017)41
b Fk(int)h(inc2)26 b Fl(:)37 b(incremen)n(t)27 b(or)g(stride)g(in)h
(second)f(dimension)125 3581 y Fh(\017)41 b Fk(int)h(nowned)32
b Fl(:)49 b(the)35 b(n)n(um)n(b)r(er)f(of)g(en)n(tries)f(that)h(are)f
(\\o)n(wned")g(b)n(y)g(this)i(ob)5 b(ject.)56 b(When)34
b Fk(nowned)41 b(>)j(0)p Fl(,)35 b Fk(entries)208 3681
y Fl(p)r(oin)n(ts)e(to)g(storage)e(for)i Fk(nowned)e
Fl(en)n(tries,)j(\()p Fk(nowned)d(double)p Fl('s)g(for)i(the)h(real)e
(case,)i Fk(2*nowned)c(double)p Fl('s)h(for)i(the)208
3781 y(complex)26 b(case\),)g(that)h(ha)n(v)n(e)f(b)r(een)h(allo)r
(cated)f(b)n(y)h(this)g(ob)5 b(ject)26 b(and)h(can)f(b)r(e)h(free'd)g
(b)n(y)g(the)g(ob)5 b(ject.)36 b(When)27 b Fk(nowned)208
3880 y(==)42 b(0)34 b Fl(but)g Fk(n1)43 b(>)g(0)34 b
Fl(and)g Fk(n2)43 b(>)g(0)p Fl(,)35 b(this)f(ob)5 b(ject)34
b(p)r(oin)n(ts)g(to)g(en)n(tries)f(that)h(ha)n(v)n(e)f(b)r(een)h(allo)r
(cated)g(elsewhere,)g(and)208 3980 y(these)27 b(en)n(tries)g(will)h
(not)f(b)r(e)i(free'd)e(b)n(y)g(this)h(ob)5 b(ject.)125
4138 y Fh(\017)41 b Fk(double)g(*entries)24 b Fl(:)37
b(p)r(oin)n(ter)27 b(to)h(the)g(base)f(address)f(of)h(the)h
Fg(double)h Fl(v)n(ector)0 4310 y(One)e(can)g(query)g(the)h(prop)r
(erties)f(of)h(the)g(fron)n(t)f(matrix)g(ob)5 b(ject)27
b(using)g(these)h(simple)g(macros.)125 4482 y Fh(\017)41
b Fk(A2)p 301 4482 V 30 w(IS)p 419 4482 V 31 w(REAL\(mtx\))24
b Fl(is)j Fk(1)g Fl(if)h Fk(mtx)f Fl(has)g(real)g(en)n(tries)g(and)g
Fk(0)g Fl(otherwise.)125 4640 y Fh(\017)41 b Fk(A2)p
301 4640 V 30 w(IS)p 419 4640 V 31 w(COMPLEX\(mtx\))22
b Fl(is)28 b Fk(1)f Fl(if)h Fk(mtx)f Fl(has)g(complex)g(en)n(tries)g
(and)g Fk(0)g Fl(otherwise.)0 4812 y(The)18 b Fk(A2)p
254 4812 V 31 w(copyEntriesToVec)o(tor)o(\(\))12 b Fl(metho)r(d)19
b(uses)f(the)g(follo)n(wing)g(constan)n(ts:)31 b Fk(A2)p
2637 4812 V 30 w(STRICT)p 2931 4812 V 29 w(LOWER)p Fl(,)17
b Fk(A2)p 3308 4812 V 30 w(LOWER)p Fl(,)g Fk(A2)p 3686
4812 V 30 w(DIAGONAL)p Fl(,)0 4912 y Fk(A2)p 93 4912
V 31 w(UPPER)p Fl(,)25 b Fk(A2)p 480 4912 V 31 w(STRICT)p
775 4912 V 29 w(UPPER)p Fl(,)g Fk(A2)p 1160 4912 V 31
w(ALL)p 1323 4912 V 30 w(ENTRIES)p Fl(,)g Fk(A2)p 1797
4912 V 30 w(BY)p 1915 4912 V 31 w(ROWS)h Fl(and)h Fk(A2)p
2397 4912 V 31 w(BY)p 2516 4912 V 31 w(COLUMNS)p Fl(.)0
5204 y Fi(1.2)135 b(Protot)l(yp)t(es)46 b(and)f(descriptions)g(of)g
Ff(A2)f Fi(metho)t(ds)0 5407 y Fl(This)28 b(section)f(con)n(tains)f
(brief)i(descriptions)f(including)h(protot)n(yp)r(es)e(of)i(all)f
(metho)r(ds)h(that)g(b)r(elong)f(to)g(the)h Fk(A2)f Fl(ob)5
b(ject.)1929 5656 y(1)p eop
%%Page: 2 2
2 1 bop 0 100 a Fl(2)p 125 100 1212 4 v 1377 w Fk(A2)26
b Fe(:)37 b Fg(DRAFT)28 b Fe(Decem)n(b)r(er)f(16,)g(1998)p
2689 100 V 0 390 a Fd(1.2.1)112 b(Basic)38 b(metho)s(ds)0
573 y Fl(As)21 b(usual,)g(there)f(are)g(four)g(basic)g(metho)r(ds)g(to)
h(supp)r(ort)f(ob)5 b(ject)20 b(creation,)h(setting)f(default)h
(\014elds,)h(clearing)d(an)n(y)h(allo)r(cated)0 672 y(data,)27
b(and)h(free'ing)f(the)h(ob)5 b(ject.)101 889 y(1.)42
b Fk(A2)g(*)h(A2_new)f(\()h(void)f(\))h(;)208 1027 y
Fl(This)28 b(metho)r(d)g(simply)h(allo)r(cates)e(storage)f(for)h(the)i
Fk(A2)e Fl(structure)h(and)g(then)h(sets)f(the)g(default)h(\014elds)f
(b)n(y)g(a)f(call)h(to)208 1127 y Fk(A2)p 301 1127 27
4 v 30 w(setDefaultFields)o(\(\))p Fl(.)101 1302 y(2.)42
b Fk(void)f(A2_setDefaultFiel)o(ds)c(\()43 b(A2)g(*mtx)f(\))h(;)208
1440 y Fl(The)34 b(structure's)h(\014elds)g(are)e(set)i(to)g(default)g
(v)-5 b(alues:)51 b Fk(type)34 b Fl(=)g Fk(SPOOLES)p
2618 1440 V 29 w(REAL)p Fl(,)f Fk(n1)h Fl(=)h Fk(inc1)e
Fl(=)h Fk(n2)h Fl(=)f Fk(inc2)f Fl(=)208 1539 y Fk(nowned)25
b Fl(=)i(0)g(and)h Fk(entries)c Fl(=)k Fk(NULL)e Fl(.)208
1677 y Fg(Err)l(or)k(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n(ted)h(and)f
(the)h(program)e(exits.)101 1852 y(3.)42 b Fk(void)f(A2_clearData)e(\()
k(A2)g(*mtx)f(\))h(;)208 1990 y Fl(This)32 b(metho)r(d)i(clears)d(the)j
(ob)5 b(ject)32 b(and)h(free's)f(an)n(y)h(o)n(wned)f(data.)52
b(If)33 b Fk(nowned)41 b(>)j(0)32 b Fl(and)h Fk(entries)d
Fl(is)j(not)g Fk(NULL)p Fl(,)208 2090 y(then)28 b Fk(DVfree\(entries\))
21 b Fl(is)28 b(called)f(to)g(free)h(the)g(storage.)35
b(It)28 b(calls)e Fk(A2)p 2487 2090 V 31 w(setDefaultFields)o(\(\))p
Fl(.)208 2227 y Fg(Err)l(or)k(che)l(cking:)38 b Fl(If)28
b Fk(mtx)f Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n
(ted)h(and)f(the)h(program)e(exits.)101 2403 y(4.)42
b Fk(void)f(A2_free)g(\()i(A2)g(*mtx)f(\))h(;)208 2540
y Fl(This)27 b(metho)r(d)h(releases)e(an)n(y)h(storage)f(b)n(y)h(a)g
(call)g(to)h Fk(A2)p 1975 2540 V 30 w(clearData\(\))c
Fl(and)j(then)h(free)f(the)h(space)f(for)g Fk(mtx)p Fl(.)208
2678 y Fg(Err)l(or)j(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n(ted)h(and)f
(the)h(program)e(exits.)0 2948 y Fd(1.2.2)112 b(Instance)38
b(metho)s(ds)101 3130 y Fl(1.)k Fk(int)g(A2_nrow)f(\()i(A2)g(*mtx)e(\))
j(;)208 3268 y Fl(This)27 b(metho)r(d)h(returns)f(the)h(n)n(um)n(b)r
(er)f(of)h(ro)n(ws)e(in)i(the)g(matrix.)208 3405 y Fg(Err)l(or)i(che)l
(cking:)38 b Fl(If)28 b Fk(mtx)f Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d
(message)i(is)g(prin)n(ted)h(and)f(the)h(program)e(exits.)101
3581 y(2.)42 b Fk(int)g(A2_ncol)f(\()i(A2)g(*mtx)e(\))j(;)208
3718 y Fl(This)27 b(metho)r(d)h(returns)f(the)h(n)n(um)n(b)r(er)f(of)h
(columns)f(in)h(the)g(matrix.)208 3856 y Fg(Err)l(or)i(che)l(cking:)38
b Fl(If)28 b Fk(mtx)f Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i
(is)g(prin)n(ted)h(and)f(the)h(program)e(exits.)101 4032
y(3.)42 b Fk(int)g(A2_inc1)f(\()i(A2)g(*mtx)e(\))j(;)208
4169 y Fl(This)33 b(metho)r(d)h(returns)e(the)i(primary)e(incremen)n
(t,)i(the)g(stride)f(in)g(memory)g(\(with)h(resp)r(ect)f(to)g(real)f
(or)h(complex)208 4269 y(en)n(tries\))27 b(b)r(et)n(w)n(een)g(adjacen)n
(t)g(en)n(tries)g(in)h(the)g(same)f(column.)208 4406
y Fg(Err)l(or)j(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n(ted)h(and)f
(the)h(program)e(exits.)101 4582 y(4.)42 b Fk(int)g(A2_inc2)f(\()i(A2)g
(*mtx)e(\))j(;)208 4719 y Fl(This)28 b(metho)r(d)h(returns)f(the)h
(secondary)e(incremen)n(t,)i(the)g(stride)g(in)g(memory)e(\(with)j
(resp)r(ect)e(to)h(real)f(or)g(complex)208 4819 y(en)n(tries\))f(b)r
(et)n(w)n(een)g(adjacen)n(t)g(en)n(tries)g(in)h(the)g(same)f(ro)n(w.)
208 4957 y Fg(Err)l(or)j(che)l(cking:)38 b Fl(If)28 b
Fk(mtx)f Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n
(ted)h(and)f(the)h(program)e(exits.)101 5132 y(5.)42
b Fk(double)f(*)i(A2_entries)c(\()k(A2)g(*mtx)f(\))h(;)208
5270 y Fl(This)27 b(metho)r(d)h(returns)f(a)g(p)r(oin)n(ter)g(to)h(the)
g(base)f(address)f(of)i(the)g(en)n(tries.)208 5407 y
Fg(Err)l(or)i(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f Fl(is)g
Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n(ted)h(and)f(the)h
(program)e(exits.)p eop
%%Page: 3 3
3 2 bop 83 100 1212 4 v 1377 100 a Fk(A2)27 b Fe(:)37
b Fg(DRAFT)110 b Fe(Decem)n(b)r(er)28 b(16,)e(1998)p
2649 100 V 1212 w Fl(3)101 390 y(6.)42 b Fk(double)f(*)i(A2_row)e(\()i
(A2)g(*mtx,)e(int)i(irow)f(\))h(;)208 540 y Fl(This)27
b(metho)r(d)h(returns)f(a)g(p)r(oin)n(ter)g(to)h(the)g(leading)f
(elemen)n(t)h(of)f(ro)n(w)g Fk(irow)p Fl(.)208 690 y
Fg(Err)l(or)k(che)l(cking:)41 b Fl(If)29 b Fk(mtx)f Fl(or)g
Fk(entries)e Fl(is)j Fk(NULL)p Fl(,)e(or)h(if)i Fk(irow)d
Fl(is)i(not)f(in)i Fk([0,n1-1])p Fl(,)c(an)i(error)f(message)g(is)i
(prin)n(ted)208 790 y(and)e(the)h(program)e(exits.)101
990 y(7.)42 b Fk(double)f(*)i(A2_column)d(\()j(A2)g(*mtx,)e(int)h(jcol)
g(\))i(;)208 1140 y Fl(This)27 b(metho)r(d)h(returns)f(a)g(p)r(oin)n
(ter)g(to)h(the)g(leading)f(elemen)n(t)h(of)f(column)h
Fk(jcol)p Fl(.)208 1290 y Fg(Err)l(or)j(che)l(cking:)41
b Fl(If)29 b Fk(mtx)f Fl(or)g Fk(entries)e Fl(is)j Fk(NULL)p
Fl(,)e(or)h(if)i Fk(jcol)d Fl(is)i(not)f(in)i Fk([0,n2-1])p
Fl(,)c(an)i(error)f(message)g(is)i(prin)n(ted)208 1390
y(and)e(the)h(program)e(exits.)101 1590 y(8.)42 b Fk(void)f
(A2_realEntry)e(\()k(A2)g(*mtx,)f(int)g(irow,)f(int)i(jcol,)e(double)g
(*pValue)g(\))i(;)208 1740 y Fl(This)27 b(metho)r(d)h(\014lls)g
Fk(*pValue)d Fl(with)j(the)g(en)n(try)f(in)h(lo)r(cation)f
Fk(\(irow,)41 b(jcol\))p Fl(.)208 1890 y Fg(Err)l(or)29
b(che)l(cking:)37 b Fl(If)27 b Fk(mtx)e Fl(or)g Fk(pValue)f
Fl(is)i Fk(NULL)p Fl(,)f(or)g(if)i(the)g(matrix)e(is)h(not)h(real,)e
(or)h Fk(irow)e Fl(is)i(not)g(in)h Fk([0,n1-1])p Fl(,)c(or)j(if)208
1990 y Fk(jcol)g Fl(is)h(not)h(in)g Fk([0,n2-1])p Fl(,)c(an)j(error)f
(message)g(is)i(prin)n(ted)f(and)g(the)h(program)e(exits.)101
2190 y(9.)42 b Fk(void)f(A2_complexEntry)d(\()43 b(A2)g(*mtx,)e(int)i
(irow,)e(int)i(jcol,)1210 2290 y(double)e(*pReal,)g(double)g(*pImag)g
(\))i(;)208 2440 y Fl(This)27 b(metho)r(d)h(\014lls)g
Fk(\(*pReal,*pImag\))21 b Fl(with)28 b(the)g(en)n(try)f(in)h(lo)r
(cation)f Fk(\(irow,)41 b(jcol\))p Fl(.)208 2590 y Fg(Err)l(or)c(che)l
(cking:)53 b Fl(If)36 b Fk(mtx)p Fl(,)f Fk(pReal)e Fl(or)i
Fk(pImag)e Fl(is)i Fk(NULL)p Fl(,)e(or)h(if)i(the)f(matrix)g(is)g(not)g
(complex,)h(or)e Fk(irow)g Fl(is)h(not)g(in)208 2690
y Fk([0,n1-1])p Fl(,)24 b(or)j(if)h Fk(jcol)e Fl(is)h(not)h(in)g
Fk([0,n2-1])p Fl(,)c(an)j(error)f(message)g(is)i(prin)n(ted)f(and)h
(the)g(program)d(exits.)60 2890 y(10.)41 b Fk(void)g(A2_setRealEntry)d
(\()43 b(A2)g(*mtx,)e(int)i(irow,)e(int)i(jcol,)e(double)g(value)h(\))h
(;)208 3040 y Fl(This)27 b(metho)r(d)h(sets)g(en)n(try)f
Fk(\(irow,jcol\))c Fl(to)k Fk(value)p Fl(.)208 3190 y
Fg(Err)l(or)h(che)l(cking:)37 b Fl(If)26 b Fk(mtx)e Fl(is)i
Fk(NULL)p Fl(,)e(or)g(if)i(the)g(matrix)f(is)g(not)h(real,)f(or)f
Fk(irow)g Fl(is)h(not)h(in)f Fk([0,n1-1])d Fl(or)j(if)h
Fk(jcol)e Fl(is)h(not)208 3290 y(in)i Fk([0,n2-1])p Fl(,)e(an)i(error)f
(message)g(is)h(prin)n(ted)h(and)f(the)h(program)e(exits.)60
3490 y(11.)41 b Fk(void)g(A2_setComplexEntr)o(y)d(\()43
b(A2)g(*mtx,)e(int)h(irow,)g(int)g(jcol,)1341 3590 y(double)f(real,)g
(double)h(imag)f(\))j(;)208 3740 y Fl(This)27 b(metho)r(d)h(sets)g(en)n
(try)f Fk(\(irow,jcol\))c Fl(to)k Fk(\(real,imag\))p
Fl(.)208 3890 y Fg(Err)l(or)k(che)l(cking:)40 b Fl(If)29
b Fk(mtx)e Fl(is)h Fk(NULL)p Fl(,)f(or)h(if)h(the)g(matrix)f(is)g(not)h
(complex,)f(or)f Fk(irow)g Fl(is)i(not)f(in)h Fk([0,n1-1])c
Fl(or)j(if)h Fk(jcol)208 3989 y Fl(is)e(not)h(in)f Fk([0,n2-1])p
Fl(,)e(an)i(error)f(message)g(is)i(prin)n(ted)f(and)g(the)h(program)e
(exits.)60 4190 y(12.)41 b Fk(void)g(A2_pointerToRealE)o(ntr)o(y)c(\()
44 b(A2)e(*mtx,)g(int)g(irow,)g(int)g(jcol,)g(double)f(**ppValue)f(\))j
(;)208 4340 y Fl(This)27 b(metho)r(d)h(sets)g Fk(*ppValue)c
Fl(to)j(the)h(p)r(oin)n(ter)g(of)f(the)h Fk(\(irow,jcol\))23
b Fl(en)n(try)-7 b(.)208 4490 y Fg(Err)l(or)31 b(che)l(cking:)41
b Fl(If)30 b Fk(mtx)d Fl(or)h Fk(ppValue)e Fl(is)j Fk(NULL)p
Fl(,)f(or)g(if)h(the)g(matrix)g(is)f(not)h(real,)g(or)f(if)h
Fk(irow)e Fl(is)i(not)g(in)g Fk([0,n1-1])p Fl(,)208 4589
y(or)d(if)i Fk(jcol)e Fl(is)i(not)f(in)h Fk([0,n2-1])p
Fl(,)d(an)i(error)f(message)g(is)h(prin)n(ted)h(and)f(the)h(program)e
(exits.)60 4790 y(13.)41 b Fk(void)g(A2_pointerToCompl)o(exE)o(nt)o(ry)
c(\()43 b(A2)g(*mtx,)f(int)g(irow,)f(int)i(jcol,)1602
4889 y(double)e(**ppReal,)f(double)h(**ppImag)g(\))i(;)208
5039 y Fl(This)26 b(metho)r(d)h(sets)f Fk(*ppReal)e Fl(to)i(the)h(p)r
(oin)n(ter)g(to)f(the)h(real)e(part)h(of)h(the)g Fk(\(irow,jcol\))22
b Fl(en)n(try)-7 b(,)26 b(and)h(sets)f Fk(*ppImag)208
5139 y Fl(to)h(the)h(p)r(oin)n(ter)f(to)h(the)g(imaginary)e(part)h(of)g
(the)h Fk(\(irow,jcol\))23 b Fl(en)n(try)-7 b(.)208 5289
y Fg(Err)l(or)30 b(che)l(cking:)38 b Fl(If)28 b Fk(mtx)p
Fl(,)e Fk(ppReal)f Fl(or)i Fk(ppImag)e Fl(is)i Fk(NULL)p
Fl(,)f(or)h(if)g(the)h(matrix)f(is)g(not)h(complex,)f(or)f(if)i
Fk(irow)e Fl(is)h(not)h(in)208 5389 y Fk([0,n1-1])p Fl(,)c(or)j(if)h
Fk(jcol)e Fl(is)h(not)h(in)g Fk([0,n2-1])p Fl(,)c(an)j(error)f(message)
g(is)i(prin)n(ted)f(and)h(the)g(program)d(exits.)p eop
%%Page: 4 4
4 3 bop 0 100 a Fl(4)p 125 100 1212 4 v 1377 w Fk(A2)26
b Fe(:)37 b Fg(DRAFT)28 b Fe(Decem)n(b)r(er)f(16,)g(1998)p
2689 100 V 0 390 a Fd(1.2.3)112 b(Initialize)38 b(metho)s(ds)101
573 y Fl(1.)k Fk(void)f(A2_init)g(\()i(A2)g(*mtx,)f(int)g(type,)f(int)i
(n1,)f(int)h(n2,)f(int)g(inc1,)g(int)g(inc2,)905 673
y(double)f(*entries)f(\))j(;)208 811 y Fl(This)30 b(is)h(the)g(basic)f
(initializer)h(metho)r(d.)47 b(W)-7 b(e)31 b(require)e(that)i
Fk(mtx)f Fl(not)h(b)r(e)g Fk(NULL)p Fl(,)e Fk(type)g
Fl(b)r(e)j(either)e Fk(SPOOLES)p 3702 811 27 4 v 29 w(REAL)208
911 y Fl(or)d Fk(SPOOLES)p 623 911 V 29 w(COMPLEX)p Fl(,)e
Fk(n1)j Fl(and)g Fk(n2)g Fl(b)r(oth)h(b)r(e)g(p)r(ositiv)n(e,)f(and)h
(b)r(oth)f Fk(inc1)f Fl(and)i Fk(inc2)e Fl(b)r(oth)i(b)r(e)f(p)r
(ositiv)n(e)g(and)h(that)208 1010 y(one)g(of)h(them)h(b)r(e)f(equal)g
(to)g(one.)44 b(Also,)30 b(w)n(e)g(only)f(initialize)i(a)e(full)i
(matrix,)f(i.e.,)h(one)f(of)g Fk(inc1)42 b(=)h(1)30 b
Fl(and)f Fk(inc2)42 b(=)208 1110 y(nrow)26 b Fl(or)g
Fk(inc1)42 b(=)h(ncol)26 b Fl(and)i Fk(inc2)42 b(=)h(1)27
b Fl(m)n(ust)h(hold.)208 1248 y(The)g(ob)5 b(ject)29
b(is)f(\014rst)g(cleared)g(with)h(a)f(call)h(to)f Fk(A2)p
1780 1248 V 31 w(clearData\(\))p Fl(.)35 b(If)29 b Fk(entries)d
Fl(is)i Fk(NULL)f Fl(then)i Fk(n1*n2)e Fl(new)i(en)n(tries)208
1348 y(are)h(found,)k Fk(mtx->entries)27 b Fl(is)32 b(set)f(to)h(this)g
(address)f(and)h Fk(nowned)d Fl(is)j(set)g(to)g Fk(n1*n2)p
Fl(.)48 b(If)32 b Fk(entries)d Fl(is)j(not)g Fk(NULL)p
Fl(,)208 1447 y(then)c Fk(mtx->entries)22 b Fl(is)28
b(set)f(to)h Fk(entries)d Fl(and)i Fk(nowned)e Fl(is)j(set)f(to)h
(zero.)208 1586 y Fg(Err)l(or)e(che)l(cking:)37 b Fl(If)25
b Fk(mtx)d Fl(is)i Fk(NULL)p Fl(,)f(or)g(if)h Fk(n1)p
Fl(,)g Fk(n2)p Fl(,)g Fk(inc1)f Fl(or)g Fk(inc2)f Fl(are)h(less)h(than)
g(or)f(equal)g(to)h(zero,)g(or)f(if)h(the)h(matrix)208
1685 y(is)k(not)h(full)h(matrix)e(\(i.e.,)i Fk(inc1)d
Fl(m)n(ust)i(b)r(e)g Fk(1)f Fl(and)h Fk(inc2)e Fl(m)n(ust)i(b)r(e)g
Fk(n1)p Fl(,)g Fg(or)g Fk(inc1)f Fl(m)n(ust)h(b)r(e)g
Fk(n2)f Fl(and)h Fk(inc2)e Fl(m)n(ust)i(b)r(e)208 1785
y Fk(1)p Fl(\),)d(an)g(error)f(message)g(is)i(prin)n(ted)f(and)h(zero)e
(is)i(returned.)101 1962 y(2.)42 b Fk(void)f(A2_subA2)g(\()i(A2)g
(*mtxA,)e(A2)i(*mtxB,)905 2061 y(int)f(firstrow,)e(int)i(lastrow,)f
(int)h(firstcol,)e(int)i(lastcol)f(\))i(;)208 2199 y
Fl(This)27 b(initializer)g(metho)r(d)h(mak)n(es)f(the)h(ob)5
b(ject)27 b Fk(mtxA)f Fl(p)r(oin)n(t)i(in)n(to)f(a)h(submatrix)f(of)g
(ob)5 b(ject)28 b Fk(mtxB)p Fl(,)e(as)208 2409 y Fk(A\(0:lastrow-fir)o
(str)o(ow)o(,0)o(:la)o(st)o(col)o(-f)o(ir)o(stc)o(ol)o(\))38
b(=)43 b(B\(firstrow:lastr)o(ow)o(,)37 b(firstcol:lastcol\))208
2619 y Fl(Note,)20 b Fk(firstrow)p Fl(,)d Fk(lastrow)p
Fl(,)g Fk(firstcol)f Fl(and)i Fk(lastcol)d Fl(m)n(ust)k(satisfy)f
Fk(0)43 b(<=)g(firstrow)d(<=)j(lastrow)d(<)k(mtxB->n1)208
2719 y Fl(and)28 b Fk(0)43 b(<=)g(firstcol)d(<=)j(lastcol)e(<)i
(mtxB->n2)p Fl(.)37 b(Ob)5 b(ject)28 b Fk(mtxA)f Fl(do)r(es)i(not)f(o)n
(wn)g(its)h(en)n(tries,)f(but)i(p)r(oin)n(ts)e(in)n(to)208
2819 y(the)g(en)n(tries)e(of)i Fk(mtxB)p Fl(.)208 2957
y Fg(Err)l(or)i(che)l(cking:)39 b Fl(If)28 b Fk(mtxA)e
Fl(or)h Fk(mtxB)f Fl(are)h Fk(NULL)p Fl(,)f(or)h(if)h
Fk(firstrow)c Fl(or)j Fk(lastrow)e Fl(are)i(out)g(of)h(range,)e(or)h
(if)h Fk(firstcol)208 3056 y Fl(or)e Fk(lastcol)f Fl(are)i(out)g(of)h
(range,)e(an)h(error)f(message)g(is)i(prin)n(ted)f(and)h(zero)e(is)i
(returned.)0 3328 y Fd(1.2.4)112 b(Metho)s(ds)39 b(used)f(in)g(the)f
Fc(QR)i Fd(factorization)101 3511 y Fl(1.)j Fk(void)f(A2_makeStaircase)
c(\()44 b(A2)e(*mtxA)g(\))h(;)208 3649 y Fl(This)34 b(metho)r(d)h(p)r
(erm)n(utes)f(the)h(ro)n(ws)e(of)h Fk(mtxA)f Fl(b)n(y)i(the)f(lo)r
(cation)g(of)h(the)f(leading)g(nonzero)f(of)i(eac)n(h)e(ro)n(w.)57
b(Up)r(on)208 3749 y(return,)27 b(the)h(matrix)f(is)g(in)h
Fg(stair)l(c)l(ase)h Fl(form.)208 3887 y Fg(Err)l(or)h(che)l(cking:)38
b Fl(If)28 b Fk(mtxA)e Fl(is)i Fk(NULL)p Fl(,)e(an)h(error)f(message)g
(is)i(prin)n(ted)f(and)h(the)g(program)d(exits.)101 4064
y(2.)42 b Fk(double)f(A2_QRreduce)e(\()k(A2)g(*mtxA,)e(DV)h(*workDV,)f
(int)h(msglvl,)f(FILE)h(*msgFile)e(\))j(;)208 4202 y
Fl(This)35 b(metho)r(d)h(computes)f Fj(A)h Fl(=)g Fj(QR)f
Fl(factorization.)59 b(On)35 b(return,)i(the)f(matrix)e
Fj(Q)h Fl(is)h(not)f(a)n(v)-5 b(ailable,)36 b(and)f Fj(R)h
Fl(is)208 4302 y(found)f(in)h(the)g(upp)r(er)f(triangle)g(or)f(upp)r
(er)i(trap)r(ezoid)e(of)i Fk(mtxA)p Fl(.)e(The)h(Householder)f(v)n
(ectors)g(are)h(stored)f(in)i(the)208 4401 y(lo)n(w)n(er)28
b(triangle)h(of)h Fk(mtxA)p Fl(,)f(with)h Fj(v)1290 4413
y Fb(j)1326 4401 y Fl(\()p Fj(j)5 b Fl(\))27 b(=)g(1)p
Fj(:)p Fl(0.)44 b(The)30 b(return)g(v)-5 b(alue)29 b(is)h(the)h(n)n(um)
n(b)r(er)f(of)g(\015oating)f(p)r(oin)n(t)h(op)r(erations)208
4501 y(that)d(w)n(ere)g(executed.)208 4639 y Fg(Err)l(or)i(che)l
(cking:)38 b Fl(If)27 b Fk(mtxA)e Fl(or)h Fk(workDV)f
Fl(is)h Fk(NULL)p Fl(,)f(or)h(if)h Fk(msglvl)41 b(>)j(0)26
b Fl(and)g Fk(msgFile)e Fl(if)k Fk(NULL)p Fl(,)d(an)h(error)f(message)g
(is)208 4739 y(prin)n(ted)i(and)g(the)h(program)e(exits.)101
4915 y(3.)42 b Fk(void)f(A2_computeQ)f(\()j(A2)f(*mtxQ,)g(A2)g(*mtxA,)f
(DV)i(*workDV,)d(int)j(msglvl,)d(FILE)i(*msgFile)f(\))i(;)208
5054 y Fl(This)32 b(metho)r(d)h(computes)f Fj(Q)g Fl(from)g(the)g
Fj(A)f Fl(=)g Fj(QR)h Fl(factorization)f(computed)i(in)f
Fk(A2)p 2948 5054 V 31 w(QRreduce\(\))p Fl(.)46 b(Note:)h
Fk(mtxA)208 5153 y Fl(and)27 b Fk(mtxQ)f Fl(m)n(ust)i(b)r(e)g(column)f
(ma)5 b(jor.)208 5291 y Fg(Err)l(or)38 b(che)l(cking:)57
b Fl(If)37 b Fk(mtxQ)p Fl(,)e Fk(mtxA)g Fl(or)h Fk(workDV)e
Fl(is)j Fk(NULL)p Fl(,)e(or)g(if)j Fk(msglvl)j(>)i(0)36
b Fl(and)h Fk(msgFile)c Fl(if)38 b Fk(NULL)p Fl(,)d(an)h(error)208
5391 y(message)26 b(is)h(prin)n(ted)h(and)f(the)h(program)e(exits.)p
eop
%%Page: 5 5
5 4 bop 83 100 1212 4 v 1377 100 a Fk(A2)27 b Fe(:)37
b Fg(DRAFT)110 b Fe(Decem)n(b)r(er)28 b(16,)e(1998)p
2649 100 V 1212 w Fl(5)0 390 y Fd(1.2.5)112 b(Norm)38
b(metho)s(ds)0 566 y Fl(These)27 b(metho)r(ds)h(return)f(a)g(norm)g(of)
h(a)f(ro)n(w)g(or)f(a)h(column,)h(or)f(the)h(easily)f(computable)g
(norms)g(of)g(the)h(matrix.)101 746 y(1.)42 b Fk(double)f(A2_maxabs)f
(\()j(A2)f(*mtx)g(\))i(;)208 876 y Fl(This)27 b(metho)r(d)h(returns)f
(magnitude)h(of)f(the)h(en)n(try)f(with)h(largest)e(magnitude.)208
1007 y Fg(Err)l(or)k(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n(ted)h(and)f
(the)h(program)e(exits.)101 1168 y(2.)42 b Fk(double)f(A2_frobNorm)e
(\()k(A2)g(*mtx)f(\))h(;)208 1299 y Fl(This)27 b(metho)r(d)h(returns)f
(the)h(F)-7 b(rob)r(enius)27 b(norm)g(of)h(the)g(matrix.)208
1429 y Fg(Err)l(or)i(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n(ted)h(and)f
(the)h(program)e(exits.)101 1591 y(3.)42 b Fk(double)f(A2_oneNorm)e(\()
k(A2)g(*mtx)f(\))h(;)208 1721 y Fl(This)27 b(metho)r(d)h(returns)f(the)
h(one)f(norm)g(of)h(the)g(matrix.)208 1852 y Fg(Err)l(or)i(che)l
(cking:)38 b Fl(If)28 b Fk(mtx)f Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d
(message)i(is)g(prin)n(ted)h(and)f(the)h(program)e(exits.)101
2013 y(4.)42 b Fk(double)f(A2_infinityNorm)c(\()43 b(A2)g(*mtx)f(\))h
(;)208 2144 y Fl(This)27 b(metho)r(d)h(returns)f(the)h(in\014nit)n(y)g
(norm)f(of)h(the)g(matrix.)208 2274 y Fg(Err)l(or)i(che)l(cking:)38
b Fl(If)28 b Fk(mtx)f Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i
(is)g(prin)n(ted)h(and)f(the)h(program)e(exits.)101 2436
y(5.)42 b Fk(double)f(A2_oneNormOfCol)o(umn)c(\()43 b(A2)g(*mtx,)e(int)
i(jcol)f(\))h(;)208 2566 y Fl(This)27 b(metho)r(d)h(returns)f(the)h
(one-norm)e(of)i(column)f Fk(jcol)f Fl(of)i(the)g(matrix.)208
2697 y Fg(Err)l(or)d(che)l(cking:)36 b Fl(If)22 b Fk(mtx)f
Fl(is)h Fk(NULL)p Fl(,)e(or)i Fk(jcol)e Fl(is)i(not)g(in)g
Fk([0,n2-1])p Fl(,)e(an)i(error)e(message)h(is)h(prin)n(ted)g(and)g
(the)g(program)208 2796 y(exits.)101 2958 y(6.)42 b Fk(double)f
(A2_twoNormOfCol)o(umn)c(\()43 b(A2)g(*mtx,)e(int)i(jcol)f(\))h(;)208
3088 y Fl(This)27 b(metho)r(d)h(returns)f(the)h(t)n(w)n(o-norm)e(of)h
(column)h Fk(jcol)e Fl(of)i(the)g(matrix.)208 3219 y
Fg(Err)l(or)d(che)l(cking:)36 b Fl(If)22 b Fk(mtx)f Fl(is)h
Fk(NULL)p Fl(,)e(or)i Fk(jcol)e Fl(is)i(not)g(in)g Fk([0,n2-1])p
Fl(,)e(an)i(error)e(message)h(is)h(prin)n(ted)g(and)g(the)g(program)208
3319 y(exits.)101 3480 y(7.)42 b Fk(double)f(A2_infinityNorm)o(OfC)o
(ol)o(umn)c(\()43 b(A2)g(*mtx,)e(int)i(jcol)e(\))j(;)208
3611 y Fl(This)27 b(metho)r(d)h(returns)f(the)h(in\014nit)n(y-norm)f
(of)h(column)f Fk(jcol)f Fl(of)i(the)g(matrix.)208 3741
y Fg(Err)l(or)d(che)l(cking:)36 b Fl(If)22 b Fk(mtx)f
Fl(is)h Fk(NULL)p Fl(,)e(or)i Fk(jcol)e Fl(is)i(not)g(in)g
Fk([0,n2-1])p Fl(,)e(an)i(error)e(message)h(is)h(prin)n(ted)g(and)g
(the)g(program)208 3841 y(exits.)101 4002 y(8.)42 b Fk(double)f
(A2_oneNormOfRow)c(\()43 b(A2)g(*mtx,)e(int)i(irow)f(\))h(;)208
4133 y Fl(This)27 b(metho)r(d)h(returns)f(the)h(one-norm)e(of)i(ro)n(w)
e Fk(irow)g Fl(of)i(the)g(matrix.)208 4263 y Fg(Err)l(or)d(che)l
(cking:)36 b Fl(If)22 b Fk(mtx)f Fl(is)h Fk(NULL)p Fl(,)e(or)i
Fk(irow)e Fl(is)i(not)g(in)g Fk([0,n1-1])p Fl(,)e(an)i(error)e(message)
h(is)h(prin)n(ted)g(and)g(the)g(program)208 4363 y(exits.)101
4524 y(9.)42 b Fk(double)f(A2_twoNormOfRow)c(\()43 b(A2)g(*mtx,)e(int)i
(irow)f(\))h(;)208 4655 y Fl(This)27 b(metho)r(d)h(returns)f(the)h(t)n
(w)n(o-norm)e(of)h(ro)n(w)g Fk(irow)f Fl(of)h(the)h(matrix.)208
4785 y Fg(Err)l(or)d(che)l(cking:)36 b Fl(If)22 b Fk(mtx)f
Fl(is)h Fk(NULL)p Fl(,)e(or)i Fk(irow)e Fl(is)i(not)g(in)g
Fk([0,n1-1])p Fl(,)e(an)i(error)e(message)h(is)h(prin)n(ted)g(and)g
(the)g(program)208 4885 y(exits.)60 5046 y(10.)41 b Fk(double)g
(A2_infinityNorm)o(OfR)o(ow)c(\()43 b(A2)g(*mtx,)e(int)i(irow)f(\))h(;)
208 5177 y Fl(This)27 b(metho)r(d)h(returns)f(the)h(in\014nit)n(y-norm)
f(of)h(ro)n(w)e Fk(irow)g Fl(of)i(the)g(matrix.)208 5308
y Fg(Err)l(or)d(che)l(cking:)36 b Fl(If)22 b Fk(mtx)f
Fl(is)h Fk(NULL)p Fl(,)e(or)i Fk(irow)e Fl(is)i(not)g(in)g
Fk([0,n1-1])p Fl(,)e(an)i(error)e(message)h(is)h(prin)n(ted)g(and)g
(the)g(program)208 5407 y(exits.)p eop
%%Page: 6 6
6 5 bop 0 100 a Fl(6)p 125 100 1212 4 v 1377 w Fk(A2)26
b Fe(:)37 b Fg(DRAFT)28 b Fe(Decem)n(b)r(er)f(16,)g(1998)p
2689 100 V 0 390 a Fd(1.2.6)112 b(Sort)37 b(metho)s(ds)101
569 y Fl(1.)42 b Fk(void)f(A2_permuteRows)d(\()43 b(A2)g(*mtx,)f(int)g
(nrow,)g(int)g(index[])f(\))i(;)208 702 y Fl(The)31 b
Fk(index[])d Fl(v)n(ector)i(con)n(tains)g(the)i Fg(r)l(ow)h(ids)f
Fl(of)f(the)g(leading)g Fk(nrow)f Fl(ro)n(ws.)46 b(This)31
b(metho)r(d)g(p)r(erm)n(utes)g(the)h(lead-)208 802 y(ing)37
b Fk(nrow)f Fl(ro)n(ws)g(of)h(the)h(matrix)f(so)g(that)h(the)f
Fk(index[])e Fl(v)n(ector)h(is)i(in)f(ascending)g(order.)65
b(This)38 b(metho)r(d)g(calls)208 902 y Fk(A2)p 301 902
27 4 v 30 w(permuteRows\(\))22 b Fl(but)29 b(do)r(es)e(not)g(o)n(v)n
(erwrite)f(the)i Fk(index[])d Fl(v)n(ector.)208 1035
y Fg(Err)l(or)31 b(che)l(cking:)43 b Fl(If)30 b Fk(mtx)e
Fl(or)h Fk(index[])d Fl(is)k Fk(NULL)p Fl(,)d(or)i(if)h
Fk(nrow)42 b(<)h(0)29 b Fl(or)g Fk(nrow)42 b(>)h(n1)p
Fl(,)29 b(an)g(error)f(message)g(is)h(prin)n(ted)208
1135 y(and)e(the)h(program)e(exits.)101 1302 y(2.)42
b Fk(void)f(A2_permuteColumns)c(\()43 b(A2)g(*mtx,)e(int)i(nrow,)e(int)
i(index[])d(\))k(;)208 1435 y Fl(The)35 b Fk(index[])e
Fl(v)n(ector)i(con)n(tains)f(the)j Fg(c)l(olumn)g(ids)f
Fl(of)g(the)g(leading)f Fk(ncol)f Fl(ro)n(ws.)60 b(This)36
b(metho)r(d)g(p)r(erm)n(utes)g(the)208 1535 y(leading)c
Fk(ncol)f Fl(columns)i(of)f(the)i(matrix)e(so)g(that)h(the)g
Fk(index[])d Fl(v)n(ector)i(is)h(in)g(ascending)f(order.)51
b(This)33 b(metho)r(d)208 1634 y(calls)27 b Fk(A2)p 486
1634 V 30 w(permuteColumns\(\))21 b Fl(but)28 b(do)r(es)g(not)f(o)n(v)n
(erwrite)f(the)i Fk(index[])c Fl(v)n(ector.)208 1768
y Fg(Err)l(or)31 b(che)l(cking:)43 b Fl(If)30 b Fk(mtx)e
Fl(or)h Fk(index[])d Fl(is)k Fk(NULL)p Fl(,)d(or)i(if)h
Fk(ncol)42 b(<)h(0)29 b Fl(or)g Fk(ncol)42 b(>)h(n2)p
Fl(,)29 b(an)g(error)f(message)g(is)h(prin)n(ted)208
1867 y(and)e(the)h(program)e(exits.)101 2035 y(3.)42
b Fk(int)g(A2_sortRowsUp)c(\()43 b(A2)g(*mtx,)f(int)g(nrow,)f(int)i
(rowids[])d(\))j(;)208 2168 y Fl(This)e(metho)r(d)g(sorts)f(the)i
(leading)e Fk(nrow)g Fl(ro)n(ws)f(of)i(the)h(matrix)e(in)n(to)h
(ascending)f(order)g(with)i(resp)r(ect)f(to)g(the)208
2268 y Fk(rowids[])24 b Fl(v)n(ector.)36 b(The)27 b(return)g(v)-5
b(alue)28 b(is)f(the)h(n)n(um)n(b)r(er)g(of)f(ro)n(w)f(sw)n(aps)h
(made.)208 2401 y Fg(Err)l(or)34 b(che)l(cking:)47 b
Fl(If)32 b Fk(mtx)f Fl(or)g Fk(rowids)e Fl(is)j Fk(NULL)p
Fl(,)e(or)h(if)i Fk(nrow)42 b(<)h(0)31 b Fl(or)g Fk(nrow)42
b(>)h(n1)p Fl(,)33 b(an)e(error)f(message)g(is)i(prin)n(ted)208
2501 y(and)27 b(the)h(program)e(exits.)101 2668 y(4.)42
b Fk(int)g(A2_sortColumnsUp)37 b(\()43 b(A2)g(*mtx,)e(int)i(ncol,)e
(int)i(colids[])d(\))j(;)208 2801 y Fl(This)30 b(metho)r(d)i(sorts)d
(the)j(leading)e Fk(ncol)f Fl(columnss)i(of)f(the)i(matrix)e(in)n(to)h
(ascending)e(order)h(with)h(resp)r(ect)g(to)g(the)208
2901 y Fk(colids[])24 b Fl(v)n(ector.)36 b(The)27 b(return)g(v)-5
b(alue)28 b(is)f(the)h(n)n(um)n(b)r(er)g(of)f(column)h(sw)n(aps)e
(made.)208 3034 y Fg(Err)l(or)34 b(che)l(cking:)47 b
Fl(If)32 b Fk(mtx)f Fl(or)g Fk(colids)e Fl(is)j Fk(NULL)p
Fl(,)e(or)h(if)i Fk(ncol)42 b(<)h(0)31 b Fl(or)g Fk(ncol)42
b(>)h(n2)p Fl(,)33 b(an)e(error)f(message)g(is)i(prin)n(ted)208
3134 y(and)27 b(the)h(program)e(exits.)0 3393 y Fd(1.2.7)112
b(Utilit)m(y)38 b(metho)s(ds)101 3571 y Fl(1.)k Fk(int)g(A2_sizeOf)e
(\()j(A2)g(*mtx)f(\))h(;)208 3705 y Fl(This)27 b(metho)r(d)h(returns)f
(the)h(n)n(um)n(b)r(er)f(of)h(b)n(ytes)f(o)n(wned)g(b)n(y)h(this)f(ob)5
b(ject.)208 3838 y Fg(Err)l(or)30 b(che)l(cking:)38 b
Fl(If)28 b Fk(mtx)f Fl(is)g Fk(NULL)f Fl(an)i(error)d(message)h(is)i
(prin)n(ted)f(and)h(the)g(program)d(exits.)101 4005 y(2.)42
b Fk(void)f(A2_shiftBase)e(\()k(A2)g(*mtx,)f(int)g(rowoff,)f(int)h
(coloff)f(\))i(;)208 4139 y Fl(This)27 b(metho)r(d)h(is)g(used)f(to)h
(shift)g(the)g(base)f(of)h(the)f(en)n(tries)g(and)h(adjust)g
(dimensions)f(of)g(the)h Fk(A2)f Fl(ob)5 b(ject.)208
4339 y Fk(mtx\(0:n1-rowoff)o(-1,)o(0:)o(n2)o(-co)o(lo)o(ff-)o(1\))37
b(:=)43 b(mtx\(rowoff:n1-1)o(,co)o(lo)o(ff:)o(n2)o(-1)o(\))208
4539 y Fg(Err)l(or)30 b(che)l(cking:)38 b Fl(If)28 b
Fk(mtx)f Fl(is)g Fk(NULL)f Fl(an)i(error)d(message)h(is)i(prin)n(ted)f
(and)h(the)g(program)d(exits.)101 4706 y(3.)42 b Fk(int)g(A2_rowMajor)d
(\()k(A2)g(*mtx)f(\))h(;)208 4840 y Fl(This)27 b(metho)r(d)h(returns)f
(1)g(if)h(the)g(storage)e(is)i(ro)n(w)e(ma)5 b(jor,)26
b(otherwise)h(it)h(returns)f(zero.)208 4973 y Fg(Err)l(or)j(che)l
(cking:)38 b Fl(If)28 b Fk(mtx)f Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d
(message)i(is)g(prin)n(ted)h(and)f(the)h(program)e(exits.)101
5140 y(4.)42 b Fk(int)g(A2_columnMajor)c(\()43 b(A2)g(*mtx)f(\))h(;)208
5274 y Fl(This)27 b(metho)r(d)h(returns)f(1)g(if)h(the)g(storage)e(is)i
(column)f(ma)5 b(jor,)27 b(otherwise)f(it)i(returns)f(zero.)208
5407 y Fg(Err)l(or)j(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n(ted)h(and)f
(the)h(program)e(exits.)p eop
%%Page: 7 7
7 6 bop 83 100 1212 4 v 1377 100 a Fk(A2)27 b Fe(:)37
b Fg(DRAFT)110 b Fe(Decem)n(b)r(er)28 b(16,)e(1998)p
2649 100 V 1212 w Fl(7)101 390 y(5.)42 b Fk(void)f(A2_transpose)e(\()k
(A2)g(*mtx)f(\))h(;)208 520 y Fl(This)36 b(metho)r(d)g(replaces)f
Fk(mtx)g Fl(with)i(its)g(transp)r(ose.)61 b(Note,)39
b(this)d(tak)n(es)f Fj(O)r Fl(\(1\))i(op)r(erations)e(since)h(w)n(e)g
(just)h(sw)n(ap)208 619 y(dimensions)27 b(and)g(incremen)n(ts.)208
749 y Fg(Err)l(or)j(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n(ted)h(and)f
(the)h(program)e(exits.)101 908 y(6.)42 b Fk(void)f(A2_extractRow)e(\()
k(A2)g(*mtx,)e(double)g(row[],)g(int)i(irow)f(\))h(;)208
1037 y Fl(This)27 b(metho)r(d)h(\014lls)g(the)g Fk(row[])d
Fl(v)n(ector)i(with)h(ro)n(w)e Fk(irow)g Fl(of)i(the)g(matrix.)208
1167 y Fg(Err)l(or)33 b(che)l(cking:)46 b Fl(If)32 b
Fk(mtx)p Fl(,)g Fk(entries)c Fl(or)j Fk(row)f Fl(are)g
Fk(NULL)p Fl(,)g(or)h(if)g Fk(irow)f Fl(is)i(not)f(in)h
Fk([0,n1-1])p Fl(,)d(an)i(error)e(message)h(is)208 1266
y(prin)n(ted)d(and)g(the)h(program)e(exits.)101 1425
y(7.)42 b Fk(void)f(A2_extractRowDV)d(\()43 b(A2)g(*mtx,)e(DV)i
(*rowDV,)e(int)h(irow)g(\))h(;)208 1555 y Fl(This)27
b(metho)r(d)h(\014lls)g(the)g Fk(rowDV)d Fl(ob)5 b(ject)28
b(with)g(ro)n(w)e Fk(irow)g Fl(of)i(the)g(matrix.)208
1684 y Fg(Err)l(or)k(che)l(cking:)44 b Fl(If)31 b Fk(mtx)e
Fl(or)h Fk(rowDV)e Fl(are)i Fk(NULL)p Fl(,)e(or)i(if)h(the)f(matrix)g
(is)g(not)h(real,)f(or)f(if)i Fk(irow)e Fl(is)h(not)h(in)f
Fk([0,n1-1])p Fl(,)208 1784 y(an)d(error)e(message)i(is)g(prin)n(ted)h
(and)f(the)h(program)e(exits.)101 1943 y(8.)42 b Fk(void)f
(A2_extractRowZV)d(\()43 b(A2)g(*mtx,)e(ZV)i(*rowZV,)e(int)h(irow)g(\))
h(;)208 2072 y Fl(This)27 b(metho)r(d)h(\014lls)g(the)g
Fk(rowZV)d Fl(ob)5 b(ject)28 b(with)g(ro)n(w)e Fk(irow)g
Fl(of)i(the)g(matrix.)208 2202 y Fg(Err)l(or)d(che)l(cking:)36
b Fl(If)23 b Fk(mtx)f Fl(or)f Fk(rowZV)g Fl(are)g Fk(NULL)p
Fl(,)g(or)h(if)h(the)g(matrix)f(is)g(not)h(complex,)g(or)f(if)h
Fk(irow)e Fl(is)h(not)g(in)h Fk([0,n1-1])p Fl(,)208 2301
y(an)k(error)e(message)i(is)g(prin)n(ted)h(and)f(the)h(program)e
(exits.)101 2461 y(9.)42 b Fk(void)f(A2_extractColumn)c(\()44
b(A2)e(*mtx,)g(double)f(col[],)g(int)h(jcol)g(\))i(;)208
2590 y Fl(This)27 b(metho)r(d)h(\014lls)g(the)g Fk(col[])d
Fl(v)n(ector)i(with)h(column)f Fk(jcol)f Fl(of)i(the)g(matrix.)208
2719 y Fg(Err)l(or)33 b(che)l(cking:)46 b Fl(If)32 b
Fk(mtx)p Fl(,)g Fk(entries)c Fl(or)j Fk(col)f Fl(are)g
Fk(NULL)p Fl(,)g(or)h(if)g Fk(jcol)f Fl(is)i(not)f(in)h
Fk([0,n2-1])p Fl(,)d(an)i(error)e(message)h(is)208 2819
y(prin)n(ted)d(and)g(the)h(program)e(exits.)60 2978 y(10.)41
b Fk(void)g(A2_extractColumnD)o(V)d(\()43 b(A2)g(*mtx,)e(DV)i(*colDV,)e
(int)h(jcol)g(\))h(;)208 3108 y Fl(This)27 b(metho)r(d)h(\014lls)g(the)
g Fk(colDV)d Fl(ob)5 b(ject)28 b(with)g(column)g Fk(jcol)e
Fl(of)h(the)h(matrix.)208 3237 y Fg(Err)l(or)d(che)l(cking:)36
b Fl(If)23 b Fk(mtx)f Fl(or)f Fk(colDV)g Fl(are)g Fk(NULL)p
Fl(,)g(or)h(if)h(the)g(matrix)f(is)g(not)h(complex,)g(or)f(if)h
Fk(jcol)e Fl(is)h(not)g(in)h Fk([0,n2-1])p Fl(,)208 3337
y(an)k(error)e(message)i(is)g(prin)n(ted)h(and)f(the)h(program)e
(exits.)60 3496 y(11.)41 b Fk(void)g(A2_extractColumnZ)o(V)d(\()43
b(A2)g(*mtx,)e(ZV)i(*colZV,)e(int)h(jcol)g(\))h(;)208
3625 y Fl(This)27 b(metho)r(d)h(\014lls)g(the)g Fk(colZV)d
Fl(ob)5 b(ject)28 b(with)g(column)g Fk(jcol)e Fl(of)h(the)h(matrix.)208
3755 y Fg(Err)l(or)d(che)l(cking:)36 b Fl(If)23 b Fk(mtx)f
Fl(or)f Fk(colZV)g Fl(are)g Fk(NULL)p Fl(,)g(or)h(if)h(the)g(matrix)f
(is)g(not)h(complex,)g(or)f(if)h Fk(jcol)e Fl(is)h(not)g(in)h
Fk([0,n2-1])p Fl(,)208 3854 y(an)k(error)e(message)i(is)g(prin)n(ted)h
(and)f(the)h(program)e(exits.)60 4014 y(12.)41 b Fk(void)g(A2_setRow)f
(\()k(A2)e(*mtx,)g(double)f(row[],)g(int)h(irow)g(\))h(;)208
4143 y Fl(This)27 b(metho)r(d)h(\014lls)g(ro)n(w)e Fk(irow)g
Fl(of)i(the)g(matrix)f(with)h(the)g(en)n(tries)f(in)h(the)g
Fk(row[])d Fl(v)n(ector.)208 4272 y Fg(Err)l(or)k(che)l(cking:)39
b Fl(If)27 b Fk(mtx)p Fl(,)f Fk(entries)e Fl(or)j Fk(row[])e
Fl(are)h Fk(NULL)p Fl(,)f(or)h(if)i Fk(irow)d Fl(is)i(not)g(in)h
Fk([0,n1-1])p Fl(,)c(an)i(error)g(message)f(is)208 4372
y(prin)n(ted)i(and)g(the)h(program)e(exits.)60 4531 y(13.)41
b Fk(void)g(A2_setRowDV)f(\()j(A2)f(*mtx,)g(DV)h(rowDV,)e(int)h(irow)g
(\))h(;)208 4661 y Fl(This)27 b(metho)r(d)h(\014lls)g(ro)n(w)e
Fk(irow)g Fl(of)i(the)g(matrix)f(with)h(the)g(en)n(tries)f(in)h(the)g
Fk(rowDV)d Fl(ob)5 b(ject.)208 4790 y Fg(Err)l(or)32
b(che)l(cking:)44 b Fl(If)31 b Fk(mtx)e Fl(or)h Fk(rowDV)e
Fl(are)i Fk(NULL)p Fl(,)e(or)i(if)h(the)f(matrix)g(is)g(not)h(real,)f
(or)f(if)i Fk(irow)e Fl(is)h(not)h(in)f Fk([0,n1-1])p
Fl(,)208 4890 y(an)d(error)e(message)i(is)g(prin)n(ted)h(and)f(the)h
(program)e(exits.)60 5049 y(14.)41 b Fk(void)g(A2_setRowZV)f(\()j(A2)f
(*mtx,)g(ZV)h(rowZV,)e(int)h(irow)g(\))h(;)208 5178 y
Fl(This)27 b(metho)r(d)h(\014lls)g(ro)n(w)e Fk(irow)g
Fl(of)i(the)g(matrix)f(with)h(the)g(en)n(tries)f(in)h(the)g
Fk(rowZV)d Fl(ob)5 b(ject.)208 5308 y Fg(Err)l(or)25
b(che)l(cking:)36 b Fl(If)23 b Fk(mtx)f Fl(or)f Fk(rowZV)g
Fl(are)g Fk(NULL)p Fl(,)g(or)h(if)h(the)g(matrix)f(is)g(not)h(complex,)
g(or)f(if)h Fk(irow)e Fl(is)h(not)g(in)h Fk([0,n1-1])p
Fl(,)208 5407 y(an)k(error)e(message)i(is)g(prin)n(ted)h(and)f(the)h
(program)e(exits.)p eop
%%Page: 8 8
8 7 bop 0 100 a Fl(8)p 125 100 1212 4 v 1377 w Fk(A2)26
b Fe(:)37 b Fg(DRAFT)28 b Fe(Decem)n(b)r(er)f(16,)g(1998)p
2689 100 V 60 390 a Fl(15.)41 b Fk(void)g(A2_setColumn)e(\()k(A2)g
(*mtx,)f(double)f(col[],)g(int)h(jcol)g(\))h(;)208 529
y Fl(This)27 b(metho)r(d)h(\014lls)g(column)f Fk(jcol)f
Fl(of)i(the)g(matrix)f(with)h(the)g(en)n(tries)f(in)h(the)g
Fk(col[])e Fl(v)n(ector.)208 668 y Fg(Err)l(or)32 b(che)l(cking:)45
b Fl(If)31 b Fk(mtx)e Fl(or)g Fk(colZV)g Fl(are)g Fk(NULL)p
Fl(,)g(or)h(if)h Fk(jcol)e Fl(is)h(not)g(in)h Fk([0,n2-1])p
Fl(,)d(an)i(error)f(message)g(is)h(prin)n(ted)208 767
y(and)d(the)h(program)e(exits.)60 945 y(16.)41 b Fk(void)g
(A2_setColumnDV)d(\()43 b(A2)g(*mtx,)f(DV)g(colDV,)g(int)g(jcol)g(\))h
(;)208 1084 y Fl(This)27 b(metho)r(d)h(\014lls)g(column)f
Fk(jcol)f Fl(of)i(the)g(matrix)f(with)h(the)g(en)n(tries)f(in)h(the)g
Fk(colDV)e Fl(ob)5 b(ject.)208 1223 y Fg(Err)l(or)25
b(che)l(cking:)36 b Fl(If)23 b Fk(mtx)f Fl(or)f Fk(colDV)g
Fl(are)g Fk(NULL)p Fl(,)g(or)h(if)h(the)g(matrix)f(is)g(not)h(complex,)
g(or)f(if)h Fk(jcol)e Fl(is)h(not)g(in)h Fk([0,n2-1])p
Fl(,)208 1322 y(an)k(error)e(message)i(is)g(prin)n(ted)h(and)f(the)h
(program)e(exits.)60 1500 y(17.)41 b Fk(void)g(A2_setColumnZV)d(\()43
b(A2)g(*mtx,)f(ZV)g(colZV,)g(int)g(jcol)g(\))h(;)208
1639 y Fl(This)27 b(metho)r(d)h(\014lls)g(column)f Fk(jcol)f
Fl(of)i(the)g(matrix)f(with)h(the)g(en)n(tries)f(in)h(the)g
Fk(colZV)e Fl(ob)5 b(ject.)208 1778 y Fg(Err)l(or)25
b(che)l(cking:)36 b Fl(If)23 b Fk(mtx)f Fl(or)f Fk(colZV)g
Fl(are)g Fk(NULL)p Fl(,)g(or)h(if)h(the)g(matrix)f(is)g(not)h(complex,)
g(or)f(if)h Fk(jcol)e Fl(is)h(not)g(in)h Fk([0,n2-1])p
Fl(,)208 1878 y(an)k(error)e(message)i(is)g(prin)n(ted)h(and)f(the)h
(program)e(exits.)60 2055 y(18.)41 b Fk(void)g(A2_fillRandomUnif)o(orm)
c(\()43 b(A2)g(*mtx,)e(double)g(lower,)g(double)h(upper,)f(int)h(seed)g
(\))h(;)208 2194 y Fl(This)18 b(metho)r(d)h(\014lls)f(the)h(matrix)f
(with)h(random)e(n)n(um)n(b)r(ers)h(tak)n(en)g(from)g(a)g(uniform)g
(distribution)h(on)f Fk([lower,upper])208 2294 y Fl(using)27
b(the)h Fk(Drand)d Fl(ob)5 b(ject.)208 2433 y Fg(Err)l(or)30
b(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f Fl(is)g Fk(NULL)p
Fl(,)f(an)i(error)d(message)i(is)g(prin)n(ted)h(and)f(the)h(program)e
(exits.)60 2610 y(19.)41 b Fk(void)g(A2_fillWithIdenti)o(ty)c(\()43
b(A2)g(*mtx)f(\))h(;)208 2749 y Fl(This)27 b(metho)r(d)h(\014lls)g(the)
g(matrix)f(with)h(the)g(iden)n(tit)n(y)g(matrix.)208
2888 y Fg(Err)l(or)i(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(is)g Fk(NULL)f Fl(or)h(if)h Fk(n1)43 b(!=)g(n2)p Fl(,)27
b(an)g(error)f(message)g(is)h(prin)n(ted)h(and)f(the)h(program)e
(exits.)60 3066 y(20.)41 b Fk(void)g(A2_zero)g(\()i(A2)g(*mtx)f(\))h(;)
208 3205 y Fl(This)27 b(metho)r(d)h(\014lls)g(the)g(matrix)f(with)h
(zeros.)208 3343 y Fg(Err)l(or)i(che)l(cking:)38 b Fl(If)28
b Fk(mtx)f Fl(is)g Fk(NULL)p Fl(,)f(an)i(error)d(message)i(is)g(prin)n
(ted)h(and)f(the)h(program)e(exits.)60 3521 y(21.)41
b Fk(void)g(A2_copy)g(\()i(A2)g(*mtxA,)e(A2)i(*mtxB)e(\))j(;)208
3660 y Fl(This)30 b(metho)r(d)h(copies)e(en)n(tries)h(from)g(matrix)g
Fk(mtxB)f Fl(in)n(to)h(matrix)g Fk(mtxA)p Fl(.)f(Note,)i
Fk(mtxA)e Fl(and)h Fk(mtxB)e Fl(need)j(not)f(b)r(e)h(of)208
3760 y(the)25 b(same)f(size,)h(the)g(leading)f Fk(min\(mtxA->n1,mtx)o
(B-)o(>n)o(1\))18 b Fl(ro)n(ws)24 b(and)g Fk(min\(mtxA->n2,mtx)o(B->)o
(n2)o(\))19 b Fl(columns)24 b(are)208 3859 y(copied.)208
3998 y Fg(Err)l(or)30 b(che)l(cking:)38 b Fl(If)28 b
Fk(mtxA)e Fl(or)g Fk(mtxB)g Fl(is)i Fk(NULL)p Fl(,)d(or)i(if)h(the)g
(matrices)e(are)h(not)g(of)h(the)f(same)g(t)n(yp)r(e,)h(an)f(error)e
(message)208 4098 y(is)i(prin)n(ted)h(and)f(the)h(program)e(exits.)60
4276 y(22.)41 b Fk(void)g(A2_sub)h(\()h(A2)g(*mtxA,)e(A2)h(*mtxB)g(\))h
(;)208 4414 y Fl(This)27 b(metho)r(d)h(subtracts)e(en)n(tries)h(in)h
(matrix)e Fk(mtxB)g Fl(from)h(en)n(tries)g(in)g(matrix)g
Fk(mtxA)p Fl(.)f(Note,)h Fk(mtxA)f Fl(and)h Fk(mtxB)f
Fl(need)208 4514 y(not)34 b(b)r(e)h(of)g(the)f(same)g(size,)i(the)f
(leading)f Fk(min\(mtxA->n1,mtxB)o(->)o(n1\))28 b Fl(ro)n(ws)33
b(and)h Fk(min\(mtxA->n2,mtx)o(B->)o(n2)o(\))208 4614
y Fl(columns)27 b(are)f(subtracted.)208 4752 y Fg(Err)l(or)k(che)l
(cking:)38 b Fl(If)28 b Fk(mtxA)e Fl(or)g Fk(mtxB)g Fl(is)i
Fk(NULL)p Fl(,)d(or)i(if)h(the)g(matrices)e(are)h(not)g(of)h(the)f
(same)g(t)n(yp)r(e,)h(an)f(error)e(message)208 4852 y(is)i(prin)n(ted)h
(and)f(the)h(program)e(exits.)60 5030 y(23.)41 b Fk(void)g(A2_swapRows)
f(\()j(A2)f(*mtx,)g(int)g(irow1,)f(int)i(irow2)e(\))i(;)208
5169 y Fl(This)27 b(metho)r(d)h(sw)n(aps)f(ro)n(ws)f
Fk(irow1)f Fl(and)j Fk(irow2)d Fl(of)j(the)g(matrix.)208
5308 y Fg(Err)l(or)34 b(che)l(cking:)49 b Fl(If)33 b
Fk(mtxA)e Fl(or)h Fk(mtxB)f Fl(is)i Fk(NULL)p Fl(,)e(or)h(if)h
Fk(irow1)e Fl(or)h Fk(irow2)e Fl(are)i(out)h(of)f(range,)h(an)f(error)f
(message)g(is)208 5407 y(prin)n(ted)c(and)g(the)h(program)e(exits.)p
eop
%%Page: 9 9
9 8 bop 83 100 1212 4 v 1377 100 a Fk(A2)27 b Fe(:)37
b Fg(DRAFT)110 b Fe(Decem)n(b)r(er)28 b(16,)e(1998)p
2649 100 V 1212 w Fl(9)60 390 y(24.)41 b Fk(void)g(A2_swapColumns)d(\()
43 b(A2)g(*mtx,)f(int)g(irow1,)f(int)i(irow2)e(\))i(;)208
523 y Fl(This)27 b(metho)r(d)h(sw)n(aps)f(columns)g Fk(jcol1)f
Fl(and)h Fk(jcol2)f Fl(of)h(the)h(matrix.)208 655 y Fg(Err)l(or)34
b(che)l(cking:)49 b Fl(If)33 b Fk(mtxA)e Fl(or)h Fk(mtxB)f
Fl(is)i Fk(NULL)p Fl(,)e(or)h(if)h Fk(jcol1)e Fl(or)h
Fk(jcol1)e Fl(are)i(out)h(of)f(range,)h(an)f(error)f(message)g(is)208
755 y(prin)n(ted)c(and)g(the)h(program)e(exits.)60 920
y(25.)41 b Fk(int)h(A2_copyEntriesTo)o(Ve)o(cto)o(r)37
b(\()44 b(A2)e(*mtx,)g(int)g(length,)f(double)g(dvec[],)1472
1020 y(int)h(copyflag,)e(int)i(storeflag)e(\))j(;)208
1153 y Fl(This)28 b(metho)r(d)h(copies)f(selected)g(en)n(tries)g(from)g
Fk(mtx)f Fl(in)n(to)h(the)h(v)n(ector)e Fk(dvec[])f Fl(with)j(length)g
Fk(length)p Fl(.)37 b(The)29 b(return)208 1252 y(v)-5
b(alue)34 b(is)h(the)g(n)n(um)n(b)r(er)g(of)g(en)n(tries)f(copied.)58
b(This)35 b(metho)r(d)g(is)g(used)g(during)f(the)h Fj(QR)h
Fl(factorization)d(to)i(extract)208 1352 y(factor)25
b(en)n(tries)h(and)g(up)r(date)h(matrix)f(en)n(tries)g(from)g(a)g(fron)
n(t.)36 b(All)27 b(en)n(tries)e(ma)n(y)h(b)r(e)h(copied,)f(or)g(only)g
(the)h(diagonal,)208 1451 y(lo)n(w)n(er)f(or)g(upp)r(er)i(en)n(tries,)f
(and)g(the)h(en)n(tries)f(ma)n(y)g(b)r(e)h(copied)f(to)h
Fk(dvec[])d Fl(b)n(y)i(ro)n(ws)g(or)f(b)n(y)i(columns.)208
1584 y Fg(Err)l(or)c(che)l(cking:)36 b Fl(If)21 b Fk(mtx)g
Fl(or)f Fk(dvec)g Fl(is)h Fk(NULL)p Fl(,)f(or)h(if)g
Fk(length)e Fl(is)j(not)f(as)g(large)f(as)g(the)i(n)n(um)n(b)r(er)f(of)
h(en)n(tries)e(to)i(b)r(e)f(copied,)208 1684 y(or)32
b(if)h Fk(copyflag)d Fl(is)i(not)h(one)g(of)g Fk(A2)p
1370 1684 27 4 v 30 w(STRICT)p 1664 1684 V 29 w(LOWER)p
Fl(,)e Fk(A2)p 2055 1684 V 31 w(LOWER)p Fl(,)g Fk(A2)p
2448 1684 V 30 w(DIAGONAL)p Fl(,)f Fk(A2)p 2971 1684
V 31 w(UPPER)p Fl(,)h Fk(A2)p 3364 1684 V 30 w(STRICT)p
3658 1684 V 29 w(UPPER)208 1783 y Fl(or)f Fk(A2)p 406
1783 V 30 w(ALL)p 568 1783 V 30 w(ENTRIES)p Fl(,)f(or)h(if)h
Fk(storeflag)d Fl(is)i(not)h(one)g(of)g Fk(A2)p 2145
1783 V 30 w(BY)p 2263 1783 V 31 w(ROWS)e Fl(or)i Fk(A2)p
2693 1783 V 30 w(BY)p 2811 1783 V 31 w(COLUMNS)p Fl(,)d(an)j(error)e
(message)g(is)208 1883 y(prin)n(ted)e(and)g(the)h(program)e(exits.)0
2140 y Fd(1.2.8)112 b(IO)38 b(metho)s(ds)0 2317 y Fl(There)27
b(are)g(the)h(usual)f(eigh)n(t)g(IO)g(routines)g(plus)h(a)f(metho)r(d)h
(to)g(write)f(the)h(ob)5 b(ject)28 b(to)f(a)g(Matlab)g(\014le.)101
2523 y(1.)42 b Fk(int)g(A2_readFromFile)37 b(\()43 b(A2)g(*mtx,)f(char)
g(*fn)g(\))h(;)208 2656 y Fl(This)28 b(metho)r(d)i(reads)d(a)i
Fk(A2)f Fl(ob)5 b(ject)28 b(from)h(a)f(\014le.)41 b(It)29
b(tries)f(to)h(op)r(en)g(the)g(\014le)g(and)f(if)i(it)f(is)f
(successful,)h(it)g(then)h(calls)208 2755 y Fk(A2)p 301
2755 V 30 w(readFromFormatte)o(dFi)o(le)o(\(\))k Fl(or)39
b Fk(A2)p 1576 2755 V 30 w(readFromBinaryFil)o(e\()o(\))p
Fl(,)e(closes)i(the)i(\014le)f(and)g(returns)f(the)h(v)-5
b(alue)208 2855 y(returned)27 b(from)g(the)h(called)f(routine.)208
2988 y Fg(Err)l(or)i(che)l(cking:)38 b Fl(If)27 b Fk(mtx)e
Fl(or)g Fk(fn)h Fl(are)g Fk(NULL)p Fl(,)f(or)g(if)i Fk(fn)f
Fl(is)g(not)g(of)h(the)g(form)f Fk(*.a2f)e Fl(\(for)i(a)g(formatted)h
(\014le\))g(or)e Fk(*.a2b)208 3087 y Fl(\(for)i(a)g(binary)g(\014le\),)
h(an)f(error)f(message)g(is)i(prin)n(ted)f(and)h(the)g(metho)r(d)g
(returns)f(zero.)101 3253 y(2.)42 b Fk(int)g(A2_readFromForma)o(tt)o
(edF)o(il)o(e)c(\()43 b(A2)f(*mtx,)g(FILE)g(*fp)g(\))h(;)208
3385 y Fl(This)34 b(metho)r(d)h(reads)f(a)g Fk(A2)g Fl(ob)5
b(ject)34 b(from)g(a)g(formatted)h(\014le)g(whose)e(p)r(oin)n(ter)i(is)
f Fk(fp)p Fl(.)57 b(If)35 b(there)g(are)e(no)h(errors)f(in)208
3485 y(reading)25 b(the)j(data,)e(the)i(v)-5 b(alue)26
b Fk(1)h Fl(is)g(returned.)36 b(If)27 b(an)g(IO)g(error)e(is)h(encoun)n
(tered)g(from)h Fk(fscanf)p Fl(,)e(zero)h(is)g(returned.)208
3617 y Fg(Err)l(or)k(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(or)g Fk(fp)f Fl(are)h Fk(NULL)p Fl(,)f(an)h(error)f(message)g(is)i
(prin)n(ted)f(and)h(zero)e(is)i(returned.)101 3783 y(3.)42
b Fk(int)g(A2_readFromBinar)o(yF)o(ile)37 b(\()43 b(A2)g(*mtx,)e(FILE)h
(*fp)h(\))g(;)208 3915 y Fl(This)26 b(metho)r(d)h(reads)e(a)h
Fk(A2)f Fl(ob)5 b(ject)27 b(from)f(a)g(binary)f(\014le)i(whose)e(p)r
(oin)n(ter)h(is)g Fk(fp)p Fl(.)36 b(If)27 b(there)f(are)f(no)i(errors)d
(in)i(reading)208 4015 y(the)i(data,)f(the)h(v)-5 b(alue)27
b Fk(1)g Fl(is)h(returned.)36 b(If)28 b(an)g(IO)f(error)f(is)h(encoun)n
(tered)g(from)g Fk(fread)p Fl(,)f(zero)g(is)i(returned.)208
4148 y Fg(Err)l(or)i(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(or)g Fk(fp)f Fl(are)h Fk(NULL)p Fl(,)f(an)h(error)f(message)g(is)i
(prin)n(ted)f(and)h(zero)e(is)i(returned.)101 4313 y(4.)42
b Fk(int)g(A2_writeToFile)c(\()43 b(A2)g(*mtx,)e(char)h(*fn)g(\))i(;)
208 4446 y Fl(This)31 b(metho)r(d)h(writes)f(a)g Fk(A2)g
Fl(ob)5 b(ject)31 b(to)h(a)f(\014le.)49 b(It)32 b(tries)f(to)g(op)r(en)
h(the)g(\014le)g(and)f(if)h(it)g(is)f(successful,)i(it)f(then)g(calls)
208 4545 y Fk(A2)p 301 4545 V 30 w(writeFromFormatt)o(edF)o(il)o(e\(\))
24 b Fl(or)29 b Fk(A2)p 1600 4545 V 31 w(writeFromBinaryF)o(ile)o(\(\))
o Fl(,)d(closes)j(the)i(\014le)g(and)f(returns)g(the)h(v)-5
b(alue)208 4645 y(returned)27 b(from)g(the)h(called)f(routine.)208
4777 y Fg(Err)l(or)i(che)l(cking:)38 b Fl(If)27 b Fk(mtx)e
Fl(or)g Fk(fn)h Fl(are)g Fk(NULL)p Fl(,)f(or)g(if)i Fk(fn)f
Fl(is)g(not)g(of)h(the)g(form)f Fk(*.a2f)e Fl(\(for)i(a)g(formatted)h
(\014le\))g(or)e Fk(*.a2b)208 4877 y Fl(\(for)i(a)g(binary)g(\014le\),)
h(an)f(error)f(message)g(is)i(prin)n(ted)f(and)h(the)g(metho)r(d)g
(returns)f(zero.)101 5042 y(5.)42 b Fk(int)g(A2_writeToFormat)o(te)o
(dFi)o(le)37 b(\()43 b(A2)g(*mtx,)e(FILE)h(*fp)h(\))g(;)208
5175 y Fl(This)23 b(metho)r(d)i(writes)e(a)h Fk(A2)f
Fl(ob)5 b(ject)23 b(to)h(a)f(formatted)h(\014le)g(whose)f(p)r(oin)n
(ter)h(is)f Fk(fp)p Fl(.)35 b(If)25 b(there)e(are)g(no)h(errors)d(in)j
(writing)208 5275 y(the)k(data,)f(the)h(v)-5 b(alue)27
b Fk(1)g Fl(is)h(returned.)36 b(If)28 b(an)g(IO)f(error)f(is)h(encoun)n
(tered)g(from)g Fk(fprintf)p Fl(,)e(zero)h(is)i(returned.)208
5407 y Fg(Err)l(or)i(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(or)g Fk(fp)f Fl(are)h Fk(NULL)p Fl(,)f(an)h(error)f(message)g(is)i
(prin)n(ted)f(and)h(zero)e(is)i(returned.)p eop
%%Page: 10 10
10 9 bop 0 100 a Fl(10)p 166 100 1191 4 v 1355 w Fk(A2)27
b Fe(:)37 b Fg(DRAFT)27 b Fe(Decem)n(b)r(er)h(16,)f(1998)p
2710 100 V 101 390 a Fl(6.)42 b Fk(int)g(A2_writeToBinary)o(Fi)o(le)37
b(\()43 b(A2)g(*mtx,)f(FILE)g(*fp)g(\))h(;)208 523 y
Fl(This)29 b(metho)r(d)i(writes)e(a)h Fk(A2)f Fl(ob)5
b(ject)30 b(to)g(a)f(binary)h(\014le)g(whose)f(p)r(oin)n(ter)h(is)f
Fk(fp)p Fl(.)44 b(If)30 b(there)g(are)f(no)g(errors)f(in)i(writing)208
622 y(the)e(data,)f(the)h(v)-5 b(alue)27 b Fk(1)g Fl(is)h(returned.)36
b(If)28 b(an)g(IO)f(error)f(is)h(encoun)n(tered)g(from)g
Fk(fwrite)p Fl(,)e(zero)i(is)g(returned.)208 754 y Fg(Err)l(or)j(che)l
(cking:)38 b Fl(If)28 b Fk(mtx)f Fl(or)g Fk(fp)f Fl(are)h
Fk(NULL)p Fl(,)f(an)h(error)f(message)g(is)i(prin)n(ted)f(and)h(zero)e
(is)i(returned.)101 920 y(7.)42 b Fk(void)f(A2_writeForHumanE)o(ye)c
(\()43 b(A2)g(*mtx,)f(FILE)g(*fp)g(\))h(;)208 1052 y
Fl(This)29 b(metho)r(d)g(writes)g(a)f Fk(A2)h Fl(ob)5
b(ject)28 b(to)h(a)g(\014le)g(in)g(an)g(easily)f(readable)g(format.)41
b(The)29 b(metho)r(d)g Fk(A2)p 3351 1052 27 4 v 31 w(writeStats\(\))208
1151 y Fl(is)e(called)g(to)h(write)f(out)h(the)g(header)e(and)i
(statistics.)208 1284 y Fg(Err)l(or)i(che)l(cking:)38
b Fl(If)28 b Fk(mtx)f Fl(or)g Fk(fp)f Fl(are)h Fk(NULL)p
Fl(,)f(an)h(error)f(message)g(is)i(prin)n(ted)f(and)h(zero)e(is)i
(returned.)101 1449 y(8.)42 b Fk(void)f(A2_writeStats)e(\()k(A2)g
(*mtx,)e(FILE)h(*fp)g(\))i(;)208 1581 y Fl(This)27 b(metho)r(d)h
(writes)f(a)h(header)e(and)i(some)f(statistics)g(to)h(a)f(\014le.)208
1713 y Fg(Err)l(or)j(che)l(cking:)38 b Fl(If)28 b Fk(mtx)f
Fl(or)g Fk(fp)f Fl(are)h Fk(NULL)p Fl(,)f(an)h(error)f(message)g(is)i
(prin)n(ted)f(and)h(zero)e(is)i(returned.)101 1879 y(9.)42
b Fk(void)f(A2_writeForMatlab)c(\()43 b(A2)g(*mtx,)e(char)h(*mtxname,)e
(FILE)i(*fp)h(\))g(;)208 2011 y Fl(This)31 b(metho)r(d)i(writes)e(the)i
(en)n(tries)e(of)h(the)g(matrix)g(to)g(a)f(\014le)h(in)h(Matlab)e
(format.)50 b(The)32 b(name)f(of)h(the)h(matrix)e(is)208
2110 y Fk(mtxname)p Fl(.)208 2243 y Fg(Err)l(or)f(che)l(cking:)38
b Fl(If)28 b Fk(mtx)p Fl(,)f Fk(mtxname)e Fl(or)h Fk(fp)h
Fl(are)g Fk(NULL)p Fl(,)f(an)h(error)f(message)g(is)i(prin)n(ted)f(and)
g(zero)g(is)g(returned.)0 2541 y Fi(1.3)135 b(Driv)l(er)46
b(programs)g(for)f(the)g Ff(A2)60 b(object)101 2748 y
Fl(1.)42 b Fk(test_norms)d(msglvl)i(msgFile)g(type)h(nrow)g(ncol)g
(inc1)g(inc2)f(seed)208 2880 y Fl(This)31 b(driv)n(er)f(program)f
(tests)i(the)h Fk(A2)e Fl(norm)h(metho)r(ds.)48 b(Use)31
b(the)g(script)g(\014le)h Fk(do)p 2818 2880 V 30 w(norms)e
Fl(for)g(testing.)48 b(When)32 b(the)208 2980 y(output)24
b(\014le)g(is)g(loaded)f(in)n(to)h(matlab,)g(the)h(last)e(t)n(w)n(o)h
(lines)f(con)n(tain)h(matrices)f(whose)g(en)n(tries)g(should)h(all)g(b)
r(e)g(around)208 3079 y(mac)n(hine)j(epsilon.)307 3260
y Fh(\017)41 b Fl(The)23 b Fk(msglvl)e Fl(parameter)g(determines)i(the)
h(amoun)n(t)e(of)h(output.)36 b(Use)23 b Fk(msglvl)41
b(=)i(1)23 b Fl(for)g(just)g(timing)g(output.)307 3392
y Fh(\017)41 b Fl(The)32 b Fk(msgFile)c Fl(parameter)i(determines)h
(the)h(message)e(\014le)i(|)f(if)h Fk(msgFile)d Fl(is)i
Fk(stdout)p Fl(,)f(then)i(the)g(message)390 3492 y(\014le)c(is)f
Fg(stdout)p Fl(,)h(otherwise)e(a)i(\014le)f(is)h(op)r(ened)f(with)i
Fg(app)l(end)g Fl(status)e(to)g(receiv)n(e)g(an)n(y)g(output)h(data.)
307 3624 y Fh(\017)41 b Fl(The)28 b Fk(type)e Fl(parameter)g(denotes)h
(the)h(t)n(yp)r(e)g(of)g(en)n(tries)f(|)g Fk(SPOOLES)p
2574 3624 V 29 w(REAL)f Fl(or)g Fk(SPOOLES)p 3214 3624
V 29 w(COMPLEX)307 3755 y Fh(\017)41 b Fl(The)28 b Fk(nrow)e
Fl(parameter)g(is)h(the)h(n)n(um)n(b)r(er)g(of)f(ro)n(ws.)307
3887 y Fh(\017)41 b Fl(The)28 b Fk(ncol)e Fl(parameter)g(is)h(the)h(n)n
(um)n(b)r(er)g(of)f(ro)n(ws.)307 4019 y Fh(\017)41 b
Fl(The)28 b Fk(inc1)e Fl(parameter)g(is)h(the)h(ro)n(w)f(incremen)n(t.)
307 4151 y Fh(\017)41 b Fl(The)28 b Fk(inc2)e Fl(parameter)g(is)h(the)h
(column)g(incremen)n(t.)307 4283 y Fh(\017)41 b Fl(The)28
b Fk(seed)e Fl(parameter)g(is)h(a)h(random)e(n)n(um)n(b)r(er)i(seed.)
101 4464 y(2.)42 b Fk(test_QR)e(msglvl)h(msgFile)g(type)h(nrow)g(ncol)g
(inc1)g(inc2)g(seed)208 4596 y Fl(This)22 b(driv)n(er)g(program)e
(tests)j(the)g Fk(A2)p 1376 4596 V 30 w(QRreduce\(\))c
Fl(and)k Fk(A2)p 2110 4596 V 30 w(QRreduce2\(\))18 b
Fl(metho)r(ds)23 b(whic)n(h)g(reduce)f Fj(A)h Fl(to)g
Fj(QR)g Fl(via)208 4696 y(rank-1)g(and)i(rank-2)f(up)r(dates.)36
b(Use)25 b(the)h(script)f(\014le)h Fk(do)p 1979 4696
V 30 w(QR)f Fl(for)f(testing.)37 b(When)25 b Fk(msglvl)41
b(>)j(1)p Fl(,)25 b(the)h(matrix)f Fj(A)g Fl(and)208
4795 y(matrices)d Fj(R)q Fl(1)g(and)g Fj(R)q Fl(2)g(\(computed)h(from)g
Fk(A2)p 1643 4795 V 30 w(QRreduce\(\))c Fl(and)k Fk(A2)p
2377 4795 V 30 w(QRreduce2\(\))p Fl(,)d(resp)r(ectiv)n(ely\))i(are)g
(prin)n(ted)g(to)208 4895 y(the)h(message)e(\014le.)36
b(When)23 b(the)h(output)f(\014le)g(is)g(loaded)f(in)n(to)h(matlab,)h
(the)f(errors)e Fj(A)2831 4865 y Fb(T)2883 4895 y Fj(A)9
b Fh(\000)g Fj(R)3092 4865 y Fb(T)3091 4916 y Fa(1)3144
4895 y Fj(R)3207 4907 y Fa(1)3267 4895 y Fl(and)23 b
Fj(A)3486 4865 y Fb(T)3539 4895 y Fj(A)9 b Fh(\000)g
Fj(R)3748 4865 y Fb(T)3747 4916 y Fa(2)3800 4895 y Fj(R)3863
4907 y Fa(2)208 4995 y Fl(\(if)28 b Fj(A)g Fl(is)f(real\))g(or)g(the)h
(errors)d Fj(A)1226 4964 y Fb(H)1290 4995 y Fj(A)18 b
Fh(\000)g Fj(R)1517 4964 y Fb(H)1516 5015 y Fa(1)1580
4995 y Fj(R)1643 5007 y Fa(1)1708 4995 y Fl(and)27 b
Fj(A)1931 4964 y Fb(H)1995 4995 y Fj(A)18 b Fh(\000)g
Fj(R)2222 4964 y Fb(H)2221 5015 y Fa(2)2285 4995 y Fj(R)2348
5007 y Fa(2)2413 4995 y Fl(\(if)28 b Fj(A)g Fl(is)g(complex\))f(are)g
(computed.)307 5176 y Fh(\017)41 b Fl(The)23 b Fk(msglvl)e
Fl(parameter)g(determines)i(the)h(amoun)n(t)e(of)h(output.)36
b(Use)23 b Fk(msglvl)41 b(=)i(1)23 b Fl(for)g(just)g(timing)g(output.)
307 5308 y Fh(\017)41 b Fl(The)32 b Fk(msgFile)c Fl(parameter)i
(determines)h(the)h(message)e(\014le)i(|)f(if)h Fk(msgFile)d
Fl(is)i Fk(stdout)p Fl(,)f(then)i(the)g(message)390 5407
y(\014le)c(is)f Fg(stdout)p Fl(,)h(otherwise)e(a)i(\014le)f(is)h(op)r
(ened)f(with)i Fg(app)l(end)g Fl(status)e(to)g(receiv)n(e)g(an)n(y)g
(output)h(data.)p eop
%%Page: 11 11
11 10 bop 83 100 1191 4 v 1356 100 a Fk(A2)27 b Fe(:)37
b Fg(DRAFT)110 b Fe(Decem)n(b)r(er)28 b(16,)f(1998)p
2629 100 V 1191 w Fl(11)307 390 y Fh(\017)41 b Fl(The)28
b Fk(type)e Fl(parameter)g(denotes)h(the)h(t)n(yp)r(e)g(of)g(en)n
(tries)f(|)g Fk(SPOOLES)p 2574 390 27 4 v 29 w(REAL)f
Fl(or)g Fk(SPOOLES)p 3214 390 V 29 w(COMPLEX)307 523
y Fh(\017)41 b Fl(The)28 b Fk(nrow)e Fl(parameter)g(is)h(the)h(n)n(um)n
(b)r(er)g(of)f(ro)n(ws.)307 656 y Fh(\017)41 b Fl(The)28
b Fk(ncol)e Fl(parameter)g(is)h(the)h(n)n(um)n(b)r(er)g(of)f(ro)n(ws.)
307 789 y Fh(\017)41 b Fl(The)28 b Fk(inc1)e Fl(parameter)g(is)h(the)h
(ro)n(w)f(incremen)n(t.)307 922 y Fh(\017)41 b Fl(The)28
b Fk(inc2)e Fl(parameter)g(is)h(the)h(column)g(incremen)n(t.)307
1054 y Fh(\017)41 b Fl(The)28 b Fk(seed)e Fl(parameter)g(is)h(a)h
(random)e(n)n(um)n(b)r(er)i(seed.)p eop
%%Page: 12 12
12 11 bop 0 866 a Fm(Index)0 1281 y Fk(A2)p 93 1281 27
4 v 31 w(clearData\(\))p Fl(,)23 b(2)0 1381 y Fk(A2)p
93 1381 V 31 w(column\(\))p Fl(,)h(3)0 1482 y Fk(A2)p
93 1482 V 31 w(columnMajor\(\))p Fl(,)e(6)0 1583 y Fk(A2)p
93 1583 V 31 w(complexEntry\(\))p Fl(,)f(3)0 1683 y Fk(A2)p
93 1683 V 31 w(copy\(\))p Fl(,)k(8)0 1784 y Fk(A2)p 93
1784 V 31 w(copyEntriesToVe)o(cto)o(r\()o(\))p Fl(,)d(9)0
1885 y Fk(A2)p 93 1885 V 31 w(entries\(\))p Fl(,)i(2)0
1985 y Fk(A2)p 93 1985 V 31 w(extractColumn\(\))o Fl(,)e(7)0
2086 y Fk(A2)p 93 2086 V 31 w(extractColumnDV)o(\(\))p
Fl(,)f(7)0 2187 y Fk(A2)p 93 2187 V 31 w(extractColumnZV)o(\(\))p
Fl(,)g(7)0 2287 y Fk(A2)p 93 2287 V 31 w(extractRow\(\))p
Fl(,)h(7)0 2388 y Fk(A2)p 93 2388 V 31 w(extractRowDV\(\))p
Fl(,)f(7)0 2489 y Fk(A2)p 93 2489 V 31 w(extractRowZV\(\))p
Fl(,)g(7)0 2589 y Fk(A2)p 93 2589 V 31 w(fillRandomUnifo)o(rm\()o(\))p
Fl(,)g(8)0 2690 y Fk(A2)p 93 2690 V 31 w(fillWithIdentit)o(y\(\))o
Fl(,)h(8)0 2790 y Fk(A2)p 93 2790 V 31 w(free\(\))p Fl(,)j(2)0
2891 y Fk(A2)p 93 2891 V 31 w(frobNorm\(\))p Fl(,)e(5)0
2992 y Fk(A2)p 93 2992 V 31 w(inc1\(\))p Fl(,)i(2)0 3092
y Fk(A2)p 93 3092 V 31 w(inc2\(\))p Fl(,)g(2)0 3193 y
Fk(A2)p 93 3193 V 31 w(infinityNorm\(\))p Fl(,)c(5)0
3294 y Fk(A2)p 93 3294 V 31 w(infinityNormOfC)o(olu)o(mn)o(\(\))o
Fl(,)h(5)0 3394 y Fk(A2)p 93 3394 V 31 w(infinityNormOfR)o(ow\()o(\))p
Fl(,)f(5)0 3495 y Fk(A2)p 93 3495 V 31 w(init\(\))p Fl(,)k(4)0
3596 y Fk(A2)p 93 3596 V 31 w(makeStaircase\(\))o Fl(,)d(4)0
3696 y Fk(A2)p 93 3696 V 31 w(maxabs\(\))p Fl(,)i(5)0
3797 y Fk(A2)p 93 3797 V 31 w(ncol\(\))p Fl(,)h(2)0 3898
y Fk(A2)p 93 3898 V 31 w(new\(\))p Fl(,)g(2)0 3998 y
Fk(A2)p 93 3998 V 31 w(nrow\(\))p Fl(,)g(2)0 4099 y Fk(A2)p
93 4099 V 31 w(oneNorm\(\))p Fl(,)f(5)0 4199 y Fk(A2)p
93 4199 V 31 w(oneNormOfColumn)o(\(\))p Fl(,)d(5)0 4300
y Fk(A2)p 93 4300 V 31 w(oneNormOfRow\(\))p Fl(,)g(5)0
4401 y Fk(A2)p 93 4401 V 31 w(permuteColumns\()o(\))p
Fl(,)h(6)0 4501 y Fk(A2)p 93 4501 V 31 w(permuteRows\(\))p
Fl(,)g(6)0 4602 y Fk(A2)p 93 4602 V 31 w(pointerToComple)o(xEn)o(tr)o
(y\()o(\))p Fl(,)g(3)0 4703 y Fk(A2)p 93 4703 V 31 w(pointerToRealEn)o
(try)o(\(\))o Fl(,)g(3)0 4803 y Fk(A2)p 93 4803 V 31
w(QRreduce2\(\))p Fl(,)h(4)0 4904 y Fk(A2)p 93 4904 V
31 w(readFromBinaryF)o(ile)o(\(\))o Fl(,)f(9)0 5005 y
Fk(A2)p 93 5005 V 31 w(readFromFile\(\))p Fl(,)f(9)0
5105 y Fk(A2)p 93 5105 V 31 w(readFromFormatt)o(edF)o(il)o(e\()o(\))p
Fl(,)h(9)0 5206 y Fk(A2)p 93 5206 V 31 w(realEntry\(\))p
Fl(,)h(3)0 5307 y Fk(A2)p 93 5307 V 31 w(row\(\))p Fl(,)i(3)0
5407 y Fk(A2)p 93 5407 V 31 w(rowMajor\(\))p Fl(,)e(6)2095
1281 y Fk(A2)p 2188 1281 V 31 w(setColumn\(\))p Fl(,)g(8)2095
1380 y Fk(A2)p 2188 1380 V 31 w(setColumnDV\(\))p Fl(,)f(8)2095
1480 y Fk(A2)p 2188 1480 V 31 w(setColumnZV\(\))p Fl(,)g(8)2095
1580 y Fk(A2)p 2188 1580 V 31 w(setComplexEntry\()o(\))p
Fl(,)g(3)2095 1679 y Fk(A2)p 2188 1679 V 31 w(setDefaultFields)o(\(\))o
Fl(,)g(2)2095 1779 y Fk(A2)p 2188 1779 V 31 w(setRealEntry\(\))p
Fl(,)g(3)2095 1879 y Fk(A2)p 2188 1879 V 31 w(setRow\(\))p
Fl(,)i(7)2095 1978 y Fk(A2)p 2188 1978 V 31 w(setRowDV\(\))p
Fl(,)f(7)2095 2078 y Fk(A2)p 2188 2078 V 31 w(setRowZV\(\))p
Fl(,)g(7)2095 2177 y Fk(A2)p 2188 2177 V 31 w(shiftBase\(\))p
Fl(,)g(6)2095 2277 y Fk(A2)p 2188 2277 V 31 w(sizeOf\(\))p
Fl(,)h(6)2095 2377 y Fk(A2)p 2188 2377 V 31 w(sortColumnsUp\(\))p
Fl(,)d(6)2095 2476 y Fk(A2)p 2188 2476 V 31 w(sortRowsUp\(\))p
Fl(,)i(6)2095 2576 y Fk(A2)p 2188 2576 V 31 w(sub\(\))p
Fl(,)j(8)2095 2676 y Fk(A2)p 2188 2676 V 31 w(subA2\(\))p
Fl(,)f(4)2095 2775 y Fk(A2)p 2188 2775 V 31 w(swapColumns\(\))p
Fl(,)d(9)2095 2875 y Fk(A2)p 2188 2875 V 31 w(swapRows\(\))p
Fl(,)h(8)2095 2974 y Fk(A2)p 2188 2974 V 31 w(transpose\(\))p
Fl(,)g(7)2095 3074 y Fk(A2)p 2188 3074 V 31 w(twoNormOfColumn\()o(\))p
Fl(,)f(5)2095 3174 y Fk(A2)p 2188 3174 V 31 w(twoNormOfRow\(\))p
Fl(,)g(5)2095 3273 y Fk(A2)p 2188 3273 V 31 w(writeForHumanEye)o(\(\))o
Fl(,)g(10)2095 3373 y Fk(A2)p 2188 3373 V 31 w(writeForMatlab\(\))o
Fl(,)g(10)2095 3473 y Fk(A2)p 2188 3473 V 31 w(writeStats\(\))p
Fl(,)h(10)2095 3572 y Fk(A2)p 2188 3572 V 31 w(writeToBinaryFil)o(e\()o
(\))p Fl(,)f(10)2095 3672 y Fk(A2)p 2188 3672 V 31 w(writeToFile\(\))p
Fl(,)g(9)2095 3772 y Fk(A2)p 2188 3772 V 31 w(writeToFormatted)o(Fi)o
(le\()o(\))p Fl(,)f(9)2095 3871 y Fk(A2)p 2188 3871 V
31 w(zero\(\))p Fl(,)k(8)1908 5656 y(12)p eop
%%Trailer
end
userdict /end-hook known{end-hook}if
%%EOF
er)e(and)i
(statistics.)208 1284 y Fg(Err)l(or)i(che)l(cking:)38
b Fl(If)28 b Fk(mtx)f Fl(or)g Fk(fp)f Fl(are)h Fk(NULL)p
Fl(,)f(an)h(error)f(message)g(is)i(prin)n(ted)f(and)h(zero)e(is)i
(returned.)101 1449 y(8.)42 b Fk(void)f(A2_writeStats)e(\()k(A2)g
(*mtx,)e(FILE)h(*fp)g(\))i(;)208 1581 y Fl(This)27 b(metho)r(d)h
(writes)f(a)h(header)e(BKL.h 0100644 0002055 0007177 00000000070 06534106403 0012650 0 ustar 00cleve compmath 0000040 0000006 #ifndef _BKL_
#define _BKL_
#include "BKL/BKL.h"
#endif
BKL/BKL.h 0100644 0002055 0007177 00000021260 06534106125 0013265 0 ustar 00cleve compmath 0000040 0000006 /* BKL.h */
#include "../BPG.h"
#include "../cfiles.h"
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
the BKL object handles the block kernihan-lin family
of algorithms defined on bipartite graphs.
bpg -- bipartite graph to work with,
not free'd when BKL object is free'd
ndom -- number of domains
nseg -- number of segments
nreg -- number of regions, nreg = ndom + nseg
totweight -- total weight of the bipartite graph
npass -- # of passes made
npatch -- # of patches evaluated
nflips -- # of domain flips that were executed
nimprove -- # of improvement steps
ngaineval -- # of gain evaluations
colors -- map from regions to colors, size nreg
cweights -- array to store color weights,
cweights[0] -- separator weight
cweights[1] -- black component weight
cweights[2] -- white component weight
regwghts -- vector of region weights.
if the Graph g has vertex weights then
regwght points to its vertex weights
and is not free'd when the BKL object is free'd
else
regwghts is allocated and set to unit weights
and free'd when the BKL object is free'd
endif
alpha -- cost function parameter
cost = |S|(1 + alpha*max(|B|,|W|)/min(|B|,|W|))
created -- 95oct07, cca
modified -- 95dec07, cca
directory cleaned up, added some efficiency,
inserted exhaustive search into fidmat procedure.
-------------------------------------------------------------------
*/
typedef struct _BKL BKL ;
struct _BKL {
BPG *bpg ;
int ndom ;
int nseg ;
int nreg ;
int totweight ;
int npass ;
int npatch ;
int nflips ;
int nimprove ;
int ngaineval ;
int *colors ;
int cweights[3] ;
int *regwghts ;
float alpha ;
} ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
constructor
created -- 95oct07, cca
-----------------------
*/
BKL *
BKL_new (
void
) ;
/*
-----------------------
set the default fields
created -- 95oct07, cca
-----------------------
*/
void
BKL_setDefaultFields (
BKL *bkl
) ;
/*
-----------------------
clear the data fields
created -- 95oct07, cca
-----------------------
*/
void
BKL_clearData (
BKL *bkl
) ;
/*
-----------------------
destructor
created -- 95oct07, cca
-----------------------
*/
void
BKL_free (
BKL *bkl
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
initialize the object
created -- 95oct07, cca
-----------------------
*/
void
BKL_init (
BKL *bkl,
BPG *bpg,
float alpha
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in util.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------
set the colors of the domains and segments
by coloring the domains black or white randomly.
created -- 95oct07, cca
------------------------------------------------
*/
void
BKL_setRandomColors (
BKL *bkl,
int seed
) ;
/*
-----------------------------------------
set the component weights.
note, we assume the domain colors are set
created -- 95oct07, cca
-----------------------------------------
*/
void
BKL_setColorWeights (
BKL *bkl
) ;
/*
---------------------------------------
return the segment color, a function of
the colors of its neighboring domains.
created -- 95oct07, cca
---------------------------------------
*/
int
BKL_segColor (
BKL *bkl,
int iseg
) ;
/*
-----------------------
flip the domain
created -- 95oct07, cca
-----------------------
*/
void
BKL_flipDomain (
BKL *bkl,
int idom
) ;
/*
------------------------------
return the next domain to flip
in a grey code sequence
created -- 95oct07, cca
------------------------------
*/
int
BKL_greyCodeDomain (
BKL *bkl,
int count
) ;
/*
----------------------------------------------------------------
set the initial partition.
flag -- specifies initial partition type
flag == 1 --> random coloring of domains
flag == 2 --> one black domain, (seed % ndom), rest are white
flag == 3 --> one black pseudoperipheral domain, found using
domain (seed % ndom) as root, rest are white
flag == 4 --> roughly half-half split, breadth first search
of domains, (seed % ndom) as root
flag == 5 --> roughly half-half split, breadth first search
of domains, (seed % ndom) as root to find
a pseudoperipheral domain as root
flag == 6 --> use domcolors[] to seed the colors[] array
seed -- random number seed, for flag == 1, if seed > 0 then
we call srand48(seed) to set the random number
generator.
domcolors -- vector of domain colors, used when flag == 6
created -- 95oct11, cca
----------------------------------------------------------------
*/
float
BKL_setInitPart (
BKL *bkl,
int flag,
int seed,
int domcolors[]
) ;
/*
---------------------------------------------------
return 1 if the domain is adjacent to the separator
created -- 95oct11, cca
---------------------------------------------------
*/
int
BKL_domAdjToSep (
BKL *bkl,
int dom
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in exhSearch.c -------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------------------
perform an exhaustive search over a subspace of domains
mdom -- number of domains in the subspace
domids -- vector of domain ids, size mdom
tcolors -- temporary vector to hold active domain colors, size mdom
note : region colors and component weights of the best
partition are left in bkl->colors[] and bkl->cweights[].
return value -- cost of best partition
created -- 95oct07, cca
--------------------------------------------------------------------
*/
float
BKL_exhSearch (
BKL *bkl,
int mdom,
int domids[],
int tcolors[]
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in evalfcn.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
evaluate the partition
created -- 95oct07, cca
-----------------------
*/
float
BKL_evalfcn (
BKL *bkl
) ;
/*
-----------------------
evaluate the partition
created -- 95oct07, cca
-----------------------
*/
float
BKL_eval (
BKL *bkl,
int Sweight,
int Bweight,
int Wweight
) ;
/*
---------------------------------------------------------
evaluate the (deltaS, deltaB and deltaW) of a domain flip
created -- 950ct11, cca
---------------------------------------------------------
*/
void
BKL_evalgain (
BKL *bkl,
int dom,
int *pdeltaS,
int *pdeltaB,
int *pdeltaW
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in fidmat.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------
improve the partition using the FidMat algorithm
created -- 95oct11, cca
------------------------------------------------
*/
float
BKL_fidmat (
BKL *bkl
) ;
/*--------------------------------------------------------------------*/
BKL/makefile 0100644 0002055 0007177 00000000141 06636223540 0014203 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd doc ; make clean
BKL/src/makefile 0100644 0002055 0007177 00000000717 06636021035 0014776 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
OBJ = BKL
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(evalfcn.o) \
$(OBJ).a(exhSearch.o) \
$(OBJ).a(fidmat.o) \
$(OBJ).a(init.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo lib $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
BKL/src/makeGlobalLib 0100644 0002055 0007177 00000000643 06600260743 0015706 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = BKL
SRC = basics.c \
evalfcn.c \
exhSearch.c \
fidmat.c \
init.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
BKL/src/basics.c 0100644 0002055 0007177 00000004304 06542212712 0014702 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../BKL.h"
/*--------------------------------------------------------------------*/
/*
-----------------------
constructor
created -- 95oct07, cca
-----------------------
*/
BKL *
BKL_new (
void
) {
BKL *bkl ;
ALLOCATE(bkl, struct _BKL, 1) ;
BKL_setDefaultFields(bkl) ;
return(bkl) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 95oct07, cca
-----------------------
*/
void
BKL_setDefaultFields (
BKL *bkl
) {
if ( bkl == NULL ) {
fprintf(stderr, "\n fatal error in BKL_setDefaultFields(%p)"
"\n bad input\n", bkl) ;
exit(-1) ;
}
bkl->bpg = NULL ;
bkl->ndom = 0 ;
bkl->nseg = 0 ;
bkl->nreg = 0 ;
bkl->totweight = 0 ;
bkl->npass = 0 ;
bkl->npatch = 0 ;
bkl->nflips = 0 ;
bkl->nimprove = 0 ;
bkl->ngaineval = 0 ;
bkl->colors = NULL ;
bkl->alpha = 0.0 ;
bkl->cweights[0] = bkl->cweights[1] = bkl->cweights[2] = 0 ;
bkl->regwghts = NULL ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
clear the data fields
created -- 95oct07, cca
modified -- 95dec07, cca
memory leak (bkl->regwghts) fixed
------------------------------------
*/
void
BKL_clearData (
BKL *bkl
) {
if ( bkl == NULL ) {
fprintf(stderr, "\n fatal error in BKL_clearData(%p)"
"\n bad input\n", bkl) ;
exit(-1) ;
}
if ( bkl->colors != NULL ) {
IVfree(bkl->colors) ;
}
if ( bkl->bpg != NULL
&& bkl->bpg->graph != NULL
&& bkl->bpg->graph->vwghts == NULL
&& bkl->regwghts != NULL ) {
IVfree(bkl->regwghts) ;
}
BKL_setDefaultFields(bkl) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
destructor
created -- 95oct07, cca
-----------------------
*/
void
BKL_free (
BKL *bkl
) {
if ( bkl == NULL ) {
fprintf(stderr, "\n fatal error in BKL_free(%p)"
"\n bad input\n", bkl) ;
exit(-1) ;
}
BKL_clearData(bkl) ;
FREE(bkl) ;
return ; }
/*--------------------------------------------------------------------*/
BKL/src/evalfcn.c 0100644 0002055 0007177 00000010465 06534106124 0015061 0 ustar 00cleve compmath 0000040 0000006 /* evalfcn.c */
#include "../BKL.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------
evaluate the partition
created -- 95oct07, cca
-----------------------
*/
float
BKL_evalfcn (
BKL *bkl
) {
float cost ;
int wmax, wmin ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL ) {
fprintf(stderr, "\n fatal error in BKL_evalfcn(%p)"
"\n bad input\n", bkl) ;
exit(-1) ;
}
if ( bkl->cweights[1] <= bkl->cweights[2] ) {
wmin = bkl->cweights[1] ;
wmax = bkl->cweights[2] ;
} else {
wmin = bkl->cweights[2] ;
wmax = bkl->cweights[1] ;
}
if ( wmin == 0 ) {
cost = ((float) bkl->totweight) * bkl->totweight ;
} else {
cost = bkl->cweights[0] * (1. + (bkl->alpha * wmax)/wmin) ;
}
return(cost) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
evaluate the partition
created -- 95oct07, cca
-----------------------
*/
float
BKL_eval (
BKL *bkl,
int Sweight,
int Bweight,
int Wweight
) {
float cost ;
int wmax, wmin ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL ) {
fprintf(stderr, "\n fatal error in BKL_evalfcn(%p)"
"\n bad input\n", bkl) ;
exit(-1) ;
}
if ( Bweight <= Wweight ) {
wmin = Bweight ;
wmax = Wweight ;
} else {
wmin = Wweight ;
wmax = Bweight ;
}
if ( wmin == 0 ) {
cost = ((float) bkl->totweight) * bkl->totweight ;
} else {
cost = Sweight * (1. + (bkl->alpha * wmax)/wmin) ;
}
return(cost) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
evaluate the (deltaS, deltaB and deltaW) of a domain flip
created -- 950ct11, cca
---------------------------------------------------------
*/
void
BKL_evalgain (
BKL *bkl,
int dom,
int *pdeltaS,
int *pdeltaB,
int *pdeltaW
) {
int ii, newc, oldc, seg, size ;
int *adj, *colors, *regwghts ;
int stats[3] ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL || dom < 0 || dom >= bkl->ndom
|| pdeltaS == NULL || pdeltaB == NULL || pdeltaW == NULL ) {
fprintf(stderr, "\n fatal error in BKL_evalGain(%p,%d,%p,%p,%p)"
"\n bad input\n", bkl, dom, pdeltaS, pdeltaB, pdeltaW) ;
exit(-1) ;
}
colors = bkl->colors ;
regwghts = bkl->regwghts ;
stats[0] = stats[1] = stats[2] = 0 ;
/*
---------------
flip the domain
---------------
*/
if ( colors[dom] == 1 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n domain %d, old color = 1, new color = 2", dom) ;
fflush(stdout) ;
#endif
stats[1] -= regwghts[dom] ;
stats[2] += regwghts[dom] ;
colors[dom] = 2 ;
} else {
#if MYDEBUG > 0
fprintf(stdout, "\n domain %d, old color = 2, new color = 1", dom) ;
fflush(stdout) ;
#endif
stats[2] -= regwghts[dom] ;
stats[1] += regwghts[dom] ;
colors[dom] = 1 ;
}
/*
-------------------------------
loop over the adjacent segments
-------------------------------
*/
Graph_adjAndSize(bkl->bpg->graph, dom, &size, &adj) ;
for ( ii = 0 ; ii < size ; ii++ ) {
seg = adj[ii] ;
oldc = colors[seg] ;
newc = BKL_segColor(bkl, seg) ;
#if MYDEBUG > 0
fprintf(stdout,
"\n segment %d, weight = %d, old color = %d, new color = %d",
seg, regwghts[seg], oldc, newc) ;
fflush(stdout) ;
#endif
if ( oldc != newc ) {
stats[oldc] -= regwghts[seg] ;
stats[newc] += regwghts[seg] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n stats = < %d %d %d >",
stats[0], stats[1], stats[2]) ;
fflush(stdout) ;
#endif
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n stats = < %d %d %d > ",
stats[0], stats[1], stats[2]) ;
fflush(stdout) ;
#endif
/*
------------------------
set the output variables
------------------------
*/
*pdeltaS = stats[0] ;
*pdeltaB = stats[1] ;
*pdeltaW = stats[2] ;
/*
--------------------
flip the domain back
--------------------
*/
if ( colors[dom] == 1 ) {
colors[dom] = 2 ;
} else {
colors[dom] = 1 ;
}
/*
---------------------------------
increment the number of gainevals
---------------------------------
*/
bkl->ngaineval++ ;
return ; }
/*--------------------------------------------------------------------*/
BKL/src/exhSearch.c 0100644 0002055 0007177 00000007772 06534106124 0015364 0 ustar 00cleve compmath 0000040 0000006 /* exhSearch.c */
#include "../BKL.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
perform an exhaustive search over a subspace of domains
mdom -- number of domains in the subspace
domids -- vector of domain ids, size mdom
tcolors -- temporary vector to hold active domain colors, size mdom
note : region colors and component weights of the best
partition are left in bkl->colors[] and bkl->cweights[].
return value -- cost of best partition
created -- 95oct07, cca
--------------------------------------------------------------------
*/
float
BKL_exhSearch (
BKL *bkl,
int mdom,
int domids[],
int tcolors[]
) {
float bestcost, newcost ;
int idom, ierr, iflip, iloc, jloc, nflip ;
int *colors ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL || mdom < 1 || domids == NULL || tcolors == NULL ) {
fprintf(stderr, "\n fatal error in BKL_exhaustiveSearch(%p,%d,%p,%p)"
"\n bad input\n", bkl, mdom, domids, tcolors) ;
exit(-1) ;
}
colors = bkl->colors ;
bkl->nflips = 0 ;
#if MYDEBUG > 0
fprintf(stdout, "\n inside BKL_exhSearch(%p,%d,%p,%p)",
bkl, mdom, domids, tcolors) ;
fprintf(stdout, "\n bkl->nflips = %d", bkl->nflips) ;
fflush(stdout) ;
#endif
/*
---------------------------------------------
copy the present colors and component weights
---------------------------------------------
*/
for ( iloc = 0 ; iloc < mdom ; iloc++ ) {
idom = domids[iloc] ;
tcolors[iloc] = colors[idom] ;
}
/*
---------------------
compute the best cost
---------------------
*/
bestcost = BKL_evalfcn(bkl) ;
#if MYDEBUG > 0
fprintf(stdout, "\n inside BKL_exhSearch(%p,%d,%p,%p)",
bkl, mdom, domids, tcolors) ;
fprintf(stdout, "\n %d domain ids : ", mdom) ;
IVfp80(stdout, mdom, domids, 20, &ierr) ;
fprintf(stdout, "\n color weights < %6d %6d %6d >, cost %9.2f",
bkl->cweights[0], bkl->cweights[1], bkl->cweights[2],
bestcost) ;
fflush(stdout) ;
#endif
#if MYDEBUG > 2
fprintf(stdout, "\n colors ") ;
IVfp80(stdout, bkl->nreg, colors, 80, &ierr) ;
fflush(stdout) ;
#endif
/*
---------------------------------
count the number of flips to make
---------------------------------
*/
for ( idom = 0, nflip = 1 ; idom < mdom ; idom++ ) {
nflip *= 2 ;
}
/*
--------------------------
loop over the 2^mdom flips
--------------------------
*/
for ( iflip = 1 ; iflip < nflip ; iflip++ ) {
iloc = BKL_greyCodeDomain(bkl, iflip) ;
idom = domids[iloc] ;
#if MYDEBUG > 1
fprintf(stdout, "\n FLIP %4d domain %4d", bkl->nflips, idom) ;
fflush(stdout) ;
#endif
#if MYDEBUG > 2
fprintf(stdout, "\n colors before flip") ;
IVfp80(stdout, bkl->nreg, colors, 80, &ierr) ;
fflush(stdout) ;
#endif
BKL_flipDomain(bkl, idom) ;
#if MYDEBUG > 2
fprintf(stdout, "\n colors after flip") ;
IVfp80(stdout, bkl->nreg, colors, 80, &ierr) ;
fprintf(stdout, "\n cweights : < %9d %9d %9d > ",
bkl->cweights[0], bkl->cweights[1], bkl->cweights[2]) ;
fflush(stdout) ;
#endif
newcost = BKL_evalfcn(bkl) ;
#if MYDEBUG > 1
fprintf(stdout, ", < %6d %6d %6d >, cost %9.2f",
bkl->cweights[0], bkl->cweights[1], bkl->cweights[2],
newcost) ;
fflush(stdout) ;
#endif
if ( newcost < bestcost ) {
#if MYDEBUG > 1
fprintf(stdout, ", better") ;
fflush(stdout) ;
#endif
bkl->nimprove++ ;
for ( jloc = 0 ; jloc < mdom ; jloc++ ) {
tcolors[jloc] = colors[domids[jloc]] ;
}
bestcost = newcost ;
}
}
/*
-----------------------------------------------------
restore the best colors and update the segment colors
-----------------------------------------------------
*/
for ( iloc = 0 ; iloc < mdom ; iloc++ ) {
idom = domids[iloc] ;
if ( colors[idom] != tcolors[iloc] ) {
BKL_flipDomain(bkl, idom) ;
}
}
return(bestcost) ; }
/*--------------------------------------------------------------------*/
------BKL/src/fidmat.c 0100644 0002055 0007177 00000023503 06616416320 0014707 0 ustar 00cleve compmath 0000040 0000006 /* fidmat.c */
#include "../BKL.h"
#define MYDEBUG 0
#define MAXNDOM_FOR_EXHAUSTIVE_SEARCH 8
/*--------------------------------------------------------------------*/
/*
---------------------------
structure used in this file
---------------------------
*/
typedef struct _cell Cell ;
struct _cell {
int domid ;
int deltaS ;
int deltaB ;
int deltaW ;
Cell *prev ;
Cell *next ;
} ;
static Cell Head, *head = &Head ;
static Cell Undo, *undo = &Undo ;
static float
BKL_fidmatPass (
BKL *bkl,
Cell cells[],
int tags[],
Graph *DomByDom,
int npass
) ;
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
improve the partition using the FidMat algorithm
created -- 95oct11, cca
modified -- 95dec07, cca
memory leak fixed, comments added, DomByDom inserted
-------------------------------------------------------
*/
float
BKL_fidmat (
BKL *bkl
) {
float cost ;
int ndom ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL ) {
fprintf(stderr, "\n fatal error in BKL_fidmat(%p)"
"\n bad input\n", bkl) ;
exit(-1) ;
}
ndom = bkl->ndom ;
/*
---------------------------------------------
if ndom <= MAXNDOM_FOR_EXHAUSTIVE_SEARCH then
do exhaustive search
else
do fidmat sweeps
endif
---------------------------------------------
*/
if ( ndom <= MAXNDOM_FOR_EXHAUSTIVE_SEARCH ) {
int mdom, *domids, *tcolors ;
/*
--------------------
do exhaustive search
--------------------
*/
mdom = ndom - 1 ;
domids = IVinit(mdom, -1) ;
tcolors = IVinit(mdom, -1) ;
IVramp(mdom, domids, 1, 1) ;
BKL_exhSearch(bkl, mdom, domids, tcolors) ;
IVfree(domids) ;
IVfree(tcolors) ;
cost = BKL_evalfcn(bkl) ;
} else {
Cell *cell, *cells ;
float bestcost ;
Graph *DomByDom ;
int idom ;
int *tags ;
/*
---------------------------------------------------
initialize the cell objects and the working vectors
---------------------------------------------------
*/
ALLOCATE(cells, struct _cell, ndom) ;
tags = IVinit(ndom, -1) ;
for ( idom = 0, cell = cells ; idom < ndom ; idom++, cell++ ) {
cell->domid = idom ;
cell->deltaS = cell->deltaB = cell->deltaW = 0 ;
cell->prev = cell->next = cell ;
}
/*
-------------------------------------
create the domain-domain Graph object
-------------------------------------
*/
DomByDom = BPG_makeGraphXbyX(bkl->bpg) ;
#if MYDEBUG > 1
fprintf(stdout, "\n\n domain-domain Graph object") ;
Graph_writeForHumanEye(DomByDom, stdout) ;
fflush(stdout) ;
#endif
/*
--------------------------
make the first fidmat pass
--------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n\n pass %d, cost %.2f, < %d %d %d >",
bkl->npass, BKL_evalfcn(bkl),
bkl->cweights[0], bkl->cweights[1], bkl->cweights[2]) ;
fflush(stdout) ;
#endif
bkl->npass = 1 ;
bestcost = BKL_fidmatPass(bkl, cells, tags, DomByDom, bkl->npass) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n pass %d, cost %.2f, < %d %d %d >",
bkl->npass, bestcost,
bkl->cweights[0], bkl->cweights[1], bkl->cweights[2]) ;
fflush(stdout) ;
#endif
/*
---------------------------------------------------
make additional passes while the partition improves
---------------------------------------------------
*/
while ( 1 ) {
bkl->npass++ ;
cost = BKL_fidmatPass(bkl, cells, tags, DomByDom, bkl->npass) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n pass %d, cost %.2f, < %d %d %d >",
bkl->npass, cost,
bkl->cweights[0], bkl->cweights[1], bkl->cweights[2]) ;
fflush(stdout) ;
#endif
if ( cost < bestcost ) {
bestcost = cost ;
} else {
break ;
}
}
/*
------------------------
free the working storage
------------------------
*/
FREE(cells) ;
IVfree(tags) ;
Graph_free(DomByDom) ;
}
return(cost) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------
make one pass of the FidMat algorithm
created -- 95oct11, cca
-------------------------------------
*/
static float
BKL_fidmatPass (
BKL *bkl,
Cell cells[],
int tags[],
Graph *DomByDom,
int npass
) {
Cell *cell ;
float bestcost, bettercost, cost ;
int dom, dom2, ii, ndom, size ;
int *cweights, *doms ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL || cells == NULL || tags == NULL || DomByDom == NULL ){
fprintf(stderr, "\n fatal error in BKL_fidmatPass(%p,%p,%p,%p,%d)"
"\n bad input\n", bkl, cells, tags, DomByDom, npass) ;
exit(-1) ;
}
ndom = bkl->ndom ;
cweights = bkl->cweights ;
/*
------------------------------
evaluate the current partition
------------------------------
*/
bestcost = BKL_evalfcn(bkl) ;
/*
-----------------------------------------------------
fill the cells with domains adjacent to the separator
-----------------------------------------------------
*/
head->next = head->prev = head ;
undo->next = undo->prev = undo ;
for ( dom = 0 ; dom < ndom ; dom++ ) {
cell = &cells[dom] ;
cell->domid = dom ;
cell->prev = cell->next = cell ;
if ( BKL_domAdjToSep(bkl, dom) == 1 ) {
/*
----------------------------------------
domain dom is adjacent to the separator
evaluate its change and insert into list
----------------------------------------
*/
BKL_evalgain(bkl, dom, &cell->deltaS,
&cell->deltaB, &cell->deltaW) ;
#if MYDEBUG > 1
fprintf(stdout, "\n loading domain %d, <%d %d %d>",
dom, cell->deltaS, cell->deltaB, cell->deltaW) ;
fflush(stdout) ;
#endif
DLIST_TAIL_INSERT(head, cell) ;
}
}
/*
---------------
loop over moves
---------------
*/
while ( head->next != head ) {
/*
-----------------------------------------------
find best move to make w.r.t. the cost function
-----------------------------------------------
*/
cell = head->next ;
dom = cell->domid ;
bettercost = BKL_eval(bkl, cweights[0] + cell->deltaS,
cweights[1] + cell->deltaB,
cweights[2] + cell->deltaW) ;
#if MYDEBUG > 1
fprintf(stdout, "\n domain %d, move cost = %.1f",
dom, bettercost) ;
fflush(stdout) ;
#endif
for ( cell = cell->next ; cell != head ; cell = cell->next ) {
cost = BKL_eval(bkl, cweights[0] + cell->deltaS,
cweights[1] + cell->deltaB,
cweights[2] + cell->deltaW) ;
#if MYDEBUG > 1
fprintf(stdout, "\n domain %d, move cost = %.1f",
cell->domid, cost) ;
fflush(stdout) ;
#endif
if ( cost < bettercost ) {
#if MYDEBUG > 1
fprintf(stdout, ", better") ;
fflush(stdout) ;
#endif
dom = cell->domid ;
bettercost = cost ;
}
}
/*
-----------------------------
remove the node from the list
-----------------------------
*/
cell = &cells[dom] ;
DLIST_DELETE(cell) ;
/*
---------------
flip the domain
---------------
*/
#if MYDEBUG > 1
fprintf(stdout, "\n flipping domain %d, cweights <%d %d %d>",
dom, cweights[0] + cell->deltaS,
cweights[1] + cell->deltaB,
cweights[2] + cell->deltaW) ;
fflush(stdout) ;
#endif
BKL_flipDomain(bkl, dom) ;
cost = BKL_eval(bkl, cweights[0], cweights[1], cweights[2]) ;
#if MYDEBUG > 1
fprintf(stdout, ", cost = %.1f", cost) ;
fflush(stdout) ;
#endif
if ( bestcost > cost ) {
/*
---------------------------------------------
better partition found, set undo list to NULL
---------------------------------------------
*/
bestcost = cost ;
DLIST_DELETE(undo) ;
bkl->nimprove++ ;
} else {
/*
----------------------------------------------
partition is not better, add move to undo list
----------------------------------------------
*/
DLIST_HEAD_INSERT(undo, cell) ;
}
/*
--------------------------
loop over adjacent domains
--------------------------
*/
tags[dom] = npass ;
Graph_adjAndSize(DomByDom, dom, &size, &doms) ;
for ( ii = 0 ; ii < size ; ii++ ) {
dom2 = doms[ii] ;
if ( tags[dom2] < npass && BKL_domAdjToSep(bkl, dom2) == 1 ) {
/*
------------------------------------
domain dom2 has not yet been flipped
and is adjacent to the separator
------------------------------------
*/
#if MYDEBUG > 1
fprintf(stdout,
"\n domain %d, not yet flipped, adj to separator",
dom2) ;
fflush(stdout) ;
#endif
cell = &cells[dom2] ;
BKL_evalgain(bkl, dom2, &cell->deltaS,
&cell->deltaB, &cell->deltaW) ;
#if MYDEBUG > 1
fprintf(stdout, ", gain < %d %d %d >",
cell->deltaS, cell->deltaB, cell->deltaW) ;
fflush(stdout) ;
#endif
if ( cell->prev == cell ) {
/*
---------------------------------------------
domain is not on the list of domains eligible
to move, insert on the tail of the list
---------------------------------------------
*/
DLIST_TAIL_INSERT(head, cell) ;
}
}
}
}
/*
-------------------------------------------------------
undo the flips of domains since the last best partition
-------------------------------------------------------
*/
while ( (cell = undo->next) != undo ) {
#if MYDEBUG > 1
fprintf(stdout, "\n un-flipping domain %d", cell->domid) ;
fflush(stdout) ;
#endif
DLIST_DELETE(cell) ;
BKL_flipDomain(bkl, cell->domid) ;
}
return(bestcost) ; }
/*--------------------------------------------------------------------*/
colors) ;
cost = BKL_evalfcn(bkl) ;
} else {
Cell *cell, *cells ;
float bestcost ;
Graph *DomByDom ;
int idom ;
int *tags ;
/*
--------------------------BKL/src/init.c 0100644 0002055 0007177 00000002156 06534106124 0014404 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../BKL.h"
/*--------------------------------------------------------------------*/
/*
-----------------------
initialize the object
created -- 95oct07, cca
-----------------------
*/
void
BKL_init (
BKL *bkl,
BPG *bpg,
float alpha
) {
/*
---------------
check the input
---------------
*/
if ( bkl == NULL || bpg == NULL ) {
fprintf(stderr, "\n fatal error in BKL_init(%p,%p,%f)"
"\n bad input\n", bkl, bpg, alpha) ;
exit(-1) ;
}
/*
--------------
clear the data
--------------
*/
BKL_clearData(bkl) ;
/*
---------------------
initialize the fields
---------------------
*/
bkl->bpg = bpg ;
bkl->ndom = bpg->nX ;
bkl->nseg = bpg->nY ;
bkl->nreg = bpg->nX + bpg->nY ;
if ( bpg->graph->vwghts == NULL ) {
bkl->totweight = bkl->nreg ;
bkl->regwghts = IVinit(bkl->nreg, 1) ;
} else {
bkl->regwghts = bpg->graph->vwghts ;
bkl->totweight = IVsum(bkl->nreg, bkl->regwghts) ;
}
bkl->colors = IVinit(bkl->nreg, 0) ;
bkl->alpha = alpha ;
return ; }
/*--------------------------------------------------------------------*/
BKL/src/util.c 0100644 0002055 0007177 00000031570 06534106124 0014420 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../BKL.h"
#include "../../Drand.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
------------------------------------------------
set the colors of the domains and segments
by coloring the domains black or white randomly.
created -- 95oct07, cca
------------------------------------------------
*/
void
BKL_setRandomColors (
BKL *bkl,
int seed
) {
int ireg, ndom, nreg ;
int *colors ;
Drand drand ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL || bkl->bpg == NULL ) {
fprintf(stderr, "\n fatal error in BKL_setRandomColors(%p,%d)"
"\n bad input\n", bkl, seed) ;
exit(-1) ;
}
ndom = bkl->ndom ;
nreg = bkl->nreg ;
colors = bkl->colors ;
Drand_setDefaultFields(&drand) ;
Drand_init(&drand) ;
Drand_setUniform(&drand, 0.0, 1.0) ;
if ( seed > 0 ) {
/*
--------------------------
set the random number seed
--------------------------
*/
Drand_setSeed(&drand, seed) ;
}
/*
-----------------
color the domains
-----------------
*/
for ( ireg = 0 ; ireg < ndom ; ireg++ ) {
colors[ireg] = (Drand_value(&drand) < 0.5) ? 1 : 2 ;
}
/*
--------------------------------------------
color the segments and set the color weights
--------------------------------------------
*/
BKL_setColorWeights(bkl) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------
set the component weights.
note, we assume the domain colors are set
created -- 95oct07, cca
modified -- 95dec07, cca
error checking inserted for colors
-----------------------------------------
*/
void
BKL_setColorWeights (
BKL *bkl
) {
int c, ireg ;
int *colors ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL ) {
fprintf(stderr, "\n fatal error in BKL_setColorsWeights(%p)"
"\n bad input\n", bkl) ;
exit(-1) ;
}
colors = bkl->colors ;
bkl->cweights[0] = bkl->cweights[1] = bkl->cweights[2] = 0 ;
/*
---------------------
check out the domains
---------------------
*/
for ( ireg = 0 ; ireg < bkl->ndom ; ireg++ ) {
if ( (c = colors[ireg]) < 1 || 2 < c ) {
fprintf(stderr, "\n fatal error in BKL_setColorWeights(%p)"
"\n region %d has color %d", bkl, ireg, c) ;
exit(-1) ;
}
bkl->cweights[c] += bkl->regwghts[ireg] ;
}
/*
------------------
color the segments
------------------
*/
for ( ireg = bkl->ndom ; ireg < bkl->nreg ; ireg++ ) {
if ( (c = BKL_segColor(bkl, ireg)) < 0 || 2 < c ) {
fprintf(stderr, "\n fatal error in BKL_setColorWeights(%p)"
"\n region %d has color %d", bkl, ireg, c) ;
exit(-1) ;
}
colors[ireg] = c ;
bkl->cweights[c] += bkl->regwghts[ireg] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------
return the segment color, a function of
the colors of its neighboring domains.
created -- 95oct07, cca
---------------------------------------
*/
int
BKL_segColor (
BKL *bkl,
int iseg
) {
int color, ii, size ;
int *adj, *colors ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL || iseg < bkl->ndom || iseg >= bkl->nreg ) {
fprintf(stderr, "\n fatal error in BKL_segColor(%p,%d)"
"\n bad input\n", bkl, iseg) ;
exit(-1) ;
}
colors = bkl->colors ;
/*
----------------------------------------------------
loop over adjacent domans,
break if adjacent to two differently colored domains
----------------------------------------------------
*/
Graph_adjAndSize(bkl->bpg->graph, iseg, &size, &adj) ;
color = 0 ;
if ( size > 0 ) {
color = colors[adj[0]] ;
for ( ii = 1 ; ii < size ; ii++ ) {
if ( color != colors[adj[ii]] ) {
color = 0 ;
break ;
}
}
}
return(color) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------
flip the domain
created -- 95oct07, cca
modified -- 95dec07, cca
simple mod to segment loop made
----------------------------------
*/
void
BKL_flipDomain (
BKL *bkl,
int idom
) {
int ii, iseg, newcolor, oldcolor, size, wdom, wseg ;
int *adj, *colors, *regwghts ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL || idom < 0 || idom >= bkl->ndom ) {
fprintf(stderr, "\n fatal error in BKL_flipDomain(%p,%d)"
"\n bad input\n", bkl, idom) ;
exit(-1) ;
}
colors = bkl->colors ;
regwghts = bkl->regwghts ;
switch ( (oldcolor = colors[idom]) ) {
case 1 :
newcolor = 2 ;
break ;
case 2 :
newcolor = 1 ;
break ;
default :
fprintf(stderr, "\n fatal error in BKL_flipDomain(%p,%d)"
"\n colors[%d] = %d\n", bkl, idom, idom, colors[idom]) ;
exit(-1) ;
}
colors[idom] = newcolor ;
/*
--------------------------------------
adjust color weights for moving domain
--------------------------------------
*/
wdom = regwghts[idom] ;
bkl->cweights[oldcolor] -= wdom ;
bkl->cweights[newcolor] += wdom ;
/*
-------------------------------
loop over the adjacent segments
-------------------------------
*/
Graph_adjAndSize(bkl->bpg->graph, idom, &size, &adj) ;
for ( ii = 0 ; ii < size ; ii++ ) {
iseg = adj[ii] ;
wseg = regwghts[iseg] ;
#if MYDEBUG > 0
fprintf(stdout, "\n checking out segment %d, weight %d",
iseg, wseg) ;
#endif
if ( (oldcolor = colors[iseg])
!= (newcolor = BKL_segColor(bkl, iseg)) ) {
bkl->cweights[oldcolor] -= wseg ;
bkl->cweights[newcolor] += wseg ;
colors[iseg] = newcolor ;
}
}
/*
-----------------------------
increment the number of flips
-----------------------------
*/
bkl->nflips++ ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------
return the next domain to flip
in a grey code sequence
created -- 95oct07, cca
modified -- 95dec07, cca
error message inserted
------------------------------
*/
int
BKL_greyCodeDomain (
BKL *bkl,
int count
) {
int chk, idom, res ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL ) {
fprintf(stderr, "\n fatal error in BKL_greyCodeDomain(%p)"
"\n bad input\n", bkl) ;
exit(-1) ;
}
for ( idom = 0, res = 1, chk = 2 ;
/* no test */ ;
idom++, res = chk, chk *= 2 ) {
if ( count % chk == res ) {
return(idom) ;
}
}
fprintf(stderr, "\n fatal error in BKL_greyCodeDomain(%p,%d)"
"\n should never have reached this point\n", bkl, count) ;
exit(-1) ;
return(-2) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
set the initial partition.
flag -- specifies initial partition type
flag == 1 --> random coloring of domains
flag == 2 --> one black domain, (seed % ndom), rest are white
flag == 3 --> one black pseudoperipheral domain, found using
domain (seed % ndom) as root, rest are white
flag == 4 --> roughly half-half split, breadth first search
of domains, (seed % ndom) as root
flag == 5 --> roughly half-half split, breadth first search
of domains, (seed % ndom) as root to find
a pseudoperipheral domain as root
flag == 6 --> use domcolors[] to seed the colors[] array
seed -- random number seed, for flag == 1, if seed > 0 then
we call set the random number generator.
domcolors -- vector of domain colors, used when flag == 6
created -- 95oct11, cca
modified -- 95nov30, cca
switch for one and two domains inserted.
----------------------------------------------------------------
*/
float
BKL_setInitPart (
BKL *bkl,
int flag,
int seed,
int domcolors[]
) {
BPG *bpg ;
float cost ;
int dom, dom2, dsize, idom, ii, jj, last, ndom, now, root,
seg, ssize ;
int *colors, *cweights, *dadj, *list, *mark, *sadj ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL
|| flag < 1 || 6 < flag || (flag == 6 && domcolors == NULL) ) {
fprintf(stderr, "\n fatal error in BKL_setInitPart(%p,%d,%d,%p)"
"\n bad input\n", bkl, flag, seed, domcolors) ;
exit(-1) ;
}
bpg = bkl->bpg ;
ndom = bkl->ndom ;
colors = bkl->colors ;
cweights = bkl->cweights ;
if ( ndom == 1 ) {
colors[0] = 1 ;
BKL_setColorWeights(bkl) ;
} else if ( ndom == 2 ) {
colors[0] = 1 ;
colors[1] = 2 ;
BKL_setColorWeights(bkl) ;
} else {
/*
---------------------
switch over the cases
---------------------
*/
switch ( flag ) {
case 1 : {
Drand drand ;
/*
-------------
random colors
-------------
*/
Drand_setDefaultFields(&drand) ;
Drand_init(&drand) ;
Drand_setUniform(&drand, 0.0, 1.0) ;
if ( seed > 0 ) {
/*
--------------------------
set the random number seed
--------------------------
*/
Drand_setSeed(&drand, seed) ;
}
for ( idom = 0 ; idom < ndom ; idom++ ) {
colors[idom] = (Drand_value(&drand) < 0.5) ? 1 : 2 ;
}
BKL_setColorWeights(bkl) ;
break ; }
case 2 :
case 3 :
/*
--------------------------------------------------------
one domain colored black = 1, the rest colored white = 2
domain is specified (flag = 2) or pseudoperipheral
(flag = 3)
--------------------------------------------------------
*/
IVfill(ndom, colors, 2) ;
if ( flag == 2 ) {
colors[seed % ndom] = 1 ;
} else {
root = BPG_pseudoperipheralnode(bkl->bpg, seed % ndom) ;
colors[root] = 1 ;
}
BKL_setColorWeights(bkl) ;
break ;
case 4 :
case 5 :
/*
----------------------------------------------
split using a random or pseudoperipheral node
as a root of a breadth first traversal
1. color all domains white
2. color segments and get color weights
3. fill the list with the seed domain
4. do a breadth first traversal of the domains
5. flip the domain
6. if |B| >= |W| then break
7. add unmarked neighboring domains to list
----------------------------------------------
*/
IVfill(ndom, colors, 2) ;
BKL_setColorWeights(bkl) ;
list = IVinit(ndom, -1) ;
mark = IVinit(ndom, -1) ;
if ( flag == 4 ) {
list[0] = seed % ndom ;
} else {
list[0] = BPG_pseudoperipheralnode(bkl->bpg, seed % ndom) ;
}
now = last = 0 ;
mark[list[0]] = 1 ;
while ( now <= last ) {
dom = list[now++] ;
BKL_flipDomain(bkl, dom) ;
if ( cweights[1] >= cweights[2] ) {
break ;
}
Graph_adjAndSize(bpg->graph, dom, &dsize, &dadj) ;
for ( ii = 0 ; ii < dsize ; ii++ ) {
seg = dadj[ii] ;
Graph_adjAndSize(bpg->graph, seg, &ssize, &sadj) ;
for ( jj = 0 ; jj < ssize ; jj++ ) {
dom2 = sadj[jj] ;
if ( mark[dom2] == -1 ) {
if ( last == ndom - 1 ) {
fprintf(stderr,
"\n fatal error in BKL_setInitPart(%p,%d,%d,%p)"
"\n list[] size exceeded\n",
bkl, flag, seed, domcolors) ;
exit(-1) ;
}
mark[dom2] = 1 ;
list[++last] = dom2 ;
}
}
}
}
IVfree(list) ;
IVfree(mark) ;
BKL_setColorWeights(bkl) ;
break ;
case 6 :
/*
------------------
copy domain colors
------------------
*/
IVcopy(ndom, colors, domcolors) ;
BKL_setColorWeights(bkl) ;
break ;
}
}
cost = BKL_evalfcn(bkl) ;
return(cost) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
return 1 if the domain is adjacent to the separator
created -- 95oct11, cca
---------------------------------------------------
*/
int
BKL_domAdjToSep (
BKL *bkl,
int dom
) {
int ii, size ;
int *adj, *colors ;
/*
---------------
check the input
---------------
*/
if ( bkl == NULL || dom < 0 || dom >= bkl->ndom ) {
fprintf(stderr, "\n fatal error in BKL_domAdjToSep(%p,%d)"
"\n bad input\n", bkl, dom) ;
exit(-1) ;
}
colors = bkl->colors ;
Graph_adjAndSize(bkl->bpg->graph, dom, &size, &adj) ;
for ( ii = 0 ; ii < size ; ii++ ) {
if ( colors[adj[ii]] == 0 ) {
/*
-------------------------------------
segment is on the separator, return 1
-------------------------------------
*/
return(1) ;
}
}
return(0) ; }
/*--------------------------------------------------------------------*/
BKL/doc/ 0042755 0002055 0007177 00000000000 06542767330 0013267 5 ustar 00cleve compmath 0000040 0000006 BKL/doc/dataStructure.tex 0100644 0002055 0007177 00000003542 06534106125 0016630 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:BKL:dataStructure}
\par
The {\tt BKL} object has the following fields.
\begin{itemize}
\item
{\tt BPG *bpg} : pointer to a {\tt BPG} bipartite graph object,
not owned by the {\tt BKL} object.
\item
{\tt int ndom} : number of domains, domain ids are in {\tt [0,ndom)}
\item
{\tt int nseg} : number of segments,
segment ids are in {\tt [ndom,ndom + nseg)}
\item
{\tt int nreg} : number of regions, equal to {\tt ndom + nseg}
\item
{\tt int totweight} : total weight of the domains and segments
\item
{\tt int npass} : number of Fiduccia-Mattheyes passes
\item
{\tt int npatch} : number of patches evaluated, not used during the
Fiduccia-Mattheyes algorithm
\item
{\tt int nflips} : number of domains that were flipped
\item
{\tt int nimprove} : number of improvements in the partition
\item
{\tt int ngaineval} : number of gain evaluations, roughly equivalent to
the number of degree evaluations in the minimum degree algorithm
\item
{\tt int *colors} : pointer to an {\tt int} vector of size {\tt nreg},
{\tt colors[idom]} is {\tt 1} or {\tt 2} for domain {\tt idom},
{\tt colors[iseg]} is {\tt 0}, {\tt 1} or {\tt 2}
for segment {\tt iseg}.
\item
{\tt int *cweights} : pointer to an {\tt int} vector of size 3,
{\tt cweights[0]} contains the weight of the separator,
{\tt cweights[1]} and {\tt cweights[2]} contains the
weights of the two components
\item
{\tt int *regwghts} :
pointer to an {\tt int} vector of size {\tt nreg},
used to store the weights of the domains and segments
\item
{\tt float alpha} : number used to store the partition
evaluation parameter, the cost of the partition is
\begin{verbatim}
balance = max(cweights[1], cweights[2])/min(cweights[1], cweights[2]) ;
cost = cweights[0]*(1. + alpha*balance) ;
\end{verbatim}
\end{itemize}
ts,
segment ids are in {\tt [ndom,ndom + nseg)}
\item
{\tt int nreg} : number of regions, equal to {\tt ndom + nseg}
\item
{\tt int totweight}BKL/doc/intro.tex 0100644 0002055 0007177 00000000716 06534106125 0015131 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt BKL}: Block Kernighan-Lin Object}
\label{chapter:BKL}
\par
Our {\tt BKL} object is used to find an initial separator of a
graph.
Its input is a {\tt BPG} bipartite graph object that represents the
domain-segment graph of a domain decomposition of the graph.
After a call to the {\tt BKL\_fidmat()} method, the object contains
a two-color partition of the graph that is accessible via the
{\tt colors[]} and {\tt cweights[]} vectors of the object.
BKL/doc/main.tex 0100644 0002055 0007177 00000001120 06650656161 0014721 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
% \documentstyle[leqno,11pt,twoside]{report}
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt BKL} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt BKL} : {\it DRAFT} \quad \today \hrulefill}
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input main.ind
\end{document}
BKL/doc/proto.tex 0100644 0002055 0007177 00000032230 06534106125 0015135 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt BKL} methods}
\label{section:BKL:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt BKL} object.
\par
\section{Basic methods}
\label{subsection:BKL:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
BKL * BKL_new ( void ) ;
\end{verbatim}
\index{BKL_new@{\tt BKL\_new()}}
This method simply allocates storage for the {\tt BKL} structure
and then sets the default fields by a call to
{\tt BKL\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BKL_setDefaultFields ( BKL *bkl ) ;
\end{verbatim}
\index{BKL_setDefaultFields@{\tt BKL\_setDefaultFields()}}
This method sets the fields of the structure to their default
values:
{\tt bpg}, {\tt colors} and {\tt regwghts} are set to {\tt NULL},
the {\tt int} parameters are set to zero,
and the {\tt cweights} vector is filled with zeros.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BKL_clearData ( BKL *bkl ) ;
\end{verbatim}
\index{BKL_clearData@{\tt BKL\_clearData()}}
This method clears any data allocated by the object,
namely the {\tt colors} and {\tt regwghts} vectors.
It then fills the structure's fields with default values
with a call to {\tt BKL\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BKL_free ( BKL *bkl ) ;
\end{verbatim}
\index{BKL_free@{\tt BKL\_free()}}
This method releases any storage by a call to
{\tt BKL\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initializer methods}
\label{subsection:BKL:proto:initializers}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BKL_init ( BKL *bkl, BPG *bpg, float alpha ) ;
\end{verbatim}
\index{BKL_init@{\tt BKL\_init()}}
This method initializes the {\tt BKL} object given a bipartite
graph object and cost function parameter as input.
Any previous data is cleared with a call to {\tt BKL\_clearData()}.
The {\tt ndom}, {\tt nseg} and {\tt nreg} scalars are set,
the {\tt regwghts[]} vector allocated and filled,
and
the {\tt colors[]} vector allocated and filled with zeros.
\par \noindent {\it Error checking:}
If {\tt bkl} or {\tt bpg} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:BKL:proto:utilities}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BKL_setRandomColors ( BKL *bkl, int seed ) ;
\end{verbatim}
\index{BKL_setRandomColors@{\tt BKL\_setRandomColors()}}
If {\tt seed > 0}
a random number generator is set using {\tt seed}.
The domains are then colored {\tt 1} or {\tt 2} randomly
and {\tt BKL\_setColorWeights()} is called to set the segment
weights.
\par \noindent {\it Error checking:}
If {\tt bkl} or {\tt bkl->bpg} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BKL_setColorWeights ( BKL *bkl ) ;
\end{verbatim}
\index{BKL_setColorWeights@{\tt BKL\_setColorWeights()}}
This method sets the color weights for the region.
It assumes that all domains are colored {\tt 1} or {\tt 2}.
The segments are then colored.
If a segment is adjacent only to domains of one color, its color is
that color, otherwise its color is {\tt 0}.
\par \noindent {\it Error checking:}
If {\tt bkl} or {\tt bkl->bpg} is {\tt NULL},
an error message is printed and the program exits.
The colors of the domains are checked to ensure they are {\tt 1} or
{\tt 2}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BKL_segColor ( BKL *bkl, int iseg ) ;
\end{verbatim}
\index{BKL_segColor@{\tt BKL\_segColor()}}
This method returns the color of segment {\tt iseg}.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
or if {\tt iseg} is not in {\tt [bkl->ndom, bkl->nreg)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BKL_flipDomain ( BKL *bkl, int idom ) ;
\end{verbatim}
\index{BKL_flipDomain@{\tt BKL\_flipDomain()}}
This method flips the color of domain {\tt idom},
adjusts the colors of neighboring segments
and the {\tt cweights[]} vector.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
or if {\tt idom} is not in {\tt [0,bkl->ndom)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BKL_greyCodeDomain ( BKL *bkl, int count ) ;
\end{verbatim}
\index{BKL_greyCodeDomain@{\tt BKL\_greyCodeDomain()}}
This method returns the next domain id in a grey code sequence,
used to exhaustively search of a subspace of partitions
defined by set of candidate domains to flip.
The value {\tt count} ranges from {\tt 1} to $2^{\mbox{\tt ndom}}$.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
float BKL_setInitPart ( BKL *bkl, int flag, int seed, int domcolors[] ) ;
\end{verbatim}
\index{BKL_setInitPart@{\tt BKL\_setInitPart()}}
This method sets the initial partition
by coloring the domains and segments.
The {\tt flag} parameter has the following values.
\begin{itemize}
\item
{\tt flag = 1} $\longrightarrow$
random coloring of the domains
\item
{\tt flag = 2} $\longrightarrow$
one black domain, ({\tt seed} \% {\tt ndom}), rest are white
\item
{\tt flag = 3} $\longrightarrow$
one black pseudoperipheral domain, found using
domain ({\tt seed} \% {\tt ndom}) as root, rest are white
\item
{\tt flag = 4} $\longrightarrow$
roughly half-half split, breadth first search
of domains, ({\tt seed} \% {\tt ndom}) as root
\item
{\tt flag = 5} $\longrightarrow$
roughly half-half split, breadth first search
of domains, ({\tt seed} \% {\tt ndom}) as root to find
a pseudoperipheral domain as root
\item
{\tt flag = 6} $\longrightarrow$
use {\tt domcolors[]} to seed the {\tt colors[]} array
\end{itemize}
The {\tt seed} input parameter is for a random number generator.
The {\tt domcolors[]} input array is used only for {\tt flag = 6}.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
or if {\tt flag = 6} and {\tt domcolors} is {\tt NULL},
or if {\tt flag} is not in {\tt [1,6]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BKL_domAdjToSep ( BKL *bkl, int dom ) ;
\end{verbatim}
\index{BKL_domAdjToSep@{\tt BKL\_domAdjToSep()}}
This method returns {\tt 1}
if domain {\tt dom} is adjacent to the separator
and {\tt 0} otherwise.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
or if {\tt dom} is not in {\tt [0,ndom)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Partition evaluation methods}
\label{subsection:BKL:proto:evaluation}
\par
There are three functions that evaluate the cost of a partition.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BKL_evalgain ( BKL *bkl, int dom, int *pdeltaS, int *pdeltaB, int *pdeltaW ) ;
\end{verbatim}
\index{BKL_evalgain@{\tt BKL\_evalgain()}}
This method evaluates the change in the components
$\Delta S$, $\Delta B$ and $\Delta W$
that would occur if domain {\tt dom} were to be flipped.
These {\it gain} values are put into the storage pointed to by
{\tt pdeltaS}, {\tt pdeltaB} and {\tt pdeltaW}.
The method checks that {\tt bkl}, {\tt pdeltaS}, {\tt pdeltaB}
and {\tt pdeltaW} are not {\tt NULL}
and that {\tt idom} is in {\tt [0,bkl->ndom)}.
\par \noindent {\it Error checking:}
If {\tt bkl}, {\tt pdeltaS}, {\tt pdeltaB} or {\tt pdeltaW}
is {\tt NULL},
or if {\tt dom} is not in {\tt [0,ndom)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
float BKL_evalfcn ( BKL *bkl ) ;
\end{verbatim}
\index{BKL_evalfcn@{\tt BKL\_evalfcn()}}
The $|S|$, $|B|$ and $|W|$ values are taken from the {\tt
cweights[]} vector.
If $\min(|B|,|W|) > 0$, this function returns
$$
|S|\left(1 + \alpha * \frac{\max(|B|,|W|)}{\min(|B|,|W|)} \right),
$$
otherwise it returns $(|S| + |B| + |W|)^2$.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
float BKL_eval ( BKL *bkl, int Sweight, int Bweight, int Wweight ) ;
\end{verbatim}
\index{BKL_eval@{\tt BKL\_eval()}}
The $|S|$, $|B|$ and $|W|$ values are taken from the {\tt
Sweight}, {\tt Bweight} and {\tt Wweight} parameters.
If $\min(|B|,|W|) > 0$, this function returns
$$
|S|\left(1 + \alpha * \frac{\max(|B|,|W|)}{\min(|B|,|W|)} \right),
$$
otherwise it returns $(|S| + |B| + |W|)^2$.
The method checks that {\tt bkl} is not {\tt NULL}.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Partition improvement methods}
\label{subsection:BKL:proto:improve}
\par
There are two functions that take a given partition and some input
parameters and return a (hopefully) improved partition.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
float BKL_exhSearch ( BKL *bkl, int mdom, int domids[], int tcolors[] ) ;
\end{verbatim}
\index{BKL_exhSearch@{\tt BKL\_exhSearch()}}
This method performs an exhaustive search of a subspace of
partitions and returns the best partition.
The starting partition is given by the {\tt BKL} object's {\tt
colors[]} vector.
The subspace of domains to flip is defined by the {\tt
domids[mdom]} vector.
The {\tt tcolors[]} vector is a work vector.
There are $2^{\mbox{\tt mdom}}$ distinct partitions in the subspace
to be explored.
We flip the domains using a grey code sequence so a total of
$2^{\mbox{\tt mdom}}$ domain flips are performed.
The {\tt bkl->colors[]} vector is filled with the colors of
the best partition and its cost is returned.
\par \noindent {\it Error checking:}
If {\tt bkl}, {\tt domids} or {\tt tcolors} is {\tt NULL},
or if {\tt mdom < 1},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
float BKL_fidmat ( BKL *bkl ) ;
\end{verbatim}
\index{BKL_fidmat@{\tt BKL\_fidmat()}}
If the number of domains is eight or less, an exhaustive search is
made.
Otherwise, this method finds a good partition using a variant of the
Fiduccia-Mattheyes algorithm.
At any step, only the domains that are adjacent to the separator
are eligible to be flipped.
For each eligible domain,
we maintain
$\Delta S$, $\Delta B$ and $\Delta W$,
the change in the three component weights
if this domain were to be flipped.
These values must be updated whenever a neighboring domain has been
flipped, and so is {\it local} information.
The cost of the partition that would result if a domain were to be
flipped is a function of the local information
$\Delta S$, $\Delta B$ and $\Delta W$,
as well as the present weights of the components
(global information).
At each step we evaluate the cost of the resulting partition for each
domain that is eligible to be flipped.
This is relatively expensive when compared to using a heap to contain
$\Delta S$ for each domain, but we have found the resulting
partitions to be better.
The eligible domains are kept on a doubly linked list to allow easy
insertions and deletions.
\par \noindent {\it Error checking:}
If {\tt bkl} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
BKL/doc/main.log 0100644 0002055 0007177 00000004200 06535770762 0014712 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 5 JUN 1998 06:26
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
)
\@indexfile=\write3
Writing index file main.idx
(main.aux) (intro.tex
Chapter 1.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 1.
) (dataStructure.tex [1
]) (proto.tex
Overfull \hbox (15.59521pt too wide) in paragraph at lines 46--50
\elvrm tors. It then fills the struc-ture's fields with de-fault val-ues with a
call to \elvtt BKL[]setDefaultFields()\elvrm .
\hbox(7.60416+0.91246)x442.37993, glue set - 1.0
.\elvrm t
.\elvrm o
.\elvrm r
.\elvrm s
.\elvrm .
.etc.
[2] [3]
Overfull \hbox (34.76115pt too wide) in paragraph at lines 231--231
[] []\elvtt void BKL_evalgain ( BKL *bkl, int dom, int *pdeltaS, int *pdeltaB,
int *pdeltaW ) ;[]
\hbox(7.60416+2.43333)x469.75499
.\glue(\leftskip) 27.37506
.\hbox(0.0+0.0)x0.0
.\glue 0.0
.\hbox(7.05666+0.0)x0.0
..\glue 0.0
..\glue 0.0
..\glue -21.90005
..\glue -5.475
..\hbox(7.05666+0.0)x21.90005, glue set 21.90005fil
...\glue 0.0 plus 1.0fil minus 1.0fil
...\hbox(7.05666+0.0)x0.0, glue set - 8.51668fil []
..etc.
.\penalty 0
.etc.
[4]) (main.ind [5] [6
]) (main.aux) )
Here is how much of TeX's memory you used:
206 strings out of 11977
2150 string characters out of 87269
33248 words of memory out of 262141
2143 multiletter control sequences out of 9500
19780 words of font info for 75 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
13i,6n,17p,180b,228s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (6 pages, 16376 bytes).
BKL/doc/main.aux 0100644 0002055 0007177 00000002667 06535770762 0014745 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}{\string\ptt\space BKL}: Block Kernighan-Lin Object}{1}}
\@writefile{lof}{\string\addvspace\space {10\p@ }}
\@writefile{lot}{\string\addvspace\space {10\p@ }}
\newlabel{chapter:BKL}{{1}{1}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Data Structure}{1}}
\newlabel{section:BKL:dataStructure}{{1.1}{1}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Prototypes and descriptions of {\string\ptt\space BKL} methods}{2}}
\newlabel{section:BKL:proto}{{1.2}{2}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}Basic methods}{2}}
\newlabel{subsection:BKL:proto:basics}{{1.3}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.3.1}Initializer methods}{3}}
\newlabel{subsection:BKL:proto:initializers}{{1.3.1}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.3.2}Utility methods}{3}}
\newlabel{subsection:BKL:proto:utilities}{{1.3.2}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.3.3}Partition evaluation methods}{4}}
\newlabel{subsection:BKL:proto:evaluation}{{1.3.3}{4}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.3.4}Partition improvement methods}{5}}
\newlabel{subsection:BKL:proto:improve}{{1.3.4}{5}}
BKL/doc/main.idx 0100644 0002055 0007177 00000001607 06535770762 0014725 0 ustar 00cleve compmath 0000040 0000006 \indexentry{BKL_new@{\tt BKL\_new()}}{2}
\indexentry{BKL_setDefaultFields@{\tt BKL\_setDefaultFields()}}{2}
\indexentry{BKL_clearData@{\tt BKL\_clearData()}}{2}
\indexentry{BKL_free@{\tt BKL\_free()}}{2}
\indexentry{BKL_init@{\tt BKL\_init()}}{3}
\indexentry{BKL_setRandomColors@{\tt BKL\_setRandomColors()}}{3}
\indexentry{BKL_setColorWeights@{\tt BKL\_setColorWeights()}}{3}
\indexentry{BKL_segColor@{\tt BKL\_segColor()}}{3}
\indexentry{BKL_flipDomain@{\tt BKL\_flipDomain()}}{3}
\indexentry{BKL_greyCodeDomain@{\tt BKL\_greyCodeDomain()}}{3}
\indexentry{BKL_setInitPart@{\tt BKL\_setInitPart()}}{3}
\indexentry{BKL_domAdjToSep@{\tt BKL\_domAdjToSep()}}{4}
\indexentry{BKL_evalgain@{\tt BKL\_evalgain()}}{4}
\indexentry{BKL_evalfcn@{\tt BKL\_evalfcn()}}{4}
\indexentry{BKL_eval@{\tt BKL\_eval()}}{5}
\indexentry{BKL_exhSearch@{\tt BKL\_exhSearch()}}{5}
\indexentry{BKL_fidmat@{\tt BKL\_fidmat()}}{5}
BKL/doc/main.ind 0100644 0002055 0007177 00000001145 06535770760 0014706 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt BKL\_clearData()}, 2
\item {\tt BKL\_domAdjToSep()}, 4
\item {\tt BKL\_eval()}, 5
\item {\tt BKL\_evalfcn()}, 4
\item {\tt BKL\_evalgain()}, 4
\item {\tt BKL\_exhSearch()}, 5
\item {\tt BKL\_fidmat()}, 5
\item {\tt BKL\_flipDomain()}, 3
\item {\tt BKL\_free()}, 2
\item {\tt BKL\_greyCodeDomain()}, 3
\item {\tt BKL\_init()}, 3
\item {\tt BKL\_new()}, 2
\item {\tt BKL\_segColor()}, 3
\item {\tt BKL\_setColorWeights()}, 3
\item {\tt BKL\_setDefaultFields()}, 2
\item {\tt BKL\_setInitPart()}, 3
\item {\tt BKL\_setRandomColors()}, 3
\end{theindex}
BKL/doc/main.ilg 0100644 0002055 0007177 00000000456 06535770760 0014713 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (17 entries accepted, 0 rejected).
Sorting entries....done (68 comparisons).
Generating output file main.ind....done (21 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
BKL/doc/makefile 0100644 0002055 0007177 00000000027 06542767330 0014761 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
BPG.h 0100644 0002055 0007177 00000000070 06534106403 0012650 0 ustar 00cleve compmath 0000040 0000006 #ifndef _BPG_
#define _BPG_
#include "BPG/BPG.h"
#endif
BPG/BPG.h 0100644 0002055 0007177 00000024763 06534106127 0013302 0 ustar 00cleve compmath 0000040 0000006 /* BPG.h */
#include "../Graph.h"
#include "../cfiles.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
the BPG object holds a bipartite graph.
the edge set E \subseteq X \times Y,
where X and Y are two sets of vertices,
X = { 0, 1, ..., nX - 1}
Y = { nX, nX + 1, ..., nX + nY - 1 }
the BPG object contains a Graph object graph,
a hack because C does not possess inheritance.
created -- 95oct06, cca
----------------------------------------------
*/
typedef struct _BPG BPG ;
struct _BPG {
int nX ;
int nY ;
Graph *graph ;
} ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------
purpose -- create and return a new BPG object
created -- 95oct06, cca
-----------------------------------------------
*/
BPG *
BPG_new (
void
) ;
/*
------------------------------------------------------
purpose -- set the default fields for the BPG object
created -- 95oct06, cca
------------------------------------------------------
*/
void
BPG_setDefaultFields (
BPG *bpg
) ;
/*
--------------------------------
purpose -- clear the data fields
created -- 95oct06, cca
--------------------------------
*/
void
BPG_clearData (
BPG *bpg
) ;
/*
--------------------------------
purpose -- free the BPG object
created -- 95oct06, cca
--------------------------------
*/
void
BPG_free (
BPG *bpg
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in DM.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------
compute the generalized Dulmadge-Mendolsohn decomposition
bpg -- BPG bipartite graph object
dmflags -- flags vector
/ 0 if x in X_R
dmflags[x] = | 1 if x in X_I
\ 2 if x in X_E
/ 0 if y in Y_R
dmflags[y] = | 1 if y in Y_I
\ 2 if y in Y_E
stats -- statistics vector
stats[0] -- weight of X_I
stats[1] -- weight of X_E
stats[2] -- weight of X_R
stats[3] -- weight of Y_I
stats[4] -- weight of Y_E
stats[5] -- weight of Y_R
created -- 95oct12, cca
---------------------------------------------------------
*/
void
BPG_DMdecomposition (
BPG *bpg,
int dmflags[],
int stats[],
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in maxFlow.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------------
find the DM decomposition of a weighted bipartite graph
using a simple max flow algorithm
bpg -- BPG bipartite graph object
dmflags -- flags vector
/ 0 if x in X_R
dmflags[x] = | 1 if x in X_I
\ 2 if x in X_E
/ 0 if y in Y_R
dmflags[y] = | 1 if y in Y_I
\ 2 if y in Y_E
stats -- statistics vector
stats[0] -- weight of X_I
stats[1] -- weight of X_E
stats[2] -- weight of X_R
stats[3] -- weight of Y_I
stats[4] -- weight of Y_E
stats[5] -- weight of Y_R
created -- 96mar08, cca
-------------------------------------------------------
*/
void
BPG_DMviaMaxFlow (
BPG *bpg,
int dmflags[],
int stats[],
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------------------
initialize a BPG object, set bpg->nX = nX, bpg->nY = nY,
and bpg->graph = graph. convert graph into bipartite form, i.e.,
adj(v) := adj(v) \cap {nX, ..., nX + nY - 1} for v in [0, nX)
adj(v) := adj(v) \cap {0, ..., nX - 1} for v in [nX, nX+nY)
created -- 95oct06, cca
--------------------------------------------------------------------
*/
void
BPG_init (
BPG *bpg,
int nX,
int nY,
Graph *graph
) ;
/*
-----------------------------------------------------------
initialize from a graph given a color vector and two target
vectors. this method can be used to get the bipartite graph
of the boundary of two components.
graph -- graph from which to extract the bipartite graph
colors -- vector of colors for the vertices
cX -- color for the X vertices
cY -- color for the Y vertices
cmap -- map from vertices in g to vertices in bpg
indX -- vector to hold the global indices in X
indY -- vector to hold the global indices in Y
created -- 95oct06, cca
-----------------------------------------------------------
*/
void
BPG_initFromColoring (
BPG *bpg,
Graph *graph,
int colors[],
int cX,
int cY,
int cmap[],
int indX[],
int indY[]
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in IO.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------
purpose -- to read in a BPG object from a file
input --
fn -- filename, must be *.bpgb or *.bpgf
return value -- 1 if success, 0 if failure
created -- 95oct06, cca
----------------------------------------------
*/
int
BPG_readFromFile (
BPG *bpg,
char *fn
) ;
/*
--------------------------------------------------------
purpose -- to read a BPG object from a formatted file
return value -- 1 if success, 0 if failure
created -- 95oct06, cca
--------------------------------------------------------
*/
int
BPG_readFromFormattedFile (
BPG *bpg,
FILE *fp
) ;
/*
----------------------------------------------------
purpose -- to read a BPG object from a binary file
return value -- 1 if success, 0 if failure
created -- 95oct06, cca
----------------------------------------------------
*/
int
BPG_readFromBinaryFile (
BPG *bpg,
FILE *fp
) ;
/*
--------------------------------------------
purpose -- to write a BPG object to a file
input --
fn -- filename
*.bpgb -- binary
*.bpgf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 95oct06, cca
--------------------------------------------
*/
int
BPG_writeToFile (
BPG *bpg,
char *fn
) ;
/*
------------------------------------------------------
purpose -- to write a BPG object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 95oct06, cca
------------------------------------------------------
*/
int
BPG_writeToFormattedFile (
BPG *bpg,
FILE *fp
) ;
/*
---------------------------------------------------
purpose -- to write a BPG object to a binary file
return value -- 1 if success, 0 otherwise
created -- 95oct06, cca
---------------------------------------------------
*/
int
BPG_writeToBinaryFile (
BPG *bpg,
FILE *fp
) ;
/*
-------------------------------------------------
purpose -- to write a BPG object for a human eye
return value -- 1 if success, 0 otherwise
created -- 95oct06, cca
-------------------------------------------------
*/
int
BPG_writeForHumanEye (
BPG *bpg,
FILE *fp
) ;
/*
-----------------------------------------------------------
purpose -- to write out the statistics for the BPG object
return value -- 1 if success, 0 otherwise
created -- 95oct06, cca
-----------------------------------------------------------
*/
int
BPG_writeStats (
BPG *bpg,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in makeGraphs.c ------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------
purpose -- return the X by X graph where (x1,x2) is an edge
if there exists a y in Y such that (x1,y) and
(x2,y) are edges in the bipartite graph.
created -- 95dec06, cca
to be used in the BKL object.
-----------------------------------------------------------
*/
Graph *
BPG_makeGraphXbyX (
BPG *bpg
) ;
/*
-----------------------------------------------------------
purpose -- return the Y by Y graph where (y1,y2) is an edge
if there exists a x in X such that (x,y1) and
(x,y2) are edges in the bipartite graph.
created -- 95dec07, cca
-----------------------------------------------------------
*/
Graph *
BPG_makeGraphYbyY (
BPG *bpg
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in pseudo.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------
return a pseudoperipheral node
created -- 95oct07, cca
------------------------------
*/
int
BPG_pseudoperipheralnode (
BPG *bpg,
int seed
) ;
/*
----------------------------------------------------
return value -- # of vertices in the level structure
created -- 95oct07, cca
----------------------------------------------------
*/
int
BPG_levelStructure (
BPG *bpg,
int root,
int list[],
int dist[],
int mark[],
int tag
) ;
/*--------------------------------------------------------------------*/
BPG/makefile 0100644 0002055 0007177 00000000223 06636223542 0014206 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd drivers ; make clean
cd doc ; make clean
BPG/src/makefile 0100644 0002055 0007177 00000000774 06636021145 0015003 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = BPG
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(DM.o) \
$(OBJ).a(init.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(makeGraphs.o) \
$(OBJ).a(maxFlow.o) \
$(OBJ).a(pseudo.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
BPG/src/makeGlobalLib 0100644 0002055 0007177 00000000657 06600260747 0015717 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = BPG
SRC = basics.c \
DM.c \
init.c \
IO.c \
makeGraphs.c \
maxFlow.c \
pseudo.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
BPG/src/DM.c 0100644 0002055 0007177 00000116065 06534106126 0013750 0 ustar 00cleve compmath 0000040 0000006 /* DM.c */
#include "../../BPG.h"
/*--------------------------------------------------------------------*/
/*
-----------------
static prototypes
-----------------
*/
static void
nonunitDM ( BPG *bpg, int dmflags[], int stats[],
int msglvl, FILE *msgFile) ;
static void
unitDM ( BPG *bpg, int dmflags[], int stats[],
int msglvl, FILE *msgFile) ;
static int
nonunitFindExposedNode ( BPG *bpg, int uexp, int list[], int link[],
int mark[], int tag, int nvexp[], IVL *ivl,
int msglvl, FILE *msgFile ) ;
static int
nonunitFindNmatch ( BPG *bpg, int uexp, int vexp, int nvexp[],
int link[], IVL *ivl, int msglvl, FILE *msgFile ) ;
static void
nonunitFlipEdges ( BPG *bpg, int uexp, int vexp, int nmatch,
int nvexp[], int link[], IVL *ivl, int msglvl,
FILE *msgFile ) ;
static void
nonunitSetFlags ( BPG *bpg, int list[], int nvexp[], int mark[],
IVL *ivl, int dmflags[], int stats[], int msglvl,
FILE *msgFile ) ;
static void
unitFindMaxMatch ( BPG *bpg, int mate[], int msglvl, FILE *msgFile ) ;
static int
unitAugmentingPath ( BPG *bpg, int uexp, int mate[], int mark[],
int link[], int list[], int msglvl, FILE *msgFile ) ;
static void
unitSetFlags ( BPG *bpg, int mate[], int dmflags[], int stats[],
int msglvl, FILE *msgFile ) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
compute the generalized Dulmadge-Mendolsohn decomposition
bpg -- BPG bipartite graph object
dmflags -- flags vector
/ 0 if x in X_R
dmflags[x] = | 1 if x in X_I
\ 2 if x in X_E
/ 0 if y in Y_R
dmflags[y] = | 1 if y in Y_I
\ 2 if y in Y_E
stats -- statistics vector
stats[0] -- weight of X_I
stats[1] -- weight of X_E
stats[2] -- weight of X_R
stats[3] -- weight of Y_I
stats[4] -- weight of Y_E
stats[5] -- weight of Y_R
created -- 95oct12, cca
---------------------------------------------------------
*/
void
BPG_DMdecomposition (
BPG *bpg,
int dmflags[],
int stats[],
int msglvl,
FILE *msgFile
) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n inside BPG_DMdecomposition") ;
fflush(msgFile) ;
}
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || dmflags == NULL || stats == NULL
|| (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr,
"\n fatal error in BPG_DMdecomposition(%p,%p,%p,%d,%p)"
"\n bad input\n", bpg, dmflags, stats, msglvl, msgFile) ;
exit(-1) ;
}
if ( bpg->graph->type % 2 == 0 ) {
/*
-----------------
unit weight graph
-----------------
*/
unitDM(bpg, dmflags, stats, msglvl, msgFile) ;
} else {
/*
--------------------
nonunit weight graph
--------------------
*/
nonunitDM(bpg, dmflags, stats, msglvl, msgFile) ;
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n leaving BPG_DMdecomposition") ;
fflush(msgFile) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
compute the generalized Dulmadge-Mendolsohn decomposition
for a nonunit weight graph.
bpg -- BPG bipartite graph object
dmflags -- flags vector
/ 0 if x in X_R
dmflags[x] = | 1 if x in X_I
\ 2 if x in X_E
/ 0 if y in Y_R
dmflags[y] = | 1 if y in Y_I
\ 2 if y in Y_E
stats -- statistics vector
stats[0] -- weight of X_I
stats[1] -- weight of X_E
stats[2] -- weight of X_R
stats[3] -- weight of Y_I
stats[4] -- weight of Y_E
stats[5] -- weight of Y_R
created -- 95oct12, cca
---------------------------------------------------------
*/
static void
nonunitDM (
BPG *bpg,
int dmflags[],
int stats[],
int msglvl,
FILE *msgFile
) {
int maxnXnY, nmatch, nX, nY, tag, x, xexp, y, yexp ;
int *link, *list, *mark, *nvexp ;
IVL *ivl ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n inside nonunitDM") ;
fflush(msgFile) ;
}
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || dmflags == NULL || stats == NULL ) {
fprintf(stderr, "\n fatal error in nonunitDM(%p,%p,%p)"
"\n bad input\n", bpg, dmflags, stats) ;
exit(-1) ;
}
nX = bpg->nX ;
nY = bpg->nY ;
maxnXnY = ( nX >= nY ) ? nX : nY ;
/*
-----------------------
create the working data
-----------------------
*/
list = IVinit(maxnXnY, -1) ;
link = IVinit(nX+nY, -1) ;
mark = IVinit(nX+nY, -1) ;
nvexp = IVinit(nX+nY, 0) ;
IVcopy(nX + nY, nvexp, bpg->graph->vwghts) ;
ivl = IVL_new() ;
IVL_setDefaultFields(ivl) ;
IVL_init3(ivl, IVL_CHUNKED, nX + nY, nvexp) ;
/*
--------
DEBUG!!!
--------
*/
/*
{ int v ;
for ( v = 0 ; v < nX + nY ; v++ ) {
IVshuffle(bpg->g->adjIVL->sizes[v], bpg->g->adjIVL->p_vec[v], 57) ;
}
}
*/
/*
------------------------
loop over the x vertices
------------------------
*/
for ( xexp = 0, tag = 1 ; xexp < nX ; xexp++ ) {
while ( nvexp[xexp] > 0 ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n\n checking out %d, nvexp[%d] = %d",
xexp, xexp, nvexp[xexp]) ;
}
yexp = nonunitFindExposedNode(bpg, xexp, list, link, mark,
tag, nvexp, ivl, msglvl, msgFile) ;
tag++ ;
if ( yexp == -1 ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile,
"\n exposed node %d, no alternating path", xexp) ;
fflush(msgFile) ;
}
break ;
} else {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile,
"\n exposed node %d, alternating node ends at %d",
xexp, yexp) ;
fprintf(msgFile, "\n path : %d", yexp) ;
x = link[yexp] ;
while ( x != xexp ) {
y = link[x] ;
fprintf(msgFile, " --> %d ==> %d", x, y) ;
x = link[y] ;
}
fprintf(msgFile, " --> %d", xexp) ;
fflush(msgFile) ;
}
nmatch = nonunitFindNmatch(bpg, xexp, yexp, nvexp, link,
ivl, msglvl, msgFile) ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n nmatch = %d", nmatch) ;
}
nonunitFlipEdges(bpg, xexp, yexp, nmatch, nvexp, link,
ivl, msglvl, msgFile) ;
}
}
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n match IVL") ;
IVL_writeForHumanEye(ivl, msgFile) ;
}
/*
-------------
set the flags
-------------
*/
nonunitSetFlags(bpg, list, nvexp, mark, ivl,
dmflags, stats, msglvl, msgFile) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(list) ;
IVfree(link) ;
IVfree(mark) ;
IVfree(nvexp) ;
IVL_free(ivl) ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n leaving nonunitDM") ;
fflush(msgFile) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
find exposed node that is the endpoint of
an alternating path that starts with uexp
this method uses a breadth-first traversal
uexp -- exposed node to be the start of the alternating path
list -- list vector, size max(nX, nY)
link -- link vector, used to define alternating path, size nX + nY
mark -- mark vector, used to keep track of nodes in the tree
tag -- unique tag for this call
nvexp -- nvexp[u] = # of exposed vertices in u
ivl -- IVL object to hold matched edges
return value -- exposed node if exists, otherwise -1
created -- 95oct14, cca
---------------------------------------------------------------------
*/
static int
nonunitFindExposedNode (
BPG *bpg,
int uexp,
int list[],
int link[],
int mark[],
int tag,
int nvexp[],
IVL *ivl,
int msglvl,
FILE *msgFile
) {
int ierr, ii, jj, last, now, u, unew, usize, v, vsize ;
int *uadj, *vind ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n inside nonunitFindExposedNode(%d)", uexp) ;
fflush(msgFile) ;
}
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || uexp < 0 || uexp > (bpg->nX + bpg->nY)
|| list == NULL || link == NULL
|| mark == NULL || nvexp == NULL || ivl == NULL ) {
fprintf(stderr,
"\n fatal error in nonunitFindExposedNode2(%p,%d,%p,%p,%p,%d,%p,%p)"
"\n bad input\n",
bpg, uexp, list, link, mark, tag, nvexp, ivl) ;
exit(-1) ;
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n\n working on exposed %d, nvexp %d",
uexp, nvexp[uexp]) ;
}
/*
-----------------------------------
load the list with the exposed node
-----------------------------------
*/
now = last = 0 ;
list[0] = u = uexp ;
mark[u] = tag ;
while ( now <= last ) {
u = list[now++] ;
Graph_adjAndSize(bpg->graph, u, &usize, &uadj) ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n checking out u = %d : ", u) ;
IVfp80(msgFile, usize, uadj, 20, &ierr) ;
fflush(msgFile) ;
}
for ( ii = 0 ; ii < usize ; ii++ ) {
v = uadj[ii] ;
if ( mark[v] != tag ) {
mark[v] = tag ;
link[v] = u ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile,
"\n adding %d with nvexp[%d] = %d to tree",
v, v, nvexp[v]) ;
fflush(msgFile) ;
}
if ( nvexp[v] > 0 ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, ", exposed") ;
fflush(msgFile) ;
}
return(v) ;
} else {
IVL_listAndSize(ivl, v, &vsize, &vind) ;
for ( jj = 0 ; jj < vsize ; jj++ ) {
unew = vind[jj] ;
if ( unew == -1 ) {
break ;
} else if ( mark[unew] != tag ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile,
"\n adding %d to tree", unew) ;
fflush(msgFile) ;
}
mark[unew] = tag ;
link[unew] = v ;
list[++last] = unew ;
}
}
}
}
}
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n leaving nonunitFindExposedNode") ;
fflush(msgFile) ;
}
return(-1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
find the minimum number of match weights along the path from
exposed node uexp to exposed node vexp.
link -- link vector, used to define alternating path, size nX + nY
nvexp -- nvexp[u] = # of exposed vertices in u
return value -- minimum match weight
created -- 95oct12, cca
-------------------------------------------------------------------
*/
static int
nonunitFindNmatch (
BPG *bpg,
int uexp,
int vexp,
int nvexp[],
int link[],
IVL *ivl,
int msglvl,
FILE *msgFile
) {
int count, ii, msize, nmatch, u, v ;
int *mind ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL
|| uexp < 0 || uexp > (bpg->nX + bpg->nY)
|| vexp < 0 || vexp > (bpg->nX + bpg->nY)
|| (uexp < bpg->nX && vexp < bpg->nX)
|| (uexp >= bpg->nX && vexp >= bpg->nX)
|| nvexp == NULL || link == NULL || ivl == NULL ) {
fprintf(stderr,
"\n fatal error in nonunitFindNmatch(%p,%d,%d,%p,%p,%p)"
"\n bad input\n", bpg, uexp, vexp, nvexp, link, ivl) ;
exit(-1) ;
}
/*
----------------------------------------------------------
set nmatch = min(# of exposed vertices in uexp and vexp)
----------------------------------------------------------
*/
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n nvexp[%d] = %d, nvexp[%d] = %d",
uexp, nvexp[uexp], vexp, nvexp[vexp]) ;
fflush(msgFile) ;
}
nmatch = (nvexp[uexp] <= nvexp[vexp]) ? nvexp[uexp] : nvexp[vexp] ;
if ( nmatch == 1 ) {
return(1) ;
}
/*
---------------------------------------------------------------
find the minimum of the weight of the matched edges in the path
---------------------------------------------------------------
*/
u = link[vexp] ;
while ( u != uexp ) {
v = link[u] ;
/*
---------------------------------------------
count the number of times u is matched with v
---------------------------------------------
*/
IVL_listAndSize(ivl, u, &msize, &mind) ;
for ( ii = 0, count = 0 ; ii < msize ; ii++ ) {
if ( mind[ii] == -1 ) {
break ;
} else if ( mind[ii] == v ) {
count++ ;
}
}
/*
---------------------
check the match count
---------------------
*/
if ( nmatch > count ) {
nmatch = count ;
if ( nmatch == 1 ) {
return(1) ;
}
}
u = link[v] ;
}
return(nmatch) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
given an alternating path, flip the edges
uexp -- exposed node at start of path
vexp -- exposed node at end of path
nmatch -- number of matched edges to flip
nvexp -- nvexp[u] = # of exposed vertices in u
link -- link vector, used to define alternating path,
size nX + nY
ivl -- IVL object to hold matched edges
created -- 95oct12, cca
-------------------------------------------------------
*/
static void
nonunitFlipEdges (
BPG *bpg,
int uexp,
int vexp,
int nmatch,
int nvexp[],
int link[],
IVL *ivl,
int msglvl,
FILE *msgFile
) {
int count, ierr, ii, msize, u, v, vnext ;
int *mind ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL
|| uexp < 0 || uexp > (bpg->nX + bpg->nY)
|| vexp < 0 || vexp > (bpg->nX + bpg->nY)
|| (uexp < bpg->nX && vexp < bpg->nX)
|| (uexp >= bpg->nX && vexp >= bpg->nX)
|| nmatch <= 0
|| nvexp == NULL || link == NULL || ivl == NULL ) {
fprintf(stderr,
"\n fatal error in BPG_flipMatch(%p,%d,%d,%d,%p,%p,%p)"
"\n bad input\n", bpg, uexp, vexp, nmatch, nvexp, link, ivl) ;
exit(-1) ;
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n match lists before edge swaps") ;
IVL_listAndSize(ivl, vexp, &msize, &mind) ;
fprintf(msgFile, "\n %d's match list :", vexp) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
u = link[vexp] ;
while ( u != uexp ) {
IVL_listAndSize(ivl, u, &msize, &mind) ;
fprintf(msgFile, "\n %d's match list :", u) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
v = link[u] ;
IVL_listAndSize(ivl, v, &msize, &mind) ;
fprintf(msgFile, "\n %d's match list :", v) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
u = link[v] ;
}
IVL_listAndSize(ivl, uexp, &msize, &mind) ;
fprintf(msgFile, "\n %d's match list :", uexp) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
fflush(msgFile) ;
}
if ( link[vexp] == uexp ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n simple case, %d <---> %d", uexp, vexp) ;
fflush(msgFile) ;
}
/*
------------------------------------
simple case, uexp --> vexp
1. add to uexp's list
2. add to vexp's list
------------------------------------
*/
IVL_listAndSize(ivl, uexp, &msize, &mind) ;
for ( ii = 0, count = 0 ; ii < msize ; ii++ ) {
if ( mind[ii] == -1 ) {
mind[ii] = vexp ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's list, mind[%d] = %d",
uexp, ii, mind[ii]) ;
fflush(msgFile) ;
}
if ( ++count == nmatch ) {
break ;
}
}
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's match list :", uexp) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
fflush(msgFile) ;
}
if ( count != nmatch ) {
fprintf(stderr, "\n fatal error in BPG_flipMatch()"
"\n uexp = %d, vexp = %d, count = %d, nmatch = %d"
"\n u matches with ", uexp, vexp, count, nmatch) ;
IVfp80(stderr, msize, mind, 12, &ierr) ;
exit(-1) ;
}
IVL_listAndSize(ivl, vexp, &msize, &mind) ;
for ( ii = 0, count = 0 ; ii < msize ; ii++ ) {
if ( mind[ii] == -1 ) {
mind[ii] = uexp ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's list, mind[%d] = %d",
vexp, ii, mind[ii]) ;
fflush(msgFile) ;
}
if ( ++count == nmatch ) {
break ;
}
}
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's match list :", vexp) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
fflush(msgFile) ;
}
if ( count != nmatch ) {
fprintf(stderr, "\n fatal error in BPG_flipMatch()"
"\n uexp = %d, vexp = %d, count = %d, nmatch = %d"
"\n v matches with ", uexp, vexp, count, nmatch) ;
IVfp80(stderr, msize, mind, 12, &ierr) ;
exit(-1) ;
}
} else {
/*
-------------------------------------------------------
uexp <--> v <==> u <--> v <==> u ... v <==> u <--> vexp
deal with the middle edges
-------------------------------------------------------
*/
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n complex case : %d <---> ... <---> %d",
uexp, vexp) ;
fflush(msgFile) ;
}
vnext = vexp ;
u = link[vexp] ;
while ( u != uexp ) {
v = link[u] ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n checking out %d <===> %d <---> %d",
v, u, vnext) ;
fflush(msgFile) ;
}
/*
----------------------------------------------------------
check out u's list of matches, find
if ( nmatch(u,v) == nmatch ) then
replace with
else if ( nmatch(u,v) > nmatch ) then
replace with
add
else
error
endif
----------------------------------------------------------
*/
IVL_listAndSize(ivl, u, &msize, &mind) ;
for ( ii = 0, count = 0 ; ii < msize ; ii++ ) {
if ( mind[ii] == v ) {
mind[ii] = vnext ;
if ( ++count == nmatch ) {
break ;
}
}
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's match list :", u) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
fflush(msgFile) ;
}
if ( count != nmatch ) {
fprintf(stderr, "\n fatal error in BPG_flipMatch()"
"\n u = %d, count = %d, nmatch = %d"
"\n %d match list : ", u, count, nmatch, u) ;
IVfp80(stderr, msize, mind, 12, &ierr) ;
exit(-1) ;
}
IVL_listAndSize(ivl, v, &msize, &mind) ;
for ( ii = 0, count = 0 ; ii < msize ; ii++ ) {
if ( mind[ii] == u ) {
mind[ii] = -1 ;
if ( ++count == nmatch ) {
break ;
}
}
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's match list :", v) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
fflush(msgFile) ;
}
if ( count != nmatch ) {
fprintf(stderr, "\n fatal error in BPG_flipMatch()"
"\n v = %d, count = %d, nmatch = %d"
"\n %d match list : ", v, count, nmatch, v) ;
IVfp80(stderr, msize, mind, 12, &ierr) ;
exit(-1) ;
}
IVL_listAndSize(ivl, vnext, &msize, &mind) ;
for ( ii = 0, count = 0 ; ii < msize ; ii++ ) {
if ( mind[ii] == -1 ) {
mind[ii] = u ;
if ( ++count == nmatch ) {
break ;
}
}
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's match list :", vnext) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
fflush(msgFile) ;
}
if ( count != nmatch ) {
fprintf(stderr, "\n fatal error in BPG_flipMatch()"
"\n vnext = %d, count = %d, nmatch = %d"
"\n %d match list : ", vnext, count, nmatch, vnext) ;
IVfp80(stderr, msize, mind, 12, &ierr) ;
exit(-1) ;
}
/*
---------------------------
on to the next matched pair
---------------------------
*/
vnext = v ;
u = link[v] ;
}
IVL_listAndSize(ivl, uexp, &msize, &mind) ;
for ( ii = 0, count = 0 ; ii < msize ; ii++ ) {
if ( mind[ii] == -1 ) {
mind[ii] = vnext ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's list, mind[%d] = %d",
uexp, ii, mind[ii]) ;
fflush(msgFile) ;
}
if ( ++count == nmatch ) {
break ;
}
}
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's match list :", uexp) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
fflush(msgFile) ;
}
if ( count != nmatch ) {
fprintf(stderr, "\n fatal error in BPG_flipMatch()"
"\n uexp = %d, vnext = %d, count = %d, nmatch = %d"
"\n u matches with ", uexp, vnext, count, nmatch) ;
IVfp80(stderr, msize, mind, 12, &ierr) ;
exit(-1) ;
}
IVL_listAndSize(ivl, vnext, &msize, &mind) ;
for ( ii = 0, count = 0 ; ii < msize ; ii++ ) {
if ( mind[ii] == -1 ) {
mind[ii] = uexp ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's list, mind[%d] = %d",
vnext, ii, mind[ii]) ;
fflush(msgFile) ;
}
if ( ++count == nmatch ) {
break ;
}
}
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n %d's match list :", vnext) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
fflush(msgFile) ;
}
if ( count != nmatch ) {
fprintf(stderr, "\n fatal error in BPG_flipMatch()"
"\n vnext = %d, uexp = %d, count = %d, nmatch = %d"
"\n v matches with ", vnext, uexp, count, nmatch) ;
IVfp80(stderr, msize, mind, 12, &ierr) ;
exit(-1) ;
}
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n match lists after edge swaps") ;
IVL_listAndSize(ivl, vexp, &msize, &mind) ;
fprintf(msgFile, "\n %d's match list :", vexp) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
u = link[vexp] ;
while ( u != uexp ) {
IVL_listAndSize(ivl, u, &msize, &mind) ;
fprintf(msgFile, "\n %d's match list :", u) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
v = link[u] ;
IVL_listAndSize(ivl, v, &msize, &mind) ;
fprintf(msgFile, "\n %d's match list :", v) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
u = link[v] ;
}
IVL_listAndSize(ivl, uexp, &msize, &mind) ;
fprintf(msgFile, "\n %d's match list :", uexp) ;
IVfp80(msgFile, msize, mind, 20, &ierr) ;
fflush(msgFile) ;
}
/*
----------------------------------------------
decrement the nvexp[] values for uexp and vexp
----------------------------------------------
*/
nvexp[uexp] -= nmatch ;
nvexp[vexp] -= nmatch ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n nvexp[%d] = %d", uexp, nvexp[uexp]) ;
fprintf(msgFile, ", nvexp[%d] = %d", vexp, nvexp[vexp]) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
given the maximum matching, set the flags for the DM decomposition
list -- list vector, size max(nX, nY)
nvexp -- nvexp[u] = # of exposed vertices in u
mark -- mark vector, used to keep track of nodes in the tree
ivl -- IVL object to hold matched edges
dmflags -- flags vector
/ 0 if x in X_R
dmflags[x] = | 1 if x in X_I
\ 2 if x in X_E
/ 0 if y in Y_R
dmflags[y] = | 1 if y in Y_I
\ 2 if y in Y_E
stats -- statistics vector
stats[0] -- weight of X_I
stats[1] -- weight of X_E
stats[2] -- weight of X_R
stats[3] -- weight of Y_I
stats[4] -- weight of Y_E
stats[5] -- weight of Y_R
created -- 95oct14, cca
------------------------------------------------------------------
*/
static void
nonunitSetFlags (
BPG *bpg,
int list[],
int nvexp[],
int mark[],
IVL *ivl,
int dmflags[],
int stats[],
int msglvl,
FILE *msgFile
) {
int ii, jj, last, now, nX, nY, x, xnew, xsize, xwght,
y, ynew, ysize, ywght ;
int *vwghts, *xadj, *yadj ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || list == NULL || nvexp == NULL
|| mark == NULL || ivl == NULL || dmflags == NULL ) {
fprintf(stderr,
"\n fatal error in BPG_seDMflags(%p,%p,%p,%p,%p,%p,%p)"
"\n bad input\n",
bpg, list, nvexp, mark, ivl, dmflags, stats) ;
exit(-1) ;
}
nX = bpg->nX ;
nY = bpg->nY ;
vwghts = bpg->graph->vwghts ;
/*
----------------------------------------------
zero the dmflags[] vector and set mark[] to -1
----------------------------------------------
*/
IVzero(nX + nY, dmflags) ;
IVfill(nX + nY, mark, -1) ;
IVzero(6, stats) ;
/*
-------------------------------------
load the list with exposed nodes in X
-------------------------------------
*/
xwght = 0 ;
last = -1 ;
for ( x = 0 ; x < nX ; x++ ) {
if ( nvexp[x] > 0 ) {
list[++last] = x ;
mark[x] = 1 ;
}
xwght += vwghts[x] ;
}
/*
------------------------------------------------------
drop an alternating level structure from the exposed
nodes in X, and set dmflags[] for nodes in X_I and Y_E
------------------------------------------------------
*/
now = 0 ;
while ( now <= last ) {
x = list[now++] ;
dmflags[x] = 1 ;
stats[0] += vwghts[x] ;
Graph_adjAndSize(bpg->graph, x, &xsize, &xadj) ;
for ( ii = 0 ; ii < xsize ; ii++ ) {
y = xadj[ii] ;
if ( mark[y] != 1 ) {
mark[y] = 1 ;
dmflags[y] = 2 ;
stats[4] += vwghts[y] ;
IVL_listAndSize(ivl, y, &ysize, &yadj) ;
for ( jj = 0 ; jj < ysize ; jj++ ) {
if ( (xnew = yadj[jj]) == -1 ) {
break ;
} else if ( mark[xnew] != 1 ) {
mark[xnew] = 1 ;
list[++last] = xnew ;
}
}
}
}
}
/*
-------------------------------------
load the list with exposed nodes in Y
-------------------------------------
*/
ywght = 0 ;
last = -1 ;
for ( y = nX ; y < nX + nY ; y++ ) {
if ( nvexp[y] > 0 ) {
list[++last] = y ;
mark[y] = 2 ;
}
ywght += vwghts[y] ;
}
/*
------------------------------------------------------
drop an alternating level structure from the exposed
nodes in Y, and set dmflags[] for nodes in Y_I and X_E
------------------------------------------------------
*/
now = 0 ;
while ( now <= last ) {
y = list[now++] ;
dmflags[y] = 1 ;
stats[3] += vwghts[y] ;
Graph_adjAndSize(bpg->graph, y, &ysize, &yadj) ;
for ( ii = 0 ; ii < ysize ; ii++ ) {
x = yadj[ii] ;
if ( mark[x] != 2 ) {
mark[x] = 2 ;
dmflags[x] = 2 ;
stats[1] += vwghts[x] ;
IVL_listAndSize(ivl, x, &xsize, &xadj) ;
for ( jj = 0 ; jj < xsize ; jj++ ) {
if ( (ynew = xadj[jj]) == -1 ) {
break ;
} else if ( mark[ynew] != 2 ) {
mark[ynew] = 2 ;
list[++last] = ynew ;
}
}
}
}
}
/*
------------------------------
set the weights of X_R and Y_R
------------------------------
*/
stats[2] = xwght - stats[0] - stats[1] ;
stats[5] = ywght - stats[3] - stats[4] ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
compute the generalized Dulmadge-Mendolsohn decomposition
for a unit weight graph.
bpg -- BPG bipartite graph object
dmflags -- flags vector
/ 0 if x in X_R
dmflags[x] = | 1 if x in X_I
\ 2 if x in X_E
/ 0 if y in Y_R
dmflags[y] = | 1 if y in Y_I
\ 2 if y in Y_E
stats -- statistics vector
stats[0] -- weight of X_I
stats[1] -- weight of X_E
stats[2] -- weight of X_R
stats[3] -- weight of Y_I
stats[4] -- weight of Y_E
stats[5] -- weight of Y_R
created -- 95oct12, cca
---------------------------------------------------------
*/
static void
unitDM (
BPG *bpg,
int dmflags[],
int stats[],
int msglvl,
FILE *msgFile
) {
int nX, nY ;
int *mate ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || dmflags == NULL || stats == NULL ) {
fprintf(stderr, "\n fatal error in unitDM(%p,%p,%p)"
"\n bad input\n", bpg, dmflags, stats) ;
exit(-1) ;
}
nX = bpg->nX ;
nY = bpg->nY ;
mate = IVinit(nX + nY, -1) ;
if ( msglvl > 1 && msgFile != NULL ) {
BPG_writeForHumanEye(bpg, msgFile) ;
}
/*
-----------------------
find a maximum matching
-----------------------
*/
unitFindMaxMatch(bpg, mate, msglvl, msgFile) ;
/*
--------------------------------------
fill the dmflags[] and stats[] vectors
--------------------------------------
*/
unitSetFlags(bpg, mate, dmflags, stats, msglvl, msgFile) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
find a maximum matching for a unit weight graph
created -- 95oct14, cca
-----------------------------------------------
*/
static void
unitFindMaxMatch (
BPG *bpg,
int mate[],
int msglvl,
FILE *msgFile
) {
int nX, nY, rc, x, y ;
int *link, *list, *mark ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || mate == NULL ) {
fprintf(stderr, "\n fatal error in unitFindMaxMatch(%p,%p)"
"\n bad input\n", bpg, mate) ;
exit(-1) ;
}
nX = bpg->nX ;
nY = bpg->nY ;
/*
--------------------------
create the working storage
--------------------------
*/
mark = IVinit(nX + nY, -1) ;
link = IVinit(nX + nY, -1) ;
list = IVinit(nX + nY, -1) ;
/*
---------------------------------------------------------
look for an augmenting path rooted at each exposed vertex
---------------------------------------------------------
*/
if ( nX <= nY ) {
for ( x = 0 ; x < nX ; x++ ) {
if ( mate[x] == -1 ) {
rc = unitAugmentingPath(bpg, x, mate, mark, link, list,
msglvl, msgFile) ;
}
}
} else {
for ( y = nX ; y < nX + nY ; y++ ) {
if ( mate[y] == -1 ) {
rc = unitAugmentingPath(bpg, y, mate, mark, link, list,
msglvl, msgFile) ;
}
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(mark) ;
IVfree(link) ;
IVfree(list) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
look for a augmenting path starting at node uexp.
if one found, flip the match edges.
return value -- 1 if success
0 otherwise
created -- 95oct14, cca
-------------------------------------------------
*/
static int
unitAugmentingPath (
BPG *bpg,
int uexp,
int mate[],
int mark[],
int link[],
int list[],
int msglvl,
FILE *msgFile
) {
int ii, last, nextv, now, u, usize, v ;
int *uadj ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || uexp < 0 || (bpg->nX + bpg->nY <= uexp)
|| mate == NULL || mark == NULL || link == NULL || list == NULL
|| mate[uexp] != -1 ) {
fprintf(stderr,
"\n fatal error in unitAugmentingPath(%p,%d,%p,%p,%p,%p)"
"\n bad input\n", bpg, uexp, mate, mark, link, list) ;
exit(-1) ;
}
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n\n uexp = %d", uexp) ;
}
now = last = 0 ;
list[0] = uexp ;
mark[uexp] = uexp ;
while ( now <= last ) {
u = list[now++] ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n checking out %d", u) ;
}
Graph_adjAndSize(bpg->graph, u, &usize, &uadj) ;
for ( ii = 0 ; ii < usize ; ii++ ) {
v = uadj[ii] ;
if ( mark[v] != uexp ) {
/*
------------------------------------
v is not yet in the alternating tree
------------------------------------
*/
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n adding v = %d to tree", v) ;
}
mark[v] = uexp ;
link[v] = u ;
if ( mate[v] == -1 ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, ", exposed") ;
}
/*
---------------------------------------------
v is exposed, flip the match edges and return
---------------------------------------------
*/
while ( v != -1 ) {
u = link[v] ;
nextv = mate[u] ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n setting %d <===> %d", v, u);
}
mate[u] = v ;
mate[v] = u ;
v = nextv ;
}
return(1) ;
} else {
/*
------------------------
put v's mate on the list
------------------------
*/
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile,
"\n adding u = %d to tree", mate[v]) ;
}
list[++last] = mate[v] ;
}
}
}
}
return(0) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
set the dmflags[] and stats[] arrays for a unit weight graph
------------------------------------------------------------
*/
static void
unitSetFlags (
BPG *bpg,
int mate[],
int dmflags[],
int stats[],
int msglvl,
FILE *msgFile
) {
int ierr, ii, last, now, nX, nY, x, xmate, xsize, y, ymate, ysize ;
int *list, *xadj, *yadj ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || mate == NULL || dmflags == NULL || stats == NULL ){
fprintf(stderr, "\n fatal error in unitSetFlags(%p,%p,%p,%p)"
"\n bad input\n", bpg, mate, dmflags, stats) ;
exit(-1) ;
}
nX = bpg->nX ;
nY = bpg->nY ;
list = IVinit(nX + nY, -1) ;
/*
--------------------------------------
zero the dmflags[] and stats[] vectors
--------------------------------------
*/
IVzero(nX + nY, dmflags) ;
IVzero(6, stats) ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n MATE") ;
IVfp80(msgFile, nX + nY, mate, 80, &ierr) ;
}
/*
-------------------------------------
load the list with exposed nodes in X
-------------------------------------
*/
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n\n exposed nodes in X") ;
}
last = -1 ;
for ( x = 0 ; x < nX ; x++ ) {
if ( mate[x] == -1 ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n loading x = %d", x) ;
}
list[++last] = x ;
dmflags[x] = 1 ;
}
}
/*
------------------------------------------------------
drop an alternating level structure from the exposed
nodes in X, and set dmflags[] for nodes in X_I and Y_E
------------------------------------------------------
*/
now = 0 ;
while ( now <= last ) {
x = list[now++] ;
Graph_adjAndSize(bpg->graph, x, &xsize, &xadj) ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n adj(%d) :", x) ;
IVfp80(msgFile, xsize, xadj, 10, &ierr) ;
fflush(msgFile) ;
}
for ( ii = 0 ; ii < xsize ; ii++ ) {
y = xadj[ii] ;
if ( dmflags[y] == 0 ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n adding y = %d", y) ;
}
dmflags[y] = 2 ;
if ( (xmate = mate[y]) == -1 ) {
fprintf(stderr, "\n fatal error in unitSetFlags"
"\n now = %d, x = %d, y = %d, mate = -1",
now, x, y) ;
fprintf(stderr, "\n adj(%d) :", x) ;
IVfp80(stderr, xsize, xadj, 10, &ierr) ;
exit(-1) ;
} else if ( dmflags[xmate] == 0 ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n adding xmate = %d", xmate) ;
}
dmflags[xmate] = 1 ;
list[++last] = xmate ;
}
}
}
}
/*
-------------------------------------
load the list with exposed nodes in Y
-------------------------------------
*/
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n\n exposed nodes in X") ;
}
last = -1 ;
for ( y = 0 ; y < nX + nY ; y++ ) {
if ( mate[y] == -1 ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n loading y = %d", y) ;
}
list[++last] = y ;
dmflags[y] = 1 ;
}
}
/*
------------------------------------------------------
drop an alternating level structure from the exposed
nodes in X, and set dmflags[] for nodes in X_I and Y_E
------------------------------------------------------
*/
now = 0 ;
while ( now <= last ) {
y = list[now++] ;
Graph_adjAndSize(bpg->graph, y, &ysize, &yadj) ;
for ( ii = 0 ; ii < ysize ; ii++ ) {
x = yadj[ii] ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n loading x = %d", x) ;
}
if ( dmflags[x] == 0 ) {
dmflags[x] = 2 ;
if ( (ymate = mate[x]) == -1 ) {
fprintf(stderr, "\n fatal error in unitSetFlags"
"\n x = %d, mate = -1", x) ;
exit(-1) ;
} else if ( dmflags[ymate] == 0 ) {
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n loading ymate = %d", ymate) ;
}
dmflags[ymate] = 1 ;
list[++last] = ymate ;
}
}
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(list) ;
/*
------------------------------
set the weights of X_R and Y_R
------------------------------
*/
stats[0] = stats[1] = stats[2] = stats[3] = stats[4] = stats[5] = 0 ;
for ( x = 0 ; x < nX ; x++ ) {
switch ( dmflags[x] ) {
case 0 : stats[2]++ ; break ;
case 1 : stats[0]++ ; break ;
case 2 : stats[1]++ ; break ;
}
}
for ( y = nX ; y < nX + nY ; y++ ) {
switch ( dmflags[y] ) {
case 0 : stats[5]++ ; break ;
case 1 : stats[3]++ ; break ;
case 2 : stats[4]++ ; break ;
}
}
return ; }
/*--------------------------------------------------------------------*/
check the input
---------------
*/
if ( bpg == NULL || dmflags == NULL || stats == NULL ) {
fprintf(stderr, "\n fatal error in unitDM(%p,%p,%p)"
"\n bad input\n", bpg, dmflags, stats) ;
exit(-1) ;
}
nX = bpg->nX ;
nY = bpg->nY ;
mate = IVinit(nX + nY, -1) ;
if ( msglvl > 1 && msgFile != NULL ) {
BPG_writeForHumanEye(bpg, msgFile) ;
}
/*
-----------------------
find a maximum matching
-----------------------
*/
unitFindMaxMBPG/src/IO.c 0100644 0002055 0007177 00000033271 06534106126 0013754 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../BPG.h"
static const char *suffixb = ".bpgb" ;
static const char *suffixf = ".bpgf" ;
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
purpose -- to read in a BPG object from a file
input --
fn -- filename, must be *.bpgb or *.bpgf
return value -- 1 if success, 0 if failure
created -- 95oct06, cca
----------------------------------------------
*/
int
BPG_readFromFile (
BPG *bpg,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || fn == NULL ) {
fprintf(stderr, "\n error in BPG_readFromFile(%p,%s)"
"\n bad input\n", bpg, fn) ;
return(0) ;
}
/*
-------------
read the file
-------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "rb")) == NULL ) {
fprintf(stderr, "\n error in BPG_readFromFile(%p,%s)"
"\n unable to open file %s", bpg, fn, fn) ;
rc = 0 ;
} else {
rc = BPG_readFromBinaryFile(bpg, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "r")) == NULL ) {
fprintf(stderr, "\n error in BPG_readFromFile(%p,%s)"
"\n unable to open file %s", bpg, fn, fn) ;
rc = 0 ;
} else {
rc = BPG_readFromFormattedFile(bpg, fp) ;
fclose(fp) ;
}
} else {
fprintf(stderr, "\n error in BPG_readFromFile(%p,%s)"
"\n bad BPG file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
bpg, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
} else {
fprintf(stderr, "\n error in BPG_readFromFile(%p,%s)"
"\n bad BPG file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
bpg, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- to read a BPG object from a formatted file
return value -- 1 if success, 0 if failure
created -- 95oct06, cca
--------------------------------------------------------
*/
int
BPG_readFromFormattedFile (
BPG *bpg,
FILE *fp
) {
Graph *graph ;
int nX, nY, rc ;
int itemp[2] ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || fp == NULL ) {
fprintf(stderr, "\n error in BPG_readFromFormattedFile(%p,%p)"
"\n bad input\n", bpg, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
BPG_clearData(bpg) ;
/*
-----------------
read in nX and nY
-----------------
*/
if ( (rc = IVfscanf(fp, 2, itemp)) != 2 ) {
fprintf(stderr, "\n error in BPG_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", bpg, fp, rc, 2) ;
return(0) ;
}
nX = itemp[0] ;
nY = itemp[1] ;
/*
--------------------------------------------------
create the Graph IVL object, then read in its data
--------------------------------------------------
*/
graph = Graph_new() ;
Graph_setDefaultFields(graph) ;
rc = Graph_readFromFormattedFile(graph, fp) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in BPG_readFromFormattedFile(%p,%p)"
"\n trying to read in Graph"
"\n return code %d from Graph_readFormattedFile(%p,%p)",
bpg, fp, rc, graph, fp) ;
return(0) ;
}
/*
---------------------
initialize the object
---------------------
*/
BPG_init(bpg, nX, nY, graph) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
purpose -- to read a BPG object from a binary file
return value -- 1 if success, 0 if failure
created -- 95oct06, cca
----------------------------------------------------
*/
int
BPG_readFromBinaryFile (
BPG *bpg,
FILE *fp
) {
Graph *graph ;
int nX, nY, rc ;
int itemp[2] ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in BPG_readFromBinaryFile(%p,%p)"
"\n bad input\n", bpg, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
BPG_clearData(bpg) ;
/*
--------------------------------------------
read in the two scalar parameters, nX and nY
--------------------------------------------
*/
if ( (rc = fread((void *) itemp, sizeof(int), 2, fp)) != 2 ) {
fprintf(stderr, "\n error in BPG_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", bpg, fp, rc, 2) ;
return(0) ;
}
nX = itemp[0] ;
nY = itemp[1] ;
/*
----------------------------------------------
create the Grapg object, then read in its data
----------------------------------------------
*/
graph = Graph_new() ;
Graph_setDefaultFields(graph) ;
rc = Graph_readFromBinaryFile(graph, fp) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in BPG_readFromBinaryFile(%p,%p)"
"\n trying to read in Graph"
"\n return code %d from Graph_readBinaryFile(%p,%p)",
bpg, fp, rc, graph, fp) ;
return(0) ;
}
/*
---------------------
initialize the object
---------------------
*/
BPG_init(bpg, nX, nY, graph) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
purpose -- to write a BPG object to a file
input --
fn -- filename
*.bpgb -- binary
*.bpgf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 95oct06, cca
--------------------------------------------
*/
int
BPG_writeToFile (
BPG *bpg,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || fn == NULL ) {
fprintf(stderr, "\n fatal error in BPG_writeToFile(%p,%s)"
"\n bad input\n", bpg, fn) ;
return(0) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in BPG_writeToFile(%p,%s)"
"\n unable to open file %s", bpg, fn, fn) ;
rc = 0 ;
} else {
rc = BPG_writeToBinaryFile(bpg, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "w")) == NULL ) {
fprintf(stderr, "\n error in BPG_writeToFile(%p,%s)"
"\n unable to open file %s", bpg, fn, fn) ;
rc = 0 ;
} else {
rc = BPG_writeToFormattedFile(bpg, fp) ;
fclose(fp) ;
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in BPG_writeToFile(%p,%s)"
"\n unable to open file %s", bpg, fn, fn) ;
rc = 0 ;
} else {
rc = BPG_writeForHumanEye(bpg, fp) ;
fclose(fp) ;
}
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in BPG_writeToFile(%p,%s)"
"\n unable to open file %s", bpg, fn, fn) ;
rc = 0 ;
} else {
rc = BPG_writeForHumanEye(bpg, fp) ;
fclose(fp) ;
}
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- to write a BPG object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 95oct06, cca
------------------------------------------------------
*/
int
BPG_writeToFormattedFile (
BPG *bpg,
FILE *fp
) {
int ierr, rc ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in BPG_writeToFormattedFile(%p,%p)"
"\n bad input\n", bpg, fp) ;
return(0) ;
}
/*
-----------------------------------
write out the two scalar parameters
-----------------------------------
*/
rc = fprintf(fp, "\n %d %d", bpg->nX, bpg->nY) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in BPG_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from first fprintf\n", bpg, fp, rc) ;
return(0) ;
}
/*
-------------------
write out the graph
-------------------
*/
rc = Graph_writeToFormattedFile(bpg->graph, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in BPG_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from Graph_writeToFormattedFile(%p,%p)"
"\n while attempting to write out graph\n",
bpg, fp, rc, bpg->graph, fp) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
purpose -- to write a BPG object to a binary file
return value -- 1 if success, 0 otherwise
created -- 95oct06, cca
---------------------------------------------------
*/
int
BPG_writeToBinaryFile (
BPG *bpg,
FILE *fp
) {
int rc ;
int itemp[6] ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in BPG_writeToBinaryFile(%p,%p)"
"\n bad input\n", bpg, fp) ;
return(0) ;
}
/*
-----------------------------------
write out the two scalar parameters
-----------------------------------
*/
itemp[0] = bpg->nX ;
itemp[1] = bpg->nY ;
rc = fwrite((void *) itemp, sizeof(int), 6, fp) ;
if ( rc != 6 ) {
fprintf(stderr, "\n error in BPG_writeToBinaryFile(%p,%p)"
"\n %d of %d scalar items written\n", bpg, fp, rc, 6) ;
return(0) ;
}
/*
-------------------
write out the graph
-------------------
*/
rc = Graph_writeToBinaryFile(bpg->graph, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in BPG_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from Graph_writeToBinaryFile(%p,%p)"
"\n while attempting to write out graph\n",
bpg, fp, rc, bpg->graph, fp) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to write a BPG object for a human eye
return value -- 1 if success, 0 otherwise
created -- 95oct06, cca
-------------------------------------------------
*/
int
BPG_writeForHumanEye (
BPG *bpg,
FILE *fp
) {
int ierr, rc ;
if ( bpg == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in BPG_writeForHumanEye(%p,%p)"
"\n bad input\n", bpg, fp) ;
exit(-1) ;
}
/*
------------------------
write out the statistics
------------------------
*/
if ( (rc = BPG_writeStats(bpg, fp)) == 0 ) {
fprintf(stderr, "\n fatal error in BPG_writeForHumanEye(%p,%p)"
"\n rc = %d, return from BPG_writeStats(%p,%p)\n",
bpg, fp, rc, bpg, fp) ;
return(0) ;
}
fflush(fp) ;
if ( bpg->graph != NULL ) {
/*
--------------------------
write out the Graph object
--------------------------
*/
fprintf(fp, "\n\n Graph object") ;
rc = Graph_writeForHumanEye(bpg->graph, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in BPG_writeForHumanEye(%p,%p)"
"\n rc = %d, return from Graph_writeForHumanEye(%p,%p)"
"\n while attempting to write out graph\n",
bpg, fp, rc, bpg->graph, fp) ;
return(0) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- to write out the statistics for the BPG object
return value -- 1 if success, 0 otherwise
created -- 95oct06, cca
-----------------------------------------------------------
*/
int
BPG_writeStats (
BPG *bpg,
FILE *fp
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || fp == NULL ) {
fprintf(stderr, "\n error in BPG_writeStats(%p,%p)"
"\n bad input\n", bpg, fp) ;
exit(-1) ;
}
if ( bpg->graph == NULL ) {
fprintf(stderr, "\n warning in BPG_writeStats(%p,%p)"
"\n bpg->graph = NULL\n", bpg, fp) ;
return(1) ;
}
switch ( bpg->graph->type ) {
case 0 :
rc = fprintf(fp, "\n BPG : unweighted bpg object :") ;
break ;
case 1 :
rc = fprintf(fp, "\n BPG : vertices weighted bpg object :") ;
break ;
case 2 :
rc = fprintf(fp, "\n BPG : edges weighted bpg object :") ;
break ;
case 3 :
rc = fprintf(fp,
"\n BPG : vertices and edges weighted bpg object :") ;
break ;
default :
fprintf(stderr, "\n fatal error in BPG_writeStats(%p,%p)"
"\n invalid bpg->g->type = %d\n",
bpg, fp, bpg->graph->type) ;
return(0) ;
}
if ( rc < 0 ) { goto IO_error ; }
fflush(fp) ;
rc = fprintf(fp, " nX = %d, nY = %d", bpg->nX, bpg->nY) ;
if ( rc < 0 ) { goto IO_error ; }
fflush(fp) ;
if ( bpg->graph != NULL ) {
if ( bpg->graph->vwghts != NULL ) {
rc = fprintf(fp, ", |X| = %d, |Y| = %d",
IVsum(bpg->nX, bpg->graph->vwghts),
IVsum(bpg->nY, bpg->graph->vwghts + bpg->nX)) ;
} else {
rc = fprintf(fp, ", |X| = %d, |Y| = %d", bpg->nX, bpg->nY) ;
}
}
if ( rc < 0 ) { goto IO_error ; }
fflush(fp) ;
return(1) ;
IO_error :
fprintf(stderr, "\n fatal error in BPG_writeStats(%p,%p)"
"\n rc = %d, return from fprintf\n", bpg, fp, rc) ;
return(0) ;
}
/*--------------------------------------------------------------------*/
-
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in BPG_writeToFile(%p,%s)"
"\n unable to BPG/src/basics.c 0100644 0002055 0007177 00000005317 06542213215 0014706 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../BPG.h"
#define MYTRACE 0
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
purpose -- create and return a new BPG object
created -- 95oct06, cca
-----------------------------------------------
*/
BPG *
BPG_new (
void
) {
BPG *bpg ;
#if MYTRACE > 0
fprintf(stdout, "\n just inside BPG_new()") ;
fflush(stdout) ;
#endif
ALLOCATE(bpg, struct _BPG, 1) ;
BPG_setDefaultFields(bpg) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving BPG_new()") ;
fflush(stdout) ;
#endif
return(bpg) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- set the default fields for the BPG object
created -- 95oct06, cca
------------------------------------------------------
*/
void
BPG_setDefaultFields (
BPG *bpg
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside BPG_setDefaultFields(%)", bpg) ;
fflush(stdout) ;
#endif
if ( bpg == NULL ) {
fprintf(stderr, "\n fatal error in BPG_setDefaultFields(%p)"
"\n bipartite graph is NULL\n", bpg) ;
exit(-1) ;
}
bpg->nX = 0 ;
bpg->nY = 0 ;
bpg->graph = NULL ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving BPG_setDefaultFields(%)", bpg) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------
purpose -- clear the data fields
created -- 95oct06, cca
--------------------------------
*/
void
BPG_clearData (
BPG *bpg
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside BPG_clearData(%)", bpg) ;
fflush(stdout) ;
#endif
if ( bpg == NULL ) {
fprintf(stderr, "\n fatal error in BPG_clearData(%p)"
"\n bipartite graph is NULL\n", bpg) ;
exit(-1) ;
}
if ( bpg->graph != NULL ) {
Graph_free(bpg->graph) ;
}
BPG_setDefaultFields(bpg) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving BPG_clearData(%)", bpg) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------
purpose -- free the BPG object
created -- 95oct06, cca
--------------------------------
*/
void
BPG_free (
BPG *bpg
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside BPG_free(%)", bpg) ;
fflush(stdout) ;
#endif
if ( bpg == NULL ) {
fprintf(stderr, "\n fatal error in BPG_free(%p)"
"\n bipartite graph is NULL\n", bpg) ;
exit(-1) ;
}
BPG_clearData(bpg) ;
FREE(bpg) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving BPG_free(%)", bpg) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
BPG/src/init.c 0100644 0002055 0007177 00000022360 06534106126 0014405 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../BPG.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
initialize a BPG object, set bpg->nX = nX, bpg->nY = nY,
and bpg->g = g. convert g into bipartite form, i.e.,
adj(v) := adj(v) \cap {nX, ..., nX + nY - 1} for v in [0, nX)
adj(v) := adj(v) \cap {0, ..., nX - 1} for v in [nX, nX+nY)
created -- 95oct06, cca
--------------------------------------------------------------------
*/
void
BPG_init (
BPG *bpg,
int nX,
int nY,
Graph *graph
) {
int ierr, ii, jj, v, vsize, w ;
int *vadj ;
IVL *adjIVL ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || nX <= 0 || nY <= 0 || graph == NULL ) {
fprintf(stderr, "\n fatal error in BPG_init(%p,%d,%d,%p)"
"\n bad input\n", bpg, nX, nY, graph) ;
exit(-1) ;
}
/*
--------------
set the fields
--------------
*/
BPG_clearData(bpg) ;
bpg->nX = nX ;
bpg->nY = nY ;
bpg->graph = graph ;
/*
------------------------------------
work on the graph's adjacency lists,
enforcing the bipartite property
------------------------------------
*/
adjIVL = graph->adjIVL ;
for ( v = 0 ; v < nX ; v++ ) {
IVL_listAndSize(adjIVL, v, &vsize, &vadj) ;
#if MYDEBUG > 0
fprintf(stdout, "\n old %d : ", v) ;
IVfp80(stdout, vsize, vadj, 10, &ierr) ;
fflush(stdout) ;
#endif
ii = 0, jj = vsize - 1 ;
while ( ii <= jj ) {
w = vadj[ii] ;
if ( nX <= w && w < nX + nY ) {
ii++ ;
} else {
vadj[ii] = vadj[jj] ;
vadj[jj] = w ;
jj-- ;
}
}
vsize = ii ;
#if MYDEBUG > 0
fprintf(stdout, "\n new %d : ", v) ;
IVfp80(stdout, vsize, vadj, 10, &ierr) ;
fflush(stdout) ;
#endif
IVL_setList(adjIVL, v, vsize, NULL) ;
}
for ( v = nX ; v < nX + nY ; v++ ) {
IVL_listAndSize(adjIVL, v, &vsize, &vadj) ;
#if MYDEBUG > 0
fprintf(stdout, "\n old %d : ", v) ;
IVfp80(stdout, vsize, vadj, 10, &ierr) ;
fflush(stdout) ;
#endif
ii = 0, jj = vsize - 1 ;
while ( ii <= jj ) {
w = vadj[ii] ;
if ( 0 <= w && w < nX ) {
ii++ ;
} else {
vadj[ii] = vadj[jj] ;
vadj[jj] = w ;
jj-- ;
}
}
vsize = ii ;
IVL_setList(adjIVL, v, vsize, NULL) ;
#if MYDEBUG > 0
fprintf(stdout, "\n new %d : ", v) ;
IVfp80(stdout, vsize, vadj, 10, &ierr) ;
fflush(stdout) ;
#endif
}
return ; }
/*--------------------------------------------------------------------*/
#define MYDEBUG 0
/*
-----------------------------------------------------------
initialize from a graph given a color vector and two target
vectors. this method can be used to get the bipartite graph
of the boundary of two components.
graph -- graph from which to extract the bipartite graph
colors -- vector of colors for the vertices
cX -- color for the X vertices
cY -- color for the Y vertices
cmap -- map from vertices in g to vertices in bpg
indX -- vector to hold the global indices in X
indY -- vector to hold the global indices in Y
created -- 95oct06, cca
-----------------------------------------------------------
*/
void
BPG_initFromColoring (
BPG *bpg,
Graph *graph,
int colors[],
int cX,
int cY,
int cmap[],
int indX[],
int indY[]
) {
Graph *bpg_g ;
int count, ierr, ii, iX, iy, msize, nV, nX, nY, v, vsize, w, x, y ;
int *ewghts, *list, *vadj, *vewghts ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || graph == NULL || colors == NULL
|| cX < 0 || cY < 0 || cX == cY || cmap == NULL ) {
fprintf(stderr,
"\n fatal error in BPG_initFromColoring(%p,%p,%p,%d,%d,%p)"
"\n bad input\n", bpg, graph, colors, cX, cY, cmap) ;
exit(-1) ;
}
BPG_clearData(bpg) ;
nV = graph->nvtx ;
IVfill(nV, cmap, -1) ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n just inside BPG_initFromColoring(%p,%p,%p,%d,%d,%p)",
bpg, graph, colors, cX, cY, cmap) ;
fflush(stdout) ;
#endif
/*
------------------
get the X vertices
------------------
*/
for ( v = 0, nX = 0 ; v < nV ; v++ ) {
if ( colors[v] == cX ) {
indX[nX] = v ;
cmap[v] = nX++ ;
}
}
/*
----------------------------------------------------
now get Y = {v | v \in \bnd{X} and colors[v] == cY }
----------------------------------------------------
*/
nY = 0 ;
for ( iX = 0 ; iX < nX ; iX++ ) {
v = indX[iX] ;
Graph_adjAndSize(graph, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
if ( (w = vadj[ii]) < nV
&& colors[w] == cY && cmap[w] == -1 ) {
indY[nY] = w ;
cmap[w] = nX + nY++ ;
}
}
}
bpg->nX = nX ;
bpg->nY = nY ;
#if MYDEBUG > 0
fprintf(stdout, "\n indX(%d) :", nX) ;
IVfp80(stdout, nX, indX, 15, &ierr) ;
fprintf(stdout, "\n indY(%d) :", nY) ;
IVfp80(stdout, nY, indY, 15, &ierr) ;
fflush(stdout) ;
#endif
#if MYDEBUG > 1
fprintf(stdout, "\n cmap(%d) :", g->nvtx) ;
IVfp80(stdout, graph->nvtx, cmap, 15, &ierr) ;
fflush(stdout) ;
#endif
if ( bpg->nX == 0 || bpg->nY == 0 ) {
fprintf(stderr, "\n fatal error in BPG_initFromColoring"
"\n nX = %d, nY = %d", nX, nY) ;
fprintf(stderr, "\n colors") ;
IVfp80(stderr, nV, colors, 80, &ierr) ;
fprintf(stderr, "\n graph") ;
Graph_writeForHumanEye(graph, stderr) ;
exit(-1) ;
}
/*
--------------------------------------
initialize the bipartite graph's graph
--------------------------------------
*/
bpg->graph = bpg_g = Graph_new() ;
Graph_init1(bpg_g, graph->type,
nX + nY, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ;
/*
-------------------------------------
set the vertex weights if appropriate
-------------------------------------
*/
if ( graph->type % 2 == 1 ) {
for ( x = 0 ; x < nX ; x++ ) {
v = indX[x] ;
bpg_g->vwghts[x] = graph->vwghts[v] ;
}
for ( iy = 0, y = nX ; iy < nY ; iy++, y++ ) {
v = indY[iy] ;
bpg_g->vwghts[y] = graph->vwghts[v] ;
}
bpg_g->totvwght = IVsum(nX + nY, bpg_g->vwghts) ;
#if MYDEBUG > 0
fprintf(stdout, "\n vertex weights for X") ;
IVfp80(stdout, nX, bpg_g->vwghts, 80, &ierr) ;
fprintf(stdout, "\n vertex weights for Y") ;
IVfp80(stdout, nY, bpg_g->vwghts + nX, 80, &ierr) ;
fprintf(stdout, "\n w(X) = %d", IVsum(nX, bpg_g->vwghts)) ;
fprintf(stdout, "\n w(Y) = %d", IVsum(nY, bpg_g->vwghts + nX)) ;
fflush(stdout) ;
#endif
}
/*
-----------------------------------------------
set the adjacency or adjacency and edge weights
-----------------------------------------------
*/
if ( graph->type < 2 ) {
/*
-------------------------------
adjacency only, no edge weights
-------------------------------
*/
msize = IVL_maxListSize(graph->adjIVL) ;
list = IVinit2(msize) ;
for ( x = 0 ; x < nX ; x++ ) {
v = indX[x] ;
Graph_adjAndSize(graph, v, &vsize, &vadj) ;
for ( ii = 0, count = 0 ; ii < vsize ; ii++ ) {
if ( (w = vadj[ii]) < nV && colors[w] == cY ) {
list[count++] = cmap[w] ;
}
}
IVqsortUp(count, list) ;
IVL_setList(bpg_g->adjIVL, x, count, list) ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting x (%d) list %d : ", x, indX[x]) ;
IVfp80(stdout, count, list, 20, &ierr) ;
fflush(stdout) ;
#endif
}
for ( iy = 0, y = nX ; iy < nY ; iy++, y++ ) {
v = indY[iy] ;
Graph_adjAndSize(graph, v, &vsize, &vadj) ;
for ( ii = 0, count = 0 ; ii < vsize ; ii++ ) {
if ( (w = vadj[ii]) < nV && colors[w] == cX ) {
list[count++] = cmap[w] ;
}
}
IVqsortUp(count, list) ;
IVL_setList(bpg_g->adjIVL, y, count, list) ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting y (%d) list %d : ", y, indY[iy]) ;
IVfp80(stdout, count, list, 20, &ierr) ;
fflush(stdout) ;
#endif
}
IVfree(list) ;
} else {
/*
--------------------------
adjacency and edge weights
--------------------------
*/
msize = IVL_maxListSize(graph->adjIVL) ;
list = IVinit2(msize) ;
ewghts = IVinit2(msize) ;
for ( x = 0 ; x < nX ; x++ ) {
v = indX[x] ;
Graph_adjAndEweights(graph, v, &vsize, &vadj, &vewghts) ;
for ( ii = 0, count = 0 ; ii < vsize ; ii++ ) {
if ( (w = vadj[ii]) < nV && colors[w] == cY ) {
list[count] = cmap[w] ;
ewghts[count] = vewghts[ii] ;
count++ ;
}
}
IV2qsortUp(count, list, ewghts) ;
IVL_setList(bpg_g->adjIVL, x, count, list) ;
IVL_setList(bpg_g->ewghtIVL, x, count, ewghts) ;
}
for ( iy = 0, y = nX ; iy < nY ; iy++, y++ ) {
v = indY[iy] ;
Graph_adjAndEweights(graph, v, &vsize, &vadj, &vewghts) ;
for ( ii = 0, count = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( colors[w] == cX ) {
list[count] = cmap[w] ;
ewghts[count] = vewghts[ii] ;
count++ ;
}
}
IV2qsortUp(count, list, ewghts) ;
IVL_setList(bpg_g->adjIVL, y, count, list) ;
IVL_setList(bpg_g->ewghtIVL, y, count, ewghts) ;
}
IVfree(list) ;
IVfree(ewghts) ;
}
bpg_g->nedges = IVsum(nX + nY, graph->adjIVL->sizes) ;
return ; }
/*--------------------------------------------------------------------*/
BPG/src/makeGraphs.c 0100644 0002055 0007177 00000010077 06534106126 0015526 0 ustar 00cleve compmath 0000040 0000006 /* makeGraphXbyX.c */
#include "../BPG.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- return the X by X graph where (x1,x2) is an edge
if there exists a y in Y such that (x1,y) and
(x2,y) are edges in the bipartite graph.
created -- 95dec06, cca
to be used in the BKL object.
-----------------------------------------------------------
*/
Graph *
BPG_makeGraphXbyX (
BPG *bpg
) {
Graph *graph, *gXbyX ;
int count, ii, jj, nX, x, xsize, y, ysize, z ;
int *list, *mark, *xadj, *yadj ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL ) {
fprintf(stdout, "\n fatal error in BPG_makeGraphXbyX(%p)"
"\n bad input\n", bpg) ;
exit(-1) ;
}
/*
----------------------
check for quick return
----------------------
*/
if ( (graph = bpg->graph) == NULL || (nX = bpg->nX) <= 0 ) {
return(NULL) ;
}
/*
--------------------
initialize the graph
--------------------
*/
gXbyX = Graph_new() ;
Graph_init1(gXbyX, graph->type, nX, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ;
/*
--------------
fill the graph
--------------
*/
mark = IVinit(nX, -1) ;
list = IVinit(nX, -1) ;
for ( x = 0 ; x < nX ; x++ ) {
Graph_adjAndSize(graph, x, &xsize, &xadj) ;
mark[x] = x ;
for ( ii = 0, count = 0 ; ii < xsize ; ii++ ) {
y = xadj[ii] ;
Graph_adjAndSize(graph, y, &ysize, &yadj) ;
for ( jj = 0 ; jj < ysize ; jj++ ) {
z = yadj[jj] ;
if ( mark[z] != x ) {
mark[z] = x ;
list[count++] = z ;
}
}
}
if ( count > 0 ) {
IVqsortUp(count, list) ;
IVL_setList(gXbyX->adjIVL, x, count, list) ;
}
}
IVfree(list) ;
IVfree(mark) ;
/*
---------------------------------------
set vertex weight vector if appropriate
---------------------------------------
*/
if ( graph->type % 2 == 1 ) {
IVcopy(nX, gXbyX->vwghts, graph->vwghts) ;
}
return(gXbyX) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- return the Y by Y graph where (y1,y2) is an edge
if there exists a x in X such that (x,y1) and
(x,y2) are edges in the bipartite graph.
created -- 95dec07, cca
-----------------------------------------------------------
*/
Graph *
BPG_makeGraphYbyY (
BPG *bpg
) {
Graph *graph, *gYbyY ;
int count, ii, jj, nX, nY, x, xsize, y, ysize, z ;
int *list, *mark, *xadj, *yadj ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL ) {
fprintf(stdout, "\n fatal error in BPG_makeGraphXbyX(%p)"
"\n bad input\n", bpg) ;
exit(-1) ;
}
/*
----------------------
check for quick return
----------------------
*/
if ( (graph = bpg->graph) == NULL || (nY = bpg->nY) <= 0 ) {
return(NULL) ;
}
nX = bpg->nX ;
/*
--------------------
initialize the graph
--------------------
*/
gYbyY = Graph_new() ;
Graph_init1(gYbyY, graph->type, nY, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ;
/*
--------------
fill the graph
--------------
*/
mark = IVinit(nY, -1) ;
list = IVinit(nY, -1) ;
for ( y = 0 ; y < nY ; y++ ) {
Graph_adjAndSize(graph, nX + y, &ysize, &yadj) ;
mark[y] = y ;
for ( ii = 0, count = 0 ; ii < ysize ; ii++ ) {
x = yadj[ii] ;
Graph_adjAndSize(graph, x, &xsize, &xadj) ;
for ( jj = 0 ; jj < xsize ; jj++ ) {
z = xadj[jj] ;
if ( mark[z] != y ) {
mark[z] = y ;
list[count++] = z ;
}
}
}
if ( count > 0 ) {
IVqsortUp(count, list) ;
IVL_setList(gYbyY->adjIVL, nX + y, count, list) ;
}
}
IVfree(list) ;
IVfree(mark) ;
/*
---------------------------------------
set vertex weight vector if appropriate
---------------------------------------
*/
if ( graph->type % 2 == 1 ) {
IVcopy(nY, gYbyY->vwghts, graph->vwghts + nX) ;
}
return(gYbyY) ; }
/*--------------------------------------------------------------------*/
BPG/src/maxFlow.c 0100644 0002055 0007177 00000050771 06534106126 0015066 0 ustar 00cleve compmath 0000040 0000006 /* maxFlow.c */
#include "../BPG.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------
a Cell structure represent an edge (x,y)
rxy -- residual for edge
fxy -- flow for edge
xnext -- next Cell in list for x
ynext -- next Cell in list for y
----------------------------------------
*/
typedef struct _Cell Cell ;
struct _Cell {
int x ;
int y ;
int rxy ;
int fxy ;
Cell *xnext ;
Cell *ynext ;
} ;
/*--------------------------------------------------------------------*/
/*
-----------------
static prototypes
-----------------
*/
static void
setupCells(BPG *bpg, Cell ***pheads, Cell **pcells,
int msglvl, FILE *msgFile) ;
static int
findFlowAugmentingPath(BPG *bpg, Cell *heads[], int xexp, int exp[],
int par[], int labels[], int list[], int mark[],
int tag, int msglvl, FILE *msgFile) ;
static void
augmentPath(BPG *bpg, int xexp, int yexp, int nvexp[], Cell *heads[],
int labels[], int par[], int msglvl, FILE *msgFile) ;
static void
setDMflags(BPG *bpg, Cell *heads[], int nvexp[], int list[], int mark[],
int dmflags[], int stats[], int msglvl, FILE *msgFile) ;
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
find the DM decomposition of a weighted bipartite graph
using a simple max flow algorithm
bpg -- BPG bipartite graph object
dmflags -- flags vector
/ 0 if x in X_R
dmflags[x] = | 1 if x in X_I
\ 2 if x in X_E
/ 0 if y in Y_R
dmflags[y] = | 1 if y in Y_I
\ 2 if y in Y_E
stats -- statistics vector
stats[0] -- weight of X_I
stats[1] -- weight of X_E
stats[2] -- weight of X_R
stats[3] -- weight of Y_I
stats[4] -- weight of Y_E
stats[5] -- weight of Y_R
created -- 96mar08, cca
-------------------------------------------------------
*/
void
BPG_DMviaMaxFlow (
BPG *bpg,
int dmflags[],
int stats[],
int msglvl,
FILE *msgFile
) {
int ierr, nX, nY, tag, x, xexp, y, yexp ;
int *labels, *list, *mark, *nvexp, *par, *vwghts ;
Cell *cell, *cells ;
Cell **heads ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || dmflags == NULL || stats == NULL
|| (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr, "\n fatal error in BPG_DMviaMaxFlow(%p,%p,%p,%d,%p)"
"\n bad input\n", bpg, dmflags, stats, msglvl, msgFile) ;
exit(-1) ;
}
nX = bpg->nX ;
nY = bpg->nY ;
/*
---------------------------------------------
set up the Cell structures and working arrays
---------------------------------------------
*/
setupCells(bpg, &heads, &cells, msglvl, msgFile) ;
nvexp = IVinit(nX + nY, 1) ;
if ( (vwghts = bpg->graph->vwghts) != NULL ) {
IVcopy(nX + nY, nvexp, vwghts) ;
}
list = IVinit(nX + nY, -1) ;
mark = IVinit(nX + nY, -1) ;
par = IVinit(nX + nY, -1) ;
labels = IVinit(nX + nY, -1) ;
/*
------------------------
loop over the x vertices
------------------------
*/
tag = 0 ;
for ( xexp = 0 ; xexp < nX ; xexp++ ) {
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n checking out x node %d, exposure %d",
xexp, nvexp[xexp]) ;
}
while ( nvexp[xexp] > 0 ) {
yexp = findFlowAugmentingPath(bpg, heads, xexp, nvexp,
par, labels, list, mark, tag,
msglvl, msgFile) ;
tag++ ;
if ( yexp == -1 ) {
/*
-------------------------------------------------------
no flow augmenting path has been found, node is exposed
-------------------------------------------------------
*/
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n node %d has exposure %d",
xexp, nvexp[xexp]) ;
}
break ;
} else {
/*
----------------------------------------
flow augmenting path found, augment path
----------------------------------------
*/
augmentPath(bpg, xexp, yexp, nvexp, heads, labels, par,
msglvl, msgFile) ;
}
}
}
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n after maximum flow found") ;
for ( x = 0 ; x < nX ; x++ ) {
fprintf(msgFile, "\n X node %d : ", x) ;
for ( cell = heads[x] ; cell != NULL ; cell = cell->xnext ) {
fprintf(msgFile, "\n (%3d,%3d,%3d)",
cell->y, cell->fxy, cell->rxy) ;
}
}
for ( y = nX ; y < nX + nY ; y++ ) {
fprintf(msgFile, "\n Y node %d : ", y) ;
for ( cell = heads[y] ; cell != NULL ; cell = cell->ynext ) {
fprintf(msgFile, "\n (%3d,%3d,%3d)",
cell->x, cell->fxy, cell->rxy) ;
}
}
}
/*
----------------
set the DM flags
----------------
*/
setDMflags(bpg, heads, nvexp, list, mark,
dmflags, stats, msglvl, msgFile) ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n X dmflags: ") ;
IVfp80(msgFile, nX, dmflags, 12, &ierr) ;
fprintf(msgFile, "\n Y dmflags: ") ;
IVfp80(msgFile, nY, dmflags + nX, 12, &ierr) ;
fflush(msgFile) ;
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(nvexp) ;
IVfree(list) ;
IVfree(mark) ;
IVfree(par) ;
IVfree(labels) ;
FREE(heads) ;
FREE(cells) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------
set up cells
------------
*/
static void
setupCells (
BPG *bpg,
Cell ***pheads,
Cell **pcells,
int msglvl,
FILE *msgFile
) {
Cell *cell, *cells ;
Cell **heads ;
Graph *graph ;
int ii, ncell, nX, nY, x, xsize, y ;
int *vwghts, *xadj ;
/*
-------------------------
count the number of cells
-------------------------
*/
nX = bpg->nX ;
nY = bpg->nY ;
graph = bpg->graph ;
ncell = 0 ;
for ( x = 0 ; x < nX ; x++ ) {
Graph_adjAndSize(graph, x, &xsize, &xadj) ;
ncell += xsize ;
}
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n %d cells required", ncell) ;
fflush(msgFile) ;
}
/*
------------------------------------------------
allocate the storage and set pointers for return
------------------------------------------------
*/
ALLOCATE(cells, struct _Cell, ncell) ;
ALLOCATE(heads, struct _Cell *, nX + nY) ;
*pcells = cells ;
*pheads = heads ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n cells = %p", cells) ;
fflush(msgFile) ;
}
for ( ii = 0 ; ii < nX + nY ; ii++ ) {
heads[ii] = NULL ;
}
/*
----------------------------------
set the vertex fields of the cells
----------------------------------
*/
for ( x = 0, cell = cells ; x < nX ; x++ ) {
Graph_adjAndSize(graph, x, &xsize, &xadj) ;
for ( ii = 0 ; ii < xsize ; ii++, cell++ ) {
y = xadj[ii] ;
cell->x = x ;
cell->y = y ;
}
}
/*
--------------------------------
set the link fields of the cells
--------------------------------
*/
for ( ii = 0, cell = cells ; ii < ncell ; ii++, cell++ ) {
x = cell->x ;
cell->xnext = heads[x] ;
heads[x] = cell ;
y = cell->y ;
cell->ynext = heads[y] ;
heads[y] = cell ;
}
/*
---------------------------------------------
set the residual and flow fields of the cells
---------------------------------------------
*/
if ( (vwghts = graph->vwghts) == NULL ) {
for ( ii = 0, cell = cells ; ii < ncell ; ii++, cell++ ) {
cell->rxy = 1 ;
cell->fxy = 0 ;
}
} else {
for ( ii = 0, cell = cells ; ii < ncell ; ii++, cell++ ) {
x = cell->x ;
y = cell->y ;
cell->rxy = (vwghts[x] < vwghts[y]) ? vwghts[x] : vwghts[y] ;
cell->fxy = 0 ;
}
}
if ( msglvl > 2 && msgFile != NULL ) {
for ( ii = 0, cell = cells ; ii < ncell ; ii++, cell++ ) {
fprintf(msgFile,
"\n cell %d, address %p : (x,y) = (%3d,%3d), r = %d, f = %d",
ii, cell, cell->x, cell->y, cell->rxy, cell->fxy) ;
}
fflush(msgFile) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
search for a flow augmenting path starting at xexp
created -- 96mar08, cca
--------------------------------------------------
*/
static int
findFlowAugmentingPath (
BPG *bpg,
Cell *heads[],
int xexp,
int exp[],
int par[],
int labels[],
int list[],
int mark[],
int tag,
int msglvl,
FILE *msgFile
) {
Cell *cell ;
Graph *graph ;
int last, now, nX, x, y ;
/*
---------------------------
get dimensions and pointers
---------------------------
*/
nX = bpg->nX ;
graph = bpg->graph ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n FIND AUGMENTING PATH FOR NODE %d", xexp) ;
fflush(msgFile) ;
}
/*
-----------------------------------
mark the exposed node with the tag,
label with its exposure,
and put into the list for traversal
-----------------------------------
*/
mark[xexp] = tag ;
list[0] = xexp ;
labels[xexp] = exp[xexp] ;
par[xexp] = -1 ;
now = last = 0 ;
while ( now <= last ) {
/*
-------------------------------
check out next node on the list
-------------------------------
*/
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n list[%d] = %d", now, list[now]) ;
fflush(msgFile) ;
}
if ( list[now] < nX ) {
x = list[now++] ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, ", X node %d", x) ;
fflush(msgFile) ;
}
for ( cell = heads[x] ; cell != NULL ; cell = cell->xnext ) {
y = cell->y ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n adjacent Y node %d, mark %d, r %d",
y, mark[y], cell->rxy) ;
fflush(msgFile) ;
}
if ( mark[y] != tag && cell->rxy > 0 ) {
/*
----------------------------------------------------------
y has not yet been visited and edge (x,y) is not saturated
----------------------------------------------------------
*/
mark[y] = tag ;
par[y] = x ;
if ( labels[x] < cell->rxy ) {
labels[y] = labels[x] ;
} else {
labels[y] = cell->rxy ;
}
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, ", label = %d", labels[y]) ;
fflush(msgFile) ;
}
if ( exp[y] > 0 ) {
/*
----------------------------------
y is exposed, set label and return
----------------------------------
*/
if ( labels[y] > exp[y] ) {
labels[y] = exp[y] ;
}
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile,
"\n Y node %d is exposed, label = %d",
y,labels[y]) ;
fflush(msgFile) ;
}
return(y) ;
}
list[++last] = y ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, ", adding to list") ;
fflush(msgFile) ;
}
}
}
} else {
y = list[now++] ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, ", Y node %d", y) ;
fflush(msgFile) ;
}
for ( cell = heads[y] ; cell != NULL ; cell = cell->ynext ) {
x = cell->x ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n adjacent X node %d, mark %d, f %d",
x, mark[x], cell->fxy) ;
fflush(msgFile) ;
}
if ( mark[x] != tag && cell->fxy > 0 ) {
/*
--------------------------------------------------------
x has not yet been visited and there is flow from x to y
--------------------------------------------------------
*/
mark[x] = tag ;
par[x] = y ;
if ( labels[y] < cell->fxy ) {
labels[x] = labels[y] ;
} else {
labels[x] = cell->fxy ;
}
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, ", labels = %d", labels[x]) ;
fflush(msgFile) ;
}
list[++last] = x ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, ", adding to list") ;
fflush(msgFile) ;
}
}
}
}
}
return(-1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------------
given an augmenting path starting with xexp and ending with yexp,
augment the path by the amount in labels[yexp]
96mar08, cca
-----------------------------------------------------------------
*/
static void
augmentPath (
BPG *bpg,
int xexp,
int yexp,
int nvexp[],
Cell *heads[],
int labels[],
int par[],
int msglvl,
FILE *msgFile
) {
Cell *cell ;
int delta, x, y ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n AUGMENT PATH FOR NODE %d", xexp) ;
fflush(msgFile) ;
}
/*
---------------------------
start at the exposed y node
---------------------------
*/
delta = labels[yexp] ;
y = yexp ;
while ( 1 ) {
x = par[y] ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n (x,y) = (%3d, %3d)", x, y) ;
fflush(msgFile) ;
}
for ( cell = heads[y] ; cell != NULL ; cell = cell->ynext ) {
if ( cell->x == x ) {
cell->rxy -= delta ;
cell->fxy += delta ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, ", r = %d, f = %d", cell->rxy, cell->fxy) ;
fflush(msgFile) ;
}
break ;
}
}
if ( cell == NULL ) {
fprintf(stderr, "\n 1. error, x = %d, y = %d", x, y) ;
exit(-1) ;
}
if ( x == xexp ) {
break ;
}
y = par[x] ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n (x,y) = (%3d, %3d)", x, y) ;
fflush(msgFile) ;
}
for ( cell = heads[x] ; cell != NULL ; cell = cell->xnext ) {
if ( cell->y == y ) {
cell->rxy += delta ;
cell->fxy -= delta ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, ", r = %d, f = %d", cell->rxy, cell->fxy) ;
fflush(msgFile) ;
}
break ;
}
}
if ( cell == NULL ) {
fprintf(stderr, "\n 2. error, x = %d, y = %d", x, y) ;
exit(-1) ;
}
}
nvexp[xexp] -= delta ;
nvexp[yexp] -= delta ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
set the flags for the DM decomposition
created -- 96mar08, cca
--------------------------------------
*/
static void
setDMflags (
BPG *bpg,
Cell *heads[],
int nvexp[],
int list[],
int mark[],
int dmflags[],
int stats[],
int msglvl,
FILE *msgFile
) {
Cell *cell ;
int ierr, last, now, nX, nY, x, xwght, y, ywght ;
int *vwghts ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n SET DM FLAGS") ;
fflush(msgFile) ;
}
nX = bpg->nX ;
nY = bpg->nY ;
IVfill(nX + nY, dmflags, 0) ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n nvexp : ") ;
IVfp80(msgFile, nX + nY, nvexp, 20, &ierr) ;
fflush(msgFile) ;
}
/*
-----------------------
load exposed nodes in X
-----------------------
*/
IVzero(nX + nY, mark) ;
last = -1 ;
for ( x = 0 ; x < nX ; x++ ) {
if ( nvexp[x] > 0 ) {
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n X node %d is exposed", x) ;
fflush(msgFile) ;
}
mark[x] = 1 ;
list[++last] = x ;
dmflags[x] = 1 ;
}
}
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n %d exposed X nodes :", last + 1) ;
IVfp80(msgFile, 1 + last, list, 20, &ierr) ;
fflush(msgFile) ;
}
/*
---------------------------------------------------------------
drop an alternating level structure from the exposed nodes in X
---------------------------------------------------------------
*/
now = 0 ;
while ( now <= last ) {
if ( list[now] < nX ) {
x = list[now++] ;
dmflags[x] = 1 ;
for ( cell = heads[x] ; cell != NULL ; cell = cell->xnext ) {
y = cell->y ;
/*
if ( mark[y] != 1 && cell->rxy > 0 ) {
*/
if ( mark[y] != 1 ) {
mark[y] = 1 ;
list[++last] = y ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n adding Y node %d", y) ;
fflush(msgFile) ;
}
}
}
} else {
y = list[now++] ;
dmflags[y] = 2 ;
for ( cell = heads[y] ; cell != NULL ; cell = cell->ynext ) {
x = cell->x ;
if ( mark[x] != 1 && cell->fxy > 0 ) {
mark[x] = 1 ;
list[++last] = x ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n adding X node %d", x) ;
fflush(msgFile) ;
}
}
}
}
}
/*
-----------------------
load exposed nodes in Y
-----------------------
*/
IVzero(nX + nY, mark) ;
last = -1 ;
for ( y = nX ; y < nX + nY ; y++ ) {
if ( nvexp[y] > 0 ) {
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n Y node %d is exposed", y) ;
fflush(msgFile) ;
}
mark[y] = 1 ;
list[++last] = y ;
dmflags[y] = 1 ;
}
}
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n %d exposed Y nodes :", last + 1) ;
IVfp80(msgFile, 1 + last, list, 20, &ierr) ;
fflush(msgFile) ;
}
/*
---------------------------------------------------------------
drop an alternating level structure from the exposed nodes in Y
---------------------------------------------------------------
*/
now = 0 ;
while ( now <= last ) {
if ( list[now] < nX ) {
x = list[now++] ;
dmflags[x] = 2 ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n checking out X node %d", x) ;
fflush(msgFile) ;
}
for ( cell = heads[x] ; cell != NULL ; cell = cell->xnext ) {
y = cell->y ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n adjacent Y node %d, mark %d, f %d",
y, mark[y], cell->fxy) ;
fflush(msgFile) ;
}
if ( mark[y] != 1 && cell->fxy > 0 ) {
mark[y] = 1 ;
list[++last] = y ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, ", adding ") ;
fflush(msgFile) ;
}
}
}
} else {
y = list[now++] ;
dmflags[y] = 1 ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n checking out Y node %d", y) ;
fflush(msgFile) ;
}
for ( cell = heads[y] ; cell != NULL ; cell = cell->ynext ) {
x = cell->x ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n adjacent X node %d, mark %d, r %d",
x, mark[x], cell->rxy) ;
fflush(msgFile) ;
}
/*
if ( mark[x] != 1 && cell->rxy > 0 ) {
*/
if ( mark[x] != 1 ) {
mark[x] = 1 ;
list[++last] = x ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, ", adding") ;
fflush(msgFile) ;
}
}
}
}
}
/*
--------------------------
fill the statistics vector
--------------------------
*/
IVzero(6, stats) ;
vwghts = bpg->graph->vwghts ;
for ( x = 0 ; x < nX ; x++ ) {
xwght = (vwghts != NULL) ? vwghts[x] : 1 ;
switch ( dmflags[x] ) {
case 0 : stats[2] += xwght ; break ;
case 1 : stats[0] += xwght ; break ;
case 2 : stats[1] += xwght ; break ;
default :
fprintf(stderr, "\n fatal error in BPG_DMviaMaxFlow"
"\n dmflags[%d] = %d\n", x, dmflags[x]) ;
exit(-1) ;
}
}
for ( y = nX ; y < nX + nY ; y++ ) {
ywght = (vwghts != NULL) ? vwghts[y] : 1 ;
switch ( dmflags[y] ) {
case 0 : stats[5] += ywght ; break ;
case 1 : stats[3] += ywght ; break ;
case 2 : stats[4] += ywght ; break ;
default :
fprintf(stderr, "\n fatal error in BPG_DMviaMaxFlow"
"\n dmflags[%d] = %d\n", y, dmflags[y]) ;
exit(-1) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
BPG/src/pseudo.c 0100644 0002055 0007177 00000007637 06534106127 0014754 0 ustar 00cleve compmath 0000040 0000006 /* pseudo.c */
#include "../BPG.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
------------------------------
return a pseudoperipheral node
created -- 95oct07, cca
------------------------------
*/
int
BPG_pseudoperipheralnode (
BPG *bpg,
int seed
) {
int last, mate, oldrad, rad, root, tag ;
int *dist, *list, *mark ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL ) {
fprintf(stderr, "\n fatal error in BPG_pseudoperipheralnode(%p,%d)"
"\n bad input\n", bpg, seed) ;
exit(-1) ;
}
if ( seed < 0 ) {
seed = - seed ;
}
seed = seed % (bpg->nX + bpg->nY) ;
list = IVinit(bpg->nX + bpg->nY, -1) ;
dist = IVinit(bpg->nX + bpg->nY, -1) ;
mark = IVinit(bpg->nX + bpg->nY, -1) ;
oldrad = 0 ;
/*
-------------------------------------------
drop a level structure from the seed vertex
-------------------------------------------
*/
tag = 1 ;
last = BPG_levelStructure(bpg, seed, list, dist, mark, tag) ;
mate = list[last] ;
rad = dist[mate] ;
#if MYDEBUG > 0
fprintf(stdout, "\n BPG_pseudoperipheralnode") ;
fprintf(stdout, "\n node %d, mate %d, rad %d", seed, mate, rad) ;
fflush(stdout) ;
#endif
/*
-----------------------------------------------
loop while vertex with a larger radius is found
-----------------------------------------------
*/
while ( oldrad < rad ) {
oldrad = rad ;
root = mate ;
tag++ ;
last = BPG_levelStructure(bpg, root, list, dist, mark, tag) ;
mate = list[last] ;
rad = dist[mate] ;
#if MYDEBUG > 0
fprintf(stdout, "\n node %d, mate %d, rad %d", root, mate, rad) ;
fflush(stdout) ;
#endif
}
#if MYDEBUG > 1
{ int root ;
for ( root = 0, tag++ ; root < bpg->nX ; root++, tag++ ) {
last = BPG_levelStructure(bpg, root, list, dist, mark, tag) ;
mate = list[last] ;
rad = dist[mate] ;
fprintf(stdout, "\n node %d, mate %d, rad %d", root, mate, rad) ;
fflush(stdout) ;
}
}
#endif
/*
------------------------
free the working storage
------------------------
*/
IVfree(list) ;
IVfree(dist) ;
IVfree(mark) ;
return(root) ; }
/*--------------------------------------------------------------------*/
#define MYDEBUG 0
/*
----------------------------------------------------
return value -- # of vertices in the level structure
created -- 95oct07, cca
----------------------------------------------------
*/
int
BPG_levelStructure (
BPG *bpg,
int root,
int list[],
int dist[],
int mark[],
int tag
) {
int ii, jj, last, now, u, usize, v, vsize, w ;
int *uadj, *vadj ;
/*
---------------
check the input
---------------
*/
if ( bpg == NULL || root < 0 || root >= bpg->nX + bpg->nY
|| list == NULL || dist == NULL || mark == NULL ) {
fprintf(stderr,
"\n fatal error in BPG_levelStructure(%p,%d,%p,%p,%p,%d)"
"\n bad input\n", bpg, root, list, dist, mark, tag) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n inside BPG_levelStructure(%p,%d,%p,%p,%p,%d)",
bpg, root, list, dist, mark, tag) ;
fflush(stdout) ;
#endif
now = last = 0 ;
list[0] = root ;
dist[root] = 0 ;
mark[root] = tag ;
while ( now <= last ) {
u = list[now++] ;
#if MYDEBUG > 0
fprintf(stdout, "\n u = %d", u) ;
fflush(stdout) ;
#endif
Graph_adjAndSize(bpg->graph, u, &usize, &uadj) ;
for ( ii = 0 ; ii < usize ; ii++ ) {
v = uadj[ii] ;
Graph_adjAndSize(bpg->graph, v, &vsize, &vadj) ;
for ( jj = 0 ; jj < vsize ; jj++ ) {
w = vadj[jj] ;
#if MYDEBUG > 0
fprintf(stdout, "\n w = %d", w) ;
#endif
if ( mark[w] != tag ) {
#if MYDEBUG > 0
fprintf(stdout, ", adding to list, dist = %d", dist[u] + 1);
fflush(stdout) ;
#endif
mark[w] = tag ;
list[++last] = w ;
dist[w] = dist[u] + 1 ;
}
}
}
}
return(last) ; }
/*--------------------------------------------------------------------*/
--------
check the input
---------------
*/
if ( bpg == NULL ) {
fprintf(stderr, "\n fatBPG/drivers/doDM 0100755 0002055 0007177 00000000507 06542755315 0014746 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = BCSSTK24
set msglvl = 1
set msgFile = stdout
foreach icomp ( 1 2 )
echo ' matrix = ' $matrix
set inBPGfile = $matrices/$matrix/sep$icomp.bpgf
set msgFile = stats.$matrix
set msgFile = stdout
testDM $msglvl $msgFile $inBPGfile
end
BPG/drivers/doExtractBPG 0100755 0002055 0007177 00000001440 06542755333 0016406 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = BCSSTK24
set inGraphFile = $matrices/$matrix/orig1.graphf
set inCompidsIVfile = $matrices/$matrix/bkl.ivf
set msglvl = 5
set msgFile = stdout
set firstseed = 1
set lastseed = 2
set lastseed = 21
set lastseed = 6
set lastseed = 51
set lastseed = 11
set lastseed = 1
set alpha = 1.0
foreach icomp ( 1 2 )
echo ' matrix = ' $matrix
set outMapIVfile = temp.ivf
set outMapIVfile = none
set outBPGfile = temp.bpgf
set outBPGfile = none
set msgFile = stdout
@ seed = $firstseed
while ( $seed <= $lastseed )
extractBPG $msglvl $msgFile $inGraphFile \
$inCompidsIVfile $icomp $outMapIVfile $outBPGfile
@ seed = $seed + 1
end
end
BPG/drivers/makefile 0100644 0002055 0007177 00000001004 06653142316 0015660 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = testIO testDM extractBPG
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
testIO : testIO.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testDM : testDM.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
extractBPG : extractBPG.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
BPG/drivers/extractBPG.c 0100644 0002055 0007177 00000013435 06542213432 0016335 0 ustar 00cleve compmath 0000040 0000006 /* extractBPG.c */
#include "../BPG.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
--------------------------------------------------------------
extract a bipartite graph from a graph and a two-set partition
created -- 96nov02, cca
--------------------------------------------------------------
*/
{
char *inGraphFileName, *inCompidsIVfileName,
*outBPGfileName, *outMapIVfileName ;
double t1, t2 ;
int msglvl, rc ;
BPG *bpg ;
FILE *msgFile ;
Graph *graph ;
int icomp, ierr, nvtx ;
int *cmap, *compids, *indX, *indY ;
IV *compidsIV ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile inCompidsIVfile"
"\n icomp outBPGfile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n inCompidsIVfile -- input file, must be *.ivf or *.ivb"
"\n icomp -- component for Y nodes"
"\n outMapIVfile -- map output file, must be *.ivf or *.ivb"
"\n outBPGfile -- output file, must be *.bpgf or *.bpgb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
inCompidsIVfileName = argv[4] ;
icomp = atoi(argv[5]) ;
outMapIVfileName = argv[6] ;
outBPGfileName = argv[7] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n inCompidsIVfile -- %s"
"\n icomp -- %d"
"\n outMapIVfile -- %s"
"\n outBPGfile -- %s"
"\n",
argv[0], msglvl, argv[2], inGraphFileName, inCompidsIVfileName,
icomp, outMapIVfileName, outBPGfileName) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
nvtx = graph->nvtx ;
/*
------------------------
read in the IV object
------------------------
*/
if ( strcmp(inCompidsIVfileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
compidsIV = IV_new() ;
MARKTIME(t1) ;
rc = IV_readFromFile(compidsIV, inCompidsIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in compidsIV from file %s",
t2 - t1, inCompidsIVfileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from IV_readFromFile(%p,%s)",
rc, compidsIV, inCompidsIVfileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading IV object from file %s",
inCompidsIVfileName) ;
if ( msglvl > 2 ) {
IV_writeForHumanEye(compidsIV, msgFile) ;
} else {
IV_writeStats(compidsIV, msgFile) ;
}
fflush(msgFile) ;
/*
---------------------------------------------------
extract out the bipartite graph that corresponds to
the separator and its boundary in component icomp
---------------------------------------------------
*/
compids = IV_entries(compidsIV) ;
cmap = IVinit(nvtx, -1) ;
indX = IVinit(nvtx, -1) ;
indY = IVinit(nvtx, -1) ;
bpg = BPG_new() ;
BPG_initFromColoring(bpg, graph, compids, 0, icomp, cmap, indX, indY) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n cmap[]") ;
IVfp80(msgFile, nvtx, cmap, 80, &ierr) ;
fprintf(msgFile, "\n\n indX[]") ;
IVfp80(msgFile, bpg->nX, indX, 80, &ierr) ;
fprintf(msgFile, "\n\n indY[]") ;
IVfp80(msgFile, bpg->nY, indY, 80, &ierr) ;
fprintf(msgFile, "\n\n bipartite graph") ;
BPG_writeForHumanEye(bpg, msgFile) ;
} else {
BPG_writeStats(bpg, msgFile) ;
}
fflush(msgFile) ;
/*
----------------------------------------------------------------
if the map vector is requested, create it and write it to a file
----------------------------------------------------------------
*/
if ( strcmp(outMapIVfileName, "none") != 0 ) {
IV mapIV ;
IV_setDefaultFields(&mapIV) ;
IV_init(&mapIV, bpg->nX + bpg->nY, NULL) ;
IVcopy(bpg->nX, IV_entries(&mapIV), indX) ;
IVcopy(bpg->nY, IV_entries(&mapIV) + bpg->nX, indY) ;
if ( msglvl > 0 ) {
IV_writeForHumanEye(&mapIV, msgFile) ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
rc = IV_writeToFile(&mapIV, outMapIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write mapIV to file %s",
t2 - t1, outMapIVfileName) ;
}
/*
------------------------
write out the BPG object
------------------------
*/
if ( strcmp(outBPGfileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = BPG_writeToFile(bpg, outBPGfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write graph to file %s",
t2 - t1, outBPGfileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from BPG_writeToFile(%p,%s)",
rc, bpg, outBPGfileName) ;
}
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
"
"\n icomp outBPGfile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n inCompidsIVfile -- inputBPG/drivers/testDM.c 0100644 0002055 0007177 00000007434 06542213653 0015541 0 ustar 00cleve compmath 0000040 0000006 /* testDM.c */
#include "../BPG.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------------------------
read BPG from file and get the Dulmage-Mendelsohn decomposition
created -- 96mar08, cca
---------------------------------------------------------------
*/
{
char *inBPGFileName ;
double t1, t2 ;
int ierr, msglvl, rc ;
int *dmflags, *stats ;
BPG *bpg ;
FILE *msgFile ;
if ( argc != 4 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.bpgf or *.bpgb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inBPGFileName = argv[3] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n",
argv[0], msglvl, argv[2], inBPGFileName) ;
fflush(msgFile) ;
/*
----------------------
read in the BPG object
----------------------
*/
if ( strcmp(inBPGFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
bpg = BPG_new() ;
MARKTIME(t1) ;
rc = BPG_readFromFile(bpg, inBPGFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inBPGFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from BPG_readFromFile(%p,%s)",
rc, bpg, inBPGFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading BPG object from file %s",
inBPGFileName) ;
if ( msglvl > 2 ) {
BPG_writeForHumanEye(bpg, msgFile) ;
} else {
BPG_writeStats(bpg, msgFile) ;
}
fflush(msgFile) ;
/*
--------------------------------------------
test out the max flow DMdecomposition method
--------------------------------------------
*/
dmflags = IVinit(bpg->nX + bpg->nY, -1) ;
stats = IVinit(6, 0) ;
MARKTIME(t1) ;
BPG_DMviaMaxFlow(bpg, dmflags, stats, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %9.5f : find DM via maxflow", t2 - t1) ;
if ( msglvl > 0 ) {
fprintf(msgFile,
"\n\n BPG_DMviaMaxFlow"
"\n |X_I| = %6d, |X_E| = %6d, |X_R| = %6d"
"\n |Y_I| = %6d, |Y_E| = %6d, |Y_R| = %6d",
stats[0], stats[1], stats[2],
stats[3], stats[4], stats[5]) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n dmflags") ;
IVfp80(msgFile, bpg->nX + bpg->nY, dmflags, 80, &ierr) ;
fflush(msgFile) ;
}
/*
------------------------------------------
test out the matching DMcomposition method
------------------------------------------
*/
IVfill(bpg->nX + bpg->nY, dmflags, -1) ;
IVfill(6, stats, -1) ;
MARKTIME(t1) ;
BPG_DMdecomposition(bpg, dmflags, stats, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %9.5f : find DM via matching", t2 - t1) ;
if ( msglvl > 0 ) {
fprintf(msgFile,
"\n\n BPG_DMdecomposition"
"\n |X_I| = %6d, |X_E| = %6d, |X_R| = %6d"
"\n |Y_I| = %6d, |Y_E| = %6d, |Y_R| = %6d",
stats[0], stats[1], stats[2],
stats[3], stats[4], stats[5]) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n dmflags") ;
IVfp80(msgFile, bpg->nX + bpg->nY, dmflags, 80, &ierr) ;
fflush(msgFile) ;
}
/*
----------------
free the storage
----------------
*/
IVfree(dmflags) ;
IVfree(stats) ;
BPG_free(bpg) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
BPG/drivers/testIO.c 0100644 0002055 0007177 00000005350 06542213470 0015540 0 ustar 00cleve compmath 0000040 0000006 /* testIO.c */
#include "../BPG.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------
test BPG_readFromFile and BPG_writeToFile,
useful for translating between formatted *.bpgf
and binary *.bpgb files.
created -- 96mar08, cca
-------------------------------------------------
*/
{
char *inBPGFileName, *outBPGFileName ;
double t1, t2 ;
int msglvl, rc ;
BPG *bpg ;
FILE *msgFile ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.bpgf or *.bpgb"
"\n outFile -- output file, must be *.bpgf or *.bpgb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inBPGFileName = argv[3] ;
outBPGFileName = argv[4] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], inBPGFileName, outBPGFileName) ;
fflush(msgFile) ;
/*
----------------------
read in the BPG object
----------------------
*/
if ( strcmp(inBPGFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
bpg = BPG_new() ;
MARKTIME(t1) ;
rc = BPG_readFromFile(bpg, inBPGFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inBPGFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from BPG_readFromFile(%p,%s)",
rc, bpg, inBPGFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading BPG object from file %s",
inBPGFileName) ;
if ( msglvl > 2 ) {
BPG_writeForHumanEye(bpg, msgFile) ;
} else {
BPG_writeStats(bpg, msgFile) ;
}
fflush(msgFile) ;
/*
------------------------
write out the BPG object
------------------------
*/
if ( strcmp(outBPGFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = BPG_writeToFile(bpg, outBPGFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write graph to file %s",
t2 - t1, outBPGFileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from BPG_writeToFile(%p,%s)",
rc, bpg, outBPGFileName) ;
}
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
BPG/doc/ 0042755 0002055 0007177 00000000000 06650141426 0013257 5 ustar 00cleve compmath 0000040 0000006 BPG/doc/dataStructure.tex 0100644 0002055 0007177 00000000743 06534106127 0016632 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:BPG:dataStructure}
\par
A bipartite graph is a triple $(X,Y,E)$
where $X$ and $Y$ are disjoint sets of vertices
and $E \subseteq X \times Y$ is a set of edges connecting vertices
in $X$ and $Y$.
The {\tt BPG} structure has three fields.
\begin{itemize}
\item {\tt int nX} : number of vertices in $X$
\item {\tt int nY} : number of vertices in $Y$
\item {\tt Graph *graph}
: pointer to a graph object $G = (X \cup Y), E)$.
\end{itemize}
BPG/doc/drivers.tex 0100644 0002055 0007177 00000012611 06535771624 0015466 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt BPG} object}
\label{section:BPG:drivers}
\par
This section contains brief descriptions of the driver programs.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testIO msglvl msgFile inFile outFile
\end{verbatim}
This driver program reads and write {\tt BPG} files, useful for
converting formatted files to binary files and vice versa.
One can also read in a {\tt BPG} file and print out just the
header information (see the {\tt BPG\_writeStats()} method).
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt BPG} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inFile} parameter is the input file for the {\tt BPG}
object. It must be of the form {\tt *.bpgf} or {\tt *.bpgb}.
The {\tt BPG} object is read from the file via the
{\tt BPG\_readFromFile()} method.
\item
The {\tt outFile} parameter is the output file for the {\tt BPG}
object.
If {\tt outFile} is {\tt none} then the {\tt BPG} object is not
written to a file.
Otherwise, the {\tt BPG\_writeToFile()} method is called to write
the graph to
a formatted file (if {\tt outFile} is of the form {\tt *.bpgf}),
or
a binary file (if {\tt outFile} is of the form {\tt *.bpgb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
extractBPG msglvl msgFile inGraphFile inCompidsIVfile
icomp outMapFile outBPGfile
\end{verbatim}
This driver program reads in a {\tt Graph} object
and an {\tt IV} object that contains the component ids.
(A separator vertex has component id zero; other vertices have
positive component ids to identify the subgraph that contains
them.)
It then extracts out the bipartite graph formed by the separator
and nodes in the target component that are adjacent to the separator.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means that all objects are written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
message data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt inCompidsIVfile} parameter is the input file for the {\tt IV}
object that contains the component ids.
It must be of the form {\tt *.ivf} or {\tt *.ivb}.
The {\tt IV} object is read from the file via the
{\tt IV\_readFromFile()} method.
\item
The {\tt icomp} parameter defines the target component to form the
$Y$ nodes of the bipartite graph.
(The separator nodes, component zero, form the $X$ nodes.)
\item
The {\tt outMapFile} parameter is the output file for the {\tt IV}
object that holds the map from vertices in the bipartite graph to
vertices in the original graph.
If {\tt outMapFile} is {\tt none} then the {\tt IV} object is not
written to a file.
Otherwise, the {\tt IV\_writeToFile()} method is called to write
the {\tt IV} object to
a formatted file (if {\tt outMapFile} is of the form {\tt *.ivf}),
or
a binary file (if {\tt outMapFile} is of the form {\tt *.ivb}).
\item
The {\tt outBPGFile} parameter is the output file for the
compressed {\tt BPG} object.
If {\tt outBPGFile} is {\tt none} then the {\tt BPG} object is not
written to a file.
Otherwise, the {\tt BPG\_writeToFile()} method is called to write
the graph to
a formatted file (if {\tt outBPGFile} is of the form {\tt *.graphf}),
or
a binary file (if {\tt outBPGFile} is of the form {\tt *.graphb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testDM msglvl msgFile inBPGfile
\end{verbatim}
This driver program reads in a {\tt BPG} object from a file.
It then finds the Dulmage-Mendelsohn decomposition using two
methods.
\begin{itemize}
\item
{\tt BPG\_DMdecomposition()} which uses matching
techniques on the weighted graph.
\item
{\tt BPG\_DMviaMaxFlow()} which forms bipartite network and solves
the max flow problem using a simple Ford-Fulkerson algorithm.
\end{itemize}
This provides a good check on the two programs (they must have the
same output) and writes their execution times.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means that all objects are written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
message data.
\item
The {\tt inBPGFile} parameter is the input file for the {\tt BPG}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt BPG} object is read from the file via the
{\tt BPG\_readFromFile()} method.
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
BPG/doc/intro.tex 0100644 0002055 0007177 00000020153 06650230146 0015126 0 ustar 00cleve compmath 0000040 0000006 \par
\chapter{{\tt BPG}: Bipartite Graph Object}
\label{chapter:BPG}
\par
The {\tt BPG} object is used to represent a bipartite graph.
A bipartite graph naturally {\it is-a} graph,
but since we are working in C, without inheritance,
we have chosen to use the {\it has-a} relationship,
i.e., our {\tt BPG} bipartite graph object {\it has-a}
{\tt Graph} object inside itself.
\par
A bipartite graph is a triple $H = (X, Y, E)$ where
$X$ and $Y$ are two disjoint sets of vertices and the edge set $E$
is a subset of $X \times Y$.
In other words, nodes in $X$ are adjacent to node in $Y$,
but no edge connects two vertices in $X$ or two vertices in $Y$.
\par
We do not support bipartite graphs that are {\it subgraphs}
of other bipartite graphs (in the sense that there are
{\tt Graph} objects that are subgraphs of other {\tt Graph}
objects) because we haven't found any reason to do so.
\par
This bipartite graph object is very rudimentary.
We have used it in two instances.
\begin{itemize}
\item
Given a domain decomposition of a graph, we want to find a bisector
of the graph that is a subset of the interface vertices.
To do this we construct a bipartite graph such that the $X$ nodes
are the domains and the $Y$ nodes are the
segments (a partition of the interface vertices).
We then apply a variant of the Kernighan-Lin algorithm to find an
edge separator that is a subset of the segments.
(Details are found in \cite{ash97-DDSEP}.)
\item
Given a 2-set partition of a graph $[S,B,W]$ where $S$ is the
separator and $B$ and $W$ are the two components, we want to find
an improved partition
$[{\widehat S}, {\widehat B}, {\widehat W}]$.
One way to do this is to construct a bipartite graph where $X = S$
and $Y = Adj(S) \cap B$ or $Y = Adj(S) \cap W$
and the edge set $E$ is constructed naturally from the appropriate
edges in the graph.
We then find the Dulmage-Mendelsohn decomposition of this bipartite
graph to look for a better 2-set partition.
(Details are found in \cite{ash98-maxflow}.)
\end{itemize}
Our bipartite graph object illustrates software in evolution.
In both cases, our desired output is a separator and the problem
can be formulated as a bipartite graph.
Does the {\it data} (the bipartite graph) {\it own} the {\it
process} (the Kernighan-Lin algorithm or the Dulmage-Mendelsohn
decomposition)?
Or does the process operate on the data?
There is no cut and dried answer.
In fact, we did it both ways.
\par
To find a separator from a domain decomposition, we took the
approach that the process works on the data.
(See the {\tt BKL} block Kernighan-Lin object.)
The process was sufficiently involved that soon the {\tt BKL} code
for the process outweighed (outline'd?) the {\tt BPG} code for the data.
Now if someone wants to modify (and hopefully improve) the
Kernighan-Lin process, they won't alter the behavior of the
bipartite graph object.
\par
Finding the Dulmage-Mendelsohn decomposition of a bipartite graph
is a little less clear cut.
When the vertices in the bipartite graph have unit weight, the
process is straightforward.
\begin{itemize}
\item
Find a maximum matching.
\item
Drop an alternating level structure from exposed nodes in $X$.
\item
Drop an alternating level structure from exposed nodes in $Y$.
\item
Based on the two previous steps, partition $X$ into three pieces
and $Y$ into three pieces and form a new separator from the
pieces.
\end{itemize}
(If these terms are not familiar, see \cite{ash98-maxflow};
our present purpose is a discussion of software design, not
algorithms.)
A matching is a very common operation on a bipartite graph,
so it is not unreasonable to expand the data object to include some
mechanism for matching, e.g., a {\tt mate[]} vector.
Finding a maximum matching is a bit more tricky for there are a
number of algorithms to do so, some fast, some slow,
some simple, some complex. Which to choose?
\par
If we only worked with unit weight bipartite graphs, then we
probably would have added methods to find a maximum matching,
and dropping alternating level structures, and then to find the
Dulmage-Mendelsohn decomposition.
If someone wanted to use a faster algorithm to find a maximum
matching it would be a simple case of replacing a method.
However, one of the strengths of this software package is that we
do not work on unit weight graphs unless we have to, we work on the
natural compressed graph.
\par
The Dulmage-Mendelsohn decomposition was not defined for non-unit
weight graphs.
We were in new territory, at least to us.
We could always expand the weighted bipartite compressed graph into
a larger unit weight graph, find the Dulmage-Mendelsohn
decomposition and map it back to the weighted graph.
(It turns out that the DM partition is conformal with the
compressed graph, i.e., a weighted vertex is completely contained
inside one of the six sets.)
This would have been a very ugly feature of an otherwise clean code.
\par
Our first remedy was to design a method that found the DM
decomposition of the unit weight graph while {\it using} the
compressed graph plus a work vector whose size was the sum of the
vertex weights.
See the method {\tt BPG\_DMdecomposition()}.
The code is appreciably faster than expanding the weighted graph to
a unit weight graph, finding the decomposition and then mapping back.
It is not really a method, but a module, for the fourteen hundred
lines of code contain many static functions.
Though the code is adequately documented, this isn't an algorithm
that we felt like publicizing, so we export the method but not the
internals.
\par
After some time, thought and reflection, we came to realize that we
can find the decomposition by solving a max flow problem.
In some sense this is obvious, for bipartite graph matching is
nothing more than a special case of max flow.
Just how to formulate the max flow problem is what eluded us for an
embarassing amount of time.
Once we were able to formulate the problem as max flow, we wrote a
new method to find the decomposition for a weighted graph.
The line count for {\tt BPG\_DMviaMaxFlow()} is about one half that
of {\tt BPG\_DMdecomposition()} and it is easier to understand.
Both methods use a simple Ford-Fulkerson augmenting flow approach.
\par
At this time we thought about writing an object to solve max flow
problems and shifting most of the responsibility of finding the
decomposition to a specialized object that solves a max flow
problem on a bipartite network.
Had we more time, we would have done so.
The advantages are clear.
In fact, that is the approach we have taken, but in a different
context.
To explain, we must return to our original problem.
\par
The goal is to improve a 2-set partition $[S,B,W]$.
Let $B$ be the larger of $B$ and $W$.
We look at the subgraph induced by $S \cup (Adj(S) \cap B)$.
The goal is to find a set $Z \subseteq S$ that will be absorbed by
the smaller component $W$ that results in a smaller separator.
As a result, some nodes in $Adj(S) \cap B$ move from $B$ into the
separator set.
The DM decomposition lets us identify a set $Z$ that results in the
{\it largest} decrease in the separator size.
But, if we consider $S \cup (Adj(S) \cap B)$ to be a {\it wide}
separator, the resulting separator ${\widehat S}$ need not be a
separator with minimal weight that is found within the wide
separator.
The trick is that some nodes in $Adj(S) \cap B$ might be absorbed
into $W$.
\par
One can find a separator with minimal weight from the wide
separator $S \cup (Adj(S) \cap B)$, in fact from {\it any} wide
separator that contains $S$, by solving a max flow problem.
The drawback is that the network induced by $S \cup (Adj(S) \cap B)$
need not be bipartite.
In other words, a bipartite induced graph necessarily implies two
layers to the wide separator, but the converse does not hold.
We were then free to examine wide separators that had more than two
layers from which to find a minimal weight separator.
It turns out that three layers is better than two, in practice.
\par
We did write a separate object to solve our max flow problem;
see the {\tt Network} object.
To smooth a separator, i.e., to improve a 2-set partition,
we no longer have need of the bipartite graph object.
We leave the two Dulmage-Mendelsohn methods in the {\tt BPG} object
for historical and sentimental reasons.
BPG/doc/main.aux 0100644 0002055 0007177 00000003023 06647207107 0014720 0 ustar 00cleve compmath 0000040 0000006 \relax
\citation{ash95-DDSEP}
\citation{ash96-maxflow}
\@writefile{toc}{\contentsline {chapter}{\numberline {1}{\tt BPG}: Bipartite Graph Object}{1}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chapter:BPG}{{1}{1}}
\citation{ash96-maxflow}
\@writefile{toc}{\contentsline {section}{\numberline {1.1}Data Structure}{3}}
\newlabel{section:BPG:dataStructure}{{1.1}{3}}
\@writefile{toc}{\contentsline {section}{\numberline {1.2}Prototypes and descriptions of {\tt BPG} methods}{3}}
\newlabel{section:BPG:proto}{{1.2}{3}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.1}Basic methods}{3}}
\newlabel{subsection:BPG:proto:basics}{{1.2.1}{3}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.2}Initializer methods}{4}}
\newlabel{subsection:BPG:proto:initializers}{{1.2.2}{4}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.3}Generate induced graphs}{4}}
\newlabel{subsection:BPG:proto:induced-graphs}{{1.2.3}{4}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.4}Utility methods}{4}}
\newlabel{subsection:BPG:proto:utilities}{{1.2.4}{4}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.5}Dulmage-Mendelsohn decomposition method}{5}}
\newlabel{subsection:BPG:proto:DM}{{1.2.5}{5}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.6}IO methods}{5}}
\newlabel{subsection:BPG:proto:IO}{{1.2.6}{5}}
\@writefile{toc}{\contentsline {section}{\numberline {1.3}Driver programs for the {\tt BPG} object}{6}}
\newlabel{section:BPG:drivers}{{1.3}{6}}
BPG/doc/main.log 0100644 0002055 0007177 00000006235 06647207107 0014714 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.14159 (C version 6.1) (format=latex 97.4.4) 13 JAN 1999 13:21
**main
(main.tex
LaTeX2e <1996/12/01> patch level 1
Babel and hyphenation patterns for english, german, loaded.
(/home/tex/teTeX/texmf/tex/latex/base/report.cls
Document Class: report 1996/10/31 v1.3u Standard LaTeX document class
(/home/tex/teTeX/texmf/tex/latex/base/leqno.clo
File: leqno.clo 1996/07/26 v1.1b Standard LaTeX option (left equation numbers)
)
(/home/tex/teTeX/texmf/tex/latex/base/size10.clo
File: size10.clo 1996/10/31 v1.3u Standard LaTeX file (size option)
)
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
\abovecaptionskip=\skip41
\belowcaptionskip=\skip42
\bibindent=\dimen102
)
\@indexfile=\write3
Writing index file main.idx
(main.aux)
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 17.
LaTeX Font Info: ... okay on input line 17.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 17.
LaTeX Font Info: ... okay on input line 17.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 17.
LaTeX Font Info: ... okay on input line 17.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 17.
LaTeX Font Info: ... okay on input line 17.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 17.
LaTeX Font Info: ... okay on input line 17.
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 17.
LaTeX Font Info: ... okay on input line 17.
(intro.tex
Chapter 1.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <7> on input line 12.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <5> on input line 12.
LaTeX Font Info: Try loading font information for OMS+cmr on input line 27.
(/home/tex/teTeX/texmf/tex/latex/base/omscmr.fd
File: omscmr.fd 1997/01/14 v2.5a Standard LaTeX font definitions
)
LaTeX Font Info: Font shape `OMS/cmr/m/n' in size <10> not available
(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 27.
LaTeX Warning: Citation `ash95-DDSEP' on page 1 undefined on input line 34.
LaTeX Warning: Citation `ash96-maxflow' on page 1 undefined on input line 46.
[1
]
LaTeX Warning: Citation `ash96-maxflow' on page 2 undefined on input line 83.
[2]) (dataStructure.tex) (proto.tex [3] [4]
Overfull \hbox (66.05252pt too wide) in paragraph at lines 260--262
[]\OT1/cmr/m/n/10 This method has the same func-tion-al-ity, call-ing se-quence
and re-turned val-ues as the pre-ced-ing \OT1/cmtt/m/n/10 BPG[]DMdecomposition
()
[]
[5]) (drivers.tex [6]) (main.ind [7] [8
]) (main.aux)
LaTeX Warning: There were undefined references.
)
Here is how much of TeX's memory you used:
310 strings out of 10908
3219 string characters out of 72189
50228 words of memory out of 262141
3227 multiletter control sequences out of 9500
7911 words of font info for 30 fonts, out of 150000 for 255
14 hyphenation exceptions out of 607
23i,7n,22p,164b,341s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (8 pages, 32148 bytes).
BPG/doc/main.tex 0100644 0002055 0007177 00000001151 06647207077 0014731 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
% \documentstyle[leqno,11pt,twoside]{report}
\documentclass[leqno,10pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt BPG} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt BPG} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
BPG/doc/proto.tex 0100644 0002055 0007177 00000037024 06647212235 0015150 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt BPG} methods}
\label{section:BPG:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt BPG} object.
\par
\subsection{Basic methods}
\label{subsection:BPG:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
BPG * BPG_new ( void ) ;
\end{verbatim}
\index{BPG_new@{\tt BPG\_new()}}
This method simply allocates storage for the {\tt BPG} structure
and then sets the default fields by a call to
{\tt BPG\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BPG_setDefaultFields ( BPG *bpg ) ;
\end{verbatim}
\index{BPG_setDefaultFields@{\tt BPG\_setDefaultFields()}}
This method sets the fields of the structure to their default values:
{\tt nX = nY = 0} and {\tt graph = NULL}.
\par \noindent {\it Error checking:}
If {\tt bpg} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BPG_clearData ( BPG *bpg ) ;
\end{verbatim}
\index{BPG_clearData@{\tt BPG\_clearData()}}
This method releases the storage for {\tt graph} via a call
to {\tt Graph\_clearData()}, and
then the structure's fields are then set to their default values
with a call to {\tt BPG\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt bpg} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BPG_free ( BPG *bpg ) ;
\end{verbatim}
\index{BPG_free@{\tt BPG\_free()}}
This method releases any storage by a call to
{\tt BPG\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt bpg} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initializer methods}
\label{subsection:BPG:proto:initializers}
\par
There are two initializer methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BPG_init ( BPG *bpg, int nX, int nY, Graph *graph ) ;
\end{verbatim}
\index{BPG_init@{\tt BPG\_init()}}
This method initializes the {\tt BPG} object when all three of its
fields are given in the calling sequence.
The {\tt Graph} object has {\tt nX + nY} vertices.
Note, the {\tt BPG} object now ``owns'' the {\tt Graph} object and
so will free the {\tt Graph} object when it is free'd.
The {\tt Graph} object may contains edges between nodes in {\tt X}
and {\tt Y}, but these edges are swapped to the end of each
adjacency list and the size of each list is then set.
\par \noindent {\it Error checking:}
If {\tt bpg} or {\tt graph} are {\tt NULL},
or if ${\tt nX} \le 0$,
or if ${\tt nY} \le 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BPG_initFromColoring ( BPG *bpg, Graph *graph, int colors[], int cX,
int cY, int cmap[], int indX[], int indY[] ) ;
\end{verbatim}
\index{BPG_initFromColoring@{\tt BPG\_initFromColoring()}}
This method extracts a bipartite graph from a {\tt Graph} object where
the {\tt X} vertices are those with {\tt cmap[]} value
equal to {\tt cX} and the {\tt Y} vertices are those
with {\tt cmap[]} value equal to {\tt cY}.
The vectors {\tt indX[]} and {\tt indY[]} hold the global vertex
ids of the {\tt X} and {\tt Y} vertices respectively.
\par \noindent {\it Error checking:}
If {\tt bpg}, {\tt graph}, {\tt colors} or {\tt cmap} are {\tt NULL},
or if ${\tt cX} \le 0$,
or if ${\tt cY} \le 0$,
or if ${\tt cX} = {\tt cY}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Generate induced graphs}
\label{subsection:BPG:proto:induced-graphs}
\par
Sometimes we need to know which {\tt X} or {\tt Y} vertices
share an edge,
e.g., in the {\tt BKL} object we need the domain-domain adjacency
graph (the domains are the {\tt X} vertices)
to efficiently implement the Fiduccia-Mattheyses algorithm.
We have two methods to generate the two induced graphs.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Graph * BPG_makeGraphXbyX ( BPG *bpg ) ;
\end{verbatim}
\index{BPG_makeGraphXbyX@{\tt BPG\_makeGraphXbyX()}}
This method constructs and returns a {\tt Graph} object whose
vertices are {\tt X} and an edge {\tt (x1,x2)} is in the graph
when there is a {\tt Y} vertex {\tt y} such that {\tt (x1,y)}
and {\tt (x2,y)} are in the bipartite graph.
\par \noindent {\it Error checking:}
If {\tt bpg} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Graph * BPG_makeGraphYbyY ( BPG *bpg ) ;
\end{verbatim}
\index{BPG_makeGraphYbyY@{\tt BPG\_makeGraphYbyY()}}
This method constructs and returns a {\tt Graph} object whose
vertices are {\tt Y} and an edge {\tt (y1,y2)} is in the graph
when there is a {\tt X} vertex {\tt x} such that {\tt (x,y1)}
and {\tt (x,y2)} are in the bipartite graph.
\par \noindent {\it Error checking:}
If {\tt bpg} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:BPG:proto:utilities}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BPG_pseudoperipheralnode ( BPG *bpg, int seed ) ;
\end{verbatim}
\index{BPG_pseudoperipheralnode@{\tt BPG\_pseudoperipheralnode()}}
This method finds and returns a pseudoperipheral node for the
bipartite graph.
\par \noindent {\it Error checking:}
If {\tt bpg} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BPG_levelStructure ( BPG *bpg, int root, int list[], int dist[],
int mark[], int tag ) ;
\end{verbatim}
\index{BPG_levelStructure@{\tt BPG\_levelStructure()}}
This method drops a level structure from vertex {\tt root}, fills
the {\tt dist[]} vector with the distances from {\tt root},
and returns the number of levels created.
The {\tt mark[]} vector is used to mark nodes with the {\tt tag}
value as they are placed in the level structure.
The {\tt list[]} vector is used to accumulate the nodes as they are
placed in the level structure.
\par \noindent {\it Error checking:}
If {\tt bpg}, {\tt list}, {\tt dist} or {\tt mark} is {\tt NULL},
or if {\tt root} is not in {\tt [0, nX+nY)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Dulmage-Mendelsohn decomposition method}
\label{subsection:BPG:proto:DM}
\par
There is one method to find the Dulmage-Mendelsohn decomposition that
uses matching when the graph is unit weight and a generalized
matching technique otherwise.
There is a second method to find the decomposition using a
Ford-Fulkerson algorithm to find a max flow and a min-cut on a
bipartite network.
This has largely been superceded by the {\tt Network} object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BPG_DMdecomposition ( BPG *bpg, int dmflags[], int stats[],
int msglvl, FILE *msgFile )
\end{verbatim}
\index{BPG_DMdecomposition@{\tt BPG\_DMdecomposition()}}
This method constructs and returns the Dulmage-Mendelsohn
decomposition for a unit weight graph and its generalization for a
non-unit weight graph.
On return, the {\tt dmflags[]} vector is filled with the following
values:
\begin{displaymath}
\mbox{\tt dmflags[x]} =
\begin{cases}
0 & \text{if \texttt{x} $\in X_R$} \\
1 & \text{if \texttt{x} $\in X_I$} \\
2 & \text{if \texttt{x} $\in X_E$}
\end{cases}
\qquad
\mbox{\tt dmflags[y]} =
\begin{cases}
0 & \text{if \texttt{y} $\in Y_R$} \\
1 & \text{if \texttt{y} $\in Y_I$} \\
2 & \text{if \texttt{y} $\in Y_E$}
\end{cases}
\end{displaymath}
The set $X_I \cup Y_E$ contains all nodes that are reachable via
alternating paths starting from exposed nodes in $X$.
The set $Y_I \cup X_E$ contains all nodes that are reachable via
alternating paths starting from exposed nodes in $Y$.
The remaining two sets are $X_R = X \setminus (X_I \cup X_E)$
and $Y_R = Y \setminus (Y_I \cup Y_E)$.
On return, the {\tt stats[]} vector is filled with the following
values:
\begin{center}
\begin{tabular}{lllllll}
{\tt stats[0]} & --- & weight of $X_I$
& \qquad & {\tt stats[3]} & --- & weight of $Y_I$ \\
{\tt stats[1]} & --- & weight of $X_E$
& \qquad & {\tt stats[4]} & --- & weight of $Y_E$ \\
{\tt stats[2]} & --- & weight of $X_R$
& \qquad & {\tt stats[5]} & --- & weight of $Y_R$
\end{tabular}
\end{center}
\par \noindent {\it Error checking:}
If {\tt bpg}, {\tt dmflags} or {\tt stats} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void BPG_DMviaMaxFlow ( BPG *bpg, int dmflags[], int stats[],
int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{BPG_DMviaMaxFlow@{\tt BPG\_DMviaMaxFlow()}}
This method has the same functionality, calling sequence and
returned values as the preceding {\tt BPG\_DMdecomposition()} method.
\par \noindent {\it Error checking:}
If {\tt bpg}, {\tt dmflags} or {\tt stats} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:BPG:proto:IO}
\par
There are the usual eight IO routines.
The file structure of a {\tt BPG} object is simple:
the two scalar fields {\tt nX} and {\tt nY}
come first and the {\tt Graph} object follows.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BPG_readFromFile ( BPG *bpg, char *fn ) ;
\end{verbatim}
\index{BPG_readFromFile@{\tt BPG\_readFromFile()}}
\par
This method reads a {\tt BPG} object from a file.
The method tries to open the file and if it is successful,
it then calls {\tt BPG\_readFromFormattedFile()} or
{\tt BPG\_readFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt bpg} or {\tt fn} is {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.bpgf} (for a formatted file)
or {\tt *.bpgb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BPG_readFromFormattedFile ( BPG *bpg, FILE *fp ) ;
\end{verbatim}
\index{BPG_readFromFormattedFile@{\tt BPG\_readFromFormattedFile()}}
\par
This method reads a {\tt BPG} object from a formatted file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fscanf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt bpg} or {\tt fp} is {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BPG_readFromBinaryFile ( BPG *bpg, FILE *fp ) ;
\end{verbatim}
\index{BPG_readFromBinaryFile@{\tt BPG\_readFromBinaryFile()}}
\par
This method reads a {\tt BPG} object from a binary file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fread}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt bpg} or {\tt fp} is {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BPG_writeToFile ( BPG *bpg, char *fn ) ;
\end{verbatim}
\index{BPG_writeToFile@{\tt BPG\_writeToFile()}}
\par
This method writes a {\tt BPG} object to a file.
The method tries to open the file and if it is successful,
it then calls {\tt BPG\_writeFromFormattedFile()} or
{\tt BPG\_writeFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt bpg} or {\tt fn} is {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.bpgf} (for a formatted file)
or {\tt *.bpgb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BPG_writeToFormattedFile ( BPG *bpg, FILE *fp ) ;
\end{verbatim}
\index{BPG_writeToFormattedFile@{\tt BPG\_writeToFormattedFile()}}
\par
This method writes a {\tt BPG} object to a formatted file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fprintf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt bpg} or {\tt fp} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BPG_writeToBinaryFile ( BPG *bpg, FILE *fp ) ;
\end{verbatim}
\index{BPG_writeToBinaryFile@{\tt BPG\_writeToBinaryFile()}}
\par
This method writes a {\tt BPG} object to a binary file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fwrite}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt bpg} or {\tt fp} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BPG_writeForHumanEye ( BPG *bpg, FILE *fp ) ;
\end{verbatim}
\index{BPG_writeForHumanEye@{\tt BPG\_writeForHumanEye()}}
\par
This method writes a {\tt BPG} object to a file
in a human readable format.
The method {\tt BPG\_writeStats()}
is called to write out the
header and statistics.
Then the {\tt bpg->graph} object is written via a call to
{\tt Graph\_writeForHumanEye()}.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt bpg} or {\tt fp} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int BPG_writeStats ( BPG *bpg, FILE *fp ) ;
\end{verbatim}
\index{BPG_writeStats@{\tt BPG\_writeStats()}}
\par
This method writes a header with statistics to a file.
A header is written and the value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt bpg} or {\tt fp} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
BPG/doc/main.idx 0100644 0002055 0007177 00000002314 06647207107 0014711 0 ustar 00cleve compmath 0000040 0000006 \indexentry{BPG_new@{\tt BPG\_new()}}{3}
\indexentry{BPG_setDefaultFields@{\tt BPG\_setDefaultFields()}}{3}
\indexentry{BPG_clearData@{\tt BPG\_clearData()}}{3}
\indexentry{BPG_free@{\tt BPG\_free()}}{3}
\indexentry{BPG_init@{\tt BPG\_init()}}{4}
\indexentry{BPG_initFromColoring@{\tt BPG\_initFromColoring()}}{4}
\indexentry{BPG_makeGraphXbyX@{\tt BPG\_makeGraphXbyX()}}{4}
\indexentry{BPG_makeGraphYbyY@{\tt BPG\_makeGraphYbyY()}}{4}
\indexentry{BPG_pseudoperipheralnode@{\tt BPG\_pseudoperipheralnode()}}{4}
\indexentry{BPG_levelStructure@{\tt BPG\_levelStructure()}}{4}
\indexentry{BPG_DMdecomposition@{\tt BPG\_DMdecomposition()}}{5}
\indexentry{BPG_DMviaMaxFlow@{\tt BPG\_DMviaMaxFlow()}}{5}
\indexentry{BPG_readFromFile@{\tt BPG\_readFromFile()}}{5}
\indexentry{BPG_readFromFormattedFile@{\tt BPG\_readFromFormattedFile()}}{5}
\indexentry{BPG_readFromBinaryFile@{\tt BPG\_readFromBinaryFile()}}{6}
\indexentry{BPG_writeToFile@{\tt BPG\_writeToFile()}}{6}
\indexentry{BPG_writeToFormattedFile@{\tt BPG\_writeToFormattedFile()}}{6}
\indexentry{BPG_writeToBinaryFile@{\tt BPG\_writeToBinaryFile()}}{6}
\indexentry{BPG_writeForHumanEye@{\tt BPG\_writeForHumanEye()}}{6}
\indexentry{BPG_writeStats@{\tt BPG\_writeStats()}}{6}
BPG/doc/main.ind 0100644 0002055 0007177 00000001436 06535771246 0014711 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt BPG\_clearData()}, 4
\item {\tt BPG\_DMdecomposition()}, 5
\item {\tt BPG\_DMviaMaxFlow()}, 6
\item {\tt BPG\_free()}, 4
\item {\tt BPG\_init()}, 4
\item {\tt BPG\_initFromColoring()}, 4
\item {\tt BPG\_levelStructure()}, 5
\item {\tt BPG\_makeGraphXbyX()}, 5
\item {\tt BPG\_makeGraphYbyY()}, 5
\item {\tt BPG\_new()}, 4
\item {\tt BPG\_pseudoperipheralnode()}, 5
\item {\tt BPG\_readFromBinaryFile()}, 7
\item {\tt BPG\_readFromFile()}, 6
\item {\tt BPG\_readFromFormattedFile()}, 6
\item {\tt BPG\_setDefaultFields()}, 4
\item {\tt BPG\_writeForHumanEye()}, 7
\item {\tt BPG\_writeStats()}, 7
\item {\tt BPG\_writeToBinaryFile()}, 7
\item {\tt BPG\_writeToFile()}, 7
\item {\tt BPG\_writeToFormattedFile()}, 7
\end{theindex}
BPG/doc/main.ilg 0100644 0002055 0007177 00000000456 06535771246 0014713 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (20 entries accepted, 0 rejected).
Sorting entries....done (81 comparisons).
Generating output file main.ind....done (24 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
BPG/doc/makefile 0100644 0002055 0007177 00000000027 06542767330 0014761 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
Chv.h 0100644 0002055 0007177 00000000070 06573537536 0013002 0 ustar 00cleve compmath 0000040 0000006 #ifndef _Chv_
#define _Chv_
#include "Chv/Chv.h"
#endif
Chv/Chv.h 0100644 0002055 0007177 00000100050 06571276070 0013510 0 ustar 00cleve compmath 0000040 0000006 /* Chv.h */
#include "../SubMtx.h"
#include "../PatchAndGoInfo.h"
#include "../cfiles.h"
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
basic chevron object, double complex
id -- object's id
nD -- number of rows and columns in the diagonal (1,1) block
nL -- number of rows in the lower (2,1) block
nU -- number of columns in the upper (1,2) block
type -- type of chevron
SPOOLES_REAL --> chevron has real entries
SPOOLES_COMPLEX --> chevron has complex entries
symflag -- symmetry flag
SPOOLES_SYMMETRIC --> chevron is symmetric
SPOOLES_HERMITIAN --> chevron is hermitian
SPOOLES_NONSYMMETRIC --> chevron is nonsymmetric
rowind -- pointer to the row indices
colind -- pointer to the column indices
entries -- pointer to the entries
wrkDV -- working storage DV object
next -- next Chv in a singly linked list
--------------------------------------------------------------------
*/
typedef struct _Chv Chv ;
struct _Chv {
int id ;
int nD ;
int nL ;
int nU ;
int type ;
int symflag ;
int *rowind ;
int *colind ;
double *entries ;
DV wrkDV ;
Chv *next ;
} ;
#define CHV_IS_REAL(chv) ((chv)->type == SPOOLES_REAL)
#define CHV_IS_COMPLEX(chv) ((chv)->type == SPOOLES_COMPLEX)
#define CHV_IS_SYMMETRIC(chv) ((chv)->symflag == SPOOLES_SYMMETRIC)
#define CHV_IS_HERMITIAN(chv) ((chv)->symflag == SPOOLES_HERMITIAN)
#define CHV_IS_NONSYMMETRIC(chv) ((chv)->symflag == SPOOLES_NONSYMMETRIC)
/*
-------------------------------------------------
example of storage layout for indices and entries
nonsymmetric case, nD = 6, nL = 4, nU = 5
+---------------------------------------+
| 10 11 12 13 14 15 16 17 18 19 20 |
| +-----------------------------------+
| | +---------------------------------+
| 9 | | 9 10 11 12 13 14 15 16 17 18 19 |
| 8 | | 8 28 29 30 31 32 33 34 35 36 37 |
| 7 | | 7 27 45 46 47 48 49 50 51 52 53 |
| 6 | | 6 26 44 60 61 62 63 64 65 66 67 |
| 5 | | 5 25 43 59 73 74 75 76 77 78 79 |
| 4 | | 4 24 42 58 72 84 85 86 87 88 89 |
| 3 | | 3 23 41 57 71 83 +--------------+
| 2 | | 2 22 40 56 70 82 |
| 1 | | 1 21 39 55 69 81 |
| 0 | | 0 20 38 54 68 80 |
+---+ +------------------+
symmetric case, nD = 6, nU = 5
+---------------------------------+
| 0 1 2 3 4 5 6 7 8 9 10 |
+---------------------------------+
+---------------------------------+
| 0 1 2 3 4 5 6 7 8 9 10 |
| 11 12 13 14 15 16 17 18 19 20 |
| 21 22 23 44 25 26 27 28 29 |
| 30 31 32 33 34 35 36 37 |
| 38 39 40 41 42 43 44 |
| 45 46 47 48 49 50 |
+---------------------------------+
-------------------------------------------------
*/
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
simplest constructor
created -- 98apr30, cca
-----------------------
*/
Chv *
Chv_new (
void
) ;
/*
-----------------------
set the default fields
created -- 98apr30, cca
-----------------------
*/
void
Chv_setDefaultFields (
Chv *chv
) ;
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98apr30, cca
--------------------------------------------------
*/
void
Chv_clearData (
Chv *chv
) ;
/*
------------------------------------------
destructor, free's the object and its data
created -- 98apr30, cca
------------------------------------------
*/
void
Chv_free (
Chv *chv
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------
return the number of bytes needed to store the chevron
created -- 98apr30, cca
------------------------------------------------------
*/
int
Chv_nbytesNeeded (
int nD,
int nL,
int nU,
int type,
int symflag
) ;
/*
----------------------------------------------------------------
return the number of bytes in the workspace owned by this object
created -- 98apr30, cca
----------------------------------------------------------------
*/
int
Chv_nbytesInWorkspace (
Chv *chv
) ;
/*
----------------------------------------------------------------
set the number of bytes in the workspace owned by this object
created -- 98apr30, cca
----------------------------------------------------------------
*/
void
Chv_setNbytesInWorkspace (
Chv *chv,
int nbytes
) ;
/*
----------------------------
purpose -- set the fields
created -- 98apr30, cca
----------------------------
*/
void
Chv_setFields (
Chv *chv,
int id,
int nD,
int nL,
int nU,
int type,
int symflag
) ;
/*
----------------------------
purpose -- basic initializer
created -- 98apr30, cca
----------------------------
*/
void
Chv_init (
Chv *chv,
int id,
int nD,
int nL,
int nU,
int type,
int symflag
) ;
/*
------------------------------------
purpose -- initializer with pointers
created -- 98apr30, cca
------------------------------------
*/
void
Chv_initWithPointers (
Chv *chv,
int id,
int nD,
int nL,
int nU,
int type,
int symflag,
int *rowind,
int *colind,
double *entries
) ;
/*
-------------------------------------------------------------
purpose -- to initialize the object from its working storage,
used when the object is an MPI message
created -- 98apr30
-------------------------------------------------------------
*/
void
Chv_initFromBuffer (
Chv *chv
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in instance.c --------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------
return the id of the chevron
created -- 98apr30, cca
----------------------------
*/
int
Chv_id (
Chv *chv
) ;
/*
------------------------------------------------------------
return the type of the chevron
return value = SPOOLES_REAL --> chevron is real
return value = SPOOLES_COMPLEX --> chevron is complex
created -- 98apr30, cca
------------------------------------------------------------
*/
int
Chv_type (
Chv *chv
) ;
/*
---------------------------------------------------------------
return the symmetry flag of the chevron
return value = SPOOLES_SYMMETRIC --> chevron is symmetric
return value = SPOOLES_HERMITIAN --> chevron is hermitian
return value = SPOOLES_NONSYMMETRIC --> chevron is nonsymmetric
created -- 98apr30, cca
---------------------------------------------------------------
*/
int
Chv_symmetryFlag (
Chv *chv
) ;
/*
--------------------------------------------------
fill *pnD with nD, *pnL with nL, and *pnU with nU.
created -- 98apr30, cca
--------------------------------------------------
*/
void
Chv_dimensions (
Chv *chv,
int *pnD,
int *pnL,
int *pnU
) ;
/*
----------------------------------------------
fill *pnrow with nD + nL, *prowind with rowind
created -- 98apr30, cca
----------------------------------------------
*/
void
Chv_rowIndices (
Chv *chv,
int *pnrow,
int **prowind
) ;
/*
----------------------------------------------
fill *pncol with nD + nU, *pcolind with colind
created -- 98apr30, cca
----------------------------------------------
*/
void
Chv_columnIndices (
Chv *chv,
int *pncol,
int **pcolind
) ;
/*
----------------------------
return the number of entries
created -- 98apr30, cca
----------------------------
*/
int
Chv_nent (
Chv *chv
) ;
/*
--------------------------------------------
fill *pentries with a pointer to the entries
created -- 98apr30, cca
--------------------------------------------
*/
double *
Chv_entries(
Chv *chv
) ;
/*
-----------------------------------------
return the location of the diagonal entry
for the ichv'th chevron
created -- 98apr30, cca
-----------------------------------------
*/
double *
Chv_diagLocation(
Chv *chv,
int ichv
) ;
/*
----------------------------------------------
return a pointer to the start of the workspace
created -- 98apr30, cca
----------------------------------------------
*/
void *
Chv_workspace(
Chv *chv
) ;
/*
------------------------------------
fill *pValue with entry (irow, jcol)
created -- 98apr30, cca
------------------------------------
*/
void
Chv_realEntry (
Chv *chv,
int irow,
int jcol,
double *pValue
) ;
/*
--------------------------------------------
fill (*pReal,*pImag) with entry (irow, jcol)
created -- 98apr30, cca
--------------------------------------------
*/
void
Chv_complexEntry (
Chv *chv,
int irow,
int jcol,
double *pReal,
double *pImag
) ;
/*
-----------------------------------------------------
fill *ppValue with the location of entry (irow, jcol)
created -- 98apr30, cca
-----------------------------------------------------
*/
void
Chv_locationOfRealEntry (
Chv *chv,
int irow,
int jcol,
double **ppValue
) ;
/*
----------------------------------------------------------
fill (*ppReal,*ppImag) with location of entry (irow, jcol)
created -- 98apr30, cca
----------------------------------------------------------
*/
void
Chv_locationOfComplexEntry (
Chv *chv,
int irow,
int jcol,
double **ppReal,
double **ppImag
) ;
/*
------------------------------------
set entry (irow, jcol) to value
created -- 98apr30, cca
------------------------------------
*/
void
Chv_setRealEntry (
Chv *chv,
int irow,
int jcol,
double value
) ;
/*
--------------------------------------------
fill (*pReal,*pImag) with entry (irow, jcol)
created -- 98apr30, cca
--------------------------------------------
*/
void
Chv_setComplexEntry (
Chv *chv,
int irow,
int jcol,
double real,
double imag
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in update.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------------------
purpose -- perform the hermitian factor update
T_{\bnd{I} \cap J, \bnd{I} \cap J}
-= U_{I, \bnd{I} \cap J}^H D_{I, I} U_{I, \bnd{I} \cap J}
and
T_{\bnd{I} \cap J, \bnd{I} \cap \bnd{J}}
-= U_{I, \bnd{I} \cap J}^H D_{I, I} U_{I, \bnd{I} \cap \bnd{J}}
created -- 98apr17, cca
---------------------------------------------------------------------
*/
void
Chv_updateH (
Chv *chvT,
SubMtx *mtxD,
SubMtx *mtxU,
DV *tempDV
) ;
/*
---------------------------------------------------------------------
purpose -- perform the symmetric factor update
T_{\bnd{I} \cap J, \bnd{I} \cap J}
-= U_{I, \bnd{I} \cap J}^T D_{I, I} U_{I, \bnd{I} \cap J}
and
T_{\bnd{I} \cap J, \bnd{I} \cap \bnd{J}}
-= U_{I, \bnd{I} \cap J}^T D_{I, I} U_{I, \bnd{I} \cap \bnd{J}}
created -- 98apr17, cca
---------------------------------------------------------------------
*/
void
Chv_updateS (
Chv *chvT,
SubMtx *mtxD,
SubMtx *mtxU,
DV *tempDV
) ;
/*
---------------------------------------------------------------------
purpose -- perform the nonsymmetric factor update
T_{\bnd{I} \cap J, \bnd{I} \cap J}
-= L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J}
and
T_{\bnd{I} \cap J, \bnd{I} \cap \bnd{J}}
-= L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap \bnd{J}}
and
T_{\bnd{I} \cap \bnd{J}, \bnd{I} \cap J}
-= L_{\bnd{I} \cap \bnd{J}, I} D_{I, I} U_{I, \bnd{I} \cap J}
created -- 98feb27, cca
---------------------------------------------------------------------
*/
void
Chv_updateN (
Chv *chvT,
SubMtx *mtxL,
SubMtx *mtxD,
SubMtx *mtxU,
DV *tempDV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in factor.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------
purpose -- to factor the front without pivoting
return value -- # of eliminated rows and columns
created -- 98aug27, cca
------------------------------------------------
*/
int
Chv_factorWithNoPivoting (
Chv *chv,
PatchAndGoInfo *info
) ;
/*
------------------------------------------------------------------
purpose -- factor the pivot chevron with pivoting
ndelay -- number of delayed rows and columns
pivotflag -- enable pivoting or not
0 --> no pivoting
1 --> enable pivoting
pivotsizesIV -- IV object that holds the sizes of the pivots,
used only when the front is symmetric or hermitian
and pivoting is enabled
workDV -- DV object used for working storage, resized as necessary
tau -- upper bound on the magnitude of the entries
in the factors, used only when pivoting is enabled
pntest -- pointer to be incremented with the number of pivot tests
return value -- # of eliminated rows and columns
created -- 98aug27, cca
------------------------------------------------------------------
*/
int
Chv_factorWithPivoting (
Chv *chv,
int ndelay,
int pivotflag,
IV *pivotsizesIV,
DV *workDV,
double tau,
int *pntest
) ;
/*
---------------------------------------------------------
perform a rank one update using the first row and column.
this is used in the (L + I)D(I + U) factorization
return code ---
0 if the pivot was zero
1 if the pivot was nonzero
created -- 98jan23, cca
---------------------------------------------------------
*/
int
Chv_r1upd (
Chv *chv
) ;
/*
------------------------------------------------------------------
perform a rank two update using the first two rows.
used in the (U^T + I)D(I + U) and (U^H + I)D(I + U) factorizations
return code ---
0 if the pivot was zero
1 if the pivot was nonzero
created -- 98jan23, cca
------------------------------------------------------------------
*/
int
Chv_r2upd (
Chv *chv
) ;
/*
------------------------------------------------------------------
purpose -- looking at just a single chevron inside the Chv object,
find the absolute value of the diagonal element, and
the maximum absolute values of the offdiagonal elements
in the chevron's row and column.
created -- 98aug26, cca
------------------------------------------------------------------
*/
void
Chv_maxabsInChevron (
Chv *chv,
int ichv,
double *pdiagmaxabs,
double *prowmaxabs,
double *pcolmaxabs
) ;
/*
-------------------------------------------------------
purpose -- zero the offdiagonal entries of chevron ichv
created -- 98aug26, cca
-------------------------------------------------------
*/
void
Chv_zeroOffdiagonalOfChevron (
Chv *chv,
int ichv
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in swap.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
swap rows irow and jrow
created -- 98apr30, cca
-----------------------
*/
void
Chv_swapRows (
Chv *chv,
int irow,
int jrow
) ;
/*
--------------------------
swap columns icol and jcol
created -- 98apr30, cca
--------------------------
*/
void
Chv_swapColumns (
Chv *chv,
int icol,
int jcol
) ;
/*
-------------------------------
swap rows and columns ii and jj
created -- 98apr30, cca
-------------------------------
*/
void
Chv_swapRowsAndColumns (
Chv *chv,
int ii,
int jj
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in search.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------
find the first unmarked entry in
the diagonal with largest magnitude
if ( mark[jj] == tag ) then
we can compare this entry
endif
created -- 98apr30, cca
-----------------------------------
*/
int
Chv_maxabsInDiagonal11 (
Chv *chv,
int mark[],
int tag,
double *pmaxval
) ;
/*
--------------------------------------------
find the first unmarked entry in
row irow with largest magnitude
if ( colmark[jj] == tag ) then
we can examined this entry
endif
only entries in the (1,1) block are examined
created -- 98apr30, cca
--------------------------------------------
*/
int
Chv_maxabsInRow11 (
Chv *chv,
int irow,
int colmark[],
int tag,
double *pmaxval
) ;
/*
--------------------------------------------
find the first unmarked entry in
column jcol with largest magnitude
if ( rowmark[ii] == tag ) then
we can examined this entry
endif
only entries in the (1,1) block are examined
created -- 98apr30, cca
--------------------------------------------
*/
int
Chv_maxabsInColumn11 (
Chv *chv,
int jcol,
int rowmark[],
int tag,
double *pmaxval
) ;
/*
--------------------------------------
return the location of the first entry
with largest magnitude in row irow.
*pmaxval is filled with its magnitude.
created -- 98apr30, cca
--------------------------------------
*/
int
Chv_maxabsInRow (
Chv *chv,
int irow,
double *pmaxval
) ;
/*
--------------------------------------
return the location of the first entry
with largest magnitude in column jcol.
*pmaxval is filled with its magnitude.
created -- 98apr30, cca
--------------------------------------
*/
int
Chv_maxabsInColumn (
Chv *chv,
int jcol,
double *pmaxval
) ;
/*
-------------------------------------------------------------
return the magnitude of a quasimax entry from the unmarked
rows and columns and fill *pirow and *pjcol with its location
created -- 98apr30, cca
-------------------------------------------------------------
*/
double
Chv_quasimax (
Chv *chv,
int rowmark[],
int colmark[],
int tag,
int *pirow,
int *pjcol
) ;
/*
---------------------------------------------------------------
find a 1x1 or 2x2 pivot using the fast Bunch-Parlett algorithm.
used only with symmetric chevrons.
created -- 98apr30, cca
---------------------------------------------------------------
*/
void
Chv_fastBunchParlettPivot (
Chv *chv,
int mark[],
int tag,
int *pirow,
int *pjcol
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in findPivot.c -------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------------
purpose -- find and test a pivot
workDV -- object that contains work vectors
tau -- upper bound on magnitude of factor entries
ndelay -- number of delayed rows and columns on input
pirow -- pointer to be filled with pivot row
pjcol -- pointer to be filled with pivot column
pntest -- pointer to be incremented with the number of pivot tests
return value -- size of pivot
0 --> pivot not found
1 --> 1x1 pivot in row *pirow and column *pjcol
2 --> 2x2 pivot in rows and columns *pirow and *pjcol,
symmetric front only
created -- 98jan24, cca
------------------------------------------------------------------
*/
int
Chv_findPivot (
Chv *chv,
DV *workDV,
double tau,
int ndelay,
int *pirow,
int *pjcol,
int *pntest
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in fill.c ------------------------------------------
------------------------------------------------------------------------
*/
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in assemble.c --------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------------
add a scaled multiple of a simple chevron to a Chv object.
the indices are offsets.
note: for this purpose, (assembling original entries into the
matrix), the row and column indices of the chevron are identical.
also, the indices of both the Chv object and the chvind[]
vector are assumed to be in ascending order.
created -- 98apr30, cca
-----------------------------------------------------------------
*/
void
Chv_addChevron (
Chv *chv,
double alpha[],
int ichv,
int chvsize,
int chvind[],
double chvent[]
) ;
/*
--------------------------------------------------------------
assemble Chv object chvI into Chv object chvJ.
note: the two objects must be of the same symmetry type,
the row indices of chvI must nest into those of chvJ,
the column indices of chvI must nest into those of chvJ.
created -- 98apr30, cca
--------------------------------------------------------------
*/
void
Chv_assembleChv (
Chv *chvJ,
Chv *chvI
) ;
/*
----------------------------------------------------------------
purpose -- assemble the postponed data from the children
newchv -- Chv object to contain fully assembled front
oldchv -- Chv object that contains former front
firstchild -- pointer to first child in the list of children
Chv objects to be merged into the new front
return value -- # of delayed rows and columns added to the front
created -- 98apr30, cca
----------------------------------------------------------------
*/
int
Chv_assemblePostponedData (
Chv *newchv,
Chv *oldchv,
Chv *firstchild
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in copy.c ------------------------------------------
------------------------------------------------------------------------
*/
#define CHV_STRICT_LOWER 1
#define CHV_DIAGONAL 2
#define CHV_STRICT_UPPER 3
#define CHV_STRICT_LOWER_11 4
#define CHV_LOWER_21 5
#define CHV_STRICT_UPPER_11 6
#define CHV_UPPER_12 7
#define CHV_BY_ROWS 0
#define CHV_BY_COLUMNS 1
/*
-------------------------------------------------------------------
purpose -- copy entries to a vector.
length -- length of dvec[]
npivot -- number of pivots, may be 0
pivotsizes -- vector of pivot sizes, may be NULL
dvec[] -- vector to receive matrix entries
copyflag -- flag to denote what part of the entries to copy
CHV_STRICT_LOWER --> copy strict lower entries
CHV_DIAGONAL --> copy diagonal entries
CHV_STRICT_UPPER --> copy strict upper entries
CHV_STRICT_LOWER_11 --> copy strict lower entries in (1,1) block
CHV_LOWER_21 --> copy lower entries in (2,1) block
CHV_STRICT_UPPER_11 --> copy strict upper entries in (1,1) block
CHV_UPPER_12 --> copy upper entries in (1,2) block
storeflag -- flag to denote how to store entries in dvec[]
CHV_BY_ROWS --> store by rows
CHV_BY_COLUMNS --> store by columns
return value -- number of entries copied
created -- 97jun05, cca
modified -- 98feb27, cca
cases 4-7 inserted
-------------------------------------------------------------------
*/
int
Chv_copyEntriesToVector (
Chv *chv,
int npivot,
int pivotsizes[],
int length,
double *dvec,
int copyflag,
int storeflag
) ;
/*
-------------------------------------------------------------------
purpose -- copy large entries to a vector. the portion copied
can be a union of the strict lower portion,
the diagonal portion, and the strict upper
portion. there is one restriction, if the strict
lower and strict upper are to be copied, the
diagonal will also be copied.
npivot -- number of pivots, may be 0
pivotsizes -- vector of pivot sizes, may be NULL
sizes[] -- vector to receive row/column sizes
ivec[] -- vector to receive row/column indices
dvec[] -- vector to receive matrix entries
copyflag -- flag to denote what part of the entries to copy
CHV_STRICT_LOWER --> copy strict lower entries
CHV_STRICT_UPPER --> copy strict upper entries
CHV_STRICT_LOWER_11 --> copy strict lower entries in (1,1) block
CHV_LOWER_21 --> copy lower entries in (2,1) block
CHV_STRICT_UPPER_11 --> copy strict upper entries in (1,1) block
CHV_UPPER_12 --> copy upper entries in (1,2) block
storeflag -- flag to denote how to store entries in dvec[]
CHV_BY_ROWS --> store by rows
CHV_BY_COLUMNS --> store by columns
droptol -- entry to be copied must be larger than this magnitude
return value -- number of entries copied
created -- 97jun05, cca
modified -- 97feb27, cca
cases 4-7 inserted
-------------------------------------------------------------------
*/
int
Chv_copyBigEntriesToVector (
Chv *chv,
int npivot,
int pivotsizes[],
int sizes[],
int ivec[],
double dvec[],
int copyflag,
int storeflag,
double droptol
) ;
/*
-------------------------------------------------------------------
purpose -- return the number of entries
in a portion of the object
countflag -- which entries to count
CHV_STRICT_LOWER --> copy strict lower entries
CHV_STRICT_UPPER --> copy strict upper entries
CHV_STRICT_LOWER_11 --> copy strict lower entries in (1,1) block
CHV_LOWER_21 --> copy lower entries in (2,1) block
CHV_STRICT_UPPER_11 --> copy strict upper entries in (1,1) block
CHV_UPPER_12 --> copy upper entries in (1,2) block
created -- 98feb27, cca
-------------------------------------------------------------------
*/
int
Chv_countEntries (
Chv *chv,
int npivot,
int pivotsizes[],
int countflag
) ;
/*
-------------------------------------------------------------------
purpose -- return the number of entries
whose magnitude is larger than droptol.
countflag -- which entries to count
CHV_STRICT_LOWER --> copy strict lower entries
CHV_STRICT_UPPER --> copy strict upper entries
CHV_STRICT_LOWER_11 --> copy strict lower entries in (1,1) block
CHV_LOWER_21 --> copy lower entries in (2,1) block
CHV_STRICT_UPPER_11 --> copy strict upper entries in (1,1) block
CHV_UPPER_12 --> copy upper entries in (1,2) block
created -- 97jun07, cca
modified -- 98feb27, cca
cases 4-7 inserted
-------------------------------------------------------------------
*/
int
Chv_countBigEntries (
Chv *chv,
int npivot,
int pivotsizes[],
int countflag,
double droptol
) ;
/*
----------------------------------------------------------
purpose -- copy the trailing chevron that starts at offset
created -- 97may16, cca
----------------------------------------------------------
*/
void
Chv_copyTrailingPortion (
Chv *chvI,
Chv *chvJ,
int offset
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in util.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------------
shift the indices, entries and adjust the nD dimension.
note: shift can be positive or negative
created -- 98apr30, cca
-------------------------------------------------------
*/
void
Chv_shift (
Chv *chv,
int shift
) ;
/*
----------------------------------------------------------
return the maximum magnitude of the entries in the chevron
created -- 98apr30, cca
----------------------------------------------------------
*/
double
Chv_maxabs (
Chv *chv
) ;
/*
-------------------------------------------------------
return the frobenius norm of the entries in the chevron
created -- 98apr30, cca
-------------------------------------------------------
*/
double
Chv_frobNorm (
Chv *chv
) ;
/*
-----------------------
subtract chvI from chvJ
created -- 98apr30, cca
-----------------------
*/
void
Chv_sub (
Chv *chvJ,
Chv *chvI
) ;
/*
-------------------------------
zero the entries in the chevron
created -- 98apr30, cca
-------------------------------
*/
void
Chv_zero (
Chv *chv
) ;
/*
-------------------------------
fill A2 object with (1,1) block
created -- 98apr30, cca
-------------------------------
*/
void
Chv_fill11block (
Chv *chv,
A2 *mtx
) ;
/*
-------------------------------
fill A2 object with (1,2) block
created -- 98apr30, cca
-------------------------------
*/
void
Chv_fill12block (
Chv *chv,
A2 *mtx
) ;
/*
-------------------------------
fill A2 object with (2,1) block
created -- 98apr30, cca
-------------------------------
*/
void
Chv_fill21block (
Chv *chv,
A2 *mtx
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in IO.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
created -- 98apr30, cca
----------------------------------------
*/
void
Chv_writeForHumanEye (
Chv *chv,
FILE *fp
) ;
/*
------------------------------------------------
purpose -- write out the entries in matlab style
created -- 98apr30, cca
------------------------------------------------
*/
void
Chv_writeForMatlab (
Chv *chv,
char *chvname,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
of a simple chevron to a Chv object.
the indices are offsets.
note: for this purpose, (assembling original entries into the
matrix), the row and column indices of the chevron are identical.
also, the indices of both the Chv object and the chvind[]
vector are assumed to be in ascending order.
created -- 98apr30, cca
-----------------------------------------------------------------
*/
void
Chv_addChevron (
Chv *chv,
double alpha[],
Chv/makefile 0100644 0002055 0007177 00000000223 06636223545 0014321 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd drivers ; make clean
cd src ; make clean
cd doc ; make clean
Chv/src/makefile 0100644 0002055 0007177 00000001222 06636021277 0015106 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = Chv
$(OBJ).a : \
$(OBJ).a(assemble.o) \
$(OBJ).a(basics.o) \
$(OBJ).a(copy.o) \
$(OBJ).a(factor.o) \
$(OBJ).a(findPivot.o) \
$(OBJ).a(init.o) \
$(OBJ).a(instance.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(search.o) \
$(OBJ).a(swap.o) \
$(OBJ).a(update.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
Chv/src/makeGlobalLib 0100644 0002055 0007177 00000001006 06600260751 0016007 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = Chv
SRC = assemble.c \
basics.c \
copy.c \
factor.c \
findPivot.c \
init.c \
instance.c \
IO.c \
search.c \
swap.c \
update.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
Chv/src/IO.c 0100644 0002055 0007177 00000014111 06571267314 0014064 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../Chv.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
created -- 98apr30, cca
----------------------------------------
*/
void
Chv_writeForHumanEye (
Chv *chv,
FILE *fp
) {
A2 mtx ;
int ierr, ncol, nD, nL, nrow, nU ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in Chv_writeForHumanEye(%p,%p)"
"\n bad input\n", chv, fp) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
fprintf(fp,
"\n Chv object at address %p"
"\n id = %d, nD = %d, nL = %d, nU = %d, type = %d, symflag = %d",
chv, chv->id, nD, nL, nU, chv->type, chv->symflag) ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) ) {
fprintf(fp, "\n chv is real and symmetric") ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
fprintf(fp, "\n chv is real and nonsymmetric") ;
} else {
fprintf(fp, "\n chv has unknown symmetry type %d", chv->symflag) ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) ) {
fprintf(fp, "\n chv is complex and symmetric") ;
} else if ( CHV_IS_HERMITIAN(chv) ) {
fprintf(fp, "\n chv is complex and hermitian") ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
fprintf(fp, "\n chv is complex and nonsymmetric") ;
} else {
fprintf(fp, "\n chv has unknown symmetry type %d", chv->symflag) ;
}
} else {
fprintf(fp, "\n chv has unknown type %d", chv->type) ;
}
Chv_rowIndices(chv, &nrow, &rowind) ;
if ( nrow > 0 && rowind != NULL ) {
fprintf(fp, "\n chv's row indices at %p", rowind) ;
IVfp80(fp, nrow, rowind, 80, &ierr) ;
}
Chv_columnIndices(chv, &ncol, &colind) ;
if ( ncol > 0 && colind != NULL ) {
fprintf(fp, "\n chv's column indices at %p", colind) ;
IVfp80(fp, ncol, colind, 80, &ierr) ;
}
/*
--------------------
load the (1,1) block
--------------------
*/
A2_setDefaultFields(&mtx) ;
Chv_fill11block(chv, &mtx) ;
fprintf(fp, "\n (1,1) block") ;
A2_writeForHumanEye(&mtx, fp) ;
if ( nU > 0 ) {
/*
--------------------
load the (1,2) block
--------------------
*/
Chv_fill12block(chv, &mtx) ;
fprintf(fp, "\n (1,2) block") ;
A2_writeForHumanEye(&mtx, fp) ;
}
if ( nL > 0 && CHV_IS_NONSYMMETRIC(chv) == 1 ) {
/*
--------------------
load the (2,1) block
--------------------
*/
Chv_fill21block(chv, &mtx) ;
fprintf(fp, "\n (2,1) block") ;
A2_writeForHumanEye(&mtx, fp) ;
}
A2_clearData(&mtx) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------
purpose -- write out the entries in matlab style
created -- 98apr30, cca
------------------------------------------------
*/
void
Chv_writeForMatlab (
Chv *chv,
char *chvname,
FILE *fp
) {
int irow, jcol, ncol, nD, nL, nrow, nU ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || chvname == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in Chv_writeForMatlab(%p,%p,%p)"
"\n bad input\n", chv, chvname, fp) ;
exit(-1) ;
}
if ( ! (CHV_IS_REAL(chv) || CHV_IS_COMPLEX(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_writeForMatlab(%p,%p,%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, chvname, fp, chv->type) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
Chv_rowIndices(chv, &nrow, &rowind) ;
Chv_columnIndices(chv, &ncol, &colind) ;
if ( CHV_IS_REAL(chv) ) {
double value ;
/*
-------------------------
write out the (1,1) block
-------------------------
*/
for ( irow = 0 ; irow < nD ; irow++ ) {
for ( jcol = 0 ; jcol < nD ; jcol++ ) {
Chv_realEntry(chv, irow, jcol, &value) ;
fprintf(fp, "\n %s(%d,%d) = %20.12e ;",
chvname, 1+rowind[irow], 1+colind[jcol], value) ;
}
}
/*
-------------------------
write out the (1,2) block
-------------------------
*/
for ( irow = 0 ; irow < nD ; irow++ ) {
for ( jcol = nD ; jcol < ncol ; jcol++ ) {
Chv_realEntry(chv, irow, jcol, &value) ;
fprintf(fp, "\n %s(%d,%d) = %20.12e ;",
chvname, 1+rowind[irow], 1+colind[jcol], value) ;
}
}
/*
-------------------------
write out the (2,1) block
-------------------------
*/
for ( irow = nD ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < nD ; jcol++ ) {
Chv_realEntry(chv, irow, jcol, &value) ;
fprintf(fp, "\n %s(%d,%d) = %20.12e ;",
chvname, 1+rowind[irow], 1+colind[jcol], value) ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
double imag, real ;
/*
-------------------------
write out the (1,1) block
-------------------------
*/
for ( irow = 0 ; irow < nD ; irow++ ) {
for ( jcol = 0 ; jcol < nD ; jcol++ ) {
Chv_complexEntry(chv, irow, jcol, &real, &imag) ;
fprintf(fp, "\n %s(%d,%d) = %20.12e + %20.12e*i;",
chvname, 1+rowind[irow], 1+colind[jcol],
real, imag) ;
}
}
/*
-------------------------
write out the (1,2) block
-------------------------
*/
for ( irow = 0 ; irow < nD ; irow++ ) {
for ( jcol = nD ; jcol < ncol ; jcol++ ) {
Chv_complexEntry(chv, irow, jcol, &real, &imag) ;
fprintf(fp, "\n %s(%d,%d) = %20.12e + %20.12e*i;",
chvname, 1+rowind[irow], 1+colind[jcol],
real, imag) ;
}
}
/*
-------------------------
write out the (2,1) block
-------------------------
*/
for ( irow = nD ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < nD ; jcol++ ) {
Chv_complexEntry(chv, irow, jcol, &real, &imag) ;
fprintf(fp, "\n %s(%d,%d) = %20.12e + %20.12e*i;",
chvname, 1+rowind[irow], 1+colind[jcol],
real, imag) ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
--------------------------------*/
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
created -- 98apr30, cca
----------------------------------------
*/
void
Chv_writeForHumanEye (
Chv *chv,
FILE *fp
) {
A2 mtx ;
int ierr, ncol, nD, nL, nrow, nU ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
iChv/src/assemble.c 0100644 0002055 0007177 00000054352 06603215130 0015344 0 ustar 00cleve compmath 0000040 0000006 /* assemble.c */
#include "../Chv.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------------
add a scaled multiple of a simple chevron to a Chv object.
the indices are offsets.
note: for this purpose, (assembling original entries into the
matrix), the row and column indices of the chevron are identical.
also, the indices of both the Chv object and the chvind[]
vector are assumed to be in ascending order.
created -- 98apr30, cca
-----------------------------------------------------------------
*/
void
Chv_addChevron (
Chv *chv,
double alpha[],
int ichv,
int chvsize,
int chvind[],
double chvent[]
) {
int ii, iloc, jcol, jj, jjfirst, jjlast,
ncol, nD, nL, nU, offset ;
int *colind ;
double *diag ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || ichv < 0 || chvsize < 0
|| chvind == NULL || chvent == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_addChevron(%p,%p,%d,%d,%p,%p)"
"\n bad input\n",
chv, alpha, ichv, chvsize, chvind, chvent) ;
exit(-1) ;
}
switch ( chv->type ) {
case SPOOLES_REAL :
switch ( chv->symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_NONSYMMETRIC :
break ;
default :
fprintf(stderr, "\n fatal error in Chv_addChevron()"
"\n type is SPOOLES_REAL, symflag = %d"
"\n must be SPOOLES_SYMMETRIC or SPOOLES_NONSYMMETRIC\n",
chv->symflag) ;
exit(-1) ;
break ;
}
case SPOOLES_COMPLEX :
switch ( chv->symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
case SPOOLES_NONSYMMETRIC :
break ;
default :
fprintf(stderr, "\n fatal error in Chv_addChevron()"
"\n type is SPOOLES_REAL, symflag = %d"
"\n must be SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN"
"\n or SPOOLES_NONSYMMETRIC\n",
chv->symflag) ;
exit(-1) ;
break ;
}
break ;
default :
fprintf(stderr, "\n fatal error in Chv_addChevron()"
"\n type is %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv->type) ;
exit(-1) ;
break ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n alpha = %f, ichv = %d, chvsize = %d",
alpha, ichv, chvsize) ;
#endif
if ( chvsize == 0
|| (CHV_IS_REAL(chv) && alpha[0] == 0.0)
|| (CHV_IS_COMPLEX(chv) && (alpha[0] == 0.0 && alpha[1] == 0.0)) ) {
/*
----------------------------
quick return, nothing to add
----------------------------
*/
return ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n Chv_addChevron(%d): ", ichv) ;
IVfprintf(stdout, chvsize, chvind) ;
DVfprintf(stdout, chvsize, chvent) ;
fflush(stdout) ;
#endif
Chv_dimensions(chv, &nD, &nL, &nU) ;
Chv_columnIndices(chv, &ncol, &colind) ;
/*
-------------------------------------
locate the chevron in the Chv object
that will accumulate these entries
-------------------------------------
*/
for ( iloc = 0 ; iloc < nD ; iloc++ ) {
if ( colind[iloc] == ichv ) {
break ;
}
}
if ( iloc == nD ) {
/*
--------------------------------------------
unable to assemble these entries, error exit
--------------------------------------------
*/
fprintf(stderr, "\n fatal error in Chv_addChevron(%p,%d,%d,%p,%p)"
"\n chevron id %d not found in colind[]",
chv, ichv, chvsize, chvind, chvent, ichv) ;
exit(-1) ;
}
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
/*
---------------------
symmetric chevron
get the local indices
---------------------
*/
jjlast = nD + nU - 1 ;
for ( ii = 0, jj = iloc ; ii < chvsize ; ii++ ) {
if ( (offset = chvind[ii]) < 0 ) {
fprintf(stderr,
"\n fatal error in Chv_addChevron(%p,%d,%d,%p,%p)"
"\n ii %d, negative offset %d\n",
chv, ichv, chvsize, chvind, chvent, ii, chvind[ii]) ;
IVfprintf(stderr, chvsize, chvind) ;
exit(-1) ;
}
jcol = ichv + offset ;
#if MYDEBUG > 0
fprintf(stdout, "\n ii = %d, offset = %d, jcol = %d",
ii, offset, jcol) ;
fflush(stdout) ;
#endif
while ( jj <= jjlast && jcol != colind[jj] ) {
jj++ ;
}
#if MYDEBUG > 0
fprintf(stdout, ", jj = %d", jj) ;
fflush(stdout) ;
#endif
if ( jj > jjlast ) {
fprintf(stderr,
"\n fatal error in Chv_addChevron(%p,%d,%d,%p,%p)"
"\n jcol %d not found in colind[]\n",
chv, ichv, chvsize, chvind, chvent, jcol) ;
fprintf(stderr, "\n colind") ;
IVfprintf(stderr, ncol, colind) ;
fprintf(stderr, "\n chvind") ;
IVfprintf(stderr, chvsize, chvind) ;
exit(-1) ;
}
chvind[ii] = jj ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n local indices") ;
IVfprintf(stdout, chvsize, chvind) ;
fflush(stdout) ;
#endif
/*
--------------------
assemble the chevron
--------------------
*/
if ( CHV_IS_REAL(chv) ) {
diag = Chv_diagLocation(chv, iloc) - iloc ;
#if MYDEBUG > 0
fprintf(stdout, "\n ichv = %d, iloc = %d, diag = %p"
"\n chv->entries = %p, diag - chv->entries = %d",
ichv, iloc, diag, chv->entries,
diag - chv->entries) ;
fflush(stdout) ;
#endif
if ( alpha[0] == 1.0 ) {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n location %d",
&diag[chvind[ii]] - chv->entries) ;
fflush(stdout) ;
#endif
diag[chvind[ii]] += chvent[ii] ;
}
} else {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
diag[chvind[ii]] += alpha[0]*chvent[ii] ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
diag = Chv_diagLocation(chv, iloc) - 2*iloc ;
#if MYDEBUG > 0
fprintf(stdout, "\n ichv = %d, iloc = %d, diag = %p"
"\n chv->entries = %p, diag - chv->entries = %d",
ichv, iloc, diag, chv->entries,
diag - chv->entries) ;
fflush(stdout) ;
#endif
if ( alpha[0] == 1.0 && alpha[1] == 0.0 ) {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n location %d",
&diag[chvind[ii]] - chv->entries) ;
fflush(stdout) ;
#endif
diag[2*chvind[ii]] += chvent[2*ii] ;
diag[2*chvind[ii]+1] += chvent[2*ii+1] ;
}
} else if ( alpha[0] != 0.0 && alpha[1] == 0.0 ) {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
diag[2*chvind[ii]] += alpha[0]*chvent[2*ii] ;
diag[2*chvind[ii]+1] += alpha[0]*chvent[2*ii+1] ;
}
} else if ( CHV_IS_SYMMETRIC(chv) ) {
double alphareal, alphaimag, xreal, ximag ;
for ( ii = 0 ; ii < chvsize ; ii++ ) {
alphareal = alpha[0] ; alphaimag = alpha[1] ;
xreal = chvent[2*ii] ; ximag = chvent[2*ii+1] ;
diag[2*chvind[ii]] += alphareal*xreal - alphaimag*ximag ;
diag[2*chvind[ii]+1] += alphareal*ximag + alphaimag*xreal ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_addChevron()"
"\n chevron is hermitian, but the scalar has nonzero imaginary part"
"\n sum is no longer hermitian\n") ;
exit(-1) ;
}
}
/*
------------------------------------
restore the indices to their offsets
------------------------------------
*/
for ( ii = 0 ; ii < chvsize ; ii++ ) {
chvind[ii] = colind[chvind[ii]] - ichv ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n restored indices") ;
IVfprintf(stdout, chvsize, chvind) ;
fflush(stdout) ;
#endif
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
-----------------------------------------
nonsymmetric chevron, symmetric structure
overwrite chvind[] with local indices
-----------------------------------------
*/
jjfirst = iloc ;
jjlast = nD + nU - 1 ;
for ( ii = 0, jj = jjlast ; ii < chvsize ; ii++ ) {
if ( (offset = chvind[ii]) >= 0 ) {
break ;
}
jcol = ichv - offset ;
while ( jj >= jjfirst && jcol != colind[jj] ) {
jj-- ;
}
if ( jj < jjfirst ) {
fprintf(stderr,
"\n fatal error in Chv_addChevron(%p,%d,%d,%p,%p)"
"\n jcol %d not found in colind[]\n",
chv, ichv, chvsize, chvind, chvent, jcol) ;
exit(-1) ;
}
chvind[ii] = -jj + iloc ;
}
for ( jj = jjfirst ; ii < chvsize ; ii++ ) {
jcol = ichv + chvind[ii] ;
while ( jj <= jjlast && jcol != colind[jj] ) {
jj++ ;
}
if ( jj > jjlast ) {
fprintf(stderr,
"\n fatal error in Chv_addChevron(%p,%d,%d,%p,%p)"
"\n jcol %d not found in colind[]\n",
chv, ichv, chvsize, chvind, chvent, jcol) ;
exit(-1) ;
}
chvind[ii] = jj - iloc ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n local indices") ;
IVfprintf(stdout, chvsize, chvind) ;
fflush(stdout) ;
#endif
/*
--------------------
assemble the chevron
--------------------
*/
diag = Chv_diagLocation(chv, iloc) ;
#if MYDEBUG > 0
fprintf(stdout, "\n ichv = %d, iloc = %d, diag = %p"
"\n chv->entries = %p, diag - chv->entries = %d",
ichv, iloc, diag, chv->entries,
diag - chv->entries) ;
fflush(stdout) ;
#endif
if ( CHV_IS_REAL(chv) ) {
if ( alpha[0] == 1.0 ) {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n diag[%d] += %12.4e, ii = %d",
chvind[ii], chvent[ii], ii) ;
fflush(stdout) ;
#endif
diag[chvind[ii]] += chvent[ii] ;
}
} else {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n diag[%d] += %12.4e, ii = %d",
chvind[ii], chvent[ii], ii) ;
fflush(stdout) ;
#endif
diag[chvind[ii]] += alpha[0] * chvent[ii] ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( alpha[0] == 1.0 && alpha[1] == 0.0 ) {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n diag[%d] += %12.4e, ii = %d",
chvind[ii], chvent[ii], ii) ;
fflush(stdout) ;
#endif
diag[2*chvind[ii]] += chvent[2*ii] ;
diag[2*chvind[ii]+1] += chvent[2*ii+1] ;
}
} else if ( alpha[0] != 1.0 && alpha[1] == 0.0 ) {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
diag[2*chvind[ii]] += alpha[0] * chvent[2*ii] ;
diag[2*chvind[ii]+1] += alpha[0] * chvent[2*ii+1] ;
}
} else {
double alphareal, alphaimag, xreal, ximag ;
for ( ii = 0 ; ii < chvsize ; ii++ ) {
alphareal = alpha[0] ; alphaimag = alpha[1] ;
xreal = chvent[2*ii] ; ximag = chvent[2*ii+1] ;
diag[2*chvind[ii]] += alphareal*xreal - alphaimag*ximag ;
diag[2*chvind[ii]+1] += alphareal*ximag + alphaimag*xreal ;
}
}
}
/*
------------------------------------
restore the indices to their offsets
------------------------------------
*/
for ( ii = 0 ; ii < chvsize ; ii++ ) {
if ( chvind[ii] < 0 ) {
chvind[ii] = ichv - colind[iloc - chvind[ii]] ;
} else {
chvind[ii] = colind[chvind[ii] + iloc] - ichv ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n restored indices") ;
IVfprintf(stdout, chvsize, chvind) ;
fflush(stdout) ;
#endif
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
assemble Chv object chvI into Chv object chvJ.
note: the two objects must be of the same symmetry type,
the row indices of chvI must nest into those of chvJ,
the column indices of chvI must nest into those of chvJ.
created -- 98apr30, cca
--------------------------------------------------------------
*/
void
Chv_assembleChv (
Chv *chvJ,
Chv *chvI
) {
double *diagI, *diagJ ;
int ii, ichvI, ichvJ, jj, ncolI, ncolJ, nDI, nDJ,
nLI, nLJ, nrowI, nrowJ, nUI, nUJ, offset ;
int *colindJ, *colindI, *rowindI, *rowindJ ;
/*
---------------
check the input
---------------
*/
if ( chvJ == NULL || chvI == NULL ) {
fprintf(stderr, "\n fatal error in Chv_assembleChv(%p,%p)"
"\n bad input\n", chvJ, chvI) ;
exit(-1) ;
}
if ( !(CHV_IS_SYMMETRIC(chvI)
|| CHV_IS_HERMITIAN(chvI)
|| CHV_IS_NONSYMMETRIC(chvI) ) ) {
fprintf(stderr, "\n fatal error in Chv_assembleChv(%p,%p)"
"\n bad symflag %d\n", chvJ, chvI, chvI->symflag) ;
exit(-1) ;
}
if ( chvI->symflag != chvJ->symflag ) {
fprintf(stderr, "\n fatal error in Chv_assembleChv(%p,%p)"
"\n chvI->symflag = %d, chvJ->symflag = %d\n",
chvJ, chvI, chvI->symflag, chvJ->symflag) ;
exit(-1) ;
}
/*
-------------------------------------
get the dimensions of the two objects
-------------------------------------
*/
Chv_dimensions(chvJ, &nDJ, &nLJ, &nUJ) ;
Chv_dimensions(chvI, &nDI, &nLI, &nUI) ;
if ( nDI + nLI > nDJ + nLJ || nDI + nUI > nDJ + nUJ ) {
fprintf(stderr, "\n fatal error in Chv_assembleChv(%p,%p)"
"\n bad dimensions"
"\n nDI = %d, nLI = %d, nUI = %d"
"\n nDI = %d, nLI = %d, nUI = %d",
chvJ, chvI, nDI, nLI, nUI, nDJ, nLJ, nUJ) ;
exit(-1) ;
}
/*
-----------------
get the local ids
-----------------
*/
Chv_columnIndices(chvJ, &ncolJ, &colindJ) ;
Chv_columnIndices(chvI, &ncolI, &colindI) ;
#if MYDEBUG > 0
fprintf(stdout, "\n colindI") ;
IVfprintf(stdout, ncolI, colindI) ;
fprintf(stdout, "\n colindJ") ;
IVfprintf(stdout, ncolJ, colindJ) ;
#endif
for ( ii = 0, jj = 0 ; ii < ncolI ; ii++ ) {
while ( jj < ncolJ && colindI[ii] != colindJ[jj] ) {
#if MYDEBUG > 0
fprintf(stdout, "\n colindI[%d] = %d, colindJ[%d] = %d",
ii, colindI[ii], jj, colindJ[jj]) ;
#endif
jj++ ;
}
if ( jj == ncolJ ) {
break ;
}
colindI[ii] = jj ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n local column indices") ;
IVfprintf(stdout, ncolI, colindI) ;
#endif
if ( jj == ncolJ ) {
fprintf(stderr, "\n fatal error in Chv_assembleChv(%p,%p)"
"\n column indicesI do not nest in indicesJ\n", chvJ, chvI) ;
fprintf(stderr, "\n colindI") ;
IVfprintf(stderr, ncolI, colindI) ;
fprintf(stderr, "\n colindJ") ;
IVfprintf(stderr, ncolJ, colindJ) ;
exit(-1) ;
}
if ( CHV_IS_SYMMETRIC(chvJ) || CHV_IS_HERMITIAN(chvJ) ) {
/*
-------------------
symmetric structure
-------------------
*/
nrowI = ncolI ;
rowindI = colindI ;
} else if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
/*
----------------------
nonsymmetric structure
----------------------
*/
Chv_rowIndices(chvJ, &nrowJ, &rowindJ) ;
Chv_rowIndices(chvI, &nrowI, &rowindI) ;
#if MYDEBUG > 0
fprintf(stdout, "\n rowindI") ;
IVfprintf(stdout, nrowI, rowindI) ;
fprintf(stdout, "\n rowindJ") ;
IVfprintf(stdout, nrowJ, rowindJ) ;
#endif
for ( ii = 0, jj = 0 ; ii < nrowI ; ii++ ) {
while ( jj < nrowJ && rowindI[ii] != rowindJ[jj] ) {
jj++ ;
}
if ( jj == nrowJ ) {
break ;
}
rowindI[ii] = jj ;
}
if ( jj == nrowJ ) {
fprintf(stderr, "\n fatal error in Chv_assembleChv(%p,%p)"
"\n row indicesI do not nest in indicesJ\n", chvJ, chvI) ;
fprintf(stderr, "\n rowindI") ;
IVfprintf(stderr, nrowI, rowindI) ;
fprintf(stderr, "\n rowindJ") ;
IVfprintf(stderr, nrowJ, rowindJ) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n local row indices") ;
IVfprintf(stdout, nrowI, rowindI) ;
#endif
}
#if MYDEBUG > 0
fprintf(stdout, "\n local column indices") ;
IVfprintf(stdout, ncolI, colindI) ;
fprintf(stdout, "\n local row indices") ;
IVfprintf(stdout, nrowI, rowindI) ;
#endif
/*
---------------------------
loop over the chevrons in I
---------------------------
*/
for ( ichvI = 0 ; ichvI < nDI ; ichvI++ ) {
ichvJ = colindI[ichvI] ;
if ( ichvJ != rowindI[ichvI] ) {
fprintf(stderr, "\n fatal error in Chv_assembleChv(%p,%p)"
"\n ichvI = %d, ichvJ = %d, rowindI[ichvI] = %d",
chvJ, chvI, ichvI, ichvJ, rowindI[ichvI]) ;
exit(-1) ;
}
diagI = Chv_diagLocation(chvI, ichvI) ;
diagJ = Chv_diagLocation(chvJ, ichvJ) ;
#if MYDEBUG > 0
fprintf(stdout,
"\n ichvI = %d, diagI - entriesI = %d"
"\n ichvJ = %d, diagJ - entriesJ = %d",
ichvI, diagI - chvI->entries, ichvJ, diagJ - chvJ->entries) ;
#endif
if ( CHV_IS_REAL(chvJ) ) {
diagJ[0] += diagI[0] ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
diagJ[0] += diagI[0] ;
diagJ[1] += diagI[1] ;
}
if ( CHV_IS_SYMMETRIC(chvJ) || CHV_IS_HERMITIAN(chvJ) ) {
/*
----------------------
symmetric or hermitian
----------------------
*/
if ( CHV_IS_REAL(chvJ) ) {
for ( ii = ichvI + 1, jj = 1 ; ii < ncolI ; ii++, jj++ ) {
offset = colindI[ii] - ichvJ ;
#if MYDEBUG > 0
fprintf(stdout,
"\n ii = %d, jj = %d, offset = %d", ii, jj, offset) ;
#endif
diagJ[offset] += diagI[jj] ;
}
} else if ( CHV_IS_COMPLEX(chvJ) ) {
for ( ii = ichvI + 1, jj = 1 ; ii < ncolI ; ii++, jj++ ) {
offset = colindI[ii] - ichvJ ;
#if MYDEBUG > 0
fprintf(stdout,
"\n ii = %d, jj = %d, offset = %d", ii, jj, offset) ;
#endif
diagJ[2*offset] += diagI[2*jj] ;
diagJ[2*offset+1] += diagI[2*jj+1] ;
}
}
} else if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
/*
------------
nonsymmetric
------------
*/
if ( CHV_IS_REAL(chvJ) ) {
for ( ii = ichvI + 1, jj = 1 ; ii < ncolI ; ii++, jj++ ) {
offset = colindI[ii] - ichvJ ;
#if MYDEBUG > 0
fprintf(stdout, "\n diagJ[%d] += diagI[%d]", offset, jj) ;
#endif
diagJ[offset] += diagI[jj] ;
}
for ( ii = ichvI + 1, jj = -1 ; ii < nrowI ; ii++, jj-- ) {
offset = rowindI[ii] - ichvJ ;
#if MYDEBUG > 0
fprintf(stdout, "\n diagJ[%d] += diagI[%d]", -offset, jj) ;
#endif
diagJ[-offset] += diagI[jj] ;
}
} else if ( CHV_IS_COMPLEX(chvJ) ) {
for ( ii = ichvI + 1, jj = 1 ; ii < ncolI ; ii++, jj++ ) {
offset = colindI[ii] - ichvJ ;
#if MYDEBUG > 0
fprintf(stdout, "\n diagJ[%d] += diagI[%d]", offset, jj) ;
#endif
diagJ[2*offset] += diagI[2*jj] ;
diagJ[2*offset+1] += diagI[2*jj+1] ;
}
for ( ii = ichvI + 1, jj = -1 ; ii < nrowI ; ii++, jj-- ) {
offset = rowindI[ii] - ichvJ ;
#if MYDEBUG > 0
fprintf(stdout, "\n diagJ[%d] += diagI[%d]", -offset, jj) ;
#endif
diagJ[-2*offset] += diagI[2*jj] ;
diagJ[-2*offset+1] += diagI[2*jj+1] ;
}
}
}
}
/*
-------------------
restore the indices
-------------------
*/
for ( ii = 0 ; ii < ncolI ; ii++ ) {
colindI[ii] = colindJ[colindI[ii]] ;
}
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
for ( ii = 0 ; ii < nrowI ; ii++ ) {
rowindI[ii] = rowindJ[rowindI[ii]] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose -- assemble the postponed data from the children
newchv -- Chv object to contain fully assembled front
oldchv -- Chv object that contains former front
firstchild -- pointer to first child in the list of children
Chv objects to be merged into the new front
return value -- # of delayed rows and columns added to the front
created -- 98apr30, cca
----------------------------------------------------------------
*/
int
Chv_assemblePostponedData (
Chv *newchv,
Chv *oldchv,
Chv *firstchild
) {
Chv *child ;
int ierr, ndelay ;
/*
---------------
check the input
---------------
*/
if ( newchv == NULL || oldchv == NULL || firstchild == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_assemblePostponedData(%p,%p,%p)"
"\n bad input\n", newchv, oldchv, firstchild) ;
exit(-1) ;
}
Chv_zero(newchv) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n inside Chv_assemblePostponedData, J = %d",
oldchv->id) ;
fprintf(stdout, "\n\n old chevron %d", oldchv->id) ;
Chv_writeForHumanEye(oldchv, stdout) ;
for ( child = firstchild ; child != NULL ; child = child->next ) {
fprintf(stdout, "\n\n child %d", child->id) ;
Chv_writeForHumanEye(child, stdout) ;
}
fprintf(stdout, "\n\n new chevron %d", newchv->id) ;
Chv_writeForHumanEye(newchv, stdout) ;
fflush(stdout) ;
#endif
/*
------------------------------------
copy the indices into the new object
------------------------------------
*/
ndelay = 0 ;
for ( child = firstchild ; child != NULL ; child = child->next ) {
IVcopy(child->nD, newchv->colind + ndelay, child->colind) ;
ndelay += child->nD ;
}
IVcopy(oldchv->nD + oldchv->nU,
newchv->colind + ndelay, oldchv->colind) ;
#if MYDEBUG > 0
fprintf(stdout, "\n ndelay = %d, new column indices", ndelay) ;
IVfp80(stdout, newchv->nD + newchv->nU, newchv->colind, 80, &ierr) ;
fflush(stdout) ;
#endif
if ( CHV_IS_NONSYMMETRIC(newchv) ) {
ndelay = 0 ;
for ( child = firstchild ; child != NULL ; child = child->next ) {
IVcopy(child->nD, newchv->rowind + ndelay, child->rowind) ;
ndelay += child->nD ;
}
IVcopy(oldchv->nD + oldchv->nU,
newchv->rowind + ndelay, oldchv->rowind) ;
#if MYDEBUG > 0
fprintf(stdout, "\n ndelay = %d, new row indices", ndelay) ;
IVfp80(stdout, newchv->nD + newchv->nL, newchv->rowind, 80, &ierr) ;
fflush(stdout) ;
#endif
}
/*
------------------------
assemble the old chevron
------------------------
*/
Chv_assembleChv(newchv, oldchv) ;
#if MYDEBUG > 0
fprintf(stdout, "\n after merging old chevron") ;
Chv_writeForHumanEye(newchv, stdout) ;
#endif
/*
------------------------------
assemble the children chevrons
------------------------------
*/
for ( child = firstchild ; child != NULL ; child = child->next ) {
Chv_assembleChv(newchv, child) ;
#if MYDEBUG > 0
fprintf(stdout, "\n after merging child %d", child->id) ;
Chv_writeForHumanEye(newchv, stdout) ;
#endif
}
return(ndelay) ; }
/*--------------------------------------------------------------------*/
|| chvI == NULL ) {
fprintf(stderr, "\n fatal error in Chv_assembleChv(%p,%p)"
"\n bad input\n", chvJ, chvI) ;
exit(-1) ;
}
if ( !(CHV_IS_SYMMETRIC(chvI)
|| CHV_IS_HERMITIAN(chvI)
|| CHV_IS_NONSYMMETRIC(chvI) ) ) {
fprintf(stderr, "\n fatal Chv/src/basics.c 0100644 0002055 0007177 00000004367 06571267314 0015035 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../Chv.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------
simplest constructor
created -- 98apr30, cca
-----------------------
*/
Chv *
Chv_new (
void
) {
Chv *chv ;
ALLOCATE(chv, struct _Chv, 1) ;
Chv_setDefaultFields(chv) ;
return(chv) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 98apr30, cca
-----------------------
*/
void
Chv_setDefaultFields (
Chv *chv
) {
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_setDefaultFields(%p)"
"\n bad input", chv) ;
exit(-1) ;
}
chv->id = -1 ;
chv->nD = 0 ;
chv->nL = 0 ;
chv->nU = 0 ;
chv->type = SPOOLES_REAL ;
chv->symflag = SPOOLES_SYMMETRIC ;
DV_setDefaultFields(&chv->wrkDV) ;
chv->rowind = NULL ;
chv->colind = NULL ;
chv->entries = NULL ;
chv->next = NULL ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98apr30, cca
--------------------------------------------------
*/
void
Chv_clearData (
Chv *chv
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_clearData(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
/*
------------------------
free the working storage
------------------------
*/
DV_clearData(&chv->wrkDV) ;
/*
----------------------
set the default fields
----------------------
*/
Chv_setDefaultFields(chv) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
destructor, free's the object and its data
created -- 98apr30, cca
------------------------------------------
*/
void
Chv_free (
Chv *chv
) {
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_free(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
Chv_clearData(chv) ;
FREE(chv) ;
return ; }
/*--------------------------------------------------------------------*/
Chv/src/copy.c 0100644 0002055 0007177 00000330346 06571267313 0014541 0 ustar 00cleve compmath 0000040 0000006 /* copyEntriesToVector.c */
#include "../Chv.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
purpose -- copy entries to a vector.
length -- length of dvec[]
npivot -- number of pivots, may be 0
pivotsizes -- vector of pivot sizes, may be NULL
dvec[] -- vector to receive matrix entries
copyflag -- flag to denote what part of the entries to copy
CHV_STRICT_LOWER --> copy strict lower entries
CHV_DIAGONAL --> copy diagonal entries
CHV_STRICT_UPPER --> copy strict upper entries
CHV_STRICT_LOWER_11 --> copy strict lower entries in (1,1) block
CHV_LOWER_21 --> copy lower entries in (2,1) block
CHV_STRICT_UPPER_11 --> copy strict upper entries in (1,1) block
CHV_UPPER_12 --> copy upper entries in (1,2) block
storeflag -- flag to denote how to store entries in dvec[]
CHV_BY_ROWS --> store by rows
CHV_BY_COLUMNS --> store by columns
return value -- number of entries copied
created -- 97jun05, cca
modified -- 98feb27, cca
cases 4-7 inserted
-------------------------------------------------------------------
*/
int
Chv_copyEntriesToVector (
Chv *chv,
int npivot,
int pivotsizes[],
int length,
double *dvec,
int copyflag,
int storeflag
) {
double *entries ;
int mm, ncol, nD, nent, nL, nrow, nU, symflag ;
/*
--------------------------------------------
check the input, get dimensions and pointers
and check that length is large enough
--------------------------------------------
*/
if ( chv == NULL || length < 0 || dvec == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_copyEntriesToVector(%p,%d,%p,,%d,%d)"
"\n bad input\n", chv, length, dvec, copyflag, storeflag) ;
exit(-1) ;
}
switch ( copyflag ) {
case CHV_STRICT_LOWER :
case CHV_DIAGONAL :
case CHV_STRICT_UPPER :
case CHV_STRICT_LOWER_11 :
case CHV_LOWER_21 :
case CHV_STRICT_UPPER_11 :
case CHV_UPPER_12 :
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_copyEntriesToVector(%p,%d,%p,%d,%d)"
"\n bad input\n"
"\n copyflag = %d, must be\n"
"\n CHV_STRICT_LOWER --> copy strict lower entries"
"\n CHV_DIAGONAL --> copy diagonal entries"
"\n CHV_STRICT_UPPER --> copy strict upper entries"
"\n CHV_STRICT_LOWER_11 --> copy strict lower entries in (1,1) block"
"\n CHV_LOWER_21 --> copy lower entries in (2,1) block"
"\n CHV_STRICT_UPPER_11 --> copy strict upper entries in (1,1) block"
"\n CHV_UPPER_12 --> copy upper entries in (1,2) block"
"\n",
chv, length, dvec, copyflag, storeflag, copyflag) ;
exit(-1) ;
break ;
}
switch ( storeflag ) {
case CHV_BY_ROWS :
case CHV_BY_COLUMNS :
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_copyEntriesToVector(%p,%d,%p,%d,%d)"
"\n bad input\n"
"\n storeflag = %d, must be\n"
"\n CHV_BY_ROWS --> store by rows"
"\n CHV_BY_COLUMNS --> store by columns"
"\n",
chv, length, dvec, copyflag, storeflag, storeflag) ;
exit(-1) ;
break ;
}
nD = chv->nD ;
nL = chv->nL ;
nU = chv->nU ;
symflag = chv->symflag ;
nrow = nD + nL ;
ncol = nD + nU ;
/*
------------------------------------------
compute the number of entries to be copied
------------------------------------------
*/
switch ( copyflag ) {
case CHV_STRICT_LOWER : /* strictly lower entries */
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
fprintf(stderr,
"\n fatal error in Chv_copyEntriesToVector(%p,%d,%p,%d,%d)"
"\n symflag = %d, copyflag = %d",
chv, length, dvec, copyflag, storeflag, symflag, copyflag) ;
exit(-1) ;
}
nent = (nD*(nD-1))/2 + nD*nL ;
break ;
case CHV_DIAGONAL : /* diagonal entries */
if ( pivotsizes == NULL ) {
nent = nD ;
} else {
int ipivot ;
for ( ipivot = nent = 0 ; ipivot < npivot ; ipivot++ ) {
nent += (pivotsizes[ipivot]*(pivotsizes[ipivot] + 1))/2 ;
}
}
break ;
case CHV_STRICT_UPPER : /* strictly upper entries */
if ( pivotsizes == NULL ) {
nent = (nD*(nD-1))/2 + nD*nU ;
} else {
int first, ipivot ;
for ( ipivot = first = nent = 0 ; ipivot < npivot ; ipivot++ ) {
nent += first * pivotsizes[ipivot] ;
first += pivotsizes[ipivot] ;
}
}
break ;
case CHV_STRICT_LOWER_11 : /* strictly lower entries in (1,1) block */
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
fprintf(stderr,
"\n fatal error in Chv_copyEntriesToVector(%p,%d,%p,%d,%d)"
"\n symflag = %d, copyflag = %d",
chv, length, dvec, copyflag, storeflag, symflag, copyflag) ;
exit(-1) ;
}
nent = (nD*(nD-1))/2 ;
break ;
case CHV_LOWER_21 : /* lower entries in (2,1) block */
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
fprintf(stderr,
"\n fatal error in Chv_copyEntriesToVector(%p,%d,%p,%d,%d)"
"\n symflag = %d, copyflag = %d",
chv, length, dvec, copyflag, storeflag, symflag, copyflag) ;
exit(-1) ;
}
nent = nD*nL ;
break ;
case CHV_STRICT_UPPER_11 : /* strictly upper entries in (1,1) block */
if ( pivotsizes == NULL ) {
nent = (nD*(nD-1))/2 ;
} else {
int first, ipivot ;
for ( ipivot = first = nent = 0 ; ipivot < npivot ; ipivot++ ) {
nent += first * pivotsizes[ipivot] ;
first += pivotsizes[ipivot] ;
}
}
break ;
case CHV_UPPER_12 : /* upper entries in (1,2) block */
nent = nD*nU ;
break ;
default :
break ;
}
if ( nent > length ) {
fprintf(stderr,
"\n fatal error in Chv_copyEntriesToVector(%p,%d,%p,%d,%d)"
"\n nent = %d, buffer length = %d",
chv, length, dvec, copyflag, storeflag, nent, length) ;
exit(-1) ;
}
/*
--------------------------------------------
make life simple, unit stride through dvec[]
--------------------------------------------
*/
entries = Chv_entries(chv) ;
mm = 0 ;
switch ( copyflag ) {
case CHV_STRICT_LOWER :
/*
----------------------------------------
copy lower entries, pivotsizes[] is NULL
----------------------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS : {
/*
-------------
store by rows
-------------
*/
int ii, jj, jjlast, kinc, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
jjlast = (ii < nD) ? (ii - 1) : (nD - 1) ;
for ( jj = 0 ; jj <= jjlast ; jj++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
jjlast = (ii < nD) ? (ii - 1) : (nD - 1) ;
for ( jj = 0 ; jj <= jjlast ; jj++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
}
} break ;
case CHV_BY_COLUMNS : {
/*
----------------
store by columns
----------------
*/
int ii, jj, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart - 1 ;
for ( ii = jj + 1 ; ii < nrow ; ii++, kk--, mm++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride -= 2 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart - 1 ;
for ( ii = jj + 1 ; ii < nrow ; ii++, kk--, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride -= 2 ;
}
}
} break ;
} break ;
case CHV_DIAGONAL :
/*
---------------------
copy diagonal entries
---------------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int first, ii, jj, ipivot, kk, kstart, last, stride ;
stride = nD + nU ;
kstart = 0 ;
if ( pivotsizes == NULL ) {
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0, kk = kstart ; ii < nD ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += stride ;
stride-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0, kk = kstart ; ii < nD ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += stride ;
stride-- ;
}
}
} else {
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( ii = first ; ii <= last ; ii++ ) {
for ( jj = ii, kk = kstart ;
jj <= last ;
jj++, mm++, kk++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride-- ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( ii = first ; ii <= last ; ii++ ) {
for ( jj = ii, kk = kstart ;
jj <= last ;
jj++, mm++, kk++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride-- ;
}
}
}
}
} else {
int ii, kk, stride ;
kk = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += stride ;
stride -= 2 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += stride ;
stride -= 2 ;
}
}
}
break ;
case CHV_STRICT_UPPER :
/*
-------------------------
copy strict upper entries
-------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS :
/*
-------------
store by rows
-------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int first, ii, ipivot, jj, kk, kstart, last, stride ;
kstart = 0 ;
stride = nD + nU ;
if ( pivotsizes == NULL ) {
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1 ; jj < ncol ; jj++, kk++, mm++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1 ; jj < ncol ; jj++, kk++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride-- ;
}
}
} else {
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = first = 0 ;
ipivot < npivot ;
ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( ii = first ; ii <= last ; ii++ ) {
kk = kstart + last - ii + 1 ;
for ( jj = last + 1 ;
jj < ncol ;
jj++, kk++, mm++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride-- ;
}
first = last + 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = first = 0 ;
ipivot < npivot ;
ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( ii = first ; ii <= last ; ii++ ) {
kk = kstart + last - ii + 1 ;
for ( jj = last + 1 ;
jj < ncol ;
jj++, kk++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride-- ;
}
first = last + 1 ;
}
}
}
} else {
int ii, jj, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1 ; jj < ncol ; jj++, kk++, mm++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride -= 2 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1 ; jj < ncol ; jj++, kk++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride -= 2 ;
}
}
}
break ;
case CHV_BY_COLUMNS :
/*
----------------
store by columns
----------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int first, ii, iilast, ipivot, jj,
kinc, kk, kstart, last, stride ;
kstart = 0 ;
stride = nD + nU - 1 ;
if ( pivotsizes == NULL ) {
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
}
} else {
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = mm = first = 0 ;
ipivot < npivot ;
ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < first ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
first = last + 1 ;
}
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = mm = first = 0 ;
ipivot < npivot ;
ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < first ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
first = last + 1 ;
}
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
}
}
} else {
int ii, iilast, jj, kinc, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
}
}
break ;
default :
break ;
} break ;
case CHV_STRICT_LOWER_11 :
/*
--------------------------------------------------------------
copy strict lower entries in (1,1) block, pivotsizes[] is NULL
--------------------------------------------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS : {
/*
-------------
store by rows
-------------
*/
int ii, jj, jjlast, kinc, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
kinc = stride ;
jjlast = ii - 1 ;
for ( jj = 0 ; jj <= jjlast ; jj++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
kinc = stride ;
jjlast = ii - 1 ;
for ( jj = 0 ; jj <= jjlast ; jj++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
}
} break ;
case CHV_BY_COLUMNS : {
/*
----------------
store by columns
----------------
*/
int ii, jj, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart - 1 ;
for ( ii = jj + 1 ; ii < nD ; ii++, kk--, mm++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride -= 2 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart - 1 ;
for ( ii = jj + 1 ; ii < nD ; ii++, kk--, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride -= 2 ;
}
}
} break ;
} break ;
case CHV_LOWER_21 :
/*
---------------------------------
copy lower entries in (2,1) block
---------------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS : {
/*
-------------
store by rows
-------------
*/
int ii, jj, kinc, kk, kstart, stride ;
kstart = nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = nD, mm = 0 ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
for ( jj = 0 ; jj < nD ; jj++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = nD, mm = 0 ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
for ( jj = 0 ; jj < nD ; jj++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
}
} break ;
case CHV_BY_COLUMNS : {
/*
----------------
store by columns
----------------
*/
int ii, jj, kk, kstart, stride ;
kstart = nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
for ( ii = nD ; ii < nrow ; ii++, kk--, mm++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride -= 2 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
for ( ii = nD ; ii < nrow ; ii++, kk--, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride -= 2 ;
}
}
} break ;
} break ;
case CHV_STRICT_UPPER_11 :
/*
----------------------------------------
copy strict upper entries in (1,1) block
----------------------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS :
/*
-------------
store by rows
-------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int first, ii, ipivot, jj, kk, kstart, last, stride ;
kstart = 0 ;
stride = nD + nU ;
if ( pivotsizes == NULL ) {
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1 ; jj < nD ; jj++, kk++, mm++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1 ; jj < nD ; jj++, kk++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride-- ;
}
}
} else {
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = first = 0 ;
ipivot < npivot ;
ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( ii = first ; ii <= last ; ii++ ) {
kk = kstart + last - ii + 1 ;
for ( jj = last + 1 ; jj < nD ; jj++, kk++, mm++ ){
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride-- ;
}
first = last + 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = first = 0 ;
ipivot < npivot ;
ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( ii = first ; ii <= last ; ii++ ) {
kk = kstart + last - ii + 1 ;
for ( jj = last + 1 ; jj < nD ; jj++, kk++, mm++ ){
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride-- ;
}
first = last + 1 ;
}
}
}
} else {
int ii, jj, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1 ; jj < nD ; jj++, kk++, mm++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride -= 2 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1 ; jj < nD ; jj++, kk++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride -= 2 ;
}
}
}
break ;
case CHV_BY_COLUMNS :
/*
----------------
store by columns
----------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int first, ii, iilast, ipivot, jj,
kinc, kk, kstart, last, stride ;
kstart = 0 ;
stride = nD + nU - 1 ;
if ( pivotsizes == NULL ) {
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
}
} else {
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = mm = first = 0 ;
ipivot < npivot ;
ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < first ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
first = last + 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = mm = first = 0 ;
ipivot < npivot ;
ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < first ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
first = last + 1 ;
}
}
}
} else {
int ii, jj, kinc, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < jj ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < jj ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
}
}
break ;
default :
break ;
} break ;
case CHV_UPPER_12 :
/*
---------------------------------
copy upper entries in (1,2) block
---------------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS :
/*
-------------
store by rows
-------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int ii, jj, kk, kstart, stride ;
kstart = nD ;
stride = nD + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
for ( jj = 0 ; jj < nU ; jj++, kk++, mm++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
for ( jj = 0 ; jj < nU ; jj++, kk++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride-- ;
}
}
} else {
int ii, jj, kk, kstart, stride ;
kstart = 2*nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
for ( jj = nD ; jj < ncol ; jj++, kk++, mm++ ) {
dvec[mm] = entries[kk] ;
}
kstart += stride ;
stride -= 2 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
for ( jj = nD ; jj < ncol ; jj++, kk++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
}
kstart += stride ;
stride -= 2 ;
}
}
}
break ;
case CHV_BY_COLUMNS :
/*
----------------
store by columns
----------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int ii, jj, kinc, kk, kstart, stride ;
kstart = nD ;
stride = nD + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
}
} else {
int ii, jj, kinc, kk, kstart, stride ;
kstart = 2*nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++, mm++ ) {
dvec[mm] = entries[kk] ;
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++, mm++ ) {
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
}
}
break ;
default :
break ;
} break ;
default :
break ;
}
return(mm) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
purpose -- copy large entries to a vector. the portion copied
can be a union of the strict lower portion,
the diagonal portion, and the strict upper
portion. there is one restriction, if the strict
lower and strict upper are to be copied, the
diagonal will also be copied.
npivot -- number of pivots, may be 0
pivotsizes -- vector of pivot sizes, may be NULL
sizes[] -- vector to receive row/column sizes
ivec[] -- vector to receive row/column indices
dvec[] -- vector to receive matrix entries
copyflag -- flag to denote what part of the entries to copy
CHV_STRICT_LOWER --> copy strict lower entries
CHV_STRICT_UPPER --> copy strict upper entries
CHV_STRICT_LOWER_11 --> copy strict lower entries in (1,1) block
CHV_LOWER_21 --> copy lower entries in (2,1) block
CHV_STRICT_UPPER_11 --> copy strict upper entries in (1,1) block
CHV_UPPER_12 --> copy upper entries in (1,2) block
storeflag -- flag to denote how to store entries in dvec[]
CHV_BY_ROWS --> store by rows
CHV_BY_COLUMNS --> store by columns
droptol -- entry to be copied must be larger than this magnitude
return value -- number of entries copied
created -- 97jun05, cca
modified -- 97feb27, cca
cases 4-7 inserted
-------------------------------------------------------------------
*/
int
Chv_copyBigEntriesToVector (
Chv *chv,
int npivot,
int pivotsizes[],
int sizes[],
int ivec[],
double dvec[],
int copyflag,
int storeflag,
double droptol
) {
double absval ;
double *entries ;
int mm, ncol, nD, nL, nrow, nU, symflag ;
/*
--------------------------------------------
check the input, get dimensions and pointers
--------------------------------------------
*/
if ( chv == NULL || sizes == NULL || ivec == NULL || dvec == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_copyBigEntriesToVector()"
"\n chv %p, sizes %p, ivec %p, dvec %p"
"\n bad input\n", chv, sizes, ivec, dvec) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% inside Chv_copyBigEntries, copyflag %d, storeflag %d",
copyflag, storeflag) ;
fflush(stdout) ;
#endif
switch ( copyflag ) {
case CHV_STRICT_LOWER :
case CHV_STRICT_UPPER :
case CHV_STRICT_LOWER_11 :
case CHV_LOWER_21 :
case CHV_STRICT_UPPER_11 :
case CHV_UPPER_12 :
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_copyBigEntriesToVector(%p,%p,%p,%p,%d,%d)"
"\n bad input\n"
"\n copyflag = %d, must be\n"
"\n 1 --> strictly lower entries"
"\n 3 --> strictly upper entries"
"\n 4 --> copy strict lower entries in (1,1) block"
"\n 5 --> copy lower entries in (2,1) block"
"\n 6 --> copy strict upper entries in (1,1) block"
"\n 7 --> copy upper entries in (1,2) block",
chv, sizes, ivec, dvec, copyflag, storeflag, copyflag) ;
exit(-1) ;
}
if ( storeflag < 0 || storeflag > 1 ) {
fprintf(stderr,
"\n fatal error in Chv_copyBigEntriesToVector(%p,%p,%p,%p,%d,%d)"
"\n bad input\n"
"\n storeflag = %d, must be\n"
"\n 0 --> store by rows"
"\n 1 --> store by columns",
chv, sizes, ivec, dvec, copyflag, storeflag, storeflag) ;
exit(-1) ;
}
nD = chv->nD ;
nL = chv->nL ;
nU = chv->nU ;
symflag = chv->symflag ;
nrow = nD + nL ;
ncol = nD + nU ;
/*
--------------------------------------------
make life simple, unit stride through dvec[]
--------------------------------------------
*/
entries = Chv_entries(chv) ;
mm = 0 ;
switch ( copyflag ) {
case CHV_STRICT_LOWER :
/*
----------------------------------------
copy lower entries, pivotsizes[] is NULL
----------------------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS : {
/*
-------------
store by rows
-------------
*/
int count, ii, jj, jjlast, kinc, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
jjlast = (ii < nD) ? (ii - 1) : (nD - 1) ;
for ( jj = count = 0 ; jj <= jjlast ; jj++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
sizes[ii] = count ;
kstart-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
jjlast = (ii < nD) ? (ii - 1) : (nD - 1) ;
for ( jj = count = 0 ; jj <= jjlast ; jj++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
sizes[ii] = count ;
kstart-- ;
}
}
} break ;
case CHV_BY_COLUMNS : {
/*
----------------
store by columns
----------------
*/
int count, ii, jj, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart - 1 ;
for ( ii = jj + 1, count = 0 ; ii < nrow ; ii++, kk-- ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
kstart += stride ;
stride -= 2 ;
sizes[jj] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart - 1 ;
for ( ii = jj + 1, count = 0 ; ii < nrow ; ii++, kk-- ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
kstart += stride ;
stride -= 2 ;
sizes[jj] = count ;
}
}
} break ;
}
break ;
case CHV_STRICT_UPPER :
/*
-------------------------
copy strict upper entries
-------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS :
/*
-------------
store by rows
-------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int count, first, ii, ipivot, jj, kk, kstart, last, stride ;
kstart = 0 ;
stride = nD + nU ;
if ( pivotsizes == NULL ) {
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1, count = 0 ;
jj < ncol ;
jj++, kk++ ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
kstart += stride ;
stride-- ;
sizes[ii] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1, count = 0 ;
jj < ncol ;
jj++, kk++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
kstart += stride ;
stride-- ;
sizes[ii] = count ;
}
}
} else {
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( ii = first ; ii <= last ; ii++ ) {
kk = kstart + last - ii + 1 ;
for ( jj = last + 1, count = 0 ;
jj < ncol ;
jj++, kk++ ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
kstart += stride ;
stride-- ;
sizes[ii] = count ;
}
first = last + 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( ii = first ; ii <= last ; ii++ ) {
kk = kstart + last - ii + 1 ;
for ( jj = last + 1, count = 0 ;
jj < ncol ;
jj++, kk++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
kstart += stride ;
stride-- ;
sizes[ii] = count ;
}
first = last + 1 ;
}
}
}
} else {
int count, ii, jj, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1, count = 0 ; jj < ncol ; jj++, kk++ ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
kstart += stride ;
stride -= 2 ;
sizes[ii] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1, count = 0 ; jj < ncol ; jj++, kk++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
kstart += stride ;
stride -= 2 ;
sizes[ii] = count ;
}
}
} break ;
case CHV_BY_COLUMNS :
/*
----------------
store by columns
----------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int count, first, ii, iilast, ipivot, jj,
kinc, kk, kstart, last, stride ;
kstart = 0 ;
stride = nD + nU - 1 ;
if ( pivotsizes == NULL ) {
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = count = 0 ; ii <= iilast ; ii++ ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = count = 0 ; ii <= iilast ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj] = count ;
}
}
} else {
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = count = 0 ; ii < first ; ii++ ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj] = count ;
}
first = last + 1 ;
}
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = count = 0 ; ii < nD ; ii++ ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = count = 0 ; ii < first ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj] = count ;
}
first = last + 1 ;
}
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = count = 0 ; ii < nD ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj] = count ;
}
}
}
} else {
int count, ii, iilast, jj, kinc, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = count = 0 ; ii <= iilast ; ii++ ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
sizes[jj] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = count = 0 ; ii <= iilast ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
sizes[jj] = count ;
}
}
}
break ;
default :
break ;
}
break ;
case CHV_STRICT_LOWER_11 :
/*
------------------------------------------------
copy entries in strict lower part of (1,1) block
------------------------------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS : {
/*
-------------
store by rows
-------------
*/
int count, ii, jj, jjlast, kinc, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
kinc = stride ;
jjlast = (ii < nD) ? (ii - 1) : (nD - 1) ;
for ( jj = count = 0 ; jj <= jjlast ; jj++ ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
sizes[ii] = count ;
kstart-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
kinc = stride ;
jjlast = (ii < nD) ? (ii - 1) : (nD - 1) ;
for ( jj = count = 0 ; jj <= jjlast ; jj++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
sizes[ii] = count ;
kstart-- ;
}
}
} break ;
case CHV_BY_COLUMNS : {
/*
----------------
store by columns
----------------
*/
int count, ii, jj, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart - 1 ;
for ( ii = jj + 1, count = 0 ; ii < nD ; ii++, kk-- ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
kstart += stride ;
stride -= 2 ;
sizes[jj] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart - 1 ;
for ( ii = jj + 1, count = 0 ; ii < nD ; ii++, kk-- ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
kstart += stride ;
stride -= 2 ;
sizes[jj] = count ;
}
}
} break ;
}
break ;
case CHV_LOWER_21 :
/*
---------------------------
copy entries in (2,1) block
---------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS : {
/*
-------------
store by rows
-------------
*/
int count, ii, jj, kinc, kk, kstart, stride ;
kstart = nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = nD ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
for ( jj = count = 0 ; jj < nD ; jj++ ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
sizes[ii-nD] = count ;
kstart-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = nD ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
for ( jj = count = 0 ; jj < nD ; jj++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
sizes[ii-nD] = count ;
kstart-- ;
}
}
} break ;
case CHV_BY_COLUMNS : {
/*
----------------
store by columns
----------------
*/
int count, ii, jj, kk, kstart, stride ;
kstart = nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
for ( ii = nD, count = 0 ; ii < nrow ; ii++, kk-- ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
kstart += stride ;
stride -= 2 ;
sizes[jj] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
for ( ii = nD, count = 0 ; ii < nrow ; ii++, kk-- ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
kstart += stride ;
stride -= 2 ;
sizes[jj] = count ;
}
}
} break ;
}
break ;
case CHV_STRICT_UPPER_11 :
/*
----------------------------------------
copy strict upper entries in (1,1) block
----------------------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS :
/*
-------------
store by rows
-------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int count, first, ii, ipivot, jj, kk, kstart, last, stride ;
kstart = 0 ;
stride = nD + nU ;
if ( pivotsizes == NULL ) {
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1, count = 0 ; jj < nD ; jj++, kk++ ){
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout,
"\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
kstart += stride ;
stride-- ;
sizes[ii] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1, count = 0 ; jj < nD ; jj++, kk++ ){
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
kstart += stride ;
stride-- ;
sizes[ii] = count ;
}
}
} else {
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( ii = first ; ii <= last ; ii++ ) {
kk = kstart + last - ii + 1 ;
for ( jj = last + 1, count = 0 ;
jj < nD ;
jj++, kk++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
kstart += stride ;
stride-- ;
sizes[ii] = count ;
}
first = last + 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( ii = first ; ii <= last ; ii++ ) {
kk = kstart + last - ii + 1 ;
for ( jj = last + 1, count = 0 ;
jj < nD ;
jj++, kk++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
kstart += stride ;
stride-- ;
sizes[ii] = count ;
}
first = last + 1 ;
}
}
}
} else {
int count, ii, jj, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1, count = 0 ; jj < nD ; jj++, kk++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% A(%d,%d) = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
kstart += stride ;
stride -= 2 ;
sizes[ii] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart + 1 ;
for ( jj = ii + 1, count = 0 ; jj < nD ; jj++, kk++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% A(%d,%d) = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
kstart += stride ;
stride -= 2 ;
sizes[ii] = count ;
}
}
}
break ;
case CHV_BY_COLUMNS :
/*
----------------
store by columns
----------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int count, first, ii, iilast, ipivot, jj,
kinc, kk, kstart, last, stride ;
kstart = 0 ;
stride = nD + nU - 1 ;
if ( pivotsizes == NULL ) {
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = count = 0 ; ii <= iilast ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = count = 0 ; ii <= iilast ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj] = count ;
}
}
} else {
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = count = 0 ; ii < first ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj] = count ;
}
first = last + 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = count = 0 ; ii < first ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj] = count ;
}
first = last + 1 ;
}
}
}
} else {
int count, ii, iilast, jj, kinc, kk, kstart, stride ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = count = 0 ; ii <= iilast ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
sizes[jj] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = count = 0 ; ii <= iilast ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
sizes[jj] = count ;
}
}
} break ;
default :
break ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n %% break from case CHV_STRICT_UPPER_11, mm = %d", mm) ;
#endif
break ;
case CHV_UPPER_12 :
/*
---------------------------
copy entries in (1,2) block
---------------------------
*/
switch ( storeflag ) {
case CHV_BY_ROWS :
/*
-------------
store by rows
-------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int count, ii, jj, kk, kstart, stride ;
kstart = nD ;
stride = nD + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
for ( jj = nD, count = 0 ; jj < ncol ; jj++, kk++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
kstart += stride ;
stride-- ;
sizes[ii] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
for ( jj = nD, count = 0 ; jj < ncol ; jj++, kk++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
kstart += stride ;
stride-- ;
sizes[ii] = count ;
}
}
} else {
int count, ii, jj, kk, kstart, stride ;
kstart = 2*nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = nD, count = 0 ; jj < ncol ; jj++, kk++ ) {
absval = fabs(entries[kk]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = nD, count = 0 ; jj < ncol ; jj++, kk++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
if ( absval >= droptol ) {
ivec[mm] = jj ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
}
}
kstart += stride ;
stride -= 2 ;
sizes[ii] = count ;
}
}
break ;
case CHV_BY_COLUMNS :
/*
----------------
store by columns
----------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int count, ii, jj, kinc, kk, kstart, stride ;
kstart = nD ;
stride = nD + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = count = 0 ; ii < nD ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj-nD] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = count = 0 ; ii < nD ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
sizes[jj-nD] = count ;
}
}
} else {
int count, ii, jj, kinc, kk, kstart, stride ;
kstart = 2*nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = count = 0 ; ii < nD ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[mm] = entries[kk] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
sizes[jj-nD] = count ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = count = 0 ; ii < nD ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
ivec[mm] = ii ;
dvec[2*mm] = entries[2*kk] ;
dvec[2*mm+1] = entries[2*kk+1] ;
mm++, count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
sizes[jj-nD] = count ;
}
}
}
break ;
default :
break ;
}
break ;
default :
break ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n %% return, mm = %d", mm) ;
#endif
return(mm) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
purpose -- return the number of entries
in a portion of the object
countflag -- which entries to count
CHV_STRICT_LOWER --> copy strict lower entries
CHV_STRICT_UPPER --> copy strict upper entries
CHV_STRICT_LOWER_11 --> copy strict lower entries in (1,1) block
CHV_LOWER_21 --> copy lower entries in (2,1) block
CHV_STRICT_UPPER_11 --> copy strict upper entries in (1,1) block
CHV_UPPER_12 --> copy upper entries in (1,2) block
created -- 98feb27, cca
-------------------------------------------------------------------
*/
int
Chv_countEntries (
Chv *chv,
int npivot,
int pivotsizes[],
int countflag
) {
int count, nD, nL, nU ;
/*
--------------------------------------------
check the input, get dimensions and pointers
--------------------------------------------
*/
if ( chv == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_countEntries(%p,%d,%p,%d)"
"\n bad input\n", chv, npivot, pivotsizes, countflag) ;
exit(-1) ;
}
if ( countflag < 1 || countflag > 7 ) {
fprintf(stderr,
"\n fatal error in Chv_countEntries(%p,%d,%p,%d)"
"\n bad input\n"
"\n countflag = %d, must be\n"
"\n 1 --> strictly lower entries"
"\n 2 --> diagonal entries"
"\n 3 --> strictly upper entries"
"\n 4 --> strictly lower entries in (1,1) block"
"\n 5 --> lower entries in (2,1) block"
"\n 6 --> strictly upper entries in (1,1) block"
"\n 7 --> upper entries in (1,2) block",
chv, npivot, pivotsizes, countflag, countflag) ;
exit(-1) ;
}
if ( (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv))
&& (countflag == 1 || countflag == 4 || countflag == 5 ) ) {
fprintf(stderr,
"\n fatal error in Chv_countEntries(%p,%d,%p,%d)"
"\n countflag = %d --> lower entries but chevron is symmetric",
chv, npivot, pivotsizes, countflag, countflag) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
switch ( countflag ) {
case CHV_STRICT_LOWER : /* strictly lower entries */
count = (nD*(nD-1))/2 + nD*nL ;
break ;
case CHV_DIAGONAL : /* diagonal entries */
if ( (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv))
&& pivotsizes != NULL ) {
count = 2*nD - npivot ;
} else {
count = nD ;
}
break ;
case CHV_STRICT_UPPER : /* strictly upper entries */
if ( (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv))
&& pivotsizes != NULL ) {
count = (nD*(nD-1))/2 - nD + npivot + nD*nU ;
} else {
count = (nD*(nD-1))/2 + nD*nU ;
}
break ;
case CHV_STRICT_LOWER_11 : /* strictly lower entries in (1,1) block */
count = (nD*(nD-1))/2 ;
break ;
case CHV_LOWER_21 : /* lower entries in (2,1) block */
count = nD*nL ;
break ;
case CHV_STRICT_UPPER_11 : /* strictly upper entries in (1,1) block */
if ( (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv))
&& pivotsizes != NULL ) {
count = (nD*(nD-1))/2 - nD + npivot ;
} else {
count = (nD*(nD-1))/2 ;
}
break ;
case CHV_UPPER_12 : /* upper entries in (1,2) block */
count = nD*nU ;
break ;
}
return(count) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
purpose -- return the number of entries
whose magnitude is larger than droptol.
countflag -- which entries to count
CHV_STRICT_LOWER --> copy strict lower entries
CHV_STRICT_UPPER --> copy strict upper entries
CHV_STRICT_LOWER_11 --> copy strict lower entries in (1,1) block
CHV_LOWER_21 --> copy lower entries in (2,1) block
CHV_STRICT_UPPER_11 --> copy strict upper entries in (1,1) block
CHV_UPPER_12 --> copy upper entries in (1,2) block
created -- 97jun07, cca
modified -- 98feb27, cca
cases 4-7 inserted
-------------------------------------------------------------------
*/
int
Chv_countBigEntries (
Chv *chv,
int npivot,
int pivotsizes[],
int countflag,
double droptol
) {
double absval ;
double *entries ;
int count, nD, nL, nU ;
/*
--------------------------------------------
check the input, get dimensions and pointers
--------------------------------------------
*/
if ( chv == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_countBigEntries(%p,%d,%p,%d,%f)"
"\n bad input\n", chv, npivot, pivotsizes, countflag, droptol) ;
exit(-1) ;
}
switch ( countflag ) {
case CHV_STRICT_LOWER :
case CHV_STRICT_UPPER :
case CHV_STRICT_LOWER_11 :
case CHV_LOWER_21 :
case CHV_STRICT_UPPER_11 :
case CHV_UPPER_12 :
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_countBigEntries(%p,%d,%p,%d,%f)"
"\n bad input\n"
"\n countflag = %d, must be\n"
"\n 1 --> strictly lower entries"
"\n 3 --> strictly upper entries"
"\n 4 --> count strict lower entries in (1,1) block"
"\n 5 --> count lower entries in (2,1) block"
"\n 6 --> count strict upper entries in (1,1) block"
"\n 7 --> count upper entries in (1,2) block",
chv, npivot, pivotsizes, countflag, droptol, countflag) ;
exit(-1) ;
}
if ( (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv))
&& (countflag == 1 || countflag == 4 || countflag == 5) ) {
fprintf(stderr,
"\n fatal error in Chv_countBigEntries(%p,%d,%p,%d,%f)"
"\n countflag = %d --> lower entries but chevron is symmetric",
chv, npivot, pivotsizes, countflag, droptol, countflag) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% inside Chv_countBigEntries, countflag %d",
countflag) ;
fflush(stdout) ;
#endif
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
switch ( countflag ) {
case CHV_STRICT_LOWER : {
int ii, jj, jlast, kinc, kk, kstart, nrow, stride ;
/*
-----------------------------------------------------
count the number of big entries in the lower triangle
-----------------------------------------------------
*/
nrow = nD + nL ;
count = 0 ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
jlast = (ii < nD) ? (ii - 1) : (nD - 1) ;
for ( jj = 0 ; jj <= jlast ; jj++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
jlast = (ii < nD) ? (ii - 1) : (nD - 1) ;
for ( jj = 0 ; jj <= jlast ; jj++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
}
} break ;
case CHV_STRICT_UPPER : {
int first, ii, iilast, ipivot, jj, kinc, kk, kstart,
last, ncol, stride ;
ncol = nD + nU ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n symmetric chevron, npivot = %d, pivotsizes = %p",
npivot, pivotsizes) ;
#endif
/*
--------------------
chevron is symmetric
--------------------
*/
count = 0 ;
kstart = 0 ;
stride = nD + nU - 1 ;
if ( pivotsizes == NULL ) {
/*
-------------
D is diagonal
-------------
*/
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = 0 ; ii <= iilast ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = 0 ; ii <= iilast ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
}
} else {
/*
---------------------------------
D can have 1 x 1 and 2 x 2 pivots
---------------------------------
*/
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n ipivot = %d, jj = %d, first = %d, last = %d, kstart = %d",
ipivot, jj, first, last, kstart) ;
#endif
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < first ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
first = last + 1 ;
}
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n ipivot = %d, jj = %d, first = %d, last = %d, kstart = %d",
ipivot, jj, first, last, kstart) ;
#endif
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < first ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
first = last + 1 ;
}
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
}
}
} else {
/*
--------------------------------------
chevron is nonsymmetric, D is diagonal
--------------------------------------
*/
count = 0 ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = 0 ; ii <= iilast ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
iilast = (jj < nD) ? (jj - 1) : (nD - 1) ;
for ( ii = 0 ; ii <= iilast ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
}
}
} break ;
case CHV_STRICT_LOWER_11 : {
int ii, jj, kinc, kk, kstart, nrow, stride ;
/*
----------------------------------------
count the number of big entries in the
strict lower triangle of the (1,1) block
----------------------------------------
*/
nrow = nD + nL ;
count = 0 ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
kinc = stride ;
for ( jj = 0 ; jj < ii ; jj++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < nD ; ii++ ) {
kk = kstart ;
kinc = stride ;
for ( jj = 0 ; jj < ii ; jj++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
}
} break ;
case CHV_LOWER_21 : {
int ii, jj, kinc, kk, kstart, nrow, stride ;
/*
--------------------------------------------------
count the number of big entries in the (2,1) block
--------------------------------------------------
*/
nrow = nD + nL ;
count = 0 ;
kstart = nL - 1 ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = nD ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
for ( jj = 0 ; jj < nD ; jj++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = nD ; ii < nrow ; ii++ ) {
kk = kstart ;
kinc = stride ;
for ( jj = 0 ; jj < nD ; jj++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart-- ;
}
}
} break ;
case CHV_STRICT_UPPER_11 : {
/*
---------------------------------------------------------------
count the number of big entries in the strict upper (1,1) block
---------------------------------------------------------------
*/
int first, ii, ipivot, jj, kinc, kk, kstart,
last, ncol, stride ;
ncol = nD + nU ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n symmetric chevron, npivot = %d, pivotsizes = %p",
npivot, pivotsizes) ;
#endif
/*
--------------------
chevron is symmetric
--------------------
*/
count = 0 ;
kstart = 0 ;
stride = nD + nU - 1 ;
if ( pivotsizes == NULL ) {
/*
-------------
D is diagonal
-------------
*/
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < jj ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < jj ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
}
} else {
/*
---------------------------------
D can have 1 x 1 and 2 x 2 pivots
---------------------------------
*/
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n %% ipivot = %d, jj = %d, first = %d, last = %d, kstart = %d",
ipivot, jj, first, last, kstart) ;
#endif
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < first ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
first = last + 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = first = 0 ; ipivot < npivot ; ipivot++ ) {
last = first + pivotsizes[ipivot] - 1 ;
for ( jj = first ; jj <= last ; jj++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n %% ipivot = %d, jj = %d, first = %d, last = %d, kstart = %d",
ipivot, jj, first, last, kstart) ;
#endif
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < first ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
first = last + 1 ;
}
}
}
} else {
/*
--------------------------------------
chevron is nonsymmetric, D is diagonal
--------------------------------------
*/
count = 0 ;
kstart = nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < jj ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = 0 ; jj < nD ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < jj ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
}
}
} break ;
case CHV_UPPER_12 : {
int ii, jj, kinc, kk, kstart, ncol, stride ;
/*
----------------------------------------
count the big entries in the (1,2) block
----------------------------------------
*/
ncol = nD + nU ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n symmetric chevron, npivot = %d, pivotsizes = %p",
npivot, pivotsizes) ;
#endif
/*
--------------------
chevron is symmetric
--------------------
*/
count = 0 ;
kstart = nD ;
stride = nD + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc-- ;
}
kstart++ ;
}
}
} else {
/*
-----------------------
chevron is nonsymmetric
-----------------------
*/
count = 0 ;
kstart = 2*nD + nL - 1 ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++ ) {
absval = fabs(entries[kk]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( jj = nD ; jj < ncol ; jj++ ) {
kk = kstart ;
kinc = stride ;
for ( ii = 0 ; ii < nD ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
if ( absval >= droptol ) {
#if MYDEBUG > 0
fprintf(stdout, ", keep") ;
#endif
count++ ;
}
kk += kinc ;
kinc -= 2 ;
}
kstart++ ;
}
}
}
} break ;
default :
break ;
}
return(count) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------
purpose -- copy the trailing chevron that starts at offset
created -- 97may16, cca
----------------------------------------------------------
*/
void
Chv_copyTrailingPortion (
Chv *chvI,
Chv *chvJ,
int offset
) {
int first, ncolI, ncolJ, nDJ, nentToCopy, nLJ, nrowI, nrowJ, nUJ ;
int *colindI, *colindJ, *rowindI, *rowindJ ;
/*
--------------
check the data
--------------
*/
if ( chvI == NULL || chvJ == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_copyTrailingPortion(%p,%p,%d)"
"\n bad input\n", chvI, chvJ, offset) ;
exit(-1) ;
}
Chv_dimensions(chvJ, &nDJ, &nLJ, &nUJ) ;
if ( offset < 0 || offset >= nDJ ) {
fprintf(stderr,
"\n fatal error in Chv_copyTrailingPortion(%p,%p,%d)"
"\n nDJ = %d, offset = %d\n",
chvI, chvJ, offset, nDJ, offset) ;
exit(-1) ;
}
/*
----------------------------------------------
initialize the chvI object and find the number
of and first location of the entries to copy
----------------------------------------------
*/
Chv_columnIndices(chvJ, &ncolJ, &colindJ) ;
if ( CHV_IS_SYMMETRIC(chvJ) || CHV_IS_HERMITIAN(chvJ) ) {
Chv_init(chvI, chvJ->id, nDJ - offset, 0, nUJ,
chvJ->type, chvJ->symflag) ;
Chv_columnIndices(chvI, &ncolI, &colindI) ;
IVcopy(nDJ + nUJ - offset, colindI, colindJ + offset) ;
first = offset*(nDJ + nUJ) - (offset*(offset-1))/2 ;
nentToCopy = (nDJ*(nDJ+1))/2 + nDJ*nUJ - first ;
} else {
Chv_rowIndices(chvJ, &nrowJ, &rowindJ) ;
Chv_init(chvI, chvJ->id, nDJ - offset, nLJ, nUJ,
chvJ->type, chvJ->symflag) ;
Chv_columnIndices(chvI, &ncolI, &colindI) ;
IVcopy(nDJ + nUJ - offset, colindI, colindJ + offset) ;
Chv_rowIndices(chvI, &nrowI, &rowindI) ;
IVcopy(nDJ + nLJ - offset, rowindI, rowindJ + offset) ;
first = offset*(2*nDJ + nLJ + nUJ - offset) ;
nentToCopy = nDJ*(nDJ + nLJ + nUJ) - first ;
}
if ( CHV_IS_REAL(chvJ) ) {
DVcopy(nentToCopy, Chv_entries(chvI), Chv_entries(chvJ) + first) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
DVcopy(2*nentToCopy, Chv_entries(chvI), Chv_entries(chvJ) + 2*first);
}
return ; }
/*--------------------------------------------------------------------*/
kinc = stride ;
for ( ii = 0 ; ii < jj ; ii++ ) {
absval = Zabs(entries[2*kk], entries[2*kk+1]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% |A(%d,%d)| = %20.12e, kk = %d",
ii, jj, absval, kk) ;
#endif
Chv/src/factor.c 0100644 0002055 0007177 00000107520 06574041670 0015040 0 ustar 00cleve compmath 0000040 0000006 /* factor.c */
#include "../Chv.h"
#define MYDEBUG 0
#define MYCHECK 0
/*--------------------------------------------------------------------*/
/*
------------------------------------------------
purpose -- to factor the front without pivoting
return value -- # of eliminated rows and columns
created -- 98aug27, cca
------------------------------------------------
*/
int
Chv_factorWithNoPivoting (
Chv *chv,
PatchAndGoInfo *info
) {
Chv wrkChv ;
int ncol, nD, nelim, nrow ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_factorWithNoPivoting()"
"\n bad input\n") ;
exit(-1) ;
}
nD = chv->nD ;
/*
--------------------------
set up the working chevron
--------------------------
*/
Chv_setDefaultFields(&wrkChv) ;
Chv_rowIndices(chv, &nrow, &rowind) ;
Chv_columnIndices(chv, &ncol, &colind) ;
Chv_initWithPointers(&wrkChv, chv->id, nD, chv->nL, chv->nU, chv->type,
chv->symflag, rowind, colind, Chv_entries(chv)) ;
/*
-------------------------------------
switch over the patch-and-go strategy
-------------------------------------
*/
if ( info == NULL ) {
/*
------------------
simple no pivoting
------------------
*/
nelim = 0 ;
while ( nelim < nD ) {
if ( Chv_r1upd(&wrkChv) == 0 ) {
break ;
}
Chv_shift(&wrkChv, 1) ;
nelim++ ;
}
} else if ( info->strategy == 1 ) {
double colmaxabs, diagabs, offmaxabs, rowmaxabs ;
/*
----------------------------------------
Patch-and-go for optimization matrices.
if |diag| < toosmall * max|offdiag| then
diag = 1.0
offdiag = 0.0
endif
----------------------------------------
*/
for ( nelim = 0 ; nelim < nD ; nelim++ ) {
Chv_maxabsInChevron(&wrkChv, 0, &diagabs, &rowmaxabs, &colmaxabs);
offmaxabs = (rowmaxabs >= colmaxabs) ? rowmaxabs : colmaxabs ;
if ( diagabs <= info->toosmall * offmaxabs ) {
if ( CHV_IS_REAL(chv) ) {
wrkChv.entries[0] = 1.0 ;
} else {
wrkChv.entries[0] = 1.0 ;
wrkChv.entries[1] = 0.0 ;
}
Chv_zeroOffdiagonalOfChevron(chv, 0) ;
if ( info->fudgeIV != NULL ) {
IV_push(info->fudgeIV, chv->colind[0]) ;
}
}
Chv_r1upd(&wrkChv) ;
Chv_shift(&wrkChv, 1) ;
}
} else if ( info->strategy == 2 ) {
double colmaxabs, diagabs, olddiag, newdiag, offmaxabs, rowmaxabs ;
/*
----------------------------------------------
Patch-and-go for structural analysis matrices.
if |diag| < fudge then
diag = fudge * max(max|offdiag|, 1.0)
endif
----------------------------------------------
*/
for ( nelim = 0 ; nelim < nD ; nelim++ ) {
Chv_maxabsInChevron(&wrkChv, 0, &diagabs, &rowmaxabs, &colmaxabs);
offmaxabs = (rowmaxabs >= colmaxabs) ? rowmaxabs : colmaxabs ;
if ( diagabs <= info->fudge ) {
olddiag = diagabs ;
if ( offmaxabs < 1.0 ) {
offmaxabs = 1.0 ;
}
if ( CHV_IS_REAL(chv) ) {
wrkChv.entries[0] = newdiag = info->fudge * offmaxabs ;
} else {
wrkChv.entries[0] = newdiag = info->fudge * offmaxabs ;
wrkChv.entries[1] = 0.0 ;
}
if ( info->fudgeIV != NULL ) {
IV_push(info->fudgeIV, chv->colind[0]) ;
}
if ( info->fudgeDV != NULL ) {
DV_push(info->fudgeDV, fabs(olddiag - newdiag)) ;
}
}
Chv_r1upd(&wrkChv) ;
Chv_shift(&wrkChv, 1) ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_factorWithNoPivoting()"
"\n patch-and-go info != NULL, strategy = %d",
info->strategy) ;
exit(-1) ;
}
return(nelim) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
purpose -- factor the pivot chevron with pivoting
ndelay -- number of delayed rows and columns
pivotflag -- enable pivoting or not
0 --> no pivoting
1 --> enable pivoting
pivotsizesIV -- IV object that holds the sizes of the pivots,
used only when the front is symmetric or hermitian
and pivoting is enabled
workDV -- DV object used for working storage, resized as necessary
tau -- upper bound on the magnitude of the entries
in the factors, used only when pivoting is enabled
pntest -- pointer to be incremented with the number of pivot tests
return value -- # of eliminated rows and columns
created -- 98aug27, cca
------------------------------------------------------------------
*/
int
Chv_factorWithPivoting (
Chv *chv,
int ndelay,
int pivotflag,
IV *pivotsizesIV,
DV *workDV,
double tau,
int *pntest
) {
Chv wrkChv ;
int irow, jcol, ncol, nD, nelim, nrow, pivotsize ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || pivotflag != 1 || ndelay < 0 ) {
fprintf(stderr, "\n fatal error in Chv_factorWithPivoting()"
"\n bad input\n") ;
exit(-1) ;
}
if ( workDV == NULL ) {
fprintf(stderr, "\n fatal error in Chv_factorWithPivoting()"
"\n workDV is NULL \n") ;
exit(-1) ;
}
if ( tau < 1.0 ) {
fprintf(stderr, "\n fatal error in Chv_factorWithPivoting()"
"\n tau = %f is invalid \n", tau) ;
exit(-1) ;
}
if ( CHV_IS_REAL(chv) && CHV_IS_SYMMETRIC(chv)
&& pivotsizesIV == NULL ) {
fprintf(stderr, "\n fatal error in Chv_factorWithPivoting()"
"\n real symmetric front"
"\n pivoting enabled, pivotsizesIV is NULL\n") ;
exit(-1) ;
}
if ( CHV_IS_COMPLEX(chv)
&& (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv))
&& pivotsizesIV == NULL ) {
fprintf(stderr, "\n fatal error in Chv_factorWithPivoting()"
"\n complex symmetric or hermitian front"
"\n pivoting enabled, pivotsizesIV is NULL\n") ;
exit(-1) ;
}
nD = chv->nD ;
/*
--------------------------
set up the working chevron
--------------------------
*/
Chv_setDefaultFields(&wrkChv) ;
Chv_rowIndices(chv, &nrow, &rowind) ;
Chv_columnIndices(chv, &ncol, &colind) ;
Chv_initWithPointers(&wrkChv, chv->id, nD, chv->nL, chv->nU, chv->type,
chv->symflag, rowind, colind, Chv_entries(chv)) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n after initializing wrkChv") ;
Chv_writeForHumanEye(&wrkChv, stdout) ;
fflush(stdout) ;
#endif
/*
-----------------------------
switch over the symmetry flag
-----------------------------
*/
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n\n pivoting, hermitian or symmetric front %d", chv->id) ;
fflush(stdout) ;
#endif
/*
-------------------------
symmetric structure front
-------------------------
*/
IV_setSize(pivotsizesIV, 0) ;
nelim = 0 ;
while ( nelim < nD ) {
/*
-------------------------
find the 1x1 or 2x2 pivot
-------------------------
*/
#if MYDEBUG > 0
fprintf(stdout,
"\n trying to find pivot, nelim = %d, nD = %d, ndelay = %d",
nelim, nD, ndelay) ;
fflush(stdout) ;
#endif
pivotsize = Chv_findPivot(&wrkChv, workDV, tau, ndelay,
&irow, &jcol, pntest) ;
if ( irow > jcol ) {
int itemp = irow ;
irow = jcol ;
jcol = itemp ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n pivotsize = %d, local irow = %d, local jcol = %d",
pivotsize, irow, jcol) ;
fflush(stdout) ;
#endif
irow += nelim ;
jcol += nelim ;
if ( pivotsize == 0 ) {
/*
---------------------------------
no pivot found, break out of loop
---------------------------------
*/
break ;
} else {
ndelay = 0 ;
if ( irow == jcol ) {
/*
------------------------------------------------------
1x1 pivot found, swap row and column, update and shift
------------------------------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n\n before swaps") ;
Chv_writeForHumanEye(chv, stdout) ;
fflush(stdout) ;
#endif
Chv_swapRowsAndColumns(chv, nelim, irow) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n after swaps") ;
Chv_writeForHumanEye(chv, stdout) ;
fflush(stdout) ;
#endif
#if MYDEBUG > 0
fprintf(stdout, "\n\n nelim = %d, before update", nelim) ;
Chv_writeForHumanEye(&wrkChv, stdout) ;
fflush(stdout) ;
#endif
if ( Chv_r1upd(&wrkChv) == 0 ) {
break ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n nelim = %d, after update", nelim) ;
Chv_writeForHumanEye(&wrkChv, stdout) ;
fflush(stdout) ;
#endif
Chv_shift(&wrkChv, 1) ;
nelim++ ;
IV_push(pivotsizesIV, 1) ;
} else {
/*
--------------------------------------------------------
2x2 pivot found, swap rows and columns, update and shift
--------------------------------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n\n before swaps") ;
Chv_writeForHumanEye(chv, stdout) ;
fflush(stdout) ;
#endif
Chv_swapRowsAndColumns(chv, nelim, irow) ;
Chv_swapRowsAndColumns(chv, nelim+1, jcol) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n after swaps") ;
Chv_writeForHumanEye(chv, stdout) ;
fflush(stdout) ;
#endif
#if MYDEBUG > 0
fprintf(stdout, "\n\n irow = %d, jcol = %d", irow, jcol) ;
fprintf(stdout, "\n\n nelim = %d, before update", nelim) ;
#endif
#if MYDEBUG > 0
Chv_writeForHumanEye(&wrkChv, stdout) ;
fflush(stdout) ;
#endif
if ( Chv_r2upd(&wrkChv) == 0 ) {
break ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n nelim = %d, after update", nelim) ;
Chv_writeForHumanEye(&wrkChv, stdout) ;
fflush(stdout) ;
#endif
Chv_shift(&wrkChv, 2) ;
nelim += 2 ;
IV_push(pivotsizesIV, 2) ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n ok, done with this pivot") ;
fflush(stdout) ;
#endif
}
} else {
/*
------------------
nonsymmetric front
------------------
*/
nelim = 0 ;
while ( nelim < nD ) {
/*
------------------
find the 1x1 pivot
------------------
*/
pivotsize = Chv_findPivot(&wrkChv, workDV, tau, ndelay,
&irow, &jcol, pntest) ;
irow += nelim ;
jcol += nelim ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n irow = %d, jcol = %d", irow, jcol) ;
fflush(stdout) ;
#endif
if ( pivotsize == 0 ) {
/*
---------------------------------
no pivot found, break out of loop
---------------------------------
*/
break ;
} else {
ndelay = 0 ;
/*
------------------------------------------------------
1x1 pivot found, swap row and column, update and shift
------------------------------------------------------
*/
#if MYDEBUG > 1
fprintf(stdout, "\n\n before swaps") ;
Chv_writeForHumanEye(chv, stdout) ;
fflush(stdout) ;
#endif
Chv_swapRows(chv, nelim, irow) ;
Chv_swapColumns(chv, nelim, jcol) ;
#if MYDEBUG > 1
fprintf(stdout, "\n\n after swaps") ;
Chv_writeForHumanEye(chv, stdout) ;
fflush(stdout) ;
#endif
#if MYDEBUG > 0
fprintf(stdout, "\n\n nelim = %d, before update", nelim) ;
fflush(stdout) ;
#endif
#if MYDEBUG > 1
Chv_writeForHumanEye(&wrkChv, stdout) ;
fflush(stdout) ;
#endif
if ( Chv_r1upd(&wrkChv) == 0 ) {
break ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n nelim = %d, after update", nelim) ;
#endif
#if MYDEBUG > 1
Chv_writeForHumanEye(&wrkChv, stdout) ;
fflush(stdout) ;
#endif
Chv_shift(&wrkChv, 1) ;
nelim++ ;
}
}
}
return(nelim) ; }
/*--------------------------------------------------------------------*/
static int symmetric1x1 ( Chv *chv ) ;
static int nonsym1x1 ( Chv *chv) ;
static int symmetric2x2 ( Chv *chv ) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
perform a rank one update using the first row and column.
this is used in the (L + I)D(I + U) factorization
return code ---
0 if the pivot was zero
1 if the pivot was nonzero
created -- 98jan23, cca
---------------------------------------------------------
*/
int
Chv_r1upd (
Chv *chv
) {
int rc = 0 ;
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_r1upd(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
if ( CHV_IS_NONSYMMETRIC(chv) ) {
rc = nonsym1x1(chv) ;
} else if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
rc = symmetric1x1(chv) ;
} else {
fprintf(stderr, "\n fatal error in Chv_r1upd(%p)"
"\n symflag = %d\n", chv, chv->symflag) ;
exit(-1) ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
perform a rank two update using the first two rows.
used in the (U^T + I)D(I + U) and (U^H + I)D(I + U) factorizations
return code ---
0 if the pivot was zero
1 if the pivot was nonzero
created -- 98jan23, cca
------------------------------------------------------------------
*/
int
Chv_r2upd (
Chv *chv
) {
int rc = 0 ;
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_r2upd(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
if ( !(CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_r2upd(%p)"
"\n symflag = %d\n", chv, chv->symflag) ;
exit(-1) ;
}
rc = symmetric2x2(chv) ;
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
perform an internal rank-1 update for a symmetric chevron
return code ---
0 if the pivot was zero
1 if the pivot was nonzero
created -- 98jan23, cca
------------------------------------------------------------
*/
static int
symmetric1x1 (
Chv *chv
) {
double dimag, dreal, fac1, fac2, limag, lreal, uimag, ureal ;
double *entries ;
int dloc, dstride, kchv, nD, nL, nU, uijloc, ukbeg, usize ;
/*
-------------------------------------
get dimensions and pointer to entries
-------------------------------------
*/
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
#if MYDEBUG > 0
fprintf(stdout, "\n nD = %d, nL = %d, nU = %d, entries = %p",
nD, nL, nU, entries) ;
#endif
/*
----------------------------------------------
dloc : offset to the first diagonal element
dstride : stride to next diagonal element
usize : size of first row in upper part
----------------------------------------------
*/
dloc = 0 ;
dstride = nD + nU ;
usize = nD + nU - 1 ;
#if MYDEBUG > 0
fprintf(stdout, "\n dloc = %d, dstride = %d, usize = %d",
dloc, dstride, usize) ;
#endif
/*
----------------------
check for a zero pivot
----------------------
*/
if ( CHV_IS_REAL(chv) ) {
dreal = entries[dloc] ;
if ( dreal == 0.0 ) {
return(0) ;
}
fac1 = 1./dreal ;
} else if ( CHV_IS_COMPLEX(chv) ) {
dreal = entries[2*dloc] ;
dimag = entries[2*dloc+1] ;
if ( dreal == 0.0 && dimag == 0.0 ) {
return(0) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n chv->id = %d : (dreal,dimag) = <%12.4e,%12.4e>",
chv->id, dreal, dimag) ;
fprintf(stdout, "\n (dreal,dimag) = <%12.4e,%12.4e>",
dreal, dimag) ;
#endif
/*
------------------------------
compute (fac1,fac2) = 1/d(0,0)
------------------------------
*/
if ( CHV_IS_HERMITIAN(chv) ) {
fac1 = 1./dreal ; fac2 = 0.0 ;
entries[2*dloc+1] = 0.0 ;
} else {
Zrecip(dreal, dimag, &fac1, &fac2) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n 1/(dreal,dimag) = <%12.4e,%12.4e>",
fac1, fac2) ;
#endif
}
/*
------------------------
scale the first row of U
------------------------
*/
if ( CHV_IS_REAL(chv) ) {
DVscale(usize, &entries[1], fac1) ;
} else if ( CHV_IS_HERMITIAN(chv) ) {
DVscale(2*usize, &entries[2], fac1) ;
} else {
ZVscale(usize, &entries[2], fac1, fac2) ;
}
/*
------------------------------------
loop over the following chevrons
uijloc -- offset into uij multiplier
------------------------------------
*/
uijloc = dloc + 1 ;
for ( kchv = 1 ; kchv < nD ; kchv++ ) {
/*
--------------------------------------------------
dloc now points to next diagonal location
ukbeg -- offset into start of row in upper part
--------------------------------------------------
*/
dloc += dstride ;
ukbeg = dloc + 1 ;
#if MYDEBUG > 0
fprintf(stdout, "\n kchv = %5d, dloc = %5d"
"\n uijloc = %5d, usize = %5d, ukbeg = %5d",
kchv, dloc, uijloc, usize, ukbeg) ;
#endif
/*
------------------------------------
pull out the multiplier coefficients
------------------------------------
*/
if ( CHV_IS_REAL(chv) ) {
ureal = entries[uijloc] ;
lreal = dreal*ureal ;
} else if ( CHV_IS_COMPLEX(chv) ) {
ureal = entries[2*uijloc] ;
uimag = entries[2*uijloc+1] ;
if (CHV_IS_HERMITIAN(chv) ) {
lreal = dreal*ureal ;
limag = -dreal*uimag ;
} else {
lreal = dreal*ureal - dimag*uimag ;
limag = dreal*uimag + dimag*ureal ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n (lreal,limag) = <%12.4e,%12.4e>"
"\n (ureal,uimag) = <%12.4e,%12.4e>",
lreal, limag, ureal, uimag) ;
#endif
}
/*
-------------------------------------------------
update the upper row including the diagonal entry
-------------------------------------------------
*/
if ( CHV_IS_REAL(chv) ) {
DVaxpy(usize, &entries[dloc], -lreal, &entries[uijloc]) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
ZVaxpy(usize, &entries[2*dloc], -lreal, -limag,
&entries[2*uijloc]) ;
}
/*
----------------------------------
adjust offsets and diagonal stride
----------------------------------
*/
uijloc++ ; dstride-- ; usize-- ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
perform an internal rank-1 update for a nonsymmetric chevron
return code ---
0 if the pivot was zero
1 if the pivot was nonzero
created -- 98jan23, cca
------------------------------------------------------------
*/
static int
nonsym1x1 (
Chv *chv
) {
double dimag, dreal, fac1, fac2, limag, lreal, uimag, ureal ;
double *entries ;
int dloc, dstride, kchv, ljiloc, lkbeg, lsize, nD, nL, nU,
uijloc, ukbeg, usize ;
/*
-------------------------------------
get dimensions and pointer to entries
-------------------------------------
*/
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
#if MYDEBUG > 0
fprintf(stdout, "\n nD = %d, nL = %d, nU = %d, entries = %p",
nD, nL, nU, entries) ;
#endif
/*
----------------------------------------------
dloc : offset to the first diagonal element
dstride : stride to next diagonal element
lsize : size of first column in lower part
usize : size of first row in upper part
----------------------------------------------
*/
dloc = nD + nL - 1 ;
dstride = 2*nD + nL + nU - 2 ;
lsize = nD + nL - 1 ;
usize = nD + nU - 1 ;
#if MYDEBUG > 0
fprintf(stdout, "\n dloc = %d, dstride = %d, lsize = %d, usize = %d",
dloc, dstride, lsize, usize) ;
#endif
/*
----------------------
check for a zero pivot
----------------------
*/
if ( CHV_IS_REAL(chv) ) {
dreal = entries[dloc] ;
if ( dreal == 0.0 ) {
return(0) ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
dreal = entries[2*dloc] ;
dimag = entries[2*dloc+1] ;
if ( dreal == 0.0 && dimag == 0.0 ) {
return(0) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n (dreal,dimag) = <%12.4e,%12.4e>",
dreal, dimag) ;
#endif
}
/*
-----------------------------------------
compute the inverse of the diagonal pivot
real: fac1 = 1/d(0,0)
complex: (fac1,fac2) = 1/d(0,0)
-----------------------------------------
*/
if ( CHV_IS_REAL(chv) ) {
fac1 = 1./dreal ;
} else if ( CHV_IS_COMPLEX(chv) ) {
Zrecip(dreal, dimag, &fac1, &fac2) ;
#if MYDEBUG > 0
fprintf(stdout, "\n 1/(dreal,dimag) = <%12.4e,%12.4e>",
fac1, fac2) ;
#endif
}
/*
---------------------------
scale the first column of L
(fac1,fac2) = 1/d(0,0)
---------------------------
*/
if ( CHV_IS_REAL(chv) ) {
DVscale(lsize, entries, fac1) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
ZVscale(lsize, entries, fac1, fac2) ;
#if MYDEBUG > 2
{ double real, imag ;
int irow ;
fprintf(stdout, "\n entries in L after scaling") ;
for ( irow = 1 ; irow < nD + nL ; irow++ ) {
Chv_entry(chv, irow, 0, &real, &imag) ;
fprintf(stdout, "\n %% A(%d,%d) = %20.12e + %20.12ei",
irow, 0, real, imag) ;
}
}
#endif
}
/*
------------------------------------
loop over the following chevrons
ljiloc -- offset into lij multiplier
uijloc -- offset into uij multiplier
------------------------------------
*/
ljiloc = dloc - 1 ;
uijloc = dloc + 1 ;
for ( kchv = 1 ; kchv < nD ; kchv++ ) {
/*
--------------------------------------------------
dloc now points to next diagonal location
lsize and usize decremented
lkbeg -- offset into start of column in lower part
ukbeg -- offset into start of row in upper part
--------------------------------------------------
*/
dloc += dstride ;
lsize-- ;
usize-- ;
lkbeg = dloc - lsize ;
ukbeg = dloc + 1 ;
#if MYDEBUG > 0
fprintf(stdout,
"\n kchv = %5d, dloc = %5d"
"\n ljiloc = %5d, uijloc = %5d"
"\n lsize = %5d, usize = %5d"
"\n lkbeg = %5d, ukbeg = %5d",
kchv, dloc, ljiloc, uijloc, lsize, usize, lkbeg, ukbeg) ;
#endif
/*
------------------------------------
pull out the multiplier coefficients
------------------------------------
*/
if ( CHV_IS_REAL(chv) ) {
lreal = entries[ljiloc] ;
ureal = entries[uijloc] ;
} else if ( CHV_IS_COMPLEX(chv) ) {
lreal = entries[2*ljiloc] ;
limag = entries[2*ljiloc+1] ;
ureal = entries[2*uijloc] ;
uimag = entries[2*uijloc+1] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n (lreal,limag) = <%12.4e,%12.4e>"
"\n (ureal,uimag) = <%12.4e,%12.4e>",
lreal, limag, ureal, uimag) ;
#endif
}
/*
-------------------------
update the diagonal entry
-------------------------
*/
if ( CHV_IS_REAL(chv) ) {
entries[dloc] -= lreal*ureal ;
} else if ( CHV_IS_COMPLEX(chv) ) {
entries[2*dloc] -= lreal*ureal - limag*uimag ;
entries[2*dloc+1] -= lreal*uimag + limag*ureal ;
}
/*
-----------------------
update the lower column
-----------------------
*/
if ( CHV_IS_REAL(chv) ) {
DVaxpy(lsize, &entries[lkbeg], -ureal, entries) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
ZVaxpy(lsize, &entries[2*lkbeg], -ureal, -uimag, entries) ;
}
/*
--------------------
update the upper row
--------------------
*/
if ( CHV_IS_REAL(chv) ) {
DVaxpy(usize, &entries[ukbeg], -lreal, &entries[uijloc+1]) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
ZVaxpy(usize, &entries[2*ukbeg],
-lreal, -limag, &entries[2*uijloc+2]) ;
}
/*
----------------------------------
adjust offsets and diagonal stride
----------------------------------
*/
ljiloc-- ; uijloc++ ; dstride -= 2 ;
}
/*
------------------
scale the row of U
------------------
*/
usize = nD + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
DVscale(usize, &entries[nD+nL], fac1) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
ZVscale(usize, &entries[2*(nD+nL)], fac1, fac2) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------
perform an internal rank-2 update for
a hermitian or symmetric chevron
return code ---
0 if the pivot was zero
1 if the pivot was nonzero
created -- 98jan23, cca
-------------------------------------
*/
static int
symmetric2x2 (
Chv *chv
) {
double areal, aimag, breal, bimag, creal, cimag,
ereal, eimag, freal, fimag, greal, gimag,
l0imag, l1imag, l0real, l1real,
u0imag, u1imag, u0real, u1real ;
double *entries ;
int dloc, dstride, kchv, nD, nL, nU, rc,
u0jloc, u1jloc, ukbeg, usize ;
/*
-------------------------------------
get dimensions and pointer to entries
-------------------------------------
*/
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
#if MYDEBUG > 0
fprintf(stdout, "\n nD = %d, nL = %d, nU = %d, entries = %p",
nD, nL, nU, entries) ;
#endif
/*
----------------------------------------
check for a zero pivot
D = [ a b ] for hermitian
[ conj(b) c ]
D = [ a b ] for symmetric
[ b c ]
compute the inverse of D
E = inv(D) = [ e f ] for hermitian
[ conj(f) g ]
E = inv(D) = [ e f ] for symmetric
[ f g ]
----------------------------------------
*/
if ( CHV_IS_REAL(chv) ) {
double denom ;
areal = entries[0] ;
breal = entries[1] ;
creal = entries[nD+nU] ;
if ( (denom = areal*creal - breal*breal) == 0.0 ) {
rc = 0 ;
} else {
rc = 1 ;
denom = 1./denom ;
ereal = creal*denom ;
freal = -breal*denom ;
greal = areal*denom ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
areal = entries[0] ;
aimag = entries[1] ;
breal = entries[2] ;
bimag = entries[3] ;
creal = entries[2*(nD+nU)] ;
cimag = entries[2*(nD+nU)+1] ;
#if MYDEBUG > 0
if ( CHV_IS_HERMITIAN(chv) ) {
fprintf(stdout,
"\n hermitian D = [ <%12.4e,%12.4e> <%12.4e,%12.4e> ]"
"\n [ <%12.4e,%12.4e> <%12.4e,%12.4e> ]",
areal, aimag, breal, bimag,
breal, -bimag, creal, cimag) ;
} else {
fprintf(stdout,
"\n symmetric D = [ <%12.4e,%12.4e> <%12.4e,%12.4e> ]"
"\n [ <%12.4e,%12.4e> <%12.4e,%12.4e> ]",
areal, aimag, breal, bimag,
breal, bimag, creal, cimag) ;
}
#endif
if ( CHV_IS_HERMITIAN(chv) ) {
rc = Zrecip2(areal, 0.0, breal, bimag,
breal, -bimag, creal, 0.0,
&ereal, NULL, &freal, &fimag,
NULL, NULL, &greal, NULL) ;
eimag = gimag = 0.0 ;
} else {
rc = Zrecip2(areal, aimag, breal, bimag,
breal, bimag, creal, cimag,
&ereal, &eimag, &freal, &fimag,
NULL, NULL, &greal, &gimag) ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_symmetric2x2"
"\n chevron must be real or complex") ;
exit(-1) ;
}
if ( rc == 0 ) {
/*
-------------------------
pivot is singular, return
-------------------------
*/
return(0) ;
}
#if MYDEBUG > 0
if ( CHV_IS_HERMITIAN(chv) ) {
fprintf(stdout,
"\n hermitian DINV = [ <%12.4e,%12.4e> <%12.4e,%12.4e> ]"
"\n [ <%12.4e,%12.4e> <%12.4e,%12.4e> ]",
ereal, eimag, freal, fimag,
freal, -fimag, greal, gimag) ;
} else {
fprintf(stdout,
"\n symmetric DINV = [ <%12.4e,%12.4e> <%12.4e,%12.4e> ]"
"\n [ <%12.4e,%12.4e> <%12.4e,%12.4e> ]",
ereal, eimag, freal, fimag,
freal, fimag, greal, gimag) ;
}
#endif
/*
-----------------------------
scale the first two rows of U
-----------------------------
*/
u0jloc = 2 ;
u1jloc = nD + nU + 1 ;
usize = nD + nU - 2 ;
if ( CHV_IS_REAL(chv) ) {
DVscale2(usize, &entries[u0jloc], &entries[u1jloc],
ereal, freal, freal, greal) ;
} else if ( CHV_IS_HERMITIAN(chv) ) {
ZVscale2(usize, &entries[2*u0jloc], &entries[2*u1jloc],
ereal, 0.0, freal, fimag, freal, -fimag, greal, 0.0) ;
} else {
ZVscale2(usize, &entries[2*u0jloc], &entries[2*u1jloc],
ereal, eimag, freal, fimag, freal, fimag, greal, gimag) ;
}
#if MYDEBUG > 2
{ double real, imag ;
int irow, jcol ;
fprintf(stdout, "\n entries in U after scaling") ;
for ( irow = 0 ; irow <= 1 ; irow++ ) {
for ( jcol = 2 ; jcol < nD + nU ; jcol++ ) {
Chv_entry(chv, 0, jcol, &real, &imag) ;
fprintf(stdout, "\n %% A(%d,%d) = %20.12e + %20.12ei",
0, jcol, real, imag) ;
}
}
}
#endif
/*
------------------------------------
loop over the following chevrons
u0jloc -- offset into u0j multiplier
u1jloc -- offset into u1j multiplier
------------------------------------
*/
usize = nD + nU - 2 ;
dloc = nD + nU ;
dstride = nD + nU - 1 ;
for ( kchv = 2 ; kchv < nD ; kchv++ ) {
/*
--------------------------------------------------
dloc now points to next diagonal location
ukbeg -- offset into start of row in upper part
--------------------------------------------------
*/
dloc += dstride ;
ukbeg = dloc + 1 ;
#if MYDEBUG > 0
fprintf(stdout, "\n kchv = %5d, dloc = %5d"
"\n u0jloc = %5d, u1jloc = %d, usize = %5d, ukbeg = %5d",
kchv, dloc, u0jloc, u1jloc, usize, ukbeg) ;
#endif
/*
------------------------------------
pull out the multiplier coefficients
------------------------------------
*/
if ( CHV_IS_REAL(chv) ) {
u0real = entries[u0jloc] ;
u1real = entries[u1jloc] ;
l0real = u0real*areal + u1real*breal ;
l1real = u0real*breal + u1real*creal ;
} else if ( CHV_IS_COMPLEX(chv) ) {
u0real = entries[2*u0jloc] ;
u0imag = entries[2*u0jloc+1] ;
u1real = entries[2*u1jloc] ;
u1imag = entries[2*u1jloc+1] ;
if ( CHV_IS_HERMITIAN(chv) ) {
l0real = u0real*areal + u1real*breal - u1imag*bimag ;
l0imag = -u0imag*areal - u1real*bimag - u1imag*breal ;
l1real = u0real*breal + u0imag*bimag + u1real*creal ;
l1imag = u0real*bimag - u0imag*breal - u1imag*creal ;
} else {
l0real = u0real*areal - u0imag*aimag
+ u1real*breal - u1imag*bimag ;
l0imag = u0real*aimag + u0imag*areal
+ u1real*bimag + u1imag*breal ;
l1real = u0real*breal - u0imag*bimag
+ u1real*creal - u1imag*cimag ;
l1imag = u0real*bimag + u0imag*breal
+ u1real*cimag + u1imag*creal ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n (l0real,l0imag) = <%12.4e,%12.4e>"
"\n (l1real,l1imag) = <%12.4e,%12.4e>",
l0real, l0imag, l1real, l1imag) ;
#endif
}
/*
-------------------------------------------------
update the upper row including the diagonal entry
-------------------------------------------------
*/
if ( CHV_IS_REAL(chv) ) {
DVaxpy2(usize, &entries[dloc], -l0real, &entries[u0jloc],
-l1real, &entries[u1jloc]) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
ZVaxpy2(usize, &entries[2*dloc],
-l0real, -l0imag, &entries[2*u0jloc],
-l1real, -l1imag, &entries[2*u1jloc]) ;
}
/*
----------------------------------
adjust offsets and diagonal stride
----------------------------------
*/
u0jloc++ ; u1jloc++ ; dstride-- ; usize-- ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
purpose -- looking at just a single chevron inside the Chv object,
find the absolute value of the diagonal element, and
the maximum absolute values of the offdiagonal elements
in the chevron's row and column.
created -- 98aug26, cca
------------------------------------------------------------------
*/
void
Chv_maxabsInChevron (
Chv *chv,
int ichv,
double *pdiagmaxabs,
double *prowmaxabs,
double *pcolmaxabs
) {
double *pdiag ;
int length, loc, nD, nL, nU ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || ichv < 0 || ichv >= chv->nD
|| pdiagmaxabs == NULL || prowmaxabs == NULL || pcolmaxabs == NULL ) {
fprintf(stderr, "\n fatal error in Chv_maxabsInChevron()"
"\n bad input\n") ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
pdiag = Chv_diagLocation(chv, ichv) ;
length = nD - ichv - 1 + nU ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) ) {
*pdiagmaxabs = fabs(*pdiag) ;
*prowmaxabs = DVmaxabs(length, pdiag + 1, &loc) ;
*pcolmaxabs = *prowmaxabs ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
*pdiagmaxabs = fabs(*pdiag) ;
*prowmaxabs = DVmaxabs(length, pdiag + 1, &loc) ;
*pcolmaxabs = DVmaxabs(length, pdiag - length, &loc) ;
} else {
fprintf(stderr, "\n fatal error in Chv_maxabsInChevron()"
"\n chv is real, chv->symflag = %d"
"\n must be symmetric or nonsymmetric\n", chv->symflag) ;
exit(-1) ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
*pdiagmaxabs = Zabs(*pdiag, *(pdiag+1)) ;
*prowmaxabs = ZVmaxabs(length, pdiag + 2) ;
*pcolmaxabs = *prowmaxabs ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
*pdiagmaxabs = Zabs(*pdiag, *(pdiag+1)) ;
*prowmaxabs = ZVmaxabs(length, pdiag + 2) ;
*pcolmaxabs = ZVmaxabs(length, pdiag - 2*length) ;
} else {
fprintf(stderr, "\n fatal error in Chv_maxabsInChevron()"
"\n chv is complex, chv->symflag = %d"
"\n must be symmetric or nonsymmetric\n", chv->symflag) ;
exit(-1) ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_maxabsInChevron()"
"\n chv->type = %d, must be real or complex\n", chv->type) ;
exit(-1) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
purpose -- zero the offdiagonal entries of chevron ichv
created -- 98aug26, cca
-------------------------------------------------------
*/
void
Chv_zeroOffdiagonalOfChevron (
Chv *chv,
int ichv
) {
double *pdiag ;
int length, nD, nL, nU ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || ichv < 0 || ichv >= chv->nD ) {
fprintf(stderr, "\n fatal error in Chv_zeroOffdiagonalOfChevron()"
"\n bad input\n") ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
pdiag = Chv_diagLocation(chv, ichv) ;
length = nD - ichv - 1 + nU ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) ) {
DVzero(length, pdiag+1) ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
DVzero(length, pdiag + 1) ;
DVzero(length, pdiag - length) ;
} else {
fprintf(stderr,
"\n fatal error in Chv_zeroOffdiagonalOfChevron()"
"\n chv is real, chv->symflag = %d"
"\n must be symmetric or nonsymmetric\n", chv->symflag) ;
exit(-1) ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
ZVzero(length, pdiag+2) ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
ZVzero(length, pdiag+2) ;
ZVzero(length, pdiag-2*length) ;
} else {
fprintf(stderr,
"\n fatal error in Chv_zeroOffdiagonalOfChevron()"
"\n chv is complex, chv->symflag = %d"
"\n must be symmetric or nonsymmetric\n", chv->symflag) ;
exit(-1) ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_zeroOffdiagonalOfChevron()"
"\n chv->type = %d, must be real or complex\n", chv->type) ;
exit(-1) ;
}
return ; }
/*--------------------------------------------------------------------*/
ntries[2] ;
bimag = entries[3] ;
creal = entries[2*(nD+nU)] ;
cimag = entries[2*(nD+nU)+1] ;
#if MYDEBUG > 0
if ( CHV_IS_HERMITIAN(chv) ) {
fprintf(stdout,
Chv/src/findPivot.c 0100644 0002055 0007177 00000044072 06571267314 0015530 0 ustar 00cleve compmath 0000040 0000006 /* findPivot.c */
#include "../Chv.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
static int findPivotSH ( Chv *chv, DV *workDV, double tau,
int ndelay, int *pirow, int *pjcol, int *pntest ) ;
static int findPivotN ( Chv *chv, DV *workDV, double tau,
int ndelay, int *pirow, int *pjcol, int *pntest ) ;
static int nonsym1x1 ( Chv *chv, int irow, int jcol, double tau,
double rowmaxes[], double colmaxes[] ) ;
static int sym1x1 ( Chv *chv, int irow,
double tau, double rowmaxes[] );
static int sym2x2 ( Chv *chv, int irow, int jcol,
double tau, double rowmaxes[] ) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
purpose -- find and test a pivot
workDV -- object that contains work vectors
tau -- upper bound on magnitude of factor entries
ndelay -- number of delayed rows and columns on input
pirow -- pointer to be filled with pivot row
pjcol -- pointer to be filled with pivot column
pntest -- pointer to be incremented with the number of pivot tests
return value -- size of pivot
0 --> pivot not found
1 --> 1x1 pivot in row *pirow and column *pjcol
2 --> 2x2 pivot in rows and columns *pirow and *pjcol,
symmetric front only
created -- 98jan24, cca
------------------------------------------------------------------
*/
int
Chv_findPivot (
Chv *chv,
DV *workDV,
double tau,
int ndelay,
int *pirow,
int *pjcol,
int *pntest
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || workDV == NULL || tau < 1.0 || ndelay < 0
|| pirow == NULL || pjcol == NULL || pntest == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_findPivot(%p,%p,%f,%d,%p,%p,%p)"
"\n bad input\n",
chv, workDV, tau, ndelay, pirow, pjcol, pntest) ;
exit(-1) ;
}
if ( !(CHV_IS_REAL(chv) || CHV_IS_COMPLEX(chv)) ) {
fprintf(stderr,
"\n fatal error in Chv_findPivot(%p,%p,%f,%d,%p,%p,%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, workDV, tau, ndelay, pirow, pjcol, pntest, chv->type) ;
exit(-1) ;
}
if ( !(CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv)
|| CHV_IS_NONSYMMETRIC(chv)) ) {
fprintf(stderr,
"\n fatal error in Chv_findPivot(%p,%p,%f,%d,%p,%p,%p)"
"\n bad symflag %d"
"\n must be SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or CHV_NONSYMMETRIC\n",
chv, workDV, tau, ndelay, pirow, pjcol, pntest, chv->symflag) ;
exit(-1) ;
}
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
rc = findPivotSH(chv, workDV, tau, ndelay, pirow, pjcol, pntest) ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
rc = findPivotN(chv, workDV, tau, ndelay, pirow, pjcol, pntest) ;
} else {
fprintf(stderr,
"\n fatal error in Chv_findPivot(%p,%p,%f,%d,%p,%p,%p)"
"\n bad symflag %d\n", chv, workDV, tau, ndelay, pirow,
pjcol, pntest, chv->symflag) ;
exit(-1) ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
purpose -- find and test a pivot for a symmetric or hermitian matrix
workDV -- object that contains work vectors
tau -- upper bound on magnitude of factor entries
ndelay -- number of delayed rows and columns on input
pirow -- pointer to be filled with pivot row
pjcol -- pointer to be filled with pivot column
pntest -- pointer to be incremented with the number of pivot tests
return value -- size of pivot
0 --> pivot not found
1 --> 1x1 pivot in row *pirow and column *pjcol
2 --> 2x2 pivot in rows and columns *pirow and *pjcol,
symmetric front only
created -- 98apr18, cca
--------------------------------------------------------------------
*/
static int
findPivotSH (
Chv *chv,
DV *workDV,
double tau,
int ndelay,
int *pirow,
int *pjcol,
int *pntest
) {
double maxval ;
double *rowmaxes ;
int ii, irow, jrow, krow, ncand, nD,
ndouble, ntest, pivotsize, tag, untag ;
int *rowids, *rowmark ;
untag = 0 ;
tag = 1 ;
nD = chv->nD ;
#if MYDEBUG > 0
fprintf(stdout,
"\n %% findPivotSH, id = %d, nD = %d, nL = %d, nU = %d, ndelay = %d",
chv->id, chv->nD, chv->nL, chv->nU, ndelay) ;
fflush(stdout) ;
#endif
*pirow = *pjcol = -1 ;
ntest = *pntest ;
/*
------------------------------------
symmetric front, set up work vectors
------------------------------------
*/
if ( sizeof(int) == sizeof(double) ) {
ndouble = 3*nD ;
} else if ( 2*sizeof(int) == sizeof(double) ) {
ndouble = 2*nD ;
}
DV_setSize(workDV, ndouble) ;
rowmaxes = DV_entries(workDV) ;
DVfill(nD, rowmaxes, 0.0) ;
rowmark = (int *) (rowmaxes + nD) ;
rowids = rowmark + nD ;
if ( ndelay > 0 ) {
IVfill(ndelay, rowmark, untag) ;
IVfill(nD - ndelay, rowmark + ndelay, tag) ;
} else {
IVfill(nD, rowmark, tag) ;
}
ncand = 0 ;
do {
pivotsize = 0 ;
/*
--------------------
find candidate pivot
--------------------
*/
Chv_fastBunchParlettPivot(chv, rowmark, tag, &irow, &jrow) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% FBP: irow = %d, jrow = %d",
irow, jrow) ;
if ( irow != -1 ) {
double imag, real ;
Chv_entry(chv, irow, irow, &real, &imag) ;
fprintf(stdout, "\n%% entry(%d,%d) = %20.12e + %20.12e*i",
irow, irow, real, imag) ;
if ( jrow != irow ) {
Chv_entry(chv, irow, jrow, &real, &imag) ;
fprintf(stdout, "\n%% entry(%d,%d) = %20.12e + %20.12e*i",
irow, jrow, real, imag) ;
Chv_entry(chv, jrow, jrow, &real, &imag) ;
fprintf(stdout, "\n%% entry(%d,%d) = %20.12e + %20.12e*i",
jrow, jrow, real, imag) ;
}
}
fflush(stdout) ;
#endif
if ( irow == -1 ) {
/*
----------------------------------------------
unable to find pivot, break out of search loop
----------------------------------------------
*/
pivotsize = 0 ; break ;
} else {
/*
-------------------------------
(irow,jrow) is a possible pivot
mark as visited and get row max
-------------------------------
*/
Chv_maxabsInRow(chv, irow, &maxval) ;
rowmaxes[irow] = maxval ;
rowmark[irow] = untag ;
if ( irow != jrow ) {
Chv_maxabsInRow(chv, jrow, &maxval) ;
rowmaxes[jrow] = maxval ;
rowmark[jrow] = untag ;
}
if ( irow == jrow ) {
/*
------------------
test the 1x1 pivot
------------------
*/
pivotsize = sym1x1(chv, irow, tau, rowmaxes) ;
ntest++ ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% pivotsize from sym1x1 = %d", pivotsize) ;
#endif
if ( pivotsize == 1 ) {
*pirow = irow ; *pjcol = jrow ;
} else {
for ( ii = 0 ; ii < ncand ; ii++ ) {
/*
----------------------------------
test the 2x2 pivot (irow, krow)
where krow is a previous candidate
----------------------------------
*/
krow = rowids[ii] ;
pivotsize = sym2x2(chv, irow, krow, tau, rowmaxes) ;
ntest++ ;
if ( pivotsize == 2 ) {
*pirow = irow ; *pjcol = krow ; break ;
}
}
}
} else {
/*
-------------------------------
test the 2x2 pivot (irow, jrow)
-------------------------------
*/
pivotsize = sym2x2(chv, irow, jrow, tau, rowmaxes) ;
ntest++ ;
if ( pivotsize == 2 ) {
*pirow = irow ; *pjcol = jrow ;
} else {
for ( ii = 0 ; ii < ncand ; ii++ ) {
krow = rowids[ii] ;
/*
----------------------------------
test the 2x2 pivot (irow, krow)
where krow is a previous candidate
----------------------------------
*/
pivotsize = sym2x2(chv, irow, krow, tau, rowmaxes) ;
ntest++ ;
if ( pivotsize == 2 ) {
*pirow = irow ; *pjcol = krow ; break ;
}
/*
----------------------------------
test the 2x2 pivot (jrow, krow)
where krow is a previous candidate
----------------------------------
*/
pivotsize = sym2x2(chv, jrow, krow, tau, rowmaxes) ;
ntest++ ;
if ( pivotsize == 2 ) {
*pirow = jrow ; *pjcol = krow ; break ;
}
}
}
}
if ( pivotsize == 0 ) {
/*
------------------------
add new candidate row(s)
------------------------
*/
rowids[ncand++] = irow ;
if ( irow != jrow ) {
rowids[ncand++] = jrow ;
}
}
}
} while ( pivotsize == 0 ) ;
*pntest = ntest ;
return(pivotsize) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
purpose -- find and test a pivot for a nonsymmetric matrix
workDV -- object that contains work vectors
tau -- upper bound on magnitude of factor entries
ndelay -- number of delayed rows and columns on input
pirow -- pointer to be filled with pivot row
pjcol -- pointer to be filled with pivot column
pntest -- pointer to be incremented with the number of pivot tests
return value -- size of pivot
0 --> pivot not found
1 --> 1x1 pivot in row *pirow and column *pjcol
2 --> 2x2 pivot in rows and columns *pirow and *pjcol,
symmetric front only
created -- 98jan24, cca
------------------------------------------------------------------
*/
static int
findPivotN (
Chv *chv,
DV *workDV,
double tau,
int ndelay,
int *pirow,
int *pjcol,
int *pntest
) {
double maxval ;
double *colmaxes, *rowmaxes ;
int icol, ii, irow, jcol, jrow, ncand, nD,
ndouble, ntest, pivotsize, tag, untag ;
int *colids, *colmark, *rowids, *rowmark ;
untag = 0 ;
tag = 1 ;
nD = chv->nD ;
#if MYDEBUG > 0
fprintf(stdout,
"\n %% Chv_findPivot, id = %d, nD = %d, nL = %d, nU = %d, ndelay = %d",
chv->id, chv->nD, chv->nL, chv->nU, ndelay) ;
fflush(stdout) ;
#endif
*pirow = *pjcol = -1 ;
ntest = *pntest ;
/*
-------------------
set up work vectors
-------------------
*/
if ( sizeof(int) == sizeof(double) ) {
ndouble = 6*nD ;
} else if ( 2*sizeof(int) == sizeof(double) ) {
ndouble = 4*nD ;
}
DV_setSize(workDV, ndouble) ;
rowmaxes = DV_entries(workDV) ;
colmaxes = rowmaxes + nD ;
DVfill(nD, rowmaxes, 0.0) ;
DVfill(nD, colmaxes, 0.0) ;
rowmark = (int *) (colmaxes + nD) ;
colmark = rowmark + nD ;
rowids = colmark + nD ;
colids = rowids + nD ;
if ( ndelay > 0 ) {
IVfill(ndelay, rowmark, untag) ;
IVfill(nD - ndelay, rowmark + ndelay, tag) ;
IVfill(ndelay, colmark, untag) ;
IVfill(nD - ndelay, colmark + ndelay, tag) ;
} else {
IVfill(nD, rowmark, tag) ;
IVfill(nD, colmark, tag) ;
}
ncand = 0 ;
do {
pivotsize = 0 ;
/*
--------------------
find candidate pivot
--------------------
*/
Chv_quasimax(chv, rowmark, colmark, tag, &irow, &jcol) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% quasimax: irow = %d, jcol = %d",
irow, jcol) ;
if ( irow != -1 ) {
double imag, real ;
Chv_entry(chv, irow, jcol, &real, &imag) ;
fprintf(stdout, "\n%% entry(%d,%d) = %20.12e + %20.12e*i",
irow, jcol, real, imag) ;
}
fflush(stdout) ;
#endif
if ( irow == -1 ) {
/*
----------------------------------------------
unable to find pivot, break out of search loop
----------------------------------------------
*/
break ;
} else {
/*
------------------------------------------------------------
find the row max for row irow and column max for column jcol
------------------------------------------------------------
*/
Chv_maxabsInRow(chv, irow, &maxval) ;
rowmaxes[irow] = maxval ;
Chv_maxabsInColumn(chv, jcol, &maxval) ;
colmaxes[jcol] = maxval ;
rowmark[irow] = untag ;
colmark[jcol] = untag ;
/*
-------------------------------------
test the (irow,jcol) entry as a pivot
-------------------------------------
*/
pivotsize = nonsym1x1(chv, irow, jcol, tau, rowmaxes, colmaxes) ;
ntest++ ;
if ( pivotsize == 1 ) {
*pirow = irow ; *pjcol = jcol ;
} else {
/*
---------------------------------------
test the other matrix entries as pivots
---------------------------------------
*/
for ( ii = 0 ; ii < ncand ; ii++ ) {
jrow = rowids[ii] ;
icol = colids[ii] ;
/*
--------------------------
test the (irow,icol) entry
--------------------------
*/
pivotsize = nonsym1x1(chv, irow, icol, tau,
rowmaxes, colmaxes) ;
ntest++ ;
if ( pivotsize == 1 ) {
*pirow = irow ; *pjcol = icol ; break ;
}
/*
--------------------------
test the (jrow,jcol) entry
--------------------------
*/
pivotsize = nonsym1x1(chv, jrow, jcol, tau,
rowmaxes, colmaxes) ;
ntest++ ;
if ( pivotsize == 1 ) {
*pirow = jrow ; *pjcol = jcol ; break ;
}
}
/*
----------------------------------------------
no pivots found, add irow to candidate row ids
and add jcol to candidate column ids
----------------------------------------------
*/
rowids[ncand] = irow ;
colids[ncand] = jcol ;
ncand++ ;
}
}
} while ( pivotsize == 0 ) ;
*pntest = ntest ;
return(pivotsize) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
return 1 if the nonsymmetric 1x1 pivot passes
return 0 otherwise
created -- 98jan24, cca
---------------------------------------------
*/
static int
nonsym1x1 (
Chv *chv,
int irow,
int jcol,
double tau,
double rowmaxes[],
double colmaxes[]
) {
double cutoff, magn ;
int rc ;
if ( CHV_IS_REAL(chv) ) {
double value ;
Chv_realEntry(chv, irow, jcol, &value) ;
magn = fabs(value) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
double imag, real ;
Chv_complexEntry(chv, irow, jcol, &real, &imag) ;
magn = Zabs(real, imag) ;
}
cutoff = tau * magn ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% magn = %12.4e, cutoff = %12.4e", magn, cutoff) ;
fprintf(stdout, "\n %% rowmaxes[%d] = %12.4e, colmaxes[%d] = %12.4e",
irow, rowmaxes[irow], jcol, colmaxes[jcol]) ;
#endif
if ( rowmaxes[irow] <= cutoff && colmaxes[jcol] <= cutoff ) {
rc = 1 ;
} else {
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
return 1 if the symmetric 1x1 pivot passes
return 0 otherwise
created -- 98jan24, cca
------------------------------------------
*/
static int
sym1x1 (
Chv *chv,
int irow,
double tau,
double rowmaxes[]
) {
double cutoff ;
int rc ;
if ( CHV_IS_REAL(chv) ) {
double value ;
Chv_realEntry(chv, irow, irow, &value) ;
cutoff = tau * fabs(value) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
double imag, real ;
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
cutoff = tau * Zabs(real, imag) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n %% cutoff = %12.4e, rowmaxes[%d] = %12.4e",
cutoff, irow, rowmaxes[irow]) ;
#endif
if ( rowmaxes[irow] <= cutoff ) {
rc = 1 ;
} else {
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
return 2 if the symmetric 2x2 pivot passes
return 0 otherwise
created -- 98jan24, cca
------------------------------------------
*/
static int
sym2x2 (
Chv *chv,
int irow,
int jcol,
double tau,
double rowmaxes[]
) {
double amag, bmag, cmag, denom, val1, val2 ;
int rc ;
if ( CHV_IS_REAL(chv) ) {
double a, b, c ;
Chv_realEntry(chv, irow, irow, &a) ;
Chv_realEntry(chv, irow, jcol, &b) ;
Chv_realEntry(chv, jcol, jcol, &c) ;
amag = fabs(a) ;
bmag = fabs(b) ;
cmag = fabs(c) ;
denom = fabs(a*c - b*b) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
double aimag, areal, bimag, breal, cimag, creal, imag, real ;
Chv_complexEntry(chv, irow, irow, &areal, &aimag) ;
Chv_complexEntry(chv, irow, jcol, &breal, &bimag) ;
Chv_complexEntry(chv, jcol, jcol, &creal, &cimag) ;
if ( CHV_IS_HERMITIAN(chv) ) {
amag = fabs(areal) ;
bmag = Zabs(breal, bimag) ;
cmag = fabs(creal) ;
denom = fabs(areal*creal - breal*breal - bimag*bimag) ;
} else if ( CHV_IS_SYMMETRIC(chv) ) {
amag = Zabs(areal, aimag) ;
bmag = Zabs(breal, bimag) ;
cmag = Zabs(creal, cimag) ;
real = areal*creal - aimag*cimag - breal*breal + bimag*bimag ;
imag = areal*cimag + aimag*creal - 2*breal*bimag ;
denom = Zabs(real, imag) ;
}
}
#if MYDEBUG > 0
fprintf(stdout,
"\n amag = %20.12e ; "
"\n bmag = %20.12e ; "
"\n cmag = %20.12e ; ", amag, bmag, cmag) ;
#endif
if ( denom == 0.0 ) {
return(0) ;
}
val1 = (cmag*rowmaxes[irow] + bmag*rowmaxes[jcol])/denom ;
val2 = (bmag*rowmaxes[irow] + amag*rowmaxes[jcol])/denom ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% sym2x2"
"\n rowmax1 = %20.12e"
"\n rowmax2 = %20.12e"
"\n val1 = %20.12e"
"\n val2 = %20.12e"
"\n denom = %20.12e",
rowmaxes[irow], rowmaxes[jcol], val1, val2, denom) ;
#endif
if ( val1 <= tau && val2 <= tau ) {
rc = 2 ;
} else {
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
-----------------
*/
pivotsize = sym2x2(chv, irow, krow, tau, rowmaxes) ;
ntest++ ;
if ( pivotsize == 2 ) {
*pirow = irow ; *pjcol = krow ; break ;
}
/*
----------------------------------
test the 2x2 pivot (jrow, krow)
where krow is a previous candidate
----------------------------------
*/
pivotsizChv/src/init.c 0100644 0002055 0007177 00000027642 06571267314 0014535 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../Chv.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
return the number of bytes needed to store the chevron
created -- 98apr30, cca
------------------------------------------------------
*/
int
Chv_nbytesNeeded (
int nD,
int nL,
int nU,
int type,
int symflag
) {
int nbytes, nent, nint ;
/*
--------------
check the data
--------------
*/
if ( nD < 0 || nL < 0 || nU < 0 ) {
fprintf(stderr, "\n fatal error in Chv_nbytesNeeded()"
"\n bad input, nD = %d, nL = %d, nU = %d\n", nD, nL, nU) ;
exit(-1) ;
}
nbytes = 0 ;
switch ( type ) {
case SPOOLES_REAL :
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
nint = 6 + nD + nU ;
nent = (nD*(nD+1))/2 + nD*nU ;
break ;
case SPOOLES_NONSYMMETRIC :
nint = 6 + 2*nD + nL + nU ;
nent = nD*(nD + nL + nU) ;
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_nbytesNeeded()"
"\n type = SPOOLES_REAL, invalid symflag = %d"
"\n must be SPOOLES_SYMMETRIC or SPOOLES_NONSYMMETRIC\n",
symflag) ;
exit(-1) ;
}
if ( 2*sizeof(int) == sizeof(double) ) {
nbytes = ((nint + 1)/2 + nent)*sizeof(double) ;
} else if ( sizeof(int) == sizeof(double) ) {
nbytes = (nint + nent)*sizeof(double) ;
} else {
fprintf(stderr,
"\n fatal error in Chv_nbytesNeeded()"
"\n sizeof(int) = %d, sizeof(double) = %d",
sizeof(int), sizeof(double)) ;
exit(-1) ;
}
break ;
case SPOOLES_COMPLEX :
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN:
nint = 6 + nD + nU ;
nent = (nD*(nD+1))/2 + nD*nU ;
break ;
case SPOOLES_NONSYMMETRIC :
nint = 6 + 2*nD + nL + nU ;
nent = nD*(nD + nL + nU) ;
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_nbytesNeeded()"
"\n type = SPOOLES_COMPLEX, invalid symflag = %d"
"\n must be SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN"
"\n or SPOOLES_NONSYMMETRIC\n",
symflag) ;
exit(-1) ;
}
if ( 2*sizeof(int) == sizeof(double) ) {
nbytes = ((nint + 1)/2 + 2*nent)*sizeof(double) ;
} else if ( sizeof(int) == sizeof(double) ) {
nbytes = (nint + 2*nent)*sizeof(double) ;
} else {
fprintf(stderr,
"\n fatal error in Chv_nbytesNeeded()"
"\n sizeof(int) = %d, sizeof(double) = %d",
sizeof(int), sizeof(double)) ;
exit(-1) ;
}
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_nbytesNeeded()"
"\n invalid type = %d"
"\n must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
type) ;
break ;
}
return(nbytes) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
return the number of bytes in the workspace owned by this object
created -- 98apr30, cca
----------------------------------------------------------------
*/
int
Chv_nbytesInWorkspace (
Chv *chv
) {
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_nbytesInWorkspace(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
return(sizeof(double)*DV_maxsize(&chv->wrkDV)) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
set the number of bytes in the workspace owned by this object
created -- 98apr30, cca
----------------------------------------------------------------
*/
void
Chv_setNbytesInWorkspace (
Chv *chv,
int nbytes
) {
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_setNbytesInWorkspace(%p,%d)"
"\n bad input\n", chv, nbytes) ;
exit(-1) ;
}
DV_setSize(&chv->wrkDV, nbytes/sizeof(double)) ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
purpose -- set the fields
created -- 98apr30, cca
----------------------------
*/
void
Chv_setFields (
Chv *chv,
int id,
int nD,
int nL,
int nU,
int type,
int symflag
) {
double *dbuffer ;
int nint ;
int *ibuffer ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || nD <= 0 || nL < 0 || nU < 0 ) {
fprintf(stderr, "\n fatal error in Chv_setFields()"
"\n bad input, chv %p, nD %d, nL %d, nU %d\n",
chv, nD, nL, nU) ;
exit(-1) ;
}
switch ( type ) {
case SPOOLES_REAL :
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_NONSYMMETRIC :
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_setFields()"
"\n type = SPOOLES_REAL, symflag = %d"
"\n must be SPOOLES_SYMMETRIC or SPOOLES_NONSYMMETRIC\n",
symflag) ;
exit(-1) ;
}
break ;
case SPOOLES_COMPLEX :
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
case SPOOLES_NONSYMMETRIC :
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_setFields()"
"\n type = SPOOLES_COMPLEX, symflag = %d"
"\n must be SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN"
"\n or SPOOLES_NONSYMMETRIC\n",
symflag) ;
exit(-1) ;
}
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_setFields()"
"\n type = %d"
"\n must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
type) ;
exit(-1) ;
}
dbuffer = DV_entries(&chv->wrkDV) ;
ibuffer = (int *) dbuffer ;
/*
---------------------
set the scalar fields
---------------------
*/
chv->id = ibuffer[0] = id ;
chv->nD = ibuffer[1] = nD ;
chv->nL = ibuffer[2] = nL ;
chv->nU = ibuffer[3] = nU ;
chv->type = ibuffer[4] = type ;
chv->symflag = ibuffer[5] = symflag ;
/*
-------------------------------------------
set the colind, rowind and entries pointers
-------------------------------------------
*/
chv->colind = ibuffer + 6 ;
nint = 6 + nD + nU ;
if ( symflag == SPOOLES_NONSYMMETRIC ) {
chv->rowind = chv->colind + nD + nU ;
nint += nD + nL ;
} else {
chv->rowind = NULL ;
}
if ( sizeof(int) == sizeof(double) ) {
chv->entries = dbuffer + nint ;
} else if ( 2*sizeof(int) == sizeof(double) ) {
chv->entries = dbuffer + (nint + 1)/2 ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
purpose -- basic initializer
created -- 98apr30, cca
----------------------------
*/
void
Chv_init (
Chv *chv,
int id,
int nD,
int nL,
int nU,
int type,
int symflag
) {
int nbytes ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || nD <= 0 || nL < 0 || nU < 0 ) {
fprintf(stderr,
"\n fatal error in Chv_init()"
"\n bad input, chv %p, nD %d, nL %d, nU %d\n",
chv, nD, nL, nU) ;
exit(-1) ;
}
switch ( type ) {
case SPOOLES_REAL :
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_NONSYMMETRIC :
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_init()"
"\n type = SPOOLES_REAL, symflag = %d"
"\n must be SPOOLES_SYMMETRIC or SPOOLES_NONSYMMETRIC\n",
symflag) ;
exit(-1) ;
}
break ;
case SPOOLES_COMPLEX :
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
case SPOOLES_NONSYMMETRIC :
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_init()"
"\n type = SPOOLES_COMPLEX, symflag = %d"
"\n must be SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN"
"\n or SPOOLES_NONSYMMETRIC\n",
symflag) ;
exit(-1) ;
}
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_init()"
"\n type = %d"
"\n must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
type) ;
exit(-1) ;
}
/*
-------------------------------------------------------
get and set the number of bytes needed in the workspace
-------------------------------------------------------
*/
nbytes = Chv_nbytesNeeded(nD, nL, nU, type, symflag) ;
Chv_setNbytesInWorkspace(chv, nbytes) ;
/*
--------------
set the fields
--------------
*/
Chv_setFields(chv, id, nD, nL, nU, type, symflag) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
purpose -- initializer with pointers
created -- 98apr30, cca
------------------------------------
*/
void
Chv_initWithPointers (
Chv *chv,
int id,
int nD,
int nL,
int nU,
int type,
int symflag,
int *rowind,
int *colind,
double *entries
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL || nD <= 0 || nL < 0 || nU < 0 ) {
fprintf(stderr,
"\n fatal error in Chv_initWithPointers() "
"\n chv = %p, nD = %d, nL = %d, nU = %d\n",
chv, nD, nL, nU) ;
exit(-1) ;
}
if ( entries == NULL || colind == NULL
|| (symflag == SPOOLES_NONSYMMETRIC && rowind == NULL) ) {
fprintf(stderr,
"\n fatal error in Chv_init()"
"\n entries = %p, colind = %p, rowind = %p, symflag = %d\n",
entries, colind, rowind, symflag) ;
exit(-1) ;
}
switch ( type ) {
case SPOOLES_REAL :
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_NONSYMMETRIC :
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_initFromPointers()"
"\n type = SPOOLES_REAL, symflag = %d"
"\n must be SPOOLES_SYMMETRIC or SPOOLES_NONSYMMETRIC\n",
symflag) ;
exit(-1) ;
}
break ;
case SPOOLES_COMPLEX :
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
case SPOOLES_NONSYMMETRIC :
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_initFromPointers()"
"\n type = SPOOLES_COMPLEX, symflag = %d"
"\n must be SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN"
"\n or SPOOLES_NONSYMMETRIC\n",
symflag) ;
exit(-1) ;
}
break ;
default :
fprintf(stderr,
"\n fatal error in Chv_initFromPointers()"
"\n type = %d"
"\n must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
type) ;
exit(-1) ;
}
/*
---------------------
set the scalar fields
---------------------
*/
chv->id = id ;
chv->nD = nD ;
chv->nL = nL ;
chv->nU = nU ;
chv->type = type ;
chv->symflag = symflag ;
/*
--------------------------
set up the working storage
--------------------------
*/
chv->entries = entries ;
chv->colind = colind ;
if ( symflag == SPOOLES_NONSYMMETRIC ) {
chv->rowind = rowind ;
} else {
chv->rowind = NULL ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
purpose -- to initialize the object from its working storage,
used when the object is an MPI message
created -- 98apr30
-------------------------------------------------------------
*/
void
Chv_initFromBuffer (
Chv *chv
) {
int *ibuffer ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_initFromBuffer(%p) "
"\n bad input\n", chv) ;
exit(-1) ;
}
ibuffer = (int *) DV_entries(&chv->wrkDV) ;
Chv_setFields(chv, ibuffer[0], ibuffer[1], ibuffer[2],
ibuffer[3], ibuffer[4], ibuffer[5]) ;
return ; }
/*--------------------------------------------------------------------*/
--------------------------------------------------------*/
/*
-----------------------------Chv/src/instance.c 0100644 0002055 0007177 00000047737 06571267314 0015405 0 ustar 00cleve compmath 0000040 0000006 /* instance.c */
#include "../Chv.h"
/*--------------------------------------------------------------------*/
/*
----------------------------
return the id of the chevron
created -- 98apr30, cca
----------------------------
*/
int
Chv_id (
Chv *chv
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_id(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
return(chv->id) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
return the type of the chevron
return value = SPOOLES_REAL --> chevron is real
return value = SPOOLES_COMPLEX --> chevron is complex
created -- 98apr30, cca
------------------------------------------------------------
*/
int
Chv_type (
Chv *chv
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_type(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
return(chv->type) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
return the symmetry flag of the chevron
return value = SPOOLES_SYMMETRIC --> chevron is symmetric
return value = SPOOLES_HERMITIAN --> chevron is hermitian
return value = SPOOLES_NONSYMMETRIC --> chevron is nonsymmetric
created -- 98apr30, cca
------------------------------------------------------------
*/
int
Chv_symmetryFlag (
Chv *chv
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_symmetryFlag(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
return(chv->symflag) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
fill *pnD with nD, *pnL with nL, and *pnU with nU.
created -- 98apr30, cca
--------------------------------------------------
*/
void
Chv_dimensions (
Chv *chv,
int *pnD,
int *pnL,
int *pnU
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL || pnD == NULL || pnL == NULL || pnU == NULL ) {
fprintf(stderr, "\n fatal error in Chv_dimensions(%p,%p,%p,%p)"
"\n bad input\n", chv, pnD, pnL, pnU) ;
exit(-1) ;
}
*pnD = chv->nD ;
*pnL = chv->nL ;
*pnU = chv->nU ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
fill *pnrow with nD + nL, *prowind with rowind
created -- 98apr30, cca
----------------------------------------------
*/
void
Chv_rowIndices (
Chv *chv,
int *pnrow,
int **prowind
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL || pnrow == NULL || prowind == NULL ) {
fprintf(stderr, "\n fatal error in Chv_rowIndices(%p,%p,%p)"
"\n bad input\n", chv, pnrow, prowind) ;
exit(-1) ;
}
if ( CHV_IS_NONSYMMETRIC(chv) ) {
*pnrow = chv->nD + chv->nL ;
*prowind = chv->rowind ;
} else if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
*pnrow = chv->nD + chv->nU ;
*prowind = chv->colind ;
} else {
fprintf(stderr, "\n fatal error in Chv_rowIndices(%p,%p,%p)"
"\n bad symflag = %d\n", chv, pnrow, prowind, chv->symflag) ;
exit(-1) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
fill *pncol with nD + nU, *pcolind with colind
created -- 98apr30, cca
----------------------------------------------
*/
void
Chv_columnIndices (
Chv *chv,
int *pncol,
int **pcolind
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL || pncol == NULL || pcolind == NULL ) {
fprintf(stderr, "\n fatal error in Chv_columnIndices(%p,%p,%p)"
"\n bad input\n", chv, pncol, pcolind) ;
exit(-1) ;
}
*pncol = chv->nD + chv->nU ;
*pcolind = chv->colind ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
return the number of entries
created -- 98apr30, cca
----------------------------
*/
int
Chv_nent (
Chv *chv
) {
int nD, nent, nL, nU ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_nent(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
nent = (nD*(nD+1))/2 + nD*nU ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
nent = nD*(nD + nL + nU) ;
} else {
fprintf(stderr, "\n fatal error in Chv_nent(%p)"
"\n bad symmetry flag %d\n", chv, chv->symflag) ;
exit(-1) ;
}
return(nent) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
fill *pentries with a pointer to the entries
created -- 98apr30, cca
--------------------------------------------
*/
double *
Chv_entries(
Chv *chv
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_entries(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
return(chv->entries) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------
return the location of the diagonal entry
for the ichv'th chevron
created -- 98apr30, cca
-----------------------------------------
*/
double *
Chv_diagLocation(
Chv *chv,
int ichv
) {
double *diag ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_diagLocation(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
if ( ichv < 0 || ichv > chv->nD ) {
fprintf(stderr, "\n fatal error in Chv_diagLocation(%p)"
"\n ichv = %d, nD = %d\n", chv, ichv, chv->nD) ;
exit(-1) ;
}
if ( chv->entries == NULL ) {
fprintf(stderr, "\n fatal error in Chv_diagLocation(%p)"
"\n chv->entries is NULL\n", chv) ;
exit(-1) ;
}
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) ) {
diag = chv->entries + ichv*(chv->nD + chv->nU)
- (ichv*(ichv-1))/2 ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
diag = chv->entries + (2*ichv+1)*chv->nD + (ichv+1)*chv->nL
+ ichv*chv->nU - ichv*ichv - ichv - 1 ;
} else {
fprintf(stderr, "\n fatal error in Chv_diagLocation(%p)"
"\n type is SPOOLES_REAL, symflag = %d"
"\n not SPOOLES_SYMMETRIC or SPOOLES_NONSYMMETRIC\n",
chv, chv->symflag) ;
exit(-1) ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
diag = chv->entries + 2*(ichv*(chv->nD + chv->nU)
- (ichv*(ichv-1))/2) ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
diag = chv->entries + 2*((2*ichv+1)*chv->nD + (ichv+1)*chv->nL
+ ichv*chv->nU - ichv*ichv - ichv - 1) ;
} else {
fprintf(stderr, "\n fatal error in Chv_diagLocation(%p)"
"\n bad symflag = %d, type is SPOOLES_COMPLEX,"
"\n must be SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN"
"\n or SPOOLES_NONSYMMETRIC\n",
chv, chv->symflag) ;
exit(-1) ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_diagLocation(%p)"
"\n bad type = %d, not SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, chv->symflag) ;
exit(-1) ;
}
return(diag) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
return a pointer to the start of the workspace
created -- 98apr30, cca
----------------------------------------------
*/
void *
Chv_workspace(
Chv *chv
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_workspace(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
return((void *) DV_entries(&chv->wrkDV)) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
fill *pValue with entry (irow, jcol)
created -- 98apr30, cca
------------------------------------
*/
void
Chv_realEntry (
Chv *chv,
int irow,
int jcol,
double *pValue
) {
int ichv, ncol, nD, nL, nrow, nU, off ;
double *base ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || irow < 0 || jcol < 0
|| pValue == NULL ) {
fprintf(stderr, "\n fatal error in Chv_realEntry(%p,%d,%d,%p)"
"\n bad input\n", chv, irow, jcol, pValue) ;
exit(-1) ;
}
if ( ! CHV_IS_REAL(chv) ) {
fprintf(stderr, "\n fatal error in Chv_realEntry(%p,%d,%d,%p)"
"\n bad type %d, not SPOOLES_REAL\n",
chv, irow, jcol, pValue, chv->type) ;
exit(-1) ;
}
if ( ! (CHV_IS_SYMMETRIC(chv) || CHV_IS_NONSYMMETRIC(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_realEntry(%p,%d,%d,%p)"
"\n bad symflag %d"
"\n must be SPOOLES_SYMMETRIC of SPOOLES_NONSYMMETRIC\n",
chv, irow, jcol, pValue, chv->symflag) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
ncol = nD + nU ;
if ( CHV_IS_SYMMETRIC(chv) ) {
nrow = ncol ;
} else {
nrow = nD + nL ;
}
if ( irow >= nrow || jcol >= ncol ) {
fprintf(stderr, "\n fatal error in Chv_realEntry(%p,%d,%d,%p)"
"\n irow = %d, jcol = %d, nrow = %d, ncol = %d\n",
chv, irow, jcol, pValue, irow, jcol, nrow, ncol) ;
exit(-1) ;
}
if ( irow >= nD && jcol >= nD ) {
*pValue = 0.0 ;
} else {
ichv = (irow <= jcol) ? irow : jcol ;
off = jcol - irow ;
if ( CHV_IS_SYMMETRIC(chv) && off < 0 ) {
off = -off ;
}
base = Chv_diagLocation(chv, ichv) ;
*pValue = base[off] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
fill (*pReal,*pImag) with entry (irow, jcol)
created -- 98apr30, cca
--------------------------------------------
*/
void
Chv_complexEntry (
Chv *chv,
int irow,
int jcol,
double *pReal,
double *pImag
) {
int ichv, ncol, nD, nL, nrow, nU, off ;
double *base ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || irow < 0 || jcol < 0
|| pReal == NULL || pImag == NULL ) {
fprintf(stderr, "\n fatal error in Chv_complexEntry(%p,%d,%d,%p,%p)"
"\n bad input\n", chv, irow, jcol, pReal, pImag) ;
exit(-1) ;
}
if ( ! CHV_IS_COMPLEX(chv) ) {
fprintf(stderr, "\n fatal error in Chv_complexEntry(%p,%d,%d,%p,%p)"
"\n bad type %d, not SPOOLES_COMPLEX\n",
chv, irow, jcol, pReal, pImag, chv->type) ;
exit(-1) ;
}
if ( ! (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv)
|| CHV_IS_NONSYMMETRIC(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_complexEntry(%p,%d,%d,%p,%p)"
"\n bad symflag %d, not SPOOLES_SYMMETRIC, "
"\n SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC \n",
chv, irow, jcol, pReal, pImag, chv->symflag) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
ncol = nD + nU ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
nrow = ncol ;
} else {
nrow = nD + nL ;
}
if ( irow >= nrow || jcol >= ncol ) {
fprintf(stderr, "\n fatal error in Chv_complexEntry(%p,%d,%d,%p,%p)"
"\n irow = %d, jcol = %d, nrow = %d, ncol = %d\n",
chv, irow, jcol, pReal, pImag, irow, jcol, nrow, ncol) ;
exit(-1) ;
}
if ( irow >= nD && jcol >= nD ) {
*pReal = *pImag = 0.0 ;
} else {
ichv = (irow <= jcol) ? irow : jcol ;
off = jcol - irow ;
if ( off < 0 && (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv)) ) {
off = -off ;
}
base = Chv_diagLocation(chv, ichv) ;
*pReal = base[2*off] ;
if ( irow > jcol && CHV_IS_HERMITIAN(chv) ) {
*pImag = - base[2*off+1] ;
} else {
*pImag = base[2*off+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
fill *ppValue with the location of entry (irow, jcol)
created -- 98apr30, cca
-----------------------------------------------------
*/
void
Chv_locationOfRealEntry (
Chv *chv,
int irow,
int jcol,
double **ppValue
) {
int ichv, ncol, nD, nL, nrow, nU, off ;
double *base ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || irow < 0 || jcol < 0
|| ppValue == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_locationOfRealEntry(%p,%d,%d,%p)"
"\n bad input\n", chv, irow, jcol, ppValue) ;
exit(-1) ;
}
if ( ! CHV_IS_REAL(chv) ) {
fprintf(stderr,
"\n fatal error in Chv_locationOfRealEntry(%p,%d,%d,%p)"
"\n bad type %d, not SPOOLES_REAL\n",
chv, irow, jcol, ppValue, chv->type) ;
exit(-1) ;
}
if ( ! (CHV_IS_SYMMETRIC(chv) || CHV_IS_NONSYMMETRIC(chv)) ) {
fprintf(stderr,
"\n fatal error in Chv_locationOfRealEntry(%p,%d,%d,%p)"
"\n bad symflag %d, not SPOOLES_SYMMETRIC of SPOOLES_NONSYMMETRIC\n",
chv, irow, jcol, ppValue, chv->symflag) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
ncol = nD + nU ;
if ( CHV_IS_SYMMETRIC(chv) ) {
nrow = ncol ;
} else {
nrow = nD + nL ;
}
if ( irow >= nrow || jcol >= ncol ) {
fprintf(stderr,
"\n fatal error in Chv_locationOfRealEntry(%p,%d,%d,%p)"
"\n irow = %d, jcol = %d, nrow = %d, ncol = %d\n",
chv, irow, jcol, ppValue, irow, jcol, nrow, ncol) ;
exit(-1) ;
}
if ( irow >= nD && jcol >= nD ) {
*ppValue = NULL ;
} else {
ichv = (irow <= jcol) ? irow : jcol ;
off = jcol - irow ;
if ( CHV_IS_SYMMETRIC(chv) && off < 0 ) {
off = -off ;
}
base = Chv_diagLocation(chv, ichv) ;
*ppValue = base + off ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------
fill (*ppReal,*ppImag) with location of entry (irow, jcol)
created -- 98apr30, cca
----------------------------------------------------------
*/
void
Chv_locationOfComplexEntry (
Chv *chv,
int irow,
int jcol,
double **ppReal,
double **ppImag
) {
int ichv, ncol, nD, nL, nrow, nU, off ;
double *base ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || irow < 0 || jcol < 0
|| ppReal == NULL || ppImag == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_locationOfComplexEntry(%p,%d,%d,%p,%p)"
"\n bad input\n", chv, irow, jcol, ppReal, ppImag) ;
exit(-1) ;
}
if ( ! CHV_IS_COMPLEX(chv) ) {
fprintf(stderr,
"\n fatal error in Chv_locationOfComplexEntry(%p,%d,%d,%p,%p)"
"\n bad type %d, not SPOOLES_COMPLEX\n",
chv, irow, jcol, ppReal, ppImag, chv->type) ;
exit(-1) ;
}
if ( ! (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv)
|| CHV_IS_NONSYMMETRIC(chv)) ) {
fprintf(stderr,
"\n fatal error in Chv_locationOfComplexEntry(%p,%d,%d,%p,%p)"
"\n bad symflag %d"
"\n not SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN"
"\n or SPOOLES_NONSYMMETRIC \n",
chv, irow, jcol, ppReal, ppImag, chv->symflag) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
ncol = nD + nU ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
nrow = ncol ;
} else {
nrow = nD + nL ;
}
if ( irow >= nrow || jcol >= ncol ) {
fprintf(stderr,
"\n fatal error in Chv_locationOfComplexEntry(%p,%d,%d,%p,%p)"
"\n irow = %d, jcol = %d, nrow = %d, ncol = %d\n",
chv, irow, jcol, ppReal, ppImag, irow, jcol, nrow, ncol) ;
exit(-1) ;
}
if ( irow >= nD && jcol >= nD ) {
*ppReal = *ppImag = NULL ;
} else {
ichv = (irow <= jcol) ? irow : jcol ;
off = jcol - irow ;
if ( off < 0 && (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv)) ) {
off = -off ;
}
base = Chv_diagLocation(chv, ichv) ;
*ppReal = base + 2*off ;
*ppImag = base + 2*off + 1 ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
set entry (irow, jcol) to value
created -- 98apr30, cca
------------------------------------
*/
void
Chv_setRealEntry (
Chv *chv,
int irow,
int jcol,
double value
) {
int ichv, ncol, nD, nL, nrow, nU, off ;
double *base ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || irow < 0 || jcol < 0 ) {
fprintf(stderr, "\n fatal error in Chv_setRealEntry(%p,%d,%d,%e)"
"\n bad input\n", chv, irow, jcol, value) ;
exit(-1) ;
}
if ( ! CHV_IS_REAL(chv) ) {
fprintf(stderr, "\n fatal error in Chv_setRealEntry(%p,%d,%d,%e)"
"\n bad type %d, not SPOOLES_REAL\n",
chv, irow, jcol, value, chv->type) ;
exit(-1) ;
}
if ( ! (CHV_IS_SYMMETRIC(chv) || CHV_IS_NONSYMMETRIC(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_setRealEntry(%p,%d,%d,%e)"
"\n bad symflag %d"
"\n must be SPOOLES_SYMMETRIC of SPOOLES_NONSYMMETRIC\n",
chv, irow, jcol, value, chv->symflag) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
ncol = nD + nU ;
if ( CHV_IS_SYMMETRIC(chv) ) {
nrow = ncol ;
} else {
nrow = nD + nL ;
}
if ( irow >= nrow || jcol >= ncol ) {
fprintf(stderr, "\n fatal error in Chv_setRealEntry(%p,%d,%d,%e)"
"\n irow = %d, jcol = %d, nrow = %d, ncol = %d\n",
chv, irow, jcol, value, irow, jcol, nrow, ncol) ;
exit(-1) ;
}
if ( irow < nD || jcol < nD ) {
ichv = (irow <= jcol) ? irow : jcol ;
off = jcol - irow ;
if ( CHV_IS_SYMMETRIC(chv) && off < 0 ) {
off = -off ;
}
base = Chv_diagLocation(chv, ichv) ;
base[off] = value ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
fill (*pReal,*pImag) with entry (irow, jcol)
created -- 98apr30, cca
--------------------------------------------
*/
void
Chv_setComplexEntry (
Chv *chv,
int irow,
int jcol,
double real,
double imag
) {
int ichv, ncol, nD, nL, nrow, nU, off ;
double *base ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || irow < 0 || jcol < 0 ) {
fprintf(stderr,
"\n fatal error in Chv_setComplexEntry(%p,%d,%d,%e,%e)"
"\n bad input\n", chv, irow, jcol, real, imag) ;
exit(-1) ;
}
if ( ! CHV_IS_COMPLEX(chv) ) {
fprintf(stderr,
"\n fatal error in Chv_setComplexEntry(%p,%d,%d,%e,%e)"
"\n bad type %d, not SPOOLES_COMPLEX\n",
chv, irow, jcol, real, imag, chv->type) ;
exit(-1) ;
}
if ( ! (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv)
|| CHV_IS_NONSYMMETRIC(chv)) ) {
fprintf(stderr,
"\n fatal error in Chv_setComplexEntry(%p,%d,%d,%e,%e)"
"\n bad symflag %d"
"\n not SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN"
"\n or SPOOLES_NONSYMMETRIC \n",
chv, irow, jcol, real, imag, chv->symflag) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
ncol = nD + nU ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
nrow = ncol ;
} else {
nrow = nD + nL ;
}
if ( irow >= nrow || jcol >= ncol ) {
fprintf(stderr,
"\n fatal error in Chv_setComplexEntry(%p,%d,%d,%e,%e)"
"\n irow = %d, jcol = %d, nrow = %d, ncol = %d\n",
chv, irow, jcol, real, imag, irow, jcol, nrow, ncol) ;
exit(-1) ;
}
if ( irow < nD || jcol < nD ) {
ichv = (irow <= jcol) ? irow : jcol ;
off = jcol - irow ;
if ( off < 0 && (CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv)) ) {
off = -off ;
}
base = Chv_diagLocation(chv, ichv) ;
base[2*off] = real ;
base[2*off+1] = imag ;
}
return ; }
/*--------------------------------------------------------------------*/
--------------------------------*Chv/src/search.c 0100644 0002055 0007177 00000065642 06571267314 0015041 0 ustar 00cleve compmath 0000040 0000006 /* search.c */
#include "../Chv.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------------------
find the first unmarked entry in
the diagonal with largest magnitude
if ( mark[jj] == tag ) then
we can compare this entry
endif
created -- 98apr30, cca
-----------------------------------
*/
int
Chv_maxabsInDiagonal11 (
Chv *chv,
int mark[],
int tag,
double *pmaxval
) {
double maxval, val ;
double *entries ;
int jcol, jj, nD, nL, nU, off, stride ;
/*
--------------
check the data
--------------
*/
if ( chv == NULL || mark == NULL || pmaxval == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_maxabsInDiagonal11(%p,%p,%d,%p)"
"\n bad input\n", chv, mark, tag, pmaxval) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------
nonsymmetric chevron
--------------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
for ( jj = 0 ; jj < nD ; jj++ ) {
if ( mark[jj] == tag ) {
val = fabs(entries[off]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
off += stride ;
stride -= 2 ;
}
} else if ( CHV_IS_SYMMETRIC(chv) ) {
/*
-----------------
symmetric chevron
-----------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = 0 ;
stride = nD + nU ;
for ( jj = 0 ; jj < nD ; jj++ ) {
if ( mark[jj] == tag ) {
val = fabs(entries[off]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
off += stride ;
stride-- ;
}
} else {
fprintf(stderr,
"\n fatal error in Chv_maxabsInDiagonal11(%p,%p,%d,%p)"
"\n type = SPOOLES_REAL, bad symflag %d \n",
chv, mark, tag, pmaxval, chv->symflag) ;
exit(-1) ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------
nonsymmetric chevron
--------------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = nD + nL - 1 ;
stride = 2*nD + nL + nU - 2 ;
for ( jj = 0 ; jj < nD ; jj++ ) {
if ( mark[jj] == tag ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
off += stride ;
stride -= 2 ;
}
} else if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
/*
------------------------------
hermitian or symmetric chevron
------------------------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = 0 ;
stride = nD + nU ;
for ( jj = 0 ; jj < nD ; jj++ ) {
if ( mark[jj] == tag ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
off += stride ;
stride-- ;
}
} else {
fprintf(stderr,
"\n fatal error in Chv_maxabsInDiagonal11(%p,%p,%d,%p)"
"\n type = SPOOLES_COMPLEX, bad symflag %d \n",
chv, mark, tag, pmaxval, chv->symflag) ;
exit(-1) ;
}
} else {
fprintf(stderr,
"\n fatal error in Chv_maxabsInDiagonal11(%p,%p,%d,%p)"
"\n bad type, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, mark, tag, pmaxval) ;
exit(-1) ;
}
*pmaxval = maxval ;
return(jcol) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
find the first unmarked entry in
row irow with largest magnitude
if ( colmark[jj] == tag ) then
we can examined this entry
endif
only entries in the (1,1) block are examined
created -- 98apr30, cca
--------------------------------------------
*/
int
Chv_maxabsInRow11 (
Chv *chv,
int irow,
int colmark[],
int tag,
double *pmaxval
) {
double maxval, val ;
double *entries ;
int jcol, jj, nD, nL, nU, off, stride ;
/*
--------------
check the data
--------------
*/
if ( chv == NULL || irow < 0 || colmark == NULL || pmaxval == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_maxabsInRow11(%p,%d,%p,%d,%p)"
"\n bad input\n", chv, irow, colmark, tag, pmaxval) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------
nonsymmetric chevron
--------------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = nD + nL - 1 - irow ;
stride = 2*nD + nL + nU - 1 ;
for ( jj = 0 ; jj < irow ; jj++ ) {
if ( colmark[jj] == tag ) {
val = fabs(entries[off]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
off += stride ;
stride -= 2 ;
}
for ( jj = irow ; jj < nD ; jj++, off++ ) {
if ( colmark[jj] == tag ) {
val = fabs(entries[off]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
}
} else if ( CHV_IS_SYMMETRIC(chv) ) {
/*
-----------------
symmetric chevron
-----------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = irow ;
stride = nD + nU - 1 ;
for ( jj = 0 ; jj < irow ; jj++ ) {
if ( colmark[jj] == tag ) {
val = fabs(entries[off]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
off += stride ;
stride-- ;
}
for ( jj = irow ; jj < nD ; jj++, off++ ) {
if ( colmark[jj] == tag ) {
val = fabs(entries[off]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
}
} else {
fprintf(stderr,
"\n fatal error in Chv_maxabsInRow11(%p,%d,%p,%d,%p)"
"\n type is SPOOLES_REAL, bad symflag %d \n",
chv, irow, colmark, tag, pmaxval, chv->symflag) ;
exit(-1) ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------
nonsymmetric chevron
--------------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = nD + nL - 1 - irow ;
stride = 2*nD + nL + nU - 1 ;
for ( jj = 0 ; jj < irow ; jj++ ) {
if ( colmark[jj] == tag ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
off += stride ;
stride -= 2 ;
}
for ( jj = irow ; jj < nD ; jj++, off++ ) {
if ( colmark[jj] == tag ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
}
} else if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
/*
------------------------------
hermitian or symmetric chevron
------------------------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = irow ;
stride = nD + nU - 1 ;
for ( jj = 0 ; jj < irow ; jj++ ) {
if ( colmark[jj] == tag ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
off += stride ;
stride-- ;
}
for ( jj = irow ; jj < nD ; jj++, off++ ) {
if ( colmark[jj] == tag ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
}
} else {
fprintf(stderr,
"\n fatal error in Chv_maxabsInRow11(%p,%d,%p,%d,%p)"
"\n type is SPOOLES_COMPLEX, bad symflag %d \n",
chv, irow, colmark, tag, pmaxval, chv->symflag) ;
exit(-1) ;
}
} else {
fprintf(stderr,
"\n fatal error in Chv_maxabsInRow11(%p,%d,%p,%d,%p)"
"\n bad type, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, irow, colmark, tag, pmaxval) ;
exit(-1) ;
}
*pmaxval = maxval ;
return(jcol) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
find the first unmarked entry in
column jcol with largest magnitude
if ( rowmark[ii] == tag ) then
we can examined this entry
endif
only entries in the (1,1) block are examined
created -- 98apr30, cca
--------------------------------------------
*/
int
Chv_maxabsInColumn11 (
Chv *chv,
int jcol,
int rowmark[],
int tag,
double *pmaxval
) {
double maxval, val ;
double *entries ;
int irow, ii, nD, nL, nU, off, stride ;
/*
--------------
check the data
--------------
*/
if ( chv == NULL || jcol < 0 || rowmark == NULL || pmaxval == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_maxabsInColumn11(%p,%d,%p,%d,%p)"
"\n bad input\n", chv, jcol, rowmark, tag, pmaxval) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
irow = -1 ;
maxval = 0.0 ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------
nonsymmetric chevron
--------------------
*/
maxval = 0.0 ;
off = nD + nL + jcol - 1 ;
stride = 2*nD + nL + nU - 3 ;
for ( ii = 0 ; ii < jcol ; ii++ ) {
if ( rowmark[ii] == tag ) {
val = fabs(entries[off]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
off += stride ;
stride -= 2 ;
}
for ( ii = jcol ; ii < nD ; ii++, off-- ) {
if ( rowmark[ii] == tag ) {
val = fabs(entries[off]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
}
} else if ( CHV_IS_SYMMETRIC(chv) ) {
/*
-----------------
symmetric chevron
-----------------
*/
maxval = 0.0 ;
off = jcol ;
stride = nD + nU - 1 ;
for ( ii = 0 ; ii < jcol ; ii++ ) {
if ( rowmark[ii] == tag ) {
val = fabs(entries[off]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
off += stride ;
stride-- ;
}
for ( ii = jcol ; ii < nD ; ii++, off++ ) {
if ( rowmark[ii] == tag ) {
val = fabs(entries[off]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------
nonsymmetric chevron
--------------------
*/
maxval = 0.0 ;
off = nD + nL + jcol - 1 ;
stride = 2*nD + nL + nU - 3 ;
for ( ii = 0 ; ii < jcol ; ii++ ) {
if ( rowmark[ii] == tag ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
off += stride ;
stride -= 2 ;
}
for ( ii = jcol ; ii < nD ; ii++, off-- ) {
if ( rowmark[ii] == tag ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
}
} else if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
/*
------------------------------
hermitian or symmetric chevron
------------------------------
*/
maxval = 0.0 ;
off = jcol ;
stride = nD + nU - 1 ;
for ( ii = 0 ; ii < jcol ; ii++ ) {
if ( rowmark[ii] == tag ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
off += stride ;
stride-- ;
}
for ( ii = jcol ; ii < nD ; ii++, off++ ) {
if ( rowmark[ii] == tag ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
}
}
} else {
fprintf(stderr,
"\n fatal error in Chv_maxabsInColumn11(%p,%d,%p,%d,%p)"
"\n bad type, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, jcol, rowmark, tag, pmaxval) ;
exit(-1) ;
}
*pmaxval = maxval ;
return(irow) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
return the location of the first entry
with largest magnitude in row irow.
*pmaxval is filled with its magnitude.
created -- 98apr30, cca
--------------------------------------
*/
int
Chv_maxabsInRow (
Chv *chv,
int irow,
double *pmaxval
) {
double maxval, val ;
double *entries ;
int jcol, jj, ncol, nD, nL, nU, off, stride ;
/*
--------------
check the data
--------------
*/
if ( chv == NULL || irow < 0 || pmaxval == NULL ) {
fprintf(stderr, "\n fatal error in Chv_maxabsInRow(%p,%d,%p)"
"\n bad input\n", chv, irow, pmaxval) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
ncol = nD + nU ;
jcol = -1 ;
maxval = 0.0 ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------
nonsymmetric chevron
--------------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = nD + nL - 1 - irow ;
stride = 2*nD + nL + nU - 1 ;
for ( jj = 0 ; jj < irow ; jj++ ) {
val = fabs(entries[off]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
off += stride ;
stride -= 2 ;
}
for ( jj = irow ; jj < ncol ; jj++, off++ ) {
val = fabs(entries[off]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
} else if ( CHV_IS_SYMMETRIC(chv) ) {
/*
-----------------
symmetric chevron
-----------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = irow ;
stride = nD + nU - 1 ;
for ( jj = 0 ; jj < irow ; jj++ ) {
val = fabs(entries[off]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
off += stride ;
stride-- ;
}
for ( jj = irow ; jj < ncol ; jj++, off++ ) {
val = fabs(entries[off]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------
nonsymmetric chevron
--------------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = nD + nL - 1 - irow ;
stride = 2*nD + nL + nU - 1 ;
for ( jj = 0 ; jj < irow ; jj++ ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
off += stride ;
stride -= 2 ;
}
for ( jj = irow ; jj < ncol ; jj++, off++ ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
} else if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
/*
------------------------------
hermitian or symmetric chevron
------------------------------
*/
jcol = -1 ;
maxval = 0.0 ;
off = irow ;
stride = nD + nU - 1 ;
for ( jj = 0 ; jj < irow ; jj++ ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
off += stride ;
stride-- ;
}
for ( jj = irow ; jj < ncol ; jj++, off++ ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( jcol == -1 || maxval < val ) {
jcol = jj ; maxval = val ;
}
}
}
} else {
fprintf(stderr,
"\n fatal error in Chv_maxabsInRow(%p,%d,%p)"
"\n bad type %d, must be SPOOLES_REAL or SPOOLES_COMPLEX \n",
chv, irow, pmaxval, chv->symflag) ;
exit(-1) ;
}
*pmaxval = maxval ;
return(jcol) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
return the location of the first entry
with largest magnitude in column jcol.
*pmaxval is filled with its magnitude.
created -- 98apr30, cca
--------------------------------------
*/
int
Chv_maxabsInColumn (
Chv *chv,
int jcol,
double *pmaxval
) {
double maxval, val ;
double *entries ;
int irow, ii, nD, nL, nrow, nU, off, stride ;
/*
--------------
check the data
--------------
*/
if ( chv == NULL || jcol < 0 || pmaxval == NULL ) {
fprintf(stderr, "\n fatal error in Chv_maxabsInColumn(%p,%d,%p)"
"\n bad input\n", chv, jcol, pmaxval) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
nrow = nD + nL ;
irow = -1 ;
maxval = 0.0 ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------
nonsymmetric chevron
--------------------
*/
maxval = 0.0 ;
off = nD + nL + jcol - 1 ;
stride = 2*nD + nL + nU - 3 ;
for ( ii = 0 ; ii < jcol ; ii++ ) {
val = fabs(entries[off]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
off += stride ;
stride -= 2 ;
}
for ( ii = jcol ; ii < nrow ; ii++, off-- ) {
val = fabs(entries[off]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
} else if ( CHV_IS_SYMMETRIC(chv) ) {
/*
-----------------
symmetric chevron
-----------------
*/
maxval = 0.0 ;
off = jcol ;
stride = nD + nU - 1 ;
for ( ii = 0 ; ii < jcol ; ii++ ) {
val = fabs(entries[off]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
off += stride ;
stride-- ;
}
for ( ii = jcol ; ii < nrow ; ii++, off++ ) {
val = fabs(entries[off]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------
nonsymmetric chevron
--------------------
*/
maxval = 0.0 ;
off = nD + nL + jcol - 1 ;
stride = 2*nD + nL + nU - 3 ;
for ( ii = 0 ; ii < jcol ; ii++ ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
off += stride ;
stride -= 2 ;
}
for ( ii = jcol ; ii < nrow ; ii++, off-- ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
} else if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
/*
------------------------------
hermitian or symmetric chevron
------------------------------
*/
maxval = 0.0 ;
off = jcol ;
stride = nD + nU - 1 ;
for ( ii = 0 ; ii < jcol ; ii++ ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
off += stride ;
stride-- ;
}
for ( ii = jcol ; ii < nrow ; ii++, off++ ) {
val = Zabs(entries[2*off], entries[2*off+1]) ;
if ( irow == -1 || maxval < val ) {
irow = ii ; maxval = val ;
}
}
}
} else {
fprintf(stderr,
"\n fatal error in Chv_maxabsInColumn(%p,%d,%p)"
"\n bad symflag %d \n", chv, jcol, pmaxval, chv->symflag) ;
exit(-1) ;
}
*pmaxval = maxval ;
return(irow) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
return the magnitude of a quasimax entry from the unmarked
rows and columns and fill *pirow and *pjcol with its location
created -- 98apr30, cca
-------------------------------------------------------------
*/
double
Chv_quasimax (
Chv *chv,
int rowmark[],
int colmark[],
int tag,
int *pirow,
int *pjcol
) {
double maxval ;
int irow, jcol, nD, qcol, qrow ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || rowmark == NULL || colmark == NULL
|| pirow == NULL || pjcol == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_quasimax(%p,%p,%p,%d,%p,%p)"
"\n bad input\n", chv, rowmark, colmark, tag, pirow, pjcol) ;
exit(-1) ;
}
if ( ! CHV_IS_NONSYMMETRIC(chv) ) {
fprintf(stderr,
"\n fatal error in Chv_quasimax(%p,%p,%p,%d,%p,%p)"
"\n chv->symflag = %d"
"\n chevron is not symmetric or hermitian"
"\n method cannot be used \n",
chv, rowmark, colmark, tag, pirow, pjcol, chv->symflag) ;
exit(-1) ;
}
nD = chv->nD ;
/*
----------------------
set the default values
----------------------
*/
*pirow = *pjcol = -1 ;
maxval = 0.0 ;
/*
-----------------------
find an unmarked column
-----------------------
*/
for ( jcol = 0 ; jcol < nD ; jcol++ ) {
if ( colmark[jcol] == tag ) {
break ;
}
}
if ( jcol == nD ) {
/*
---------------------------
no unmarked columns, return
---------------------------
*/
return(maxval) ;
}
/*
----------------------------------------
find a maxabs entry in the unmarked rows
----------------------------------------
*/
irow = Chv_maxabsInColumn11(chv, jcol, rowmark, tag, &maxval) ;
#if MYDEBUG > 0
fprintf(stdout, "\n first maxabs = %12.4e in (%d,%d)",
Chv_entry(chv, irow, jcol), irow, jcol) ;
fflush(stdout) ;
#endif
if ( irow == -1 ) {
/*
------------------------
no unmarked rows, return
------------------------
*/
return(maxval) ;
}
while ( 1 ) {
/*
----------------------------------
find a new maxabs entry in the row
----------------------------------
*/
qcol = Chv_maxabsInRow11(chv, irow, colmark, tag, &maxval) ;
#if MYDEBUG > 0
fprintf(stdout, "\n new maxabs = %12.4e in (%d,%d)",
Chv_entry(chv, irow, qcol), irow, qcol) ;
fflush(stdout) ;
#endif
if ( qcol == jcol ) {
/*
--------------------------------------------
same as before, break out of the search loop
--------------------------------------------
*/
break ;
}
jcol = qcol ;
/*
-------------------------------------
find a new maxabs entry in the column
-------------------------------------
*/
qrow = Chv_maxabsInColumn11(chv, jcol, rowmark, tag, &maxval) ;
#if MYDEBUG > 0
fprintf(stdout, "\n new maxabs = %12.4e in (%d,%d)",
Chv_entry(chv, qrow, jcol), qrow, jcol) ;
fflush(stdout) ;
#endif
if ( qrow == irow ) {
/*
--------------------------------------------
same as before, break out of the search loop
--------------------------------------------
*/
break ;
}
irow = qrow ;
}
/*
--------------------------------------------------------
set the row and column where the quasimax entry is found
--------------------------------------------------------
*/
*pjcol = jcol ;
*pirow = irow ;
return(maxval) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
find a 1x1 or 2x2 pivot using the fast Bunch-Parlett algorithm.
used only with symmetric chevrons.
created -- 98apr30, cca
---------------------------------------------------------------
*/
void
Chv_fastBunchParlettPivot (
Chv *chv,
int mark[],
int tag,
int *pirow,
int *pjcol
) {
double maxdiag, gamma_r, gamma_s ;
double *entries ;
int nD, nL, nU, r, s, t ;
/*
--------------
check the data
--------------
*/
if ( chv == NULL || mark == NULL || pirow == NULL || pjcol == NULL ) {
fprintf(stderr,
"\n fatal error in Chv_fastBunchParlettPivot(%p,%p,%d,%p,%p)"
"\n bad input\n",
chv, mark, tag, pirow, pjcol) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
/*
----------------------
set the default values
----------------------
*/
*pirow = *pjcol = -1 ;
/*
------------------------------------------
find an unmarked entry of maximum magitude
------------------------------------------
*/
r = Chv_maxabsInDiagonal11(chv, mark, tag, &maxdiag) ;
if ( r == -1 ) {
/*
-------------------------------------------------------
all rows and columns are marked, return without success
-------------------------------------------------------
*/
*pirow = *pjcol = -1 ;
return ;
}
/*
-------------------------------------------------------------------
find the offdiagonal entry of maximum magnitude in row and column r
-------------------------------------------------------------------
*/
s = -1 ;
gamma_r = 0.0 ;
s = Chv_maxabsInRow11(chv, r, mark, tag, &gamma_r) ;
if ( s == -1 ) {
/*
---------------------------------------------
r is the only unmarked row and column, return
---------------------------------------------
*/
*pirow = *pjcol = r ;
return ;
}
if ( maxdiag >= 0.6404 * gamma_r ) {
/*
-------------------------
1 x 1 pivot is acceptable
-------------------------
*/
*pirow = *pjcol = r ;
return ;
} else {
/*
---------------
loop until done
---------------
*/
while ( 1 ) {
/*
----------------------------------------------
find
t = index of max off diag entry in column s
gamma_s is its magnitude
----------------------------------------------
*/
t = Chv_maxabsInRow11(chv, s, mark, tag, &gamma_s) ;
if ( t == r || gamma_s == gamma_r ) {
/*
-------------------------
2 x 2 pivot is acceptable
-------------------------
*/
*pirow = r ;
*pjcol = s ;
return ;
} else {
/*
--------------------------------
keep looking for a local maximum
--------------------------------
*/
r = s ;
gamma_r = gamma_s ;
s = t ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
--------------------
return the location of the first entry
with largest magnitude in cChv/src/swap.c 0100644 0002055 0007177 00000040736 06571267314 0014543 0 ustar 00cleve compmath 0000040 0000006 /* swap.c */
#include "../Chv.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------
swap rows irow and jrow
created -- 98apr30, cca
-----------------------
*/
void
Chv_swapRows (
Chv *chv,
int irow,
int jrow
) {
double dtmp ;
double *entries ;
int ii, ioff, itmp, joff, nD, nL, nrow, nU, stride ;
int *rowind ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || irow < 0 || jrow < 0 ) {
fprintf(stderr, "\n fatal error in Chv_swapRows(%p,%d,%d)"
"\n bad input\n", chv, irow, jrow) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout,"\n %% Chv_swapRows(%p,%d,%d)", chv, irow, jrow) ;
fprintf(stdout,"\n %% chv->symflag = %d", chv->symflag) ;
fflush(stdout) ;
#endif
if ( irow == jrow ) {
return ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
if ( irow >= nD || jrow >= nD ) {
fprintf(stderr, "\n fatal error in Chv_swapRows(%p,%d,%d)"
"\n rows must be less than nD = %d", chv, irow, irow, nD) ;
exit(-1) ;
}
entries = Chv_entries(chv) ;
#if MYDEBUG > 0
fprintf(stdout,"\n %% nD = %d, nL = %d, nU = %d, entries = %p",
nD, nL, nU, entries) ;
fflush(stdout) ;
#endif
if ( entries == NULL ) {
fprintf(stderr, "\n fatal error in Chv_swapRows(%p,%d,%d)"
"\n bad input, entries = %p, nD = %d\n",
chv, irow, jrow, entries, nD) ;
exit(-1) ;
}
if ( ! (CHV_IS_REAL(chv) || CHV_IS_COMPLEX(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_swapRows(%p,%d,%d)"
"\n type = %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, irow, jrow, chv->type) ;
exit(-1) ;
}
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
/*
------------------------------------------------
call method for hermitian and symmetric chevrons
------------------------------------------------
*/
Chv_swapRowsAndColumns(chv, irow, jrow) ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
------------------------
swap the two row indices
------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n %% getting ready to swap row indices") ;
fflush(stdout) ;
#endif
Chv_rowIndices(chv, &nrow, &rowind) ;
#if MYDEBUG > 0
fprintf(stdout,
"\n %% before: rowind = %p, rowind[%d] = %d, rowind[%d] = %d",
rowind, irow, rowind[irow], jrow, rowind[jrow]) ;
IVfprintf(stdout, nrow, rowind) ;
fflush(stdout) ;
#endif
itmp = rowind[irow] ;
rowind[irow] = rowind[jrow] ;
rowind[jrow] = itmp ;
#if MYDEBUG > 0
fprintf(stdout,
"\n %% after: rowind = %p, rowind[%d] = %d, rowind[%d] = %d",
rowind, irow, rowind[irow], jrow, rowind[jrow]) ;
IVfprintf(stdout, nrow, rowind) ;
fflush(stdout) ;
#endif
/*
--------------------------------------------------
set irow = min(irow, jrow), jrow = max(irow, jrow)
--------------------------------------------------
*/
if ( irow > jrow ) {
itmp = irow ;
irow = jrow ;
jrow = itmp ;
}
/*
--------------------------------
swap the entries in the two rows
--------------------------------
*/
ioff = nD + nL - 1 - irow ;
joff = nD + nL - 1 - jrow ;
stride = 2*nD + nL + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < irow ; ii++ ) {
dtmp = entries[ioff] ;
entries[ioff] = entries[joff] ;
entries[joff] = dtmp ;
ioff += stride, joff += stride, stride -= 2 ;
}
for ( ii = irow ; ii < jrow ; ii++ ) {
dtmp = entries[ioff] ;
entries[ioff] = entries[joff] ;
entries[joff] = dtmp ;
ioff += 1, joff += stride, stride -= 2 ;
}
for ( ii = jrow ; ii < nD + nU ; ii++ ) {
dtmp = entries[ioff] ;
entries[ioff] = entries[joff] ;
entries[joff] = dtmp ;
ioff += 1, joff += 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < irow ; ii++ ) {
dtmp = entries[2*ioff] ;
entries[2*ioff] = entries[2*joff] ;
entries[2*joff] = dtmp ;
dtmp = entries[2*ioff+1] ;
entries[2*ioff+1] = entries[2*joff+1] ;
entries[2*joff+1] = dtmp ;
ioff += stride, joff += stride, stride -= 2 ;
}
for ( ii = irow ; ii < jrow ; ii++ ) {
dtmp = entries[2*ioff] ;
entries[2*ioff] = entries[2*joff] ;
entries[2*joff] = dtmp ;
dtmp = entries[2*ioff+1] ;
entries[2*ioff+1] = entries[2*joff+1] ;
entries[2*joff+1] = dtmp ;
ioff += 1, joff += stride, stride -= 2 ;
}
for ( ii = jrow ; ii < nD + nU ; ii++ ) {
dtmp = entries[2*ioff] ;
entries[2*ioff] = entries[2*joff] ;
entries[2*joff] = dtmp ;
dtmp = entries[2*ioff+1] ;
entries[2*ioff+1] = entries[2*joff+1] ;
entries[2*joff+1] = dtmp ;
ioff += 1, joff += 1 ;
}
}
} else {
fprintf(stderr, "\n fatal error in Chv_swapRows(%p,%d,%d)"
"\n bad symmetryflag %d\n", chv, irow, jrow, chv->symflag) ;
exit(-1) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------
swap columns icol and jcol
created -- 98apr30, cca
--------------------------
*/
void
Chv_swapColumns (
Chv *chv,
int icol,
int jcol
) {
double dtmp ;
double *entries ;
int ii, ioff, itmp, joff, ncol, nD, nL, nU, stride ;
int *colind ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || icol < 0 || jcol < 0 ) {
fprintf(stderr, "\n fatal error in Chv_swapColumns(%p,%d,%d)"
"\n bad input\n", chv, icol, jcol) ;
exit(-1) ;
}
if ( icol == jcol ) {
return ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
if ( entries == NULL || icol >= nD || jcol >= nD ) {
fprintf(stderr, "\n fatal error in Chv_swapColumns(%p,%d,%d)"
"\n bad input, entries = %p, nD = %d\n",
chv, icol, jcol, entries, nD) ;
exit(-1) ;
}
if ( ! (CHV_IS_REAL(chv) || CHV_IS_COMPLEX(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_swapColumns(%p,%d,%d)"
"\n type = %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, icol, jcol, chv->type) ;
exit(-1) ;
}
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
/*
------------------------------------------------
call method for symmetric and hermitian chevrons
------------------------------------------------
*/
Chv_swapRowsAndColumns(chv, icol, jcol) ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
---------------------------
swap the two column indices
---------------------------
*/
Chv_columnIndices(chv, &ncol, &colind) ;
itmp = colind[icol] ;
colind[icol] = colind[jcol] ;
colind[jcol] = itmp ;
/*
--------------------------------------------------
set icol = min(icol, jcol), jcol = max(icol, jcol)
--------------------------------------------------
*/
if ( icol > jcol ) {
itmp = icol ;
icol = jcol ;
jcol = itmp ;
}
/*
-----------------------------------
swap the entries in the two columns
-----------------------------------
*/
ioff = nD + nL - 1 + icol ;
joff = nD + nL - 1 + jcol ;
stride = 2*nD + nL + nU - 3 ;
if ( CHV_IS_REAL(chv) ) {
for ( ii = 0 ; ii < icol ; ii++ ) {
dtmp = entries[ioff] ;
entries[ioff] = entries[joff] ;
entries[joff] = dtmp ;
ioff += stride, joff += stride, stride -= 2 ;
}
for ( ii = icol ; ii < jcol ; ii++ ) {
dtmp = entries[ioff] ;
entries[ioff] = entries[joff] ;
entries[joff] = dtmp ;
ioff -= 1, joff += stride, stride -= 2 ;
}
for ( ii = jcol ; ii < nD + nL ; ii++ ) {
dtmp = entries[ioff] ;
entries[ioff] = entries[joff] ;
entries[joff] = dtmp ;
ioff -= 1, joff -= 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ii = 0 ; ii < icol ; ii++ ) {
dtmp = entries[2*ioff] ;
entries[2*ioff] = entries[2*joff] ;
entries[2*joff] = dtmp ;
dtmp = entries[2*ioff+1] ;
entries[2*ioff+1] = entries[2*joff+1] ;
entries[2*joff+1] = dtmp ;
ioff += stride, joff += stride, stride -= 2 ;
}
for ( ii = icol ; ii < jcol ; ii++ ) {
dtmp = entries[2*ioff] ;
entries[2*ioff] = entries[2*joff] ;
entries[2*joff] = dtmp ;
dtmp = entries[2*ioff+1] ;
entries[2*ioff+1] = entries[2*joff+1] ;
entries[2*joff+1] = dtmp ;
ioff -= 1, joff += stride, stride -= 2 ;
}
for ( ii = jcol ; ii < nD + nL ; ii++ ) {
dtmp = entries[2*ioff] ;
entries[2*ioff] = entries[2*joff] ;
entries[2*joff] = dtmp ;
dtmp = entries[2*ioff+1] ;
entries[2*ioff+1] = entries[2*joff+1] ;
entries[2*joff+1] = dtmp ;
ioff -= 1, joff -= 1 ;
}
}
} else {
fprintf(stderr, "\n fatal error in Chv_swapColumns(%p,%d,%d)"
"\n bad symmetryflag %d\n", chv, icol, jcol, chv->symflag) ;
exit(-1) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------
swap rows and columns ii and jj
created -- 98apr30, cca
-------------------------------
*/
void
Chv_swapRowsAndColumns (
Chv *chv,
int ii,
int jj
) {
double dtmp ;
double *entries ;
int iiloc, ioff, itmp, jjloc, joff, kk, ncol, nD, nL, nU, stride ;
int *colind ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || ii < 0 || jj < 0 ) {
fprintf(stderr,
"\n fatal error in Chv_swapRowsAndColumns(%p,%d,%d)"
"\n bad input\n", chv, ii, jj) ;
exit(-1) ;
}
if ( ii == jj ) {
return ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
if ( entries == NULL || ii >= nD || jj >= nD ) {
fprintf(stderr,
"\n fatal error in Chv_swapRowsAndColumns(%p,%d,%d)"
"\n bad input, entries = %p, nD = %d\n",
chv, ii, jj, entries, nD) ;
exit(-1) ;
}
if ( ! (CHV_IS_REAL(chv) || CHV_IS_COMPLEX(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_swapRowsAndColumns(%p,%d,%d)"
"\n type = %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, ii, jj, chv->type) ;
exit(-1) ;
}
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
--------------------------------------
call methods for nonsymmetric chevrons
--------------------------------------
*/
Chv_swapRows(chv, ii, jj) ;
Chv_swapColumns(chv, ii, jj) ;
} else if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
/*
---------------------------
swap the two column indices
---------------------------
*/
Chv_columnIndices(chv, &ncol, &colind) ;
itmp = colind[ii] ;
colind[ii] = colind[jj] ;
colind[jj] = itmp ;
/*
--------------------------------------
set ii = min(ii, jj), jj = max(ii, jj)
--------------------------------------
*/
if ( ii > jj ) {
itmp = ii ;
ii = jj ;
jj = itmp ;
}
/*
------------------------------------------
step 1, swap A(0:ii-1,ii) and A(0:ii-1,jj)
------------------------------------------
*/
ioff = ii ;
joff = jj ;
stride = nD + nU - 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( kk = 0 ; kk < ii ; kk++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% first step, kk = %d, ioff = %d, joff = %d, stride = %d",
kk, ioff, joff, stride) ;
#endif
dtmp = entries[ioff] ;
entries[ioff] = entries[joff] ;
entries[joff] = dtmp ;
ioff += stride, joff += stride, stride -= 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( kk = 0 ; kk < ii ; kk++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% first step, kk = %d, ioff = %d, joff = %d, stride = %d",
kk, ioff, joff, stride) ;
#endif
dtmp = entries[2*ioff] ;
entries[2*ioff] = entries[2*joff] ;
entries[2*joff] = dtmp ;
dtmp = entries[2*ioff+1] ;
entries[2*ioff+1] = entries[2*joff+1] ;
entries[2*joff+1] = dtmp ;
ioff += stride, joff += stride, stride -= 1 ;
}
}
iiloc = ioff ;
/*
-------------------------------------------
2. swap A(ii,ii+1:jj-1) and A(ii+1:jj-1,jj)
tricky part if hermitian
-------------------------------------------
*/
ioff++, joff += stride, stride -= 1 ;
if ( CHV_IS_REAL(chv) ) {
for ( kk = ii + 1 ; kk < jj ; kk++ ) {
double aiikk, akkjj ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n second step, %% kk = %d, ioff = %d, joff = %d, stride = %d",
kk, ioff, joff, stride) ;
#endif
aiikk = entries[ioff] ;
akkjj = entries[joff] ;
entries[ioff] = akkjj ;
entries[joff] = aiikk ;
ioff += 1, joff += stride, stride -= 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( kk = ii + 1 ; kk < jj ; kk++ ) {
double imagiikk, imagkkjj, realiikk, realkkjj ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n second step, %% kk = %d, ioff = %d, joff = %d, stride = %d",
kk, ioff, joff, stride) ;
#endif
realiikk = entries[2*ioff] ;
imagiikk = entries[2*ioff+1] ;
realkkjj = entries[2*joff] ;
imagkkjj = entries[2*joff+1] ;
entries[2*ioff] = realkkjj ;
entries[2*joff] = realiikk ;
if ( CHV_IS_SYMMETRIC(chv) ) {
entries[2*ioff+1] = imagkkjj ;
entries[2*joff+1] = imagiikk ;
} else {
entries[2*ioff+1] = -imagkkjj ;
entries[2*joff+1] = -imagiikk ;
}
ioff += 1, joff += stride, stride -= 1 ;
}
if ( CHV_IS_HERMITIAN(chv) ) {
/*
----------------------------------
set (ii,jj) entry to its conjugate
----------------------------------
*/
entries[2*ioff+1] = -entries[2*ioff+1] ;
}
}
jjloc = joff ;
/*
-----------------------------
4. swap A(ii,ii) and A(jj,jj)
-----------------------------
*/
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% third step, iiloc = %d, jjloc = %d", iiloc, jjloc) ;
#endif
if ( CHV_IS_REAL(chv) ) {
dtmp = entries[iiloc] ;
entries[iiloc] = entries[jjloc] ;
entries[jjloc] = dtmp ;
} else if ( CHV_IS_COMPLEX(chv) ) {
dtmp = entries[2*iiloc] ;
entries[2*iiloc] = entries[2*jjloc] ;
entries[2*jjloc] = dtmp ;
dtmp = entries[2*iiloc+1] ;
entries[2*iiloc+1] = entries[2*jjloc+1] ;
entries[2*jjloc+1] = dtmp ;
}
/*
-------------------------------------------------
swap
4. swap A(ii,jj+1:nD+nU-1) and A(jj,jj+1:nD+nU-1)
-------------------------------------------------
*/
ioff++, joff++ ;
if ( CHV_IS_REAL(chv) ) {
for ( kk = jj + 1 ; kk < nD + nU ; kk++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% fourth step, kk = %d, ioff = %d, joff = %d, stride = %d",
kk, ioff, joff, stride) ;
#endif
dtmp = entries[ioff] ;
entries[ioff] = entries[joff] ;
entries[joff] = dtmp ;
ioff += 1, joff += 1 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( kk = jj + 1 ; kk < nD + nU ; kk++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% fourth step, kk = %d, ioff = %d, joff = %d, stride = %d",
kk, ioff, joff, stride) ;
#endif
dtmp = entries[2*ioff] ;
entries[2*ioff] = entries[2*joff] ;
entries[2*joff] = dtmp ;
dtmp = entries[2*ioff+1] ;
entries[2*ioff+1] = entries[2*joff+1] ;
entries[2*joff+1] = dtmp ;
ioff += 1, joff += 1 ;
}
}
} else {
fprintf(stderr, "\n fatal error in Chv_swapRowsAndColumns(%p,%d,%d)"
"\n bad symmetryflag %d\n", chv, ii, jj, chv->symflag) ;
exit(-1) ;
}
return ; }
/*--------------------------------------------------------------------*/
Chv/src/update.c 0100644 0002055 0007177 00000341036 06571267314 0015050 0 ustar 00cleve compmath 0000040 0000006 /* update.c */
#include "../Chv.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
purpose -- perform the hermitian factor update
T_{\bnd{I} \cap J, \bnd{I} \cap J}
-= U_{I, \bnd{I} \cap J}^H D_{I, I} U_{I, \bnd{I} \cap J}
and
T_{\bnd{I} \cap J, \bnd{I} \cap \bnd{J}}
-= U_{I, \bnd{I} \cap J}^H D_{I, I} U_{I, \bnd{I} \cap \bnd{J}}
created -- 98apr17, cca
---------------------------------------------------------------------
*/
void
Chv_updateH (
Chv *chvT,
SubMtx *mtxD,
SubMtx *mtxU,
DV *tempDV
) {
int firstInT, firstInU, jcolT, jcolU, lastInT, lastInU, ncolT, ncolU ;
int *colindT, *colindU ;
/*
---------------
check the input
---------------
*/
if ( chvT == NULL || mtxD == NULL || mtxU == NULL || tempDV == NULL ) {
fprintf(stderr, "\n fatal error in Chv_updateH(%p,%p,%p,%p)"
"\n bad input\n", chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
if ( ! CHV_IS_COMPLEX(chvT) ) {
fprintf(stderr, "\n fatal error in Chv_updateH(%p,%p,%p,%p)"
"\n bad input, chvT is not complex\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
if ( ! SUBMTX_IS_COMPLEX(mtxD) ) {
fprintf(stderr, "\n fatal error in Chv_updateH(%p,%p,%p,%p)"
"\n bad input, mtxD is not complex\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
if ( ! SUBMTX_IS_COMPLEX(mtxU) ) {
fprintf(stderr, "\n fatal error in Chv_updateH(%p,%p,%p,%p)"
"\n bad input, mtxU is not complex\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
Chv_columnIndices(chvT, &ncolT, &colindT) ;
SubMtx_columnIndices(mtxU, &ncolU, &colindU) ;
/*
-----------------------------
locate first column of U in T
-----------------------------
*/
firstInT = colindT[0] ;
lastInT = colindT[chvT->nD-1] ;
for ( jcolU = 0 ; jcolU < ncolU ; jcolU++ ) {
if ( firstInT <= colindU[jcolU] && colindU[jcolU] <= lastInT ) {
break ;
}
}
if ( (firstInU = jcolU) == ncolU ) {
return ;
}
/*
----------------------------
locate last column of U in T
----------------------------
*/
lastInU = firstInU ;
for ( ; jcolU < ncolU ; jcolU++ ) {
if ( colindU[jcolU] <= lastInT ) {
lastInU = jcolU ;
} else {
break ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n %% firstInU = %d, lastInU = %d",
firstInU, lastInU) ;
fflush(stdout) ;
#endif
/*
----------------------------------------------------------
overwrite supported column indices with indices local to T
----------------------------------------------------------
*/
for ( jcolU = firstInU, jcolT = 0 ; jcolU < ncolU ; jcolU++ ) {
while ( colindU[jcolU] != colindT[jcolT] ) {
jcolT++ ;
}
colindU[jcolU] = jcolT ;
}
if ( SUBMTX_IS_DENSE_COLUMNS(mtxU) ) {
double isum, rsum ;
double sums[18] ;
double *base0, *base1, *base2, *colU0, *colU1, *colU2, *entU,
*rowUT0, *rowUT1, *rowUT2, *temp0, *temp1, *temp2 ;
int ichv0, ichv1, ichv2, ii, inc1, inc2, irowUT,
kloc0, kloc1, kloc2, nrowU ;
SubMtx_denseInfo(mtxU, &nrowU, &ncolU, &inc1, &inc2, &entU) ;
DV_setSize(tempDV, 6*nrowU) ;
temp0 = DV_entries(tempDV) ;
temp1 = temp0 + 2*nrowU ;
temp2 = temp1 + 2*nrowU ;
/*
--------------------------------------------
loop over the rows of U^H in groups of three
--------------------------------------------
*/
rowUT0 = entU + 2*firstInU*nrowU ;
for ( irowUT = firstInU ; irowUT <= lastInU - 2 ; irowUT += 3 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on rows %d, %d and %d",
colindU[irowUT], colindU[irowUT+1], colindU[irowUT+2]) ;
fflush(stdout) ;
#endif
rowUT1 = rowUT0 + 2*nrowU ;
rowUT2 = rowUT1 + 2*nrowU ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - 2*ichv0 ;
ichv1 = colindU[irowUT+1] ;
base1 = Chv_diagLocation(chvT, ichv1) - 2*ichv1 ;
ichv2 = colindU[irowUT+2] ;
base2 = Chv_diagLocation(chvT, ichv2) - 2*ichv2 ;
/*
------------------------------------
[ temp0 ] [ rowUT0 ]^H
compute [ temp1 ] = [ rowUT1 ] * D
[ temp2 ] [ rowUT2 ]
------------------------------------
*/
DVzero(6*nrowU, temp0) ;
SubMtx_scale3vec(mtxD, temp0, temp1, temp2,
rowUT0, rowUT1, rowUT2) ;
for ( ii = 0 ; ii < nrowU ; ii++ ) {
temp0[2*ii+1] = -temp0[2*ii+1] ;
temp1[2*ii+1] = -temp1[2*ii+1] ;
temp2[2*ii+1] = -temp2[2*ii+1] ;
}
/*
--------------------------------------------------
update the 3x3 upper triangle for these three rows
--------------------------------------------------
*/
colU0 = rowUT0 ;
colU1 = rowUT1 ;
colU2 = rowUT2 ;
ZVdotU(nrowU, temp0, colU0, &rsum, &isum) ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, "\n (%d,%d) : imag(diag) = %12.5e",
chvT->id, mtxD->rowid, base0[2*ichv0+1]) ;
}
*/
/*
base0[2*ichv0] -= rsum ; base0[2*ichv0+1] -= isum ;
*/
base0[2*ichv0] -= rsum ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, ", isum = %12.5e, imag(diag) = %12.5e",
isum, base0[2*ichv0+1]) ;
}
*/
ZVdotU(nrowU, temp0, colU1, &rsum, &isum) ;
base0[2*ichv1] -= rsum ; base0[2*ichv1+1] -= isum ;
ZVdotU(nrowU, temp0, colU2, &rsum, &isum) ;
base0[2*ichv2] -= rsum ; base0[2*ichv2+1] -= isum ;
ZVdotU(nrowU, temp1, colU1, &rsum, &isum) ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, "\n (%d,%d) : imag(diag) = %12.5e",
chvT->id, mtxD->rowid, base1[2*ichv1+1]) ;
}
*/
/*
base1[2*ichv1] -= rsum ; base1[2*ichv1+1] -= isum ;
*/
base1[2*ichv1] -= rsum ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, ", isum = %12.5e, imag(diag) = %12.5e",
isum, base1[2*ichv1+1]) ;
}
*/
ZVdotU(nrowU, temp1, colU2, &rsum, &isum) ;
base1[2*ichv2] -= rsum ; base1[2*ichv2+1] -= isum ;
ZVdotU(nrowU, temp2, colU2, &rsum, &isum) ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, "\n (%d,%d) : imag(diag) = %12.5e",
chvT->id, mtxD->rowid, base2[2*ichv2+1]) ;
}
*/
/*
base2[2*ichv2] -= rsum ; base2[2*ichv2+1] -= isum ;
*/
base2[2*ichv2] -= rsum ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, ", isum = %12.5e, imag(diag) = %12.5e",
isum, base2[2*ichv2+1]) ;
}
*/
colU0 = colU2 + 2*nrowU ;
/*
--------------------------------------
update the remainder of the three rows
--------------------------------------
*/
for ( jcolU = irowUT + 3 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
colU1 = colU0 + 2*nrowU ;
colU2 = colU1 + 2*nrowU ;
ZVdotU33(nrowU, temp0, temp1, temp2,
colU0, colU1, colU2, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
kloc2 = 2*colindU[jcolU+2] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
base0[kloc2] -= sums[ 4] ; base0[kloc2+1] -= sums[ 5] ;
base1[kloc0] -= sums[ 6] ; base1[kloc0+1] -= sums[ 7] ;
base1[kloc1] -= sums[ 8] ; base1[kloc1+1] -= sums[ 9] ;
base1[kloc2] -= sums[10] ; base1[kloc2+1] -= sums[11] ;
base2[kloc0] -= sums[12] ; base2[kloc0+1] -= sums[13] ;
base2[kloc1] -= sums[14] ; base2[kloc1+1] -= sums[15] ;
base2[kloc2] -= sums[16] ; base2[kloc2+1] -= sums[17] ;
colU0 = colU2 + 2*nrowU ;
}
if ( jcolU == ncolU - 2 ) {
colU1 = colU0 + 2*nrowU ;
ZVdotU32(nrowU, temp0, temp1, temp2, colU0, colU1, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
base1[kloc0] -= sums[ 4] ; base1[kloc0+1] -= sums[ 5] ;
base1[kloc1] -= sums[ 6] ; base1[kloc1+1] -= sums[ 7] ;
base2[kloc0] -= sums[ 8] ; base2[kloc0+1] -= sums[ 9] ;
base2[kloc1] -= sums[10] ; base2[kloc1+1] -= sums[11] ;
} else if ( jcolU == ncolU - 1 ) {
ZVdotU31(nrowU, temp0, temp1, temp2, colU0, sums) ;
kloc0 = 2*colindU[jcolU] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base1[kloc0] -= sums[ 2] ; base1[kloc0+1] -= sums[ 3] ;
base2[kloc0] -= sums[ 4] ; base2[kloc0+1] -= sums[ 5] ;
}
rowUT0 = rowUT2 + 2*nrowU ;
}
if ( irowUT == lastInU - 1 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on rows %d and %d",
colindU[irowUT], colindU[irowUT+1]) ;
fflush(stdout) ;
#endif
rowUT1 = rowUT0 + 2*nrowU ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - 2*ichv0 ;
ichv1 = colindU[irowUT+1] ;
base1 = Chv_diagLocation(chvT, ichv1) - 2*ichv1 ;
/*
------------------------------------
[ temp0 ] [ rowUT0 ]^H
compute [ temp1 ] = [ rowUT1 ] * D
------------------------------------
*/
DVzero(4*nrowU, temp0) ;
SubMtx_scale2vec(mtxD, temp0, temp1, rowUT0, rowUT1) ;
for ( ii = 0 ; ii < nrowU ; ii++ ) {
temp0[2*ii+1] = -temp0[2*ii+1] ;
temp1[2*ii+1] = -temp1[2*ii+1] ;
}
/*
------------------------------------------------
update the 2x2 upper triangle for these two rows
------------------------------------------------
*/
colU0 = rowUT0 ;
colU1 = rowUT1 ;
ZVdotU(nrowU, temp0, colU0, &rsum, &isum) ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, "\n (%d,%d) : imag(diag) = %12.5e",
chvT->id, mtxD->rowid, base0[2*ichv0+1]) ;
}
*/
/*
base0[2*ichv0] -= rsum ; base0[2*ichv0+1] -= isum ;
*/
base0[2*ichv0] -= rsum ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, ", isum = %12.5e, imag(diag) = %12.5e",
isum, base0[2*ichv0+1]) ;
}
*/
ZVdotU(nrowU, temp0, colU1, &rsum, &isum) ;
base0[2*ichv1] -= rsum ; base0[2*ichv1+1] -= isum ;
ZVdotU(nrowU, temp1, colU1, &rsum, &isum) ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, "\n (%d,%d) : imag(diag) = %12.5e",
chvT->id, mtxD->rowid, base1[2*ichv1+1]) ;
}
*/
/*
base1[2*ichv1] -= rsum ; base1[2*ichv1+1] -= isum ;
*/
base1[2*ichv1] -= rsum ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, ", isum = %12.5e, imag(diag) = %12.5e",
isum, base1[2*ichv1+1]) ;
}
*/
colU0 = colU1 + 2*nrowU ;
/*
------------------------------------
update the remainder of the two rows
------------------------------------
*/
for ( jcolU = irowUT + 2 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
colU1 = colU0 + 2*nrowU ;
colU2 = colU1 + 2*nrowU ;
ZVdotU23(nrowU, temp0, temp1, colU0, colU1, colU2, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
kloc2 = 2*colindU[jcolU+2] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
base0[kloc2] -= sums[ 4] ; base0[kloc2+1] -= sums[ 5] ;
base1[kloc0] -= sums[ 6] ; base1[kloc0+1] -= sums[ 7] ;
base1[kloc1] -= sums[ 8] ; base1[kloc1+1] -= sums[ 9] ;
base1[kloc2] -= sums[10] ; base1[kloc2+1] -= sums[11] ;
colU0 = colU2 + 2*nrowU ;
}
if ( jcolU == ncolU - 2 ) {
colU1 = colU0 + 2*nrowU ;
ZVdotU22(nrowU, temp0, temp1, colU0, colU1, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
base1[kloc0] -= sums[ 4] ; base1[kloc0+1] -= sums[ 5] ;
base1[kloc1] -= sums[ 6] ; base1[kloc1+1] -= sums[ 7] ;
} else if ( jcolU == ncolU - 1 ) {
ZVdotU21(nrowU, temp0, temp1, colU0, sums) ;
kloc0 = 2*colindU[jcolU] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base1[kloc0] -= sums[ 2] ; base1[kloc0+1] -= sums[ 3] ;
}
} else if ( irowUT == lastInU ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on row %d", colindU[irowUT]) ;
fflush(stdout) ;
#endif
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - 2*ichv0 ;
/*
------------------------------------
compute [ temp0 ] = [ rowUT0 ]^H * D
------------------------------------
*/
DVzero(2*nrowU, temp0) ;
SubMtx_scale1vec(mtxD, temp0, rowUT0) ;
for ( ii = 0 ; ii < nrowU ; ii++ ) {
temp0[2*ii+1] = -temp0[2*ii+1] ;
}
/*
------------------------------------------
update the 1x1 upper triangle for this row
------------------------------------------
*/
colU0 = rowUT0 ;
ZVdotU(nrowU, temp0, colU0, &rsum, &isum) ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, "\n (%d,%d) : imag(diag) = %12.5e",
chvT->id, mtxD->rowid, base0[2*ichv0+1]) ;
}
*/
/*
base0[2*ichv0] -= rsum ; base0[2*ichv0+1] -= isum ;
*/
base0[2*ichv0] -= rsum ;
/*
if ( chvT->id != -1 ) {
fprintf(stdout, ", isum = %12.5e, imag(diag) = %12.5e",
isum, base0[2*ichv0+1]) ;
}
*/
colU0 = colU0 + 2*nrowU ;
/*
-------------------------------
update the remainder of the row
-------------------------------
*/
for ( jcolU = irowUT + 1 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on columns %d, %d and %d",
jcolU, jcolU+1, jcolU+2) ;
fflush(stdout) ;
#endif
colU1 = colU0 + 2*nrowU ;
colU2 = colU1 + 2*nrowU ;
ZVdotU13(nrowU, temp0, colU0, colU1, colU2, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
kloc2 = 2*colindU[jcolU+2] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
base0[kloc2] -= sums[ 4] ; base0[kloc2+1] -= sums[ 5] ;
colU0 = colU2 + 2*nrowU ;
}
if ( jcolU == ncolU - 2 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on columns %d and %d",
jcolU, jcolU+1) ;
fflush(stdout) ;
#endif
colU1 = colU0 + 2*nrowU ;
ZVdotU12(nrowU, temp0, colU0, colU1, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
} else if ( jcolU == ncolU - 1 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on column %d", jcolU) ;
fflush(stdout) ;
#endif
ZVdotU11(nrowU, temp0, colU0, sums) ;
/*
fprintf(stdout, "\n SUMS[0] = %12.4e, SUMS[1] = %12.4e",
sums[0], sums[1]) ;
*/
kloc0 = 2*colindU[jcolU] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
/*
fprintf(stdout, "\n base0[%d] = %12.4e, base0[%d] = %12.4e",
kloc0, base0[kloc0], kloc0+1, base0[kloc0+1]) ;
*/
}
}
} else if ( SUBMTX_IS_SPARSE_COLUMNS(mtxU) ) {
double isum, rsum ;
double *base0, *colU0, *entU, *rowUT0, *temp0, *temp1 ;
int ichv0, ii, iloc, irowUT, kloc0, nentU, nrowU, offset,
rloc, sizeU, sizeUT ;
int *indU, *indU0, *indUT0, *sizes ;
SubMtx_sparseColumnsInfo(mtxU, &ncolU, &nentU, &sizes, &indU, &entU) ;
nrowU = mtxU->nrow ;
DV_setSize(tempDV, 4*nrowU) ;
temp0 = DV_entries(tempDV) ;
temp1 = temp0 + 2*nrowU ;
/*
-------------------------------------------
get the offset into the indices and entries
-------------------------------------------
*/
for ( jcolU = offset = 0 ; jcolU < firstInU ; jcolU++ ) {
offset += sizes[jcolU] ;
}
/*
------------------------------------
loop over the supporting rows of U^H
------------------------------------
*/
rowUT0 = entU + 2*offset ;
indUT0 = indU + offset ;
for ( irowUT = firstInU ; irowUT <= lastInU ; irowUT++ ) {
if ( (sizeUT = sizes[irowUT]) > 0 ) {
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - 2*ichv0 ;
/*
------------------------------------
compute [ temp0 ] = [ rowUT0 ]^H * D
------------------------------------
*/
DVzero(4*nrowU, temp0) ;
for ( ii = 0 ; ii < sizeUT ; ii++ ) {
rloc = 2*indUT0[ii] ; iloc = rloc + 1 ;
temp1[rloc] = rowUT0[2*ii] ;
temp1[iloc] = rowUT0[2*ii+1] ;
}
SubMtx_scale1vec(mtxD, temp0, temp1) ;
for ( ii = 0 ; ii < nrowU ; ii++ ) {
temp0[2*ii+1] = -temp0[2*ii+1] ;
}
/*
-------------------------------
loop over the following columns
-------------------------------
*/
colU0 = rowUT0 ;
indU0 = indUT0 ;
for ( jcolU = irowUT ; jcolU < ncolU ; jcolU++ ) {
if ( (sizeU = sizes[jcolU]) > 0 ) {
ZVdotiU(sizeU, temp0, indU0, colU0, &rsum, &isum) ;
kloc0 = 2*colindU[jcolU] ;
base0[kloc0] -= rsum ; base0[kloc0+1] -= isum ;
colU0 += 2*sizeU ;
indU0 += sizeU ;
}
}
rowUT0 += 2*sizeUT ;
indUT0 += sizeUT ;
}
}
} else {
fprintf(stderr, "\n fatal error in Chv_updateH(%p,%p,%p,%p)"
"\n mtxU must have dense or sparse columns\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
/*
---------------------------------------------------
overwrite the local indices with the global indices
---------------------------------------------------
*/
for ( jcolU = firstInU ; jcolU < ncolU ; jcolU++ ) {
colindU[jcolU] = colindT[colindU[jcolU]] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
purpose -- perform the symmetric factor update
T_{\bnd{I} \cap J, \bnd{I} \cap J}
-= U_{I, \bnd{I} \cap J}^T D_{I, I} U_{I, \bnd{I} \cap J}
and
T_{\bnd{I} \cap J, \bnd{I} \cap \bnd{J}}
-= U_{I, \bnd{I} \cap J}^T D_{I, I} U_{I, \bnd{I} \cap \bnd{J}}
created -- 98apr17, cca
---------------------------------------------------------------------
*/
void
Chv_updateS (
Chv *chvT,
SubMtx *mtxD,
SubMtx *mtxU,
DV *tempDV
) {
int firstInT, firstInU, jcolT, jcolU, lastInT, lastInU, ncolT, ncolU ;
int *colindT, *colindU ;
/*
---------------
check the input
---------------
*/
if ( chvT == NULL || mtxD == NULL || mtxU == NULL || tempDV == NULL ) {
fprintf(stderr, "\n fatal error in Chv_updateS(%p,%p,%p,%p)"
"\n bad input\n", chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
if ( CHV_IS_REAL(chvT) ) {
if ( ! SUBMTX_IS_REAL(mtxD) || ! SUBMTX_IS_REAL(mtxU) ) {
fprintf(stderr, "\n fatal error in Chv_updateT(%p,%p,%p,%p)"
"\n chvT is real, but mtxD and/or mtxU are not\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
} else if ( CHV_IS_COMPLEX(chvT) ) {
if ( ! SUBMTX_IS_COMPLEX(mtxD) || ! SUBMTX_IS_COMPLEX(mtxU) ) {
fprintf(stderr, "\n fatal error in Chv_updateT(%p,%p,%p,%p)"
"\n chvT is complex, but mtxD and/or mtxU are not\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_updateT(%p,%p,%p,%p)"
"\n bad input, chvT is not real or complex\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
Chv_columnIndices(chvT, &ncolT, &colindT) ;
SubMtx_columnIndices(mtxU, &ncolU, &colindU) ;
#if MYDEBUG > 0
fprintf(stdout, "\n %% Chv column indices") ;
IVfprintf(stdout, ncolT, colindT) ;
fprintf(stdout, "\n %% submtx column indices") ;
IVfprintf(stdout, ncolU, colindU) ;
fflush(stdout) ;
#endif
/*
-----------------------------
locate first column of U in T
-----------------------------
*/
firstInT = colindT[0] ;
lastInT = colindT[chvT->nD-1] ;
for ( jcolU = 0 ; jcolU < ncolU ; jcolU++ ) {
if ( firstInT <= colindU[jcolU] && colindU[jcolU] <= lastInT ) {
break ;
}
}
if ( (firstInU = jcolU) == ncolU ) {
return ;
}
/*
----------------------------
locate last column of U in T
----------------------------
*/
lastInU = firstInU ;
for ( ; jcolU < ncolU ; jcolU++ ) {
if ( colindU[jcolU] <= lastInT ) {
lastInU = jcolU ;
} else {
break ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n %% firstInU = %d, lastInU = %d",
firstInU, lastInU) ;
fflush(stdout) ;
#endif
/*
----------------------------------------------------------
overwrite supported column indices with indices local to T
----------------------------------------------------------
*/
for ( jcolU = firstInU, jcolT = 0 ; jcolU < ncolU ; jcolU++ ) {
while ( colindU[jcolU] != colindT[jcolT] ) {
jcolT++ ;
}
colindU[jcolU] = jcolT ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n %% submtx column indices") ;
IVfprintf(stdout, ncolU, colindU) ;
fflush(stdout) ;
#endif
if ( CHV_IS_REAL(chvT) ) {
if ( SUBMTX_IS_DENSE_COLUMNS(mtxU) ) {
double sums[9] ;
double *base0, *base1, *base2, *colU0, *colU1, *colU2, *entU,
*rowUT0, *rowUT1, *rowUT2, *temp0, *temp1, *temp2 ;
int ichv0, ichv1, ichv2, inc1, inc2, irowUT,
kloc0, kloc1, kloc2, nrowU ;
SubMtx_denseInfo(mtxU, &nrowU, &ncolU, &inc1, &inc2, &entU) ;
DV_setSize(tempDV, 3*nrowU) ;
temp0 = DV_entries(tempDV) ;
temp1 = temp0 + nrowU ;
temp2 = temp1 + nrowU ;
/*
--------------------------------------------
loop over the rows of U^T in groups of three
--------------------------------------------
*/
rowUT0 = entU + firstInU*nrowU ;
for ( irowUT = firstInU ; irowUT <= lastInU - 2 ; irowUT += 3 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on rows %d, %d and %d",
colindU[irowUT], colindU[irowUT+1], colindU[irowUT+2]) ;
fflush(stdout) ;
#endif
rowUT1 = rowUT0 + nrowU ;
rowUT2 = rowUT1 + nrowU ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - ichv0 ;
ichv1 = colindU[irowUT+1] ;
base1 = Chv_diagLocation(chvT, ichv1) - ichv1 ;
ichv2 = colindU[irowUT+2] ;
base2 = Chv_diagLocation(chvT, ichv2) - ichv2 ;
/*
------------------------------------
[ temp0 ] [ rowUT0 ]^T
compute [ temp1 ] = [ rowUT1 ] * D
[ temp2 ] [ rowUT2 ]
------------------------------------
*/
DVzero(3*nrowU, temp0) ;
SubMtx_scale3vec(mtxD, temp0, temp1, temp2,
rowUT0, rowUT1, rowUT2) ;
/*
--------------------------------------------------
update the 3x3 upper triangle for these three rows
--------------------------------------------------
*/
colU0 = rowUT0 ;
colU1 = rowUT1 ;
colU2 = rowUT2 ;
base0[ichv0] -= DVdot(nrowU, temp0, colU0) ;
base0[ichv1] -= DVdot(nrowU, temp0, colU1) ;
base0[ichv2] -= DVdot(nrowU, temp0, colU2) ;
base1[ichv1] -= DVdot(nrowU, temp1, colU1) ;
base1[ichv2] -= DVdot(nrowU, temp1, colU2) ;
base2[ichv2] -= DVdot(nrowU, temp2, colU2) ;
colU0 = colU2 + nrowU ;
/*
--------------------------------------
update the remainder of the three rows
--------------------------------------
*/
for ( jcolU = irowUT + 3 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
colU1 = colU0 + nrowU ;
colU2 = colU1 + nrowU ;
DVdot33(nrowU, temp0, temp1, temp2,
colU0, colU1, colU2, sums) ;
kloc0 = colindU[jcolU] ;
kloc1 = colindU[jcolU+1] ;
kloc2 = colindU[jcolU+2] ;
base0[kloc0] -= sums[0] ;
base0[kloc1] -= sums[1] ;
base0[kloc2] -= sums[2] ;
base1[kloc0] -= sums[3] ;
base1[kloc1] -= sums[4] ;
base1[kloc2] -= sums[5] ;
base2[kloc0] -= sums[6] ;
base2[kloc1] -= sums[7] ;
base2[kloc2] -= sums[8] ;
colU0 = colU2 + nrowU ;
}
if ( jcolU == ncolU - 2 ) {
colU1 = colU0 + nrowU ;
DVdot32(nrowU, temp0, temp1, temp2, colU0, colU1, sums) ;
kloc0 = colindU[jcolU] ;
kloc1 = colindU[jcolU+1] ;
base0[kloc0] -= sums[0] ;
base0[kloc1] -= sums[1] ;
base1[kloc0] -= sums[2] ;
base1[kloc1] -= sums[3] ;
base2[kloc0] -= sums[4] ;
base2[kloc1] -= sums[5] ;
} else if ( jcolU == ncolU - 1 ) {
DVdot31(nrowU, temp0, temp1, temp2, colU0, sums) ;
kloc0 = colindU[jcolU] ;
base0[kloc0] -= sums[0] ;
base1[kloc0] -= sums[1] ;
base2[kloc0] -= sums[2] ;
}
rowUT0 = rowUT2 + nrowU ;
}
if ( irowUT == lastInU - 1 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on rows %d and %d",
colindU[irowUT], colindU[irowUT+1]) ;
fflush(stdout) ;
#endif
rowUT1 = rowUT0 + nrowU ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - ichv0 ;
ichv1 = colindU[irowUT+1] ;
base1 = Chv_diagLocation(chvT, ichv1) - ichv1 ;
/*
------------------------------------
[ temp0 ] [ rowUT0 ]^T
compute [ temp1 ] = [ rowUT1 ] * D
------------------------------------
*/
DVzero(2*nrowU, temp0) ;
SubMtx_scale2vec(mtxD, temp0, temp1, rowUT0, rowUT1) ;
/*
------------------------------------------------
update the 2x2 upper triangle for these two rows
------------------------------------------------
*/
colU0 = rowUT0 ;
colU1 = rowUT1 ;
base0[ichv0] -= DVdot(nrowU, temp0, colU0) ;
base0[ichv1] -= DVdot(nrowU, temp0, colU1) ;
base1[ichv1] -= DVdot(nrowU, temp1, colU1) ;
colU0 = colU1 + nrowU ;
/*
------------------------------------
update the remainder of the two rows
------------------------------------
*/
for ( jcolU = irowUT + 2 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
colU1 = colU0 + nrowU ;
colU2 = colU1 + nrowU ;
DVdot23(nrowU, temp0, temp1, colU0, colU1, colU2, sums) ;
kloc0 = colindU[jcolU] ;
kloc1 = colindU[jcolU+1] ;
kloc2 = colindU[jcolU+2] ;
base0[kloc0] -= sums[0] ;
base0[kloc1] -= sums[1] ;
base0[kloc2] -= sums[2] ;
base1[kloc0] -= sums[3] ;
base1[kloc1] -= sums[4] ;
base1[kloc2] -= sums[5] ;
colU0 = colU2 + nrowU ;
}
if ( jcolU == ncolU - 2 ) {
colU1 = colU0 + nrowU ;
DVdot22(nrowU, temp0, temp1, colU0, colU1, sums) ;
kloc0 = colindU[jcolU] ;
kloc1 = colindU[jcolU+1] ;
base0[kloc0] -= sums[0] ;
base0[kloc1] -= sums[1] ;
base1[kloc0] -= sums[2] ;
base1[kloc1] -= sums[3] ;
} else if ( jcolU == ncolU - 1 ) {
DVdot21(nrowU, temp0, temp1, colU0, sums) ;
kloc0 = colindU[jcolU] ;
base0[kloc0] -= sums[0] ;
base1[kloc0] -= sums[1] ;
}
} else if ( irowUT == lastInU ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on row %d", colindU[irowUT]) ;
fflush(stdout) ;
#endif
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - ichv0 ;
/*
------------------------------------
compute [ temp0 ] = [ rowUT0 ]^T * D
------------------------------------
*/
DVzero(nrowU, temp0) ;
SubMtx_scale1vec(mtxD, temp0, rowUT0) ;
/*
------------------------------------------
update the 1x1 upper triangle for this row
------------------------------------------
*/
colU0 = rowUT0 ;
base0[ichv0] -= DVdot(nrowU, temp0, colU0) ;
colU0 = colU0 + nrowU ;
/*
-------------------------------
update the remainder of the row
-------------------------------
*/
for ( jcolU = irowUT + 1 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on columns %d, %d and %d",
jcolU, jcolU+1, jcolU+2) ;
fflush(stdout) ;
#endif
colU1 = colU0 + nrowU ;
colU2 = colU1 + nrowU ;
DVdot13(nrowU, temp0, colU0, colU1, colU2, sums) ;
kloc0 = colindU[jcolU] ;
kloc1 = colindU[jcolU+1] ;
kloc2 = colindU[jcolU+2] ;
base0[kloc0] -= sums[0] ;
base0[kloc1] -= sums[1] ;
base0[kloc2] -= sums[2] ;
colU0 = colU2 + nrowU ;
}
if ( jcolU == ncolU - 2 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on columns %d and %d",
jcolU, jcolU+1) ;
fflush(stdout) ;
#endif
colU1 = colU0 + nrowU ;
DVdot12(nrowU, temp0, colU0, colU1, sums) ;
kloc0 = colindU[jcolU] ;
kloc1 = colindU[jcolU+1] ;
base0[kloc0] -= sums[0] ;
base0[kloc1] -= sums[1] ;
} else if ( jcolU == ncolU - 1 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on column %d", jcolU) ;
fflush(stdout) ;
#endif
DVdot11(nrowU, temp0, colU0, sums) ;
kloc0 = colindU[jcolU] ;
base0[kloc0] -= sums[0] ;
}
}
} else if ( SUBMTX_IS_SPARSE_COLUMNS(mtxU) ) {
double sum ;
double *base0, *colU0, *entU, *rowUT0, *temp0, *temp1 ;
int ichv0, ii, irowUT, kloc0, loc, nentU, nrowU, offset,
sizeU, sizeUT ;
int *indU, *indU0, *indUT0, *sizes ;
SubMtx_sparseColumnsInfo(mtxU,
&ncolU, &nentU, &sizes, &indU, &entU) ;
nrowU = mtxU->nrow ;
DV_setSize(tempDV, 2*nrowU) ;
temp0 = DV_entries(tempDV) ;
temp1 = temp0 + nrowU ;
/*
-------------------------------------------
get the offset into the indices and entries
-------------------------------------------
*/
for ( jcolU = offset = 0 ; jcolU < firstInU ; jcolU++ ) {
offset += sizes[jcolU] ;
}
/*
------------------------------------
loop over the supporting rows of U^T
------------------------------------
*/
rowUT0 = entU + offset ;
indUT0 = indU + offset ;
for ( irowUT = firstInU ; irowUT <= lastInU ; irowUT++ ) {
if ( (sizeUT = sizes[irowUT]) > 0 ) {
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - ichv0 ;
/*
------------------------------------
compute [ temp0 ] = [ rowUT0 ]^T * D
------------------------------------
*/
DVzero(2*nrowU, temp0) ;
for ( ii = 0 ; ii < sizeUT ; ii++ ) {
loc = indUT0[ii] ;
temp1[loc] = rowUT0[ii] ;
}
SubMtx_scale1vec(mtxD, temp0, temp1) ;
/*
-------------------------------
loop over the following columns
-------------------------------
*/
colU0 = rowUT0 ;
indU0 = indUT0 ;
for ( jcolU = irowUT ; jcolU < ncolU ; jcolU++ ) {
if ( (sizeU = sizes[jcolU]) > 0 ) {
sum = DVdoti(sizeU, temp0, indU0, colU0) ;
kloc0 = colindU[jcolU] ;
base0[kloc0] -= sum ;
colU0 += sizeU ;
indU0 += sizeU ;
}
}
rowUT0 += sizeUT ;
indUT0 += sizeUT ;
}
}
} else {
fprintf(stderr, "\n fatal error in Chv_updateT(%p,%p,%p,%p)"
"\n bad input, mtxU must have dense or sparse columns\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
} else if ( CHV_IS_COMPLEX(chvT) ) {
if ( SUBMTX_IS_DENSE_COLUMNS(mtxU) ) {
double isum, rsum ;
double sums[18] ;
double *base0, *base1, *base2, *colU0, *colU1, *colU2, *entU,
*rowUT0, *rowUT1, *rowUT2, *temp0, *temp1, *temp2 ;
int ichv0, ichv1, ichv2, inc1, inc2, irowUT,
kloc0, kloc1, kloc2, nrowU ;
SubMtx_denseInfo(mtxU, &nrowU, &ncolU, &inc1, &inc2, &entU) ;
DV_setSize(tempDV, 6*nrowU) ;
temp0 = DV_entries(tempDV) ;
temp1 = temp0 + 2*nrowU ;
temp2 = temp1 + 2*nrowU ;
/*
--------------------------------------------
loop over the rows of U^T in groups of three
--------------------------------------------
*/
rowUT0 = entU + 2*firstInU*nrowU ;
for ( irowUT = firstInU ; irowUT <= lastInU - 2 ; irowUT += 3 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on rows %d, %d and %d",
colindU[irowUT], colindU[irowUT+1], colindU[irowUT+2]) ;
fflush(stdout) ;
#endif
rowUT1 = rowUT0 + 2*nrowU ;
rowUT2 = rowUT1 + 2*nrowU ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - 2*ichv0 ;
ichv1 = colindU[irowUT+1] ;
base1 = Chv_diagLocation(chvT, ichv1) - 2*ichv1 ;
ichv2 = colindU[irowUT+2] ;
base2 = Chv_diagLocation(chvT, ichv2) - 2*ichv2 ;
/*
------------------------------------
[ temp0 ] [ rowUT0 ]^T
compute [ temp1 ] = [ rowUT1 ] * D
[ temp2 ] [ rowUT2 ]
------------------------------------
*/
DVzero(6*nrowU, temp0) ;
SubMtx_scale3vec(mtxD, temp0, temp1, temp2,
rowUT0, rowUT1, rowUT2) ;
/*
--------------------------------------------------
update the 3x3 upper triangle for these three rows
--------------------------------------------------
*/
colU0 = rowUT0 ;
colU1 = rowUT1 ;
colU2 = rowUT2 ;
ZVdotU(nrowU, temp0, colU0, &rsum, &isum) ;
base0[2*ichv0] -= rsum ; base0[2*ichv0+1] -= isum ;
ZVdotU(nrowU, temp0, colU1, &rsum, &isum) ;
base0[2*ichv1] -= rsum ; base0[2*ichv1+1] -= isum ;
ZVdotU(nrowU, temp0, colU2, &rsum, &isum) ;
base0[2*ichv2] -= rsum ; base0[2*ichv2+1] -= isum ;
ZVdotU(nrowU, temp1, colU1, &rsum, &isum) ;
base1[2*ichv1] -= rsum ; base1[2*ichv1+1] -= isum ;
ZVdotU(nrowU, temp1, colU2, &rsum, &isum) ;
base1[2*ichv2] -= rsum ; base1[2*ichv2+1] -= isum ;
ZVdotU(nrowU, temp2, colU2, &rsum, &isum) ;
base2[2*ichv2] -= rsum ; base2[2*ichv2+1] -= isum ;
colU0 = colU2 + 2*nrowU ;
/*
--------------------------------------
update the remainder of the three rows
--------------------------------------
*/
for ( jcolU = irowUT + 3 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
colU1 = colU0 + 2*nrowU ;
colU2 = colU1 + 2*nrowU ;
ZVdotU33(nrowU, temp0, temp1, temp2,
colU0, colU1, colU2, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
kloc2 = 2*colindU[jcolU+2] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
base0[kloc2] -= sums[ 4] ; base0[kloc2+1] -= sums[ 5] ;
base1[kloc0] -= sums[ 6] ; base1[kloc0+1] -= sums[ 7] ;
base1[kloc1] -= sums[ 8] ; base1[kloc1+1] -= sums[ 9] ;
base1[kloc2] -= sums[10] ; base1[kloc2+1] -= sums[11] ;
base2[kloc0] -= sums[12] ; base2[kloc0+1] -= sums[13] ;
base2[kloc1] -= sums[14] ; base2[kloc1+1] -= sums[15] ;
base2[kloc2] -= sums[16] ; base2[kloc2+1] -= sums[17] ;
colU0 = colU2 + 2*nrowU ;
}
if ( jcolU == ncolU - 2 ) {
colU1 = colU0 + 2*nrowU ;
ZVdotU32(nrowU, temp0, temp1, temp2, colU0, colU1, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
base1[kloc0] -= sums[ 4] ; base1[kloc0+1] -= sums[ 5] ;
base1[kloc1] -= sums[ 6] ; base1[kloc1+1] -= sums[ 7] ;
base2[kloc0] -= sums[ 8] ; base2[kloc0+1] -= sums[ 9] ;
base2[kloc1] -= sums[10] ; base2[kloc1+1] -= sums[11] ;
} else if ( jcolU == ncolU - 1 ) {
ZVdotU31(nrowU, temp0, temp1, temp2, colU0, sums) ;
kloc0 = 2*colindU[jcolU] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base1[kloc0] -= sums[ 2] ; base1[kloc0+1] -= sums[ 3] ;
base2[kloc0] -= sums[ 4] ; base2[kloc0+1] -= sums[ 5] ;
}
rowUT0 = rowUT2 + 2*nrowU ;
}
if ( irowUT == lastInU - 1 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on rows %d and %d",
colindU[irowUT], colindU[irowUT+1]) ;
fflush(stdout) ;
#endif
rowUT1 = rowUT0 + 2*nrowU ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - 2*ichv0 ;
ichv1 = colindU[irowUT+1] ;
base1 = Chv_diagLocation(chvT, ichv1) - 2*ichv1 ;
/*
------------------------------------
[ temp0 ] [ rowUT0 ]^T
compute [ temp1 ] = [ rowUT1 ] * D
------------------------------------
*/
DVzero(4*nrowU, temp0) ;
SubMtx_scale2vec(mtxD, temp0, temp1, rowUT0, rowUT1) ;
/*
------------------------------------------------
update the 2x2 upper triangle for these two rows
------------------------------------------------
*/
colU0 = rowUT0 ;
colU1 = rowUT1 ;
ZVdotU(nrowU, temp0, colU0, &rsum, &isum) ;
base0[2*ichv0] -= rsum ; base0[2*ichv0+1] -= isum ;
ZVdotU(nrowU, temp0, colU1, &rsum, &isum) ;
base0[2*ichv1] -= rsum ; base0[2*ichv1+1] -= isum ;
ZVdotU(nrowU, temp1, colU1, &rsum, &isum) ;
base1[2*ichv1] -= rsum ; base1[2*ichv1+1] -= isum ;
colU0 = colU1 + 2*nrowU ;
/*
------------------------------------
update the remainder of the two rows
------------------------------------
*/
for ( jcolU = irowUT + 2 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
colU1 = colU0 + 2*nrowU ;
colU2 = colU1 + 2*nrowU ;
ZVdotU23(nrowU, temp0, temp1, colU0, colU1, colU2, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
kloc2 = 2*colindU[jcolU+2] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
base0[kloc2] -= sums[ 4] ; base0[kloc2+1] -= sums[ 5] ;
base1[kloc0] -= sums[ 6] ; base1[kloc0+1] -= sums[ 7] ;
base1[kloc1] -= sums[ 8] ; base1[kloc1+1] -= sums[ 9] ;
base1[kloc2] -= sums[10] ; base1[kloc2+1] -= sums[11] ;
colU0 = colU2 + 2*nrowU ;
}
if ( jcolU == ncolU - 2 ) {
colU1 = colU0 + 2*nrowU ;
ZVdotU22(nrowU, temp0, temp1, colU0, colU1, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
base1[kloc0] -= sums[ 4] ; base1[kloc0+1] -= sums[ 5] ;
base1[kloc1] -= sums[ 6] ; base1[kloc1+1] -= sums[ 7] ;
} else if ( jcolU == ncolU - 1 ) {
ZVdotU21(nrowU, temp0, temp1, colU0, sums) ;
kloc0 = 2*colindU[jcolU] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base1[kloc0] -= sums[ 2] ; base1[kloc0+1] -= sums[ 3] ;
}
} else if ( irowUT == lastInU ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on row %d", colindU[irowUT]) ;
fflush(stdout) ;
#endif
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - 2*ichv0 ;
/*
------------------------------------
compute [ temp0 ] = [ rowUT0 ]^T * D
------------------------------------
*/
DVzero(2*nrowU, temp0) ;
SubMtx_scale1vec(mtxD, temp0, rowUT0) ;
/*
------------------------------------------
update the 1x1 upper triangle for this row
------------------------------------------
*/
colU0 = rowUT0 ;
ZVdotU(nrowU, temp0, colU0, &rsum, &isum) ;
base0[2*ichv0] -= rsum ; base0[2*ichv0+1] -= isum ;
colU0 = colU0 + 2*nrowU ;
/*
-------------------------------
update the remainder of the row
-------------------------------
*/
for ( jcolU = irowUT + 1 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on columns %d, %d and %d",
jcolU, jcolU+1, jcolU+2) ;
fflush(stdout) ;
#endif
colU1 = colU0 + 2*nrowU ;
colU2 = colU1 + 2*nrowU ;
ZVdotU13(nrowU, temp0, colU0, colU1, colU2, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
kloc2 = 2*colindU[jcolU+2] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
base0[kloc2] -= sums[ 4] ; base0[kloc2+1] -= sums[ 5] ;
colU0 = colU2 + 2*nrowU ;
}
if ( jcolU == ncolU - 2 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on columns %d and %d",
jcolU, jcolU+1) ;
fflush(stdout) ;
#endif
colU1 = colU0 + 2*nrowU ;
ZVdotU12(nrowU, temp0, colU0, colU1, sums) ;
kloc0 = 2*colindU[jcolU] ;
kloc1 = 2*colindU[jcolU+1] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
base0[kloc1] -= sums[ 2] ; base0[kloc1+1] -= sums[ 3] ;
} else if ( jcolU == ncolU - 1 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on column %d", jcolU) ;
fflush(stdout) ;
#endif
ZVdotU11(nrowU, temp0, colU0, sums) ;
kloc0 = 2*colindU[jcolU] ;
base0[kloc0] -= sums[ 0] ; base0[kloc0+1] -= sums[ 1] ;
}
}
} else if ( SUBMTX_IS_SPARSE_COLUMNS(mtxU) ) {
double isum, rsum ;
double *base0, *colU0, *entU, *rowUT0, *temp0, *temp1 ;
int ichv0, ii, iloc, irowUT, kloc0, nentU, nrowU, offset,
rloc, sizeU, sizeUT ;
int *indU, *indU0, *indUT0, *sizes ;
SubMtx_sparseColumnsInfo(mtxU,
&ncolU, &nentU, &sizes, &indU, &entU) ;
nrowU = mtxU->nrow ;
DV_setSize(tempDV, 4*nrowU) ;
temp0 = DV_entries(tempDV) ;
temp1 = temp0 + 2*nrowU ;
/*
-------------------------------------------
get the offset into the indices and entries
-------------------------------------------
*/
for ( jcolU = offset = 0 ; jcolU < firstInU ; jcolU++ ) {
offset += sizes[jcolU] ;
}
/*
------------------------------------
loop over the supporting rows of U^T
------------------------------------
*/
rowUT0 = entU + 2*offset ;
indUT0 = indU + offset ;
for ( irowUT = firstInU ; irowUT <= lastInU ; irowUT++ ) {
if ( (sizeUT = sizes[irowUT]) > 0 ) {
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowUT] ;
base0 = Chv_diagLocation(chvT, ichv0) - 2*ichv0 ;
/*
------------------------------------
compute [ temp0 ] = [ rowUT0 ]^T * D
------------------------------------
*/
DVzero(4*nrowU, temp0) ;
for ( ii = 0 ; ii < sizeUT ; ii++ ) {
rloc = 2*indUT0[ii] ; iloc = rloc + 1 ;
temp1[rloc] = rowUT0[2*ii] ;
temp1[iloc] = rowUT0[2*ii+1] ;
}
SubMtx_scale1vec(mtxD, temp0, temp1) ;
/*
-------------------------------
loop over the following columns
-------------------------------
*/
colU0 = rowUT0 ;
indU0 = indUT0 ;
for ( jcolU = irowUT ; jcolU < ncolU ; jcolU++ ) {
if ( (sizeU = sizes[jcolU]) > 0 ) {
ZVdotiU(sizeU, temp0, indU0, colU0, &rsum, &isum) ;
kloc0 = 2*colindU[jcolU] ;
base0[kloc0] -= rsum ; base0[kloc0+1] -= isum ;
colU0 += 2*sizeU ;
indU0 += sizeU ;
}
}
rowUT0 += 2*sizeUT ;
indUT0 += sizeUT ;
}
}
} else {
fprintf(stderr, "\n fatal error in Chv_updateT(%p,%p,%p,%p)"
"\n bad input, mtxU must have dense or sparse columns\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
}
/*
---------------------------------------------------
overwrite the local indices with the global indices
---------------------------------------------------
*/
for ( jcolU = firstInU ; jcolU < ncolU ; jcolU++ ) {
colindU[jcolU] = colindT[colindU[jcolU]] ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
purpose -- perform the nonsymmetric factor update
T_{\bnd{I} \cap J, \bnd{I} \cap J}
-= L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J}
and
T_{\bnd{I} \cap J, \bnd{I} \cap \bnd{J}}
-= L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap \bnd{J}}
and
T_{\bnd{I} \cap \bnd{J}, \bnd{I} \cap J}
-= L_{\bnd{I} \cap \bnd{J}, I} D_{I, I} U_{I, \bnd{I} \cap J}
created -- 98feb27, cca
---------------------------------------------------------------------
*/
void
Chv_updateN (
Chv *chvT,
SubMtx *mtxL,
SubMtx *mtxD,
SubMtx *mtxU,
DV *tempDV
) {
int firstInT, firstInU, jcolT, jcolU, lastInT, lastInU, ncolT, ncolU ;
int *colindT, *colindU ;
/*
---------------
check the input
---------------
*/
if ( chvT == NULL || mtxD == NULL || mtxU == NULL || tempDV == NULL ) {
fprintf(stderr, "\n fatal error in Chv_updateN(%p,%p,%p,%p,%p)"
"\n bad input\n", chvT, mtxL, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
if ( CHV_IS_REAL(chvT) ) {
if ( ! SUBMTX_IS_REAL(mtxD) || ! SUBMTX_IS_REAL(mtxL)
|| ! SUBMTX_IS_REAL(mtxU) ) {
fprintf(stderr, "\n fatal error in Chv_updateN(%p,%p,%p,%p)"
"\n chvT is real, but mtxD, mtxL and/or mtxU are not\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
} else if ( CHV_IS_COMPLEX(chvT) ) {
if ( ! SUBMTX_IS_COMPLEX(mtxD) || ! SUBMTX_IS_COMPLEX(mtxL)
|| ! SUBMTX_IS_COMPLEX(mtxU) ) {
fprintf(stderr, "\n fatal error in Chv_updateN(%p,%p,%p,%p)"
"\n chvT is complex, but mtxD, mtxL and/or mtxU are not\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_updateN(%p,%p,%p,%p)"
"\n bad input, chvT is not real or complex\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
Chv_columnIndices(chvT, &ncolT, &colindT) ;
SubMtx_columnIndices(mtxU, &ncolU, &colindU) ;
/*
-----------------------------
locate first column of U in T
-----------------------------
*/
firstInT = colindT[0] ;
lastInT = colindT[chvT->nD-1] ;
for ( jcolU = 0 ; jcolU < ncolU ; jcolU++ ) {
if ( firstInT <= colindU[jcolU] && colindU[jcolU] <= lastInT ) {
break ;
}
}
if ( (firstInU = jcolU) == ncolU ) {
return ;
}
/*
----------------------------
locate last column of U in T
----------------------------
*/
lastInU = firstInU ;
for ( ; jcolU < ncolU ; jcolU++ ) {
if ( colindU[jcolU] <= lastInT ) {
lastInU = jcolU ;
} else {
break ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n %% firstInU = %d, lastInU = %d",
firstInU, lastInU) ;
fflush(stdout) ;
#endif
/*
----------------------------------------------------------
overwrite supported column indices with indices local to T
----------------------------------------------------------
*/
for ( jcolU = firstInU, jcolT = 0 ; jcolU < ncolU ; jcolU++ ) {
while ( colindU[jcolU] != colindT[jcolT] ) {
jcolT++ ;
}
colindU[jcolU] = jcolT ;
}
if ( CHV_IS_REAL(chvT) ) {
if ( SUBMTX_IS_DENSE_COLUMNS(mtxU) && SUBMTX_IS_DENSE_ROWS(mtxL) ) {
double sums[9] ;
double *base0, *base1, *base2, *colU0, *colU1, *colU2, *entL,
*entU, *Ltemp0, *Ltemp1, *Ltemp2, *rowL0, *rowL1, *rowL2,
*Utemp0, *Utemp1, *Utemp2 ;
int ichv0, ichv1, ichv2, inc1, inc2, irowL, jcolU,
loc, loc0, loc1, loc2, ncolL, nrowL, nrowU, offset ;
SubMtx_denseInfo(mtxL, &nrowL, &ncolL, &inc1, &inc2, &entL) ;
SubMtx_denseInfo(mtxU, &nrowU, &ncolU, &inc1, &inc2, &entU) ;
DV_setSize(tempDV, 6*nrowU) ;
Ltemp0 = DV_entries(tempDV) ;
Ltemp1 = Ltemp0 + nrowU ;
Ltemp2 = Ltemp1 + nrowU ;
Utemp0 = Ltemp2 + nrowU ;
Utemp1 = Utemp0 + nrowU ;
Utemp2 = Utemp1 + nrowU ;
/*
-----------------------------------------------------
loop over the rows of L in groups of three
updating the diagonal and upper blocks of the chevron
-----------------------------------------------------
*/
offset = firstInU*nrowU ;
for ( irowL = firstInU ; irowL <= lastInU - 2 ; irowL += 3 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on rows %d, %d and %d",
colindU[irowL], colindU[irowL+1], colindU[irowL+2]) ;
fflush(stdout) ;
#endif
rowL0 = entL + offset ;
rowL1 = rowL0 + nrowU ;
rowL2 = rowL1 + nrowU ;
colU0 = entU + offset ;
colU1 = colU0 + nrowU ;
colU2 = colU1 + nrowU ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowL] ;
base0 = Chv_diagLocation(chvT, ichv0) ;
ichv1 = colindU[irowL+1] ;
base1 = Chv_diagLocation(chvT, ichv1) ;
ichv2 = colindU[irowL+2] ;
base2 = Chv_diagLocation(chvT, ichv2) ;
/*
-----------------------------------
[ Ltemp0 ] [ rowL0 ]
compute [ Ltemp1 ] = [ rowL1 ] * D
[ Ltemp2 ] [ rowL2 ]
-----------------------------------
*/
DVzero(3*nrowU, Ltemp0) ;
SubMtx_scale3vec(mtxD, Ltemp0, Ltemp1, Ltemp2,
rowL0, rowL1, rowL2) ;
/*
-----------------------------------
[ Utemp0 ] [ colU0 ]
compute [ Utemp1 ] = D * [ colU0 ]
[ Utemp2 ] [ colU0 ]
-----------------------------------
*/
DVzero(3*nrowU, Utemp0) ;
SubMtx_scale3vec(mtxD, Utemp0, Utemp1, Utemp2,
colU0, colU1, colU2) ;
/*
--------------------------------------------------------------
update the 3x3 diagonal block for these three rows and columns
--------------------------------------------------------------
*/
DVdot33(nrowU, Ltemp0, Ltemp1, Ltemp2,
colU0, colU1, colU2, sums) ;
/*
-------------------------------------
inject the nine sums into the chevron
-------------------------------------
*/
base0[0] -= sums[0] ;
loc = ichv1 - ichv0 ;
base0[loc] -= sums[1] ;
base0[-loc] -= sums[3] ;
loc = ichv2 - ichv0 ;
base0[loc] -= sums[2] ;
base0[-loc] -= sums[6] ;
base1[0] -= sums[4] ;
loc = ichv2 - ichv1 ;
base1[loc] -= sums[5] ;
base1[-loc] -= sums[7] ;
base2[0] -= sums[8] ;
/*
------------------------------------------
update the lower and upper blocks together
------------------------------------------
*/
rowL0 = rowL2 + nrowU ;
colU0 = colU2 + nrowU ;
for ( jcolU = irowL + 3 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
rowL1 = rowL0 + nrowU ;
rowL2 = rowL1 + nrowU ;
colU1 = colU0 + nrowU ;
colU2 = colU1 + nrowU ;
/*
------------------------------------------------------
get the local indices for these three rows and columns
------------------------------------------------------
*/
loc0 = colindU[jcolU] ;
loc1 = colindU[jcolU+1] ;
loc2 = colindU[jcolU+2] ;
/*
---------------------
upper 3x3 block first
---------------------
*/
DVdot33(nrowU, Ltemp0, Ltemp1, Ltemp2,
colU0, colU1, colU2, sums) ;
/*
-------------------------------------
inject the nine sums into the chevron
-------------------------------------
*/
base0 -= ichv0 ;
base1 -= ichv1 ;
base2 -= ichv2 ;
base0[loc0] -= sums[0] ;
base0[loc1] -= sums[1] ;
base0[loc2] -= sums[2] ;
base1[loc0] -= sums[3] ;
base1[loc1] -= sums[4] ;
base1[loc2] -= sums[5] ;
base2[loc0] -= sums[6] ;
base2[loc1] -= sums[7] ;
base2[loc2] -= sums[8] ;
base0 += ichv0 ;
base1 += ichv1 ;
base2 += ichv2 ;
/*
----------------------
lower 3x3 block second
----------------------
*/
DVdot33(nrowU, rowL0, rowL1, rowL2,
Utemp0, Utemp1, Utemp2, sums) ;
/*
-------------------------------------
inject the nine sums into the chevron
-------------------------------------
*/
base0 += ichv0 ;
base1 += ichv1 ;
base2 += ichv2 ;
base0[-loc0] -= sums[0] ;
base1[-loc0] -= sums[1] ;
base2[-loc0] -= sums[2] ;
base0[-loc1] -= sums[3] ;
base1[-loc1] -= sums[4] ;
base2[-loc1] -= sums[5] ;
base0[-loc2] -= sums[6] ;
base1[-loc2] -= sums[7] ;
base2[-loc2] -= sums[8] ;
base0 -= ichv0 ;
base1 -= ichv1 ;
base2 -= ichv2 ;
/*
-------------------------------------
increment the row and column pointers
-------------------------------------
*/
rowL0 = rowL2 + nrowU ;
colU0 = colU2 + nrowU ;
}
if ( jcolU == ncolU - 2 ) {
rowL1 = rowL0 + nrowU ;
colU1 = colU0 + nrowU ;
/*
----------------------------------------------------
get the local indices for these two rows and columns
----------------------------------------------------
*/
loc0 = colindU[jcolU] ;
loc1 = colindU[jcolU+1] ;
/*
---------------------
upper 3x2 block first
---------------------
*/
DVdot32(nrowU, Ltemp0, Ltemp1, Ltemp2, colU0, colU1, sums) ;
/*
------------------------------------
inject the six sums into the chevron
------------------------------------
*/
base0 -= ichv0 ;
base1 -= ichv1 ;
base2 -= ichv2 ;
base0[loc0] -= sums[0] ;
base0[loc1] -= sums[1] ;
base1[loc0] -= sums[2] ;
base1[loc1] -= sums[3] ;
base2[loc0] -= sums[4] ;
base2[loc1] -= sums[5] ;
base0 += ichv0 ;
base1 += ichv1 ;
base2 += ichv2 ;
/*
----------------------
lower 2x3 block second
----------------------
*/
DVdot23(nrowU, rowL0, rowL1, Utemp0, Utemp1, Utemp2, sums) ;
/*
------------------------------------
inject the six sums into the chevron
------------------------------------
*/
base0 += ichv0 ;
base1 += ichv1 ;
base2 += ichv2 ;
base0[-loc0] -= sums[0] ;
base1[-loc0] -= sums[1] ;
base2[-loc0] -= sums[2] ;
base0[-loc1] -= sums[3] ;
base1[-loc1] -= sums[4] ;
base2[-loc1] -= sums[5] ;
base0 -= ichv0 ;
base1 -= ichv1 ;
base2 -= ichv2 ;
} else if ( jcolU == ncolU - 1 ) {
/*
---------------------------------------------
get the local indices for this row and column
---------------------------------------------
*/
loc0 = colindU[jcolU] ;
/*
---------------------
upper 3x1 block first
---------------------
*/
DVdot31(nrowU, Ltemp0, Ltemp1, Ltemp2, colU0, sums) ;
/*
--------------------------------------
inject the three sums into the chevron
--------------------------------------
*/
base0 -= ichv0 ;
base1 -= ichv1 ;
base2 -= ichv2 ;
base0[loc0] -= sums[0] ;
base1[loc0] -= sums[1] ;
base2[loc0] -= sums[2] ;
base0 += ichv0 ;
base1 += ichv1 ;
base2 += ichv2 ;
/*
----------------------
lower 1x3 block second
----------------------
*/
DVdot13(nrowU, rowL0, Utemp0, Utemp1, Utemp2, sums) ;
/*
--------------------------------------
inject the three sums into the chevron
--------------------------------------
*/
base0 += ichv0 ;
base1 += ichv1 ;
base2 += ichv2 ;
base0[-loc0] -= sums[0] ;
base1[-loc0] -= sums[1] ;
base2[-loc0] -= sums[2] ;
base0 -= ichv0 ;
base1 -= ichv1 ;
base2 -= ichv2 ;
}
offset += 3*nrowU ;
}
if ( irowL == lastInU - 1 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on rows %d and %d",
colindU[irowL], colindU[irowL+1]) ;
fflush(stdout) ;
#endif
rowL0 = entL + offset ;
rowL1 = rowL0 + nrowU ;
colU0 = entU + offset ;
colU1 = colU0 + nrowU ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowL] ;
base0 = Chv_diagLocation(chvT, ichv0) ;
ichv1 = colindU[irowL+1] ;
base1 = Chv_diagLocation(chvT, ichv1) ;
/*
-----------------------------------
[ Ltemp0 ] [ rowL0 ]
compute [ Ltemp1 ] = [ rowL1 ] * D
-----------------------------------
*/
DVzero(2*nrowU, Ltemp0) ;
SubMtx_scale2vec(mtxD, Ltemp0, Ltemp1, rowL0, rowL1) ;
/*
-----------------------------------
[ Utemp0 ] [ colU0 ]
compute [ Utemp1 ] = D * [ colU0 ]
-----------------------------------
*/
DVzero(2*nrowU, Utemp0) ;
SubMtx_scale2vec(mtxD, Utemp0, Utemp1, colU0, colU1) ;
/*
------------------------------------------------------------
update the 2x2 diagonal block for these two rows and columns
------------------------------------------------------------
*/
DVdot22(nrowU, Ltemp0, Ltemp1, colU0, colU1, sums) ;
/*
-------------------------------------
inject the four sums into the chevron
-------------------------------------
*/
base0[0] -= sums[ 0] ;
loc = ichv1 - ichv0 ;
base0[loc] -= sums[ 1] ;
base0[-loc] -= sums[ 2] ;
base1[0] -= sums[ 3] ;
/*
------------------------------------------
update the lower and upper blocks together
------------------------------------------
*/
rowL0 = rowL1 + nrowU ;
colU0 = colU1 + nrowU ;
for ( jcolU = irowL + 2 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
rowL1 = rowL0 + nrowU ;
rowL2 = rowL1 + nrowU ;
colU1 = colU0 + nrowU ;
colU2 = colU1 + nrowU ;
/*
------------------------------------------------------
get the local indices for these three rows and columns
------------------------------------------------------
*/
loc0 = colindU[jcolU] ;
loc1 = colindU[jcolU+1] ;
loc2 = colindU[jcolU+2] ;
/*
---------------------
upper 2x3 block first
---------------------
*/
DVdot23(nrowU, Ltemp0, Ltemp1, colU0, colU1, colU2, sums) ;
/*
------------------------------------
inject the six sums into the chevron
------------------------------------
*/
base0 -= ichv0 ;
base1 -= ichv1 ;
base0[loc0] -= sums[0] ;
base0[loc1] -= sums[1] ;
base0[loc2] -= sums[2] ;
base1[loc0] -= sums[3] ;
base1[loc1] -= sums[4] ;
base1[loc2] -= sums[5] ;
base0 += ichv0 ;
base1 += ichv1 ;
/*
----------------------
lower 3x2 block second
----------------------
*/
DVdot32(nrowU, rowL0, rowL1, rowL2, Utemp0, Utemp1, sums) ;
/*
------------------------------------
inject the six sums into the chevron
------------------------------------
*/
base0 += ichv0 ;
base1 += ichv1 ;
base0[-loc0] -= sums[0] ;
base1[-loc0] -= sums[1] ;
base0[-loc1] -= sums[2] ;
base1[-loc1] -= sums[3] ;
base0[-loc2] -= sums[4] ;
base1[-loc2] -= sums[5] ;
base0 -= ichv0 ;
base1 -= ichv1 ;
/*
-------------------------------------
increment the row and column pointers
-------------------------------------
*/
rowL0 = rowL2 + nrowU ;
colU0 = colU2 + nrowU ;
}
if ( jcolU == ncolU - 2 ) {
rowL1 = rowL0 + nrowU ;
colU1 = colU0 + nrowU ;
/*
----------------------------------------------------
get the local indices for these two rows and columns
----------------------------------------------------
*/
loc0 = colindU[jcolU] ;
loc1 = colindU[jcolU+1] ;
/*
---------------------
upper 2x2 block first
---------------------
*/
DVdot22(nrowU, Ltemp0, Ltemp1, colU0, colU1, sums) ;
/*
-------------------------------------
inject the four sums into the chevron
-------------------------------------
*/
base0 -= ichv0 ;
base1 -= ichv1 ;
base0[loc0] -= sums[0] ;
base0[loc1] -= sums[1] ;
base1[loc0] -= sums[2] ;
base1[loc1] -= sums[3] ;
base0 += ichv0 ;
base1 += ichv1 ;
/*
----------------------
lower 2x2 block second
----------------------
*/
DVdot22(nrowU, rowL0, rowL1, Utemp0, Utemp1, sums) ;
/*
-------------------------------------
inject the four sums into the chevron
-------------------------------------
*/
base0 += ichv0 ;
base1 += ichv1 ;
base0[-loc0] -= sums[0] ;
base1[-loc0] -= sums[1] ;
base0[-loc1] -= sums[2] ;
base1[-loc1] -= sums[3] ;
base0 -= ichv0 ;
base1 -= ichv1 ;
} else if ( jcolU == ncolU - 1 ) {
/*
---------------------------------------------
get the local indices for this row and column
---------------------------------------------
*/
loc0 = colindU[jcolU] ;
/*
---------------------
upper 2x1 block first
---------------------
*/
DVdot21(nrowU, Ltemp0, Ltemp1, colU0, sums) ;
/*
------------------------------------
inject the two sums into the chevron
------------------------------------
*/
base0 -= ichv0 ;
base1 -= ichv1 ;
base0[loc0] -= sums[0] ;
base1[loc0] -= sums[1] ;
base0 += ichv0 ;
base1 += ichv1 ;
/*
----------------------
lower 1x2 block second
----------------------
*/
DVdot12(nrowU, rowL0, Utemp0, Utemp1, sums) ;
/*
------------------------------------
inject the two sums into the chevron
------------------------------------
*/
base0 += ichv0 ;
base1 += ichv1 ;
base0[-loc0] -= sums[0] ;
base1[-loc0] -= sums[1] ;
base0 -= ichv0 ;
base1 -= ichv1 ;
}
} else if ( irowL == lastInU ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on row %d", colindU[irowL]) ;
fflush(stdout) ;
#endif
rowL0 = entL + offset ;
colU0 = entU + offset ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowL] ;
base0 = Chv_diagLocation(chvT, ichv0) ;
/*
-----------------------------------
compute [ Ltemp0 ] = [ rowL0 ] * D
-----------------------------------
*/
DVzero(nrowU, Ltemp0) ;
SubMtx_scale1vec(mtxD, Ltemp0, rowL0) ;
/*
-----------------------------------
compute [ Utemp0 ] = D * [ colU0 ]
-----------------------------------
*/
DVzero(nrowU, Utemp0) ;
SubMtx_scale1vec(mtxD, Utemp0, colU0) ;
/*
------------------------------------------------------------
update the 1x1 diagonal block for these two rows and columns
------------------------------------------------------------
*/
DVdot11(nrowU, Ltemp0, colU0, sums) ;
/*
-------------------------------
inject the sum into the chevron
-------------------------------
*/
base0[0] -= sums[0] ;
/*
------------------------------------------
update the lower and upper blocks together
------------------------------------------
*/
rowL0 = rowL0 + nrowU ;
colU0 = colU0 + nrowU ;
for ( jcolU = irowL + 1 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
rowL1 = rowL0 + nrowU ;
rowL2 = rowL1 + nrowU ;
colU1 = colU0 + nrowU ;
colU2 = colU1 + nrowU ;
/*
------------------------------------------------------
get the local indices for these three rows and columns
------------------------------------------------------
*/
loc0 = colindU[jcolU] ;
loc1 = colindU[jcolU+1] ;
loc2 = colindU[jcolU+2] ;
/*
---------------------
upper 1x3 block first
---------------------
*/
DVdot13(nrowU, Ltemp0, colU0, colU1, colU2, sums) ;
/*
--------------------------------------
inject the three sums into the chevron
--------------------------------------
*/
base0 -= ichv0 ;
base0[loc0] -= sums[0] ;
base0[loc1] -= sums[1] ;
base0[loc2] -= sums[2] ;
base0 += ichv0 ;
/*
----------------------
lower 3x1 block second
----------------------
*/
DVdot31(nrowU, rowL0, rowL1, rowL2, Utemp0, sums) ;
/*
--------------------------------------
inject the three sums into the chevron
--------------------------------------
*/
base0 += ichv0 ;
base0[-loc0] -= sums[0] ;
base0[-loc1] -= sums[1] ;
base0[-loc2] -= sums[2] ;
base0 -= ichv0 ;
/*
-------------------------------------
increment the row and column pointers
-------------------------------------
*/
rowL0 = rowL2 + nrowU ;
colU0 = colU2 + nrowU ;
}
if ( jcolU == ncolU - 2 ) {
rowL1 = rowL0 + nrowU ;
colU1 = colU0 + nrowU ;
/*
----------------------------------------------------
get the local indices for these two rows and columns
----------------------------------------------------
*/
loc0 = colindU[jcolU] ;
loc1 = colindU[jcolU+1] ;
/*
---------------------
upper 1x2 block first
---------------------
*/
DVdot12(nrowU, Ltemp0, colU0, colU1, sums) ;
/*
------------------------------------
inject the two sums into the chevron
------------------------------------
*/
base0 -= ichv0 ;
base0[loc0] -= sums[0] ;
base0[loc1] -= sums[1] ;
base0 += ichv0 ;
/*
----------------------
lower 2x1 block second
----------------------
*/
DVdot21(nrowU, rowL0, rowL1, Utemp0, sums) ;
/*
------------------------------------
inject the two sums into the chevron
------------------------------------
*/
base0 += ichv0 ;
base0[-loc0] -= sums[0] ;
base0[-loc1] -= sums[1] ;
base0 -= ichv0 ;
} else if ( jcolU == ncolU - 1 ) {
/*
---------------------------------------------
get the local indices for this row and column
---------------------------------------------
*/
loc0 = colindU[jcolU] ;
/*
---------------------
upper 1x1 block first
---------------------
*/
DVdot11(nrowU, Ltemp0, colU0, sums) ;
/*
-------------------------------
inject the sum into the chevron
-------------------------------
*/
base0 -= ichv0 ;
base0[loc0] -= sums[0] ;
base0 += ichv0 ;
/*
----------------------
lower 1x1 block second
----------------------
*/
DVdot11(nrowU, rowL0, Utemp0, sums) ;
/*
-------------------------------
inject the sum into the chevron
-------------------------------
*/
base0 += ichv0 ;
base0[-loc0] -= sums[0] ;
base0 -= ichv0 ;
}
}
} else if ( SUBMTX_IS_SPARSE_COLUMNS(mtxU)
&& SUBMTX_IS_SPARSE_ROWS(mtxL) ) {
double *base, *colU0, *colU1, *entL, *entU, *rowL0, *rowL1,
*temp0, *temp1, *temp2 ;
int ichv, ii, irow0, irow1, jj, loc, ncolL, ncolU, nentL,
nentU, nrowL, nrowU, offsetL, offsetU, sizeL0, sizeL1,
sizeU0, sizeU1 ;
int *indL, *indL0, *indL1, *indU, *indU0, *indU1,
*sizesL, *sizesU ;
SubMtx_sparseColumnsInfo(mtxU,
&ncolU, &nentU, &sizesU, &indU, &entU) ;
SubMtx_sparseRowsInfo(mtxL,
&nrowL, &nentL, &sizesL, &indL, &entL) ;
nrowU = mtxU->nrow ;
ncolL = mtxL->ncol ;
DV_setSize(tempDV, 3*nrowU) ;
temp0 = DV_entries(tempDV) ;
temp1 = temp0 + nrowU ;
temp2 = temp1 + nrowU ;
/*
--------------------------------------------
get the offsets into the indices and entries
--------------------------------------------
*/
for ( jcolU = offsetL = offsetU = 0 ;
jcolU < firstInU ;
jcolU++ ) {
offsetL += sizesL[jcolU] ;
offsetU += sizesU[jcolU] ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% offsetL %d, offsetU %d",
offsetL, offsetU) ;
fflush(stdout) ;
#endif
/*
---------------------------------------------------
loop over the supporting rows of L and columns of U
---------------------------------------------------
*/
for ( irow0 = firstInU ; irow0 <= lastInU ; irow0++ ) {
rowL0 = entL + offsetL ;
indL0 = indL + offsetL ;
colU0 = entU + offsetU ;
indU0 = indU + offsetU ;
sizeL0 = sizesL[irow0] ;
sizeU0 = sizesU[irow0] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% irow0 %d, offsetL %d, offsetU %d, sizeL0 %d, sizeU0 %d",
irow0, offsetL, offsetU, sizeL0, sizeU0) ;
fflush(stdout) ;
#endif
if ( sizeL0 > 0 || sizeU0 > 0 ) {
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv = colindU[irow0] ;
base = Chv_diagLocation(chvT, ichv) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% ichv = %d, base = %p", ichv, base) ;
fflush(stdout) ;
#endif
if ( sizeL0 > 0 ) {
/*
----------------------------------
compute [ temp0 ] = D * [ rowL0 ]
----------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% loading temp1") ;
fflush(stdout) ;
#endif
DVzero(2*nrowU, temp0) ;
for ( ii = 0 ; ii < sizeL0 ; ii++ ) {
jj = indL0[ii] ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% ii = %d, jj = %d", ii, jj) ;
fflush(stdout) ;
#endif
temp1[jj] = rowL0[ii] ;
}
SubMtx_scale1vec(mtxD, temp0, temp1) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% temp0 = L * D") ;
DVfprintf(stdout, 2*nrowU, temp0) ;
fflush(stdout) ;
#endif
}
if ( sizeU0 > 0 ) {
/*
----------------------------------
compute [ temp1 ] = D * [ colU0 ]
----------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% loading temp2") ;
fflush(stdout) ;
#endif
DVzero(2*nrowU, temp1) ;
for ( ii = 0 ; ii < sizeU0 ; ii++ ) {
jj = indU0[ii] ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% ii = %d, jj = %d", ii, jj) ;
fflush(stdout) ;
#endif
temp2[jj] = colU0[ii] ;
}
SubMtx_scale1vec(mtxD, temp1, temp2) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% temp1 = D * U") ;
DVfprintf(stdout, nrowU, temp1) ;
fflush(stdout) ;
#endif
}
if ( sizeL0 > 0 && sizeU0 > 0 ) {
/*
-------------------------
update the diagonal entry
-------------------------
*/
base[0] -= DVdoti(sizeU0, temp0, indU0, colU0) ;
}
/*
----------------------------------------
loop over the following rows and columns
----------------------------------------
*/
if ( sizeU0 > 0 ) {
/*
------------------------
update the lower entries
------------------------
*/
base += ichv ;
rowL1 = rowL0 + sizeL0 ;
indL1 = indL0 + sizeL0 ;
for ( irow1 = irow0 + 1 ; irow1 < ncolU ; irow1++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% irow1 %d, sizeL1 %d",
irow1, sizesL[irow1]) ;
fflush(stdout) ;
#endif
if ( (sizeL1 = sizesL[irow1]) > 0 ) {
loc = colindU[irow1] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% base[%d] = %12.4e, base[%d] = %12.4e",
-loc, base[-loc], -loc + 1, base[-loc+1]) ;
fflush(stdout) ;
#endif
base[-loc] -= DVdoti(sizeL1, temp1, indL1, rowL1) ;
rowL1 += sizeL1 ;
indL1 += sizeL1 ;
}
}
base -= ichv ;
}
if ( sizeL0 > 0 ) {
/*
------------------------
update the upper entries
------------------------
*/
base -= ichv ;
colU1 = colU0 + sizeU0 ;
indU1 = indU0 + sizeU0 ;
for ( irow1 = irow0 + 1 ; irow1 < ncolU ; irow1++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% irow1 %d, sizeU1 %d",
irow1, sizesU[irow1]) ;
fflush(stdout) ;
#endif
if ( (sizeU1 = sizesU[irow1]) > 0 ) {
loc = colindU[irow1] ;
base[loc] -= DVdoti(sizeU1, temp0, indU1, colU1) ;
colU1 += sizeU1 ;
indU1 += sizeU1 ;
}
}
base -= ichv ;
}
}
offsetL += sizeL0 ;
offsetU += sizeU0 ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_updateN(%p,%p,%p,%p)"
"\n bad input, mtxU must have dense or sparse columns"
"\n and mtxL must have dense or sparse rows\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
} else if ( CHV_IS_COMPLEX(chvT) ) {
if ( SUBMTX_IS_DENSE_COLUMNS(mtxU) && SUBMTX_IS_DENSE_ROWS(mtxL) ) {
double sums[18] ;
double *base0, *base1, *base2, *colU0, *colU1, *colU2, *entL,
*entU, *Ltemp0, *Ltemp1, *Ltemp2, *rowL0, *rowL1, *rowL2,
*Utemp0, *Utemp1, *Utemp2 ;
int ichv0, ichv1, ichv2, inc1, inc2, irowL, jcolU,
loc, loc0, loc1, loc2, ncolL, nrowL, nrowU, offset ;
SubMtx_denseInfo(mtxL, &nrowL, &ncolL, &inc1, &inc2, &entL) ;
SubMtx_denseInfo(mtxU, &nrowU, &ncolU, &inc1, &inc2, &entU) ;
DV_setSize(tempDV, 12*nrowU) ;
Ltemp0 = DV_entries(tempDV) ;
Ltemp1 = Ltemp0 + 2*nrowU ;
Ltemp2 = Ltemp1 + 2*nrowU ;
Utemp0 = Ltemp2 + 2*nrowU ;
Utemp1 = Utemp0 + 2*nrowU ;
Utemp2 = Utemp1 + 2*nrowU ;
/*
-----------------------------------------------------
loop over the rows of L in groups of three
updating the diagonal and upper blocks of the chevron
-----------------------------------------------------
*/
offset = firstInU*nrowU ;
for ( irowL = firstInU ; irowL <= lastInU - 2 ; irowL += 3 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on rows %d, %d and %d",
colindU[irowL], colindU[irowL+1], colindU[irowL+2]) ;
fflush(stdout) ;
#endif
rowL0 = entL + 2*offset ;
rowL1 = rowL0 + 2*nrowU ;
rowL2 = rowL1 + 2*nrowU ;
colU0 = entU + 2*offset ;
colU1 = colU0 + 2*nrowU ;
colU2 = colU1 + 2*nrowU ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowL] ;
base0 = Chv_diagLocation(chvT, ichv0) ;
ichv1 = colindU[irowL+1] ;
base1 = Chv_diagLocation(chvT, ichv1) ;
ichv2 = colindU[irowL+2] ;
base2 = Chv_diagLocation(chvT, ichv2) ;
/*
-----------------------------------
[ Ltemp0 ] [ rowL0 ]
compute [ Ltemp1 ] = [ rowL1 ] * D
[ Ltemp2 ] [ rowL2 ]
-----------------------------------
*/
DVzero(6*nrowU, Ltemp0) ;
SubMtx_scale3vec(mtxD, Ltemp0, Ltemp1, Ltemp2,
rowL0, rowL1, rowL2) ;
/*
-----------------------------------
[ Utemp0 ] [ colU0 ]
compute [ Utemp1 ] = D * [ colU0 ]
[ Utemp2 ] [ colU0 ]
-----------------------------------
*/
DVzero(6*nrowU, Utemp0) ;
SubMtx_scale3vec(mtxD, Utemp0, Utemp1, Utemp2,
colU0, colU1, colU2) ;
/*
--------------------------------------------------------------
update the 3x3 diagonal block for these three rows and columns
--------------------------------------------------------------
*/
ZVdotU33(nrowU, Ltemp0, Ltemp1, Ltemp2,
colU0, colU1, colU2, sums) ;
/*
-------------------------------------
inject the nine sums into the chevron
-------------------------------------
*/
base0[0] -= sums[ 0] ; base0[1] -= sums[ 1] ;
loc = 2*(ichv1 - ichv0) ;
base0[loc] -= sums[ 2] ; base0[loc+1] -= sums[ 3] ;
base0[-loc] -= sums[ 6] ; base0[-loc+1] -= sums[ 7] ;
loc = 2*(ichv2 - ichv0) ;
base0[loc] -= sums[ 4] ; base0[loc+1] -= sums[ 5] ;
base0[-loc] -= sums[12] ; base0[-loc+1] -= sums[13] ;
base1[0] -= sums[ 8] ; base1[1] -= sums[ 9] ;
loc = 2*(ichv2 - ichv1) ;
base1[loc] -= sums[10] ; base1[loc+1] -= sums[11] ;
base1[-loc] -= sums[14] ; base1[-loc+1] -= sums[15] ;
base2[0] -= sums[16] ; base2[1] -= sums[17] ;
/*
------------------------------------------
update the lower and upper blocks together
------------------------------------------
*/
rowL0 = rowL2 + 2*nrowU ;
colU0 = colU2 + 2*nrowU ;
for ( jcolU = irowL + 3 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
rowL1 = rowL0 + 2*nrowU ;
rowL2 = rowL1 + 2*nrowU ;
colU1 = colU0 + 2*nrowU ;
colU2 = colU1 + 2*nrowU ;
/*
------------------------------------------------------
get the local indices for these three rows and columns
------------------------------------------------------
*/
loc0 = 2*colindU[jcolU] ;
loc1 = 2*colindU[jcolU+1] ;
loc2 = 2*colindU[jcolU+2] ;
/*
---------------------
upper 3x3 block first
---------------------
*/
ZVdotU33(nrowU, Ltemp0, Ltemp1, Ltemp2,
colU0, colU1, colU2, sums) ;
/*
-------------------------------------
inject the nine sums into the chevron
-------------------------------------
*/
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
base2 -= 2*ichv2 ;
base0[loc0] -= sums[ 0] ; base0[loc0+1] -= sums[ 1] ;
base0[loc1] -= sums[ 2] ; base0[loc1+1] -= sums[ 3] ;
base0[loc2] -= sums[ 4] ; base0[loc2+1] -= sums[ 5] ;
base1[loc0] -= sums[ 6] ; base1[loc0+1] -= sums[ 7] ;
base1[loc1] -= sums[ 8] ; base1[loc1+1] -= sums[ 9] ;
base1[loc2] -= sums[10] ; base1[loc2+1] -= sums[11] ;
base2[loc0] -= sums[12] ; base2[loc0+1] -= sums[13] ;
base2[loc1] -= sums[14] ; base2[loc1+1] -= sums[15] ;
base2[loc2] -= sums[16] ; base2[loc2+1] -= sums[17] ;
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
base2 += 2*ichv2 ;
/*
----------------------
lower 3x3 block second
----------------------
*/
ZVdotU33(nrowU, rowL0, rowL1, rowL2,
Utemp0, Utemp1, Utemp2, sums) ;
/*
-------------------------------------
inject the nine sums into the chevron
-------------------------------------
*/
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
base2 += 2*ichv2 ;
base0[-loc0] -= sums[ 0] ; base0[-loc0+1] -= sums[ 1] ;
base1[-loc0] -= sums[ 2] ; base1[-loc0+1] -= sums[ 3] ;
base2[-loc0] -= sums[ 4] ; base2[-loc0+1] -= sums[ 5] ;
base0[-loc1] -= sums[ 6] ; base0[-loc1+1] -= sums[ 7] ;
base1[-loc1] -= sums[ 8] ; base1[-loc1+1] -= sums[ 9] ;
base2[-loc1] -= sums[10] ; base2[-loc1+1] -= sums[11] ;
base0[-loc2] -= sums[12] ; base0[-loc2+1] -= sums[13] ;
base1[-loc2] -= sums[14] ; base1[-loc2+1] -= sums[15] ;
base2[-loc2] -= sums[16] ; base2[-loc2+1] -= sums[17] ;
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
base2 -= 2*ichv2 ;
/*
-------------------------------------
increment the row and column pointers
-------------------------------------
*/
rowL0 = rowL2 + 2*nrowU ;
colU0 = colU2 + 2*nrowU ;
}
if ( jcolU == ncolU - 2 ) {
rowL1 = rowL0 + 2*nrowU ;
colU1 = colU0 + 2*nrowU ;
/*
----------------------------------------------------
get the local indices for these two rows and columns
----------------------------------------------------
*/
loc0 = 2*colindU[jcolU] ;
loc1 = 2*colindU[jcolU+1] ;
/*
---------------------
upper 3x2 block first
---------------------
*/
ZVdotU32(nrowU, Ltemp0, Ltemp1, Ltemp2,
colU0, colU1, sums) ;
/*
------------------------------------
inject the six sums into the chevron
------------------------------------
*/
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
base2 -= 2*ichv2 ;
base0[loc0] -= sums[ 0] ; base0[loc0+1] -= sums[ 1] ;
base0[loc1] -= sums[ 2] ; base0[loc1+1] -= sums[ 3] ;
base1[loc0] -= sums[ 4] ; base1[loc0+1] -= sums[ 5] ;
base1[loc1] -= sums[ 6] ; base1[loc1+1] -= sums[ 7] ;
base2[loc0] -= sums[ 8] ; base2[loc0+1] -= sums[ 9] ;
base2[loc1] -= sums[10] ; base2[loc1+1] -= sums[11] ;
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
base2 += 2*ichv2 ;
/*
----------------------
lower 2x3 block second
----------------------
*/
ZVdotU23(nrowU, rowL0, rowL1,
Utemp0, Utemp1, Utemp2, sums) ;
/*
------------------------------------
inject the six sums into the chevron
------------------------------------
*/
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
base2 += 2*ichv2 ;
base0[-loc0] -= sums[ 0] ; base0[-loc0+1] -= sums[ 1] ;
base1[-loc0] -= sums[ 2] ; base1[-loc0+1] -= sums[ 3] ;
base2[-loc0] -= sums[ 4] ; base2[-loc0+1] -= sums[ 5] ;
base0[-loc1] -= sums[ 6] ; base0[-loc1+1] -= sums[ 7] ;
base1[-loc1] -= sums[ 8] ; base1[-loc1+1] -= sums[ 9] ;
base2[-loc1] -= sums[10] ; base2[-loc1+1] -= sums[11] ;
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
base2 -= 2*ichv2 ;
} else if ( jcolU == ncolU - 1 ) {
/*
---------------------------------------------
get the local indices for this row and column
---------------------------------------------
*/
loc0 = 2*colindU[jcolU] ;
/*
---------------------
upper 3x1 block first
---------------------
*/
ZVdotU31(nrowU, Ltemp0, Ltemp1, Ltemp2, colU0, sums) ;
/*
--------------------------------------
inject the three sums into the chevron
--------------------------------------
*/
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
base2 -= 2*ichv2 ;
base0[loc0] -= sums[ 0] ; base0[loc0+1] -= sums[ 1] ;
base1[loc0] -= sums[ 2] ; base1[loc0+1] -= sums[ 3] ;
base2[loc0] -= sums[ 4] ; base2[loc0+1] -= sums[ 5] ;
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
base2 += 2*ichv2 ;
/*
----------------------
lower 1x3 block second
----------------------
*/
ZVdotU13(nrowU, rowL0, Utemp0, Utemp1, Utemp2, sums) ;
/*
--------------------------------------
inject the three sums into the chevron
--------------------------------------
*/
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
base2 += 2*ichv2 ;
base0[-loc0] -= sums[ 0] ; base0[-loc0+1] -= sums[ 1] ;
base1[-loc0] -= sums[ 2] ; base1[-loc0+1] -= sums[ 3] ;
base2[-loc0] -= sums[ 4] ; base2[-loc0+1] -= sums[ 5] ;
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
base2 -= 2*ichv2 ;
}
offset += 3*nrowU ;
}
if ( irowL == lastInU - 1 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on rows %d and %d",
colindU[irowL], colindU[irowL+1]) ;
fflush(stdout) ;
#endif
rowL0 = entL + 2*offset ;
rowL1 = rowL0 + 2*nrowU ;
colU0 = entU + 2*offset ;
colU1 = colU0 + 2*nrowU ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowL] ;
base0 = Chv_diagLocation(chvT, ichv0) ;
ichv1 = colindU[irowL+1] ;
base1 = Chv_diagLocation(chvT, ichv1) ;
/*
-----------------------------------
[ Ltemp0 ] [ rowL0 ]
compute [ Ltemp1 ] = [ rowL1 ] * D
-----------------------------------
*/
DVzero(4*nrowU, Ltemp0) ;
SubMtx_scale2vec(mtxD, Ltemp0, Ltemp1, rowL0, rowL1) ;
/*
-----------------------------------
[ Utemp0 ] [ colU0 ]
compute [ Utemp1 ] = D * [ colU0 ]
-----------------------------------
*/
DVzero(4*nrowU, Utemp0) ;
SubMtx_scale2vec(mtxD, Utemp0, Utemp1, colU0, colU1) ;
/*
------------------------------------------------------------
update the 2x2 diagonal block for these two rows and columns
------------------------------------------------------------
*/
ZVdotU22(nrowU, Ltemp0, Ltemp1, colU0, colU1, sums) ;
/*
-------------------------------------
inject the four sums into the chevron
-------------------------------------
*/
base0[0] -= sums[ 0] ; base0[1] -= sums[ 1] ;
loc = 2*(ichv1 - ichv0) ;
base0[loc] -= sums[ 2] ; base0[loc+1] -= sums[ 3] ;
base0[-loc] -= sums[ 4] ; base0[-loc+1] -= sums[ 5] ;
base1[0] -= sums[ 6] ; base1[1] -= sums[ 7] ;
/*
------------------------------------------
update the lower and upper blocks together
------------------------------------------
*/
rowL0 = rowL1 + 2*nrowU ;
colU0 = colU1 + 2*nrowU ;
for ( jcolU = irowL + 2 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
rowL1 = rowL0 + 2*nrowU ;
rowL2 = rowL1 + 2*nrowU ;
colU1 = colU0 + 2*nrowU ;
colU2 = colU1 + 2*nrowU ;
/*
------------------------------------------------------
get the local indices for these three rows and columns
------------------------------------------------------
*/
loc0 = 2*colindU[jcolU] ;
loc1 = 2*colindU[jcolU+1] ;
loc2 = 2*colindU[jcolU+2] ;
/*
---------------------
upper 2x3 block first
---------------------
*/
ZVdotU23(nrowU, Ltemp0, Ltemp1, colU0, colU1, colU2, sums) ;
/*
------------------------------------
inject the six sums into the chevron
------------------------------------
*/
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
base0[loc0] -= sums[ 0] ; base0[loc0+1] -= sums[ 1] ;
base0[loc1] -= sums[ 2] ; base0[loc1+1] -= sums[ 3] ;
base0[loc2] -= sums[ 4] ; base0[loc2+1] -= sums[ 5] ;
base1[loc0] -= sums[ 6] ; base1[loc0+1] -= sums[ 7] ;
base1[loc1] -= sums[ 8] ; base1[loc1+1] -= sums[ 9] ;
base1[loc2] -= sums[10] ; base1[loc2+1] -= sums[11] ;
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
/*
----------------------
lower 3x2 block second
----------------------
*/
ZVdotU32(nrowU, rowL0, rowL1, rowL2, Utemp0, Utemp1, sums) ;
/*
------------------------------------
inject the six sums into the chevron
------------------------------------
*/
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
base0[-loc0] -= sums[ 0] ; base0[-loc0+1] -= sums[ 1] ;
base1[-loc0] -= sums[ 2] ; base1[-loc0+1] -= sums[ 3] ;
base0[-loc1] -= sums[ 4] ; base0[-loc1+1] -= sums[ 5] ;
base1[-loc1] -= sums[ 6] ; base1[-loc1+1] -= sums[ 7] ;
base0[-loc2] -= sums[ 8] ; base0[-loc2+1] -= sums[ 9] ;
base1[-loc2] -= sums[10] ; base1[-loc2+1] -= sums[11] ;
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
/*
-------------------------------------
increment the row and column pointers
-------------------------------------
*/
rowL0 = rowL2 + 2*nrowU ;
colU0 = colU2 + 2*nrowU ;
}
if ( jcolU == ncolU - 2 ) {
rowL1 = rowL0 + 2*nrowU ;
colU1 = colU0 + 2*nrowU ;
/*
----------------------------------------------------
get the local indices for these two rows and columns
----------------------------------------------------
*/
loc0 = 2*colindU[jcolU] ;
loc1 = 2*colindU[jcolU+1] ;
/*
---------------------
upper 2x2 block first
---------------------
*/
ZVdotU22(nrowU, Ltemp0, Ltemp1, colU0, colU1, sums) ;
/*
-------------------------------------
inject the four sums into the chevron
-------------------------------------
*/
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
base0[loc0] -= sums[ 0] ; base0[loc0+1] -= sums[ 1] ;
base0[loc1] -= sums[ 2] ; base0[loc1+1] -= sums[ 3] ;
base1[loc0] -= sums[ 4] ; base1[loc0+1] -= sums[ 5] ;
base1[loc1] -= sums[ 6] ; base1[loc1+1] -= sums[ 7] ;
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
/*
----------------------
lower 2x2 block second
----------------------
*/
ZVdotU22(nrowU, rowL0, rowL1, Utemp0, Utemp1, sums) ;
/*
-------------------------------------
inject the four sums into the chevron
-------------------------------------
*/
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
base0[-loc0] -= sums[ 0] ; base0[-loc0+1] -= sums[ 1] ;
base1[-loc0] -= sums[ 2] ; base1[-loc0+1] -= sums[ 3] ;
base0[-loc1] -= sums[ 4] ; base0[-loc1+1] -= sums[ 5] ;
base1[-loc1] -= sums[ 6] ; base1[-loc1+1] -= sums[ 7] ;
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
} else if ( jcolU == ncolU - 1 ) {
/*
---------------------------------------------
get the local indices for this row and column
---------------------------------------------
*/
loc0 = 2*colindU[jcolU] ;
/*
---------------------
upper 2x1 block first
---------------------
*/
ZVdotU21(nrowU, Ltemp0, Ltemp1, colU0, sums) ;
/*
------------------------------------
inject the two sums into the chevron
------------------------------------
*/
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
base0[loc0] -= sums[ 0] ; base0[loc0+1] -= sums[ 1] ;
base1[loc0] -= sums[ 2] ; base1[loc0+1] -= sums[ 3] ;
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
/*
----------------------
lower 1x2 block second
----------------------
*/
ZVdotU12(nrowU, rowL0, Utemp0, Utemp1, sums) ;
/*
------------------------------------
inject the two sums into the chevron
------------------------------------
*/
base0 += 2*ichv0 ;
base1 += 2*ichv1 ;
base0[-loc0] -= sums[ 0] ; base0[-loc0+1] -= sums[ 1] ;
base1[-loc0] -= sums[ 2] ; base1[-loc0+1] -= sums[ 3] ;
base0 -= 2*ichv0 ;
base1 -= 2*ichv1 ;
}
} else if ( irowL == lastInU ) {
#if MYDEBUG > 0
fprintf(stdout, "\n %% working on row %d", colindU[irowL]) ;
fflush(stdout) ;
#endif
rowL0 = entL + 2*offset ;
colU0 = entU + 2*offset ;
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv0 = colindU[irowL] ;
base0 = Chv_diagLocation(chvT, ichv0) ;
/*
-----------------------------------
compute [ Ltemp0 ] = [ rowL0 ] * D
-----------------------------------
*/
DVzero(2*nrowU, Ltemp0) ;
SubMtx_scale1vec(mtxD, Ltemp0, rowL0) ;
/*
-----------------------------------
compute [ Utemp0 ] = D * [ colU0 ]
-----------------------------------
*/
DVzero(2*nrowU, Utemp0) ;
SubMtx_scale1vec(mtxD, Utemp0, colU0) ;
/*
------------------------------------------------------------
update the 1x1 diagonal block for these two rows and columns
------------------------------------------------------------
*/
ZVdotU11(nrowU, Ltemp0, colU0, sums) ;
/*
-------------------------------
inject the sum into the chevron
-------------------------------
*/
base0[0] -= sums[ 0] ; base0[1] -= sums[ 1] ;
/*
------------------------------------------
update the lower and upper blocks together
------------------------------------------
*/
rowL0 = rowL0 + 2*nrowU ;
colU0 = colU0 + 2*nrowU ;
for ( jcolU = irowL + 1 ; jcolU < ncolU - 2 ; jcolU += 3 ) {
rowL1 = rowL0 + 2*nrowU ;
rowL2 = rowL1 + 2*nrowU ;
colU1 = colU0 + 2*nrowU ;
colU2 = colU1 + 2*nrowU ;
/*
------------------------------------------------------
get the local indices for these three rows and columns
------------------------------------------------------
*/
loc0 = 2*colindU[jcolU] ;
loc1 = 2*colindU[jcolU+1] ;
loc2 = 2*colindU[jcolU+2] ;
/*
---------------------
upper 1x3 block first
---------------------
*/
ZVdotU13(nrowU, Ltemp0, colU0, colU1, colU2, sums) ;
/*
--------------------------------------
inject the three sums into the chevron
--------------------------------------
*/
base0 -= 2*ichv0 ;
base0[loc0] -= sums[ 0] ; base0[loc0+1] -= sums[ 1] ;
base0[loc1] -= sums[ 2] ; base0[loc1+1] -= sums[ 3] ;
base0[loc2] -= sums[ 4] ; base0[loc2+1] -= sums[ 5] ;
base0 += 2*ichv0 ;
/*
----------------------
lower 3x1 block second
----------------------
*/
ZVdotU31(nrowU, rowL0, rowL1, rowL2, Utemp0, sums) ;
/*
--------------------------------------
inject the three sums into the chevron
--------------------------------------
*/
base0 += 2*ichv0 ;
base0[-loc0] -= sums[ 0] ; base0[-loc0+1] -= sums[ 1] ;
base0[-loc1] -= sums[ 2] ; base0[-loc1+1] -= sums[ 3] ;
base0[-loc2] -= sums[ 4] ; base0[-loc2+1] -= sums[ 5] ;
base0 -= 2*ichv0 ;
/*
-------------------------------------
increment the row and column pointers
-------------------------------------
*/
rowL0 = rowL2 + 2*nrowU ;
colU0 = colU2 + 2*nrowU ;
}
if ( jcolU == ncolU - 2 ) {
rowL1 = rowL0 + 2*nrowU ;
colU1 = colU0 + 2*nrowU ;
/*
----------------------------------------------------
get the local indices for these two rows and columns
----------------------------------------------------
*/
loc0 = 2*colindU[jcolU] ;
loc1 = 2*colindU[jcolU+1] ;
/*
---------------------
upper 1x2 block first
---------------------
*/
ZVdotU12(nrowU, Ltemp0, colU0, colU1, sums) ;
/*
------------------------------------
inject the two sums into the chevron
------------------------------------
*/
base0 -= 2*ichv0 ;
base0[loc0] -= sums[ 0] ; base0[loc0+1] -= sums[ 1] ;
base0[loc1] -= sums[ 2] ; base0[loc1+1] -= sums[ 3] ;
base0 += 2*ichv0 ;
/*
----------------------
lower 2x1 block second
----------------------
*/
ZVdotU21(nrowU, rowL0, rowL1, Utemp0, sums) ;
/*
------------------------------------
inject the two sums into the chevron
------------------------------------
*/
base0 += 2*ichv0 ;
base0[-loc0] -= sums[ 0] ; base0[-loc0+1] -= sums[ 1] ;
base0[-loc1] -= sums[ 2] ; base0[-loc1+1] -= sums[ 3] ;
base0 -= 2*ichv0 ;
} else if ( jcolU == ncolU - 1 ) {
/*
---------------------------------------------
get the local indices for this row and column
---------------------------------------------
*/
loc0 = 2*colindU[jcolU] ;
/*
---------------------
upper 1x1 block first
---------------------
*/
ZVdotU11(nrowU, Ltemp0, colU0, sums) ;
/*
-------------------------------
inject the sum into the chevron
-------------------------------
*/
base0 -= 2*ichv0 ;
base0[loc0] -= sums[ 0] ; base0[loc0+1] -= sums[ 1] ;
base0 += 2*ichv0 ;
/*
----------------------
lower 1x1 block second
----------------------
*/
ZVdotU11(nrowU, rowL0, Utemp0, sums) ;
/*
-------------------------------
inject the sum into the chevron
-------------------------------
*/
base0 += 2*ichv0 ;
base0[-loc0] -= sums[ 0] ; base0[-loc0+1] -= sums[ 1] ;
base0 -= 2*ichv0 ;
}
}
} else if ( SUBMTX_IS_SPARSE_COLUMNS(mtxU)
&& SUBMTX_IS_SPARSE_ROWS(mtxL) ) {
double imag, real ;
double *base, *colU0, *colU1, *entL, *entU, *rowL0, *rowL1,
*temp0, *temp1, *temp2 ;
int ichv, ii, irow0, irow1, jj, loc, ncolL, ncolU, nentL,
nentU, nrowL, nrowU, offsetL, offsetU, sizeL0, sizeL1,
sizeU0, sizeU1 ;
int *indL, *indL0, *indL1, *indU, *indU0, *indU1,
*sizesL, *sizesU ;
SubMtx_sparseColumnsInfo(mtxU,
&ncolU, &nentU, &sizesU, &indU, &entU) ;
SubMtx_sparseRowsInfo(mtxL,
&nrowL, &nentL, &sizesL, &indL, &entL) ;
nrowU = mtxU->nrow ;
ncolL = mtxL->ncol ;
DV_setSize(tempDV, 6*nrowU) ;
temp0 = DV_entries(tempDV) ;
temp1 = temp0 + 2*nrowU ;
temp2 = temp1 + 2*nrowU ;
/*
--------------------------------------------
get the offsets into the indices and entries
--------------------------------------------
*/
for ( jcolU = offsetL = offsetU = 0 ;
jcolU < firstInU ;
jcolU++ ) {
offsetL += sizesL[jcolU] ;
offsetU += sizesU[jcolU] ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% offsetL %d, offsetU %d",
offsetL, offsetU) ;
fflush(stdout) ;
#endif
/*
---------------------------------------------------
loop over the supporting rows of L and columns of U
---------------------------------------------------
*/
for ( irow0 = firstInU ; irow0 <= lastInU ; irow0++ ) {
rowL0 = entL + 2*offsetL ;
indL0 = indL + offsetL ;
colU0 = entU + 2*offsetU ;
indU0 = indU + offsetU ;
sizeL0 = sizesL[irow0] ;
sizeU0 = sizesU[irow0] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% irow0 %d, offsetL %d, offsetU %d, sizeL0 %d, sizeU0 %d",
irow0, offsetL, offsetU, sizeL0, sizeU0) ;
fflush(stdout) ;
#endif
if ( sizeL0 > 0 || sizeU0 > 0 ) {
/*
-----------------------------------------------------
get base locations for the chevron's diagonal entries
-----------------------------------------------------
*/
ichv = colindU[irow0] ;
base = Chv_diagLocation(chvT, ichv) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% ichv = %d, base = %p", ichv, base) ;
fflush(stdout) ;
#endif
if ( sizeL0 > 0 ) {
/*
----------------------------------
compute [ temp0 ] = D * [ rowL0 ]
----------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% loading temp1") ;
fflush(stdout) ;
#endif
DVzero(4*nrowU, temp0) ;
for ( ii = 0 ; ii < sizeL0 ; ii++ ) {
jj = indL0[ii] ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% ii = %d, jj = %d", ii, jj) ;
fflush(stdout) ;
#endif
temp1[2*jj] = rowL0[2*ii] ;
temp1[2*jj+1] = rowL0[2*ii+1] ;
#if MYDEBUG > 0
fprintf(stdout, ", (%12.4e,%12.4e)",
rowL0[2*ii], rowL0[2*ii+1]) ;
fflush(stdout) ;
#endif
}
SubMtx_scale1vec(mtxD, temp0, temp1) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% temp0 = L * D") ;
DVfprintf(stdout, 2*nrowU, temp0) ;
fflush(stdout) ;
#endif
}
if ( sizeU0 > 0 ) {
/*
----------------------------------
compute [ temp1 ] = D * [ colU0 ]
----------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% loading temp2") ;
fflush(stdout) ;
#endif
DVzero(4*nrowU, temp1) ;
for ( ii = 0 ; ii < sizeU0 ; ii++ ) {
jj = indU0[ii] ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% ii = %d, jj = %d", ii, jj) ;
fflush(stdout) ;
#endif
temp2[2*jj] = colU0[2*ii] ;
temp2[2*jj+1] = colU0[2*ii+1] ;
#if MYDEBUG > 0
fprintf(stdout, ", (%12.4e,%12.4e)",
colU0[2*ii], colU0[2*ii+1]) ;
fflush(stdout) ;
#endif
}
SubMtx_scale1vec(mtxD, temp1, temp2) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% temp1 = D * U") ;
DVfprintf(stdout, 2*nrowU, temp1) ;
fflush(stdout) ;
#endif
}
if ( sizeL0 > 0 && sizeU0 > 0 ) {
/*
-------------------------
update the diagonal entry
-------------------------
*/
ZVdotiU(sizeU0, temp0, indU0, colU0, &real, &imag) ;
base[0] -= real ; base[1] -= imag ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% sum = %12.4e + %12.4e*i, "
"\n base[%d] = %12.4e, base[%d] = %12.4e ",
real, imag, 0, base[0], 1, base[1]) ;
fflush(stdout) ;
#endif
}
/*
----------------------------------------
loop over the following rows and columns
----------------------------------------
*/
if ( sizeU0 > 0 ) {
/*
------------------------
update the lower entries
------------------------
*/
base += 2*ichv ;
rowL1 = rowL0 + 2*sizeL0 ;
indL1 = indL0 + sizeL0 ;
for ( irow1 = irow0 + 1 ; irow1 < ncolU ; irow1++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% irow1 %d, sizeL1 %d",
irow1, sizesL[irow1]) ;
fflush(stdout) ;
#endif
if ( (sizeL1 = sizesL[irow1]) > 0 ) {
loc = 2*colindU[irow1] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% base[%d] = %12.4e, base[%d] = %12.4e",
-loc, base[-loc], -loc + 1, base[-loc+1]) ;
fflush(stdout) ;
#endif
ZVdotiU(sizeL1, temp1, indL1, rowL1, &real, &imag);
base[-loc] -= real ; base[-loc+1] -= imag ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% sum = %12.4e + %12.4e*i, "
"\n base[%d] = %12.4e, base[%d] = %12.4e ",
real, imag, -loc, base[-loc],
-loc + 1, base[-loc+1]) ;
fflush(stdout) ;
#endif
rowL1 += 2*sizeL1 ;
indL1 += sizeL1 ;
}
}
base -= 2*ichv ;
}
if ( sizeL0 > 0 ) {
/*
------------------------
update the upper entries
------------------------
*/
base -= 2*ichv ;
colU1 = colU0 + 2*sizeU0 ;
indU1 = indU0 + sizeU0 ;
for ( irow1 = irow0 + 1 ; irow1 < ncolU ; irow1++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n\n %% irow1 %d, sizeU1 %d",
irow1, sizesU[irow1]) ;
fflush(stdout) ;
#endif
if ( (sizeU1 = sizesU[irow1]) > 0 ) {
loc = 2*colindU[irow1] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% base[%d] = %12.4e, base[%d] = %12.4e",
loc, base[loc], loc + 1, base[loc+1]) ;
fflush(stdout) ;
#endif
ZVdotiU(sizeU1, temp0, indU1, colU1, &real, &imag);
base[loc] -= real ; base[loc+1] -= imag ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n %% sum = %12.4e + %12.4e*i, "
"\n base[%d] = %12.4e, base[%d] = %12.4e ",
real, imag, loc, base[loc], loc + 1, base[loc+1]) ;
fflush(stdout) ;
#endif
colU1 += 2*sizeU1 ;
indU1 += sizeU1 ;
}
}
base -= ichv ;
}
}
offsetL += sizeL0 ;
offsetU += sizeU0 ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_updateN(%p,%p,%p,%p)"
"\n bad input, mtxU must have dense or sparse columns"
"\n and mtxL must have dense or sparse rows\n",
chvT, mtxD, mtxU, tempDV) ;
exit(-1) ;
}
}
/*
---------------------------------------------------
overwrite the local indices with the global indices
---------------------------------------------------
*/
for ( jcolU = firstInU ; jcolU < ncolU ; jcolU++ ) {
colindU[jcolU] = colindT[colindU[jcolU]] ;
}
return ; }
/*--------------------------------------------------------------------*/
= sums[ 2] ; base0[-loc1+1] -= sums[ 3] ;
base0 -= 2*ichv0 ;
} else if ( jcolU == ncolU - 1 ) {
/*
---------------------------------------------
get the local indices for this row and column
---------------------------------------------
*/
loc0 = 2*colindU[jcolU] ;
/*
---------------------
upper 1x1 block first
---------------------
*/
ZVdotU11(nrowU, Ltemp0, colChv/src/util.c 0100644 0002055 0007177 00000044377 06571267314 0014553 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../Chv.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
shift the indices, entries and adjust the nD dimension.
note: shift can be positive or negative
created -- 98apr30, cca
-------------------------------------------------------
*/
void
Chv_shift (
Chv *chv,
int shift
) {
int ii, stride ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_shift(%p,%d)"
"\n bad input\n", chv, shift) ;
exit(-1) ;
}
if ( shift == 0 ) {
return ;
}
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) ) {
/*
--------------------
chevron is symmetric
--------------------
*/
chv->colind += shift ;
if ( shift < 0 ) {
stride = chv->nD + chv->nU + 1 ;
for ( ii = shift ; ii < 0 ; ii++ ) {
chv->entries -= stride ;
stride++ ;
}
} else {
stride = chv->nD + chv->nU ;
for ( ii = 0 ; ii < shift ; ii++ ) {
chv->entries += stride ;
stride-- ;
}
}
chv->nD -= shift ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
-----------------------
chevron is nonsymmetric
-----------------------
*/
chv->rowind += shift ;
chv->colind += shift ;
if ( shift < 0 ) {
stride = 2*chv->nD + chv->nL + chv->nU + 1 ;
for ( ii = shift ; ii < 0 ; ii++ ) {
chv->entries -= stride ;
stride += 2 ;
}
} else {
stride = 2*chv->nD + chv->nL + chv->nU - 1 ;
for ( ii = 0 ; ii < shift ; ii++ ) {
chv->entries += stride ;
stride -= 2 ;
}
}
chv->nD -= shift ;
} else {
fprintf(stderr, "\n fatal error in Chv_shift(%p,%d)"
"\n type is SPOOLES_REAL, symflag = %d"
"\n must be SPOOLES_SYMMETRIC or SPOOLES_NONSYMMETRIC\n",
chv, shift, chv->symflag) ;
exit(-1) ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
/*
--------------------
chevron is symmetric
--------------------
*/
chv->colind += shift ;
if ( shift < 0 ) {
stride = chv->nD + chv->nU + 1 ;
for ( ii = shift ; ii < 0 ; ii++ ) {
chv->entries -= 2*stride ;
stride++ ;
}
} else {
stride = chv->nD + chv->nU ;
for ( ii = 0 ; ii < shift ; ii++ ) {
chv->entries += 2*stride ;
stride-- ;
}
}
chv->nD -= shift ;
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
-----------------------
chevron is nonsymmetric
-----------------------
*/
chv->rowind += shift ;
chv->colind += shift ;
if ( shift < 0 ) {
stride = 2*chv->nD + chv->nL + chv->nU + 1 ;
for ( ii = shift ; ii < 0 ; ii++ ) {
chv->entries -= 2*stride ;
stride += 2 ;
}
} else {
stride = 2*chv->nD + chv->nL + chv->nU - 1 ;
for ( ii = 0 ; ii < shift ; ii++ ) {
chv->entries += 2*stride ;
stride -= 2 ;
}
}
chv->nD -= shift ;
} else {
fprintf(stderr, "\n fatal error in Chv_shift(%p,%d)"
"\n type is SPOOLES_COMPLEX, symflag = %d"
"\n must be SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN"
"\n or SPOOLES_NONSYMMETRIC\n",
chv, shift, chv->symflag) ;
exit(-1) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------
return the maximum magnitude of the entries in the chevron
created -- 98apr30, cca
----------------------------------------------------------
*/
double
Chv_maxabs (
Chv *chv
) {
double maxabs ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_maxabs(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
maxabs = 0.0 ;
if ( CHV_IS_REAL(chv) ) {
int loc ;
maxabs = DVmaxabs(Chv_nent(chv), Chv_entries(chv), &loc) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
maxabs = ZVmaxabs(Chv_nent(chv), Chv_entries(chv)) ;
} else {
fprintf(stderr, "\n fatal error in Chv_maxabs(%p)"
"\n type is %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, chv->type) ;
exit(-1) ;
}
return(maxabs) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
return the frobenius norm of the entries in the chevron
created -- 98apr30, cca
-------------------------------------------------------
*/
double
Chv_frobNorm (
Chv *chv
) {
double sum ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_frobNorm(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
if ( CHV_IS_REAL(chv) ) {
double value, *entries ;
int ii, nent ;
nent = Chv_nent(chv) ;
entries = Chv_entries(chv) ;
for ( ii = 0, sum = 0.0 ; ii < nent ; ii++ ) {
value = entries[ii] ;
sum += value*value ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
double imag, real, *entries ;
int ii, nent ;
nent = Chv_nent(chv) ;
entries = Chv_entries(chv) ;
for ( ii = 0, sum = 0.0 ; ii < nent ; ii++ ) {
real = entries[2*ii] ;
imag = entries[2*ii+1] ;
sum += real*real + imag*imag ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_frobNorm(%p)"
"\n type is %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, chv->type) ;
exit(-1) ;
}
return(sqrt(sum)) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
subtract chvI from chvJ
created -- 98apr30, cca
-----------------------
*/
void
Chv_sub (
Chv *chvJ,
Chv *chvI
) {
double *entriesI, *entriesJ ;
int ii, nDI, nDJ, nent, nLI, nLJ, nUI, nUJ ;
/*
---------------
check the input
---------------
*/
if ( chvI == NULL || chvJ == NULL ) {
fprintf(stderr, "\n fatal error in Chv_sub(%p,%p)"
"\n bad input\n", chvI, chvJ) ;
exit(-1) ;
}
Chv_dimensions(chvJ, &nDJ, &nLJ, &nUJ) ;
Chv_dimensions(chvI, &nDI, &nLI, &nUI) ;
if ( nDJ != nDI || nLJ != nLI || nUJ != nUI ) {
fprintf(stderr, "\n fatal error in Chv_sub(%p,%p)"
"\n dimensions do not match\n", chvJ, chvI) ;
exit(-1) ;
}
entriesJ = Chv_entries(chvJ) ;
entriesI = Chv_entries(chvI) ;
if ( entriesJ == NULL || entriesI == NULL ) {
fprintf(stderr, "\n fatal error in Chv_sub(%p,%p)"
"\n entriesJ = %p, entriesI = %p\n",
chvJ, chvI, entriesJ, entriesI) ;
exit(-1) ;
}
if ( CHV_IS_REAL(chvJ) && CHV_IS_REAL(chvI) ) {
nent = Chv_nent(chvJ) ;
for ( ii = 0 ; ii < nent ; ii++ ) {
entriesJ[ii] -= entriesI[ii] ;
}
} else if ( CHV_IS_COMPLEX(chvJ) && CHV_IS_COMPLEX(chvI) ) {
nent = Chv_nent(chvJ) ;
for ( ii = 0 ; ii < nent ; ii++ ) {
entriesJ[2*ii] -= entriesI[2*ii] ;
entriesJ[2*ii+1] -= entriesI[2*ii+1] ;
}
} else {
fprintf(stderr, "\n fatal error in Chv_sub(%p,%p)"
"\n typeJ = %d, typeI = %d"
"\n both must be SPOOLES_REAL or SPOOLES_COMPLEX",
chvJ, chvI, chvJ->type, chvI->type) ;
exit(-1) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------
zero the entries in the chevron
created -- 98apr30, cca
-------------------------------
*/
void
Chv_zero (
Chv *chv
) {
/*
---------------
check the input
---------------
*/
if ( chv == NULL ) {
fprintf(stderr, "\n fatal error in Chv_zero(%p)"
"\n bad input\n", chv) ;
exit(-1) ;
}
if ( CHV_IS_REAL(chv) ) {
DVzero(Chv_nent(chv), Chv_entries(chv)) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
ZVzero(Chv_nent(chv), Chv_entries(chv)) ;
} else {
fprintf(stderr, "\n fatal error in Chv_zero(%p)"
"\n type = %d, must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
chv, chv->type) ;
exit(-1) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------
fill A2 object with (1,1) block
created -- 98apr30, cca
-------------------------------
*/
void
Chv_fill11block (
Chv *chv,
A2 *mtx
) {
double *entries ;
int nD, nL, nU ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || mtx == NULL ) {
fprintf(stderr, "\n fatal error in Chv_fill11block(%p,%p)"
"\n bad input\n", chv, mtx) ;
exit(-1) ;
}
if ( ! (CHV_IS_REAL(chv) || CHV_IS_COMPLEX(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_fill11block(%p,%p)"
"\n type = %d, must be real or complex\n",
chv, mtx, chv->type) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
A2_init(mtx, SPOOLES_REAL, nD, nD, 1, nD, NULL) ;
A2_zero(mtx) ;
if ( CHV_IS_SYMMETRIC(chv) ) {
int ii, iioff, ioff, istride, jj ;
/*
----------------
chv is symmetric
----------------
*/
ioff = 0 ;
istride = nD + nU ;
for ( ii = 0 ; ii < nD ; ii++ ) {
A2_setRealEntry(mtx, ii, ii, entries[ioff]) ;
for ( jj = ii + 1, iioff = ioff + 1 ;
jj < nD ;
jj++, iioff++ ) {
A2_setRealEntry(mtx, ii, jj, entries[iioff]) ;
A2_setRealEntry(mtx, jj, ii, 0.0) ;
}
ioff += istride ;
istride-- ;
}
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
int ii, iioff, ioff, istride, jj ;
/*
---------------------
chv is nonsymmetric
---------------------
*/
ioff = nD + nL - 1 ;
istride = 2*nD + nU + nL - 2 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
A2_setRealEntry(mtx, ii, ii, entries[ioff]) ;
for ( jj = ii + 1, iioff = ioff + 1 ;
jj < nD ;
jj++, iioff++ ) {
A2_setRealEntry(mtx, ii, jj, entries[iioff]) ;
}
for ( jj = ii + 1, iioff = ioff - 1 ;
jj < nD ;
jj++, iioff-- ) {
A2_setRealEntry(mtx, jj, ii, entries[iioff]) ;
}
ioff += istride ;
istride -= 2 ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
A2_init(mtx, SPOOLES_COMPLEX, nD, nD, 1, nD, NULL) ;
A2_zero(mtx) ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int ii, iioff, ioff, istride, jj ;
/*
----------------
chv is symmetric
----------------
*/
ioff = 0 ;
istride = nD + nU ;
for ( ii = 0 ; ii < nD ; ii++ ) {
A2_setComplexEntry(mtx, ii, ii,
entries[2*ioff], entries[2*ioff+1]) ;
for ( jj = ii + 1, iioff = ioff + 1 ;
jj < nD ;
jj++, iioff++ ) {
A2_setComplexEntry(mtx, ii, jj,
entries[2*iioff], entries[2*iioff+1]) ;
A2_setComplexEntry(mtx, jj, ii, 0.0, 0.0) ;
}
ioff += istride ;
istride-- ;
}
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
int ii, iioff, ioff, istride, jj ;
/*
---------------------
chv is nonsymmetric
---------------------
*/
ioff = nD + nL - 1 ;
istride = 2*nD + nU + nL - 2 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n ii %d, ioff %d, setting (%d,%d) = (%20.12e,%20.12e)",
ii, ioff, ii, ii, entries[2*ioff], entries[2*ioff+1]) ;
#endif
A2_setComplexEntry(mtx, ii, ii,
entries[2*ioff], entries[2*ioff+1]) ;
for ( jj = ii + 1, iioff = ioff + 1 ;
jj < nD ;
jj++, iioff++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n jj %d, iioff %d, setting (%d,%d) = (%20.12e,%20.12e)",
jj, iioff, ii, ii, entries[2*iioff], entries[2*iioff+1]) ;
#endif
A2_setComplexEntry(mtx, ii, jj,
entries[2*iioff], entries[2*iioff+1]) ;
}
for ( jj = ii + 1, iioff = ioff - 1 ;
jj < nD ;
jj++, iioff-- ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n jj %d, iioff %d, setting (%d,%d) = (%20.12e,%20.12e)",
jj, iioff, ii, ii, entries[2*iioff], entries[2*iioff+1]) ;
#endif
A2_setComplexEntry(mtx, jj, ii,
entries[2*iioff], entries[2*iioff+1]) ;
}
ioff += istride ;
istride -= 2 ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------
fill A2 object with (1,2) block
created -- 98apr30, cca
-------------------------------
*/
void
Chv_fill12block (
Chv *chv,
A2 *mtx
) {
double *entries ;
int nD, nL, nU ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || mtx == NULL ) {
fprintf(stderr, "\n fatal error in Chv_fill12block(%p,%p)"
"\n bad input\n", chv, mtx) ;
exit(-1) ;
}
if ( ! (CHV_IS_REAL(chv) || CHV_IS_COMPLEX(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_fill12block(%p,%p)"
"\n type = %d, must be real or complex\n",
chv, mtx, chv->type) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
/*
---------------------------------
resize the A2 object as necessary
---------------------------------
*/
if ( CHV_IS_REAL(chv) ) {
A2_init(mtx, SPOOLES_REAL, nD, nU, 1, nD, NULL) ;
A2_zero(mtx) ;
if ( CHV_IS_SYMMETRIC(chv) ) {
int ii, iioff, ioff, istride, jj ;
/*
------------------
chv is symmetric
------------------
*/
ioff = 0 ;
istride = nD + nU ;
for ( ii = 0 ; ii < nD ; ii++ ) {
for ( jj = 0, iioff = ioff + nD - ii ;
jj < nU ;
jj++, iioff++ ) {
A2_setRealEntry(mtx, ii, jj, entries[iioff]) ;
}
ioff += istride ;
istride-- ;
}
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
int ii, iioff, ioff, istride, jj ;
/*
---------------------
chv is nonsymmetric
---------------------
*/
ioff = nD + nL - 1 ;
istride = 2*nD + nU + nL - 2 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
for ( jj = 0, iioff = ioff + nD - ii ;
jj < nU ;
jj++, iioff++ ) {
A2_setRealEntry(mtx, ii, jj, entries[iioff]) ;
}
ioff += istride ;
istride -= 2 ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
A2_init(mtx, SPOOLES_COMPLEX, nD, nU, 1, nD, NULL) ;
A2_zero(mtx) ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
int ii, iioff, ioff, istride, jj ;
/*
------------------
chv is symmetric
------------------
*/
ioff = 0 ;
istride = nD + nU ;
for ( ii = 0 ; ii < nD ; ii++ ) {
for ( jj = 0, iioff = ioff + nD - ii ;
jj < nU ;
jj++, iioff++ ) {
A2_setComplexEntry(mtx, ii, jj,
entries[2*iioff], entries[2*iioff+1]) ;
#if MYDEBUG > 0
fprintf(stdout,
"\n 21: ii %d, jj %d, iioff %d, setting (%d,%d) = (%20.12e,%20.12e)",
ii, jj, iioff, ii, ii, entries[2*iioff], entries[2*iioff+1]) ;
#endif
}
ioff += istride ;
istride-- ;
}
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
int ii, iioff, ioff, istride, jj ;
/*
---------------------
chv is nonsymmetric
---------------------
*/
ioff = nD + nL - 1 ;
istride = 2*nD + nU + nL - 2 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
for ( jj = 0, iioff = ioff + nD - ii ;
jj < nU ;
jj++, iioff++ ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n 21: ii %d, jj %d, iioff %d, setting (%d,%d) = (%20.12e,%20.12e)",
ii, jj, iioff, ii, ii, entries[2*iioff], entries[2*iioff+1]) ;
#endif
A2_setComplexEntry(mtx, ii, jj,
entries[2*iioff], entries[2*iioff+1]) ;
}
ioff += istride ;
istride -= 2 ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------
fill A2 object with (2,1) block
created -- 98apr30, cca
-------------------------------
*/
void
Chv_fill21block (
Chv *chv,
A2 *mtx
) {
double *entries ;
int nD, nL, nU ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || mtx == NULL ) {
fprintf(stderr, "\n fatal error in Chv_fillReal21block(%p,%p)"
"\n bad input\n", chv, mtx) ;
exit(-1) ;
}
if ( ! (CHV_IS_REAL(chv) || CHV_IS_COMPLEX(chv)) ) {
fprintf(stderr, "\n fatal error in Chv_fill21block(%p,%p)"
"\n type = %d, must be real or complex\n",
chv, mtx, chv->type) ;
exit(-1) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
int ii, iioff, ioff, istride, jj ;
A2_init(mtx, SPOOLES_REAL, nL, nD, nD, 1, NULL) ;
A2_zero(mtx) ;
ioff = nD + nL - 1 ;
istride = 2*nD + nU + nL - 2 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
for ( jj = 0, iioff = ioff - nD + ii ;
jj < nL ;
jj++, iioff-- ) {
A2_setRealEntry(mtx, jj, ii, entries[iioff]) ;
}
ioff += istride ;
istride -= 2 ;
}
} else if ( CHV_IS_COMPLEX(chv) ) {
int ii, iioff, ioff, istride, jj ;
A2_init(mtx, SPOOLES_COMPLEX, nL, nD, nD, 1, NULL) ;
A2_zero(mtx) ;
ioff = nD + nL - 1 ;
istride = 2*nD + nU + nL - 2 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
for ( jj = 0, iioff = ioff - nD + ii ;
jj < nL ;
jj++, iioff-- ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n 12: ii %d, jj %d, iioff %d, setting (%d,%d) = (%20.12e,%20.12e)",
ii, jj, iioff, ii, ii, entries[2*iioff], entries[2*iioff+1]) ;
#endif
A2_setComplexEntry(mtx, jj, ii,
entries[2*iioff], entries[2*iioff+1]) ;
}
ioff += istride ;
istride -= 2 ;
}
}
return ; }
/*--------------------------------------------------------------------*/
----------------------------
fill A2 object with (1,1) block
created -- 98apr30, cca
-------------------------------
*/
void
Chv_fill11block (
Chv *chv,
A2 *mtx
) {
double *entries ;
int nD, nL, nU ;
/*
---------------
checChv/drivers/do_addChevron 0100755 0002055 0007177 00000000665 06571267317 0017001 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
set msglvl = 2
set msgFile = res
set msgFile = stdout
set type = 2
set symflag = 0
set nD = 9
set nU = 5
set alphareal = 1.0
set alphareal = 9.0
set alphaimag = 0.0
set alphaimag = 4.0
set seed = 7377
test_addChevron \
$msglvl $msgFile $nD $nU $type $symflag $seed $alphareal $alphaimag
Chv/drivers/do_assmbChv 0100755 0002055 0007177 00000000566 06571267320 0016464 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
set msglvl = 2
set msgFile = res
set msgFile = stdout
set type = 2
set symflag = 2
set nDJ = 10
set nUJ = 12
set nDI = 7
set nUI = 8
set seed = 7387788
test_assmbChv \
$msglvl $msgFile $nDJ $nUJ $nDI $nUI $type $symflag $seed
Chv/drivers/do_copyBigEntriesToVector 0100755 0002055 0007177 00000001322 06571267320 0021321 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
# test the ZChv_copyEntriesToVector() method
#
# created -- 98apr22, cca
#
set msglvl = 4
set msgFile = res
set msgFile = stdout
set type = 1
set symflag = 0
set nD = 6
set nU = 5
set pivotingflag = 1
set copyflag = 3
set storeflag = 0
set seed = 1
set droptol = 7.5e-1
foreach type ( 2 )
foreach symflag ( 2 )
foreach pivotingflag ( 1 )
foreach storeflag ( 1 )
test_copyBigEntriesToVector \
$msglvl $msgFile $nD $nU $type $symflag \
$pivotingflag $storeflag $seed $droptol
end
end
end
end
Chv/drivers/do_copyEntriesToVector 0100755 0002055 0007177 00000001252 06571267317 0020707 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
# test the Chv_copyEntriesToVector() method
#
# created -- 98apr22, cca
#
set msglvl = 4
set msgFile = res
set msgFile = stdout
set type = 1
set symflag = 0
set nD = 6
set nU = 5
set pivotingflag = 1
set copyflag = 3
set storeflag = 0
set seed = 1
foreach type ( 2 )
foreach symflag ( 2 )
foreach pivotingflag ( 1 )
foreach storeflag ( 1 )
test_copyEntriesToVector \
$msglvl $msgFile $nD $nU $type $symflag \
$pivotingflag $storeflag $seed
end
end
end
end
Chv/drivers/do_factor 0100755 0002055 0007177 00000001102 06573543520 0016160 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
# test the Chv_factor() method
#
# created -- 98apr22, cca
#
set msglvl = 4
set msgFile = res
set msgFile = stdout
set type = 2
set symflag = 0
set nD = 16
set nU = 15
set pivotingflag = 1
set seed = 188291
set tau = 5
foreach type ( 2 )
foreach symflag ( 2 )
foreach pivotingflag ( 1 )
test_factor \
$msglvl $msgFile $nD $nU $type $symflag \
$pivotingflag $seed $tau
end
end
end
Chv/drivers/do_findPivot 0100755 0002055 0007177 00000000521 06571267320 0016647 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
set msglvl = 1
set msgFile = res
set msgFile = stdout
set type = 2
set symflag = 2
set nD = 6
set nU = 5
set seed = 77787
set tau = 10
test_findPivot \
$msglvl $msgFile $nD $nU $type $symflag $seed $tau
Chv/drivers/do_maxabs 0100755 0002055 0007177 00000000455 06571267317 0016174 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
set msglvl = 1
set msgFile = res
set msgFile = stdout
set type = 2
set symflag = 2
set nD = 6
set nU = 5
set seed = 7777
test_maxabs \
$msglvl $msgFile $nD $nU $type $symflag $seed
Chv/drivers/do_r1upd 0100755 0002055 0007177 00000000532 06571267317 0015750 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
# test the ZChv_r1upd() method
#
# created -- 98apr22, cca
#
set msglvl = 4
set msgFile = res
set msgFile = stdout
set type = 2
set symflag = 2
set nD = 6
set nU = 5
set seed = 1821
foreach symflag ( 0 )
test_r1upd $msglvl $msgFile $nD $nU $type $symflag $seed
end
Chv/drivers/do_r2upd 0100755 0002055 0007177 00000000531 06571267317 0015750 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
# test the ZChv_r2upd() method
#
# created -- 98apr22, cca
#
set msglvl = 4
set msgFile = res
set msgFile = stdout
set type = 1
set symflag = 0
set nD = 6
set nU = 5
set seed = 18291
foreach symflag ( 0 )
test_r2upd $msglvl $msgFile $nD $nU $type $symflag $seed
end
Chv/drivers/do_swap 0100755 0002055 0007177 00000000453 06571267317 0015671 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
set msglvl = 1
set msgFile = res
set msgFile = stdout
set type = 2
set symflag = 1
set nD = 6
set nU = 5
set seed = 7777
test_swap \
$msglvl $msgFile $nD $nU $type $symflag $seed
Chv/drivers/do_update 0100755 0002055 0007177 00000001422 06571267317 0016176 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
#
set msglvl = 2
set msgFile = res
set msgFile = stdout
set type = 1
set symflag = 0
set sparsityflag = 1
set ncolT = 14
set nDT = 5
set ncolU = $ncolT
set ncolU = 18
set nrowD = 10
set nentU = 55
set offset = 4
set seed = 66666
# nDT = 5, 6, 7
set nDT = 7
# ncolT = 12, 13, 14
set ncolT = 14
set offset = 4
set nrowD = 10
@ ncolU = $ncolT + $offset
foreach type ( 2 )
foreach symflag ( 2 )
foreach sparsityflag ( 1 )
test_update \
$msglvl $msgFile $type $symflag $sparsityflag \
$ncolT $nDT $ncolU $nrowD $nentU $offset $seed
end
end
end
Chv/drivers/makefile 0100644 0002055 0007177 00000003250 06653142377 0016004 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = test_addChevron \
test_assmbChv \
test_copyEntriesToVector\
test_copyBigEntriesToVector\
test_factor \
test_findPivot \
test_maxabs \
test_swap \
test_r1upd \
test_r2upd \
test_update
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
test_assmbChv : test_assmbChv.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_factor : test_factor.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_findPivot : test_findPivot.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_maxabs : test_maxabs.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_r2upd : test_r2upd.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_r1upd : test_r1upd.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_addChevron : test_addChevron.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_copyBigEntriesToVector : test_copyBigEntriesToVector.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_copyEntriesToVector : test_copyEntriesToVector.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_swap : test_swap.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
test_update : test_update.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ ${PURIFY_GCC_VERSION} ${LIBS}
Chv/drivers/test_addChevron.c 0100644 0002055 0007177 00000021755 06571267317 0017577 0 ustar 00cleve compmath 0000040 0000006 /* test_addChevron.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------
test the Chv_addChevron() method.
created -- 98apr18, cca
---------------------------------------
*/
{
Chv *chv ;
double alpha[2] ;
double imag, real, t1, t2 ;
double *chvent, *entries ;
Drand *drand ;
FILE *msgFile ;
int chvsize, count, ichv, ierr, ii, iloc, irow, jcol,
lastcol, msglvl, ncol, nD, nent, nL, nrow, nU,
off, seed, symflag, type, upper ;
int *chvind, *colind, *keys, *rowind, *temp ;
if ( argc != 10 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nD nU type symflag seed "
"\n alphareal alphaimag"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nD -- # of rows and columns in the (1,1) block"
"\n nU -- # of columns in the (1,2) block"
"\n type -- entries type"
"\n 1 --> real"
"\n 2 --> complex"
"\n symflag -- symmetry flag"
"\n 0 --> symmetric"
"\n 1 --> hermitian"
"\n 2 --> nonsymmetric"
"\n seed -- random number seed"
"\n alpha -- scaling parameter"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
nD = atoi(argv[3]) ;
nU = atoi(argv[4]) ;
type = atoi(argv[5]) ;
symflag = atoi(argv[6]) ;
seed = atoi(argv[7]) ;
alpha[0] = atof(argv[8]) ;
alpha[1] = atof(argv[9]) ;
if ( nD <= 0 || nU < 0 || symflag < 0 || symflag > 2 ) {
fprintf(stderr, "\n invalid input"
"\n nD = %d, nU = %d, symflag = %d\n", nD, nU, symflag) ;
exit(-1) ;
}
fprintf(msgFile, "\n alpha = %12.4e + %12.4e*i ;", alpha[0], alpha[1]) ;
nL = nU ;
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setSeed(drand, seed) ;
Drand_setUniform(drand, -1.0, 1.0) ;
/*
----------------------------
initialize the Chv object
----------------------------
*/
MARKTIME(t1) ;
chv = Chv_new() ;
Chv_init(chv, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize chv object",
t2 - t1) ;
fflush(msgFile) ;
Chv_columnIndices(chv, &ncol, &colind) ;
temp = IVinit(2*(nD+nU), -1) ;
IVramp(2*(nD+nU), temp, 0, 1) ;
IVshuffle(2*(nD+nU), temp, ++seed) ;
IVcopy(ncol, colind, temp) ;
IVqsortUp(ncol, colind) ;
if ( CHV_IS_NONSYMMETRIC(chv) ) {
Chv_rowIndices(chv, &nrow, &rowind) ;
IVcopy(nrow, rowind, colind) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% column indices") ;
IVfprintf(msgFile, ncol, colind) ;
}
lastcol = colind[ncol-1] ;
nent = Chv_nent(chv) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
Drand_fillDvector(drand, nent, entries) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
Drand_fillDvector(drand, 2*nent, entries) ;
}
if ( CHV_IS_HERMITIAN(chv) ) {
/*
---------------------------------------------------------
hermitian example, set imaginary part of diagonal to zero
---------------------------------------------------------
*/
for ( irow = 0 ; irow < nD ; irow++ ) {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
Chv_setComplexEntry(chv, irow, irow, real, 0.0) ;
}
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n a = zeros(%d,%d) ;", lastcol+1, lastcol+1) ;
Chv_writeForMatlab(chv, "a", msgFile) ;
}
/*
--------------------------------------------------
fill a chevron with random numbers and indices
that are a subset of a front's, as in the assembly
of original matrix entries.
--------------------------------------------------
*/
Drand_setUniform(drand, 0, nD) ;
iloc = (int) Drand_value(drand) ;
ichv = colind[iloc] ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
upper = nD - iloc + nU ;
} else {
upper = 2*(nD - iloc) - 1 + nL + nU ;
}
Drand_setUniform(drand, 1, upper) ;
chvsize = (int) Drand_value(drand) ;
fprintf(msgFile, "\n %% iloc = %d, ichv = %d, chvsize = %d",
iloc, ichv, chvsize) ;
chvind = IVinit(chvsize, -1) ;
chvent = DVinit(2*chvsize, 0.0) ;
Drand_setNormal(drand, 0.0, 1.0) ;
if ( CHV_IS_REAL(chv) ) {
Drand_fillDvector(drand, chvsize, chvent) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
Drand_fillDvector(drand, 2*chvsize, chvent) ;
}
keys = IVinit(upper+1, -1) ;
keys[0] = 0 ;
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
for ( ii = iloc + 1, count = 1 ; ii < nD + nU ; ii++ ) {
keys[count++] = colind[ii] - ichv ;
}
} else {
for ( ii = iloc + 1, count = 1 ; ii < nD + nU ; ii++ ) {
keys[count++] = colind[ii] - ichv ;
keys[count++] = - colind[ii] + ichv ;
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% iloc = %d, ichv = %d", iloc, ichv) ;
fprintf(msgFile, "\n %% upper = %d", upper) ;
fprintf(msgFile, "\n %% chvsize = %d", chvsize) ;
fprintf(msgFile, "\n %% initial keys") ;
IVfprintf(msgFile, count, keys) ;
}
IVshuffle(count, keys, ++seed) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% shuffled keys") ;
IVfp80(msgFile, count, keys, 80, &ierr) ;
}
IVcopy(chvsize, chvind, keys) ;
if ( CHV_IS_REAL(chv) ) {
IVDVqsortUp(chvsize, chvind, chvent) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
IVZVqsortUp(chvsize, chvind, chvent) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% chvind") ;
IVfprintf(msgFile, chvsize, chvind) ;
}
if ( CHV_IS_HERMITIAN(chv) ) {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
if ( chvind[ii] == 0 ) {
chvent[2*ii+1] = 0.0 ;
}
}
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n b = zeros(%d,%d) ;", lastcol+1, lastcol+1) ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) ) {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
off = chvind[ii] ;
fprintf(msgFile, "\n b(%d,%d) = %20.12e ;",
colind[iloc]+1, colind[iloc]+off+1, chvent[ii]) ;
fprintf(msgFile, "\n b(%d,%d) = %20.12e ;",
colind[iloc]+off+1, colind[iloc]+1, chvent[ii]) ;
}
} else {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
off = chvind[ii] ;
if ( off > 0 ) {
fprintf(msgFile, "\n b(%d,%d) = %20.12e ;",
colind[iloc]+1, colind[iloc]+off+1, chvent[ii]) ;
} else {
fprintf(msgFile, "\n b(%d,%d) = %20.12e ;",
colind[iloc]-off+1, colind[iloc]+1, chvent[ii]) ;
}
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
off = chvind[ii] ;
fprintf(msgFile, "\n b(%d,%d) = %20.12e + %20.12e*i;",
colind[iloc]+1, colind[iloc]+off+1,
chvent[2*ii], chvent[2*ii+1]) ;
if ( CHV_IS_HERMITIAN(chv) ) {
fprintf(msgFile, "\n b(%d,%d) = %20.12e + %20.12e*i;",
colind[iloc]+off+1, colind[iloc]+1,
chvent[2*ii], -chvent[2*ii+1]) ;
} else {
fprintf(msgFile, "\n b(%d,%d) = %20.12e + %20.12e*i;",
colind[iloc]+off+1, colind[iloc]+1,
chvent[2*ii], chvent[2*ii+1]) ;
}
}
} else {
for ( ii = 0 ; ii < chvsize ; ii++ ) {
off = chvind[ii] ;
if ( off > 0 ) {
fprintf(msgFile, "\n b(%d,%d) = %20.12e + %20.12e*i;",
colind[iloc]+1, colind[iloc]+off+1,
chvent[2*ii], chvent[2*ii+1]) ;
} else {
fprintf(msgFile, "\n b(%d,%d) = %20.12e + %20.12e*i;",
colind[iloc]-off+1, colind[iloc]+1,
chvent[2*ii], chvent[2*ii+1]) ;
}
}
}
}
}
/*
------------------------------------
add the chevron into the Chv object
------------------------------------
*/
Chv_addChevron(chv, alpha, ichv, chvsize, chvind, chvent) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n %% after adding the chevron") ;
fprintf(msgFile, "\n c = zeros(%d,%d) ;", lastcol+1, lastcol+1) ;
Chv_writeForMatlab(chv, "c", msgFile) ;
}
/*
-----------------
compute the error
-----------------
*/
fprintf(msgFile, "\n max(max(abs(c - (a + alpha*b))))") ;
/*
------------------------
free the working storage
------------------------
*/
Chv_free(chv) ;
Drand_free(drand) ;
IVfree(temp) ;
IVfree(chvind) ;
DVfree(chvent) ;
IVfree(keys) ;
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
Chv/drivers/test_assmbChv.c 0100644 0002055 0007177 00000014153 06571267320 0017254 0 ustar 00cleve compmath 0000040 0000006 /* test_assmbChv.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
------------------------------------
test the Chv_assembleChv() method.
created -- 98apr18, cca
------------------------------------
*/
{
Chv *chvI, *chvJ ;
double imag, real, t1, t2 ;
double *entriesI, *entriesJ ;
Drand *drand ;
FILE *msgFile ;
int ierr, ii, irow, jcol,
lastcol, msglvl, ncolI, ncolJ, nDI, nDJ, nentI, nentJ,
nrowI, nrowJ, nUI, nUJ, seed, symflag, type ;
int *colindI, *colindJ, *rowindI, *rowindJ, *temp ;
if ( argc != 10 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nDJ nUJ nDI nUI type symflag seed "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nDJ -- # of rows and columns in the (1,1) block"
"\n nUJ -- # of columns in the (1,2) block"
"\n nDI -- # of rows and columns in the (1,1) block"
"\n nUI -- # of columns in the (1,2) block"
"\n type -- entries type"
"\n 1 --> real"
"\n 2 --> complex"
"\n symflag -- symmetry flag"
"\n 0 --> symmetric"
"\n 1 --> hermitian"
"\n 2 --> nonsymmetric"
"\n seed -- random number seed"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
nDJ = atoi(argv[3]) ;
nUJ = atoi(argv[4]) ;
nDI = atoi(argv[5]) ;
nUI = atoi(argv[6]) ;
type = atoi(argv[7]) ;
symflag = atoi(argv[8]) ;
seed = atoi(argv[9]) ;
if ( nDJ <= 0 || nUJ < 0
|| nDI <= 0 || nUI < 0
|| nDI >= nDJ || (nDI + nUI) >= (nDJ + nUJ)
|| nUI >= (nDJ + nUJ - nDI)
|| ( symflag != SPOOLES_SYMMETRIC
&& symflag != SPOOLES_HERMITIAN
&& symflag != SPOOLES_NONSYMMETRIC) ) {
fprintf(stderr, "\n invalid input"
"\n nDJ = %d, nUJ = %d, nDI = %d, nUI = %d, symflag = %d\n",
nDJ, nUJ, nDI, nUI, symflag) ;
exit(-1) ;
}
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setSeed(drand, seed) ;
Drand_setUniform(drand, -1.0, 1.0) ;
/*
----------------------------
initialize the ChvJ object
----------------------------
*/
MARKTIME(t1) ;
chvJ = Chv_new() ;
Chv_init(chvJ, 0, nDJ, nUJ, nUJ, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize chv object",
t2 - t1) ;
fflush(msgFile) ;
Chv_columnIndices(chvJ, &ncolJ, &colindJ) ;
temp = IVinit(2*(nDJ+nUJ), -1) ;
IVramp(2*(nDJ+nUJ), temp, 0, 1) ;
IVshuffle(2*(nDJ+nUJ), temp, ++seed) ;
IVcopy(ncolJ, colindJ, temp) ;
IVfree(temp) ;
IVqsortUp(ncolJ, colindJ) ;
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
Chv_rowIndices(chvJ, &nrowJ, &rowindJ) ;
IVcopy(nrowJ, rowindJ, colindJ) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %% column indices") ;
IVfprintf(msgFile, ncolJ, colindJ) ;
}
lastcol = colindJ[ncolJ-1] ;
nentJ = Chv_nent(chvJ) ;
entriesJ = Chv_entries(chvJ) ;
if ( CHV_IS_REAL(chvJ) ) {
Drand_fillDvector(drand, nentJ, entriesJ) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
Drand_fillDvector(drand, 2*nentJ, entriesJ) ;
}
if ( CHV_IS_HERMITIAN(chvJ) ) {
/*
---------------------------------------------------------
hermitian example, set imaginary part of diagonal to zero
---------------------------------------------------------
*/
for ( irow = 0 ; irow < nDJ ; irow++ ) {
Chv_complexEntry(chvJ, irow, irow, &real, &imag) ;
Chv_setComplexEntry(chvJ, irow, irow, real, 0.0) ;
}
}
/*
---------------------------
initialize the ChvI object
---------------------------
*/
chvI = Chv_new() ;
Chv_init(chvI, 0, nDI, nUI, nUI, type, symflag) ;
Chv_columnIndices(chvI, &ncolI, &colindI) ;
temp = IVinit(ncolJ, -1) ;
IVramp(ncolJ, temp, 0, 1) ;
while ( 1 ) {
IVshuffle(ncolJ, temp, ++seed) ;
IVqsortUp(ncolI, temp) ;
if ( temp[0] < nDJ ) {
break ;
}
}
for ( ii = 0 ; ii < ncolI ; ii++ ) {
colindI[ii] = colindJ[temp[ii]] ;
}
IVfree(temp) ;
if ( CHV_IS_NONSYMMETRIC(chvI) ) {
Chv_rowIndices(chvI, &nrowI, &rowindI) ;
IVcopy(nrowI, rowindI, colindI) ;
}
nentI = Chv_nent(chvI) ;
entriesI = Chv_entries(chvI) ;
if ( CHV_IS_REAL(chvI) ) {
Drand_fillDvector(drand, nentI, entriesI) ;
} else if ( CHV_IS_COMPLEX(chvI) ) {
Drand_fillDvector(drand, 2*nentI, entriesI) ;
}
if ( CHV_IS_HERMITIAN(chvI) ) {
/*
---------------------------------------------------------
hermitian example, set imaginary part of diagonal to zero
---------------------------------------------------------
*/
for ( irow = 0 ; irow < nDI ; irow++ ) {
Chv_complexEntry(chvI, irow, irow, &real, &imag) ;
Chv_setComplexEntry(chvI, irow, irow, real, 0.0) ;
}
}
/*
--------------------------------------------------
write out the two chevron objects to a matlab file
--------------------------------------------------
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n a = zeros(%d,%d) ;", lastcol+1, lastcol+1) ;
Chv_writeForMatlab(chvJ, "a", msgFile) ;
fprintf(msgFile, "\n b = zeros(%d,%d) ;", lastcol+1, lastcol+1) ;
Chv_writeForMatlab(chvI, "b", msgFile) ;
}
/*
---------------------------------------------
assemble the chvI object into the chvJ object
---------------------------------------------
*/
Chv_assembleChv(chvJ, chvI) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n %% after assembly") ;
fprintf(msgFile, "\n c = zeros(%d,%d) ;", lastcol+1, lastcol+1) ;
Chv_writeForMatlab(chvJ, "c", msgFile) ;
}
/*
-----------------
compute the error
-----------------
*/
fprintf(msgFile, "\n max(max(abs(c - (b + a))))") ;
/*
------------------------
free the working storage
------------------------
*/
Chv_free(chvJ) ;
Chv_free(chvI) ;
Drand_free(drand) ;
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
nUJ, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize chv object",
t2 - t1) ;
fflush(msgFile) ;
Chv_columnIndices(chvJ, &ncolJ, &colindJ) ;
temp = IVinit(2*(nDJ+nUJ), -1) ;
IVramp(2*(nDJ+nUJ), temp, 0, 1) ;
IVshuffle(2*(nDJ+nUJ), temp, ++seed) ;
IVcopy(ncolJ, colindJ, temp) ;
IVfree(temp) ;
IVqsortUp(ncolJ, colindJ) ;
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
Chv_roChv/drivers/test_copyBigEntriesToVector.c 0100644 0002055 0007177 00000054150 06571267320 0022123 0 ustar 00cleve compmath 0000040 0000006 /* test_copyBigEntriesToVector.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------
test the copyBigEntriesToVector routine
created -- 98apr18, cca,
---------------------------------------
*/
{
Chv *chvJ, *chvI ;
double droptol, imag, real, t1, t2 ;
double *dvec, *entries ;
Drand *drand ;
FILE *msgFile ;
int count, first, ierr, ii, iilast, ipivot, irow, jcol, jj,
jjlast, maxnent, mm, msglvl, ncol, nD, nent, nentD, nentL,
nentL11, nentL21, nentU, nentU11, nentU12, nL, npivot, nrow,
nU, pivotingflag, seed, storeflag, symflag, total, type ;
int *colind, *ivec, *pivotsizes, *rowind, *sizes ;
if ( argc != 11 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nD nU type symflag "
"\n pivotingflag storeflag seed droptol"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nD -- # of rows and columns in the (1,1) block"
"\n nU -- # of columns in the (1,2) block"
"\n type -- entries type"
"\n 1 --> real"
"\n 2 --> complex"
"\n symflag -- symmetry flag"
"\n 0 --> symmetric"
"\n 1 --> nonsymmetric"
"\n pivotingflag -- pivoting flag"
"\n if symflag = 1 and pivotingflag = 1 then"
"\n construct pivotsizes[] vector"
"\n endif"
"\n storeflag -- flag to denote how to store entries"
"\n 0 --> store by rows"
"\n 1 --> store by columns"
"\n seed -- random number seed"
"\n droptol -- entries whose magnitude >= droptol are copied"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
nD = atoi(argv[3]) ;
nU = atoi(argv[4]) ;
type = atoi(argv[5]) ;
symflag = atoi(argv[6]) ;
pivotingflag = atoi(argv[7]) ;
storeflag = atoi(argv[8]) ;
seed = atoi(argv[9]) ;
droptol = atof(argv[10]) ;
if ( msglvl > 0 ) {
switch ( storeflag ) {
case 0 : fprintf(msgFile, "\n\n %% STORE BY ROWS") ; break ;
case 1 : fprintf(msgFile, "\n\n %% STORE BY COLUMNS") ; break ;
default :
fprintf(stderr, "\n bad value %d for storeflag", storeflag) ;
break ;
}
}
nL = nU ;
if ( symflag == SPOOLES_NONSYMMETRIC ) {
pivotingflag = 0 ;
}
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setNormal(drand, 0.0, 1.0) ;
Drand_setSeed(drand, seed) ;
/*
--------------------------
initialize the chvJ object
--------------------------
*/
MARKTIME(t1) ;
chvJ = Chv_new() ;
Chv_init(chvJ, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize matrix objects",
t2 - t1) ;
nent = Chv_nent(chvJ) ;
entries = Chv_entries(chvJ) ;
if ( CHV_IS_REAL(chvJ) ) {
Drand_fillDvector(drand, nent, entries) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
Drand_fillDvector(drand, 2*nent, entries) ;
}
Chv_columnIndices(chvJ, &ncol, &colind) ;
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
Chv_rowIndices(chvJ, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% chevron a") ;
Chv_writeForMatlab(chvJ, "a", msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------
initialize the chvI object
--------------------------
*/
MARKTIME(t1) ;
chvI = Chv_new() ;
Chv_init(chvI, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize matrix objects",
t2 - t1) ;
Chv_zero(chvI) ;
Chv_columnIndices(chvI, &ncol, &colind) ;
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chvI) ) {
Chv_rowIndices(chvI, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
if ( symflag == 0 && pivotingflag == 1 ) {
/*
------------------------------
create the pivotsizes[] vector
------------------------------
*/
Drand_setUniform(drand, 1, 2.999) ;
pivotsizes = IVinit(nD, 0) ;
Drand_fillIvector(drand, nD, pivotsizes) ;
/*
fprintf(msgFile, "\n initial pivotsizes[] : ") ;
IVfp80(msgFile, nD, pivotsizes, 80, &ierr) ;
*/
for ( npivot = count = 0 ; npivot < nD ; npivot++ ) {
count += pivotsizes[npivot] ;
if ( count > nD ) {
pivotsizes[npivot]-- ;
count-- ;
}
if ( count == nD ) {
break ;
}
}
npivot++ ;
/*
fprintf(msgFile, "\n final pivotsizes[] : ") ;
IVfp80(msgFile, npivot, pivotsizes, 80, &ierr) ;
*/
} else {
npivot = 0 ;
pivotsizes = NULL ;
}
/*
--------------------------------------------------
first test: copy lower, diagonal and upper entries
--------------------------------------------------
*/
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
nentL = Chv_countBigEntries(chvJ, npivot, pivotsizes,
CHV_STRICT_LOWER, droptol) ;
} else {
nentL = 0 ;
}
nentD = Chv_countEntries(chvJ, npivot, pivotsizes, CHV_DIAGONAL) ;
nentU = Chv_countBigEntries(chvJ, npivot, pivotsizes,
CHV_STRICT_UPPER, droptol) ;
maxnent = nentL ;
if ( maxnent < nentD ) { maxnent = nentD ; }
if ( maxnent < nentU ) { maxnent = nentU ; }
fprintf(msgFile, "\n %% nentL = %d, nentD = %d, nentU = %d",
nentL, nentD, nentU) ;
sizes = IVinit(ncol, 0) ;
ivec = IVinit(maxnent, 0) ;
if ( CHV_IS_REAL(chvJ) ) {
dvec = DVinit(maxnent, 0.0) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
dvec = DVinit(2*maxnent, 0.0) ;
}
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
/*
--------------------------------------
copy the entries in the lower triangle,
then move into the chvI object
--------------------------------------
*/
nent = Chv_copyBigEntriesToVector(chvJ, npivot, pivotsizes, sizes,
ivec, dvec, CHV_STRICT_LOWER,
storeflag, droptol) ;
if ( nent != nentL ) {
fprintf(stderr, "\n error: nentL = %d, nent = %d", nentL, nent) ;
exit(-1) ;
}
if ( storeflag == 0 ) {
for ( irow = 0, mm = 0 ; irow < nrow ; irow++ ) {
if ( sizes[irow] > 0 ) {
for ( jj = 0 ; jj < sizes[irow] ; jj++, mm++ ) {
jcol = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
} else {
for ( jcol = 0, mm = 0 ; jcol < nD ; jcol++ ) {
if ( sizes[jcol] > 0 ) {
for ( ii = 0 ; ii < sizes[jcol] ; ii++, mm++ ) {
irow = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
}
}
/*
---------------------------------------
copy the entries in the diagonal matrix
then move into the chvI object
---------------------------------------
*/
nent = Chv_copyEntriesToVector(chvJ, npivot, pivotsizes, maxnent,
dvec, CHV_DIAGONAL, storeflag) ;
if ( nent != nentD ) {
fprintf(stderr, "\n error: nentD = %d, nent = %d", nentD, nent) ;
exit(-1) ;
}
if ( pivotsizes == NULL ) {
for ( jcol = 0, mm = 0 ; jcol < nD ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, jcol, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, jcol, jcol, real, imag) ;
}
}
} else {
for ( ipivot = irow = mm = 0 ; ipivot < npivot ; ipivot++ ) {
if ( pivotsizes[ipivot] == 1 ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow, real, imag) ;
}
mm++ ; irow++ ;
} else {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow, real) ;
mm++ ;
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow+1, real) ;
mm++ ;
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow+1, irow+1, real) ;
mm++ ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow, real, imag) ;
mm++ ;
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow+1, real, imag) ;
mm++ ;
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow+1, irow+1, real, imag) ;
mm++ ;
}
irow += 2 ;
}
}
}
/*
--------------------------------------
copy the entries in the upper triangle,
then move into the chvI object
--------------------------------------
*/
nent = Chv_copyBigEntriesToVector(chvJ, npivot, pivotsizes, sizes,
ivec, dvec, CHV_STRICT_UPPER,
storeflag, droptol) ;
if ( nent != nentU ) {
fprintf(stderr, "\n error: nentU = %d, nent = %d", nentU, nent) ;
exit(-1) ;
}
if ( storeflag == 1 ) {
for ( jcol = mm = 0 ; jcol < ncol ; jcol++ ) {
if ( sizes[jcol] > 0 ) {
for ( ii = 0 ; ii < sizes[jcol] ; ii++, mm++ ) {
irow = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
} else {
for ( irow = mm = 0 ; irow < nD ; irow++ ) {
if ( sizes[irow] > 0 ) {
for ( jj = 0 ; jj < sizes[irow] ; jj++, mm++ ) {
jcol = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% chevron b") ;
Chv_writeForMatlab(chvI, "b", msgFile) ;
fprintf(msgFile,
"\n\n emtx1 = abs(a - b) ; enorm1 = max(max(emtx1))") ;
fflush(msgFile) ;
}
IVfree(sizes) ;
IVfree(ivec) ;
DVfree(dvec) ;
/*
-----------------------------------------------------
second test: copy lower (1,1), lower (2,1), diagonal,
upper(1,1) and upper(1,2) blocks
-----------------------------------------------------
*/
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
nentL11 = Chv_countBigEntries(chvJ, npivot, pivotsizes,
CHV_STRICT_LOWER_11, droptol);
nentL21 = Chv_countBigEntries(chvJ, npivot, pivotsizes,
CHV_LOWER_21, droptol);
} else {
nentL11 = 0 ;
nentL21 = 0 ;
}
nentD = Chv_countEntries(chvJ, npivot, pivotsizes, CHV_DIAGONAL) ;
nentU11 = Chv_countBigEntries(chvJ, npivot, pivotsizes,
CHV_STRICT_UPPER_11, droptol) ;
nentU12 = Chv_countBigEntries(chvJ, npivot, pivotsizes,
CHV_UPPER_12, droptol) ;
maxnent = nentL11 ;
if ( maxnent < nentL21 ) { maxnent = nentL21 ; }
if ( maxnent < nentD ) { maxnent = nentD ; }
if ( maxnent < nentU11 ) { maxnent = nentU11 ; }
if ( maxnent < nentU12 ) { maxnent = nentU12 ; }
fprintf(msgFile,
"\n %% nentL11 = %d, nentL21 = %d"
"\n %% nentD = %d, nentU11 = %d, nentU12 = %d",
nentL11, nentL21, nentD, nentU11, nentU12) ;
sizes = IVinit(ncol, 0) ;
ivec = IVinit(maxnent, 0) ;
if ( CHV_IS_REAL(chvJ) ) {
dvec = DVinit(maxnent, 0.0) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
dvec = DVinit(2*maxnent, 0.0) ;
}
Chv_zero(chvI) ;
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
/*
------------------------------------------
copy the entries in the lower (1,1) block,
then move into the chvI object
------------------------------------------
*/
nent = Chv_copyBigEntriesToVector(chvJ, npivot, pivotsizes, sizes,
ivec, dvec, CHV_STRICT_LOWER_11,
storeflag, droptol) ;
if ( nent != nentL11 ) {
fprintf(stderr,
"\n error: nentL11 = %d, nent = %d", nentL11, nent) ;
exit(-1) ;
}
if ( storeflag == 0 ) {
for ( irow = 0, mm = 0 ; irow < nD ; irow++ ) {
if ( sizes[irow] > 0 ) {
for ( jj = 0 ; jj < sizes[irow] ; jj++, mm++ ) {
jcol = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
} else if ( storeflag == 1 ) {
for ( jcol = 0, mm = 0 ; jcol < nD ; jcol++ ) {
if ( sizes[jcol] > 0 ) {
for ( ii = 0 ; ii < sizes[jcol] ; ii++, mm++ ) {
irow = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
}
/*
------------------------------------------
copy the entries in the lower (2,1) block,
then move into the chvI object
------------------------------------------
*/
nent = Chv_copyBigEntriesToVector(chvJ, npivot, pivotsizes, sizes,
ivec, dvec, CHV_LOWER_21,
storeflag, droptol) ;
if ( nent != nentL21 ) {
fprintf(stderr, "\n error: nentL21 = %d, nent = %d",
nentL21, nent) ;
exit(-1) ;
}
if ( storeflag == 0 ) {
for ( irow = nD, mm = 0 ; irow < nrow ; irow++ ) {
if ( sizes[irow-nD] > 0 ) {
for ( jj = 0 ; jj < sizes[irow-nD] ; jj++, mm++ ) {
jcol = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
} else {
for ( jcol = mm = 0 ; jcol < nD ; jcol++ ) {
if ( sizes[jcol] > 0 ) {
for ( ii = 0 ; ii < sizes[jcol] ; ii++, mm++ ) {
irow = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
}
}
/*
---------------------------------------
copy the entries in the diagonal matrix
then move into the chvI object
---------------------------------------
*/
nent = Chv_copyEntriesToVector(chvJ, npivot, pivotsizes,
maxnent, dvec, CHV_DIAGONAL, storeflag) ;
/*
fprintf(stdout, "\n diagonal dvec") ;
DVfprintf(stdout, 2*nent, dvec) ;
*/
if ( nent != nentD ) {
fprintf(stderr, "\n error: nentD = %d, nent = %d", nentD, nent) ;
exit(-1) ;
}
if ( pivotsizes == NULL ) {
for ( jcol = 0, mm = 0 ; jcol < nD ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ; imag = dvec[2*mm+1] ;
Chv_setRealEntry(chvI, jcol, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, jcol, jcol, real, imag) ;
}
}
} else {
for ( ipivot = irow = mm = 0 ; ipivot < npivot ; ipivot++ ) {
if ( pivotsizes[ipivot] == 1 ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow, real, imag) ;
}
mm++ ; irow++ ;
} else {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow, real) ;
mm++ ;
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow+1, real) ;
mm++ ;
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow+1, irow+1, real) ;
mm++ ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow, real, imag) ;
mm++ ;
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow+1, real, imag) ;
mm++ ;
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow+1, irow+1, real, imag) ;
mm++ ;
}
irow += 2 ;
}
}
}
/*
-----------------------------------------
copy the entries in the upper (1,1) block
then move into the chvI object
-----------------------------------------
*/
nent = Chv_copyBigEntriesToVector(chvJ, npivot, pivotsizes, sizes,
ivec, dvec, CHV_STRICT_UPPER_11,
storeflag, droptol) ;
/*
fprintf(stdout, "\n U11 sizes") ;
IVfprintf(stdout, nD, sizes) ;
fprintf(stdout, "\n U11 ivec") ;
IVfprintf(stdout, nent, ivec) ;
fprintf(stdout, "\n U11 dvec") ;
DVfprintf(stdout, 2*nent, dvec) ;
*/
if ( nent != nentU11 ) {
fprintf(stderr, "\n error: nentU11 = %d, nent = %d", nentU11, nent) ;
exit(-1) ;
}
if ( storeflag == 1 ) {
for ( jcol = mm = 0 ; jcol < nD ; jcol++ ) {
if ( sizes[jcol] > 0 ) {
for ( ii = 0 ; ii < sizes[jcol] ; ii++, mm++ ) {
irow = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
} else if ( storeflag == 0 ) {
for ( irow = mm = 0 ; irow < nD ; irow++ ) {
if ( sizes[irow] > 0 ) {
for ( jj = 0 ; jj < sizes[irow] ; jj++, mm++ ) {
jcol = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
}
/*
-----------------------------------------
copy the entries in the upper (1,2) block
then move into the chvI object
-----------------------------------------
*/
nent = Chv_copyBigEntriesToVector(chvJ, npivot, pivotsizes, sizes,
ivec, dvec, CHV_UPPER_12,
storeflag, droptol) ;
/*
fprintf(stdout, "\n U12 sizes") ;
if ( storeflag == 1 ) {
IVfprintf(stdout, nU, sizes) ;
} else {
IVfprintf(stdout, nD, sizes) ;
}
fprintf(stdout, "\n U12 ivec") ;
IVfprintf(stdout, nent, ivec) ;
fprintf(stdout, "\n U12 dvec") ;
DVfprintf(stdout, 2*nent, dvec) ;
*/
if ( nent != nentU12 ) {
fprintf(stderr, "\n error: nentU12 = %d, nent = %d", nentU12, nent) ;
exit(-1) ;
}
if ( storeflag == 1 ) {
for ( jcol = nD, mm = 0 ; jcol < ncol ; jcol++ ) {
if ( sizes[jcol-nD] > 0 ) {
for ( ii = 0 ; ii < sizes[jcol-nD] ; ii++, mm++ ) {
irow = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
} else if ( storeflag == 0 ) {
for ( irow = 0, mm = 0 ; irow < nD ; irow++ ) {
if ( sizes[irow] > 0 ) {
for ( jj = 0 ; jj < sizes[irow] ; jj++, mm++ ) {
jcol = ivec[mm] ;
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% chevron b") ;
Chv_writeForMatlab(chvI, "b", msgFile) ;
fprintf(msgFile,
"\n\n emtx2 = abs(a - b) ; enorm2 = max(max(emtx2))"
"\n droptol = %12.4e", droptol) ;
fprintf(msgFile, "\n\n [ enorm1 enorm2 droptol ]") ;
fflush(msgFile) ;
}
fprintf(msgFile, "\n") ;
Chv_free(chvJ) ;
Chv_free(chvI) ;
Drand_free(drand) ;
IVfree(sizes) ;
IVfree(ivec) ;
DVfree(dvec) ;
if ( pivotsizes != NULL ) {
IVfree(pivotsizes) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
; }
if ( maxnent < nentU11 ) { maxnent = nentU11 ; }
if ( maxnent < nentU12 ) { maxnent = nentU12 ; }
fprintf(msgFile,
"\n %% nentL11 = %d, nentL21 = %d"
"\n %% nentD = %d, nentU11 = %d, nentU12 = %d",
nentL11, nentL21, nentD, nentU11, nentU12) ;
sizes = IVinit(ncol, 0) ;
ivec = IVinit(maxnent, 0) ;
if ( CHV_IS_REAL(chvJ) ) {
dvec = DVinit(maxnent, 0.0) ;
} else if ( CHV_IS_CChv/drivers/test_copyEntriesToVector.c 0100644 0002055 0007177 00000062435 06571267317 0021514 0 ustar 00cleve compmath 0000040 0000006 /* test_copyEntriesToVector.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
------------------------------------
test the copyEntriesToVector routine
created -- 98may01, cca,
------------------------------------
*/
{
Chv *chvJ, *chvI ;
double imag, real, t1, t2 ;
double *dvec, *entries ;
Drand *drand ;
FILE *msgFile ;
int count, first, ierr, ii, iilast, ipivot, irow, jcol, jj,
jjlast, maxnent, mm, msglvl, ncol, nD, nent, nentD, nentL,
nentL11, nentL21, nentU, nentU11, nentU12, nL, npivot, nrow,
nU, pivotingflag, seed, storeflag, symflag, total, type ;
int *colind, *pivotsizes, *rowind ;
if ( argc != 10 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nD nU type symflag "
"\n pivotingflag storeflag seed"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nD -- # of rows and columns in the (1,1) block"
"\n nU -- # of columns in the (1,2) block"
"\n type -- entries type"
"\n 1 --> real"
"\n 2 --> complex"
"\n symflag -- symmetry flag"
"\n 0 --> symmetric"
"\n 1 --> nonsymmetric"
"\n pivotingflag -- pivoting flag"
"\n if symflag = 1 and pivotingflag = 1 then"
"\n construct pivotsizes[] vector"
"\n endif"
"\n storeflag -- flag to denote how to store entries"
"\n 0 --> store by rows"
"\n 1 --> store by columns"
"\n seed -- random number seed"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
nD = atoi(argv[3]) ;
nU = atoi(argv[4]) ;
type = atoi(argv[5]) ;
symflag = atoi(argv[6]) ;
pivotingflag = atoi(argv[7]) ;
storeflag = atoi(argv[8]) ;
seed = atoi(argv[9]) ;
if ( msglvl > 0 ) {
switch ( storeflag ) {
case 0 : fprintf(msgFile, "\n\n %% STORE BY ROWS") ; break ;
case 1 : fprintf(msgFile, "\n\n %% STORE BY COLUMNS") ; break ;
default :
fprintf(stderr, "\n bad value %d for storeflag", storeflag) ;
break ;
}
}
nL = nU ;
if ( symflag == SPOOLES_NONSYMMETRIC ) {
pivotingflag = 0 ;
}
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setNormal(drand, 0.0, 1.0) ;
Drand_setSeed(drand, seed) ;
/*
--------------------------
initialize the chvJ object
--------------------------
*/
MARKTIME(t1) ;
chvJ = Chv_new() ;
Chv_init(chvJ, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize matrix objects",
t2 - t1) ;
nent = Chv_nent(chvJ) ;
entries = Chv_entries(chvJ) ;
if ( CHV_IS_REAL(chvJ) ) {
Drand_fillDvector(drand, nent, entries) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
Drand_fillDvector(drand, 2*nent, entries) ;
}
Chv_columnIndices(chvJ, &ncol, &colind) ;
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
Chv_rowIndices(chvJ, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% chevron a") ;
Chv_writeForMatlab(chvJ, "a", msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------
initialize the chvI object
--------------------------
*/
MARKTIME(t1) ;
chvI = Chv_new() ;
Chv_init(chvI, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize matrix objects",
t2 - t1) ;
Chv_zero(chvI) ;
Chv_columnIndices(chvI, &ncol, &colind) ;
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chvI) ) {
Chv_rowIndices(chvI, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
if ( symflag == 0 && pivotingflag == 1 ) {
/*
------------------------------
create the pivotsizes[] vector
------------------------------
*/
Drand_setUniform(drand, 1, 2.999) ;
pivotsizes = IVinit(nD, 0) ;
Drand_fillIvector(drand, nD, pivotsizes) ;
/*
fprintf(msgFile, "\n initial pivotsizes[] : ") ;
IVfp80(msgFile, nD, pivotsizes, 80, &ierr) ;
*/
for ( npivot = count = 0 ; npivot < nD ; npivot++ ) {
count += pivotsizes[npivot] ;
if ( count > nD ) {
pivotsizes[npivot]-- ;
count-- ;
}
if ( count == nD ) {
break ;
}
}
npivot++ ;
/*
fprintf(msgFile, "\n final pivotsizes[] : ") ;
IVfp80(msgFile, npivot, pivotsizes, 80, &ierr) ;
*/
} else {
npivot = 0 ;
pivotsizes = NULL ;
}
/*
--------------------------------------------------
first test: copy lower, diagonal and upper entries
--------------------------------------------------
*/
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
nentL = Chv_countEntries(chvJ, npivot, pivotsizes, CHV_STRICT_LOWER);
} else {
nentL = 0 ;
}
nentD = Chv_countEntries(chvJ, npivot, pivotsizes, CHV_DIAGONAL) ;
nentU = Chv_countEntries(chvJ, npivot, pivotsizes, CHV_STRICT_UPPER) ;
maxnent = nentL ;
if ( maxnent < nentD ) { maxnent = nentD ; }
if ( maxnent < nentU ) { maxnent = nentU ; }
if ( CHV_IS_REAL(chvJ) ) {
dvec = DVinit(maxnent, 0.0) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
dvec = DVinit(2*maxnent, 0.0) ;
}
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
/*
--------------------------------------
copy the entries in the lower triangle,
then move into the chvI object
--------------------------------------
*/
nent = Chv_copyEntriesToVector(chvJ, npivot, pivotsizes, maxnent,
dvec, CHV_STRICT_LOWER, storeflag) ;
if ( nent != nentL ) {
fprintf(stderr, "\n error: nentL = %d, nent = %d", nentL, nent) ;
exit(-1) ;
}
if ( storeflag == 0 ) {
for ( irow = 0, mm = 0 ; irow < nrow ; irow++ ) {
jjlast = (irow < nD) ? irow - 1 : nD - 1 ;
for ( jj = 0 ; jj <= jjlast ; jj++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jj, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ;
imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jj, real, imag) ;
}
}
}
} else {
for ( jcol = 0, mm = 0 ; jcol < nD ; jcol++ ) {
for ( irow = jcol + 1 ; irow < nrow ; irow++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
/*
fprintf(msgFile, "\n %% mm = %d, a(%d,%d) = %20.12e + %20.12e*i",
mm, irow, jcol, real, imag) ;
*/
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
}
/*
---------------------------------------
copy the entries in the diagonal matrix
then move into the chvI object
---------------------------------------
*/
nent = Chv_copyEntriesToVector(chvJ, npivot, pivotsizes, maxnent,
dvec, CHV_DIAGONAL, storeflag) ;
if ( nent != nentD ) {
fprintf(stderr, "\n error: nentD = %d, nent = %d", nentD, nent) ;
exit(-1) ;
}
if ( pivotsizes == NULL ) {
for ( jcol = 0, mm = 0 ; jcol < nD ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, jcol, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, jcol, jcol, real, imag) ;
}
}
} else {
for ( ipivot = irow = mm = 0 ; ipivot < npivot ; ipivot++ ) {
if ( pivotsizes[ipivot] == 1 ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow, real, imag) ;
}
mm++ ; irow++ ;
} else {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow, real) ;
mm++ ;
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow+1, real) ;
mm++ ;
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow+1, irow+1, real) ;
mm++ ;
irow += 2 ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow, real, imag) ;
mm++ ;
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow+1, real, imag) ;
mm++ ;
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow+1, irow+1, real, imag) ;
mm++ ;
irow += 2 ;
}
}
}
}
/*
--------------------------------------
copy the entries in the upper triangle,
then move into the chvI object
--------------------------------------
*/
nent = Chv_copyEntriesToVector(chvJ, npivot, pivotsizes, maxnent,
dvec, CHV_STRICT_UPPER, storeflag) ;
if ( nent != nentU ) {
fprintf(stderr, "\n error: nentU = %d, nent = %d", nentU, nent) ;
exit(-1) ;
}
if ( storeflag == 1 ) {
if ( pivotsizes == NULL ) {
for ( jcol = mm = 0 ; jcol < ncol ; jcol++ ) {
iilast = (jcol < nD) ? jcol - 1 : nD - 1 ;
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, ii, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, ii, jcol, real, imag) ;
}
}
}
} else {
for ( ipivot = jcol = mm = 0 ; ipivot < npivot ; ipivot++ ) {
iilast = jcol - 1 ;
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, ii, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, ii, jcol, real, imag) ;
}
}
jcol++ ;
if ( pivotsizes[ipivot] == 2 ) {
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, ii, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, ii, jcol, real, imag) ;
}
}
jcol++ ;
}
}
for ( jcol = nD ; jcol < ncol ; jcol++ ) {
for ( irow = 0 ; irow < nD ; irow++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
} else {
if ( pivotsizes == NULL ) {
for ( irow = mm = 0 ; irow < nD ; irow++ ) {
for ( jcol = irow + 1 ; jcol < ncol ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
} else {
for ( ipivot = irow = mm = 0 ; ipivot < npivot ; ipivot++ ) {
if ( pivotsizes[ipivot] == 1 ) {
for ( jcol = irow + 1 ; jcol < ncol ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
irow++ ;
} else {
for ( jcol = irow + 2 ; jcol < ncol ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
for ( jcol = irow + 2 ; jcol < ncol ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow+1, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow+1, jcol, real, imag) ;
}
}
irow += 2 ;
}
}
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% chevron b") ;
Chv_writeForMatlab(chvI, "b", msgFile) ;
fprintf(msgFile,
"\n\n emtx1 = abs(a - b) ; enorm1 = max(max(emtx1))") ;
fflush(msgFile) ;
}
DVfree(dvec) ;
/*
-----------------------------------------------------
second test: copy lower (1,1), lower (2,1), diagonal,
upper(1,1) and upper(1,2) blocks
-----------------------------------------------------
*/
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
nentL11 = Chv_countEntries(chvJ, npivot, pivotsizes,
CHV_STRICT_LOWER_11) ;
nentL21 = Chv_countEntries(chvJ, npivot, pivotsizes,
CHV_LOWER_21) ;
} else {
nentL11 = 0 ;
nentL21 = 0 ;
}
nentD = Chv_countEntries(chvJ, npivot, pivotsizes, CHV_DIAGONAL) ;
nentU11 = Chv_countEntries(chvJ, npivot, pivotsizes,
CHV_STRICT_UPPER_11) ;
nentU12 = Chv_countEntries(chvJ, npivot, pivotsizes,
CHV_UPPER_12) ;
maxnent = nentL11 ;
if ( maxnent < nentL21 ) { maxnent = nentL21 ; }
if ( maxnent < nentD ) { maxnent = nentD ; }
if ( maxnent < nentU11 ) { maxnent = nentU11 ; }
if ( maxnent < nentU12 ) { maxnent = nentU12 ; }
fprintf(msgFile,
"\n %% nentL11 = %d, nentL21 = %d"
"\n %% nentD = %d, nentU11 = %d, nentU12 = %d",
nentL11, nentL21, nentD, nentU11, nentU12) ;
if ( CHV_IS_REAL(chvJ) ) {
dvec = DVinit(maxnent, 0.0) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
dvec = DVinit(2*maxnent, 0.0) ;
}
Chv_zero(chvI) ;
if ( CHV_IS_NONSYMMETRIC(chvJ) ) {
/*
------------------------------------------
copy the entries in the lower (1,1) block,
then move into the chvI object
------------------------------------------
*/
nent = Chv_copyEntriesToVector(chvJ, npivot, pivotsizes, maxnent,
dvec, CHV_STRICT_LOWER_11, storeflag) ;
if ( nent != nentL11 ) {
fprintf(stderr, "\n error: nentL = %d, nent = %d", nentL, nent) ;
exit(-1) ;
}
if ( storeflag == 0 ) {
for ( irow = 0, mm = 0 ; irow < nD ; irow++ ) {
jjlast = (irow < nD) ? irow - 1 : nD - 1 ;
for ( jj = 0 ; jj <= jjlast ; jj++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jj, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jj, real, imag) ;
}
}
}
} else {
for ( jcol = 0, mm = 0 ; jcol < nD ; jcol++ ) {
for ( irow = jcol + 1 ; irow < nD ; irow++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
/*
------------------------------------------
copy the entries in the lower (2,1) block,
then move into the chvI object
------------------------------------------
*/
nent = Chv_copyEntriesToVector(chvJ, npivot, pivotsizes, maxnent,
dvec, CHV_LOWER_21, storeflag);
if ( nent != nentL21 ) {
fprintf(stderr, "\n error: nentL21 = %d, nent = %d",
nentL21, nent) ;
exit(-1) ;
}
if ( storeflag == 0 ) {
for ( irow = nD, mm = 0 ; irow < nrow ; irow++ ) {
for ( jcol = 0 ; jcol < nD ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
} else {
for ( jcol = 0, mm = 0 ; jcol < nD ; jcol++ ) {
for ( irow = nD ; irow < nrow ; irow++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
}
/*
---------------------------------------
copy the entries in the diagonal matrix
then move into the chvI object
---------------------------------------
*/
nent = Chv_copyEntriesToVector(chvJ, npivot, pivotsizes, maxnent,
dvec, CHV_DIAGONAL, storeflag) ;
if ( nent != nentD ) {
fprintf(stderr, "\n error: nentD = %d, nent = %d", nentD, nent) ;
exit(-1) ;
}
if ( pivotsizes == NULL ) {
for ( jcol = 0, mm = 0 ; jcol < nD ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, jcol, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, jcol, jcol, real, imag) ;
}
}
} else {
for ( ipivot = irow = mm = 0 ; ipivot < npivot ; ipivot++ ) {
if ( pivotsizes[ipivot] == 1 ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow, real, imag) ;
}
mm++ ; irow++ ;
} else {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow, real) ;
mm++ ;
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, irow+1, real) ;
mm++ ;
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow+1, irow+1, real) ;
mm++ ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow, real, imag) ;
mm++ ;
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, irow+1, real, imag) ;
mm++ ;
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow+1, irow+1, real, imag) ;
mm++ ;
}
irow += 2 ;
}
}
}
/*
-----------------------------------------
copy the entries in the upper (1,1) block
then move into the chvI object
-----------------------------------------
*/
nent = Chv_copyEntriesToVector(chvJ, npivot, pivotsizes, maxnent,
dvec, CHV_STRICT_UPPER_11, storeflag) ;
if ( nent != nentU11 ) {
fprintf(stderr, "\n error: nentU11 = %d, nent = %d", nentU11, nent) ;
exit(-1) ;
}
if ( storeflag == 1 ) {
if ( pivotsizes == NULL ) {
for ( jcol = mm = 0 ; jcol < nD ; jcol++ ) {
iilast = (jcol < nD) ? jcol - 1 : nD - 1 ;
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, ii, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, ii, jcol, real, imag) ;
}
}
}
} else {
for ( ipivot = jcol = mm = 0 ; ipivot < npivot ; ipivot++ ) {
iilast = jcol - 1 ;
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, ii, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, ii, jcol, real, imag) ;
}
}
jcol++ ;
if ( pivotsizes[ipivot] == 2 ) {
for ( ii = 0 ; ii <= iilast ; ii++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, ii, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, ii, jcol, real, imag) ;
}
}
jcol++ ;
}
}
}
} else {
if ( pivotsizes == NULL ) {
for ( irow = mm = 0 ; irow < nD ; irow++ ) {
for ( jcol = irow + 1 ; jcol < nD ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
} else {
for ( ipivot = irow = mm = 0 ; ipivot < npivot ; ipivot++ ) {
if ( pivotsizes[ipivot] == 1 ) {
for ( jcol = irow + 1 ; jcol < nD ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
irow++ ;
} else {
for ( jcol = irow + 2 ; jcol < nD ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
for ( jcol = irow + 2 ; jcol < nD ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow+1, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow+1, jcol, real, imag) ;
}
}
irow += 2 ;
}
}
}
}
/*
-----------------------------------------
copy the entries in the upper (1,2) block
then move into the chvI object
-----------------------------------------
*/
nent = Chv_copyEntriesToVector(chvJ, npivot, pivotsizes, maxnent,
dvec, CHV_UPPER_12, storeflag) ;
if ( nent != nentU12 ) {
fprintf(stderr, "\n error: nentU12 = %d, nent = %d", nentU12, nent) ;
exit(-1) ;
}
if ( storeflag == 1 ) {
for ( jcol = nD, mm = 0 ; jcol < ncol ; jcol++ ) {
for ( irow = 0 ; irow < nD ; irow++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
} else {
for ( irow = mm = 0 ; irow < nD ; irow++ ) {
for ( jcol = nD ; jcol < ncol ; jcol++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv_setRealEntry(chvI, irow, jcol, real) ;
} else if ( CHV_IS_COMPLEX(chvJ) ) {
real = dvec[2*mm] ; imag = dvec[2*mm+1] ;
Chv_setComplexEntry(chvI, irow, jcol, real, imag) ;
}
}
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %% chevron b") ;
Chv_writeForMatlab(chvI, "b", msgFile) ;
fprintf(msgFile,
"\n\n emtx2 = abs(a - b) ; enorm2 = max(max(emtx2))") ;
fprintf(msgFile, "\n\n [ enorm1 enorm2]") ;
fflush(msgFile) ;
}
/*
------------------------
free the working storage
------------------------
*/
if ( pivotsizes != NULL ) {
IVfree(pivotsizes) ;
}
Chv_free(chvJ) ;
Chv_free(chvI) ;
Drand_free(drand) ;
DVfree(dvec) ;
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
for ( irow = 0, mm = 0 ; irow < nD ; irow++ ) {
jjlast = (irow < nD) ? irow - 1 : nD - 1 ;
for ( jj = 0 ; jj <= jjlast ; jj++, mm++ ) {
if ( CHV_IS_REAL(chvJ) ) {
real = dvec[mm] ;
Chv/drivers/test_factor.c 0100644 0002055 0007177 00000033350 06573543234 0016767 0 ustar 00cleve compmath 0000040 0000006 /* test_factor.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------
test the Chv_factor() method.
the program's output is a matlab file
to check correctness of the code.
created -- 98apr22, cca
-------------------------------------
*/
{
Chv *chv ;
double imag, real, tau, t1, t2 ;
double *entries ;
Drand *drand ;
DV *workDV ;
FILE *msgFile ;
int ii, ipivot, irow, jcol, msglvl, ncol, nD, ndelay,
nelim, nent, nL, nrow, npivot, ntest, nU, pivotflag,
rc, seed, symflag, tag, type ;
int *colind, *pivotsizes, *rowind ;
IV *pivotsizesIV ;
if ( argc != 10 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nD nU type symflag pivotflag seed tau "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nD -- # of rows and columns in the (1,1) block"
"\n nU -- # of columns in the (1,2) block"
"\n type -- entries type"
"\n 1 --> real"
"\n 2 --> complex"
"\n symflag -- symmetry flag"
"\n 0 --> hermitian"
"\n 1 --> symmetric"
"\n 2 --> nonsymmetric"
"\n pivotflag -- pivoting flag"
"\n 0 --> no pivoting"
"\n 1 --> pivoting"
"\n tau -- bound on magnitude of factor entries"
"\n seed -- random number seed"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
nD = atoi(argv[3]) ;
nU = atoi(argv[4]) ;
type = atoi(argv[5]) ;
symflag = atoi(argv[6]) ;
pivotflag = atoi(argv[7]) ;
seed = atoi(argv[8]) ;
tau = atof(argv[9]) ;
fprintf(msgFile, "\n %% testChv:"
"\n %% msglvl = %d"
"\n %% msgFile = %s"
"\n %% nD = %d"
"\n %% nU = %d"
"\n %% type = %d"
"\n %% symflag = %d"
"\n %% pivotflag = %d"
"\n %% seed = %d"
"\n %% tau = %f",
msglvl, argv[2], nD, nU, type, symflag, pivotflag, seed, tau) ;
nL = nU ;
/*
-----------------------------
check for errors in the input
-----------------------------
*/
if ( nD <= 0 || nL < 0 || nU < 0
|| symflag < 0 || symflag > 2 ) {
fprintf(stderr, "\n invalid input"
"\n nD = %d, nL = %d, nU = %d, symflag = %d\n",
nD, nL, nU, symflag) ;
exit(-1) ;
}
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setSeed(drand, seed) ;
Drand_setNormal(drand, 0.0, 1.0) ;
/*
----------------------------
initialize the Chv object
----------------------------
*/
MARKTIME(t1) ;
chv = Chv_new() ;
Chv_init(chv, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize chv object",
t2 - t1) ;
fflush(msgFile) ;
Chv_columnIndices(chv, &ncol, &colind) ;
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chv) ) {
Chv_rowIndices(chv, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
/*
------------------------------------
load the entries with random entries
------------------------------------
*/
nent = Chv_nent(chv) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
Drand_fillDvector(drand, nent, entries) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
Drand_fillDvector(drand, 2*nent, entries) ;
}
if ( CHV_IS_HERMITIAN(chv) ) {
for ( irow = 0 ; irow < nD ; irow++ ) {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
Chv_setComplexEntry(chv, irow, irow, real, 0.0) ;
}
}
fprintf(msgFile, "\n %% matrix entries") ;
Chv_writeForMatlab(chv, "A", msgFile) ;
if ( pivotflag == 1 ) {
pivotsizesIV = IV_new() ;
} else {
pivotsizesIV = NULL ;
}
workDV = DV_new() ;
/*
-----------------
factor the matrix
-----------------
*/
ndelay = ntest = 0 ;
if ( pivotflag == SPOOLES_PIVOTING ) {
nelim = Chv_factorWithPivoting(chv, ndelay, pivotflag, pivotsizesIV,
workDV, tau, &ntest) ;
} else {
nelim = Chv_factorWithNoPivoting(chv, NULL) ;
}
fprintf(msgFile, "\n nD = %d ;\n nelim = %d", nD, nelim) ;
/*
---------------------
write out the factors
---------------------
*/
Chv_rowIndices(chv, &nrow, &rowind) ;
Chv_columnIndices(chv, &ncol, &colind) ;
fprintf(msgFile,
"\n\n L = eye(%d,%d); "
"\n D = zeros(%d,%d); "
"\n T = zeros(%d,%d); "
"\n U = eye(%d,%d); ",
ncol, ncol, ncol, ncol, ncol, ncol, ncol, ncol) ;
if ( pivotflag == 0 ) {
if ( CHV_IS_REAL(chv) ) {
for ( irow = 0 ; irow < nD ; irow++ ) {
Chv_realEntry(chv, irow, irow, &real) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e ;",
rowind[irow]+1, colind[irow]+1, real) ;
for ( jcol = irow + 1 ; jcol < nD + nU ; jcol++ ) {
Chv_realEntry(chv, irow, jcol, &real) ;
fprintf(msgFile, "\n U(%d,%d) = %20.12e ;",
rowind[irow]+1, colind[jcol]+1, real) ;
Chv_realEntry(chv, jcol, irow, &real) ;
fprintf(msgFile, "\n L(%d,%d) = %20.12e ;",
rowind[jcol]+1, colind[irow]+1, real) ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( irow = 0 ; irow < nD ; irow++ ) {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow]+1, colind[irow]+1, real, imag) ;
for ( jcol = irow + 1 ; jcol < nD + nU ; jcol++ ) {
Chv_complexEntry(chv, irow, jcol, &real, &imag) ;
fprintf(msgFile, "\n U(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow]+1, colind[jcol]+1, real, imag) ;
Chv_complexEntry(chv, jcol, irow, &real, &imag) ;
fprintf(msgFile, "\n L(%d,%d) = %20.12e + %20.12e*i ;",
rowind[jcol]+1, colind[irow]+1, real, imag) ;
}
}
}
} else {
for ( irow = 0 ; irow < nrow ; irow++ ) {
fprintf(msgFile, "\n colind(%d) = %d;",
irow + 1, 1+colind[irow]) ;
}
if ( CHV_IS_NONSYMMETRIC(chv) ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
fprintf(msgFile, "\n rowind(%d) = %d;",
irow + 1, 1+rowind[irow]) ;
}
IV_setSize(pivotsizesIV, nelim) ;
IV_fill(pivotsizesIV, 1) ;
} else {
fprintf(msgFile, "\n rowind = colind ;") ;
}
fprintf(msgFile, "\n A = A(rowind,colind) ;") ;
IVramp(nrow, rowind, 0, 1) ;
IVramp(ncol, colind, 0, 1) ;
IV_sizeAndEntries(pivotsizesIV, &npivot, &pivotsizes) ;
fprintf(msgFile, "\n npivot = %d ;", npivot) ;
if ( CHV_IS_REAL(chv) ) {
for ( ipivot = irow = 0 ; ipivot < npivot ; ipivot++ ) {
if ( pivotsizes[ipivot] == 1 ) {
Chv_realEntry(chv, irow, irow, &real) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e ;",
rowind[irow]+1, colind[irow]+1, real) ;
for ( jcol = irow + 1 ; jcol < nD + nU ; jcol++ ) {
Chv_realEntry(chv, irow, jcol, &real) ;
fprintf(msgFile, "\n U(%d,%d) = %20.12e ;",
rowind[irow]+1, colind[jcol]+1, real) ;
Chv_realEntry(chv, jcol, irow, &real) ;
fprintf(msgFile, "\n L(%d,%d) = %20.12e ;",
rowind[jcol]+1, colind[irow]+1, real) ;
}
irow += 1 ;
} else {
Chv_realEntry(chv, irow, irow, &real) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e ;",
rowind[irow]+1, colind[irow]+1, real) ;
Chv_realEntry(chv, irow, irow+1, &real) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e ;",
rowind[irow]+1, colind[irow+1]+1, real) ;
Chv_realEntry(chv, irow+1, irow, &real) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e ;",
rowind[irow+1]+1, colind[irow]+1, real) ;
Chv_realEntry(chv, irow+1, irow+1, &real) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e ;",
rowind[irow+1]+1, colind[irow+1]+1, real) ;
for ( jcol = irow + 2 ; jcol < nD + nU ; jcol++ ) {
Chv_realEntry(chv, irow, jcol, &real) ;
fprintf(msgFile, "\n U(%d,%d) = %20.12e ;",
rowind[irow]+1, colind[jcol]+1, real) ;
Chv_realEntry(chv, jcol, irow, &real) ;
fprintf(msgFile, "\n L(%d,%d) = %20.12e ;",
rowind[jcol]+1, colind[irow]+1, real) ;
Chv_realEntry(chv, irow+1, jcol, &real) ;
fprintf(msgFile, "\n U(%d,%d) = %20.12e ;",
rowind[irow+1]+1, colind[jcol]+1, real) ;
Chv_realEntry(chv, jcol, irow+1, &real) ;
fprintf(msgFile, "\n L(%d,%d) = %20.12e ;",
rowind[jcol]+1, colind[irow+1]+1, real) ;
}
irow += 2 ;
}
}
for ( irow = nelim ; irow < nD ; irow++ ) {
Chv_realEntry(chv, irow, irow, &real) ;
fprintf(msgFile, "\n T(%d,%d) = %20.12e ;",
rowind[irow]+1, colind[irow]+1, real) ;
for ( jcol = irow + 1 ; jcol < ncol ; jcol++ ) {
Chv_realEntry(chv, irow, jcol, &real) ;
fprintf(msgFile, "\n T(%d,%d) = %20.12e ;",
rowind[irow]+1, colind[jcol]+1, real) ;
Chv_realEntry(chv, jcol, irow, &real) ;
fprintf(msgFile, "\n T(%d,%d) = %20.12e ;",
rowind[jcol]+1, colind[irow]+1, real) ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
for ( ipivot = irow = 0 ; ipivot < npivot ; ipivot++ ) {
if ( pivotsizes[ipivot] == 1 ) {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow]+1, colind[irow]+1, real, imag) ;
for ( jcol = irow + 1 ; jcol < nD + nU ; jcol++ ) {
Chv_complexEntry(chv, irow, jcol, &real, &imag) ;
fprintf(msgFile, "\n U(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow]+1, colind[jcol]+1, real, imag) ;
Chv_complexEntry(chv, jcol, irow, &real, &imag) ;
fprintf(msgFile, "\n L(%d,%d) = %20.12e + %20.12e*i ;",
rowind[jcol]+1, colind[irow]+1, real, imag) ;
}
irow += 1 ;
} else {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow]+1, colind[irow]+1, real, imag) ;
Chv_complexEntry(chv, irow, irow+1, &real, &imag) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow]+1, colind[irow+1]+1, real, imag) ;
Chv_complexEntry(chv, irow+1, irow, &real, &imag) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow+1]+1, colind[irow]+1, real, imag) ;
Chv_complexEntry(chv, irow+1, irow+1, &real, &imag) ;
fprintf(msgFile, "\n D(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow+1]+1, colind[irow+1]+1, real, imag) ;
for ( jcol = irow + 2 ; jcol < nD + nU ; jcol++ ) {
Chv_complexEntry(chv, irow, jcol, &real, &imag) ;
fprintf(msgFile, "\n U(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow]+1, colind[jcol]+1, real, imag) ;
Chv_complexEntry(chv, jcol, irow, &real, &imag) ;
fprintf(msgFile, "\n L(%d,%d) = %20.12e + %20.12e*i ;",
rowind[jcol]+1, colind[irow]+1, real, imag) ;
Chv_complexEntry(chv, irow+1, jcol, &real, &imag) ;
fprintf(msgFile, "\n U(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow+1]+1, colind[jcol]+1, real, imag) ;
Chv_complexEntry(chv, jcol, irow+1, &real, &imag) ;
fprintf(msgFile, "\n L(%d,%d) = %20.12e + %20.12e*i ;",
rowind[jcol]+1, colind[irow+1]+1, real, imag) ;
}
irow += 2 ;
}
}
for ( irow = nelim ; irow < nD ; irow++ ) {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
fprintf(msgFile, "\n T(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow]+1, colind[irow]+1, real, imag) ;
for ( jcol = irow + 1 ; jcol < ncol ; jcol++ ) {
Chv_complexEntry(chv, irow, jcol, &real, &imag) ;
fprintf(msgFile, "\n T(%d,%d) = %20.12e + %20.12e*i ;",
rowind[irow]+1, colind[jcol]+1, real, imag) ;
Chv_complexEntry(chv, jcol, irow, &real, &imag) ;
fprintf(msgFile, "\n T(%d,%d) = %20.12e + %20.12e*i ;",
rowind[jcol]+1, colind[irow]+1, real, imag) ;
}
}
}
}
fprintf(msgFile, "\n B = A ;") ;
fprintf(msgFile,
"\n B = A - T - L(:,1:%d) * D(1:%d,1:%d) * U(1:%d,:) ; ",
nelim, nelim, nelim, nelim) ;
fprintf(msgFile, "\n B(%d:%d,%d:%d) = 0.0 ; ", nD+1, ncol, nD+1, ncol) ;
fprintf(msgFile,
"\n maxabsB = max(max(abs(B)))"
"\n maxabsL = max(max(abs(L - eye(%d,%d))))"
"\n maxabsU = max(max(abs(U - eye(%d,%d))))"
"\n [ maxabsB maxabsL maxabsU ]",
ncol, ncol, ncol, ncol) ;
/*
------------------------
free the working storage
------------------------
*/
Chv_free(chv) ;
DV_free(workDV) ;
if ( pivotsizesIV != NULL ) {
IV_free(pivotsizesIV) ;
}
Drand_free(drand) ;
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
File, "\n colind(%d) = %d;",
irow + 1, 1+colind[irow]) ;
}
if ( CHV_IS_NONSYMMETRIC(chv) ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
fprintf(msgFile, "\n rowind(%d) = %d;",
irow + 1, 1+rowind[irow]) ;
}
IV_setSizChv/drivers/test_findPivot.c 0100644 0002055 0007177 00000022415 06571267320 0017450 0 ustar 00cleve compmath 0000040 0000006 /* test_findPivot.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------------
test the Chv_findPivot(), swap and update methods.
the program's output is a matlab file
to check correctness of the code.
created -- 98jan24, cca
---------------------------------------------------
*/
{
Chv *chv ;
double imag, real, tau, t1, t2 ;
double *entries ;
Drand *drand ;
DV *workDV ;
FILE *msgFile ;
int icol, ii, ipvt, irow, jcol, jpvt, jrow, msglvl, ncol, nD,
ndelay, nent, nL, nrow, ntest, nU, rc, pivotsize, seed,
symflag, tag, temp, type ;
int *colind, *rowind ;
if ( argc != 9 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nD nU type symflag seed tau "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nD -- # of rows and columns in the (1,1) block"
"\n nU -- # of columns in the (1,2) block"
"\n type -- entries type"
"\n 1 --> real"
"\n 2 --> complex"
"\n symflag -- symmetry flag"
"\n 0 --> symmetric"
"\n 1 --> hermitian"
"\n 2 --> nonsymmetric"
"\n seed -- random number seed"
"\n tau -- bound on magnitudes of factor entries"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
nD = atoi(argv[3]) ;
nU = atoi(argv[4]) ;
type = atoi(argv[5]) ;
symflag = atoi(argv[6]) ;
seed = atoi(argv[7]) ;
tau = atof(argv[8]) ;
fprintf(msgFile, "\n %% testChv:"
"\n %% msglvl = %d"
"\n %% msgFile = %s"
"\n %% nD = %d"
"\n %% nU = %d"
"\n %% type = %d"
"\n %% symflag = %d"
"\n %% seed = %d"
"\n %% tau = %12.4e",
msglvl, argv[2], nD, nU, type, symflag, seed, tau) ;
nL = nU ;
nrow = nD + nL ;
ncol = nD + nU ;
/*
-----------------------------
check for errors in the input
-----------------------------
*/
if ( nD <= 0 || nU < 0
|| (symflag != SPOOLES_SYMMETRIC
&& symflag != SPOOLES_HERMITIAN
&& symflag != SPOOLES_NONSYMMETRIC) ) {
fprintf(stderr, "\n invalid input"
"\n nD = %d, nL = %d, nU = %d, symflag = %d\n",
nD, nL, nU, symflag) ;
exit(-1) ;
}
if ( (symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN)
&& nL != nU ) {
fprintf(stderr, "\n invalid input"
"\n symflag = %d, nL = %d, nU = %d", symflag, nL, nU) ;
exit(-1) ;
}
fprintf(msgFile,
"\n nD = %d ;"
"\n nL = %d ;"
"\n nU = %d ;"
"\n nrow = nD + nL ;"
"\n ncol = nD + nU ;",
nD, nL, nU) ;
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setSeed(drand, seed) ;
Drand_setNormal(drand, 0.0, 1.0) ;
/*
--------------------------
initialize the Chv object
--------------------------
*/
MARKTIME(t1) ;
chv = Chv_new() ;
Chv_init(chv, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize chv object",
t2 - t1) ;
fflush(msgFile) ;
Chv_columnIndices(chv, &ncol, &colind) ;
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chv) ) {
Chv_rowIndices(chv, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
/*
------------------------------------
load the entries with random entries
------------------------------------
*/
nent = Chv_nent(chv) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
Drand_fillDvector(drand, nent, entries) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
Drand_fillDvector(drand, 2*nent, entries) ;
}
if ( msglvl > 4 ) {
fprintf(msgFile, "\n raw entries vector") ;
DVfprintf(msgFile, 2*nent, entries) ;
fflush(msgFile) ;
}
if ( CHV_IS_HERMITIAN(chv) ) {
/*
---------------------------------------------------------
hermitian example, set imaginary part of diagonal to zero
---------------------------------------------------------
*/
for ( irow = 0 ; irow < nD ; irow++ ) {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
Chv_setComplexEntry(chv, irow, irow, real, 0.0) ;
}
}
fprintf(msgFile, "\n %% matrix entries") ;
Chv_writeForMatlab(chv, "a", msgFile) ;
/*
------------
find a pivot
------------
*/
workDV = DV_new() ;
ndelay = 0 ;
ntest = 0 ;
pivotsize = Chv_findPivot(chv, workDV, tau, ndelay,
&irow, &jcol, &ntest) ;
fprintf(msgFile, "\n\n %% pivotsize = %d", pivotsize) ;
ipvt = irow ;
jpvt = jcol ;
if ( (symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN)
&& irow > jcol ) {
temp = irow ;
irow = jcol ;
jcol = temp ;
}
fprintf(msgFile, "\n\n irow = %d ; \n jcol = %d ;", irow+1, jcol+1) ;
/*
-------------------------
swap the rows and columns
-------------------------
*/
if ( pivotsize == 0 ) {
exit(0) ;
} else if ( pivotsize == 1 ) {
fprintf(msgFile,
"\n b = a ;"
"\n xtemp = b(irow,:) ;"
"\n b(irow,:) = b(1,:) ;"
"\n b(1,:) = xtemp ;"
"\n xtemp = b(:,jcol) ;"
"\n b(:,jcol) = b(:,1) ;"
"\n b(:,1) = xtemp ;") ;
if ( CHV_IS_SYMMETRIC(chv) || symflag == CHV_IS_HERMITIAN(chv) ) {
Chv_swapRowsAndColumns(chv, 0, irow) ;
} else {
Chv_swapRows(chv, 0, irow) ;
Chv_swapColumns(chv, 0, jcol) ;
}
} else if ( pivotsize == 2 ) {
if ( symflag < 2 ) {
fprintf(msgFile,
"\n b = a ;"
"\n xtemp = b(irow,:) ;"
"\n b(irow,:) = b(1,:) ;"
"\n b(1,:) = xtemp ;"
"\n xtemp = b(:,irow) ;"
"\n b(:,irow) = b(:,1) ;"
"\n b(:,1) = xtemp ;"
"\n xtemp = b(jcol,:) ;"
"\n b(jcol,:) = b(2,:) ;"
"\n b(2,:) = xtemp ;"
"\n xtemp = b(:,jcol) ;"
"\n b(:,jcol) = b(:,2) ;"
"\n b(:,2) = xtemp ;") ;
Chv_swapRowsAndColumns(chv, 0, irow) ;
Chv_swapRowsAndColumns(chv, 1, jcol) ;
} else {
fprintf(stderr, "\n fatal error, symflag = %d, pvtsize = %d",
symflag, pivotsize) ;
exit(-1) ;
}
}
/*
-----------------------------------------
check that the swap was executed properly
-----------------------------------------
*/
fprintf(msgFile, "\n %% matrix entries") ;
Chv_writeForMatlab(chv, "c", msgFile) ;
fprintf(msgFile, "\n maxerrswap = norm(c - a)") ;
/*
---------------------------
ramp the indices once again
---------------------------
*/
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chv) ) {
Chv_rowIndices(chv, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
/*
-----------------------------------
perform the rank-1 or rank-2 update
-----------------------------------
*/
fprintf(msgFile, "\n\n ckeep = b ;") ;
fprintf(msgFile, "\n\n c = b ;") ;
if ( pivotsize == 1 ) {
rc = Chv_r1upd(chv) ;
fprintf(msgFile,
"\n\n d = c(1,1) ;"
"\n l = c(2:nrow,1)/d ;"
"\n u = c(1,2:ncol) ;") ;
if ( nD > 1 ) {
fprintf(msgFile,
"\n c(2:nrow,2:ncol) = c(2:nrow,2:ncol) - l*u ;") ;
}
fprintf(msgFile,
"\n u = u / d ;"
"\n c(1:1,1:1) = d ; "
"\n c(1:1,2:ncol) = u ; "
"\n c(2:ncol,1:1) = l ; ") ;
fprintf(msgFile, "\n c(nD+1:nrow,nD+1:ncol) = 0 ;") ;
} else {
rc = Chv_r2upd(chv) ;
fprintf(msgFile,
"\n\n d = c(1:2,1:2) ;"
"\n l = c(3:nrow,1:2) / d ;"
"\n u = c(1:2,3:ncol) ;") ;
if ( nD > 2 ) {
fprintf(msgFile,
"\n c(3:nrow,3:ncol) = c(3:nrow,3:ncol) - l*u ;") ;
}
fprintf(msgFile,
"\n u = d \\ u ; "
"\n c(1:2,1:2) = d ; "
"\n c(1:2,3:ncol) = u ; "
"\n c(3:ncol,1:2) = l ; ") ;
if ( nU > 0 ) {
fprintf(msgFile,
"\n c(nD+1:nrow,nD+1:ncol) = 0 ;") ;
}
}
fprintf(msgFile, "\n %% matrix entries after update") ;
Chv_writeForMatlab(chv, "f", msgFile) ;
fprintf(msgFile, "\n maxerrupd = norm(f - c)") ;
/*
------------------------------------------------------
check out the maximum magnitude of elements in l and u
------------------------------------------------------
*/
fprintf(msgFile, "\n ipvt = %d", ipvt + 1) ;
fprintf(msgFile, "\n jpvt = %d", jpvt + 1) ;
fprintf(msgFile, "\n pivotsize = %d", pivotsize) ;
fprintf(msgFile, "\n tau = %12.4e", tau) ;
if ( symflag < 2 ) {
fprintf(msgFile, "\n ubound = max(max(abs(u))) ") ;
} else {
fprintf(msgFile,
"\n lbound = max(max(abs(l))) "
"\n ubound = max(max(abs(u))) ") ;
}
/*
------------------------
free the working storage
------------------------
*/
Chv_free(chv) ;
Drand_free(drand) ;
DV_free(workDV) ;
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
Chv/drivers/test_maxabs.c 0100644 0002055 0007177 00000017206 06571267320 0016763 0 ustar 00cleve compmath 0000040 0000006 /* test_maxabs.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
----------------------------------------------------
test the Chv_maxabsInDiagonal(), Chv_maxabsInRow()
and Chv_maxabsInColumn() methods.
the program's output is a matlab file
to check correctness of the code.
created -- 98apr22, cca
----------------------------------------------------
*/
{
Chv *chv ;
double imag, maxval, real, t1, t2 ;
double *colmaxes, *entries, *rowmaxes ;
Drand *drand ;
FILE *msgFile ;
int icol, ii, irow, jcol, jrow, msglvl, ncol, nD, nent,
nL, nrow, nU, rc, seed, symflag, tag, type ;
int *colind, *colmark, *rowind, *rowmark ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nD nU type symflag seed "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nD -- # of rows and columns in the (1,1) block"
"\n nU -- # of columns in the (1,2) block"
"\n type -- entries type"
"\n 1 --> real"
"\n 2 --> complex"
"\n symflag -- symmetry flag"
"\n 0 --> symmetric"
"\n 1 --> hermitian"
"\n 2 --> nonsymmetric "
"\n seed -- random number seed"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
nD = atoi(argv[3]) ;
nU = atoi(argv[4]) ;
type = atoi(argv[5]) ;
symflag = atoi(argv[6]) ;
seed = atoi(argv[7]) ;
fprintf(msgFile, "\n %% testChv:"
"\n %% msglvl = %d"
"\n %% msgFile = %s"
"\n %% nD = %d"
"\n %% nU = %d"
"\n %% type = %d"
"\n %% symflag = %d"
"\n %% seed = %d",
msglvl, argv[2], nD, nU, type, symflag, seed) ;
nL = nU ;
nrow = nD + nL ;
ncol = nD + nU ;
/*
-----------------------------
check for errors in the input
-----------------------------
*/
if ( nD <= 0 || nL < 0 || nU < 0
|| symflag < 0 || symflag > 3 ) {
fprintf(stderr, "\n invalid input"
"\n nD = %d, nL = %d, nU = %d, symflag = %d\n",
nD, nL, nU, symflag) ;
exit(-1) ;
}
fprintf(msgFile,
"\n nD = %d ;"
"\n nL = %d ;"
"\n nU = %d ;"
"\n nrow = nD + nL ;"
"\n ncol = nD + nU ;",
nD, nL, nU) ;
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setSeed(drand, seed) ;
Drand_setNormal(drand, 0.0, 1.0) ;
/*
----------------------------
initialize the Chv object
----------------------------
*/
MARKTIME(t1) ;
chv = Chv_new() ;
Chv_init(chv, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize chv object",
t2 - t1) ;
fflush(msgFile) ;
Chv_columnIndices(chv, &ncol, &colind) ;
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chv) ) {
Chv_rowIndices(chv, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
/*
------------------------------------
load the entries with random entries
------------------------------------
*/
nent = Chv_nent(chv) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
Drand_fillDvector(drand, nent, entries) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
Drand_fillDvector(drand, 2*nent, entries) ;
}
if ( CHV_IS_HERMITIAN(chv) ) {
/*
---------------------------------------------------------
hermitian example, set imaginary part of diagonal to zero
---------------------------------------------------------
*/
for ( irow = 0 ; irow < nD ; irow++ ) {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
Chv_setComplexEntry(chv, irow, irow, real, 0.0) ;
}
}
fprintf(msgFile, "\n %% matrix entries") ;
Chv_writeForMatlab(chv, "a", msgFile) ;
/*
-----------------------------
find the row and column maxes
-----------------------------
*/
rowmaxes = DVinit(nrow, 0.0) ;
colmaxes = DVinit(nrow, 0.0) ;
for ( irow = 0 ; irow < nD ; irow++ ) {
jcol = Chv_maxabsInRow(chv, irow, &maxval) ;
rowmaxes[irow] = maxval ;
}
for ( jcol = 0 ; jcol < nD ; jcol++ ) {
irow = Chv_maxabsInColumn(chv, jcol, &maxval) ;
colmaxes[jcol] = maxval ;
}
fprintf(msgFile, "\n\n rowmaxes = [ ...") ;
for ( irow = 0 ; irow < nD ; irow++ ) {
fprintf(msgFile, "\n %20.12e", rowmaxes[irow]) ;
}
fprintf(msgFile, " ] ;") ;
fprintf(msgFile, "\n\n colmaxes = [ ...") ;
for ( jcol = 0 ; jcol < nD ; jcol++ ) {
fprintf(msgFile, "\n %20.12e", colmaxes[jcol]) ;
}
fprintf(msgFile, " ] ;") ;
/*
-----------------
check with matlab
-----------------
*/
fprintf(msgFile,
"\n\n for irow = 1:nD"
"\n maxval = max(abs(a(irow,:))) ;"
"\n rmaxes(irow) = maxval ;"
"\nend"
"\nrowerror = norm(rmaxes' - rowmaxes) "
"\nfor jcol = 1:nD"
"\n maxval = max(abs(a(:,jcol))) ;"
"\n cmaxes(jcol) = maxval ;"
"\nend"
"\ncolerror = norm(cmaxes' - colmaxes) ") ;
/*
-----------------------------------------------------
find the row and column maxes of just the (1,1) block
-----------------------------------------------------
*/
rowmark = IVinit(nD, -1) ;
colmark = IVinit(nD, -1) ;
tag = -1 ;
for ( irow = 0 ; irow < nD ; irow++ ) {
jcol = Chv_maxabsInRow11(chv, irow, colmark, tag, &maxval) ;
rowmaxes[irow] = maxval ;
}
for ( jcol = 0 ; jcol < nD ; jcol++ ) {
irow = Chv_maxabsInColumn11(chv, jcol, rowmark, tag, &maxval) ;
colmaxes[jcol] = maxval ;
}
fprintf(msgFile, "\n\n rowmaxes = [ ...") ;
for ( irow = 0 ; irow < nD ; irow++ ) {
fprintf(msgFile, "\n %20.12e", rowmaxes[irow]) ;
}
fprintf(msgFile, " ] ;") ;
fprintf(msgFile, "\n\n colmaxes = [ ...") ;
for ( jcol = 0 ; jcol < nD ; jcol++ ) {
fprintf(msgFile, "\n %20.12e", colmaxes[jcol]) ;
}
fprintf(msgFile, " ] ;") ;
/*
-----------------
check with matlab
-----------------
*/
fprintf(msgFile,
"\n\n for irow = 1:nD"
"\n maxval = max(abs(a(irow,1:nD))) ;"
"\n rmaxes(irow) = maxval ;"
"\nend"
"\nrow11error = norm(rmaxes' - rowmaxes) "
"\nfor jcol = 1:nD"
"\n maxval = max(abs(a(1:nD,jcol))) ;"
"\n cmaxes(jcol) = maxval ;"
"\nend"
"\ncol11error = norm(cmaxes' - colmaxes) ") ;
/*
---------------------------------------------
find the diagonal max of just the (1,1) block
---------------------------------------------
*/
jcol = Chv_maxabsInDiagonal11(chv, colmark, tag, &maxval) ;
fprintf(msgFile, "\n\n maxval = %20.12e ;", maxval) ;
/*
-----------------
check with matlab
-----------------
*/
fprintf(msgFile,
"\n\n maxabs = abs(a(1,1)) ;"
"\nfor irow = 2:nD"
"\n val = abs(a(irow,irow)) ;"
"\n if maxabs < val"
"\n maxabs = val ;"
"\n end "
"\nend"
"\ndiag11error = abs(maxabs - maxval)") ;
fprintf(msgFile,
"\n [ rowerror colerror row11error col11error diag11error]") ;
/*
------------------------
free the working storage
------------------------
*/
Chv_free(chv) ;
Drand_free(drand) ;
DVfree(rowmaxes) ;
DVfree(colmaxes) ;
IVfree(rowmark) ;
IVfree(colmark) ;
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
Chv/drivers/test_r1upd.c 0100644 0002055 0007177 00000012104 06571267320 0016533 0 ustar 00cleve compmath 0000040 0000006 /* test_r1upd.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------
test the Chv_r1upd() method.
the program's output is a matlab file
to check correctness of the code.
created -- 98apr30, cca
-------------------------------------
*/
{
Chv *chv ;
double imag, real, t1, t2 ;
double *entries ;
Drand *drand ;
FILE *msgFile ;
int ii, irow, jcol, msglvl, ncol, nD, nent, nL, nrow, nU,
rc, seed, symflag, tag, type ;
int *colind, *rowind ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nD nU type symflag seed "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nD -- # of rows and columns in the (1,1) block"
"\n nU -- # of columns in the (1,2) block"
"\n type -- entries type"
"\n 1 --> real"
"\n 2 --> complex"
"\n symflag -- symmetry flag"
"\n 0 --> hermitian"
"\n 1 --> symmetric"
"\n 2 --> nonsymmetric "
"\n seed -- random number seed"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
nD = atoi(argv[3]) ;
nU = atoi(argv[4]) ;
type = atoi(argv[5]) ;
symflag = atoi(argv[6]) ;
seed = atoi(argv[7]) ;
fprintf(msgFile, "\n %% testChv:"
"\n %% msglvl = %d"
"\n %% msgFile = %s"
"\n %% nD = %d"
"\n %% nU = %d"
"\n %% type = %d"
"\n %% symflag = %d"
"\n %% seed = %d",
msglvl, argv[2], nD, nU, type, symflag, seed) ;
nL = nU ;
/*
-----------------------------
check for errors in the input
-----------------------------
*/
if ( nD <= 0 || nL < 0 || nU < 0
|| symflag < 0 || symflag > 3 ) {
fprintf(stderr, "\n invalid input"
"\n nD = %d, nL = %d, nU = %d, symflag = %d\n",
nD, nL, nU, symflag) ;
exit(-1) ;
}
if ( symflag <= 2 && nL != nU ) {
fprintf(stderr, "\n invalid input"
"\n symflag = %d, nL = %d, nU = %d", symflag, nL, nU) ;
exit(-1) ;
}
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setSeed(drand, seed) ;
Drand_setNormal(drand, 0.0, 1.0) ;
/*
----------------------------
initialize the Chv object
----------------------------
*/
MARKTIME(t1) ;
chv = Chv_new() ;
Chv_init(chv, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize chv object",
t2 - t1) ;
fflush(msgFile) ;
Chv_columnIndices(chv, &ncol, &colind) ;
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chv) ) {
Chv_rowIndices(chv, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
/*
------------------------------------
load the entries with random entries
------------------------------------
*/
nent = Chv_nent(chv) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
Drand_fillDvector(drand, nent, entries) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
Drand_fillDvector(drand, 2*nent, entries) ;
}
if ( CHV_IS_HERMITIAN(chv) ) {
for ( irow = 0 ; irow < nD ; irow++ ) {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
Chv_setComplexEntry(chv, irow, irow, real, 0.0) ;
}
}
fprintf(msgFile, "\n %% matrix entries") ;
Chv_writeForMatlab(chv, "a", msgFile) ;
/*
---------------------------------------
write out matlab code for rank-1 update
---------------------------------------
*/
fprintf(msgFile,
"\n nD = %d ;"
"\n nL = %d ;"
"\n nU = %d ;"
"\n nrow = nD + nL ;"
"\n ncol = nD + nU ;"
"\n b = a ; "
"\n d = a(1,1) ;"
"\n l = a(2:nrow,1) / d ; "
"\n u = a(1,2:ncol) ; "
"\n b(2:nrow,2:ncol) = a(2:nrow,2:ncol) - l * u ; "
"\n u = u / d ; "
"\n b(1,1) = d ; "
"\n b(1,2:ncol) = u ; "
"\n b(2:nrow,1) = l ; ",
nD, nL, nU) ;
if ( nL > 0 && nU > 0 ) {
fprintf(msgFile, "\n b(nD+1:nrow,nD+1:ncol) = 0.0 ;") ;
}
/*
-------------------------
perform the rank-1 update
-------------------------
*/
rc = Chv_r1upd(chv) ;
/*
fprintf(msgFile, "\n raw entries vector") ;
DVfprintf(msgFile, 2*nent, entries) ;
*/
fprintf(msgFile, "\n %% matrix entries after update") ;
Chv_writeForMatlab(chv, "c", msgFile) ;
fprintf(msgFile, "\n maxerr = max(max(abs(c-b)))") ;
/*
------------------------
free the working storage
------------------------
*/
Chv_free(chv) ;
Drand_free(drand) ;
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
nt, nL, nrow, nU,
rc, seed, symflag, tag, type ;
int *colind, *rowind ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nD nU type symflag seed "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nD -- # of rows and columns in the (1,1) block"
"\n nU -- # of columns in the (1,2) block"
"\n type --Chv/drivers/test_r2upd.c 0100644 0002055 0007177 00000012224 06571267320 0016537 0 ustar 00cleve compmath 0000040 0000006 /* test_r2upd.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------
test the Chv_r2upd() method.
the program's output is a matlab file
to check correctness of the code.
created -- 98jan23, cca
-------------------------------------
*/
{
Chv *chv ;
double imag, real, t1, t2 ;
double *entries ;
Drand *drand ;
FILE *msgFile ;
int ii, irow, jcol, msglvl, ncol, nD, nent, nL, nrow, nU,
rc, seed, symflag, tag, type ;
int *colind, *rowind ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nD nU symflag seed "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nD -- # of rows and columns in the (1,1) block"
"\n nU -- # of columns in the (1,2) block"
"\n type -- entries type"
"\n 1 --> real"
"\n 2 --> complex"
"\n symflag -- symmetry flag"
"\n 0 --> hermitian"
"\n 1 --> symmetric"
"\n seed -- random number seed"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
nD = atoi(argv[3]) ;
nU = atoi(argv[4]) ;
type = atoi(argv[5]) ;
symflag = atoi(argv[6]) ;
seed = atoi(argv[7]) ;
fprintf(msgFile, "\n %% testChv:"
"\n %% msglvl = %d"
"\n %% msgFile = %s"
"\n %% nD = %d"
"\n %% nU = %d"
"\n %% type = %d"
"\n %% symflag = %d"
"\n %% seed = %d",
msglvl, argv[2], nD, nU, type, symflag, seed) ;
nL = nU ;
/*
-----------------------------
check for errors in the input
-----------------------------
*/
if ( nD <= 0 || nL < 0 || nU < 0
|| (symflag != SPOOLES_SYMMETRIC && symflag != SPOOLES_HERMITIAN) ) {
fprintf(stderr, "\n invalid input"
"\n nD = %d, nL = %d, nU = %d, symflag = %d\n",
nD, nL, nU, symflag) ;
exit(-1) ;
}
if ( symflag <= 2 && nL != nU ) {
fprintf(stderr, "\n invalid input"
"\n symflag = %d, nL = %d, nU = %d", symflag, nL, nU) ;
exit(-1) ;
}
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setSeed(drand, seed) ;
Drand_setNormal(drand, 0.0, 1.0) ;
/*
----------------------------
initialize the Chv object
----------------------------
*/
MARKTIME(t1) ;
chv = Chv_new() ;
Chv_init(chv, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize chv object",
t2 - t1) ;
fflush(msgFile) ;
Chv_columnIndices(chv, &ncol, &colind) ;
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chv) ) {
Chv_rowIndices(chv, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
/*
------------------------------------
load the entries with random entries
------------------------------------
*/
nent = Chv_nent(chv) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
Drand_fillDvector(drand, nent, entries) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
Drand_fillDvector(drand, 2*nent, entries) ;
}
/*
fprintf(msgFile, "\n raw entries vector") ;
DVfprintf(msgFile, 2*nent, entries) ;
*/
if ( CHV_IS_HERMITIAN(chv) ) {
for ( irow = 0 ; irow < nD ; irow++ ) {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
Chv_setComplexEntry(chv, irow, irow, real, 0.0) ;
}
}
fprintf(msgFile, "\n %% matrix entries") ;
Chv_writeForMatlab(chv, "a", msgFile) ;
/*
---------------------------------------
write out matlab code for rank-2 update
---------------------------------------
*/
fprintf(msgFile,
"\n nD = %d ;"
"\n nL = %d ;"
"\n nU = %d ;"
"\n nrow = nD + nL ;"
"\n ncol = nD + nU ;"
"\n b = a ; "
"\n d = a(1:2,1:2) ;"
"\n l = a(3:nrow,1:2) * inv(d) ; "
"\n u = inv(d)*a(1:2,3:ncol) ; "
"\n b(3:nrow,3:ncol) = a(3:nrow,3:ncol) - l * d * u ; "
"\n b(1:2,1:2) = d ; "
"\n b(1:2,3:ncol) = u ; "
"\n b(3:nrow,1:2) = l ; ",
nD, nL, nU) ;
if ( nL > 0 && nU > 0 ) {
fprintf(msgFile, "\n b(nD+1:nrow,nD+1:ncol) = 0.0 ;") ;
}
/*
-------------------------
perform the rank-2 update
-------------------------
*/
rc = Chv_r2upd(chv) ;
/*
fprintf(msgFile, "\n raw entries vector") ;
DVfprintf(msgFile, 2*nent, entries) ;
*/
fprintf(msgFile, "\n %% matrix entries after update") ;
Chv_writeForMatlab(chv, "c", msgFile) ;
fprintf(msgFile, "\n maxerr = max(max(abs(c-b)))") ;
/*
------------------------
free the working storage
------------------------
*/
Chv_free(chv) ;
Drand_free(drand) ;
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
Chv/drivers/test_swap.c 0100644 0002055 0007177 00000020167 06571267317 0016470 0 ustar 00cleve compmath 0000040 0000006 /* test_swap.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
------------------------------------------------
test the Chv_swapRows(), Chv_swapColumns() and
Chv_swapRowsAndColumns() methods.
the program's output is a matlab file
to check correctness of the code.
created -- 98apr18, cca
------------------------------------------------
*/
{
Chv *chv ;
double imag, real, t1, t2 ;
double *entries ;
Drand *drand ;
FILE *msgFile ;
int icol, ii, irow, jcol, jrow, msglvl, ncol, nD, nent,
nL, nrow, nU, rc, seed, symflag, tag, type ;
int *colind, *rowind ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile nD nU type symflag seed "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n nD -- # of rows and columns in the (1,1) block"
"\n nU -- # of columns in the (1,2) block"
"\n type -- entries type"
"\n 1 --> real"
"\n 2 --> complex"
"\n symflag -- symmetry flag"
"\n 0 --> symmetric"
"\n 1 --> hermitian"
"\n 2 --> nonsymmetric"
"\n seed -- random number seed"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
nD = atoi(argv[3]) ;
nU = atoi(argv[4]) ;
type = atoi(argv[5]) ;
symflag = atoi(argv[6]) ;
seed = atoi(argv[7]) ;
fprintf(msgFile, "\n %% testChv:"
"\n %% msglvl = %d"
"\n %% msgFile = %s"
"\n %% nD = %d"
"\n %% nU = %d"
"\n %% type = %d"
"\n %% symflag = %d"
"\n %% seed = %d",
msglvl, argv[2], nD, nU, type, symflag, seed) ;
nL = nU ;
nrow = nD + nL ;
ncol = nD + nU ;
/*
-----------------------------
check for errors in the input
-----------------------------
*/
if ( nD <= 0 || nL < 0 || nU < 0
|| !(type == SPOOLES_REAL || type == SPOOLES_COMPLEX)
|| !(symflag == SPOOLES_SYMMETRIC
|| symflag == SPOOLES_HERMITIAN
|| symflag == SPOOLES_NONSYMMETRIC) ) {
fprintf(stderr, "\n invalid input"
"\n nD = %d, nL = %d, nU = %d, type = %d, symflag = %d\n",
nD, nL, nU, type, symflag) ;
exit(-1) ;
}
fprintf(msgFile,
"\n nD = %d ;"
"\n nL = %d ;"
"\n nU = %d ;"
"\n nrow = nD + nL ;"
"\n ncol = nD + nU ;",
nD, nL, nU) ;
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setSeed(drand, seed) ;
Drand_setNormal(drand, 0.0, 1.0) ;
/*
--------------------------
initialize the Chv object
--------------------------
*/
MARKTIME(t1) ;
chv = Chv_new() ;
Chv_init(chv, 0, nD, nL, nU, type, symflag) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize chv object",
t2 - t1) ;
fflush(msgFile) ;
Chv_columnIndices(chv, &ncol, &colind) ;
IVramp(ncol, colind, 0, 1) ;
if ( CHV_IS_NONSYMMETRIC(chv) ) {
Chv_rowIndices(chv, &nrow, &rowind) ;
IVramp(nrow, rowind, 0, 1) ;
}
/*
------------------------------------
load the entries with random entries
------------------------------------
*/
nent = Chv_nent(chv) ;
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
Drand_fillDvector(drand, nent, entries) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
Drand_fillDvector(drand, 2*nent, entries) ;
}
if ( msglvl > 4 ) {
fprintf(msgFile, "\n raw entries vector") ;
if ( CHV_IS_REAL(chv) ) {
DVfprintf(msgFile, nent, entries) ;
} else if ( CHV_IS_COMPLEX(chv) ) {
DVfprintf(msgFile, 2*nent, entries) ;
}
fflush(msgFile) ;
}
if ( CHV_IS_COMPLEX(chv) && CHV_IS_HERMITIAN(chv) ) {
/*
---------------------------------------------------------
hermitian example, set imaginary part of diagonal to zero
---------------------------------------------------------
*/
for ( irow = 0 ; irow < nD ; irow++ ) {
Chv_complexEntry(chv, irow, irow, &real, &imag) ;
fprintf(msgFile, "\n %% setting a_{%d,%d} = %20.12e ;",
irow, irow, real) ;
Chv_setComplexEntry(chv, irow, irow, real, 0.0) ;
}
}
fprintf(msgFile, "\n %% matrix entries") ;
Chv_writeForMatlab(chv, "a", msgFile) ;
if ( CHV_IS_NONSYMMETRIC(chv) ) {
/*
---------------------------
choose the two rows to swap
---------------------------
*/
Drand_setUniform(drand, 0.0, nD) ;
irow = Drand_value(drand) ;
jrow = Drand_value(drand) ;
while ( jrow == irow ) {
jrow = Drand_value(drand) ;
}
if ( irow < 0 || irow >= nD || jrow < 0 || jrow >= nD ) {
fprintf(stderr, "\n fatal error, irow = %d, jrow = %d\n",
irow, jrow) ;
exit(-1) ;
}
fprintf(msgFile, "\n %% swapping rows %d and %d", irow+1, jrow+1) ;
fprintf(msgFile,
"\n irow = %d ;"
"\n jrow = %d ;"
"\n b = a ;"
"\n b(irow,:) = a(jrow,:) ;"
"\n b(jrow,:) = a(irow,:) ;",
irow+1, jrow+1) ;
fflush(msgFile) ;
Chv_swapRows(chv, irow, jrow) ;
fprintf(msgFile, "\n %% matrix entries") ;
Chv_writeForMatlab(chv, "c", msgFile) ;
fprintf(msgFile, "\n maxerrrowswap1 = norm(c - a)") ;
/*
------------------------------
choose the two columns to swap
------------------------------
*/
Drand_setUniform(drand, 0.0, nD) ;
icol = Drand_value(drand) ;
jcol = Drand_value(drand) ;
while ( jcol == icol ) {
jcol = Drand_value(drand) ;
}
if ( icol < 0 || icol >= nD || jcol < 0 || jcol >= nD ) {
fprintf(stderr, "\n fatal error, icol = %d, jcol = %d\n",
icol, jrow) ;
exit(-1) ;
}
fprintf(msgFile,
"\n %% swapping columns %d and %d", icol+1, jcol+1) ;
fprintf(msgFile,
"\n icol = %d ;"
"\n jcol = %d ;"
"\n c = b ;"
"\n c(:,icol) = b(:,jcol) ;"
"\n c(:,jcol) = b(:,icol) ;",
icol+1, jcol+1) ;
fflush(msgFile) ;
Chv_swapColumns(chv, icol, jcol) ;
fprintf(msgFile, "\n %% matrix entries") ;
Chv_writeForMatlab(chv, "d", msgFile) ;
fprintf(msgFile, "\n maxerrcolswap1 = norm(d - a)") ;
IVramp(ncol, colind, 0, 1) ;
IVramp(nrow, rowind, 0, 1) ;
Chv_writeForMatlab(chv, "e", msgFile) ;
fprintf(msgFile, "\n maxerrswap = norm(e - c)") ;
} else {
/*
---------------------------------------
choose the two rows and columns to swap
---------------------------------------
*/
Drand_setUniform(drand, 0.0, nD) ;
irow = Drand_value(drand) ;
jrow = Drand_value(drand) ;
while ( jrow == irow ) {
jrow = Drand_value(drand) ;
}
if ( irow < 0 || irow >= nD || jrow < 0 || jrow >= nD ) {
fprintf(stderr, "\n fatal error, irow = %d, jrow = %d\n",
irow, jrow) ;
exit(-1) ;
}
fprintf(msgFile,
"\n %% swapping rows and columns %d and %d", irow+1, jrow+1) ;
fprintf(msgFile,
"\n irow = %d ;"
"\n jrow = %d ;"
"\n b = a ;"
"\n b(irow,:) = a(jrow,:) ;"
"\n b(jrow,:) = a(irow,:) ;"
"\n c = b ;"
"\n c(:,irow) = b(:,jrow) ;"
"\n c(:,jrow) = b(:,irow) ;",
irow+1, jrow+1) ;
fflush(msgFile) ;
Chv_swapRowsAndColumns(chv, irow, jrow) ;
fprintf(msgFile, "\n %% matrix entries") ;
Chv_writeForMatlab(chv, "d", msgFile) ;
fprintf(msgFile, "\n maxerrsymswap1 = norm(d - a)") ;
IVramp(ncol, colind, 0, 1) ;
Chv_writeForMatlab(chv, "e", msgFile) ;
fprintf(msgFile, "\n maxerrsymswap2 = norm(e - c)") ;
}
/*
------------------------
free the working storage
------------------------
*/
Chv_free(chv) ;
Drand_free(drand) ;
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
Chv/drivers/test_update.c 0100644 0002055 0007177 00000025070 06571267317 0016776 0 ustar 00cleve compmath 0000040 0000006 /* test_factorupd.c */
#include "../Chv.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------
test the Chv_update{H,S,N}() methods.
T := T - U^T * D * U
T := T - U^H * D * U
T := T - L * D * U
created -- 98apr23, cca
-------------------------------------
*/
{
Chv *chvT ;
SubMtx *mtxD, *mtxL, *mtxU ;
double imag, ops, real, t1, t2 ;
Drand *drand ;
DV *tempDV ;
FILE *msgFile ;
int irow, msglvl, ncolT, nDT, ncolU, nentT, nentU, nrowD,
nrowL, nrowT, offset, seed, size, sparsityflag, symflag, type ;
int *colindT, *colindU, *ivec, *rowindL, *rowindT ;
if ( argc != 13 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile type symflag sparsityflag"
"\n ncolT ncolU nrowD nentU offset seed"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n type -- entries type"
"\n 1 -- real"
"\n 2 -- complex"
"\n symflag -- type of matrix U"
"\n 0 -- symmetric"
"\n 1 -- hermitian"
"\n 2 -- nonsymmetric"
"\n sparsityflag -- dense or sparse"
"\n 0 -- dense"
"\n 1 -- sparse"
"\n ncolT -- # of rows and columns in matrix T"
"\n nDT -- # of internal rows and columns in matrix T"
"\n ncolU -- # of rows and columns in matrix U"
"\n nrowD -- # of rows and columns in matrix D"
"\n nentU -- # of entries in matrix U"
"\n offset -- distance between D_I and T"
"\n seed -- random number seed"
"\n", argv[0]) ;
return(0) ;
}
if ( (msglvl = atoi(argv[1])) < 0 ) {
fprintf(stderr, "\n message level must be positive\n") ;
exit(-1) ;
}
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[2]) ;
return(-1) ;
}
type = atoi(argv[3]) ;
symflag = atoi(argv[4]) ;
sparsityflag = atoi(argv[5]) ;
ncolT = atoi(argv[6]) ;
nDT = atoi(argv[7]) ;
ncolU = atoi(argv[8]) ;
nrowD = atoi(argv[9]) ;
nentU = atoi(argv[10]) ;
offset = atoi(argv[11]) ;
seed = atoi(argv[12]) ;
fprintf(msgFile, "\n %% %s:"
"\n %% msglvl = %d"
"\n %% msgFile = %s"
"\n %% type = %d"
"\n %% symflag = %d"
"\n %% sparsityflag = %d"
"\n %% ncolT = %d"
"\n %% nDT = %d"
"\n %% ncolU = %d"
"\n %% nrowD = %d"
"\n %% nentU = %d"
"\n %% offset = %d"
"\n %% seed = %d",
argv[0], msglvl, argv[2], type, symflag, sparsityflag,
ncolT, nDT, ncolU, nrowD, nentU, offset, seed) ;
/*
-----------------------------
check for errors in the input
-----------------------------
*/
if ( (type != SPOOLES_REAL
&& type != SPOOLES_COMPLEX)
|| (symflag != SPOOLES_SYMMETRIC
&& symflag != SPOOLES_HERMITIAN
&& symflag != SPOOLES_NONSYMMETRIC)
|| (sparsityflag < 0 || sparsityflag > 1)
|| ncolT <= 0 || ncolU > (ncolT + offset) || nrowD <= 0 ) {
fprintf(stderr, "\n invalid input\n") ;
exit(-1) ;
}
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new() ;
Drand_init(drand) ;
Drand_setSeed(drand, ++seed) ;
Drand_setNormal(drand, 0.0, 1.0) ;
/*
-----------------------
get a vector of indices
-----------------------
*/
size = nrowD + offset + ncolT ;
ivec = IVinit(size, -1) ;
IVramp(size, ivec, 0, 1) ;
/*
----------------------------
initialize the T Chv object
----------------------------
*/
fprintf(msgFile, "\n\n %% symflag = %d", symflag) ;
MARKTIME(t1) ;
chvT = Chv_new() ;
Chv_init(chvT, 0, nDT, ncolT - nDT, ncolT - nDT, type, symflag) ;
nentT = Chv_nent(chvT) ;
if ( CHV_IS_REAL(chvT) ) {
Drand_fillDvector(drand, nentT, Chv_entries(chvT)) ;
} else if ( CHV_IS_COMPLEX(chvT) ) {
Drand_fillDvector(drand, 2*nentT, Chv_entries(chvT)) ;
}
Chv_columnIndices(chvT, &ncolT, &colindT) ;
IVcopy(ncolT, colindT, ivec + nrowD + offset) ;
if ( CHV_IS_NONSYMMETRIC(chvT) ) {
Chv_rowIndices(chvT, &nrowT, &rowindT) ;
IVcopy(nrowT, rowindT, colindT) ;
}
IVfree(ivec) ;
if ( CHV_IS_HERMITIAN(chvT) ) {
fprintf(msgFile, "\n\n %% hermitian\n") ;
/*
---------------------------------------------------------
hermitian example, set imaginary part of diagonal to zero
---------------------------------------------------------
*/
for ( irow = 0 ; irow < nDT ; irow++ ) {
Chv_complexEntry(chvT, irow, irow, &real, &imag) ;
Chv_setComplexEntry(chvT, irow, irow, real, 0.0) ;
}
}
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize chvT Chv object",
t2 - t1) ;
fprintf(msgFile, "\n T = zeros(%d,%d); ", size, size) ;
Chv_writeForMatlab(chvT, "T", msgFile) ;
/*
---------------------------
initialize the D Mtx object
---------------------------
*/
MARKTIME(t1) ;
mtxD = SubMtx_new() ;
if ( CHV_IS_REAL(chvT) ) {
if ( CHV_IS_SYMMETRIC(chvT) ) {
SubMtx_initRandom(mtxD, SPOOLES_REAL, SUBMTX_BLOCK_DIAGONAL_SYM,
0, 0, nrowD, nrowD, nrowD*nrowD, ++seed) ;
} else {
SubMtx_initRandom(mtxD, SPOOLES_REAL, SUBMTX_DIAGONAL,
0, 0, nrowD, nrowD, nrowD*nrowD, ++seed) ;
}
} else if ( CHV_IS_COMPLEX(chvT) ) {
if ( CHV_IS_HERMITIAN(chvT) ) {
SubMtx_initRandom(mtxD,SPOOLES_COMPLEX,SUBMTX_BLOCK_DIAGONAL_HERM,
0, 0, nrowD, nrowD, nrowD*nrowD, ++seed) ;
} else if ( CHV_IS_SYMMETRIC(chvT) ) {
SubMtx_initRandom(mtxD,SPOOLES_COMPLEX, SUBMTX_BLOCK_DIAGONAL_SYM,
0, 0, nrowD, nrowD, nrowD*nrowD, ++seed) ;
} else {
SubMtx_initRandom(mtxD, SPOOLES_COMPLEX, SUBMTX_DIAGONAL,
0, 0, nrowD, nrowD, nrowD*nrowD, ++seed) ;
}
}
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize D SubMtx object",
t2 - t1) ;
fprintf(msgFile, "\n D = zeros(%d,%d) ;", nrowD, nrowD) ;
SubMtx_writeForMatlab(mtxD, "D", msgFile) ;
/*
----------------------------
initialize the U SubMtx object
----------------------------
*/
MARKTIME(t1) ;
mtxU = SubMtx_new() ;
if ( CHV_IS_REAL(chvT) ) {
if ( sparsityflag == 0 ) {
SubMtx_initRandom(mtxU, SPOOLES_REAL, SUBMTX_DENSE_COLUMNS,
0, 0, nrowD, ncolU, nentU, ++seed) ;
} else {
SubMtx_initRandom(mtxU, SPOOLES_REAL, SUBMTX_SPARSE_COLUMNS,
0, 0, nrowD, ncolU, nentU, ++seed) ;
}
} else if ( CHV_IS_COMPLEX(chvT) ) {
if ( sparsityflag == 0 ) {
SubMtx_initRandom(mtxU, SPOOLES_COMPLEX, SUBMTX_DENSE_COLUMNS,
0, 0, nrowD, ncolU, nentU, ++seed) ;
} else {
SubMtx_initRandom(mtxU, SPOOLES_COMPLEX, SUBMTX_SPARSE_COLUMNS,
0, 0, nrowD, ncolU, nentU, ++seed) ;
}
}
ivec = IVinit(offset + ncolT, -1) ;
IVramp(offset + ncolT, ivec, nrowD, 1) ;
IVshuffle(offset + ncolT, ivec, ++seed) ;
SubMtx_columnIndices(mtxU, &ncolU, &colindU) ;
IVcopy(ncolU, colindU, ivec) ;
IVqsortUp(ncolU, colindU) ;
IVfree(ivec) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize U SubMtx object",
t2 - t1) ;
fprintf(msgFile, "\n U = zeros(%d,%d) ;", nrowD, size) ;
SubMtx_writeForMatlab(mtxU, "U", msgFile) ;
if ( CHV_IS_NONSYMMETRIC(chvT) ) {
/*
----------------------------
initialize the L SubMtx object
----------------------------
*/
MARKTIME(t1) ;
mtxL = SubMtx_new() ;
if ( CHV_IS_REAL(chvT) ) {
if ( sparsityflag == 0 ) {
SubMtx_initRandom(mtxL, SPOOLES_REAL, SUBMTX_DENSE_ROWS,
0, 0, ncolU, nrowD, nentU, ++seed) ;
} else {
SubMtx_initRandom(mtxL, SPOOLES_REAL, SUBMTX_SPARSE_ROWS,
0, 0, ncolU, nrowD, nentU, ++seed) ;
}
} else if ( CHV_IS_COMPLEX(chvT) ) {
if ( sparsityflag == 0 ) {
SubMtx_initRandom(mtxL, SPOOLES_COMPLEX, SUBMTX_DENSE_ROWS,
0, 0, ncolU, nrowD, nentU, ++seed) ;
} else {
SubMtx_initRandom(mtxL, SPOOLES_COMPLEX, SUBMTX_SPARSE_ROWS,
0, 0, ncolU, nrowD, nentU, ++seed) ;
}
}
SubMtx_rowIndices(mtxL, &nrowL, &rowindL) ;
IVcopy(nrowL, rowindL, colindU) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to initialize L SubMtx object",
t2 - t1) ;
fprintf(msgFile, "\n L = zeros(%d,%d) ;", size, nrowD) ;
SubMtx_writeForMatlab(mtxL, "L", msgFile) ;
} else {
mtxL = NULL ;
}
/*
--------------------------------
compute the matrix-matrix update
--------------------------------
*/
tempDV = DV_new() ;
ops = 8*nrowD*nrowD*ncolU ;
if ( CHV_IS_SYMMETRIC(chvT) ) {
Chv_updateS(chvT, mtxD, mtxU, tempDV) ;
} else if ( CHV_IS_HERMITIAN(chvT) ) {
Chv_updateH(chvT, mtxD, mtxU, tempDV) ;
} else if ( CHV_IS_NONSYMMETRIC(chvT) ) {
Chv_updateN(chvT, mtxL, mtxD, mtxU, tempDV) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n %% CPU : %.3f to compute m-m, %.3f mflops",
t2 - t1, ops*1.e-6/(t2 - t1)) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n %% Z Chv object") ;
fprintf(msgFile, "\n Z = zeros(%d,%d); ", size, size) ;
Chv_writeForMatlab(chvT, "Z", msgFile) ;
fflush(msgFile) ;
}
/*
-----------------
check with matlab
-----------------
*/
if ( msglvl > 1 ) {
if ( CHV_IS_HERMITIAN(chvT) ) {
fprintf(msgFile, "\n\n B = ctranspose(U) * D * U ;") ;
} else if ( CHV_IS_SYMMETRIC(chvT) ) {
fprintf(msgFile, "\n\n B = transpose(U) * D * U ;") ;
} else {
fprintf(msgFile, "\n\n B = L * D * U ;") ;
}
fprintf(msgFile,
"\n\n for irow = 1:%d"
"\n for jcol = 1:%d"
"\n if T(irow,jcol) ~= 0.0"
"\n T(irow,jcol) = T(irow,jcol) - B(irow,jcol) ;"
"\n end"
"\n end"
"\n end"
"\n emtx = abs(Z - T) ;",
size, size) ;
fprintf(msgFile, "\n\n maxabs = max(max(emtx)) ") ;
fflush(msgFile) ;
}
/*
------------------------
free the working storage
------------------------
*/
if ( mtxL != NULL ) {
SubMtx_free(mtxL) ;
}
Chv_free(chvT) ;
SubMtx_free(mtxD) ;
SubMtx_free(mtxU) ;
DV_free(tempDV) ;
Drand_free(drand) ;
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
Chv/doc/ 0042755 0002055 0007177 00000000000 06650232144 0013365 5 ustar 00cleve compmath 0000040 0000006 Chv/doc/DChv.eps 0100644 0002055 0007177 00000003143 06571267315 0014730 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 500.0 440.0
%%%EndComments
/nD 10 def
/nL 12 def
/nU 15 def
/margin 0 def
/xscale 500 margin 2 mul sub nD nL add div def
/yscale 500 margin 2 mul sub nD nU add div def
xscale yscale le { % true action -- if else
/yscale xscale def
} { % false action -- if else
/xscale yscale def
} ifelse
(xscale) == xscale ==
(yscale) == yscale ==
margin margin 500 margin 2 mul sub 440 margin 2 mul sub rectstroke
gsave
%
% translate, scale and rotate
%
margin margin translate
xscale yscale scale
0.05 setlinewidth
0 nD nL add translate
-90 rotate
%
% draw the outlines of the three DA2 objects
%
0.0 setgray
0 0 nD nD rectstroke
nD 0 nL nD rectstroke
0 nD nD nU rectstroke
%
% draw the thick edges
%
0 1 nD 1 sub {
/ix exch def
newpath
ix 0.5 add ix 0.5 add moveto
0 nD nU add ix sub 1 sub rlineto
ix 0.5 add ix 0.5 add moveto
nD nL add ix sub 1 sub 0 rlineto
stroke
} for
%
% draw the circles that represent entries
%
/r 0.2 def
/x 0.5 def
0 1 nD 1 sub {
/y 0.5 def
0 1 nD nU add 1 sub {
newpath
1.0 setgray
pop x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
/x nD 0.5 add def
0 1 nL 1 sub {
/y 0.5 def
0 1 nD 1 sub {
pop
newpath
1.0 setgray
x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
stroke
grestore
showpage
U 15 def
/margin 0 def
/xscale 500 margin 2 mul sub nD nL add div def
/yscale 500 margin 2 mul sub nD nU add div def
xscale yscale le { % true action -- if else
/yscale xscale def
} { % false action -- if else
/xscale yscale def
} ifelse
(xscale) == xscale ==
(yscale) == yscale ==
margin margin 500 margin 2 mul sub 440 margin 2 mul sub rectstroke
gsave
%
% translate, scale and rotate
%
margin marginChv/doc/DChvsym.eps 0100644 0002055 0007177 00000003203 06571267315 0015456 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 500.0 200.0
%%%EndComments
/nD 10 def
/nL 12 def
/nL 0 def
/nU 15 def
/margin 0 def
/xscale 500 margin 2 mul sub nD nL add div def
/yscale 500 margin 2 mul sub nD nU add div def
xscale yscale le { % true action -- if else
/yscale xscale def
} { % false action -- if else
/xscale yscale def
} ifelse
(xscale) == xscale ==
(yscale) == yscale ==
margin margin 500 200 rectstroke
gsave
%
% translate, scale and rotate
%
margin margin translate
xscale yscale scale
0.05 setlinewidth
0 nD nL add translate
-90 rotate
%
% draw the outlines of the three DA2 objects
%
0.0 setgray
0 0 nD nD rectstroke
% nD 0 nL nD rectstroke
0 nD nD nU rectstroke
%
% draw the thick edges
%
0 1 nD 1 sub {
/ix exch def
newpath
ix 0.5 add ix 0.5 add moveto
0 nD nU add ix sub 1 sub rlineto
% ix 0.5 add ix 0.5 add moveto
% nD nL add ix sub 1 sub 0 rlineto
stroke
} for
%
% draw the circles that represent entries
%
/r 0.2 def
/x 0.5 def
0 1 nD 1 sub {
/ix exch def
/y x def
0 1 nD nU ix sub add 1 sub {
newpath
1.0 setgray
pop x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
% /x nD 0.5 add def
% 0 1 nL 1 sub {
% /y 0.5 def
% 0 1 nD 1 sub {
% pop
% newpath
% 1.0 setgray
% x r add y moveto x y r 0 360 arc
% fill
% newpath
% 0.0 setgray
% x r add y moveto x y r 0 360 arc
% stroke
% /y y 1 add def
% } for
% /x x 1 add def
% } for
stroke
grestore
showpage
Chv/doc/dataStructure.tex 0100644 0002055 0007177 00000003652 06571267315 0016754 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:Chv:dataStructure}
\par
\par
The {\tt Chv} structure has the following fields.
\begin{itemize}
\item
{\tt int id} : object's id, default value is {\tt -1}.
\item
{\tt int nD} : number of rows and columns in the (1,1) block
\item
{\tt int nL} : number of rows in the (2,1) block
\item
{\tt int nU} : number of columns in the (1,2) block
\item
{\tt int type} : type of entries
\begin{itemize}
\item {\tt SPOOLES\_REAL} $\Longrightarrow$ real entries
\item {\tt SPOOLES\_COMPLEX} $\Longrightarrow$ complex entries
\end{itemize}
\item
{\tt int symflag} : symmetry flag
\begin{itemize}
\item {\tt SPOOLES\_SYMMETRIC} $\Longrightarrow$
symmetric entries
\item {\tt SPOOLES\_HERMITIAN} $\Longrightarrow$
Hermitian entries
\item {\tt SPOOLES\_NONSYMMETRIC} $\Longrightarrow$
nonsymmetric entries
\end{itemize}
\item
{\tt int *rowind} :
pointer to the base address of the {\tt int} vector
that contains row indices.
\item
{\tt int *colind} :
pointer to the base address of the {\tt int} vector
that contains column indices.
\item
{\tt double *entries} :
pointer to the base address of the {\tt double} vector that
contains the entries.
\item
{\tt DV wrkDV} :
object that manages the owned working storage.
\item
{\tt Chv *next} :
link to a next object in a singly linked list.
\end{itemize}
\par
One can query the type and symmetry
of the object using these simple macros.
\begin{itemize}
\item
{\tt CHV\_IS\_REAL(chv)} is {\tt 1} if {\tt chv}
has real entries and {\tt 0} otherwise.
\item
{\tt CHV\_IS\_COMPLEX(chv)} is {\tt 1} if {\tt chv}
has complex entries and {\tt 0} otherwise.
\item
{\tt CHV\_IS\_SYMMETRIC(chv)} is {\tt 1} if {\tt chv}
is symmetric and {\tt 0} otherwise.
\item
{\tt CHV\_IS\_HERMITIAN(chv)} is {\tt 1} if {\tt chv}
is Hermitian and {\tt 0} otherwise.
\item
{\tt CHV\_IS\_NONSYMMETRIC(chv)} is {\tt 1} if {\tt chv}
is nonsymmetric and {\tt 0} otherwise.
\end{itemize}
Chv/doc/front.eps 0100644 0002055 0007177 00000006251 06571267315 0015237 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 500.0 500.0
%%%EndComments
/nD 10 def
/nL 15 def
/nU 12 def
/margin 50 def
/xscale 500 margin 2 mul sub nD nL add div def
/yscale 500 margin 2 mul sub nD nU add div def
xscale yscale le { % true action -- if else
/yscale xscale def
} { % false action -- if else
/xscale yscale def
} ifelse
(xscale) == xscale ==
(yscale) == yscale ==
% 50 50 400 400 rectstroke
gsave
%
% translate, scale and rotate
%
50 50 translate
xscale yscale scale
0.05 setlinewidth
0 nD nL add translate
-90 rotate
%
% draw the outlines of the three DA2 objects
%
0.0 setgray
0 0 nD nD rectstroke
nD 0 nL nD rectstroke
0 nD nD nU rectstroke
%
% draw the pivot elements
%
/x 0 def
/y 0 def
0 1 nD 1 sub {
pop x y 1 1 rectstroke
/x x 1 add def
/y y 1 add def
} for
%
% draw the solid edges for diagonal entries
%
currentlinewidth 2.0 mul setlinewidth
newpath
/x 0.5 def
/y 0.5 def
x y moveto
0 1 nD 2 sub {
pop 1 1 rlineto
} for
stroke
%
% draw the thick edges for L_{J,J}
%
2 1 nD 1 sub {
/ix exch def
newpath
ix 0.5 add 0.5 moveto
0 1 ix 2 sub {
/iy exch def
0.0 1.0 rlineto
} for
stroke
} for
%
% draw the thick edges for L_{bnd{J},J}
%
nD 1 nD nL add 1 sub {
/ix exch def
newpath
ix 0.5 add 0.5 moveto
0 1 nD 2 sub {
/iy exch def
0.0 1.0 rlineto
} for
stroke
} for
%
% draw the thin edges for L_{J,J} and L_{bnd{J},J}
%
currentlinewidth 0.5 mul setlinewidth
newpath
1.5 0.5 moveto
2 1 nD 1 sub {
/ix exch def
ix 0.5 add 0.5 lineto
ix 0.5 add ix 0.5 sub moveto
} for
stroke
newpath
nD 0.5 sub nD 1.5 sub moveto
nD 1 nD nL add 1 sub {
/ix exch def
ix 0.5 add 0.5 lineto
ix 0.5 add nD 0.5 sub moveto
} for
stroke
%
% draw the thick edges for U_{J,J}
%
currentlinewidth 2.0 mul setlinewidth
2 1 nD 1 sub {
/iy exch def
newpath
0.5 iy 0.5 add moveto
0 1 iy 2 sub {
/ix exch def
1.0 0.0 rlineto
} for
stroke
} for
%
% draw the thick edges for U_{bnd{J},J}
%
nD 1 nD nU add 1 sub {
/iy exch def
newpath
0.5 iy 0.5 add moveto
0 1 nD 2 sub {
/ix exch def
1.0 0.0 rlineto
} for
stroke
} for
%
% draw the thin edges for U_{J,J} and U_{bnd{J},J}
%
currentlinewidth 0.5 mul setlinewidth
newpath
0.5 1.5 moveto
2 1 nD 1 sub {
/iy exch def
0.5 iy 0.5 add lineto
iy 0.5 sub iy 0.5 add moveto
} for
stroke
newpath
nD 1.5 sub nD 0.5 sub moveto
nD 1 nD nU add 1 sub {
/iy exch def
0.5 iy 0.5 add lineto
nD 0.5 sub iy 0.5 add moveto
} for
stroke
%
% draw the circles that represent entries
%
/r 0.2 def
/x 0.5 def
0 1 nD 1 sub {
/y 0.5 def
0 1 nD nU add 1 sub {
newpath
1.0 setgray
pop x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
/x nD 0.5 add def
0 1 nL 1 sub {
/y 0.5 def
0 1 nD 1 sub {
pop
newpath
1.0 setgray
x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
stroke
grestore
Chv/doc/frontnonsym.eps 0100644 0002055 0007177 00000006251 06571267315 0016503 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 500.0 500.0
%%%EndComments
/nD 10 def
/nL 15 def
/nU 12 def
/margin 50 def
/xscale 500 margin 2 mul sub nD nL add div def
/yscale 500 margin 2 mul sub nD nU add div def
xscale yscale le { % true action -- if else
/yscale xscale def
} { % false action -- if else
/xscale yscale def
} ifelse
(xscale) == xscale ==
(yscale) == yscale ==
% 50 50 400 400 rectstroke
gsave
%
% translate, scale and rotate
%
50 50 translate
xscale yscale scale
0.05 setlinewidth
0 nD nL add translate
-90 rotate
%
% draw the outlines of the three DA2 objects
%
0.0 setgray
0 0 nD nD rectstroke
nD 0 nL nD rectstroke
0 nD nD nU rectstroke
%
% draw the pivot elements
%
/x 0 def
/y 0 def
0 1 nD 1 sub {
pop x y 1 1 rectstroke
/x x 1 add def
/y y 1 add def
} for
%
% draw the solid edges for diagonal entries
%
currentlinewidth 2.0 mul setlinewidth
newpath
/x 0.5 def
/y 0.5 def
x y moveto
0 1 nD 2 sub {
pop 1 1 rlineto
} for
stroke
%
% draw the thick edges for L_{J,J}
%
2 1 nD 1 sub {
/ix exch def
newpath
ix 0.5 add 0.5 moveto
0 1 ix 2 sub {
/iy exch def
0.0 1.0 rlineto
} for
stroke
} for
%
% draw the thick edges for L_{bnd{J},J}
%
nD 1 nD nL add 1 sub {
/ix exch def
newpath
ix 0.5 add 0.5 moveto
0 1 nD 2 sub {
/iy exch def
0.0 1.0 rlineto
} for
stroke
} for
%
% draw the thin edges for L_{J,J} and L_{bnd{J},J}
%
currentlinewidth 0.5 mul setlinewidth
newpath
1.5 0.5 moveto
2 1 nD 1 sub {
/ix exch def
ix 0.5 add 0.5 lineto
ix 0.5 add ix 0.5 sub moveto
} for
stroke
newpath
nD 0.5 sub nD 1.5 sub moveto
nD 1 nD nL add 1 sub {
/ix exch def
ix 0.5 add 0.5 lineto
ix 0.5 add nD 0.5 sub moveto
} for
stroke
%
% draw the thick edges for U_{J,J}
%
currentlinewidth 2.0 mul setlinewidth
2 1 nD 1 sub {
/iy exch def
newpath
0.5 iy 0.5 add moveto
0 1 iy 2 sub {
/ix exch def
1.0 0.0 rlineto
} for
stroke
} for
%
% draw the thick edges for U_{bnd{J},J}
%
nD 1 nD nU add 1 sub {
/iy exch def
newpath
0.5 iy 0.5 add moveto
0 1 nD 2 sub {
/ix exch def
1.0 0.0 rlineto
} for
stroke
} for
%
% draw the thin edges for U_{J,J} and U_{bnd{J},J}
%
currentlinewidth 0.5 mul setlinewidth
newpath
0.5 1.5 moveto
2 1 nD 1 sub {
/iy exch def
0.5 iy 0.5 add lineto
iy 0.5 sub iy 0.5 add moveto
} for
stroke
newpath
nD 1.5 sub nD 0.5 sub moveto
nD 1 nD nU add 1 sub {
/iy exch def
0.5 iy 0.5 add lineto
nD 0.5 sub iy 0.5 add moveto
} for
stroke
%
% draw the circles that represent entries
%
/r 0.2 def
/x 0.5 def
0 1 nD 1 sub {
/y 0.5 def
0 1 nD nU add 1 sub {
newpath
1.0 setgray
pop x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
/x nD 0.5 add def
0 1 nL 1 sub {
/y 0.5 def
0 1 nD 1 sub {
pop
newpath
1.0 setgray
x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
stroke
grestore
Chv/doc/frontnonsymDA2.eps 0100644 0002055 0007177 00000004767 06571267316 0017005 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 500.0 500.0
%%%EndComments
/nD 10 def
/nL 15 def
/nU 12 def
/margin 50 def
/xscale 500 margin 2 mul sub nD nL add div def
/yscale 500 margin 2 mul sub nD nU add div def
xscale yscale le { % true action -- if else
/yscale xscale def
} { % false action -- if else
/xscale yscale def
} ifelse
(xscale) == xscale ==
(yscale) == yscale ==
% 50 50 400 400 rectstroke
gsave
%
% translate, scale and rotate
%
50 50 translate
xscale yscale scale
0.05 setlinewidth
0 nD nL add translate
-90 rotate
%
% draw the outlines of the three DA2 objects
%
0.0 setgray
0 0 nD nD rectstroke
nD 0 nL nD rectstroke
0 nD nD nU rectstroke
%
% draw the thick edges for A_{J,J}
%
0 1 nD 1 sub {
/iy exch def
newpath
0.5 iy 0.5 add moveto
0 1 nD 2 sub {
/iy exch def
1.0 0.0 rlineto
} for
stroke
} for
%
% draw the thick edges for A_{bnd{J},J}
%
nD 1 nD nL add 1 sub {
/ix exch def
newpath
ix 0.5 add 0.5 moveto
0 1 nD 2 sub {
/iy exch def
0.0 1.0 rlineto
} for
stroke
} for
%
% draw the thin edges for A_{J,J} and A_{bnd{J},J}
%
currentlinewidth 0.5 mul setlinewidth
newpath
nD 0.5 sub 0.5 moveto
2 1 nD {
/iy exch def
0.5 iy 0.5 sub lineto
nD 1 sub 0 rmoveto
} for
stroke
newpath
nD 0.5 add nD 0.5 sub moveto
nD 1 add 1 nD nL add 1 sub {
/ix exch def
ix 0.5 add 0.5 lineto
ix 0.5 add nD 0.5 sub moveto
} for
stroke
%
% draw the thick edges for A_{J,bnd{J}}
%
nD 1 nD nU add 1 sub {
/iy exch def
newpath
0.5 iy 0.5 add moveto
0 1 nD 2 sub {
/ix exch def
1.0 0.0 rlineto
} for
stroke
} for
%
% draw the thin edges for U_{J,bnd{J}}
%
currentlinewidth 0.5 mul setlinewidth
newpath
nD 0.5 sub nD 0.5 add moveto
nD 1 add 1 nD nU add 1 sub {
/iy exch def
0.5 iy 0.5 add lineto
nD 0.5 sub iy 0.5 add moveto
} for
stroke
%
% draw the circles that represent entries
%
/r 0.2 def
/x 0.5 def
0 1 nD 1 sub {
/y 0.5 def
0 1 nD nU add 1 sub {
newpath
1.0 setgray
pop x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
/x nD 0.5 add def
0 1 nL 1 sub {
/y 0.5 def
0 1 nD 1 sub {
pop
newpath
1.0 setgray
x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
stroke
grestore
Chv/doc/frontsym.eps 0100644 0002055 0007177 00000006676 06571267316 0016004 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 500.0 500.0
%%%EndComments
/nD 10 def
/nL 15 def
/nU 15 def
/margin 50 def
/xscale 500 margin 2 mul sub nD nL add div def
/yscale 500 margin 2 mul sub nD nU add div def
xscale yscale le { % true action -- if else
/yscale xscale def
} { % false action -- if else
/xscale yscale def
} ifelse
(xscale) == xscale ==
(yscale) == yscale ==
% 50 50 400 400 rectstroke
gsave
%
% translate, scale and rotate
%
50 50 translate
xscale yscale scale
0.05 setlinewidth
0 nD nL add translate
-90 rotate
%
% draw the outlines of the three DA2 objects
%
0.0 setgray
0 0 nD nD rectstroke
nD 0 nL nD rectstroke
0 nD nD nU rectstroke
%
% draw the pivot elements
% 1x1, 2x2, 2x2, 1x1, 1x1, 1x1, 2x2
%
/first [ -1 0 0 2 2 4 5 6 7 7 ] def
0 0 1 1 rectstroke
1 1 2 2 rectstroke
3 3 2 2 rectstroke
5 5 1 1 rectstroke
6 6 1 1 rectstroke
7 7 1 1 rectstroke
8 8 2 2 rectstroke
%
% draw the solid edges for diagonal entries
%
currentlinewidth 2.0 mul setlinewidth
newpath
0.5 0.5 moveto
1 1 rlineto
0 1 rlineto
1 0 rlineto
1 1 rlineto
0 1 rlineto
1 0 rlineto
1 1 rlineto
1 1 rlineto
1 1 rlineto
1 1 rlineto
0 1 rlineto
1 0 rlineto
stroke
%
% draw the thick edges for L_{J,J}
%
2 1 nD 1 sub {
/ix exch def
newpath
ix 0.5 add 0.5 moveto
0 1 first ix get 1 sub {
/iy exch def
0.0 1.0 rlineto
} for
stroke
} for
%
% draw the thick edges for L_{bnd{J},J}
%
nD 1 nD nL add 1 sub {
/ix exch def
newpath
ix 0.5 add 0.5 moveto
0 1 nD 2 sub {
/iy exch def
0.0 1.0 rlineto
} for
stroke
} for
%
% draw the thin edges for L_{J,J} and L_{bnd{J},J}
%
currentlinewidth 0.5 mul setlinewidth
newpath
1.5 0.5 moveto
2 1 nD 1 sub {
/ix exch def
ix 0.5 add 0.5 lineto
ix 0.5 add first ix get 0.5 add moveto
} for
stroke
newpath
nD 0.5 sub first nD 1 sub get 0.5 add moveto
nD 1 nD nL add 1 sub {
/ix exch def
ix 0.5 add 0.5 lineto
ix 0.5 add nD 0.5 sub moveto
} for
stroke
%
% draw the thick edges for U_{J,J}
%
currentlinewidth 2.0 mul setlinewidth
2 1 nD 1 sub {
/iy exch def
newpath
0.5 iy 0.5 add moveto
0 1 first iy get 1 sub {
/ix exch def
1.0 0.0 rlineto
} for
stroke
} for
%
% draw the thick edges for U_{bnd{J},J}
%
nD 1 nD nU add 1 sub {
/iy exch def
newpath
0.5 iy 0.5 add moveto
0 1 nD 2 sub {
/ix exch def
1.0 0.0 rlineto
} for
stroke
} for
%
% draw the thin edges for U_{J,J} and U_{bnd{J},J}
%
currentlinewidth 0.5 mul setlinewidth
newpath
0.5 1.5 moveto
2 1 nD 1 sub {
/iy exch def
0.5 iy 0.5 add lineto
first iy get 0.5 add iy 0.5 add moveto
} for
stroke
newpath
first nD 1 sub get 0.5 add nD 0.5 sub moveto
nD 1 nD nU add 1 sub {
/iy exch def
0.5 iy 0.5 add lineto
nD 0.5 sub iy 0.5 add moveto
} for
stroke
%
% draw the circles that represent entries
%
/r 0.2 def
/x 0.5 def
0 1 nD 1 sub {
/y 0.5 def
0 1 nD nU add 1 sub {
newpath
1.0 setgray
pop x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
/x nD 0.5 add def
0 1 nL 1 sub {
/y 0.5 def
0 1 nD 1 sub {
pop
newpath
1.0 setgray
x r add y moveto x y r 0 360 arc
fill
newpath
0.0 setgray
x r add y moveto x y r 0 360 arc
stroke
/y y 1 add def
} for
/x x 1 add def
} for
stroke
grestore
d rotate
%
50 50 translate
xscale yscale scale
0.05 setliChv/doc/intro.tex 0100644 0002055 0007177 00000016021 06571267316 0015250 0 ustar 00cleve compmath 0000040 0000006 \par
\chapter{{\tt Chv}: Block chevron}
\par
The {\tt Chv} object is used to store and operate on a {\it front}
during a sparse factorization.
The {\tt Chv} object can contain either double precision real or
complex data.
A front is a portion of a matrix, shaded grey in the diagram below.
\begin{center}
\makebox{
% \psfig{file=simple.eps,width=1.0in,height=1.00in}
\psfig{file=../../Chv/doc/simple.eps,width=1.0in,height=1.00in}
}
\end{center}
We use the word ``chevron'' to describe the front, because if you
rotate the figure $45^\circ$ clockwise the shaded region resembles
the chevron insignia of enlisted personnel in the armed forces.
Similar matrices are also known as ``arrowhead'' matrices, but we
have found the ``chevron'' has a simpler abbreviation.
We use the adjective ``block'' to emphasize that the chevron object
may have multiple entries of the diagonal of the matrix.
A ``single'' chevron (which is one way we assemble entries from a
matrix into this data structure) contains a single entry from the
diagonal of the matrix.
\par
The shaded region in the diagram above will normally be sparse,
i.e., many of the entries might be zero.
There are three logical blocks to the {\tt Chv} object:
a nonempty square (1,1) block in the upper left corner,
and (possibly empty) (1,2) and (2,1) blocks in the upper right
and lower left corners.
To conserve space and minimize work on logically zero elements,
we store only rows of the lower part and columns of the upper part
that have (or may have) nonzero elements.
(Note, a particular row or column may
have zero elements, but normally there will be nonzeros in each row
and column that we store.)
\par
{\tt Chv} objects come in three types --- symmetric, Hermitian and
nonsymmetric.
When an object is symmetric or Hermitian, we only store the upper
triangle.
There is one limitation, perhaps unnecessary,
that we put on the {\tt Chv} object ---
the number of rows in the (2,1) block and number of columns
in the (1,2) block are equal.
The {\tt Chv} object is used within the context of a factorization
of a sparse matrix that is assumed to have symmetric structure.
If we ever extend the code to handle a true nonsymmetric structure
factorization (e.g., {\sc umfpack} and {\sc superlu}), then we can
modify the {\tt Chv} object to handle unequal rows and columns.
\par
During a factorization,
a front has to take part in four distinct operations.
\begin{enumerate}
\item
Assemble entries from the original matrix (or matrix pencil).
(See the {\tt Chv\_addChevron()} method.)
\item
Accumulate updates from descendant fronts.
(See the {\tt Chv\_update\{S,H,N\}()} methods.)
\item
Assemble any postponed data from its children fronts.
(See the {\tt Chv\_assemblePostponedData()} method.)
\item
Compute the factorization of the completely assembled front.
(See the {\tt Chv\_factor()} method.)
\end{enumerate}
\par
The implementor of a front object has a great deal of freedom to
design the underlying data structures.
We have chosen to store the entries in each single chevron
in contiguous memory --- the first entry of a chevron is in
the last row of the front, the last entry of a chevron is
in the last column of the front.
The figure below shows the storage locations for the
entries --- on the left is a nonsymmetric chevron, on the right is
a symmetric or hermitian chevron.
\begin{center}
\makebox{
% \psfig{file=simple2.eps,width=2.2in,height=1.00in}
\psfig{file=../../Chv/doc/simple2.eps,width=2.2in,height=1.00in}
}
\end{center}
\par
Any storage format has advantages and disadvantages.
\begin{itemize}
\item[{\bf con}]
Moving along the diagonal is a nonconstant stride through memory.
The same holds for moving along a row in the lower part and along a
column in the upper part.
While the strides are nonconstant, they are easily determined,
particularly when starting in the first chevron.
This affects the search methods that look for a pivot in the (1,1)
block, the method that evaluates a pivot,
the swap methods that swap rows and columns,
and the methods that extract the entries from the chevron to be
stored in the factor matrix.
\item[{{\bf pro}}]
Moving along a row in the upper part and along a column in the
lower part uses a unit stride.
This is useful when performing an update to the remaining part of
the front after a pivot element has been selected.
\item[{\bf pro}]
The assembly of data, be it from the original matrix stored by
chevrons, aggregate update fronts from other processes in a
parallel factorization, or postponed data when pivoting for
stability is used can be done in a straightforward manner.
\end{itemize}
\par
The chevron object exists within the context of a larger global
matrix, and so needs indices to define its rows and columns.
For a symmetric or Hermitian matrix, we only store the column
indices.
For a nonsymmetric matrix, we store the both the row and column
indices.
This second case may seem unnecessary, since we assume that the
larger global matrix has symmetric structure.
However, during a factorization with pivoting enabled,
a pivot element may be chosen from anywhere in the (1,1) block,
so the row indices and column indices may no longer be identical.
\par
A {\tt Chv} object is inherently a serial, single threaded object,
meaning it is designed so that only one thread or process ``owns''
or operates on a particular {\tt Chv} object.
A {\tt Chv} object is an ``atom'' of communication.
It stores postponed rows and columns to be assembled in a parent
front.
It might have to be written to and read from a file in an
out-of-core implementation.
In a distributed environment, it is communicated between processes.
For these reasons, we designed the object so that its data
(the scalars that describe its dimensions, id and type,
the row and column indices, and its entries) are found in
contiguous storage managed by a {\tt DV} object.
A file operation can be done with a single read or write,
a message can be sent without packing and unpacking data,
or defining a new datatype.
Managing working storage for a number of {\tt Chv} objects
is now simpler.
\par
When the {\tt Chv} object contains double precision {\it complex} data,
it stores and operates on them as double precision entries.
We follow the FORTRAN convention that the real and imaginary part
of a complex number are stored consecutively, the real part first
followed by the imaginary number.
In the above complex nonsymmetric matrix,
the third diagonal entry is found
at location 38 {\it in terms of the complex numbers}, but its real
and imaginary parts are found in locations 2*38 = 76 and 2*38+1 = 77
of the double precision vector that stores the entries.
Computations are done in a mix of subroutine calls
(see {\tt Utilites/ZV.h}) and by expanding the complex arithmetic
into real arithmetic.
\par
The {\tt Chv} object ``knows'' about the {\tt IV}, {\tt DV} and
{\tt ZV} vector objects (for {\tt int}, {\tt double} and
{\tt double complex} data types),
the {\tt A2} object for dense 2-D arrays,
and the {\tt SubMtx} object for dense or sparse 2-D submatrices.
These {\tt IV}, {\tt DV}, {\tt ZV}, {\tt A2} and {\tt SubMtx} objects
are subordinate to the {\tt Chv} object.
Chv/doc/main.aux 0100644 0002055 0007177 00000004272 06650201723 0015027 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\contentsline {chapter}{\numberline {1}{\tt Chv}: Block chevron}{1}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {1.1}Data Structure}{3}}
\newlabel{section:Chv:dataStructure}{{1.1}{3}}
\@writefile{toc}{\contentsline {section}{\numberline {1.2}Prototypes and descriptions of {\tt Chv} methods}{4}}
\newlabel{section:Chv:proto}{{1.2}{4}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.1}Basic methods}{4}}
\newlabel{subsection:Chv:proto:basics}{{1.2.1}{4}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.2}Instance methods}{5}}
\newlabel{subsection:Chv:proto:instance}{{1.2.2}{5}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.3}Initialization methods}{7}}
\newlabel{subsection:Chv:proto:initial}{{1.2.3}{7}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.4}Search methods}{8}}
\newlabel{subsection:Chv:proto:search}{{1.2.4}{8}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.5}Pivot methods}{9}}
\newlabel{subsection:Chv:proto:pivot}{{1.2.5}{9}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.6}Update methods}{10}}
\newlabel{subsection:Chv:proto:updates}{{1.2.6}{10}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.7}Assembly methods}{10}}
\newlabel{subsection:Chv:proto:assembly}{{1.2.7}{10}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.8}Factorization methods}{11}}
\newlabel{subsection:Chv:proto:factor}{{1.2.8}{11}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.9}Copy methods}{12}}
\newlabel{subsection:Chv:proto:copy}{{1.2.9}{12}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.10}Swap methods}{14}}
\newlabel{subsection:Chv:proto:swap}{{1.2.10}{14}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.11}Utility methods}{15}}
\newlabel{subsection:Chv:proto:utilities}{{1.2.11}{15}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.12}IO methods}{17}}
\newlabel{subsection:Chv:proto:IO}{{1.2.12}{17}}
\@writefile{toc}{\contentsline {section}{\numberline {1.3}Driver programs for the {\tt Chv object}}{17}}
\newlabel{section:Chv:drivers}{{1.3}{17}}
Chv/doc/main.idx 0100644 0002055 0007177 00000007407 06650201723 0015021 0 ustar 00cleve compmath 0000040 0000006 \indexentry{Chv_new@{\tt Chv\_new()}}{4}
\indexentry{Chv_setDefaultFields@{\tt Chv\_setDefaultFields()}}{4}
\indexentry{Chv_clearData@{\tt Chv\_clearData()}}{4}
\indexentry{Chv_free@{\tt Chv\_free()}}{4}
\indexentry{Chv_id@{\tt Chv\_id()}}{5}
\indexentry{Chv_type@{\tt Chv\_type()}}{5}
\indexentry{Chv_symmetryFlag@{\tt Chv\_symmetryFlag()}}{5}
\indexentry{Chv_dimensions@{\tt Chv\_dimensions()}}{5}
\indexentry{Chv_rowIndices@{\tt Chv\_rowIndices()}}{5}
\indexentry{Chv_columnIndices@{\tt Chv\_columnIndices()}}{5}
\indexentry{Chv_nent@{\tt Chv\_nent()}}{5}
\indexentry{Chv_entries@{\tt Chv\_entries()}}{6}
\indexentry{Chv_diagLocation@{\tt Chv\_diagLocation()}}{6}
\indexentry{Chv_workspace@{\tt Chv\_workspace()}}{6}
\indexentry{Chv_realEntry@{\tt Chv\_realEntry()}}{6}
\indexentry{Chv_locationOfRealEntry@{\tt Chv\_locationOfRealEntry()}}{6}
\indexentry{Chv_setRealEntry@{\tt Chv\_setRealEntry()}}{6}
\indexentry{Chv_complexEntry@{\tt Chv\_complexEntry()}}{6}
\indexentry{Chv_locationOfComplexEntry@{\tt Chv\_locationOfComplexEntry()}}{7}
\indexentry{Chv_setComplexEntry@{\tt Chv\_setComplexEntry()}}{7}
\indexentry{Chv_init@{\tt Chv\_init()}}{7}
\indexentry{Chv_initWithPointers@{\tt Chv\_initWithPointers()}}{7}
\indexentry{Chv_initFromBuffer@{\tt Chv\_initFromBuffer()}}{7}
\indexentry{Chv_maxabsInDiagonal11@{\tt Chv\_maxabsInDiagonal11()}}{8}
\indexentry{Chv_maxabsInRow11@{\tt Chv\_maxabsInRow11()}}{8}
\indexentry{Chv_maxabsInColumn11@{\tt Chv\_maxabsInColumn11()}}{8}
\indexentry{Chv_maxabsInRow@{\tt Chv\_maxabsInRow()}}{8}
\indexentry{Chv_maxabsInColumn@{\tt Chv\_maxabsInColumn()}}{8}
\indexentry{Chv_quasimax@{\tt Chv\_quasimax()}}{9}
\indexentry{Chv_fastBunchParlettPivot@{\tt Chv\_fastBunchParlettPivot()}}{9}
\indexentry{Chv_findPivot@{\tt Chv\_findPivot()}}{9}
\indexentry{Chv_updateS@{\tt Chv\_updateS()}}{10}
\indexentry{Chv_updateH@{\tt Chv\_updateH()}}{10}
\indexentry{Chv_updateN@{\tt Chv\_updateN()}}{10}
\indexentry{Chv_addChevron@{\tt Chv\_addChevron()}}{10}
\indexentry{Chv_assembleChv@{\tt Chv\_assembleChv()}}{11}
\indexentry{Chv_assemblePostponedData@{\tt Chv\_assemblePostponedData()}}{11}
\indexentry{Chv_factorWithPivoting@{\tt Chv\_factorWithPivoting()}}{11}
\indexentry{Chv_factorWithNoPivoting@{\tt Chv\_factorWithNoPivoting()}}{11}
\indexentry{Chv_r1upd@{\tt Chv\_r1upd()}}{12}
\indexentry{Chv_r2upd@{\tt Chv\_r2upd()}}{12}
\indexentry{Chv_maxabsInChevron@{\tt Chv\_maxabsInChevron()}}{12}
\indexentry{Chv_zeroOffdiagonalOfChevron@{\tt Chv\_zeroOffdiagonalOfChevron()}}{12}
\indexentry{Chv_countEntries@{\tt Chv\_countEntries()}}{12}
\indexentry{Chv_countBigEntries@{\tt Chv\_countBigEntries()}}{13}
\indexentry{Chv_copyEntriesToVector@{\tt Chv\_copyEntriesToVector()}}{13}
\indexentry{Chv_copyBigEntriesToVector@{\tt Chv\_copyBigEntriesToVector()}}{14}
\indexentry{Chv_copyTrailingPortion@{\tt Chv\_copyTrailingPortion()}}{14}
\indexentry{Chv_swapRows@{\tt Chv\_swapRows()}}{14}
\indexentry{Chv_swapColumns@{\tt Chv\_swapColumns()}}{15}
\indexentry{Chv_swapRowsAndColumns@{\tt Chv\_swapRowsAndColumns()}}{15}
\indexentry{Chv_nbytesNeeded@{\tt Chv\_nbytesNeeded()}}{15}
\indexentry{Chv_nbytesInWorkspace@{\tt Chv\_nbytesInWorkspace()}}{15}
\indexentry{Chv_setNbytesInWorkspace@{\tt Chv\_setNbytesInWorkspace()}}{15}
\indexentry{Chv_setFields@{\tt Chv\_setFields()}}{15}
\indexentry{Chv_shift@{\tt Chv\_shift()}}{15}
\indexentry{Chv_fill11block@{\tt Chv\_fill11block()}}{16}
\indexentry{Chv_fill12block@{\tt Chv\_fill12block()}}{16}
\indexentry{Chv_fill21block@{\tt Chv\_fill21block()}}{16}
\indexentry{Chv_maxabs@{\tt Chv\_maxabs()}}{16}
\indexentry{Chv_frobNorm@{\tt Chv\_frobNorm()}}{16}
\indexentry{Chv_sub@{\tt Chv\_sub()}}{16}
\indexentry{Chv_zero@{\tt Chv\_zero()}}{16}
\indexentry{Chv_writeForHumanEye@{\tt Chv\_writeForHumanEye()}}{17}
\indexentry{Chv_writeForMatlab@{\tt Chv\_writeForMatlab()}}{17}
Chv/doc/main.ilg 0100644 0002055 0007177 00000000457 06571267316 0015022 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (62 entries accepted, 0 rejected).
Sorting entries....done (437 comparisons).
Generating output file main.ind....done (66 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
Chv/doc/main.ind 0100644 0002055 0007177 00000004411 06571267316 0015013 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt Chv\_addChevron()}, 10
\item {\tt Chv\_assembleChv()}, 11
\item {\tt Chv\_assemblePostponedData()}, 11
\item {\tt Chv\_clearData()}, 4
\item {\tt Chv\_columnIndices()}, 5
\item {\tt Chv\_complexEntry()}, 6
\item {\tt Chv\_copyBigEntriesToVector()}, 13
\item {\tt Chv\_copyEntriesToVector()}, 13
\item {\tt Chv\_copyTrailingPortion()}, 14
\item {\tt Chv\_countBigEntries()}, 12
\item {\tt Chv\_countEntries()}, 12
\item {\tt Chv\_diagLocation()}, 6
\item {\tt Chv\_dimensions()}, 5
\item {\tt Chv\_entries()}, 6
\item {\tt Chv\_factor()}, 11
\item {\tt Chv\_fastBunchParlettPivot()}, 9
\item {\tt Chv\_fill11block()}, 15
\item {\tt Chv\_fill12block()}, 15
\item {\tt Chv\_fill21block()}, 16
\item {\tt Chv\_findPivot()}, 9
\item {\tt Chv\_free()}, 4
\item {\tt Chv\_frobNorm()}, 16
\item {\tt Chv\_id()}, 5
\item {\tt Chv\_init()}, 7
\item {\tt Chv\_initFromBuffer()}, 7
\item {\tt Chv\_initWithPointers()}, 7
\item {\tt Chv\_locationOfComplexEntry()}, 7
\item {\tt Chv\_locationOfRealEntry()}, 6
\item {\tt Chv\_maxabs()}, 16
\item {\tt Chv\_maxabsInColumn()}, 8
\item {\tt Chv\_maxabsInColumn11()}, 8
\item {\tt Chv\_maxabsInDiagonal11()}, 8
\item {\tt Chv\_maxabsInRow()}, 8
\item {\tt Chv\_maxabsInRow11()}, 8
\item {\tt Chv\_nbytesInWorkspace()}, 15
\item {\tt Chv\_nbytesNeeded()}, 15
\item {\tt Chv\_nent()}, 5
\item {\tt Chv\_new()}, 4
\item {\tt Chv\_quasimax()}, 9
\item {\tt Chv\_r1upd()}, 11
\item {\tt Chv\_r2upd()}, 12
\item {\tt Chv\_realEntry()}, 6
\item {\tt Chv\_rowIndices()}, 5
\item {\tt Chv\_setComplexEntry()}, 7
\item {\tt Chv\_setDefaultFields()}, 4
\item {\tt Chv\_setFields()}, 15
\item {\tt Chv\_setNbytesInWorkspace()}, 15
\item {\tt Chv\_setRealEntry()}, 6
\item {\tt Chv\_shift()}, 15
\item {\tt Chv\_sub()}, 16
\item {\tt Chv\_swapColumns()}, 14
\item {\tt Chv\_swapRows()}, 14
\item {\tt Chv\_swapRowsAndColumns()}, 14
\item {\tt Chv\_symmetryFlag()}, 5
\item {\tt Chv\_type()}, 5
\item {\tt Chv\_updateH()}, 10
\item {\tt Chv\_updateN()}, 10
\item {\tt Chv\_updateS()}, 10
\item {\tt Chv\_workspace()}, 6
\item {\tt Chv\_writeForHumanEye()}, 16
\item {\tt Chv\_writeForMatlab()}, 16
\item {\tt Chv\_zero()}, 16
\end{theindex}
Chv/doc/main.log 0100644 0002055 0007177 00000026453 06650201723 0015020 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.14159 (C version 6.1) (format=latex 97.4.4) 16 JAN 1999 13:25
**main
(main.tex
LaTeX2e <1996/12/01> patch level 1
Babel and hyphenation patterns for english, german, loaded.
(/home/tex/teTeX/texmf/tex/latex/base/latex209.def
File: latex209.def 1996/05/21 v0.51 Standard LaTeX file
Entering LaTeX 2.09 compatibility mode.
\footheight=\dimen102
\@maxsep=\dimen103
\@dblmaxsep=\dimen104
\@cla=\count79
\@clb=\count80
\mscount=\count81
(/home/tex/teTeX/texmf/tex/latex/base/tracefnt.sty
Package: tracefnt 1996/07/26 v3.0i Standard LaTeX package (font tracing)
\tracingfonts=\count82
LaTeX Info: Redefining \selectfont on input line 139.
)
\symbold=\mathgroup4
\symsans=\mathgroup5
\symtypewriter=\mathgroup6
\symitalic=\mathgroup7
\symsmallcaps=\mathgroup8
\symslanted=\mathgroup9
LaTeX Font Info: Redeclaring math alphabet \mathbf on input line 306.
LaTeX Font Info: Redeclaring math alphabet \mathsf on input line 307.
LaTeX Font Info: Redeclaring math alphabet \mathtt on input line 308.
LaTeX Font Info: Redeclaring math alphabet \mathit on input line 314.
LaTeX Info: Redefining \em on input line 324.
(/home/tex/teTeX/texmf/tex/latex/base/latexsym.sty
Package: latexsym 1996/11/20 v2.2d Standard LaTeX package (lasy symbols)
\symlasy=\mathgroup10
LaTeX Font Info: Overwriting symbol font `lasy' in version `bold'
(Font) U/lasy/m/n --> U/lasy/b/n on input line 85.
)
LaTeX Font Info: Redeclaring math delimiter \lgroup on input line 388.
LaTeX Font Info: Redeclaring math delimiter \rgroup on input line 390.
LaTeX Font Info: Redeclaring math delimiter \bracevert on input line 392.
(/home/tex/teTeX/texmf/tex/latex/config/latex209.cfg
(/home/tex/teTeX/texmf/tex/latex/tools/rawfonts.sty
Compatibility mode: package `' requested, but `rawfonts' provided.
Package: rawfonts 1994/05/08 Low-level LaTeX 2.09 font compatibility
(/home/tex/teTeX/texmf/tex/latex/tools/somedefs.sty
Package: somedefs 1994/06/01 Toolkit for optional definitions
)
LaTeX Font Info: Try loading font information for U+lasy on input line 36.
(/home/tex/teTeX/texmf/tex/latex/base/ulasy.fd
File: ulasy.fd 1996/11/20 v2.2dLaTeX symbol font definitions
))))
(/home/tex/teTeX/texmf/tex/latex/base/report.cls
Document Class: report 1996/10/31 v1.3u Standard LaTeX document class
(/home/tex/teTeX/texmf/tex/latex/base/leqno.clo
File: leqno.clo 1996/07/26 v1.1b Standard LaTeX option (left equation numbers)
)
(/home/tex/teTeX/texmf/tex/latex/base/size11.clo
File: size11.clo 1996/10/31 v1.3u Standard LaTeX file (size option)
)
\c@part=\count83
\c@chapter=\count84
\c@section=\count85
\c@subsection=\count86
\c@subsubsection=\count87
\c@paragraph=\count88
\c@subparagraph=\count89
\c@figure=\count90
\c@table=\count91
\abovecaptionskip=\skip41
\belowcaptionskip=\skip42
Compatibility mode: definition of \rm ignored.
Compatibility mode: definition of \sf ignored.
Compatibility mode: definition of \tt ignored.
Compatibility mode: definition of \bf ignored.
Compatibility mode: definition of \it ignored.
Compatibility mode: definition of \sl ignored.
Compatibility mode: definition of \sc ignored.
LaTeX Info: Redefining \cal on input line 622.
LaTeX Info: Redefining \mit on input line 623.
\bibindent=\dimen105
)
(/home/tex/teTeX/texmf/tex/generic/local/psfig/psfig.tex
\@unused=\write3
\ps@stream=\read1
\p@intvaluex=\dimen106
\p@intvaluey=\dimen107
psfig/tex 1.10-dvips
)
\@indexfile=\write4
Writing index file main.idx
(main.aux)
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
(intro.tex
Chapter 1.
psfig: searching ../../Chv/doc/simple.eps for bounding box
psfig: including ../../Chv/doc/simple.eps
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <10.95> on input line 16.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <8> on input line 16.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <6> on input line 16.
[1
]
LaTeX Font Info: Try loading font information for OMS+cmtt on input line 61.
LaTeX Font Info: No file OMScmtt.fd. on input line 61.
LaTeX Font Warning: Font shape `OMS/cmtt/m/n' undefined
(Font) using `OMS/cmsy/m/n' instead
(Font) for symbol `textbraceleft' on input line 61.
Overfull \hbox (7.47354pt too wide) in paragraph at lines 63--66
[]\OT1/cmr/m/n/10.95 Assemble any post-poned data from its chil-dren fronts. (S
ee the \OT1/cmtt/m/n/10.95 Chv[]assemblePostponedData()
[]
Overfull \hbox (1.0263pt too wide) in paragraph at lines 66--68
[]\OT1/cmr/m/n/10.95 Compute the fac-tor-iza-tion of the com-pletely as-sem-ble
d front. (See the \OT1/cmtt/m/n/10.95 Chv[]factor() \OT1/cmr/m/n/10.95 method.)
[]
psfig: searching ../../Chv/doc/simple2.eps for bounding box
psfig: including ../../Chv/doc/simple2.eps
[2]) (dataStructure.tex
LaTeX Font Info: Try loading font information for OMS+cmr on input line 9.
(/home/tex/teTeX/texmf/tex/latex/base/omscmr.fd
File: omscmr.fd 1997/01/14 v2.5a Standard LaTeX font definitions
)
LaTeX Font Info: Font shape `OMS/cmr/m/n' in size <10.95> not available
(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 9.
[3]) (proto.tex [4] [5] [6]
Overfull \hbox (29.01247pt too wide) in paragraph at lines 324--324
[]\OT1/cmtt/m/n/10.95 void Chv_init( Chv *chv, int id, int nD, int nL, int nU,
int type, int symflag ) ;[]
[]
Overfull \hbox (11.7664pt too wide) in paragraph at lines 347--347
[]\OT1/cmtt/m/n/10.95 void Chv_initWithPointers ( Chv *chv, int id, int nD, in
t nL, int nU, int type,[]
[]
Overfull \hbox (52.00722pt too wide) in paragraph at lines 347--347
[] \OT1/cmtt/m/n/10.95 int symflag, int *rowind, in
t *colind, double *entries ) ;[]
[]
Overfull \hbox (11.7664pt too wide) in paragraph at lines 390--390
[]\OT1/cmtt/m/n/10.95 int Chv_maxabsInDiagonal11 ( Chv *chv, int mark[], int t
ag, double *pmaxval ) ;[]
[]
[7] [8] [9] [10]
Overfull \hbox (0.26903pt too wide) in paragraph at lines 681--681
[]\OT1/cmtt/m/n/10.95 int Chv_assemblePostponedData ( Chv *newchv, Chv *oldchv
, Chv *firstchild ) ;[]
[]
[11] [12]
Overfull \hbox (8.37198pt too wide) in paragraph at lines 921--925
[]\OT1/cmr/m/n/10.95 If \OT1/cmtt/m/n/10.95 storeflag \OT1/cmr/m/n/10.95 is \OT
1/cmtt/m/n/10.95 CHV[]BY[]ROWS\OT1/cmr/m/n/10.95 , the en-tries are stored by r
ows and if \OT1/cmtt/m/n/10.95 storeflag \OT1/cmr/m/n/10.95 is \OT1/cmtt/m/n/10
.95 CHV[]BY[]COLUMNS\OT1/cmr/m/n/10.95 ,
[]
[13]
Overfull \hbox (8.37198pt too wide) in paragraph at lines 973--977
[]\OT1/cmr/m/n/10.95 If \OT1/cmtt/m/n/10.95 storeflag \OT1/cmr/m/n/10.95 is \OT
1/cmtt/m/n/10.95 CHV[]BY[]ROWS\OT1/cmr/m/n/10.95 , the en-tries are stored by r
ows and if \OT1/cmtt/m/n/10.95 storeflag \OT1/cmr/m/n/10.95 is \OT1/cmtt/m/n/10
.95 CHV[]BY[]COLUMNS\OT1/cmr/m/n/10.95 ,
[]
[14] [15] [16]) (drivers.tex
Overfull \hbox (4.80856pt too wide) in paragraph at lines 36--40
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
[17]
Overfull \hbox (4.80856pt too wide) in paragraph at lines 87--91
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
Overfull \hbox (4.80856pt too wide) in paragraph at lines 127--131
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
[18]
Overfull \hbox (4.80856pt too wide) in paragraph at lines 177--181
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
[19]
Overfull \hbox (4.80856pt too wide) in paragraph at lines 227--231
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
Overfull \hbox (4.80856pt too wide) in paragraph at lines 273--277
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
Overfull \hbox (28.20038pt too wide) in paragraph at lines 287--301
[]\OT1/cmr/m/n/10.95 This driver pro-gram tests the \OT1/cmtt/m/n/10.95 Chv[]ma
xabsInRow()\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95 Chv[]maxabsInRow11()\OT1/cm
r/m/n/10.95 , \OT1/cmtt/m/n/10.95 Chv[]maxabsInColumn()\OT1/cmr/m/n/10.95 ,
[]
[20]
Overfull \hbox (4.80856pt too wide) in paragraph at lines 321--325
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
Overfull \hbox (4.80856pt too wide) in paragraph at lines 360--364
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
Overfull \hbox (4.80856pt too wide) in paragraph at lines 395--399
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
[21]
Overfull \hbox (4.80856pt too wide) in paragraph at lines 435--439
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
Overfull \hbox (4.80856pt too wide) in paragraph at lines 470--474
[]\OT1/cmr/m/n/10.95 The \OT1/cmtt/m/n/10.95 symflag \OT1/cmr/m/n/10.95 pa-ram-
e-ter is the sym-me-try flag --- \OT1/cmtt/m/n/10.95 SPOOLES[]SYMMETRIC\OT1/cmr
/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN
[]
[22]) (main.ind [23] [24
]) (main.aux)
LaTeX Font Warning: Some font shapes were not available, defaults substituted.
)
Here is how much of TeX's memory you used:
839 strings out of 10908
8656 string characters out of 72189
55441 words of memory out of 262141
3675 multiletter control sequences out of 9500
23452 words of font info for 88 fonts, out of 150000 for 255
14 hyphenation exceptions out of 607
22i,7n,21p,313b,388s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (24 pages, 84792 bytes).
kage: rawfonts 1994/05/08 Low-level LaTeX 2.09 font compatibility
(/home/tex/teTeX/texmf/tex/latex/tools/somedefs.sty
Package: somedefs 1994/06/01 Toolkit for optional definitions
)
LaTeX Font Info: Try loadinChv/doc/main.tex 0100644 0002055 0007177 00000001151 06650656170 0015035 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\newcommand{\bnd}{{\partial}}
\input psfig
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt Chv} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt Chv} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
Chv/doc/notes 0100644 0002055 0007177 00000000612 06571267316 0014445 0 ustar 00cleve compmath 0000040 0000006 (1) DFront's create new DFront objects as the first step
of an update, an inter-front computation.
(2) The second step is the assembly of one DFront object
into another.
(3) I.e., DFront objects do not have internal access to
others of their own class during the update.
(4) Later, we can write the code to perform the update
with direct-action-on-storage of the two DFront's.
Chv/doc/proto.tex 0100644 0002055 0007177 00000151171 06650202342 0015250 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt Chv} methods}
\label{section:Chv:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt Chv} object.
\par
\subsection{Basic methods}
\label{subsection:Chv:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Chv * Chv_new ( void ) ;
\end{verbatim}
\index{Chv_new@{\tt Chv\_new()}}
This method simply allocates storage for the {\tt Chv} structure
and then sets the default fields by a call to
{\tt Chv\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_setDefaultFields ( Chv *chv ) ;
\end{verbatim}
\index{Chv_setDefaultFields@{\tt Chv\_setDefaultFields()}}
The structure's fields are set to default values:
{\tt id} = {\tt -1}, {\tt nD} = {\tt nL} = {\tt nU} = 0,
{\tt type} = {\tt SPOOLES\_REAL},
{\tt symflag} = {\tt SPOOLES\_SYMMETRIC},
and {\tt rowind} = {\tt colind} = {\tt entries} = {\tt next}
= {\tt NULL} .
The {\tt wrkDV} object has its default fields set via a call to
{\tt DV\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_clearData ( Chv *chv ) ;
\end{verbatim}
\index{Chv_clearData@{\tt Chv\_clearData()}}
This method clears the object and free's any owned data
by invoking the {\tt \_clearData()} methods for its internal
{\tt DV} object.
There is a concluding call to {\tt Chv\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_free ( Chv *chv ) ;
\end{verbatim}
\index{Chv_free@{\tt Chv\_free()}}
This method releases any storage by a call to
{\tt Chv\_clearData()} and then free the space for {\tt chv}.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Instance methods}
\label{subsection:Chv:proto:instance}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_id ( Chv *chv ) ;
\end{verbatim}
\index{Chv_id@{\tt Chv\_id()}}
This method returns the {\it id} of the object.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_type ( Chv *chv ) ;
\end{verbatim}
\index{Chv_type@{\tt Chv\_type()}}
This method returns the {\it type} of the object.
\begin{itemize}
\item
{\tt SPOOLES\_REAL} $\Longrightarrow$ real entries
\item
{\tt SPOOLES\_COMPLEX} $\Longrightarrow$ complex entries
\end{itemize}
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_symmetryFlag ( Chv *chv ) ;
\end{verbatim}
\index{Chv_symmetryFlag@{\tt Chv\_symmetryFlag()}}
This method returns the {\it symmetry flag} of the object.
\begin{itemize}
\item
{\tt SPOOLES\_SYMMETRIC} $\Longrightarrow$
symmetric entries, i.e., $a_{i,j} = a_{j,i}$.
\item
{\tt SPOOLES\_HERMITIAN} $\Longrightarrow$
hermitian entries, i.e., $a_{i,j} = \overline{a_{j,i}}$.
\item
{\tt SPOOLES\_NONSYMMETRIC} $\Longrightarrow$
nonsymmetric entries.
\end{itemize}
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_dimensions ( Chv *chv, int *pnD, int *pnL, *pnU ) ;
\end{verbatim}
\index{Chv_dimensions@{\tt Chv\_dimensions()}}
This method
fills {\tt *pnD}, {\tt *pnL} and {\tt *pnU}
with {\tt nD}, {\tt nL} and {\tt nU}.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_rowIndices ( Chv *chv, int *pnrow, **prowind ) ;
\end{verbatim}
\index{Chv_rowIndices@{\tt Chv\_rowIndices()}}
This method fills {\tt *pnrow} with the number of rows ({\tt nD + nL})
and {\tt *prowind} with a pointer to the row indices.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt pnrow} or {\tt prowind} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_columnIndices ( Chv *chv, int *pncol, **pcolind ) ;
\end{verbatim}
\index{Chv_columnIndices@{\tt Chv\_columnIndices()}}
This method fills {\tt *pncol} with the number of columns
({\tt nD + nU})
and {\tt *pcolind} with a pointer to the column indices.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt pncol} or {\tt pcolind} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_nent ( Chv *chv ) ;
\end{verbatim}
\index{Chv_nent@{\tt Chv\_nent()}}
This method returns number of matrix entries that the object contains.
Note, for a complex chevron,
this is the number of {\it double precision complex} entries,
equal to one half the number of double precision entries
that are stored.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double * Chv_entries ( Chv *chv ) ;
\end{verbatim}
\index{Chv_entries@{\tt Chv\_entries()}}
This method returns the {\it entries} field of the object,
a pointer to the base location of the double precision array that
stores the complex data.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double * Chv_diagLocation ( Chv *chv, int ichv ) ;
\end{verbatim}
\index{Chv_diagLocation@{\tt Chv\_diagLocation()}}
This method returns a pointer to the address of the entry in
the {\tt ichv}'th diagonal location.
For a real chevron,
to find the entry {\tt k} places to the right of the diagonal entry,
add {\tt k} to the address.
To find an entry {\tt k} places below the diagonal entry,
subtract {\tt k} from the address.
For a complex chevron,
to find the entry {\tt k} places to the right of the diagonal entry,
add {\tt 2*k} to the address.
To find an entry {\tt k} places below the diagonal entry,
subtract {\tt 2*k} from the address.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void * Chv_workspace ( Chv *chv ) ;
\end{verbatim}
\index{Chv_workspace@{\tt Chv\_workspace()}}
This method returns a pointer to the base address of the workspace.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_realEntry ( Chv *chv, int irow, int jcol, double *pValue ) ;
\end{verbatim}
\index{Chv_realEntry@{\tt Chv\_realEntry()}}
This method fills {\tt *pValue} with the entry
in row {\tt irow} and column {\tt jcol}.
Note, {\tt irow} and {\tt jcol} are {\it local} indices,
i.e., $0 \le \mbox{\tt irow} < \mbox{\tt nD} + \mbox{\tt nL}$
and $0 \le \mbox{\tt jcol} < \mbox{\tt nD} + \mbox{\tt nU}$.
\par \noindent {\it Error checking:}
If {\tt chv} or {\tt pValue} is {\tt NULL},
or if {\tt irow} or {\tt jcol} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Chv_locationOfRealEntry ( Chv *chv, int irow, int jcol, double **ppValue ) ;
\end{verbatim}
\index{Chv_locationOfRealEntry@{\tt Chv\_locationOfRealEntry()}}
This method fills {\tt *ppValue} with a pointer to the
entry in row {\tt irow} and column {\tt jcol}.
Note, {\tt irow} and {\tt jcol} are {\it local} indices,
i.e., $0 \le \mbox{\tt irow} < \mbox{\tt nD} + \mbox{\tt nL}$
and $0 \le \mbox{\tt jcol} < \mbox{\tt nD} + \mbox{\tt nU}$.
\par \noindent {\it Error checking:}
If {\tt chv} or {\tt ppValue} is {\tt NULL},
or if {\tt irow} or {\tt jcol} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_setRealEntry ( Chv *chv, int irow, int jcol, double value ) ;
\end{verbatim}
\index{Chv_setRealEntry@{\tt Chv\_setRealEntry()}}
This method sets the entry in row {\tt irow} and column {\tt jcol}
to be {\tt value}.
Note, {\tt irow} and {\tt jcol} are {\it local} indices,
i.e., $0 \le \mbox{\tt irow} < \mbox{\tt nD} + \mbox{\tt nL}$
and $0 \le \mbox{\tt jcol} < \mbox{\tt nD} + \mbox{\tt nU}$.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
or if {\tt irow} or {\tt jcol} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_complexEntry ( Chv *chv, int irow, int jcol,
double *pReal, double *pImag ) ;
\end{verbatim}
\index{Chv_complexEntry@{\tt Chv\_complexEntry()}}
This method fills {\tt *pReal} with the real part and
{\tt *pImag} with the imaginary part of the the entry
in row {\tt irow} and column {\tt jcol}.
Note, {\tt irow} and {\tt jcol} are {\it local} indices,
i.e., $0 \le \mbox{\tt irow} < \mbox{\tt nD} + \mbox{\tt nL}$
and $0 \le \mbox{\tt jcol} < \mbox{\tt nD} + \mbox{\tt nU}$.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt pReal} or {\tt pImag} is {\tt NULL},
or if {\tt irow} or {\tt jcol} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Chv_locationOfComplexEntry ( Chv *chv, int irow, int jcol,
double **ppReal, double **ppImag ) ;
\end{verbatim}
\index{Chv_locationOfComplexEntry@{\tt Chv\_locationOfComplexEntry()}}
This method fills {\tt *ppReal} with a pointer to the real part
and {\tt *ppImag} with a pointer to the imaginary part of
the entry in row {\tt irow} and column {\tt jcol}.
Note, {\tt irow} and {\tt jcol} are {\it local} indices,
i.e., $0 \le \mbox{\tt irow} < \mbox{\tt nD} + \mbox{\tt nL}$
and $0 \le \mbox{\tt jcol} < \mbox{\tt nD} + \mbox{\tt nU}$.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt ppReal} or {\tt ppImag} is {\tt NULL},
or if {\tt irow} or {\tt jcol} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_setComplexEntry ( Chv *chv, int irow, int jcol,
double real, double imag ) ;
\end{verbatim}
\index{Chv_setComplexEntry@{\tt Chv\_setComplexEntry()}}
This method sets the real and imaginary parts and the entry
in row {\tt irow} and column {\tt jcol} to be {\tt real} and {\tt
imag}, respectively.
Note, {\tt irow} and {\tt jcol} are {\it local} indices,
i.e., $0 \le \mbox{\tt irow} < \mbox{\tt nD} + \mbox{\tt nL}$
and $0 \le \mbox{\tt jcol} < \mbox{\tt nD} + \mbox{\tt nU}$.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
or if {\tt irow} or {\tt jcol} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initialization methods}
\label{subsection:Chv:proto:initial}
\par
There are three initializer methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_init( Chv *chv, int id, int nD, int nL, int nU, int type, int symflag ) ;
\end{verbatim}
\index{Chv_init@{\tt Chv\_init()}}
This is the initializer method used when the {\tt Chv}
object is to use its owned workspace to store indices and entries.
The number of indices and entries is computed,
the work space is set up via calls to {\tt Chv\_nbytesNeeded()}
and {\tt Chv\_setNbytesInWorkspace()},
and the scalars, pointers and buffer are set up via a call to
{\tt Chv\_setFields()}.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
or if ${\tt nD} \le 0$,
or if {\tt nL} or ${\tt nU} < 0$,
or if {\tt type} or if {\tt symflag} is not valid,
% or if {\tt type} is not {\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX},
% or if {\tt symflag} is not {\tt SPOOLES\_SYMMETRIC},
% {\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_initWithPointers ( Chv *chv, int id, int nD, int nL, int nU, int type,
int symflag, int *rowind, int *colind, double *entries ) ;
\end{verbatim}
\index{Chv_initWithPointers@{\tt Chv\_initWithPointers()}}
This initializer method is used when the {\tt Chv}
object does not own the storage for its indices and entries,
but points into some other storage.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
or if ${\tt nD} \le 0$,
or if {\tt nL} or ${\tt nU} < 0$,
or if {\tt type} or if {\tt symflag} is not valid,
% or if {\tt type} is not {\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX},
% or if {\tt symflag} is not {\tt SPOOLES\_SYMMETRIC},
% {\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}
or if {\tt entries} or {\tt colind} is {\tt NULL},
or if {\tt symflag = SPOOLES\_NONSYMMETRIC}
and {\tt rowind} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_initFromBuffer ( Chv *chv ) ;
\end{verbatim}
\index{Chv_initFromBuffer@{\tt Chv\_initFromBuffer()}}
This initializer method is used to set the scalar and pointer fields
when the object's buffer is already preloaded.
This functionality is used in the MPI factorization where a {\tt
Chv} object is sent and received, more precisely, the workspace
buffer owned by the {\tt Chv} object is sent and received.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Search methods}
\label{subsection:Chv:proto:search}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_maxabsInDiagonal11 ( Chv *chv, int mark[], int tag, double *pmaxval ) ;
\end{verbatim}
\index{Chv_maxabsInDiagonal11@{\tt Chv\_maxabsInDiagonal11()}}
This method returns the location of the first tagged element with the
largest magnitude in the diagonal of the (1,1) block.
Element {\tt jj} must have {\tt mark[jj] = tag} to be eligible.
Its magnitude is returned in {\tt *pmaxval}.
Note, if the chevron is complex, the location is in terms
of the complex entries, not in the real entries,
i.e., if {\tt k = Chv\_maxabsDiagonal11(chv,...)},
then the complex entry is found in {\tt chv->entries[2*kk:2*kk+1]}.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt mark} or {\tt pmaxval} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_maxabsInRow11 ( Chv *chv, int irow, int colmark[],
int tag, double *pmaxval ) ;
\end{verbatim}
\index{Chv_maxabsInRow11@{\tt Chv\_maxabsInRow11()}}
This method returns the location of the first element with the
largest magnitude in row {\tt irow} of the (1,1) block.
Element {\tt jj} must have {\tt colmark[jj] = tag} to be eligible.
Its magnitude is returned in {\tt *pmaxval}.
Note, if the chevron is complex,
the location is in terms of the complex entries, not in the
real entries, i.e., if {\tt k = Chv\_maxabsRow11(chv,...)},
then the complex entry is found in {\tt chv->entries[2*kk:2*kk+1]}.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL} or {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_maxabsInColumn11 ( Chv *chv, int jcol, int rowmark[],
int tag, double *pmaxval ) ;
\end{verbatim}
\index{Chv_maxabsInColumn11@{\tt Chv\_maxabsInColumn11()}}
This method returns the location of the first element with the
largest magnitude in column {\tt jcol} of the (1,1) block.
Element {\tt jj} must have {\tt rowmark[jj] = tag} to be eligible.
Its magnitude is returned in {\tt *pmaxval}.
Note, if the chevron is complex,
the location is in terms of the complex entries, not in the
real entries, i.e., if {\tt k = Chv\_maxabsColumn11(chv,...)},
then the complex entry is found in {\tt chv->entries[2*kk:2*kk+1]}.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL} or {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_maxabsInRow ( Chv *chv, int irow, int colmark[],
int tag, double *pmaxval ) ;
\end{verbatim}
\index{Chv_maxabsInRow@{\tt Chv\_maxabsInRow()}}
This method returns the location of the first element with the
largest magnitude in row {\tt irow}.
Element {\tt jj} must have {\tt colmark[jj] = tag} to be eligible.
Its magnitude is returned in {\tt *pmaxval}.
Note, if the chevron is complex,
the location is in terms of the complex entries, not in the
real entries, i.e., if {\tt k = Chv\_maxabsRow(chv,...)},
then the complex entry is found in {\tt chv->entries[2*kk:2*kk+1]}.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL} or {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_maxabsInColumn ( Chv *chv, int jcol, int rowmark[],
int tag, double *pmaxval ) ;
\end{verbatim}
\index{Chv_maxabsInColumn@{\tt Chv\_maxabsInColumn()}}
This method returns the location of the first element with the
largest magnitude in column {\tt jcol}.
Element {\tt jj} must have {\tt rowmark[jj] = tag} to be eligible.
Its magnitude is returned in {\tt *pmaxval}.
Note, if the chevron is complex,
the location is in terms of the complex entries, not in the
real entries, i.e., if {\tt k = Chv\_maxabsColumn11(chv,...)},
then the complex entry is found in {\tt chv->entries[2*kk:2*kk+1]}.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL} or {\tt irow} is not in {\tt [0,n1-1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double Chv_quasimax ( Chv *chv, int rowmark[], int colmark[]
int tag, int *pirow, int *pjcol ) ;
\end{verbatim}
\index{Chv_quasimax@{\tt Chv\_quasimax()}}
This method searches for a {\it quasimax} entry in the $(1,1)$
block, an entry $a_{i,j}$ that has largest magnitude
of the tagged entries in row $i$ and column $j$.
An entry $a_{i,j}$ is {\it tagged} when {\tt rowmark[i] = tag}
and {\tt colmark[j] = tag}.
On return,
{\tt *pirow} is filled with the row id and
{\tt *pjcol} is filled with the column id of the quasimax entry.
The return value is the magnitude of the entry.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt rowmark}, {\tt colmark}, {\tt pirow} or {\tt pjcol}
is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_fastBunchParlettPivot ( Chv *chv, int mark[], int tag,
int *pirow, int *pjcol ) ;
\end{verbatim}
\index{Chv_fastBunchParlettPivot@{\tt Chv\_fastBunchParlettPivot()}}
This method is used only for a symmetric or hermitian object and
finds a $1 \times 1$ or $2 \times 2$ pivot
that is suitable for elimination.
Only pivots from the $(1,1)$ block can be chosen.
A diagonal element $a_{r,r}$ with maximum magnitude is first found
using the {\tt Chv\_maxabsInDiagonal11()} method.
We then find the element $a_{r,k}$ in that row that has
a maximum magnitude.
If $|a_{r,r}| > 0.6404 |a_{r,k}|$
then we accept the $1 \times 1$ pivot element.
Otherwise we look for an offdiagonal element that is largest in its
row and column and return it as a $2 \times 2$ pivot.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt mark}, {\tt pirow} or {\tt pjcol} is {\tt NULL},
an error message is printed and the method returns.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Pivot methods}
\label{subsection:Chv:proto:pivot}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_findPivot ( Chv *chv, DV *workDV, double tau, int ndelay,
int *pirow, int *pjcol, int *pntest ) ;
\end{verbatim}
\index{Chv_findPivot@{\tt Chv\_findPivot()}}
This method finds and tests a pivot, where if it were used at the
next elimination step, each entry in $L$ and $U$ would have
magnitude less than or equal to {\tt tau}.
The {\tt workDV} object is used for workspace,
it is resized as necessary.
The {\tt ndelay} parameter allows one to specify the number of leading
rows and columns to ignore, useful when delayed rows and columns
have been placed in the leading portion of the chevron.
The {\tt pirow}, {\tt pjcol} and {\tt pntest} addresses are filled
with the pivot row, pivot column, and number of pivot tests
performed to find the pivot.
If no pivot was found, {\tt pirow} and {\tt pjcol} are filled with
{\tt -1}.
The return value is the size of the pivot.
If the chevron is symmetric, we can find a
$1 \times 1$ or $2 \times 2$ pivot.
If the chevron is nonsymmetric, we only find a $1 \times 1$ pivot.
A return value of zero means that no pivot was found.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt workDV}, {\tt pirow}, {\tt pjcol} or {\tt pntest}
is {\tt NULL},
or if ${\tt tau} < 1.0$, or if ${\tt ndelay} < 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Update methods}
\label{subsection:Chv:proto:updates}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_updateS ( Chv *chv, SubMtx *mtxD, SubMtx *mtxU, DV *tempDV ) ;
void Chv_updateH ( Chv *chv, SubMtx *mtxD, SubMtx *mtxU, DV *tempDV ) ;
void Chv_updateN ( Chv *chv, SubMtx *mtxL, SubMtx *mtxD, SubMtx *mtxU,
DV *tempDV ) ;
\end{verbatim}
\index{Chv_updateS@{\tt Chv\_updateS()}}
\index{Chv_updateH@{\tt Chv\_updateH()}}
\index{Chv_updateN@{\tt Chv\_updateN()}}
These methods perform an update to a chevron during the factorization.
For a symmetric chevron, we compute
\begin{eqnarray*}
T_{J \cap \bnd{I},J \cap \bnd{I}}
& := & T_{J \cap \bnd{I},J \cap \bnd{I}}
- U_{I,J \cap \bnd{I}}^T D_{I,I} U_{I, J \cap \bnd{I}} \\
T_{J \cap \bnd{I},\bnd{J} \cap \bnd{I}}
& := & T_{J \cap \bnd{I},\bnd{J} \cap \bnd{I}}
- U_{I,J \cap \bnd{I}}^T D_{I,I} U_{I, \bnd{J} \cap \bnd{I}}
\end{eqnarray*}
where $D$ is diagonal or block diagonal with $1 \times 1$ and/or
symmetric $2 \times 2$ pivots.
$U$ is stored by sparse or dense columns.
For a Hermitian chevron, we compute
\begin{eqnarray*}
T_{J \cap \bnd{I},J \cap \bnd{I}}
& := & T_{J \cap \bnd{I},J \cap \bnd{I}}
- U_{I,J \cap \bnd{I}}^H D_{I,I} U_{I, J \cap \bnd{I}} \\
T_{J \cap \bnd{I},\bnd{J} \cap \bnd{I}}
& := & T_{J \cap \bnd{I},\bnd{J} \cap \bnd{I}}
- U_{I,J \cap \bnd{I}}^H D_{I,I} U_{I, \bnd{J} \cap \bnd{I}}
\end{eqnarray*}
where $D$ is diagonal or block diagonal with $1 \times 1$ and/or
Hermitian $2 \times 2$ pivots.
$U$ is stored by sparse or dense columns.
For a nonsymmetric chevron, we compute
\begin{eqnarray*}
T_{J \cap \bnd{I},J \cap \bnd{I}}
& := & T_{J \cap \bnd{I},J \cap \bnd{I}}
- L_{J \cap \bnd{I},I} D_{I,I} U_{I, J \cap \bnd{I}} \\
T_{J \cap \bnd{I},\bnd{J} \cap \bnd{I}}
& := & T_{J \cap \bnd{I},\bnd{J} \cap \bnd{I}}
- L_{J \cap \bnd{I},I} D_{I,I} U_{I, \bnd{J} \cap \bnd{I}} \\
T_{\bnd{J} \cap \bnd{I},J \cap \bnd{I}}
& := & T_{\bnd{J} \cap \bnd{I},J \cap \bnd{I}}
- L_{\bnd{J} \cap \bnd{I},I} D_{I,I} U_{I, J \cap \bnd{I}}
\end{eqnarray*}
where $D$ is diagonal,
$L$ is stored by sparse or dense rows, and
$U$ is stored by sparse or dense columns.
{\tt tempDV} is a temporary working vector whose storage
is resized as necessary.
\par \noindent {\it Error checking:}
If {\tt chvT}, {\tt mtxL}, {\tt mtxD}, {\tt mtxU} or {\tt tempDV}
is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Assembly methods}
\label{subsection:Chv:proto:assembly}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_addChevron ( Chv *chv, double alpha[], int ichv, int chvsize,
int chvind[], double chvent[] ) ;
\end{verbatim}
\index{Chv_addChevron@{\tt Chv\_addChevron()}}
This method is used to assemble entries from the matrix pencil
$A + \sigma B$ into the block chevron object.
Typically the entries from $A$ or $B$ will come from a {\tt InpMtx}
object, one of whose modes of storage is by single {\tt chevrons}.
The value {\tt ichv} is the row and column location of the diagonal
entry.
The indices found in {\tt chvind[]} are {\it offsets}.
Let {\tt off = chvind[ii]} be the offset for one of the chevron's
entries.
If $\mbox{\tt off} \ge 0$, then the entry is found in location
{\tt (ichv, ichv+off)} of the matrix.
If $\mbox{\tt off} < 0$, then the entry is found in location
{\tt (ichv-off, ichv)} of the matrix.
The value(s) in {\tt alpha[]} form a scalar
used to scale the entire chevron for its assembly.
A call to assemble entries in $A$ (from the pencil $A + \sigma B$)
would have {\tt alpha[] = (1.0,0.0)};
to assemble entries in $B$ (from the pencil $A + \sigma B$)
would have $\mbox{\tt alpha[]} = (Real(\sigma),Imag(\sigma))$.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt chvind}, {\tt chvent} or {\tt alpha} is {\tt NULL},
or if {\tt ichv} or {\tt chvsize} are less than zero,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_assembleChv ( Chv *chvJ, Chv *chvI ) ;
\end{verbatim}
\index{Chv_assembleChv@{\tt Chv\_assembleChv()}}
This method is used to assemble entries from one {\tt Chv} object
into another.
The application is during a factorization with pivoting,
postponed entries from the children are stored in the {\tt chvI Chv}
object and need to be assembled into the final working front,
along with all updates from the descendents (which are stored in
the {\tt chvJ Chv} object.
Note, the row and column indices of {\tt chvI} {\it must nest}
with those of {\tt chvJ}.
\par \noindent {\it Error checking:}
If {\tt chvI} or {\tt chvJ} is {\tt NULL},
or if their {\tt symflag} fields are not identical,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_assemblePostponedData ( Chv *newchv, Chv *oldchv, Chv *firstchild ) ;
\end{verbatim}
\index{Chv_assemblePostponedData@{\tt Chv\_assemblePostponedData()}}
This method is used to assemble a {\tt Chv} object for a front
({\tt oldchv})
along with any postponed data from the children
(objects are held in a list where {\tt firstchild} is the head)
into a {\tt Chv} object {\tt newchv}.
The return value is the number of delayed rows and columns from the
children fronts which are found in the leading rows and columns of
the chevron.
\par \noindent {\it Error checking:}
If {\tt newchv}, {\tt oldchv} or {\tt firstchild} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Factorization methods}
\label{subsection:Chv:proto:factor}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_factorWithPivoting ( Chv *chv, int ndelay, int pivotflag,
IV *pivotsizesIV, DV *workDV, double tau, int *pntest ) ;
\end{verbatim}
\index{Chv_factorWithPivoting@{\tt Chv\_factorWithPivoting()}}
This method factors a front using pivoting for numerical stability.
The number of rows and columns that have been delayed (assembled
from the children) is given by {\tt ndelay}, this allows the method
that finds the pivots to skip over these rows and columns since no
pivot can be found there.
When pivoting is enabled ({\tt pivotflag} is {\tt SPOOLES\_PIVOTING}),
the {\tt workDV}
object used during the search process for pivots
must be non-{\tt NULL},
{\tt tau} is the upper bound on factor entries, and {\tt pivotsizesIV}
must be non-{\tt NULL} when the front is symmetric or Hermitian.
The address {\tt pntest} is incremented with the number of pivot
tests by the {\tt Chv\_findPivot()} method.
The return value is the number of eliminated rows and columns.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
or if {\tt pivotflag} is not valid,
or if {\tt ndelay} is negative,
or if {\tt pivotflag == SPOOLES\_PIVOTING}
and {\tt workDV} is {\tt NULL} or {\tt tau} is less than {\tt 1.0},
or if the chevron is symmetric or Hermitian,
{\tt pivotflag == SPOOLES\_PIVOTING} and
{\tt pivotsizesIV} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_factorWithNoPivoting ( Chv *chv, PatchAndGoInfo *info ) ;
\end{verbatim}
\index{Chv_factorWithNoPivoting@{\tt Chv\_factorWithNoPivoting()}}
This method factors a front without using pivoting
for numerical stability.
It does support ``patch-and-go'' functionality, where if a small or
zero entry is found in the diagonal element that is to be
eliminated, some action can be taken.
The return value is the number of eliminated rows and columns.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_r1upd ( Chv *chv ) ;
\end{verbatim}
\index{Chv_r1upd@{\tt Chv\_r1upd()}}
This method is used during the factorization of a front,
performing a rank-one update of the chevron.
The return value is {\tt 1} if the pivot is nonzero,
{\tt 0} otherwise.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_r2upd ( Chv *chv ) ;
\end{verbatim}
\index{Chv_r2upd@{\tt Chv\_r2upd()}}
This method is used during the factorization of a front,
performing a rank-two update of the chevron.
The return value is {\tt 1} if the pivot is nonsingular,
{\tt 0} otherwise.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
or if the chevron is nonsymmetric,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_maxabsInChevron ( Chv *chv, int ichv,
double *pdiagmaxabs, *prowmaxabs, *pcolmaxabs ) ;
\end{verbatim}
\index{Chv_maxabsInChevron@{\tt Chv\_maxabsInChevron()}}
This method is used during the factorization of a front
with a ``patch-and-go'' strategy.
On return,
{\tt *pdiagmaxabs} contains the magnitude of the diagonal
entry for the chevron,
{\tt *prowmaxabs} contains the maximum magnitude of the entries
in the row of the chevron,
and {\tt *pcolmaxabs} contains the maximum magnitude of the entries
in the column of the chevron.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt pdiagmaxabs}, {\tt prowmaxabs} or {\tt pcolmaxabs}
is {\tt NULL},
or if {\tt ichv} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_zeroOffdiagonalOfChevron ( Chv *chv, int ichv ) ;
\end{verbatim}
\index{Chv_zeroOffdiagonalOfChevron@{\tt Chv\_zeroOffdiagonalOfChevron()}}
This method is used during the factorization of a front
with a ``patch-and-go'' strategy.
On return,
the offdiagonal entries of chevron {\tt ichv} have been set to zero.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
or if {\tt ichv} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Copy methods}
\label{subsection:Chv:proto:copy}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_countEntries ( Chv *chv, int npivot, int pivotsizes[],
int countflag ) ;
\end{verbatim}
\index{Chv_countEntries@{\tt Chv\_countEntries()}}
This method counts the number of entries in the chevron that are
larger in magnitude than {\tt droptol}.
{\tt countflag} has the following meaning.
\begin{itemize}
\item {\tt CHV\_STRICT\_LOWER} $\Longrightarrow$
count strict lower entries
\item {\tt CHV\_DIAGONAL} $\Longrightarrow$ count diagonal entries
\item {\tt CHV\_STRICT\_UPPER} $\Longrightarrow$
count strict upper entries
\item {\tt CHV\_STRICT\_LOWER\_11} $\Longrightarrow$
count strict lower entries in the (1,1) block
\item {\tt CHV\_LOWER\_21} $\Longrightarrow$
count lower entries in the (2,1) block
\item {\tt CHV\_STRICT\_UPPER\_11} $\Longrightarrow$
count strict upper entries in the (1,1) block
\item {\tt CHV\_UPPER\_12} $\Longrightarrow$
count upper entries in the (1,2) block
\end{itemize}
This method is used to compute the necessary storage to store a
chevron as a dense front.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL}
or if {\tt countflag} is not valid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_countBigEntries ( Chv *chv, int npivot, int pivotsizes[],
int countflag, double droptol ) ;
\end{verbatim}
\index{Chv_countBigEntries@{\tt Chv\_countBigEntries()}}
This method counts the number of entries in the chevron that are
larger in magnitude than {\tt droptol}.
{\tt countflag} has the following meaning.
\begin{itemize}
\item {\tt CHV\_STRICT\_LOWER} $\Longrightarrow$
count strict lower entries
\item {\tt CHV\_STRICT\_UPPER} $\Longrightarrow$
count strict upper entries
\item {\tt CHV\_STRICT\_LOWER\_11} $\Longrightarrow$
count strict lower entries in the (1,1) block
\item {\tt CHV\_LOWER\_21} $\Longrightarrow$
count lower entries in the (2,1) block
\item {\tt CHV\_STRICT\_UPPER\_11} $\Longrightarrow$
count strict upper entries in the (1,1) block
\item {\tt CHV\_UPPER\_12} $\Longrightarrow$
count upper entries in the (1,2) block
\end{itemize}
This method is used to compute the necessary storage to store a
chevron as a sparse front.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL}
or if {\tt countflag} is not valid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_copyEntriesToVector ( Chv *chv, int npivot, int pivotsizes[],
int length, double dvec[], int copyflag, int storeflag) ;
\end{verbatim}
\index{Chv_copyEntriesToVector@{\tt Chv\_copyEntriesToVector()}}
This method copies some entries the chevron object into a double
precision vector.
This method is called after a front has been factored and
is used to store the factor entries into the
storage for the factor matrix.
If the front is nonsymmetric, the front contains entries
of $L$, $D$ and $U$, where $D$ is diagonal.
If the front is symmetric or Hermitian, the front contains entries
of $D$ and $U$, and $D$ is diagonal if {\tt pivotsizesIV} is {\tt
NULL} or may contain a mixture of $1 \times 1$ and $2 \times 2$
pivots otherwise.
{\tt copyflag} has the following meaning.
\begin{itemize}
\item {\tt CHV\_STRICT\_LOWER} $\Longrightarrow$
copy strict lower entries
\item {\tt CHV\_DIAGONAL} $\Longrightarrow$ copy diagonal entries
\item {\tt CHV\_STRICT\_UPPER} $\Longrightarrow$
copy strict upper entries
\item {\tt CHV\_STRICT\_LOWER\_11} $\Longrightarrow$
copy strict lower entries in the (1,1) block
\item {\tt CHV\_LOWER\_21} $\Longrightarrow$
copy lower entries in the (2,1) block
\item {\tt CHV\_STRICT\_UPPER\_11} $\Longrightarrow$
copy strict upper entries in the (1,1) block
\item {\tt CHV\_UPPER\_12} $\Longrightarrow$
copy upper entries in the (1,2) block
\end{itemize}
\par
%% The {\tt DFrontMtx} object presently stores the entries in $U$
%% by columns and the entries in $L$ by rows.
%% This allows us to use dot product kernels during the factorization.
%% On other architectures it may be more efficient to have {\tt axpy}
%% kernels, in which the entries in $U$ would be stored by rows and
%% the entries in $L$ stored by columns.
%% This method supports both formats, where
If {\tt storeflag} is {\tt CHV\_BY\_ROWS},
the entries are stored by rows
and if {\tt storeflag} is {\tt CHV\_BY\_COLUMNS},
the entries are stored by columns.
\par \noindent {\it Error checking:}
If {\tt chv} or {\tt dvec} is {\tt NULL}
or if {\tt length} is less than the number of entries to be copied,
or if {\tt copyflag} or {\tt storeflag} is valid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_copyBigEntriesToVector ( Chv *chv, int npivot, int pivotsizes[],
int sizes[], int ivec[], double dvec[],
int copyflag, int storeflag, double droptol ) ;
\end{verbatim}
\index{Chv_copyBigEntriesToVector@{\tt Chv\_copyBigEntriesToVector()}}
This method also copies some entries the chevron object into a double
precision vector, but only those entries whose magnitude is
greater than or equal to {\tt droptol} are copied.
This method is called after a front has been factored and
is used to store the factor entries of large magnitude into the
storage for the factor matrix.
If the front is nonsymmetric, the front contains entries
of $L$, $D$ and $U$, where $D$ is diagonal.
If the front is symmetric, the front contains entries
of $D$ and $U$, and $D$ is diagonal if {\tt pivotsizesIV} is {\tt
NULL} or may contain a mixture of $1 \times 1$ and $2 \times 2$
pivots otherwise.
{\tt copyflag} has the following meaning.
\begin{itemize}
\item {\tt CHV\_STRICT\_LOWER} $\Longrightarrow$
copy strict lower entries
\item {\tt CHV\_STRICT\_UPPER} $\Longrightarrow$
copy strict upper entries
\item {\tt CHV\_STRICT\_LOWER\_11} $\Longrightarrow$
copy strict lower entries in the (1,1) block
\item {\tt CHV\_LOWER\_21} $\Longrightarrow$
copy lower entries in the (2,1) block
\item {\tt CHV\_STRICT\_UPPER\_11} $\Longrightarrow$
copy strict upper entries in the (1,1) block
\item {\tt CHV\_UPPER\_12} $\Longrightarrow$
copy upper entries in the (1,2) block
\end{itemize}
\par
% The {\tt DFrontMtx} object presently stores the entries in $U$
% by columns and the entries in $L$ by rows.
% This allows us to use dot product kernels during the factorization.
% On other architectures it may be more efficient to have {\tt axpy}
% kernels, in which the entries in $U$ would be stored by rows and
% the entries in $L$ stored by columns.
% This method supports both formats, where
If {\tt storeflag} is {\tt CHV\_BY\_ROWS},
the entries are stored by rows
and if {\tt storeflag} is {\tt CHV\_BY\_COLUMNS},
the entries are stored by columns.
\par
When we store the large entries in the columns of $U$,
{\tt sizes[jcol]} contains the number of large entries in column
{\tt jcol}.
The vectors {\tt ivec[]} and {\tt dvec[]} contain the row indices
and the entries that are stored.
When we store the large entries in the rows of $L$,
{\tt sizes[irow]} contains the number of large entries in column
{\tt irow}.
The vectors {\tt ivec[]} and {\tt dvec[]} contain the column indices
and the entries that are stored.
Presently there is no checking that {\tt sizes[]}, {\tt ivec[]} and
{\tt dvec[]} are large enough to store the sizes, indices and entries.
The large entry count can be obtained using the method
{\tt Chv\_countBigEntries()}.
\par \noindent {\it Error checking:}
If {\tt chv} or {\tt dvec} is {\tt NULL}
or if {\tt length} is less than the number of entries to be copied,
or if {\tt copyflag} or {\tt storeflag} is not valid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_copyTrailingPortion ( Chv *chvI, Chv *chvJ, int offset ) ;
\end{verbatim}
\index{Chv_copyTrailingPortion@{\tt Chv\_copyTrailingPortion()}}
This method copies the trailing portion of {\tt chvJ} into {\tt chvI}.
The first {\tt offsets} chevrons are not copied, the remainder are
copied.
This method is used to extract the delayed entries from a front
which has been factored.
\par \noindent {\it Error checking:}
If {\tt chvI} or {\tt chvJ} is {\tt NULL},
or if ${\tt offset} < 0$ or {\tt offset} is greater than the number
of chevrons in {\tt chvJ},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Swap methods}
\label{subsection:Chv:proto:swap}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_swapRows ( Chv *chv, int irow, int jrow ) ;
\end{verbatim}
\index{Chv_swapRows@{\tt Chv\_swapRows()}}
This method swaps rows {\tt irow} and {\tt jrow} of the chevron.
Both rows must be less than the width {\tt nD} of the chevron.
The row ids of the two rows are also swapped.
If the chevron is symmetric, then the method
{\tt Chv\_swapRowsAndColumns()} is called.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL}
or if {\tt irow} or {\tt jrow} are less than 0 or greater than or equal
to {\tt nD},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_swapColumns ( Chv *chv, int icol, int jcol ) ;
\end{verbatim}
\index{Chv_swapColumns@{\tt Chv\_swapColumns()}}
This method swaps columns {\tt icol} and {\tt jcol} of the chevron.
Both columns must be less than the width {\tt nD} of the chevron.
The column ids of the two columns are also swapped.
If the chevron is symmetric, then the method
{\tt Chv\_swapRowsAndColumns()} is called.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL}
or if {\tt icol} or {\tt jcol} are less than 0 or greater than or equal
to {\tt nD},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_swapRowsAndColumns ( Chv *chv, int ii, int jj ) ;
\end{verbatim}
\index{Chv_swapRowsAndColumns@{\tt Chv\_swapRowsAndColumns()}}
This method swaps rows and columns {\tt ii} and {\tt jj} of the chevron.
Both must be less than the width {\tt nD} of the chevron.
The row and/or column ids are also swapped.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL}
or if {\tt ii} or {\tt jj} are less than 0 or greater than or equal
to {\tt nD},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:Chv:proto:utilities}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_nbytesNeeded ( int nD, int nL, int nU, int type, int symflag ) ;
\end{verbatim}
\index{Chv_nbytesNeeded@{\tt Chv\_nbytesNeeded()}}
This method returns the number of bytes necessary to store an
object with the given dimensions and type in its workspace.
\par \noindent {\it Error checking:}
If {\tt nD}, {\tt nL}, or {\tt nU} is less than zero,
or if {\tt type} or {\tt symflag} are not valid,
% or if {\tt type} is not {\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX},
% or if {\tt symflag} is not {\tt SPOOLES\_SYMMETRIC},
% {\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Chv_nbytesInWorkspace ( Chv *chv ) ;
\end{verbatim}
\index{Chv_nbytesInWorkspace@{\tt Chv\_nbytesInWorkspace()}}
This method returns the number of bytes in the workspace.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_setNbytesInWorkspace ( Chv *chv, int nbytes ) ;
\end{verbatim}
\index{Chv_setNbytesInWorkspace@{\tt Chv\_setNbytesInWorkspace()}}
This method sets the number of bytes in the workspace.
If {\tt nbytes} is less than the number of present bytes in the
workspace, the workspace is not shrunk.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_setFields ( Chv *chv, int id, int nD, int nL, int nU,
int type, int symflag ) ;
\end{verbatim}
\index{Chv_setFields@{\tt Chv\_setFields()}}
This method sets the scalar fields and {\tt rowind}, {\tt colind}
and {\tt entries} pointers.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
or if ${\tt nD} \le 0$,
or if {\tt nL} or {\tt nU} are less than zero,
or if {\tt type} or {\tt symflag} are not valid,
% or if {\tt type} is not {\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX},
% or if {\tt symflag} is not {\tt SPOOLES\_SYMMETRIC},
% {\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_shift ( Chv *chv, int shift ) ;
\end{verbatim}
\index{Chv_shift@{\tt Chv\_shift()}}
This method is used to shift the base of the entries and adjust
dimensions of the {\tt Chv} object.
If {\tt shift} is positive,
the first {\tt shift} chevrons are removed from the chevron.
If {\tt shift} is negative,
the {\tt shift} previous chevrons are prepended to the chevron.
This is a dangerous method as it changes the state of the object.
We use it during the factorization of a front, where one {\tt Chv}
object points to the entire chevron in order to swap rows and
columns, while another chevron points to the uneliminated rows
and columns of the front.
It is the latter chevron that is shifted during the factorization.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_fill11block ( Chv *chv, A2 *mtx ) ;
\end{verbatim}
\index{Chv_fill11block@{\tt Chv\_fill11block()}}
This method is used to fill a {\tt A2} dense matrix object with
the entries in the $(1,1)$ block of the chevron.
\par \noindent {\it Error checking:}
If {\tt chv} or {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_fill12block ( Chv *chv, A2 *mtx ) ;
\end{verbatim}
\index{Chv_fill12block@{\tt Chv\_fill12block()}}
This method is used to fill a {\tt A2} dense matrix object with
the entries in the $(1,2)$ block of the chevron.
\par \noindent {\it Error checking:}
If {\tt chv} or {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_fill21block ( Chv *chv, A2 *mtx ) ;
\end{verbatim}
\index{Chv_fill21block@{\tt Chv\_fill21block()}}
This method is used to fill a {\tt A2} dense matrix object with
the entries in the $(2,1)$ block of the chevron.
\par \noindent {\it Error checking:}
If {\tt chv} or {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double Chv_maxabs ( Chv *chv ) ;
\end{verbatim}
\index{Chv_maxabs@{\tt Chv\_maxabs()}}
This method returns the magnitude of the entry of largest magnitude
in the object.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double Chv_frobNorm ( Chv *chv ) ;
\end{verbatim}
\index{Chv_frobNorm@{\tt Chv\_frobNorm()}}
This method returns the Frobenius norm of the chevron.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_sub ( Chv *chvJ, Chv *chvI ) ;
\end{verbatim}
\index{Chv_sub@{\tt Chv\_sub()}}
This method subtracts {\tt chvI} from {\tt chvJ}.
\par \noindent {\it Error checking:}
If {\tt chvJ} or {\tt chvI} is {\tt NULL},
or if their dimensions are not the same,
or if either of their {\tt entries} fields are {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_zero ( Chv *chv ) ;
\end{verbatim}
\index{Chv_zero@{\tt Chv\_zero()}}
This method zeroes the entries in the chevron.
\par \noindent {\it Error checking:}
If {\tt chv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:Chv:proto:IO}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_writeForHumanEye ( Chv *chv, FILE *fp ) ;
\end{verbatim}
\index{Chv_writeForHumanEye@{\tt Chv\_writeForHumanEye()}}
\par
This method writes a {\tt Chv} object to a file in an easily
readable format.
\par \noindent {\it Error checking:}
If {\tt chv} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_writeForMatlab ( Chv *chv, char *chvname, FILE *fp ) ;
\end{verbatim}
\index{Chv_writeForMatlab@{\tt Chv\_writeForMatlab()}}
\par
This method writes a {\tt Chv} object to a file in a matlab format.
For a real chevron, a sample line is
\begin{verbatim}
a(10,5) = -1.550328201511e-01 ;
\end{verbatim}
where chvname = {\tt "a"}.
For a complex chevron, a sample line is
\begin{verbatim}
a(10,5) = -1.550328201511e-01 + 1.848033378871e+00*i;
\end{verbatim}
where chvname = {\tt "a"}.
The matrix indices come from the {\tt rowind[]} and {\tt colind[]}
vectors, and are incremented by one to follow the Matlab and
FORTRAN convention.
\par \noindent {\it Error checking:}
If {\tt chv}, {\tt chvname} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
\par
label{subsection:Chv:proto:swap}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Chv_swapRows ( Chv *chv, int irow, int jrow ) ;
\end{verbatim}
\index{Chv_swapRows@{\tt Chv\_swapRows()}}
This method swaps rows {\tt irow} and {\tt jrow} of theChv/doc/drivers.tex 0100644 0002055 0007177 00000042401 06571267316 0015574 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt Chv object}}
\label{section:Chv:drivers}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_addChevron msglvl msgFile nD nU type symflag seed alphareal alphaimag
\end{verbatim}
This driver program tests the {\tt Chv\_addChevron} method.
Use the script file {\tt do\_addChevron} for testing.
When the output file is loaded into matlab,
the last line to the screen is the error of the assembly.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt nD} parameter is the number of rows and columns
in the (1,1) block.
\item
The {\tt nU} parameter is the number of columns
in the (1,2) block.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt seed} parameter is a random number seed.
\item
The {\tt alphareal} and {\tt alphaimag} parameters form a complex
number that is a scaling parameter.
Normally {\tt alpha} is (1.0,0.0), when we are just loading matrix
entries into a front.
However, when we factor $A + \alpha B$, the entries of $B$ will
be loaded with {\tt alpha} set equal to $\alpha[0:1]$.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_assmbChv msglvl msgFile nDJ nUJ nDI nUI type symflag seed
\end{verbatim}
This driver program tests the {\tt Chv\_assembleChv} method.
It assembles a chevron $T_I$ into $T_J$, as is done during the
assembly of postponed rows and columns during the factorization
when pivoting is enabled.
Use the script file {\tt do\_assmbChv} for testing.
When the output file is loaded into matlab,
the last line to the screen is the error of the assembly.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt nDJ} parameter is the number of rows and columns
in the (1,1) block of $T_J$.
\item
The {\tt nUJ} parameter is the number of columns
in the (1,2) block of $T_J$.
\item
The {\tt nDI} parameter is the number of rows and columns
in the (1,1) block of $T_I$.
\item
The {\tt nUI} parameter is the number of columns
in the (1,2) block of $T_I$.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt seed} parameter is a random number seed.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_copyEntriesToVector msglvl msgFile nD nU type symflag
pivotingflag storeflag seed
\end{verbatim}
This driver program tests the {\tt Chv\_copyEntriesToVector} method
which is used when after a front has been factored to store the
entries into dense $L$ and $U$ submatrices.
Use the script file {\tt do\_copyEntriesToVector} for testing.
When the output file is loaded into matlab,
the last line to the screen is a matrix that contains two entries.
If the program executes correctly, these two entries should be
exactly zero.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt nD} parameter is the number of rows and columns
in the (1,1) block.
\item
The {\tt nU} parameter is the number of columns
in the (1,2) block.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt pivotingflag} parameter is the pivoting flag ---
{\tt SPOOLES\_NO\_PIVOTING} for no pivoting,
{\tt SPOOLES\_PIVOTING} for pivoting.
\item
The {\tt storeflag} parameter is the storage flag,
to store by rows, use {\tt SPOOLES\_BY\_ROWS},
to store by columns, use {\tt SPOOLES\_BY\_COLUMNS}.
\item
The {\tt seed} parameter is a random number seed.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_copyBigEntriesToVector msglvl msgFile nD nU type symflag
pivotingflag storeflag seed droptol
\end{verbatim}
This driver program tests the {\tt Chv\_copyBigEntriesToVector} method
which is used when after a front has been factored to store the
entries into sparse $L$ and $U$ submatrices.
Use the script file {\tt do\_copyBigEntriesToVector} for testing.
When the output file is loaded into matlab,
the last line to the screen is a matrix that contains three entries.
The first two are the maximum magnitudes of the entries that were
not copied (two different ways), and the third is the drop tolerance.
If the program executes correctly, the third term is larger than
the first two.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt nD} parameter is the number of rows and columns
in the (1,1) block.
\item
The {\tt nU} parameter is the number of columns
in the (1,2) block.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt pivotingflag} parameter is the pivoting flag ---
{\tt SPOOLES\_NO\_PIVOTING} for no pivoting,
{\tt SPOOLES\_PIVOTING} for pivoting.
\item
The {\tt storeflag} parameter is the storage flag,
to store by rows, use {\tt SPOOLES\_BY\_ROWS},
to store by columns, use {\tt SPOOLES\_BY\_COLUMNS}.
\item
The {\tt seed} parameter is a random number seed.
\item
The {\tt droptol} parameter is a drop tolerance parameters,
entries whose magnitude is smaller than {\tt droptol} are not
copied.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_factor msglvl msgFile nD nU type symflag pivotingflag seed tau
\end{verbatim}
This driver program tests the {\tt Chv\_factor} method.
Use the script file {\tt do\_factor} for testing.
When the output file is loaded into matlab,
the last line to the screen is a matrix that contains three entries.
The first entry is the error in the factorization.
The second and third entries are the maximum magnitudes of the
entries in $L$ and $U$, respectively.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt nD} parameter is the number of rows and columns
in the (1,1) block.
\item
The {\tt nU} parameter is the number of columns
in the (1,2) block.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt pivotingflag} parameter is the pivoting flag ---
{\tt SPOOLES\_NO\_PIVOTING} for no pivoting,
{\tt SPOOLES\_PIVOTING} for pivoting.
\item
The {\tt seed} parameter is a random number seed.
\item
The {\tt tau} parameter is used when pivoting is enabled.
All entries in $L$ and $U$ will have magnitudes less than {\tt tau}.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_findPivot msglvl msgFile nD nU type symflag seed tau
\end{verbatim}
This driver program tests the {\tt Chv\_findPivot} method.
Use the script file {\tt do\_findPivot} for testing.
When the output file is loaded into matlab,
look on the screen for the variables
{\tt maxerrupd} (the error in the factor and update),
{\tt ubound} (the maximum magnitude of the entries in $U$),
and if nonsymmetric
{\tt lbound} (the maximum magnitude of the entries in $L$).
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt nD} parameter is the number of rows and columns
in the (1,1) block.
\item
The {\tt nU} parameter is the number of columns
in the (1,2) block.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt seed} parameter is a random number seed.
\item
The {\tt tau} parameter is used when pivoting is enabled.
All entries in $L$ and $U$ will have magnitudes less than {\tt tau}.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_maxabs msglvl msgFile nD nU type symflag seed
\end{verbatim}
This driver program tests the
{\tt Chv\_maxabsInRow()},
{\tt Chv\_maxabsInRow11()},
{\tt Chv\_maxabsInColumn()},
{\tt Chv\_maxabsInColumn11()} and
{\tt Chv\_maxabsInDiagonal11()}
methods.
Use the script file {\tt do\_maxabs} for testing.
When the output file is loaded into matlab,
look on the screen for the variables
{\tt rowerror}, {\tt colerror},
{\tt rowerror11}, {\tt colerror11}
and {\tt diag11error}.
All should be zero.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt nD} parameter is the number of rows and columns
in the (1,1) block.
\item
The {\tt nU} parameter is the number of columns
in the (1,2) block.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt pivotingflag} parameter is the pivoting flag ---
{\tt SPOOLES\_NO\_PIVOTING} for no pivoting,
{\tt SPOOLES\_PIVOTING} for pivoting.
\item
The {\tt seed} parameter is a random number seed.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_r1upd msglvl msgFile nD nU type symflag seed
\end{verbatim}
This driver program tests the {\tt Chv\_r1upd()} method.
Use the script file {\tt do\_r1upd} for testing.
When the output file is loaded into matlab,
the last line is the error of the update.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt nD} parameter is the number of rows and columns
in the (1,1) block.
\item
The {\tt nU} parameter is the number of columns
in the (1,2) block.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt seed} parameter is a random number seed.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_r2upd msglvl msgFile nD nU type symflag seed
\end{verbatim}
This driver program tests the {\tt Chv\_r2upd()} method.
Use the script file {\tt do\_r2upd} for testing.
When the output file is loaded into matlab,
the last line is the error of the update.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt nD} parameter is the number of rows and columns
in the (1,1) block.
\item
The {\tt nU} parameter is the number of columns
in the (1,2) block.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt seed} parameter is a random number seed.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_swap msglvl msgFile nD nU type symflag seed
\end{verbatim}
This driver program tests three methods:
{\tt Chv\_swapRowsAndColumns()},
{\tt Chv\_swapRows()} and
{\tt Chv\_swapColumns()}.
Use the script file {\tt do\_swap} for testing.
When the output file is loaded into matlab,
look for the {\tt maxerrrowswap1}, {\tt maxerrcolswap1},
{\tt maxerrswap}, {\tt maxerrsymswap1} and {\tt maxerrsymswap2} values.
All should be zero.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt nD} parameter is the number of rows and columns
in the (1,1) block.
\item
The {\tt nU} parameter is the number of columns
in the (1,2) block.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt seed} parameter is a random number seed.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
test_update msglvl msgFile type symflag sparsityflag
ncolT ncolU nrowD nentU offset seed
\end{verbatim}
This driver program tests the
{\tt Chv\_updateH()},
{\tt Chv\_updateS()} and
{\tt Chv\_updateN()} methods.
The {\tt Chv} object $T$ is updated by $-U^TDU$, $-U^HDU$ or $-LDU$,
depending on whether $T$ is symmetric, hermitian or nonsymmetric.
Use the script file {\tt do\_update} for testing.
When the output file is loaded into matlab,
the last line is the error in the update which should be zero.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt type} parameter denotes the type of entries ---
{\tt SPOOLES\_REAL} or {\tt SPOOLES\_COMPLEX}
\item
The {\tt symflag} parameter is the symmetry flag ---
{\tt SPOOLES\_SYMMETRIC}, {\tt SPOOLES\_HERMITIAN}
or {\tt SPOOLES\_NONSYMMETRIC}.
\item
The {\tt sparsityflag} parameter should be zero for dense $U$ and $L$,
or 1 for sparse $U$ and $L$.
\item
The {\tt ncolT} parameter is the number of columns
in the (1,1) and (1,2) blocks of $T$.
\item
The {\tt nDT} parameter is the number of rows and columns
in the (1,1) block of $T$.
\item
The {\tt ncolU} parameter is the number of columns in $U$.
\item
The {\tt nrowD} parameter is the number of rows and columns in $D$.
\item
The {\tt nentU} parameter is the number entries in $U$, ignored if
{\tt sparsityflag = 0}.
\item
The {\tt offset} parameter is the offset of first index in $T$ from
the last index in $D$.
\item
The {\tt seed} parameter is a random number seed.
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
le {\tt do\_factor} for testing.
When the output file is loaded into matlab,
the last line to the screen is a matrix that contains three entries.
The first entry is the error in the factorization.
The second and third entries are the maximum magnitudes ofChv/doc/temp.tex 0100644 0002055 0007177 00000005125 06571267316 0015065 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentstyle[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\newcommand{\bnd}{{\partial}}
\renewcommand{\Re}{{\mbox{Re}}}
\renewcommand{\Im}{{\mbox{Im}}}
\input psfig
\makeindex
\begin{document}
$$
\left \lbrack \begin{array}{cc}
x & y \\
\overline{y} & z
\end{array} \right \rbrack
\left \lbrack \begin{array}{c}
u_{1,j} \\
u_{2,j}
\end{array} \right \rbrack
=
\left \lbrack \begin{array}{c}
a_{1,j} \\
a_{2,j}
\end{array} \right \rbrack
$$
Multiply on the left by the inverse of the pivot block.
$$
\left \lbrack \begin{array}{c}
u_{1,j} \\
u_{2,j}
\end{array} \right \rbrack
=
\frac{1}{xz - y\overline{y}}
\left \lbrack \begin{array}{cc}
z & -y \\
-\overline{y} & x
\end{array} \right \rbrack
\left \lbrack \begin{array}{c}
a_{1,j} \\
a_{2,j}
\end{array} \right \rbrack
=
\frac{1}{xz - y\overline{y}}
\left \lbrack \begin{array}{c}
z a_{1,j} - y a_{2,j} \\
- \overline{y} a_{1,j} + x a_{2,j}
\end{array} \right \rbrack
$$
Look at each of the two entries in the rightmost vector.
\begin{eqnarray*}
z a_{1,j} - y a_{2,j}
& = &
\Re(z) ( \Re(a_{1,j}) + i\ \Im(a_{1,j}) )
- ( \Re(y) + i\ \Im(y) )( \Re(a_{2,j}) + i\ \Im(a_{2,I}) )
\\
& = &
(
\Re(z) \Re(a_{1,j}) - \Re(y) \Re(a_{2,j}) + \Im(y) \Im(a_{2,I})
) \\
& &
\qquad +\ i(
\Re(z) \Im(a_{1,j}) - \Re(y) \Im(a_{2,I}) - \Im(y) \Re(a_{2,j})
)
\\
- \overline{y} a_{1,j} + x a_{2,j}
& = &
-( \Re(y) - i \Im(y) ) ( \Re(a_{1,j}) + i \Im(a_{1,j}) )
+ \Re(x) ( \Re(a_{2,j}) + i \Im(a_{2,I}) )
\\
& = &
(
-\Re(y) \Re(a_{1,j}) - \Im(y) \Im(a_{1,j}) + x \Re(a_{2,j})
) \\
& &
\qquad + i\ (
-\Re(y) \Im(a_{1,j}) + \Im(y) \Re(a_{1,j}) + x \Im(a_{2,I})
)
\end{eqnarray*}
\begin{eqnarray*}
\Re(u_{1,j})
& = &
\frac{ \Re(z) \Re(a_{1,j}) - \Re(y) \Re(a_{2,j})
+ \Im(y) \Im(a_{2,j}) }
{ xz - y\overline{y} }
\\
\Im(u_{1,j})
& = &
\frac{ \Re(z) \Im(a_{1,j}) - \Re(y) \Im(a_{2,I}) - \Im(y) \Re(a_{2,j}) }
{ xz - y\overline{y} }
\end{eqnarray*}
Taking absolute values and use the triangle inequality.
\begin{eqnarray*}
\Re(u_{1,j})
& = &
\left |
\frac{ \Re(z) \Re(a_{1,j}) - \Re(y) \Re(a_{2,j})
+ \Im(y) \Im(a_{2,j}) }
{ xz - y\overline{y} }
\right |
\\
& \le &
\frac{
|\Re(z)|\ |\Re(a_{1,j})| + |\Re(y)|\ |\Re(a_{2,j})|
+ |\Im(y)|\ |\Im(a_{2,j})|
} {
\left | xz - y\overline{y} \right |
}
\\
\max_{j} |\Re(u_{1,j})|
& \le &
\frac{
|\Re(z)|\ \max_j|\Re(a_{1,j})| + |\Re(y)|\ \max_j|\Re(a_{2,j})|
+ |\Im(y)|\ \max_j|\Im(a_{2,j})|
} {
\left | xz - y\overline{y} \right |
}
\\
\end{eqnarray*}
\end{document}
Chv/doc/temp.log 0100644 0002055 0007177 00000002512 06571267316 0015043 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 24 JAN 1998 13:38
**temp
(temp.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
) (/usr/local/lib/texmf/tex/generic/psfig/psfig.tex
\@unused=\write3
\ps@stream=\read1
\p@intvaluex=\dimen100
\p@intvaluey=\dimen101
psfig/tex 1.10-dvips
)
\@indexfile=\write4
Writing index file temp.idx
(temp.aux) [1
] (temp.aux) )
Here is how much of TeX's memory you used:
397 strings out of 11977
3945 string characters out of 87269
37241 words of memory out of 262141
2344 multiletter control sequences out of 9500
18996 words of font info for 72 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
12i,9n,17p,149b,94s stack positions out of 300i,40n,60p,3000b,4000s
Output written on temp.dvi (1 page, 4344 bytes).
Chv/doc/temp.idx 0100644 0002055 0007177 00000000000 06571267316 0015034 0 ustar 00cleve compmath 0000040 0000006 Chv/doc/temp.aux 0100644 0002055 0007177 00000000010 06571267316 0015046 0 ustar 00cleve compmath 0000040 0000006 \relax
Chv/doc/simple2.eps 0100644 0002055 0007177 00000004146 06571267316 0015464 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 220.0 100.0
%%%EndComments
/NumberFont /Helvetica findfont 7 scalefont def
NumberFont setfont
/CSH {
dup stringwidth pop 2 div neg 2 rmoveto show
} def
gsave
%
% first chevron
%
10 5 moveto (0) CSH
10 15 moveto (1) CSH
10 25 moveto (2) CSH
10 35 moveto (3) CSH
10 45 moveto (4) CSH
10 55 moveto (5) CSH
10 65 moveto (6) CSH
10 75 moveto (7) CSH
10 85 moveto (8) CSH
20 85 moveto (9) CSH
30 85 moveto (10) CSH
40 85 moveto (11) CSH
50 85 moveto (12) CSH
60 85 moveto (13) CSH
70 85 moveto (14) CSH
80 85 moveto (15) CSH
90 85 moveto (16) CSH
%
% second chevron
%
20 5 moveto (17) CSH
20 15 moveto (18) CSH
20 25 moveto (19) CSH
20 35 moveto (20) CSH
20 45 moveto (21) CSH
20 55 moveto (22) CSH
20 65 moveto (23) CSH
20 75 moveto (24) CSH
30 75 moveto (25) CSH
40 75 moveto (26) CSH
50 75 moveto (27) CSH
60 75 moveto (28) CSH
70 75 moveto (29) CSH
80 75 moveto (30) CSH
90 75 moveto (31) CSH
%
% third chevron
%
30 5 moveto (32) CSH
30 15 moveto (33) CSH
30 25 moveto (34) CSH
30 35 moveto (35) CSH
30 45 moveto (36) CSH
30 55 moveto (37) CSH
30 65 moveto (38) CSH
40 65 moveto (39) CSH
50 65 moveto (40) CSH
60 65 moveto (41) CSH
70 65 moveto (42) CSH
80 65 moveto (43) CSH
90 65 moveto (44) CSH
0 0 100 100 rectstroke
grestore
gsave
120 0 translate
%
% first chevron
%
10 85 moveto (0) CSH
20 85 moveto (1) CSH
30 85 moveto (2) CSH
40 85 moveto (3) CSH
50 85 moveto (4) CSH
60 85 moveto (5) CSH
70 85 moveto (6) CSH
80 85 moveto (7) CSH
90 85 moveto (8) CSH
%
% second chevron
%
20 75 moveto (9) CSH
30 75 moveto (10) CSH
40 75 moveto (11) CSH
50 75 moveto (12) CSH
60 75 moveto (13) CSH
70 75 moveto (14) CSH
80 75 moveto (15) CSH
90 75 moveto (16) CSH
%
% third chevron
%
30 65 moveto (17) CSH
40 65 moveto (18) CSH
50 65 moveto (19) CSH
60 65 moveto (20) CSH
70 65 moveto (21) CSH
80 65 moveto (22) CSH
90 65 moveto (23) CSH
0 0 100 100 rectstroke
grestore
showpage
Chv/doc/simple.eps 0100644 0002055 0007177 00000001103 06571267316 0015370 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 100.0 100.0
%%%EndComments
%
% center then show a string
%
/CSH {
%
% stack
% string str
%
dup stringwidth pop 2 div neg 0 rmoveto
show
} def
gsave
0.5 setgray
25 0 75 75 rectfill
1.0 setgray
50 0 50 50 rectfill
0.0 setgray
0 0 100 100 rectstroke
25 50 25 25 rectstroke
25 0 25 75 rectstroke
50 50 50 25 rectstroke
/Helvetica findfont 10 scalefont setfont
1.0 setgray
37.5 60 moveto (\(1,1\)) CSH
75 60 moveto (\(1,2\)) CSH
37.5 25 moveto (\(2,1\)) CSH
grestore
showpage
Chv/doc/makefile 0100644 0002055 0007177 00000000027 06571267316 0015072 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
Chv/doc/simple.eps.bak 0100644 0002055 0007177 00000000270 06571267317 0016131 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 100.0 100.0
%%%EndComments
0.5 setgray
25 0 75 75 rectfill
1.0 setgray
50 0 50 50 rectfill
0.0 setgray
0 0 100 100 rectstroke
showpage
ChvList.h 0100644 0002055 0007177 00000000110 06534106411 0013606 0 ustar 00cleve compmath 0000040 0000006 #ifndef _ChvList_
#define _ChvList_
#include "ChvList/ChvList.h"
#endif
ChvList/ChvList.h 0100644 0002055 0007177 00000013302 06536244332 0015200 0 ustar 00cleve compmath 0000040 0000006 /* ChvList.h */
#include "../Chv.h"
#include "../Lock.h"
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
this object handles a list of lists of Chv objects
nlist -- # of lists
heads -- heads[ilist] contains a pointer
to the first Chv object in list ilist
counts -- when not-NULL, counts[ilist] contains the remaining number
of objects to be added to list ilist before it is complete
lock -- mutex object, can be NULL
flags -- when not NULL, a vector to specify when a list needs
to be locked before adding an object to it.
flags[ilist] = 'N' --> no need to lock
flags[ilist] = 'Y' --> must lock
nlocks -- number of times the list was locked
--------------------------------------------------------------------
*/
typedef struct _ChvList ChvList ;
struct _ChvList {
int nlist ;
Chv **heads ;
int *counts ;
Lock *lock ;
char *flags ;
int nlocks ;
} ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
simplest constructor
created -- 98may02, cca
-----------------------
*/
ChvList *
ChvList_new (
void
) ;
/*
-----------------------
set the default fields
created -- 98may02, cca
-----------------------
*/
void
ChvList_setDefaultFields (
ChvList *chvlist
) ;
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98may02, cca
--------------------------------------------------
*/
void
ChvList_clearData (
ChvList *chvlist
) ;
/*
------------------------------------------
destructor, free's the object and its data
created -- 98may02, cca
------------------------------------------
*/
void
ChvList_free (
ChvList *chvlist
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------------
purpose -- basic initializer
nlist -- number of lists to be held by this object
counts -- vector that contains number of items expected
for each list.
counts == NULL --> unknown number of items expected
counts != NULL --> known number of items expected
lockflag -- flag to specify lock status
lockflag = 0 --> mutex lock is not allocated or initialized
lockflag = 1 --> mutex lock is allocated and it can synchronize
only threads in this process.
lockflag = 2 --> mutex lock is allocated and it can synchronize
threads in this and other processes.
flags -- vector to specify whether to lock individual lists
flags == NULL --> none or all lists must be locked,
use lockflag to determine
flags[ilist] = 'N' --> no need to lock list ilist
flags[ilist] = 'Y' --> must lock list ilist
created -- 98may02, cca
------------------------------------------------------------------
*/
void
ChvList_init (
ChvList *chvlist,
int nlist,
int counts[],
int lockflag,
char flags[]
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in IO.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
created -- 98may02, cca
----------------------------------------
*/
void
ChvList_writeForHumanEye (
ChvList *chvlist,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in util.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------
return 1 if list ilist is not empty
return 0 if list ilist is empty
created -- 98may02, cca
-----------------------------------
*/
int
ChvList_isListNonempty (
ChvList *chvlist,
int ilist
) ;
/*
---------------------------------------------------------
return 1 if the count for list ilist is zero
return 0 if the count for list ilist is greater than zero
created -- 98may02, cca
---------------------------------------------------------
*/
int
ChvList_isCountZero (
ChvList *chvlist,
int ilist
) ;
/*
---------------------------------
if chv is not NULL then
add chv to list ilist
endif
decrement the count of list ilist
created -- 98may02, cca
---------------------------------
*/
void
ChvList_addObjectToList (
ChvList *chvlist,
Chv *chv,
int ilist
) ;
/*
------------------------------------
return pointer to head of list ilist
and set head to NULL
created -- 98may02, cca
------------------------------------
*/
Chv *
ChvList_getList (
ChvList *chvlist,
int ilist
) ;
/*--------------------------------------------------------------------*/
ChvList/makefile 0100644 0002055 0007177 00000000141 06636223550 0015150 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd doc ; make clean
ChvList/src/makefile 0100644 0002055 0007177 00000000674 06636021527 0015752 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = ChvList
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(init.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
ChvList/src/makeGlobalLib 0100644 0002055 0007177 00000000575 06600260754 0016660 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = ChvList
SRC = basics.c \
init.c \
IO.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
ChvList/src/IO.c 0100644 0002055 0007177 00000003270 06534106247 0014720 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../ChvList.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
created -- 98may02, cca
----------------------------------------
*/
void
ChvList_writeForHumanEye (
ChvList *chvlist,
FILE *fp
) {
Chv *chv ;
int ilist ;
/*
---------------
check the input
---------------
*/
if ( chvlist == NULL || fp == NULL ) {
fprintf(stderr,
"\n fatal error in ChvList_writeForHumanEye(%p,%p)"
"\n bad input\n", chvlist, fp) ;
exit(-1) ;
}
fprintf(fp, "\n ChvList object at address %p"
"\n %d lists, %d locks",
chvlist, chvlist->nlist, chvlist->nlocks) ;
if ( chvlist->lock != NULL ) {
fprintf(fp, "\n lock located at %p", chvlist->lock) ;
} else {
fprintf(fp, "\n lock is NULL") ;
}
for ( ilist = 0 ; ilist < chvlist->nlist ; ilist++ ) {
fprintf(fp, "\n %6d", ilist) ;
if ( chvlist->counts != NULL ) {
fprintf(fp, " %6d", chvlist->counts[ilist]) ;
} else {
fprintf(fp, " %6d", 0) ;
}
if ( chvlist->flags != NULL ) {
fprintf(fp, " %6c", chvlist->flags[ilist]) ;
} else {
fprintf(fp, " %6c", 'N') ;
}
if ( chvlist->heads != NULL && chvlist->heads[ilist] != NULL ) {
fprintf(fp, " %10p", chvlist->heads[ilist]) ;
} else {
fprintf(fp, " NULL") ;
}
}
/*
for ( chv = chvlist->head ; chv != NULL ; chv = chv->next ) {
fprintf(fp, "\n chv %d, nbytes %d",
chv->id, Chv_nbytesInWorkspace(chv)) ;
}
*/
return ; }
/*--------------------------------------------------------------------*/
ChvList/src/basics.c 0100644 0002055 0007177 00000005026 06534106247 0015656 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../ChvList.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------
simplest constructor
created -- 98may02, cca
-----------------------
*/
ChvList *
ChvList_new (
void
) {
ChvList *chvlist ;
ALLOCATE(chvlist, struct _ChvList, 1) ;
ChvList_setDefaultFields(chvlist) ;
return(chvlist) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 98may02, cca
-----------------------
*/
void
ChvList_setDefaultFields (
ChvList *chvlist
) {
if ( chvlist == NULL ) {
fprintf(stderr, "\n fatal error in ChvList_setDefaultFields(%p)"
"\n bad input", chvlist) ;
exit(-1) ;
}
chvlist->nlist = 0 ;
chvlist->heads = NULL ;
chvlist->counts = NULL ;
chvlist->lock = NULL ;
chvlist->flags = NULL ;
chvlist->nlocks = 0 ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98may02, cca
--------------------------------------------------
*/
void
ChvList_clearData (
ChvList *chvlist
) {
/*
---------------
check the input
---------------
*/
if ( chvlist == NULL ) {
fprintf(stderr, "\n fatal error in ChvList_clearData(%p)"
"\n bad input\n", chvlist) ;
exit(-1) ;
}
/*
-------------
free the data
-------------
*/
if ( chvlist->heads != NULL ) {
FREE(chvlist->heads) ;
}
if ( chvlist->counts != NULL ) {
IVfree(chvlist->counts) ;
}
if ( chvlist->flags != NULL ) {
CVfree(chvlist->flags) ;
}
if ( chvlist->lock != NULL ) {
/*
-------------------------
destroy and free the lock
-------------------------
*/
Lock_free(chvlist->lock) ;
}
/*
----------------------
set the default fields
----------------------
*/
ChvList_setDefaultFields(chvlist) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
destructor, free's the object and its data
created -- 98may02, cca
------------------------------------------
*/
void
ChvList_free (
ChvList *chvlist
) {
if ( chvlist == NULL ) {
fprintf(stderr, "\n fatal error in ChvList_free(%p)"
"\n bad input\n", chvlist) ;
exit(-1) ;
}
ChvList_clearData(chvlist) ;
FREE(chvlist) ;
return ; }
/*--------------------------------------------------------------------*/
ChvList/src/init.c 0100644 0002055 0007177 00000005374 06534106247 0015363 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../ChvList.h"
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
purpose -- basic initializer
nlist -- number of lists to be held by this object
counts -- vector that contains number of items expected
for each list.
counts == NULL --> unknown number of items expected
counts != NULL --> known number of items expected
lockflag -- flag to specify lock status
lockflag = 0 --> mutex lock is not allocated or initialized
lockflag = 1 --> mutex lock is allocated and it can synchronize
only threads in this process.
lockflag = 2 --> mutex lock is allocated and it can synchronize
only threads in this and other processes.
flags -- vector to specify whether to lock individual lists
flags == NULL --> none or all lists must be locked,
use lockflag to determine
flags[ilist] = 'N' --> no need to lock list ilist
flags[ilist] = 'Y' --> must lock list ilist
created -- 98may02, cca
------------------------------------------------------------------
*/
void
ChvList_init (
ChvList *chvlist,
int nlist,
int counts[],
int lockflag,
char flags[]
) {
int ilist ;
/*
---------------
check the input
---------------
*/
if ( chvlist == NULL || nlist <= 0 || lockflag < 0 || lockflag > 1 ) {
fprintf(stderr, "\n fatal error in ChvList_init(%p,%d,%p,%d,%p)"
"\n bad input\n", chvlist, nlist, counts, lockflag, flags) ;
exit(-1) ;
}
/*
--------------
clear all data
--------------
*/
ChvList_clearData(chvlist) ;
/*
-------------------------------------------------------
set the number of lists and allocate the heads[] vector
-------------------------------------------------------
*/
chvlist->nlist = nlist ;
ALLOCATE(chvlist->heads, struct _Chv *, nlist) ;
for ( ilist = 0 ; ilist < nlist ; ilist++ ) {
chvlist->heads[ilist] = NULL ;
}
if ( counts != NULL ) {
/*
-------------------------------------
allocate and fill the counts[] vector
-------------------------------------
*/
chvlist->counts = IVinit(nlist, 0) ;
IVcopy(nlist, chvlist->counts, counts) ;
}
if ( lockflag > 0 ) {
/*
-----------------
allocate the lock
-----------------
*/
chvlist->lock = Lock_new() ;
Lock_init(chvlist->lock, lockflag) ;
}
if ( flags != NULL ) {
/*
------------------------------------
allocate and fill the flags[] vector
------------------------------------
*/
chvlist->flags = CVinit(nlist, 'N') ;
CVcopy(nlist, chvlist->flags, flags) ;
}
return ; }
/*--------------------------------------------------------------------*/
ChvList/src/util.c 0100644 0002055 0007177 00000011672 06536244373 0015400 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../ChvList.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------------------
return 1 if list ilist is not empty
return 0 if list ilist is empty
created -- 98may02, cca
-----------------------------------
*/
int
ChvList_isListNonempty (
ChvList *chvlist,
int ilist
) {
/*
---------------
check the input
---------------
*/
if ( chvlist == NULL || ilist < 0 || ilist >= chvlist->nlist ) {
fprintf(stderr, "\n fatal error in ChvList_isListNonempty(%p,%d)"
"\n bad input\n", chvlist, ilist) ;
}
return(chvlist->heads[ilist] != NULL) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
return 1 if the count for list ilist is zero
return 0 if the count for list ilist is greater than zero
created -- 98may02, cca
---------------------------------------------------------
*/
int
ChvList_isCountZero (
ChvList *chvlist,
int ilist
) {
/*
---------------
check the input
---------------
*/
if ( chvlist == NULL || ilist < 0 || ilist >= chvlist->nlist ) {
fprintf(stderr, "\n fatal error in ChvList_isCountZero(%p,%d)"
"\n bad input\n", chvlist, ilist) ;
}
if ( chvlist->counts == NULL ) {
return(1) ;
} else {
return(chvlist->counts[ilist] == 0) ;
}
}
/*--------------------------------------------------------------------*/
/*
---------------------------------
if chv is not NULL then
add chv to list ilist
endif
decrement the count of list ilist
created -- 98may02, cca
---------------------------------
*/
void
ChvList_addObjectToList (
ChvList *chvlist,
Chv *chv,
int ilist
) {
/*
---------------
check the input
---------------
*/
if ( chvlist == NULL || ilist < 0 || ilist >= chvlist->nlist ) {
fprintf(stderr,
"\n fatal error in ChvList_addObjectToList(%p,%p,%d)"
"\n bad input\n", chvlist, chv, ilist) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n ChvList %p : adding chv %p to list %d",
chvlist, chv, ilist) ;
fflush(stdout) ;
#endif
if ( chvlist->lock != NULL
&& (chvlist->flags == NULL || chvlist->flags[ilist] == 'Y' ) ) {
/*
--------------------------------------------------
we must lock the list to (possibly) add the object
and decrement the list's count
--------------------------------------------------
*/
Lock_lock(chvlist->lock) ;
if ( chv != NULL ) {
chv->next = chvlist->heads[ilist] ;
chvlist->heads[ilist] = chv ;
}
if ( chvlist->counts != NULL ) {
chvlist->counts[ilist]-- ;
}
chvlist->nlocks++ ;
Lock_unlock(chvlist->lock) ;
} else {
/*
---------------------------------------------
no need to lock the list, just (possibly)
add the object and decrement the list's count
---------------------------------------------
*/
if ( chv != NULL ) {
chv->next = chvlist->heads[ilist] ;
chvlist->heads[ilist] = chv ;
}
if ( chvlist->counts != NULL ) {
chvlist->counts[ilist]-- ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n ChvList %p : heads[%d] = %p, counts[%d] = %d",
chvlist, ilist, chvlist->heads[ilist],
ilist, chvlist->counts[ilist]) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
return pointer to head of list ilist
and set head to NULL
created -- 98may02, cca
------------------------------------
*/
Chv *
ChvList_getList (
ChvList *chvlist,
int ilist
) {
Chv *chv ;
/*
---------------
check the input
---------------
*/
if ( chvlist == NULL || ilist < 0 || ilist >= chvlist->nlist ) {
fprintf(stderr,
"\n fatal error in ChvList_getList(%p,%d)"
"\n bad input\n", chvlist, ilist) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n ChvList %p : get list %d", chvlist, ilist) ;
fflush(stdout) ;
#endif
if ( chvlist->heads[ilist] != NULL ) {
if ( chvlist->lock == NULL
|| (chvlist->flags != NULL && chvlist->flags[ilist] == 'N')
|| (chvlist->counts != NULL && chvlist->counts[ilist] == 0) ) {
/*
------------------------
no need to lock the list
------------------------
*/
chv = chvlist->heads[ilist] ;
chvlist->heads[ilist] = NULL ;
} else {
/*
----------------------------------------------------
we must lock the list to return the head of the list
----------------------------------------------------
*/
Lock_lock(chvlist->lock) ;
chv = chvlist->heads[ilist] ;
chvlist->heads[ilist] = NULL ;
chvlist->nlocks++ ;
Lock_unlock(chvlist->lock) ;
}
} else {
chv = NULL ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n ChvList %p : chv %p", chvlist, chv) ;
fflush(stdout) ;
#endif
return(chv) ; }
/*--------------------------------------------------------------------*/
ChvList/doc/ 0042755 0002055 0007177 00000000000 06542767330 0014233 5 ustar 00cleve compmath 0000040 0000006 ChvList/doc/dataStructure.tex 0100644 0002055 0007177 00000001333 06536242410 0017570 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:ChvList:dataStructure}
\par
\par
The {\tt ChvList} structure has the following fields.
\begin{itemize}
\item
{\tt int nlist} : number of lists.
\item
{\tt Chv **heads} :
vector of pointers to the heads of the list of {\tt Chv} objects.
\item
{\tt int *counts} : vector of incoming counts for the lists.
\item
{\tt Lock *lock} : mutual exclusion lock.
\item
{\tt char *flags} : vector of lock flags for the lists.
If {\tt flags[ilist] == 'N'}, the list does not need to be locked.
If {\tt flags[ilist] == 'Y'}, the list does need to be locked.
Used only when {\tt lock} is not {\tt NULL}.
\item
{\tt int nlocks} :
total number of locks made on the mutual exclusion lock.
\end{itemize}
ChvList/doc/intro.tex 0100644 0002055 0007177 00000005302 06536242377 0016105 0 ustar 00cleve compmath 0000040 0000006 \par
\chapter{{\tt ChvList}: {\tt Chv} list object }
\par
This object was created to handle a list of lists of {\tt
Chv} objects during a matrix factorization.
Its form and function is very close to the {\tt SubMtxList} object
that handles lists of lists of {\tt SubMtx} objects during the
forward and backsolves.
\par
Here are the main properties.
\begin{enumerate}
\item
There are a fixed number of lists, set when the {\tt ChvList}
object is initialized.
\item
For each list there is an expected count, the number of times an
object will be added to the list. (Note, a {\tt NULL} object can be
added to the list. In this case, nothing is added to the list,
but its count is decremented.)
\item
There is one lock for all the lists, but each list can be flagged
as necessary to lock or not necessary to lock before an insertion,
count decrement, or an extraction is made to the list.
\end{enumerate}
\par
The {\tt ChvList} object manages a number of lists that may require
handling critical sections of code.
For example, one thread may want to add an object to a particular
list while another thread is removing objects.
The critical sections are hidden inside the {\tt ChvList} object.
Our factorization code does not know about any mutual exclusion
locks that govern access to the lists.
\par
There are four functions of the {\tt ChvList} object.
\begin{itemize}
\item
Is the incoming count for a list nonzero?
\item
Is a list nonempty?
\item
Add an object to a list (possibly a {\tt NULL} object) and
decrement the incoming count.
\item
Remove a subset of objects from a list.
\end{itemize}
The first two operations are queries, and can be done without
locking the list.
The third operation needs a lock only when two or more threads will
be inserting objects into the list.
The fourth operation requires a lock only when one thread will add
an object while another thread removes the object and the incoming
count is not yet zero.
\par
Having a lock associated with a {\tt ChvList} object is optional,
for example, it is not needed during a serial factorization nor a
MPI factorization.
In the latter case there is one {\tt ChvList} per process.
For a multithreaded factorization there is one {\tt ChvList}
object that is shared by all threads.
The mutual exclusion lock that is (optionally) embedded in the {\tt
ChvList} object is a {\tt Lock} object from this library.
It is inside the {\tt Lock} object that we have a
mutual exclusion lock.
Presently we support the Solaris and POSIX thread packages.
Porting the multithreaded codes to another platform should be
simple if the POSIX thread package is present.
Another type of thread package will require some modifications
to the {\tt Lock} object, but none to the {\tt ChvList} objects.
\par
e to the {\tt SubMtxList} object
that handles lists of lists of {\tt SubMtx} objects during the
forward and backsolves.
\par
Here are the main properties.
\begin{enumerate}
\item
There are a fixed number of lists, set when the {\tt ChvList}
object is initialized.
\item
For each list there is an expected count, the nuChvList/doc/main.aux 0100644 0002055 0007177 00000002373 06536242431 0015667 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}{\string\ptt\space ChvList}: {\string\ptt\space Chv} list object }{1}}
\@writefile{lof}{\string\addvspace\space {10\p@ }}
\@writefile{lot}{\string\addvspace\space {10\p@ }}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Data Structure}{2}}
\newlabel{section:ChvList:dataStructure}{{1.1}{2}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Prototypes and descriptions of {\string\ptt\space ChvList} methods}{2}}
\newlabel{section:ChvList:proto}{{1.2}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.1}Basic methods}{2}}
\newlabel{subsection:ChvList:proto:basics}{{1.2.1}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Initialization methods}{3}}
\newlabel{subsection:ChvList:proto:initial}{{1.2.2}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.3}Utility methods}{3}}
\newlabel{subsection:ChvList:proto:utility}{{1.2.3}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.4}IO methods}{4}}
\newlabel{subsection:ChvList:proto:IO}{{1.2.4}{4}}
ChvList/doc/main.idx 0100644 0002055 0007177 00000001164 06536242431 0015653 0 ustar 00cleve compmath 0000040 0000006 \indexentry{ChvList_new@{\tt ChvList\_new()}}{2}
\indexentry{ChvList_setDefaultFields@{\tt ChvList\_setDefaultFields()}}{2}
\indexentry{ChvList_clearData@{\tt ChvList\_clearData()}}{3}
\indexentry{ChvList_free@{\tt ChvList\_free()}}{3}
\indexentry{ChvList_init@{\tt ChvList\_init()}}{3}
\indexentry{ChvList_isListNonempty@{\tt ChvList\_isListNonempty()}}{3}
\indexentry{ChvList_isCountZero@{\tt ChvList\_isCountZero()}}{3}
\indexentry{ChvList_getList@{\tt ChvList\_getList()}}{4}
\indexentry{ChvList_addObjectToList@{\tt ChvList\_addObjectToList()}}{4}
\indexentry{ChvList_writeForHumanEye@{\tt ChvList\_writeForHumanEye()}}{4}
ChvList/doc/main.ilg 0100644 0002055 0007177 00000000456 06536242427 0015652 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (10 entries accepted, 0 rejected).
Sorting entries....done (36 comparisons).
Generating output file main.ind....done (14 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
ChvList/doc/main.ind 0100644 0002055 0007177 00000000647 06536242427 0015653 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt ChvList\_addObjectToList()}, 4
\item {\tt ChvList\_clearData()}, 3
\item {\tt ChvList\_free()}, 3
\item {\tt ChvList\_getList()}, 4
\item {\tt ChvList\_init()}, 3
\item {\tt ChvList\_isCountZero()}, 3
\item {\tt ChvList\_isListNonempty()}, 3
\item {\tt ChvList\_new()}, 2
\item {\tt ChvList\_setDefaultFields()}, 2
\item {\tt ChvList\_writeForHumanEye()}, 4
\end{theindex}
ChvList/doc/main.log 0100644 0002055 0007177 00000003062 06536242431 0015647 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 6 JUN 1998 06:33
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
) (/usr/local/lib/texmf/tex/generic/psfig/psfig.tex
\@unused=\write3
\ps@stream=\read1
\p@intvaluex=\dimen100
\p@intvaluey=\dimen101
psfig/tex 1.10-dvips
)
\@indexfile=\write4
Writing index file main.idx
(main.aux) (intro.tex
Chapter 1.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 2.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 2.
[1
]) (dataStructure.tex) (proto.tex [2] [3]) (main.ind [4] [5
]) (main.aux) )
Here is how much of TeX's memory you used:
421 strings out of 11977
4265 string characters out of 87269
36690 words of memory out of 262141
2356 multiletter control sequences out of 9500
19780 words of font info for 75 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
13i,4n,17p,184b,199s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (5 pages, 11544 bytes).
ChvList/doc/main.tex 0100644 0002055 0007177 00000001136 06650656174 0015700 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\newcommand{\bnd}{{\partial}}
\input psfig
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt ChvList} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt ChvList} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input main.ind
\end{document}
ChvList/doc/proto.tex 0100644 0002055 0007177 00000016501 06536242471 0016113 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt ChvList} methods}
\label{section:ChvList:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt ChvList} object.
\par
\subsection{Basic methods}
\label{subsection:ChvList:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ChvList * ChvList_new ( void ) ;
\end{verbatim}
\index{ChvList_new@{\tt ChvList\_new()}}
This method simply allocates storage
for the {\tt ChvList} structure
and then sets the default fields by a call to
{\tt ChvList\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvList_setDefaultFields ( ChvList *list ) ;
\end{verbatim}
\index{ChvList_setDefaultFields@{\tt ChvList\_setDefaultFields()}}
The structure's fields are set to default values:
{\tt nlist} and {\tt nlocks} set to zero,
and {\tt heads}, {\tt counts}, {\tt lock} and {\tt flags}
are set to {\tt NULL} .
\par \noindent {\it Error checking:}
If {\tt list} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvList_clearData ( ChvList *list ) ;
\end{verbatim}
\index{ChvList_clearData@{\tt ChvList\_clearData()}}
This method clears the object and free's any owned data
by calling {\tt Chv\_free()} for each object on the free
list.
If {\tt heads} is not {\tt NULL}, it is free'd.
If {\tt counts} is not {\tt NULL},
it is free'd via a call to {\tt IVfree()}.
If {\tt flags} is not {\tt NULL},
it is free'd via a call to {\tt CVfree()}.
If the lock is not {\tt NULL}, it is destroyed via a call to
{\tt Lock\_free()}.
There is a concluding call to
{\tt ChvList\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt list} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvList_free ( ChvList *list ) ;
\end{verbatim}
\index{ChvList_free@{\tt ChvList\_free()}}
This method releases any storage by a call to
{\tt ChvList\_clearData()}
and then free the space for {\tt list}.
\par \noindent {\it Error checking:}
If {\tt list} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initialization methods}
\label{subsection:ChvList:proto:initial}
\par
There are three initializer methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvList_init( ChvList *list, int nlist, int counts[],
int lockflag, char flags[] ) ;
\end{verbatim}
\index{ChvList_init@{\tt ChvList\_init()}}
Any data is cleared via a call to
{\tt ChvList\_clearData()}.
The number of lists is set and the {\tt heads[]} vector is
initialized.
If {\tt counts} is not {\tt NULL}, the object's {\tt counts[]}
vector is allocated and filled with the incoming entries.
If {\tt lockflag} is zero, the lock is not initialized.
If {\tt lockflag} is {\tt 1}, the lock is initialized
to be able to synchronize threads with the calling process.
If {\tt lockflag} is {\tt 2}, the lock is initialized
to be able to synchronize threads across processes.
If {\tt flags} is not {\tt NULL}, the object's {\tt flags[]}
vector is allocated and filled with the incoming entries.
\par \noindent {\it Error checking:}
If {\tt list} is {\tt NULL},
or if ${\tt nlist} \le 0$,
or if {\tt lockflag} is not in {\tt [0,2]},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:ChvList:proto:utility}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ChvList_isListNonempty ( ChvList *list, int ilist ) ;
\end{verbatim}
\index{ChvList_isListNonempty@{\tt ChvList\_isListNonempty()}}
\par
If list {\tt ilist} is empty, the method returns 0.
Otherwise, the method returns 1.
\par \noindent {\it Error checking:}
If {\tt list} is {\tt NULL},
or if {\tt ilist} is not in the range {\tt [0,nlist)},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ChvList_isCountZero ( ChvList *list, int ilist ) ;
\end{verbatim}
\index{ChvList_isCountZero@{\tt ChvList\_isCountZero()}}
\par
If {\tt counts} is {\tt NULL},
or if {\tt counts[ilist]} equal to zero, the method returns 1.
Otherwise, the method returns 0.
\par \noindent {\it Error checking:}
If {\tt list} is {\tt NULL},
or if {\tt ilist} is not in the range {\tt [0,nlist)},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Chv * ChvList_getList ( ChvList *list, int ilist ) ;
\end{verbatim}
\index{ChvList_getList@{\tt ChvList\_getList()}}
\par
If list {\tt ilist} is empty, the method returns {\tt NULL}.
Otherwise, if the list needs to be locked, the lock is locked.
The head of the list is saved to a pointer and then the head is set
to {\tt NULL}.
If the list was locked, the number of locks is incremented and the
lock unlocked.
The saved pointer is returned.
\par \noindent {\it Error checking:}
If {\tt list} is {\tt NULL},
or if {\tt ilist} is not in the range {\tt [0,nlist)},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvList_addObjectToList ( ChvList *list, Chv *chv, int ilist ) ;
\end{verbatim}
\index{ChvList_addObjectToList@{\tt ChvList\_addObjectToList()}}
\par
If the list needs to be locked, the lock is locked.
If {\tt chv} is not {\tt NULL}, it is added to the head of the list.
If {\tt counts} is not {\tt NULL}, then {\tt counts[ilist]} is
decremented.
If the lock was locked, the number of locks is incremented
and it is now unlocked.
\par \noindent {\it Error checking:}
If {\tt list} is {\tt NULL},
or if {\tt ilist} is not in the range {\tt [0,nlist)},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:ChvList:proto:IO}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvList_writeForHumanEye ( ChvList *list, FILE *fp ) ;
\end{verbatim}
\index{ChvList_writeForHumanEye@{\tt ChvList\_writeForHumanEye()}}
\par
This method writes the list to a file in user readable form.
\par \noindent {\it Error checking:}
If {\tt list} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
ChvList/doc/makefile 0100644 0002055 0007177 00000000027 06542767330 0015725 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
ChvManager.h 0100644 0002055 0007177 00000000124 06534106411 0014252 0 ustar 00cleve compmath 0000040 0000006 #ifndef _ChvManager_
#define _ChvManager_
#include "ChvManager/ChvManager.h"
#endif
ChvManager/ChvManager.h 0100644 0002055 0007177 00000011263 06536255770 0016312 0 ustar 00cleve compmath 0000040 0000006 /* ChvManager.h */
#include "../Chv.h"
#include "../Lock.h"
/*--------------------------------------------------------------------*/
/*
*/
typedef struct _ChvManager ChvManager ;
struct _ChvManager {
Chv *head ;
Lock *lock ;
int mode ;
int nactive ;
int nbytesactive ;
int nbytesrequested ;
int nbytesalloc ;
int nrequests ;
int nreleases ;
int nlocks ;
int nunlocks ;
} ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
simplest constructor
created -- 98may02, cca
-----------------------
*/
ChvManager *
ChvManager_new (
void
) ;
/*
-----------------------
set the default fields
created -- 98may02, cca
-----------------------
*/
void
ChvManager_setDefaultFields (
ChvManager *manager
) ;
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98may02, cca
--------------------------------------------------
*/
void
ChvManager_clearData (
ChvManager *manager
) ;
/*
------------------------------------------
destructor, free's the object and its data
created -- 98may02, cca
------------------------------------------
*/
void
ChvManager_free (
ChvManager *manager
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------------
simple initializer
lockflag = 0 --> mutex lock is not allocated or initialized
lockflag = 1 --> mutex lock is allocated and it can synchronize
only threads in this process.
lockflag = 2 --> mutex lock is allocated and it can synchronize
only threads in this and other processes.
mode = 0 --> free object and storage on release
mode = 1 --> recycle object and storage on release
created -- 98may02, cca
---------------------------------------------------------------
*/
void
ChvManager_init (
ChvManager *manager,
int lockflag,
int mode
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in util.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------
return a pointer to a Chv object that has
been initialized with the input parameters
created -- 98may02, cca
------------------------------------------
*/
Chv *
ChvManager_newObject (
ChvManager *manager,
int id,
int nD,
int nL,
int nU,
int symflag
) ;
/*
------------------------------------------
return a pointer to a Chv object that has
been initialized with the input parameters
created -- 98may02, cca
------------------------------------------
*/
Chv *
ChvManager_newObjectOfSizeNbytes (
ChvManager *manager,
int nbytesNeeded
) ;
/*
-----------------------
release a Chv instance
created -- 98may02, cca
-----------------------
*/
void
ChvManager_releaseObject (
ChvManager *manager,
Chv *chv
) ;
/*
------------------------------
release a list of Chv objects
created -- 98may02, cca
------------------------------
*/
void
ChvManager_releaseListOfObjects (
ChvManager *manager,
Chv *head
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in IO.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
created -- 98may02, cca
----------------------------------------
*/
void
ChvManager_writeForHumanEye (
ChvManager *manager,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
ChvManager/makefile 0100644 0002055 0007177 00000000141 06636223552 0015611 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd doc ; make clean
ChvManager/src/makefile 0100644 0002055 0007177 00000000677 06636021604 0016410 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = ChvManager
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(init.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
-rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
ChvManager/src/makeGlobalLib 0100644 0002055 0007177 00000000601 06600260757 0017310 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = ChvManager
SRC = basics.o \
init.o \
IO.o \
util.o
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
ChvManager/src/IO.c 0100644 0002055 0007177 00000002524 06536255720 0015363 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../ChvManager.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
created -- 98may02, cca
----------------------------------------
*/
void
ChvManager_writeForHumanEye (
ChvManager *manager,
FILE *fp
) {
Chv *chv ;
/*
---------------
check the input
---------------
*/
if ( manager == NULL || fp == NULL ) {
fprintf(stderr,
"\n fatal error in ChvManager_writeForHumanEye(%p,%p)"
"\n bad input\n", manager, fp) ;
exit(-1) ;
}
fprintf(fp,
"\n\n ChvManager object at address %p"
"\n %d active objects, %d bytes active"
"\n %d total bytes requested, %d total bytes allocated "
"\n %d requests, %d releases, %d locks, %d unlocks",
manager, manager->nactive, manager->nbytesactive,
manager->nbytesrequested, manager->nbytesalloc,
manager->nrequests, manager->nreleases,
manager->nlocks, manager->nunlocks) ;
/*
for ( chv = manager->head ; chv != NULL ; chv = chv->next ) {
fprintf(fp, "\n chv %d, nbytes %d",
chv->id, Chv_nbytesInWorkspace(chv)) ;
}
*/
return ; }
/*--------------------------------------------------------------------*/
orHumanEye (
ChvManager *manager,
FILE *fp
) {
Chv *chv ;
/*
---------------
check the input
---------------
*/
if ( manager == NULL || fp == NULChvManager/src/basics.c 0100644 0002055 0007177 00000005373 06536254742 0016330 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../ChvManager.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------
simplest constructor
created -- 98may02, cca
-----------------------
*/
ChvManager *
ChvManager_new (
void
) {
ChvManager *manager ;
ALLOCATE(manager, struct _ChvManager, 1) ;
ChvManager_setDefaultFields(manager) ;
return(manager) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 98may02, cca
-----------------------
*/
void
ChvManager_setDefaultFields (
ChvManager *manager
) {
if ( manager == NULL ) {
fprintf(stderr, "\n fatal error in ChvManager_setDefaultFields(%p)"
"\n bad input", manager) ;
exit(-1) ;
}
manager->head = NULL ;
manager->lock = NULL ;
manager->mode = 0 ;
manager->nactive = 0 ;
manager->nbytesactive = 0 ;
manager->nbytesrequested = 0 ;
manager->nbytesalloc = 0 ;
manager->nrequests = 0 ;
manager->nreleases = 0 ;
manager->nlocks = 0 ;
manager->nunlocks = 0 ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98may02, cca
--------------------------------------------------
*/
void
ChvManager_clearData (
ChvManager *manager
) {
Chv *chv ;
/*
---------------
check the input
---------------
*/
if ( manager == NULL ) {
fprintf(stderr, "\n fatal error in ChvManager_clearData(%p)"
"\n bad input\n", manager) ;
exit(-1) ;
}
/*
------------------------
free the working storage
------------------------
*/
while ( (chv = manager->head) != NULL ) {
manager->head = chv->next ;
Chv_free(chv) ;
}
if ( manager->lock != NULL ) {
/*
-------------------------
destroy and free the lock
-------------------------
*/
Lock_free(manager->lock) ;
}
/*
----------------------
set the default fields
----------------------
*/
ChvManager_setDefaultFields(manager) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
destructor, free's the object and its data
created -- 98may02, cca
------------------------------------------
*/
void
ChvManager_free (
ChvManager *manager
) {
if ( manager == NULL ) {
fprintf(stderr, "\n fatal error in ChvManager_free(%p)"
"\n bad input\n", manager) ;
exit(-1) ;
}
ChvManager_clearData(manager) ;
FREE(manager) ;
return ; }
/*--------------------------------------------------------------------*/
ChvManager/src/init.c 0100644 0002055 0007177 00000003237 06536255047 0016023 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../ChvManager.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
simple initializer
lockflag = 0 --> mutex lock is not allocated or initialized
lockflag = 1 --> mutex lock is allocated and it can synchronize
omly threads in this process.
lockflag = 2 --> mutex lock is allocated and it can synchronize
omly threads in this and other processes.
mode = 0 --> free object and storage on release
mode = 1 --> recycle object and storage on release
created -- 98may02, cca
---------------------------------------------------------------
*/
void
ChvManager_init (
ChvManager *manager,
int lockflag,
int mode
) {
/*
---------------
check the input
---------------
*/
if ( manager == NULL
|| lockflag < 0 || lockflag > 2
|| mode < 0 || mode > 1 ) {
fprintf(stderr, "\n fatal error in ChvManager_init(%p,%d,%d)"
"\n bad input\n", manager, lockflag, mode) ;
exit(-1) ;
}
/*
--------------------------------------------------
clear any previous data and set the default fields
--------------------------------------------------
*/
ChvManager_clearData(manager) ;
if ( lockflag > 0 ) {
/*
---------------------------
initialize the mutex object
---------------------------
*/
manager->lock = Lock_new() ;
Lock_init(manager->lock, lockflag) ;
}
/*
------------
set the mode
------------
*/
manager->mode = mode ;
return ; }
/*--------------------------------------------------------------------*/
ChvManager/src/util.c 0100644 0002055 0007177 00000021361 06536256047 0016034 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../ChvManager.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
------------------------------------------
return a pointer to a Chv object that has
been initialized with the input parameters
created -- 98may02, cca
------------------------------------------
*/
Chv *
ChvManager_newObjectOfSizeNbytes (
ChvManager *manager,
int nbytesNeeded
) {
Chv *chv, *prev ;
int nbytesAvailable, newinstance ;
/*
---------------
check the input
---------------
*/
if ( manager == NULL || nbytesNeeded <= 0 ) {
fprintf(stderr,
"\n fatal error in ChvMananger_newObjectOfSizeNbytes(%p,%d)"
"\n bad input\n", manager, nbytesNeeded) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n %d bytes needed", nbytesNeeded) ;
fflush(stdout) ;
#endif
if ( manager->lock != NULL ) {
/*
-----------------------------------------------
lock the lock, get exclusive access to the list
-----------------------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n manager: locking") ;
fflush(stdout) ;
#endif
Lock_lock(manager->lock) ;
manager->nlocks++ ;
#if MYDEBUG > 0
fprintf(stdout, ", %d locks so far", manager->nlocks) ;
fflush(stdout) ;
#endif
}
/*
----------------------------------------------------
find a Chv object with the required number of bytes
----------------------------------------------------
*/
for ( chv = manager->head, prev = NULL ;
chv != NULL ;
chv = chv->next ) {
nbytesAvailable = Chv_nbytesInWorkspace(chv) ;
#if MYDEBUG > 0
fprintf(stdout, "\n free chev %p, nbytes = %d",
chv, nbytesAvailable) ;
fflush(stdout) ;
#endif
if ( nbytesNeeded <= nbytesAvailable ) {
break ;
}
prev = chv ;
}
if ( chv != NULL ) {
/*
---------------------------------------
suitable object found, remove from list
---------------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n chv = %p, %d nbytes available",
chv, nbytesAvailable) ;
fflush(stdout) ;
#endif
if ( prev == NULL ) {
manager->head = chv->next ;
} else {
prev->next = chv->next ;
}
newinstance = 0 ;
} else {
/*
------------------------------------------------------------------
no suitable object found, create new instance and allocate storage
------------------------------------------------------------------
*/
chv = Chv_new() ;
#if MYDEBUG > 0
fprintf(stdout, "\n new postponed chv = %p", chv) ;
fflush(stdout) ;
#endif
newinstance = 1 ;
DV_setSize(&chv->wrkDV, nbytesNeeded/sizeof(double)) ;
}
/*
-------------------------------
increment the statistics fields
-------------------------------
*/
if ( newinstance == 1 ) {
manager->nbytesalloc += Chv_nbytesInWorkspace(chv) ;
}
manager->nactive++ ;
manager->nbytesactive += Chv_nbytesInWorkspace(chv) ;
manager->nbytesrequested += nbytesNeeded ;
#if MYDEBUG > 0
fprintf(stdout, "\n %d bytes active, %d bytes requested",
manager->nbytesactive, manager->nbytesrequested) ;
#endif
manager->nrequests++ ;
if ( manager->lock != NULL ) {
/*
-----------------------------------------------------
unlock the lock, release exclusive access to the list
-----------------------------------------------------
*/
manager->nunlocks++ ;
Lock_unlock(manager->lock) ;
#if MYDEBUG > 0
fprintf(stdout, "\n manager: unlocking, %d unlocks so far",
manager->nunlocks) ;
fflush(stdout) ;
#endif
}
return(chv) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
release a Chv instance
created -- 98may02, cca
-----------------------
*/
void
ChvManager_releaseObject (
ChvManager *manager,
Chv *chv1
) {
Chv *chv2, *prev ;
int nbytes1, nbytes2 ;
/*
---------------
check the input
---------------
*/
if ( manager == NULL || chv1 == NULL ) {
fprintf(stderr,
"\n fatal error in ChvMananger_releaseObject(%p,%p)"
"\n bad input\n", manager, chv1) ;
exit(-1) ;
}
if ( manager->lock != NULL ) {
/*
-----------------------------------------------
lock the lock, get exclusive access to the list
-----------------------------------------------
*/
Lock_lock(manager->lock) ;
manager->nlocks++ ;
}
manager->nreleases++ ;
manager->nbytesactive -= Chv_nbytesInWorkspace(chv1) ;
manager->nactive-- ;
if ( manager->mode == 0 ) {
/*
-------------------
release the storage
-------------------
*/
Chv_free(chv1) ;
} else {
/*
--------------------------------------------------------
find a place in the list where the Chv objects are
sorted in ascending order of the size of their workspace
--------------------------------------------------------
*/
nbytes1 = Chv_nbytesInWorkspace(chv1) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n trying to release chevron %p with %d bytes",
chv1, nbytes1) ;
#endif
for ( chv2 = manager->head, prev = NULL ;
chv2 != NULL ;
chv2 = chv2->next ) {
nbytes2 = Chv_nbytesInWorkspace(chv2) ;
#if MYDEBUG > 0
fprintf(stdout, "\n list chv %p with %d bytes", chv2, nbytes2) ;
#endif
if ( nbytes2 > nbytes1 ) {
break ;
}
prev = chv2 ;
}
if ( prev == NULL ) {
manager->head = chv1 ;
#if MYDEBUG > 0
fprintf(stdout, "\n manager->head = %p", chv1) ;
#endif
} else {
prev->next = chv1 ;
#if MYDEBUG > 0
fprintf(stdout, "\n %p->next = %p", prev, chv1) ;
#endif
}
chv1->next = chv2 ;
#if MYDEBUG > 0
fprintf(stdout, "\n %p->next = %p", chv1, chv2) ;
#endif
}
if ( manager->lock != NULL ) {
/*
-----------------------------------------------------
unlock the lock, release exclusive access to the list
-----------------------------------------------------
*/
manager->nunlocks++ ;
Lock_unlock(manager->lock) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------
release a list of Chv objects
created -- 98may02, cca
------------------------------
*/
void
ChvManager_releaseListOfObjects (
ChvManager *manager,
Chv *head
) {
Chv *chv1, *chv2, *prev ;
int nbytes1, nbytes2 ;
/*
---------------
check the input
---------------
*/
if ( manager == NULL || head == NULL ) {
fprintf(stderr,
"\n fatal error in ChvManager_releaseListOfObjects(%p,%p)"
"\n bad input\n", manager, head) ;
exit(-1) ;
}
if ( manager->lock != NULL ) {
/*
-----------------------------------------------
lock the lock, get exclusive access to the list
-----------------------------------------------
*/
Lock_lock(manager->lock) ;
manager->nlocks++ ;
}
if ( manager->mode == 0 ) {
/*
---------------
release storage
---------------
*/
while ( (chv1 = head) != NULL ) {
head = head->next ;
manager->nbytesactive -= Chv_nbytesInWorkspace(chv1) ;
manager->nactive-- ;
manager->nreleases++ ;
Chv_free(chv1) ;
}
} else {
/*
-------------------
recycle the objects
-------------------
*/
while ( head != NULL ) {
chv1 = head ;
head = chv1->next ;
/*
--------------------------------------------------------
find a place in the list where the Chv objects are
sorted in ascending order of the size of their workspace
--------------------------------------------------------
*/
nbytes1 = Chv_nbytesInWorkspace(chv1) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n trying to release chevron %p with %d bytes",
chv1, nbytes1) ;
#endif
for ( chv2 = manager->head, prev = NULL ;
chv2 != NULL ;
chv2 = chv2->next ) {
nbytes2 = Chv_nbytesInWorkspace(chv2) ;
#if MYDEBUG > 0
fprintf(stdout,
"\n list chevron %p with %d bytes", chv2, nbytes2) ;
#endif
if ( nbytes2 > nbytes1 ) {
break ;
}
prev = chv2 ;
}
if ( prev == NULL ) {
manager->head = chv1 ;
#if MYDEBUG > 0
fprintf(stdout, "\n manager->head = %p", chv1) ;
#endif
} else {
prev->next = chv1 ;
#if MYDEBUG > 0
fprintf(stdout, "\n %p->next = %p", prev, chv1) ;
#endif
}
chv1->next = chv2 ;
#if MYDEBUG > 0
fprintf(stdout, "\n %p->next = %p", chv1, chv2) ;
#endif
manager->nbytesactive -= Chv_nbytesInWorkspace(chv1) ;
manager->nactive-- ;
manager->nreleases++ ;
}
}
if ( manager->lock != NULL ) {
/*
-----------------------------------------------------
unlock the lock, release exclusive access to the list
-----------------------------------------------------
*/
manager->nunlocks++ ;
Lock_unlock(manager->lock) ;
}
return ; }
/*--------------------------------------------------------------------*/
ChvManager/doc/ 0042755 0002055 0007177 00000000000 06542767330 0014672 5 ustar 00cleve compmath 0000040 0000006 ChvManager/doc/dataStructure.tex 0100644 0002055 0007177 00000002070 06650202503 0020222 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:ChvManager:dataStructure}
\par
\par
The {\tt ChvList} structure has the following fields.
\begin{itemize}
\item
{\tt Chv *head} :
vector of pointers to the heads of the list of {\tt Chv} objects.
\item
{\tt Lock *lock} : mutual exclusion lock.
\item
{\tt int mode} : behavior mode.
When {\tt mode = 0}, the object calls {\tt SubMtx\_new()}
and {\tt SubMtx\_free()} to create and release objects.
When {\tt mode = 1}, the object recycles the objects.
\item
{\tt int nactive} :
number of active instances.
\item
{\tt int nbytesactive} :
number of bytes that are active.
\item
{\tt int nbytesrequested} :
number of bytes that have been requested.
\item
{\tt int nbytesalloc} :
number of bytes that have been allocated.
\item
{\tt int nrequests} :
number of requests for instances.
\item
{\tt int releases} :
number of instances that have been released.
\item
{\tt int nlocks} :
total number of locks made on the mutual exclusion lock.
{\tt int nunlocks} :
total number of unlocks made on the mutual exclusion lock.
\end{itemize}
ChvManager/doc/intro.tex 0100644 0002055 0007177 00000005654 06536257414 0016554 0 ustar 00cleve compmath 0000040 0000006 \par
\chapter{{\tt ChvManager}: {\tt Chv} manager object }
\par
This object was created to handle
a number of instances of {\tt Chv} objects.
Our codes are heavily dependent on dynamic memory management.
This is partly due to the pivoting capability during the
factorization and partly to the nondeterministic nature of
parallel computation --- we may not know ahead of time just what
data structures will exist during the computations.
\par
We wanted to be able to generate and re-use {\tt Chv} objects,
and we wanted to make the process somewhat transparent to other
sections of the code.
Towards this aim, there are two simple functions.
\begin{itemize}
\item
Ask the manager object for a {\tt Chv} object that has a certain
amount of workspace.
\item
Return to the manager object a {\tt Chv} object or list of objects
that are no longer needed.
\end{itemize}
Where the manager object gets an instance,
or what the manager does with the
instance objects when they are returned to it,
is of no concern to the user of the manager object ---
unless the process takes too much time or storage.
We support two {\it modes} of behavior.
\begin{itemize}
\item {\it catch-and-release}
\par
In this mode the {\tt ChvManager} object is just a front to
{\tt malloc()} and {\tt free()} calls.
The user asks for an object of a certain size, and the manager
creates one using a call to {\tt malloc()}.
When the user returns an object, the manager releases the storage
via a call to {\tt free()}.
\item {\it recycle}
\par
In this mode the {\tt ChvManager} object keeps a free pool of {\tt
Chv} objects. When the user requests a {\tt Chv} object of a
certain size, the manager searches the pool and finds one of that
size or larger, removes the object from the pool,
and returns the object to the user.
(Our implementation finds {\it a} smallest object
of that size or larger.)
If there is no object on the free pool of sufficient size,
one is created and returned.
When the user releases an object to the manager, the object is
placed on the free pool.
\end{itemize}
For the factorization, serial, multithreaded or MPI,
we recommend using the recycling mode.
\par
A multithreaded environment creates some difficulties.
Should there be one manager object per thread, or should all the
threads share one object?
We have chosen the latter course, but this requires that a lock be
present to guard the critical section of code where one searches or
adds an object to the list.
The lock we use is a {\tt Lock} object, and so the {\tt
ChvManager} code is completely independent of the thread package.
Porting to a new system might require some modification to
the {\tt Lock}, but none to the manager object.
\par
Each manager object keeps track of certain statistics,
% e.g., the number of active {\tt Chv} objects, the number of
bytes in their workspaces, the total number of bytes requested,
the number of requests for a {\tt Chv} objects, the number of
releases, and the number of locks and unlocks.
ChvManager/doc/main.tex 0100644 0002055 0007177 00000001140 06650656176 0016334 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\newcommand{\bnd}{{\partial}}
\input psfig
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt DChvList} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt DChvList} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input main.ind
\end{document}
ChvManager/doc/proto.tex 0100644 0002055 0007177 00000014204 06536257220 0016546 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt ChvManager} methods}
\label{section:ChvManager:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt ChvManager} object.
\par
\subsection{Basic methods}
\label{subsection:ChvManager:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ChvManager * ChvManager_new ( void ) ;
\end{verbatim}
\index{ChvManager_new@{\tt ChvManager\_new()}}
This method simply allocates storage
for the {\tt ChvManager} structure
and then sets the default fields by a call to
{\tt ChvManager\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvManager_setDefaultFields ( ChvManager *manager ) ;
\end{verbatim}
\index{ChvManager_setDefaultFields@{\tt ChvManager\_setDefaultFields()}}
The structure's fields are set to default values:
{\tt mode},
{\tt nactive},
{\tt nbytesactive},
{\tt nbytesrequested},
{\tt nbytesalloc},
{\tt nrequests},
{\tt nreleases},
{\tt nlocks} and
{\tt nunlocks}
set to zero,
and {\tt head} and {\tt lock}
are set to {\tt NULL} .
\par \noindent {\it Error checking:}
If {\tt manager} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvManager_clearData ( ChvManager *manager ) ;
\end{verbatim}
\index{ChvManager_clearData@{\tt ChvManager\_clearData()}}
This method clears the object and free's any owned data
by calling {\tt Chv\_free()} for each object on the free
list.
If the lock is not {\tt NULL}, it is destroyed via a call to
{\tt mutex\_destroy()} and then free'd.
There is a concluding call to
{\tt ChvManager\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt manager} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvManager_free ( ChvManager *manager ) ;
\end{verbatim}
\index{ChvManager_free@{\tt ChvManager\_free()}}
This method releases any storage by a call to
{\tt ChvManager\_clearData()}
and then free the space for {\tt manager}.
\par \noindent {\it Error checking:}
If {\tt manager} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initialization methods}
\label{subsection:ChvManager:proto:initial}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvManager_init( ChvManager *manager, int lockflag, int mode ) ;
\end{verbatim}
\index{ChvManager_init@{\tt ChvManager\_init()}}
Any data is cleared via a call to
{\tt ChvManager\_clearData()}.
If {\tt lockflag} is zero, the lock is not initialized.
If {\tt lockflag} is {\tt 1}, the lock is initialized
to be able to synchronize threads with the calling process.
If {\tt lockflag} is {\tt 2}, the lock is initialized
to be able to synchronize threads across processes.
The behavior mode is set to {\tt mode}.
\par \noindent {\it Error checking:}
If {\tt manager} is {\tt NULL},
or if {\tt lockflag} is not in {\tt [0,2]},
or if {\tt mode} is not in {\tt [0,1]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:ChvManager:proto:utility}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Chv * ChvManager_newObjectOfSizeNbytes ( ChvManager *manager,
int nbytesNeeded ) ;
\end{verbatim}
\index{ChvManager_newObjectOfSizeNbytes@{\tt ChvManager\_newObjectOfSizeNbytes()}}
\par
This method returns a {\tt Chv} object whose workspace contains at
least {\tt nbytesNeeded} bytes.
\par \noindent {\it Error checking:}
If {\tt manager} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvManager_releaseObject ( ChvManager *manager, Chv *chv ) ;
\end{verbatim}
\index{ChvManager_releaseObject@{\tt ChvManager\_releaseObject()}}
\par
This method releases the {\tt chv} instance into the free pool of
objects.
\par \noindent {\it Error checking:}
If {\tt manager} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvManager_releaseListOfObjects ( ChvManager *manager, Chv *chv ) ;
\end{verbatim}
\index{ChvManager_releaseListOfObjects@{\tt ChvManager\_releaseListOfObjects()}}
\par
This method releases a list of {\tt Chv} objects into the free pool of
objects.
The head of the list is the {\tt chv} instance.
\par \noindent {\it Error checking:}
If {\tt manager} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:ChvManager:proto:IO}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ChvManager_writeForHumanEye ( ChvManager *manager, FILE *fp ) ;
\end{verbatim}
\index{ChvManager_writeForHumanEye@{\tt ChvManager\_writeForHumanEye()}}
\par
This method writes the statistics to a file in user readable form.
\par \noindent {\it Error checking:}
If {\tt manager} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
rief descriptions including prototypes
of all methods that belong to the {\tt ChvManager} object.
\par
\subsection{Basic methods}
\label{subsection:ChvManager:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%===================================================ChvManager/doc/main.log 0100644 0002055 0007177 00000004716 06536343507 0016323 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 6 JUN 1998 15:48
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
) (/usr/local/lib/texmf/tex/generic/psfig/psfig.tex
\@unused=\write3
\ps@stream=\read1
\p@intvaluex=\dimen100
\p@intvaluey=\dimen101
psfig/tex 1.10-dvips
)
\@indexfile=\write4
Writing index file main.idx
(main.aux) (intro.tex
Chapter 1.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 2.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 2.
[1
]) (dataStructure.tex
Overfull \hbox (8.41794pt too wide) in paragraph at lines 14--19
[] []\elvtt int mode \elvrm : be-hav-ior mode. When \elvtt mode = 0\elvrm , the
ob-ject calls \elvtt SubMtx[]new() \elvrm and \elvtt SubMtx[]free()
\hbox(7.60416+2.12917)x442.37993, glue set - 1.0
.\hbox(0.0+0.0)x0.0
.\glue 0.0
.\hbox(4.86667+0.0)x0.0
..\glue 0.0
..\glue -21.90005
..\glue -5.475
..\hbox(4.86667+0.0)x21.90005, glue set 21.90005fil
...\glue 0.0 plus 1.0fil minus 1.0fil
...\hbox(4.86667+0.0)x0.0, glue set - 5.475fil []
..\glue 5.475
.\penalty 0
.\elvtt i
.etc.
) (proto.tex
Overfull \hbox (14.44592pt too wide) in paragraph at lines 33--46
[]\elvrm The struc-ture's fields are set to de-fault val-ues: \elvtt mode\elvrm
, \elvtt nactive\elvrm , \elvtt nbytesactive\elvrm , \elvtt nbytesrequested\el
vrm ,
\hbox(7.60416+2.43333)x442.37993, glue set - 1.0
.\hbox(0.0+0.0)x0.0
.\elvrm T
.\elvrm h
.\elvrm e
.\glue 3.65 plus 1.825 minus 1.21666
.etc.
[2] [3]) (main.ind [4] [5
]) (main.aux) )
Here is how much of TeX's memory you used:
421 strings out of 11977
4283 string characters out of 87269
38079 words of memory out of 262141
2356 multiletter control sequences out of 9500
19780 words of font info for 75 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
13i,5n,17p,187b,258s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (5 pages, 10720 bytes).
ChvManager/doc/main.idx 0100644 0002055 0007177 00000001215 06536343507 0016315 0 ustar 00cleve compmath 0000040 0000006 \indexentry{ChvManager_new@{\tt ChvManager\_new()}}{2}
\indexentry{ChvManager_setDefaultFields@{\tt ChvManager\_setDefaultFields()}}{3}
\indexentry{ChvManager_clearData@{\tt ChvManager\_clearData()}}{3}
\indexentry{ChvManager_free@{\tt ChvManager\_free()}}{3}
\indexentry{ChvManager_init@{\tt ChvManager\_init()}}{3}
\indexentry{ChvManager_newObjectOfSizeNbytes@{\tt ChvManager\_newObjectOfSizeNbytes()}}{3}
\indexentry{ChvManager_releaseObject@{\tt ChvManager\_releaseObject()}}{3}
\indexentry{ChvManager_releaseListOfObjects@{\tt ChvManager\_releaseListOfObjects()}}{3}
\indexentry{ChvManager_writeForHumanEye@{\tt ChvManager\_writeForHumanEye()}}{4}
ChvManager/doc/main.aux 0100644 0002055 0007177 00000002426 06536343507 0016333 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}{\string\ptt\space ChvManager}: {\string\ptt\space Chv} manager object }{1}}
\@writefile{lof}{\string\addvspace\space {10\p@ }}
\@writefile{lot}{\string\addvspace\space {10\p@ }}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Data Structure}{2}}
\newlabel{section:ChvManager:dataStructure}{{1.1}{2}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Prototypes and descriptions of {\string\ptt\space ChvManager} methods}{2}}
\newlabel{section:ChvManager:proto}{{1.2}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.1}Basic methods}{2}}
\newlabel{subsection:ChvManager:proto:basics}{{1.2.1}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Initialization methods}{3}}
\newlabel{subsection:ChvManager:proto:initial}{{1.2.2}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.3}Utility methods}{3}}
\newlabel{subsection:ChvManager:proto:utility}{{1.2.3}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.4}IO methods}{4}}
\newlabel{subsection:ChvManager:proto:IO}{{1.2.4}{4}}
ChvManager/doc/main.ind 0100644 0002055 0007177 00000000654 06536343504 0016306 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt ChvManager\_clearData()}, 3
\item {\tt ChvManager\_free()}, 3
\item {\tt ChvManager\_init()}, 3
\item {\tt ChvManager\_new()}, 2
\item {\tt ChvManager\_newObjectOfSizeNbytes()}, 3
\item {\tt ChvManager\_releaseListOfObjects()}, 3
\item {\tt ChvManager\_releaseObject()}, 3
\item {\tt ChvManager\_setDefaultFields()}, 3
\item {\tt ChvManager\_writeForHumanEye()}, 4
\end{theindex}
ChvManager/doc/main.ilg 0100644 0002055 0007177 00000000455 06536343504 0016306 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (9 entries accepted, 0 rejected).
Sorting entries....done (26 comparisons).
Generating output file main.ind....done (13 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
ChvManager/doc/makefile 0100644 0002055 0007177 00000000027 06542767330 0016364 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
Coords.h 0100644 0002055 0007177 00000000104 06534106370 0013472 0 ustar 00cleve compmath 0000040 0000006 #ifndef _Coords_
#define _Coords_
#include "Coords/Coords.h"
#endif
Coords/Coords.h 0100644 0002055 0007177 00000020771 06535035655 0014747 0 ustar 00cleve compmath 0000040 0000006 /* Coords.h */
#include "../cfiles.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
object to hold coordinates of a graph
type -- coordinates type
1 -- use tuple, x(icoor, idim) = coors[idim + ndim*icoor]
2 -- use bycoord, x(icoor, idim) = coors[icoor + ncoor*idim]
ndim -- number of dimensions
ncoor -- number of coordinates
coors -- coordinate array
---------------------------------------------------------------
*/
typedef struct _Coords Coords ;
struct _Coords {
int type ;
int ndim ;
int ncoor ;
float *coors ;
} ;
#define COORDS_BY_TUPLE 1
#define COORDS_BY_COORD 2
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
simplest constructor
created -- 95dec17, cca
-----------------------
*/
Coords *
Coords_new (
void
) ;
/*
-----------------------
set the default fields
created -- 95dec17, cca
-----------------------
*/
void
Coords_setDefaultFields (
Coords *coords
) ;
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 95dec17, cca
--------------------------------------------------
*/
void
Coords_clearData (
Coords *coords
) ;
/*
------------------------------------------
destructor, free's the object and its data
created -- 95dec17, cca
------------------------------------------
*/
Coords *
Coords_free (
Coords *coords
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------
initialize the object, storage freed if repeat call
created -- 95dec17, cca
---------------------------------------------------
*/
void
Coords_init (
Coords *coords,
int type,
int ndim,
int ncoor
) ;
/*
----------------------------------------------------------
purpose -- initialize a 9-point operator on a n1 x n2 grid
input --
bbox -- bounding box
bbox[0] -- x southwest
bbox[1] -- y southwest
bbox[2] -- x northeast
bbox[3] -- y northeast
Type -- type of object
n1 -- # of grid points in first direction
n2 -- # of grid points in second direction
ncomp -- # of components per grid point
created -- 95dec17, cca
----------------------------------------------------------
*/
void
Coords_init9P (
Coords *coords,
float bbox[],
int type,
int n1,
int n2,
int ncomp
) ;
/*
----------------------------------------------------------------
purpose -- initialize a 27-point operator on a n1 x n2 x n3 grid
input --
bbox -- bounding box
bbox[0] -- x southwest bottom
bbox[1] -- y southwest bottom
bbox[2] -- z southwest bottom
bbox[3] -- x northeast top
bbox[4] -- y northeast top
bbox[5] -- z northeast top
Type -- type of object
n1 -- # of grid points in first direction
n2 -- # of grid points in second direction
n3 -- # of grid points in third direction
ncomp -- # of components per grid point
created -- 95dec17, cca
----------------------------------------------------------------
*/
void
Coords_init27P (
Coords *coords,
float bbox[],
int Type,
int n1,
int n2,
int n3,
int ncomp
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in util.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 95dec17, cca
----------------------------------------------
*/
int
Coords_sizeOf (
Coords *coords
) ;
/*
--------------------------------------------------
return the minimum coordinate in the dim-direction
created -- 95dec17, cca
--------------------------------------------------
*/
float
Coords_min (
Coords *coords,
int dim
) ;
/*
--------------------------------------------------
return the maximum coordinate in the dim-direction
created -- 95dec17, cca
--------------------------------------------------
*/
float
Coords_max (
Coords *coords,
int dim
) ;
/*
-----------------------
1 <= idim <= ndim
0 <= icoor < ncoor
created -- 95dec17, cca
-----------------------
*/
float
Coords_value (
Coords *coords,
int idim,
int icoor
) ;
/*
-----------------------
1 <= idim <= ndim
0 <= icoor < ncoor
created -- 95dec17, cca
-----------------------
*/
void
Coords_setValue (
Coords *coords,
int idim,
int icoor,
float val
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in IO.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------
purpose -- to read in an Coords object from a file
input --
fn -- filename, must be *.coordsb or *.coordsf
return value -- 1 if success, 0 if failure
created -- 95dec19, cca
---------------------------------------------------
*/
int
Coords_readFromFile (
Coords *coords,
char *fn
) ;
/*
---------------------------------------------------------
purpose -- to read an Coords object from a formatted file
return value -- 1 if success, 0 if failure
created -- 95dec19, cca
---------------------------------------------------------
*/
int
Coords_readFromFormattedFile (
Coords *coords,
FILE *fp
) ;
/*
------------------------------------------------------
purpose -- to read an Coords object from a binary file
return value -- 1 if success, 0 if failure
created -- 95dec19, cca
------------------------------------------------------
*/
int
Coords_readFromBinaryFile (
Coords *coords,
FILE *fp
) ;
/*
----------------------------------------------
purpose -- to write an Coords object to a file
input --
fn -- filename
*.coordsb -- binary
*.coordsf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 95dec19, cca
----------------------------------------------
*/
int
Coords_writeToFile (
Coords *coords,
char *fn
) ;
/*
--------------------------------------------------------
purpose -- to write an Coords object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 95dec19, cca
--------------------------------------------------------
*/
int
Coords_writeToFormattedFile (
Coords *coords,
FILE *fp
) ;
/*
-----------------------------------------------------
purpose -- to write an Coords object to a binary file
return value -- 1 if success, 0 otherwise
created -- 95dec19, cca
-----------------------------------------------------
*/
int
Coords_writeToBinaryFile (
Coords *coords,
FILE *fp
) ;
/*
----------------------------------------------------
purpose -- to write an Coords object for a human eye
return value -- 1 if success, 0 otherwise
created -- 95dec19, cca
----------------------------------------------------
*/
int
Coords_writeForHumanEye (
Coords *coords,
FILE *fp
) ;
/*
------------------------------------------------------------
purpose -- to write out the statistics for the Coords object
return value -- 1 if success, 0 otherwise
created -- 95dec19, cca
------------------------------------------------------------
*/
int
Coords_writeStats (
Coords *coords,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
Coords/makefile 0100644 0002055 0007177 00000000223 06636223553 0015031 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd drivers ; make clean
cd doc ; make clean
Coords/src/makefile 0100644 0002055 0007177 00000000677 06636021661 0015631 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = Coords
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(init.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
Coords/src/makeGlobalLib 0100644 0002055 0007177 00000000574 06600260762 0016533 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = Coords
SRC = basics.c \
init.c \
IO.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
Coords/src/IO.c 0100644 0002055 0007177 00000031003 06535035702 0014566 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../Coords.h"
static const char *suffixb = ".coordsb" ;
static const char *suffixf = ".coordsf" ;
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
purpose -- to read in an Coords object from a file
input --
fn -- filename, must be *.coordsb or *.coordsf
return value -- 1 if success, 0 if failure
created -- 95dec19, cca
---------------------------------------------------
*/
int
Coords_readFromFile (
Coords *coords,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL || fn == NULL ) {
fprintf(stderr,
"\n error in Coords_readFromFile(%p,%s), file %s, line %d"
"\n bad input\n", coords, fn, __FILE__, __LINE__) ;
return(0) ;
}
/*
-------------
read the file
-------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "rb")) == NULL ) {
fprintf(stderr, "\n error in Coords_readFromFile(%p,%s)"
"\n unable to open file %s", coords, fn, fn) ;
rc = 0 ;
} else {
rc = Coords_readFromBinaryFile(coords, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "r")) == NULL ) {
fprintf(stderr, "\n error in Coords_readFromFile(%p,%s)"
"\n unable to open file %s", coords, fn, fn) ;
rc = 0 ;
} else {
rc = Coords_readFromFormattedFile(coords, fp) ;
fclose(fp) ;
}
} else {
fprintf(stderr, "\n error in Coords_readFromFile(%p,%s)"
"\n bad Coords file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
coords, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
} else {
fprintf(stderr, "\n error in Coords_readFromFile(%p,%s)"
"\n bad Coords file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
coords, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
purpose -- to read an Coords object from a formatted file
return value -- 1 if success, 0 if failure
created -- 95dec19, cca
---------------------------------------------------------
*/
int
Coords_readFromFormattedFile (
Coords *coords,
FILE *fp
) {
int rc, size ;
int itemp[3] ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL || fp == NULL ) {
fprintf(stderr, "\n error in Coords_readFromFormattedFile(%p,%p)"
"\n bad input\n", coords, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
Coords_clearData(coords) ;
/*
---------------------------------------
read in the three scalar parameters
type, # of dimensions, # of coordinates
---------------------------------------
*/
if ( (rc = IVfscanf(fp, 3, itemp)) != 3 ) {
fprintf(stderr, "\n error in Coords_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", coords, fp, rc, 3) ;
return(0) ;
}
/*
---------------------
initialize the object
---------------------
*/
Coords_init(coords, itemp[0], itemp[1], itemp[2]) ;
/*
--------------------------
read in the coors[] vector
--------------------------
*/
size = itemp[1]*itemp[2] ;
if ( (rc = FVfscanf(fp, size, coords->coors)) != size ) {
fprintf(stderr, "\n error in Coords_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", coords, fp, rc, size) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- to read an Coords object from a binary file
return value -- 1 if success, 0 if failure
created -- 95dec19, cca
------------------------------------------------------
*/
int
Coords_readFromBinaryFile (
Coords *coords,
FILE *fp
) {
int rc, size ;
int itemp[3] ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in Coords_readFromBinaryFile(%p,%p)"
"\n bad input\n", coords, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
Coords_clearData(coords) ;
/*
---------------------------------------
read in the three scalar parameters
type, # of dimensions, # of coordinates
---------------------------------------
*/
if ( (rc = fread((void *) itemp, sizeof(int), 3, fp)) != 3 ) {
fprintf(stderr, "\n error in Coords_readFromBinaryFile(%p,%p)"
"\n itemp(3) : %d items of %d read\n", coords, fp, rc, 3) ;
return(0) ;
}
/*
---------------------
initialize the object
---------------------
*/
Coords_init(coords, itemp[0], itemp[1], itemp[2]) ;
/*
--------------------------
read in the coors[] vector
--------------------------
*/
size = itemp[1]*itemp[2] ;
if ( (rc = fread((void *) coords->coors, sizeof(float), size, fp))
!= size ) {
fprintf(stderr, "\n error in Coords_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", coords, fp, rc, size) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
purpose -- to write an Coords object to a file
input --
fn -- filename
*.coordsb -- binary
*.coordsf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 95dec19, cca
----------------------------------------------
*/
int
Coords_writeToFile (
Coords *coords,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL || fn == NULL ) {
fprintf(stderr, "\n fatal error in Coords_writeToFile(%p,%s)"
"\n bad input\n", coords, fn) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in Coords_writeToFile(%p,%s)"
"\n unable to open file %s", coords, fn, fn) ;
rc = 0 ;
} else {
rc = Coords_writeToBinaryFile(coords, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "w")) == NULL ) {
fprintf(stderr, "\n error in Coords_writeToFile(%p,%s)"
"\n unable to open file %s", coords, fn, fn) ;
rc = 0 ;
} else {
rc = Coords_writeToFormattedFile(coords, fp) ;
fclose(fp) ;
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in Coords_writeToFile(%p,%s)"
"\n unable to open file %s", coords, fn, fn) ;
rc = 0 ;
} else {
rc = Coords_writeForHumanEye(coords, fp) ;
fclose(fp) ;
}
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in Coords_writeToFile(%p,%s)"
"\n unable to open file %s", coords, fn, fn) ;
rc = 0 ;
} else {
rc = Coords_writeForHumanEye(coords, fp) ;
fclose(fp) ;
}
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- to write an Coords object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 95dec19, cca
--------------------------------------------------------
*/
int
Coords_writeToFormattedFile (
Coords *coords,
FILE *fp
) {
int rc, size ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL || fp == NULL
|| (size = coords->ndim * coords->ncoor) <= 0 ) {
fprintf(stderr, "\n fatal error in Coords_writeToFormattedFile(%p,%p)"
"\n bad input\n", coords, fp) ;
exit(-1) ;
}
/*
-------------------------------------
write out the three scalar parameters
-------------------------------------
*/
rc = fprintf(fp, "\n %d %d %d",
coords->type, coords->ndim, coords->ncoor) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in Coords_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from first fprintf\n", coords, fp, rc) ;
return(0) ;
}
/*
--------------------------------
write out the coordinates vector
--------------------------------
*/
FVfprintf(fp, size, coords->coors) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
purpose -- to write an Coords object to a binary file
return value -- 1 if success, 0 otherwise
created -- 95dec19, cca
-----------------------------------------------------
*/
int
Coords_writeToBinaryFile (
Coords *coords,
FILE *fp
) {
int rc, size ;
int itemp[3] ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL || fp == NULL
|| (size = coords->ndim * coords->ncoor) <= 0 ) {
fprintf(stderr, "\n fatal error in Coords_writeToBinaryFile(%p,%p)"
"\n bad input\n", coords, fp) ;
exit(-1) ;
}
itemp[0] = coords->type ;
itemp[1] = coords->ndim ;
itemp[2] = coords->ncoor ;
rc = fwrite((void *) itemp, sizeof(int), 3, fp) ;
if ( rc != 3 ) {
fprintf(stderr, "\n error in Coords_writeToBinaryFile(%p,%p)"
"\n %d of %d scalar items written\n", coords, fp, rc, 3) ;
return(0) ;
}
rc = fwrite((void *) coords->coors, sizeof(float), size, fp) ;
if ( rc != size ) {
fprintf(stderr, "\n error in Coords_writeToBinaryFile(%p,%p)"
"\n coords->coors, %d of %d items written\n",
coords, fp, rc, size) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
purpose -- to write an Coords object for a human eye
return value -- 1 if success, 0 otherwise
created -- 95dec19, cca
----------------------------------------------------
*/
int
Coords_writeForHumanEye (
Coords *coords,
FILE *fp
) {
int icoor, idim, rc ;
if ( coords == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in Coords_writeForHumanEye(%p,%p)"
"\n bad input\n", coords, fp) ;
exit(-1) ;
}
if ( (rc = Coords_writeStats(coords, fp)) == 0 ) {
fprintf(stderr, "\n fatal error in Coords_writeForHumanEye(%p,%p)"
"\n rc = %d, return from Coords_writeStats(%p,%p)\n",
coords, fp, rc, coords, fp) ;
return(0) ;
}
for ( icoor = 0 ; icoor < coords->ncoor ; icoor++ ) {
fprintf(fp, "\n %6d", icoor) ;
for ( idim = 1 ; idim <= coords->ndim ; idim++ ) {
fprintf(fp, " %12.4g", Coords_value(coords, idim, icoor)) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
purpose -- to write out the statistics for the Coords object
return value -- 1 if success, 0 otherwise
created -- 95dec19, cca
------------------------------------------------------------
*/
int
Coords_writeStats (
Coords *coords,
FILE *fp
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL || fp == NULL ) {
fprintf(stderr, "\n error in Coords_writeStats(%p,%p)"
"\n bad input\n", coords, fp) ;
exit(-1) ;
}
rc = fprintf(fp, "\n Coords : coordinates object :") ;
if ( rc < 0 ) { goto IO_error ; }
rc = fprintf(fp, "\n type %d", coords->type) ;
if ( rc < 0 ) { goto IO_error ; }
switch ( coords->type ) {
case 1 : rc = fprintf(fp, ", storage by tuples") ; break ;
case 2 : rc = fprintf(fp, ", storage by vectors") ; break ;
}
if ( rc < 0 ) { goto IO_error ; }
rc = fprintf(fp,
"\n %d dimensions, %d coordinates, occupies %d bytes",
coords->ndim, coords->ncoor, Coords_sizeOf(coords)) ;
if ( rc < 0 ) { goto IO_error ; }
return(1) ;
IO_error :
fprintf(stderr, "\n fatal error in Coords_writeStats(%p,%p)"
"\n rc = %d, return from fprintf\n", coords, fp, rc) ;
return(0) ;
}
/*--------------------------------------------------------------------*/
NULL || fn == NULL ) {
fprintf(stderr, "\n fatal error in Coords_writeToFile(%p,%s)"
"\n bad input\n", coords, fn) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in Coords_writeToFile(%p,%s)"
"\n unable to open file %s", coords, fn, fCoords/src/basics.c 0100644 0002055 0007177 00000004201 06535036362 0015526 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../Coords.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------
simplest constructor
created -- 95dec17, cca
-----------------------
*/
Coords *
Coords_new (
void
) {
Coords *coords ;
ALLOCATE(coords, struct _Coords, 1) ;
Coords_setDefaultFields(coords) ;
return(coords) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 95dec17, cca
-----------------------
*/
void
Coords_setDefaultFields (
Coords *coords
) {
if ( coords == NULL ) {
fprintf(stderr, "\n fatal error in Coords_setDefaultFields(%p)"
"\n bad input", coords) ;
exit(-1) ;
}
coords->type = COORDS_BY_TUPLE ;
coords->ndim = 0 ;
coords->ncoor = 0 ;
coords->coors = NULL ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 95dec17, cca
--------------------------------------------------
*/
void
Coords_clearData (
Coords *coords
) {
/*
---------------
check the input
---------------
*/
if ( coords == NULL ) {
fprintf(stderr, "\n fatal error in Coords_clearData(%p)"
"\n bad input\n", coords) ;
exit(-1) ;
}
if ( coords->coors != NULL ) {
FVfree(coords->coors) ;
}
/*
----------------------
set the default fields
----------------------
*/
Coords_setDefaultFields(coords) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
destructor, free's the object and its data
created -- 95dec17, cca
------------------------------------------
*/
Coords *
Coords_free (
Coords *coords
) {
if ( coords == NULL ) {
fprintf(stderr, "\n fatal error in Coords_free(%p)"
"\n bad input\n", coords) ;
exit(-1) ;
}
Coords_clearData(coords) ;
FREE(coords) ;
return(NULL) ; }
/*--------------------------------------------------------------------*/
Coords/src/init.c 0100644 0002055 0007177 00000013601 06535036047 0015231 0 ustar 00cleve compmath 0000040 0000006 /* init.C */
#include "../Coords.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
initialize the object, storage freed if repeat call
created -- 95dec17, cca
---------------------------------------------------
*/
void
Coords_init (
Coords *coords,
int type,
int ndim,
int ncoor
) {
/*
---------------
check the input
---------------
*/
if ( coords == NULL
|| !(type == COORDS_BY_TUPLE || type == COORDS_BY_COORD)
|| ndim < 1 || ncoor <= 0 ) {
fprintf(stderr, "\n fatal error in Coords_init(%p,%d,%d,%d)"
"\n bad input\n", coords, type, ndim, ncoor) ;
exit(-1) ;
}
/*
--------------
clear the data
--------------
*/
Coords_clearData(coords) ;
/*
-------------------
set the data fields
-------------------
*/
coords->type = type ;
coords->ndim = ndim ;
coords->ncoor = ncoor ;
coords->coors = FVinit(ndim*ncoor, 0.0) ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------
purpose -- initialize a 9-point operator on a n1 x n2 grid
input --
bbox -- bounding box
bbox[0] -- x southwest
bbox[1] -- y southwest
bbox[2] -- x northeast
bbox[3] -- y northeast
Type -- type of object
n1 -- # of grid points in first direction
n2 -- # of grid points in second direction
ncomp -- # of components per grid point
created -- 95dec17, cca
----------------------------------------------------------
*/
void
Coords_init9P (
Coords *coords,
float bbox[],
int type,
int n1,
int n2,
int ncomp
) {
int i, idof, j, k ;
float deltax, deltay ;
float *x, *y ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL || bbox == NULL
|| !(type == COORDS_BY_TUPLE || type == COORDS_BY_COORD)
|| n1 <= 0 || n2 <= 0 || ncomp <= 0 ) {
fprintf(stderr, "\n fatal error in Coords_init9P(%p,%p,%d,%d,%d,%d)"
"\n bad input\n", coords, bbox, type, n1, n2, ncomp) ;
exit(-1) ;
}
/*
---------------------
initialize the object
---------------------
*/
Coords_init(coords, type, 2, n1*n2) ;
/*
--------------------
fill the coordinates
--------------------
*/
deltax = (bbox[2] - bbox[0]) / (n1-1) ;
deltay = (bbox[3] - bbox[1]) / (n2-1) ;
switch ( type ) {
case COORDS_BY_TUPLE :
x = coords->coors ;
y = coords->coors + 1 ;
for ( j = 0, idof = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
for ( k = 0 ; k < ncomp ; k++, idof += 2 ) {
x[idof] = bbox[0] + deltax*i ;
y[idof] = bbox[1] + deltay*j ;
}
}
}
break ;
case COORDS_BY_COORD :
x = coords->coors ;
y = coords->coors + n1*n2 ;
for ( j = 0, idof = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
for ( k = 0 ; k < ncomp ; k++, idof++ ) {
x[idof] = bbox[0] + deltax*i ;
y[idof] = bbox[1] + deltay*j ;
}
}
}
break ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose -- initialize a 27-point operator on a n1 x n2 x n3 grid
input --
bbox -- bounding box
bbox[0] -- x southwest bottom
bbox[1] -- y southwest bottom
bbox[2] -- z southwest bottom
bbox[3] -- x northeast top
bbox[4] -- y northeast top
bbox[5] -- z northeast top
Type -- type of object
n1 -- # of grid points in first direction
n2 -- # of grid points in second direction
n3 -- # of grid points in third direction
ncomp -- # of components per grid point
created -- 95dec17, cca
----------------------------------------------------------------
*/
void
Coords_init27P (
Coords *coords,
float bbox[],
int type,
int n1,
int n2,
int n3,
int ncomp
) {
int i, idof, j, k, l ;
float deltax, deltay, deltaz ;
float *x, *y, *z ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL || bbox == NULL
|| !(type == COORDS_BY_TUPLE || type == COORDS_BY_COORD)
|| n1 <= 0 || n2 <= 0 || n3 <= 0 || ncomp <= 0 ) {
fprintf(stderr,
"\n fatal error in Coords_init27P(%p,%p,%d,%d,%d,%d,%d)"
"\n bad input\n", coords, bbox, type, n1, n2, n3, ncomp) ;
exit(-1) ;
}
/*
---------------------
initialize the object
---------------------
*/
Coords_init(coords, type, 3, n1*n2*n3) ;
/*
--------------------
fill the coordinates
--------------------
*/
deltax = (bbox[3] - bbox[0]) / (n1-1) ;
deltay = (bbox[4] - bbox[1]) / (n2-1) ;
deltaz = (bbox[5] - bbox[2]) / (n3-1) ;
switch ( type ) {
case COORDS_BY_TUPLE :
x = coords->coors ;
y = coords->coors + 1 ;
z = coords->coors + 2 ;
for ( k = 0, idof = 0 ; k < n3 ; k++ ) {
for ( j = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
for ( l = 0 ; l < ncomp ; l++, idof += 3 ) {
x[idof] = bbox[0] + deltax*i ;
y[idof] = bbox[1] + deltay*j ;
z[idof] = bbox[2] + deltaz*k ;
}
}
}
}
break ;
case COORDS_BY_COORD :
x = coords->coors ;
y = coords->coors + coords->ncoor ;
z = coords->coors + 2*coords->ncoor ;
for ( k = 0, idof = 0 ; k < n3 ; k++ ) {
for ( j = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
for ( l = 0 ; l < ncomp ; l++, idof++ ) {
x[idof] = bbox[0] + deltax*i ;
y[idof] = bbox[1] + deltay*j ;
z[idof] = bbox[2] + deltaz*k ;
}
}
}
}
break ;
}
return ; }
/*--------------------------------------------------------------------*/
Coords/src/util.c 0100644 0002055 0007177 00000015053 06535036400 0015237 0 ustar 00cleve compmath 0000040 0000006 /* basics.C */
#include "../Coords.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 95dec17, cca
----------------------------------------------
*/
int
Coords_sizeOf (
Coords *coords
) {
int nbytes ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL ) {
fprintf(stderr, "\n fatal error in Coords_sizeof(%p)"
"\n bad input\n", coords) ;
exit(-1) ;
}
nbytes = sizeof(struct _Coords) ;
if ( coords->ndim > 0 && coords->ncoor > 0 ) {
nbytes += coords->ndim * coords->ncoor * sizeof(float) ;
}
return(nbytes) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
return the minimum coordinate in the dim-direction
created -- 95dec17, cca
--------------------------------------------------
*/
float
Coords_min (
Coords *coords,
int dim
) {
float minval ;
float *coors ;
int i, j, ncoor, ndim ;
if ( coords == NULL ) {
fprintf(stderr, "\n fatal error in Coords_min(%p,%d)"
"\n bad input \n", coords, dim) ;
exit(-1) ;
} else if ( !(coords->type == COORDS_BY_TUPLE
|| coords->type == COORDS_BY_COORD) ) {
fprintf(stderr, "\n fatal error in Coords_min(%p,%d)"
"\n coords->type = %d",
coords, dim, coords->type) ;
exit(-1) ;
} else if ( (ndim = coords->ndim) < 1 ) {
fprintf(stderr, "\n fatal error in Coords_min(%p,%d)"
"\n coords->ndim = %d",
coords, dim, coords->ndim) ;
exit(-1) ;
} else if ( (ncoor = coords->ncoor) < 1 ) {
fprintf(stderr, "\n fatal error in Coords_min(%p,%d)"
"\n coords->ncoor = %d",
coords, dim, coords->ncoor) ;
exit(-1) ;
} else if ( (coors = coords->coors) == NULL ) {
fprintf(stderr, "\n fatal error in Coords_min(%p,%d)"
"\n coords->coords = %p",
coords, dim, coords->coors) ;
exit(-1) ;
} else if ( dim <= 0 || dim > coords->ndim ) {
fprintf(stderr, "\n fatal error in Coords_min(%p,%d)"
"\n bad input value, dim %d, ndim %d",
coords, dim, dim, ndim) ;
exit(-1) ;
}
switch ( coords->type ) {
case COORDS_BY_TUPLE :
i = dim - 1 ;
minval = coors[i] ;
for ( j = 1, i += ndim ; j < ncoor ; j++, i += ndim ) {
if ( coors[i] < minval ) {
minval = coors[i] ;
}
}
break ;
case COORDS_BY_COORD :
i = (dim - 1)*ncoor ;
minval = coors[i] ;
for ( i++ ; i < ncoor ; i++ ) {
if ( coors[i] < minval ) {
minval = coors[i] ;
}
}
break ;
}
return(minval) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
return the maximum coordinate in the dim-direction
created -- 95dec17, cca
--------------------------------------------------
*/
float
Coords_max (
Coords *coords,
int dim
) {
float maxval ;
float *coors ;
int i, j, ncoor, ndim ;
if ( coords == NULL ) {
fprintf(stderr, "\n fatal error in Coords_max(%p,%d)"
"\n bad input \n", coords, dim) ;
exit(-1) ;
} else if ( !(coords->type == COORDS_BY_TUPLE
|| coords->type == COORDS_BY_COORD) ) {
fprintf(stderr, "\n fatal error in Coords_max(%p,%d)"
"\n coords->type = %d",
coords, dim, coords->type) ;
exit(-1) ;
} else if ( (ndim = coords->ndim) < 1 ) {
fprintf(stderr, "\n fatal error in Coords_max(%p,%d)"
"\n coords->ndim = %d",
coords, dim, coords->ndim) ;
exit(-1) ;
} else if ( (ncoor = coords->ncoor) < 1 ) {
fprintf(stderr, "\n fatal error in Coords_max(%p,%d)"
"\n coords->ncoor = %d",
coords, dim, coords->ncoor) ;
exit(-1) ;
} else if ( (coors = coords->coors) == NULL ) {
fprintf(stderr, "\n fatal error in Coords_max(%p,%d)"
"\n coords->coords = %p",
coords, dim, coords->coors) ;
exit(-1) ;
} else if ( dim <= 0 || dim > coords->ndim ) {
fprintf(stderr, "\n fatal error in Coords_max(%p,%d)"
"\n bad input value, dim %d, ndim %d",
coords, dim, dim, ndim) ;
exit(-1) ;
}
switch ( coords->type ) {
case COORDS_BY_TUPLE :
i = dim - 1 ;
maxval = coors[i] ;
for ( j = 1, i += ndim ; j < ncoor ; j++, i += ndim ) {
if ( coors[i] > maxval ) {
maxval = coors[i] ;
}
}
break ;
case COORDS_BY_COORD :
i = (dim - 1)*ncoor ;
maxval = coors[i] ;
for ( i++ ; i < ncoor ; i++ ) {
if ( coors[i] > maxval ) {
maxval = coors[i] ;
}
}
break ;
}
return(maxval) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
1 <= idim <= ndim
0 <= icoor < ncoor
created -- 95dec17, cca
-----------------------
*/
float
Coords_value (
Coords *coords,
int idim,
int icoor
) {
float val ;
/*
---------------
check the input
---------------
*/
if ( coords == NULL || idim <= 0
|| !(coords->type == COORDS_BY_TUPLE
|| coords->type == COORDS_BY_COORD)
|| icoor < 0 || coords->ncoor <= icoor || coords->coors == NULL ) {
fprintf(stderr, "\n fatal error in Coords_value(%p,%d,%d)"
"\n bad input or object\n", coords, idim, icoor) ;
exit(-1) ;
}
switch ( coords->type ) {
case COORDS_BY_TUPLE :
val = coords->coors[idim - 1 + coords->ndim*icoor] ;
break ;
case COORDS_BY_COORD :
val = coords->coors[icoor + coords->ncoor*(idim - 1)] ;
break ;
}
return(val) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
1 <= idim <= ndim
0 <= icoor < ncoor
created -- 95dec17, cca
-----------------------
*/
void
Coords_setValue (
Coords *coords,
int idim,
int icoor,
float val
) {
/*
---------------
check the input
---------------
*/
if ( coords == NULL || idim <= 0
|| !(coords->type == COORDS_BY_TUPLE
|| coords->type == COORDS_BY_COORD)
|| icoor < 0 || coords->ncoor <= icoor || coords->coors == NULL ) {
fprintf(stderr, "\n fatal error in Coords_setValue(%p,%d,%d,%f)"
"\n bad input or object\n", coords, idim, icoor, val) ;
exit(-1) ;
}
switch ( coords->type ) {
case COORDS_BY_TUPLE :
coords->coors[idim - 1 + coords->ndim*icoor] = val ;
break ;
case COORDS_BY_COORD :
coords->coors[icoor + coords->ncoor*(idim - 1)] = val ;
break ;
}
return ; }
/*--------------------------------------------------------------------*/
i, j, ncoor, ndim ;
if ( coords == NULL ) {
fprintf(stderr, "\n fatal error in Coords_max(%p,%d)"
"\n bad input \n", coords, dim) ;
exit(-1) ;
} else if ( !(coords->type == COORDS_BY_TUPLE
|| coords->type == COORDS_BY_COORD) ) {
fprintf(stderr, "\n fatal error in Coords_max(%p,%d)"
"\n coords->type = %d",
coords, dim, coords->type) ;
exit(-1) ;
} else if ( (ndim = coords->ndim) < 1 ) {
fprintf(stderr, "\n Coords/drivers/do_mk9PCoords 0100755 0002055 0007177 00000000466 06535037222 0017414 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set msglvl = 3
set msgFile = stdout
set n1 = 7
set n2 = 7
set matrices = ../../Matrices
set matrix = GRD7x7
set outCoordsFile = $matrices/$matrix/$matrix.coordsf
set outCoordsFile = temp.coordsf
mk9PCoords $msglvl $msgFile $n1 $n2 $outCoordsFile
Coords/drivers/do_testIO 0100755 0002055 0007177 00000000754 06534105774 0016640 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set msglvl = 2
set msgFile = stdout
set n1 = 7
set n2 = 7
set matrices = ../../Matrices
set matrix = GRD7x7
set inCoordsFile = none
set inCoordsFile = $matrices/$matrix/$matrix.coordsb
set inCoordsFile = $matrices/$matrix/$matrix.coordsf
set outCoordsFile = $matrices/$matrix/$matrix.coordsf
set outCoordsFile = $matrices/$matrix/$matrix.coordsb
set outCoordsFile = none
testIO $msglvl $msgFile $inCoordsFile $outCoordsFile
Coords/drivers/makefile 0100644 0002055 0007177 00000000637 06653142406 0016514 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = testIO mk9PCoords
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
mk9PCoords : mk9PCoords.o ../../spooles.a
${PURIFY} $(CC) $@.o -o $@ $(PURIFY_GCC_VERSION) $(LIBS)
testIO : testIO.o ../../spooles.a
${PURIFY} $(CC) $@.o -o $@ $(PURIFY_GCC_VERSION) $(LIBS)
Coords/drivers/mk9PCoords.c 0100644 0002055 0007177 00000004130 06535037045 0017143 0 ustar 00cleve compmath 0000040 0000006 /* mk9PCoords.c */
#include "../Coords.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
------------------------------------
create a Coords object for a 9P grid
created -- 96feb02, cca
------------------------------------
*/
{
Coords *coords ;
double t1, t2 ;
FILE *msgFile ;
float bbox[4] = { 0.0, 0.0, 1.0, 1.0 } ;
int msglvl, n1, n2 ;
if ( argc != 6 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile n1 n2 outCoordsFile \n"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n n1 -- # of grid points in first direction"
"\n n2 -- # of grid points in second direction"
"\n outCoordsFile -- file to write out Coords object"
"\n", argv[0]) ;
return(1) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s", argv[0], argv[2]) ;
exit(-1) ;
}
n1 = atoi(argv[3]) ;
n2 = atoi(argv[4]) ;
fprintf(msgFile, "\n\n %s %d %s %d %d %s",
argv[0], msglvl, argv[2], n1, n2, argv[5]) ;
fflush(msgFile) ;
/*
------------------------
create the Coords object
------------------------
*/
MARKTIME(t1) ;
coords = Coords_new() ;
Coords_init9P(coords, bbox, COORDS_BY_TUPLE, n1, n2, 1) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %.3f : create Coords object", (t2 - t1)) ;
if ( msglvl <= 2 ) {
Coords_writeStats(coords, msgFile) ;
fflush(msgFile) ;
} else {
Coords_writeForHumanEye(coords, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
write out the Coords object
---------------------------
*/
if ( strcmp("none", argv[5]) != 0 ) {
MARKTIME(t1) ;
Coords_writeToFile(coords, argv[5]) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %.3f : write out Coords to file %s",
(t2 - t1), argv[5]) ;
}
fprintf(msgFile, "\n") ;
fflush(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
Coords/drivers/testIO.c 0100644 0002055 0007177 00000005104 06535050577 0016367 0 ustar 00cleve compmath 0000040 0000006 /* testIO.c */
#include "../Coords.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
--------------------------------------------------
test Coords_readFromFile and Coords_writeToFile,
useful for translating between formatted *.coordsf
and binary *.coordsb files.
created -- 95dec17, cca
--------------------------------------------------
*/
{
int msglvl, rc ;
Coords coords ;
FILE *msgFile ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : testIO msglvl msgFile inFile outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.coordsf or *.coordsb"
"\n outFile -- output file, must be *.coordsf or *.coordsb"
"\n") ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
fprintf(msgFile,
"\n testIO "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
msglvl, argv[2], argv[3], argv[4]) ;
fflush(msgFile) ;
/*
----------------------
set the default fields
----------------------
*/
Coords_setDefaultFields(&coords) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n after setting default fields") ;
Coords_writeForHumanEye(&coords, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------
read in the Coords object
-------------------------
*/
if ( strcmp(argv[3], "none") == 0 ) {
fprintf(msgFile, "\n no file to read from\n") ;
exit(0) ;
}
rc = Coords_readFromFile(&coords, argv[3]) ;
fprintf(msgFile, "\n return value %d from Coords_readFromFile(%p,%s)",
rc, &coords, argv[3]) ;
if ( rc != 1 ) {
exit(-1) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n after reading Coords object from file %s",
argv[3]) ;
Coords_writeForHumanEye(&coords, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
write out the Coords object
---------------------------
*/
if ( strcmp(argv[4], "none") != 0 ) {
rc = Coords_writeToFile(&coords, argv[4]) ;
fprintf(msgFile, "\n return value %d from Coords_writeToFile(%p,%s)",
rc, &coords, argv[4]) ;
}
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
Coords/doc/ 0042755 0002055 0007177 00000000000 06542767330 0014110 5 ustar 00cleve compmath 0000040 0000006 Coords/doc/drivers.tex 0100644 0002055 0007177 00000005556 06534105775 0016316 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt Coords} object}
\label{section:Coords:drivers}
\par
This section contains brief descriptions of the driver programs.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testIO msglvl msgFile inFile outFile
\end{verbatim}
This driver program reads and write {\tt Coords} files, useful for
converting formatted files to binary files and vice versa.
One can also read in a {\tt Coords} file and print out just the
header information (see the {\tt Coords\_writeStats()} method).
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt Coords} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inFile} parameter is the input file for the {\tt Coords}
object. It must be of the form {\tt *.coordsf} or {\tt *.coordsb}.
The {\tt Coords} object is read from the file via the
{\tt Coords\_readFromFile()} method.
\item
The {\tt outFile} parameter is the output file for the {\tt Coords}
object.
If {\tt outFile} is {\tt none} then the {\tt Coords} object is not
written to a file.
Otherwise, the {\tt Coords\_writeToFile()} method is called to write
the object to
a formatted file (if {\tt outFile} is of the form {\tt *.coordsf}),
or
a binary file (if {\tt outFile} is of the form {\tt *.coordsb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
mk9PCoords msglvl msgFile n1 n2 outCoordsFile
\end{verbatim}
This driver program creates a {\tt Coords} object
for 9-point finite difference operator on
a $\mbox{\tt n1} \times \mbox{\tt n2}$ grid
and optionally writes it to a file.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means that all objects are written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
message data.
\item
The {\tt outCoordsFile} parameter is the output file for the
{\tt Coords} object.
If {\tt outCoordsFile} is {\tt none} then the {\tt Coords} object
is not written to a file.
Otherwise, the {\tt Coords\_writeToFile()} method is called to write
the object to
a formatted file (if {\tt outCoordsFile}
is of the form {\tt *.coordsf}), or
a binary file (if {\tt outCoordsFile} is of the form {\tt *.coordsb}).
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
Coords/doc/dataStructure.tex 0100640 0002055 0007177 00000001777 06534105775 0017467 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\par
The {\tt Coords} object has four fields.
\begin{itemize}
\item {\tt int type} : coordinate type.
When {\tt type = 1}, coordinates are stored by tuples,
$(x_0,y_0,\ldots)$ first,
$(x_1,y_1,\ldots)$ next, etc.
% \begin{verbatim}
% x(icoor, idim) = coors[idim + icoor*ndim]
% \end{verbatim}
When {\tt type = 2}, coordinates are stored by $x$-coordinates
first, $y$-coordinates next, etc.
% \begin{verbatim}
% x(icoor, idim) = coors[icoor + idim*ncoor]
% \end{verbatim}
\item {\tt int ndim} :
number of dimensions for the coordinates,
e.g., for $(x,y)$ coordinates {\tt ndim = 2},
for $(x,y,z)$ coordinates {\tt ndim = 3}.
\item {\tt int ncoor} :
number of coordinates (i.e., number of grid points).
\item {\tt float *coors} :
pointer to a {\tt float} vector that holds the coordinates
\end{itemize}
A correctly initialized and nontrivial {\tt Coords} object
will have {\tt type} be {\tt 1} or {\tt 2},
positive {\tt ndim} and {\tt ncoor} values,
and a non-{\tt NULL} {\tt coors} field.
Coords/doc/intro.tex 0100640 0002055 0007177 00000000310 06534105775 0015746 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt Coords}: Coordinates Object}
\par
The {\tt Coords} object is used to hold $(x,y)$, $(x,y,z)$ or
larger dimensional coordinates.
We use it to visualize two- and three-dimensional graphs.
Coords/doc/main.tex 0100644 0002055 0007177 00000001102 06650656200 0015534 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt Coords} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt Coords} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
Coords/doc/proto.tex 0100644 0002055 0007177 00000034013 06535037421 0015762 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt Coords} methods}
\label{section:Coords:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt Coords} object.
\par
\subsection{Basic methods}
\label{subsection:Coords:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Coords * Coords_new ( void ) ;
\end{verbatim}
\index{Coords_new@{\tt Coords\_new()}}
This method simply allocates storage for the {\tt Coords} structure
and then sets the default fields by a call to
{\tt Coords\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Coords_setDefaultFields ( Coords *coords ) ;
\end{verbatim}
\index{Coords_setDefaultFields@{\tt Coords\_setDefaultFields()}}
This method sets the structure's fields are set to default values:
{\tt type = COORDS\_BY\_TUPLE},
{\tt ndim = ncoor = 0} and {\tt coors = NULL}.
\par \noindent {\it Error checking:}
If {\tt coords} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Coords_clearData ( Coords *coords ) ;
\end{verbatim}
\index{Coords_clearData@{\tt Coords\_clearData()}}
This method clears data and releases any storage allocated by the
object.
If {\tt coords->coors} is not {\tt NULL},
then {\tt FVfree(coords->coors)} is called to free the {\tt float}
vector.
It then sets the structure's default fields
with a call to {\tt Coords\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt coords} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Coords_free ( Coords *coords ) ;
\end{verbatim}
\index{Coords_free@{\tt Coords\_free()}}
This method releases any storage by a call to
{\tt Coords\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt coords} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initializer methods}
\label{subsection:Coords:proto:initializers}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Coords_init ( Coords *coords, int type, int ndim, int ncoor ) ;
\end{verbatim}
\index{Coords_init@{\tt Coords\_init()}}
This method initializes a {\tt Coords} object given
the type, number of dimensions and number of grid points.
It clears any previous data with a call to
{\tt Coords\_clearData()}.
The {\tt float} vector is initialized by a call to {\tt FVinit()}.
\par \noindent {\it Error checking:}
If {\tt coords} is {\tt NULL} or {\tt type} is not
{\tt COORDS\_BY\_TUPLE} or {\tt COORDS\_BY\_COORD},
or if either {\tt ndim} or {\tt ncoor} are nonpositive,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Coords_init9P ( Coords *coords, float bbox[], int type,
int n1, int n2, int ncomp ) ;
\end{verbatim}
\index{Coords_init9P@{\tt Coords\_init9P()}}
This method initializes a {\tt Coords} object for a 9-point
operator on a $\mbox{\tt n1} \times \mbox{\tt n2}$ grid with
{\tt ncomp} degrees of freedom at a grid point.
The grid's location is given by the bounding box vector,
{\tt bbox[0]} = $x$-coordinate of the southwest point,
{\tt bbox[1]} = $y$-coordinate of the southwest point,
{\tt bbox[2]} = $x$-coordinate of the northeast point, and
{\tt bbox[3]} = $y$-coordinate of the northeast point.
\par \noindent {\it Error checking:}
If {\tt coords} {\tt bbox} is {\tt NULL},
or if {\tt type} is not
{\tt COORDS\_BY\_TUPLE} or {\tt COORDS\_BY\_COORD},
or if any of {\tt n1}, {\tt n2} or {\tt ncomp} are nonpositive,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Coords_init27P ( Coords *coords, float bbox[], int type,
int n1, int n2, int n3, int ncomp ) ;
\end{verbatim}
\index{Coords_init27P@{\tt Coords\_init27P()}}
This method initializes a {\tt Coords} object for a 27-point
operator on a $\mbox{\tt n1} \times \mbox{\tt n2} \times {\tt n3}$
grid with {\tt ncomp} degrees of freedom at a grid point.
The grid's location is given by the bounding box vector,
{\tt bbox[0]} = $x$-coordinate of the southwest point,
{\tt bbox[1]} = $y$-coordinate of the southwest point,
{\tt bbox[2]} = $z$-coordinate of the southwest point,
{\tt bbox[3]} = $x$-coordinate of the northeast point,
{\tt bbox[4]} = $y$-coordinate of the northeast point, and
{\tt bbox[5]} = $z$-coordinate of the northeast point.
\par \noindent {\it Error checking:}
If {\tt coords} {\tt bbox} is {\tt NULL},
or if {\tt type} is not
{\tt COORDS\_BY\_TUPLE} or {\tt COORDS\_BY\_COORD},
or if any of {\tt n1}, {\tt n2}, {\tt n3}
or {\tt ncomp} are nonpositive,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:Coords:proto:utilities}
\par
There are three utility methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Coords_sizeOf ( Coords *coords ) ;
\end{verbatim}
\index{Coords_sizeOf@{\tt Coords\_sizeOf()}}
This method returns the number of bytes that the object occupies.
\par \noindent {\it Error checking:}
If {\tt coords} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
float Coords_min ( Coords *coords, int dim )
\end{verbatim}
\index{Coords_min@{\tt Coords\_min()}}
This method returns the minimum coordinate value for the {\tt
dim}'th entry in the coordinates.
For example, {\tt Coords\_min(coords, 1)} is the minimum $x$-value
and {\tt Coords\_min(coords, 2)} is the minimum $y$-value.
\par \noindent {\it Error checking:}
If {\tt coords} is {\tt NULL},
or if {\tt idim} does not lie in the range {\tt [1,ndim]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
float Coords_max ( Coords *coords, int dim )
\end{verbatim}
\index{Coords_max@{\tt Coords\_max()}}
This method returns the maximum coordinate value for the {\tt
dim}'th entry in the coordinates.
For example, {\tt Coords\_max(coords, 1)} is the maximum $x$-value
and {\tt Coords\_max(coords, 2)} is the maximum $y$-value.
\par \noindent {\it Error checking:}
If {\tt coords} is {\tt NULL},
or if {\tt idim} does not lie in the range {\tt [1,ndim]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
float Coords_value ( Coords *coords, int idim, int icoor ) ;
\end{verbatim}
\index{Coords_value@{\tt Coords\_value()}}
This method returns the {\tt float} value of the {\tt idim}-th
coordinate of the {\tt icoor}-th grid point.
For example, {\tt Coords\_value(coords, 1, 27)} returns $x_{27}$,
{\tt Coords\_value(coords, 2, 16)} returns $y_{16}$,
and {\tt Coords\_value(coords, 3, 118)} returns $z_{118}$.
\par \noindent {\it Error checking:}
If {\tt coords} is {\tt NULL},
or if {\tt idim} does not lie in the range {\tt [1,ndim]},
or if {\tt icoor} does not lie in the range {\tt [0,ncoor)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Coords_setValue ( Coords *coords, int idim, int icoor, float val ) ;
\end{verbatim}
\index{Coords_setValue@{\tt Coords\_setValue()}}
This method sets the {\tt float} value of the {\tt idim}-th
coordinate of the {\tt icoor}-th grid point.
For example,
{\tt Coords\_setValue(coords, 1, 27, 1.2)} sets $x_{27} = 1.2$,
{\tt Coords\_setValue(coords, 2, 16, 3.3)} sets $y_{16} = 3.3$,
and {\tt Coords\_setValue(coords, 3, 118, 0)} sets $z_{118} = 0$.
\par \noindent {\it Error checking:}
If {\tt coords} is {\tt NULL},
or if {\tt idim} does not lie in the range {\tt [1,ndim]},
or if {\tt icoor} does not lie in the range {\tt [0,ncoor)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:Coords:proto:IO}
\par
There are the usual eight IO routines.
The file structure of a {\tt Coords} object is simple:
{\tt type}, {\tt ndim}, {\tt ncoor}
followed by the {\tt coors[]} vector.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Coords_readFromFile ( Coords *coords, char *filename ) ;
\end{verbatim}
\index{Coords_readFromFile@{\tt Coords\_readFromFile()}}
\par
This method read a {\tt Coords} object from a file.
It tries to open the file and if it is successful,
it then calls {\tt Coords\_readFromFormattedFile()} or
{\tt Coords\_readFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt coords} or {\tt filename} is {\tt NULL},
or if {\tt filename} is not of the form
{\tt *.coordsf} (for a formatted file)
or {\tt *.coordsb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Coords_readFromFormattedFile ( Coords *coords, FILE *fp ) ;
\end{verbatim}
\index{Coords_readFromFormattedFile@{\tt Coords\_readFromFormattedFile()}}
\par
This method reads in a {\tt Coords} object from a formatted file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fscanf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt coords} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Coords_readFromBinaryFile ( Coords *coords, FILE *fp ) ;
\end{verbatim}
\index{Coords_readFromBinaryFile@{\tt Coords\_readFromBinaryFile()}}
\par
This method reads in a {\tt Coords} object from a binary file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fread}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt coords} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Coords_writeToFile ( Coords *coords, char *fn ) ;
\end{verbatim}
\index{Coords_writeToFile@{\tt Coords\_writeToFile()}}
\par
This method write a {\tt Coords} object to a file.
The method tries to open the file and if it is successful,
it then calls {\tt Coords\_writeFromFormattedFile()} or
{\tt Coords\_writeFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt coords} or {\tt fn} is {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.coordsf} (for a formatted file)
or {\tt *.coordsb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Coords_writeToFormattedFile ( Coords *coords, FILE *fp ) ;
\end{verbatim}
\index{Coords_writeToFormattedFile@{\tt Coords\_writeToFormattedFile()}}
\par
This method writes a {\tt Coords} object to a formatted file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fprintf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt coords} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Coords_writeToBinaryFile ( Coords *coords, FILE *fp ) ;
\end{verbatim}
\index{Coords_writeToBinaryFile@{\tt Coords\_writeToBinaryFile()}}
\par
This method writes a {\tt Coords} object to a binary file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fwrite}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt coords} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Coords_writeForHumanEye ( Coords *coords, FILE *fp ) ;
\end{verbatim}
\index{Coords_writeForHumanEye@{\tt Coords\_writeForHumanEye()}}
\par
This method write the {\tt Coords} object to a file in an easy to
read fashion.
The method {\tt Coords\_writeStats()} is called to write out the
header and statistics.
The {\tt coors[]} vector is then printed out.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt coords} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Coords_writeStats ( Coords *coords, FILE *fp ) ;
\end{verbatim}
\index{Coords_writeStats@{\tt Coords\_writeStats()}}
\par
The header and statistics are written.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt coords} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
on{Utility methods}
\label{subsection:Coords:proto:utilities}
\par
There are three utility methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Coords_sizeOf ( Coords *coords ) ;
\end{verbatim}
\index{Coords_sizeOf@{\tt Coords\_sizeOf()}}
This method returns the number of bytes that the object occupies.
\par \noindent {\it Error checking:}
If {\ttCoords/doc/main.log 0100644 0002055 0007177 00000007051 06535037440 0015527 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 2 JUN 1998 11:06
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
)
\@indexfile=\write3
Writing index file main.idx
(main.aux) (intro.tex
Chapter 1.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 1.
) (dataStructure.tex) (proto.tex [1
]
Overfull \hbox (2.62105pt too wide) in paragraph at lines 105--113
\elvit Error check-ing: \elvrm If \elvtt coords bbox \elvrm is \elvtt NULL\elvr
m , or if \elvtt type \elvrm is not \elvtt COORDS[]BY[]TUPLE \elvrm or \elvtt C
OORDS[]BY[]COORD\elvrm ,
\hbox(7.60416+2.43333)x442.37993, glue set - 1.0
.\elvit E
.\elvit r
.\elvit r
.\kern-0.55968
.\elvit o
.etc.
[2]
Overfull \hbox (2.62105pt too wide) in paragraph at lines 128--136
\elvit Error check-ing: \elvrm If \elvtt coords bbox \elvrm is \elvtt NULL\elvr
m , or if \elvtt type \elvrm is not \elvtt COORDS[]BY[]TUPLE \elvrm or \elvtt C
OORDS[]BY[]COORD\elvrm ,
\hbox(7.60416+2.43333)x442.37993, glue set - 1.0
.\elvit E
.\elvit r
.\elvit r
.\kern-0.55968
.\elvit o
.etc.
[3]
Overfull \hbox (4.44226pt too wide) in paragraph at lines 283--289
\elvrm cess-ful, it then calls \elvtt Coords[]writeFromFormattedFile() \elvrm o
r \elvtt Coords[]writeFromBinaryFile()\elvrm ,
\hbox(7.60416+2.43333)x442.37993, glue set - 1.0
.\elvrm c
.\elvrm e
.\elvrm s
.\elvrm s
.\discretionary
..\elvrm -
.etc.
[4]) (drivers.tex
Overfull \hbox (42.63402pt too wide) in paragraph at lines 30--35
\elvtt *.coordsf \elvrm or \elvtt *.coordsb\elvrm . The \elvtt Coords \elvrm ob
-ject is read from the file via the \elvtt Coords[]readFromFile()
\hbox(7.60416+2.12917)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt c
.\elvtt o
.\elvtt o
.etc.
Overfull \hbox (1.44826pt too wide) in paragraph at lines 65--74
[] []\elvrm The \elvtt outCoordsFile \elvrm pa-ram-e-ter is the out-put file fo
r the \elvtt Coords \elvrm ob-ject. If \elvtt outCoordsFile
\hbox(7.60416+2.12917)x418.2899, glue set - 1.0
.\hbox(0.0+0.0)x0.0
.\glue 0.0
.\hbox(4.86667+0.0)x0.0
..\glue 0.0
..\glue -18.61502
..\glue -5.475
..\hbox(4.86667+0.0)x18.61502, glue set 18.61502fil
...\glue 0.0 plus 1.0fil minus 1.0fil
...\hbox(4.86667+0.0)x0.0, glue set - 5.475fil []
..\glue 5.475
.\penalty 0
.\elvrm T
.etc.
Overfull \hbox (18.78839pt too wide) in paragraph at lines 65--74
\elvrm is \elvtt none \elvrm then the \elvtt Coords \elvrm ob-ject is not writ-
ten to a file. Oth-er-wise, the \elvtt Coords[]writeToFile()
\hbox(7.60416+2.12917)x418.2899, glue set - 1.0
.\elvrm i
.\elvrm s
.\glue 3.65 plus 1.825 minus 1.21666
.\elvtt n
.\elvtt o
.etc.
[5]) (main.ind [6] [7
]) (main.aux) )
Here is how much of TeX's memory you used:
207 strings out of 11977
2133 string characters out of 87269
33641 words of memory out of 262141
2141 multiletter control sequences out of 9500
19780 words of font info for 75 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
14i,4n,17p,183b,226s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (7 pages, 18624 bytes).
1) (format=lplain 94.11.14) 2 JUN 1998 11:06
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/Coords/doc/main.aux 0100644 0002055 0007177 00000002562 06535037440 0015545 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}{\string\ptt\space Coords}: Coordinates Object}{1}}
\@writefile{lof}{\string\addvspace\space {10\p@ }}
\@writefile{lot}{\string\addvspace\space {10\p@ }}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Data Structure}{1}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Prototypes and descriptions of {\string\ptt\space Coords} methods}{1}}
\newlabel{section:Coords:proto}{{1.2}{1}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.1}Basic methods}{1}}
\newlabel{subsection:Coords:proto:basics}{{1.2.1}{1}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Initializer methods}{2}}
\newlabel{subsection:Coords:proto:initializers}{{1.2.2}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.3}Utility methods}{3}}
\newlabel{subsection:Coords:proto:utilities}{{1.2.3}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.4}IO methods}{4}}
\newlabel{subsection:Coords:proto:IO}{{1.2.4}{4}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}Driver programs for the {\string\ptt\space Coords} object}{5}}
\newlabel{section:Coords:drivers}{{1.3}{5}}
Coords/doc/main.idx 0100644 0002055 0007177 00000002302 06535037440 0015524 0 ustar 00cleve compmath 0000040 0000006 \indexentry{Coords_new@{\tt Coords\_new()}}{2}
\indexentry{Coords_setDefaultFields@{\tt Coords\_setDefaultFields()}}{2}
\indexentry{Coords_clearData@{\tt Coords\_clearData()}}{2}
\indexentry{Coords_free@{\tt Coords\_free()}}{2}
\indexentry{Coords_init@{\tt Coords\_init()}}{2}
\indexentry{Coords_init9P@{\tt Coords\_init9P()}}{2}
\indexentry{Coords_init27P@{\tt Coords\_init27P()}}{2}
\indexentry{Coords_sizeOf@{\tt Coords\_sizeOf()}}{3}
\indexentry{Coords_min@{\tt Coords\_min()}}{3}
\indexentry{Coords_max@{\tt Coords\_max()}}{3}
\indexentry{Coords_value@{\tt Coords\_value()}}{3}
\indexentry{Coords_setValue@{\tt Coords\_setValue()}}{3}
\indexentry{Coords_readFromFile@{\tt Coords\_readFromFile()}}{4}
\indexentry{Coords_readFromFormattedFile@{\tt Coords\_readFromFormattedFile()}}{4}
\indexentry{Coords_readFromBinaryFile@{\tt Coords\_readFromBinaryFile()}}{4}
\indexentry{Coords_writeToFile@{\tt Coords\_writeToFile()}}{4}
\indexentry{Coords_writeToFormattedFile@{\tt Coords\_writeToFormattedFile()}}{4}
\indexentry{Coords_writeToBinaryFile@{\tt Coords\_writeToBinaryFile()}}{4}
\indexentry{Coords_writeForHumanEye@{\tt Coords\_writeForHumanEye()}}{5}
\indexentry{Coords_writeStats@{\tt Coords\_writeStats()}}{5}
Coords/doc/main.ind 0100644 0002055 0007177 00000001431 06535037434 0015517 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt Coords\_clearData()}, 2
\item {\tt Coords\_free()}, 2
\item {\tt Coords\_init()}, 2
\item {\tt Coords\_init27P()}, 2
\item {\tt Coords\_init9P()}, 2
\item {\tt Coords\_max()}, 3
\item {\tt Coords\_min()}, 3
\item {\tt Coords\_new()}, 2
\item {\tt Coords\_readFromBinaryFile()}, 4
\item {\tt Coords\_readFromFile()}, 4
\item {\tt Coords\_readFromFormattedFile()}, 4
\item {\tt Coords\_setDefaultFields()}, 2
\item {\tt Coords\_setValue()}, 3
\item {\tt Coords\_sizeOf()}, 3
\item {\tt Coords\_value()}, 3
\item {\tt Coords\_writeForHumanEye()}, 5
\item {\tt Coords\_writeStats()}, 5
\item {\tt Coords\_writeToBinaryFile()}, 4
\item {\tt Coords\_writeToFile()}, 4
\item {\tt Coords\_writeToFormattedFile()}, 4
\end{theindex}
Coords/doc/main.ilg 0100644 0002055 0007177 00000000456 06535037434 0015526 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (20 entries accepted, 0 rejected).
Sorting entries....done (93 comparisons).
Generating output file main.ind....done (24 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
Coords/doc/makefile 0100644 0002055 0007177 00000000027 06542767330 0015602 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
DSTree.h 0100644 0002055 0007177 00000000104 06534106401 0013362 0 ustar 00cleve compmath 0000040 0000006 #ifndef _DSTree_
#define _DSTree_
#include "DSTree/DSTree.h"
#endif
DSTree/DSTree.h 0100644 0002055 0007177 00000023541 06534106064 0014527 0 ustar 00cleve compmath 0000040 0000006 /* DSTree.h */
#include "../cfiles.h"
#include "../Tree.h"
#include "../IV.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
the DSTree object models a domain/separator tree.
it contains a Tree object to represent the connectivity of
the domains and separators and an IV object to contain the
map from vertices to domains and separators.
tree -- pointer to a Tree object that contains the tree adjacency
mapIV -- pointer to IV object that contains the map
from vertices to domains and separators
created -- 96mar10, cca
---------------------------------------------------------------------
*/
typedef struct _DSTree DSTree ;
struct _DSTree {
Tree *tree ;
IV *mapIV ;
} ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in basics.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------
purpose -- create and return a new DSTree object
created -- 96mar10, cca
-----------------------------------------------
*/
DSTree *
DSTree_new (
void
) ;
/*
------------------------------------------------------
purpose -- set the default fields for the DSTree object
created -- 96mar10, cca
------------------------------------------------------
*/
void
DSTree_setDefaultFields (
DSTree *dstree
) ;
/*
--------------------------------
purpose -- clear the data fields
created -- 96mar10, cca
--------------------------------
*/
void
DSTree_clearData (
DSTree *dstree
) ;
/*
--------------------------------
purpose -- free the DSTree object
created -- 96mar10, cca
--------------------------------
*/
void
DSTree_free (
DSTree *dstree
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in instance.c -------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------
return a pointer to the internal Tree object
created -- 97jun21, cca
--------------------------------------------
*/
Tree *
DSTree_tree (
DSTree *dstree
) ;
/*
-------------------------------------
return a pointer to the map IV object
created -- 97jun21, cca
-------------------------------------
*/
IV *
DSTree_mapIV (
DSTree *dstree
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in init.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------
initialize the object given the number of nodes
created -- 96mar10, cca
-----------------------------------------------
*/
void
DSTree_init1 (
DSTree *dstree,
int ndomsep,
int nvtx
) ;
/*
-----------------------------------------
initialize the object given a Tree object
created -- 96mar10, cca
-----------------------------------------
*/
void
DSTree_init2 (
DSTree *dstree,
Tree *tree,
IV *mapIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in stages.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------------
create a stages vector for a nested dissection ordering
created -- 96mar10, cca
-------------------------------------------------------
*/
IV *
DSTree_NDstages (
DSTree *dstree
) ;
/*
----------------------------------------------------------------
create a stages vector for a ``half'' nested dissection ordering
created -- 96mar10, cca
----------------------------------------------------------------
*/
IV *
DSTree_ND2stages (
DSTree *dstree
) ;
/*
------------------------------------------------------------
create a stages vector for a two-level multisection ordering
created -- 96mar10, cca
------------------------------------------------------------
*/
IV *
DSTree_MS2stages (
DSTree *dstree
) ;
/*
--------------------------------------------------------------
create a stages vector for a three-level multisection ordering
created -- 96mar10, cca
--------------------------------------------------------------
*/
IV *
DSTree_MS3stages (
DSTree *dstree
) ;
/*
---------------------------------------------------
create a stages vector via cutoff on domain weights
created -- 96mar10, cca
---------------------------------------------------
*/
IV *
DSTree_stagesViaDomainWeight (
DSTree *dstree,
int *vwghts,
DV *cutoffDV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in util.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 96mar10, cca
----------------------------------------------
*/
int
DSTree_sizeOf (
DSTree *dstree
) ;
/*
---------------------------------------------
renumber the fronts by a post-order traversal
created -- 96apr13, cca
---------------------------------------------
*/
void
DSTree_renumberViaPostOT (
DSTree * dstree
) ;
/*
-----------------------------------------------------------
purpose -- return the weight of the vertices in the domains
created -- 97jun21, cca
-----------------------------------------------------------
*/
int
DSTree_domainWeight (
DSTree *dstree,
int vwghts[]
) ;
/*
-----------------------------------------------------------
purpose -- return the weight of the vertices in the domains
created -- 97jun21, cca
-----------------------------------------------------------
*/
int
DSTree_domainWeight (
DSTree *dstree,
int vwghts[]
) ;
/*
--------------------------------------------------------------
purpose -- return the weight of the vertices in the separators
created -- 97jun21, cca
--------------------------------------------------------------
*/
int
DSTree_separatorWeight (
DSTree *dstree,
int vwghts[]
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in IO.c -------------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------
purpose -- to read in an DSTree object from a file
input --
fn -- filename, must be *.dstreeb or *.dstreef
return value -- 1 if success, 0 if failure
created -- 96mar10, cca
--------------------------------------------------
*/
int
DSTree_readFromFile (
DSTree *dstree,
char *fn
) ;
/*
---------------------------------------------------------
purpose -- to read an DSTree object from a formatted file
return value -- 1 if success, 0 if failure
created -- 96mar10, cca
---------------------------------------------------------
*/
int
DSTree_readFromFormattedFile (
DSTree *dstree,
FILE *fp
) ;
/*
------------------------------------------------------
purpose -- to read an DSTree object from a binary file
return value -- 1 if success, 0 if failure
created -- 96mar10, cca
------------------------------------------------------
*/
int
DSTree_readFromBinaryFile (
DSTree *dstree,
FILE *fp
) ;
/*
----------------------------------------------
purpose -- to write an DSTree object to a file
input --
fn -- filename
*.dstreeb -- binary
*.dstreef -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
----------------------------------------------
*/
int
DSTree_writeToFile (
DSTree *dstree,
char *fn
) ;
/*
--------------------------------------------------------
purpose -- to write an DSTree object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
--------------------------------------------------------
*/
int
DSTree_writeToFormattedFile (
DSTree *dstree,
FILE *fp
) ;
/*
-----------------------------------------------------
purpose -- to write an DSTree object to a binary file
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
-----------------------------------------------------
*/
int
DSTree_writeToBinaryFile (
DSTree *dstree,
FILE *fp
) ;
/*
----------------------------------------------------
purpose -- to write an DSTree object for a human eye
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
----------------------------------------------------
*/
int
DSTree_writeForHumanEye (
DSTree *dstree,
FILE *fp
) ;
/*
------------------------------------------------------------
purpose -- to write out the statistics for the DSTree object
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
------------------------------------------------------------
*/
int
DSTree_writeStats (
DSTree *dstree,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
DSTree/makefile 0100644 0002055 0007177 00000000223 06636223555 0014730 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd drivers ; make clean
cd doc ; make clean
DSTree/src/makefile 0100644 0002055 0007177 00000000741 06636022051 0015510 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = DSTree
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(init.o) \
$(OBJ).a(instance.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(stages.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
DSTree/src/makeGlobalLib 0100644 0002055 0007177 00000000640 06600260765 0016425 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = DSTree
SRC = basics.c \
init.c \
instance.c \
IO.c \
stages.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
DSTree/src/IO.c 0100644 0002055 0007177 00000027411 06534106062 0014470 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../DSTree.h"
static const char *suffixb = ".dstreeb" ;
static const char *suffixf = ".dstreef" ;
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
purpose -- to read in an DSTree object from a file
input --
fn -- filename, must be *.dstreeb or *.dstreef
return value -- 1 if success, 0 if failure
created -- 96mar10, cca
--------------------------------------------------
*/
int
DSTree_readFromFile (
DSTree *dstree,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL || fn == NULL ) {
fprintf(stderr, "\n error in DSTree_readFromFile(%p,%s)"
"\n bad input\n", dstree, fn) ;
return(0) ;
}
/*
-------------
read the file
-------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "rb")) == NULL ) {
fprintf(stderr, "\n error in DSTree_readFromFile(%p,%s)"
"\n unable to open file %s", dstree, fn, fn) ;
rc = 0 ;
} else {
rc = DSTree_readFromBinaryFile(dstree, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "r")) == NULL ) {
fprintf(stderr, "\n error in DSTree_readFromFile(%p,%s)"
"\n unable to open file %s", dstree, fn, fn) ;
rc = 0 ;
} else {
rc = DSTree_readFromFormattedFile(dstree, fp) ;
fclose(fp) ;
}
} else {
fprintf(stderr, "\n error in DSTree_readFromFile(%p,%s)"
"\n bad DSTree file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
dstree, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
} else {
fprintf(stderr, "\n error in DSTree_readFromFile(%p,%s)"
"\n bad DSTree file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
dstree, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
purpose -- to read an DSTree object from a formatted file
return value -- 1 if success, 0 if failure
created -- 96mar10, cca
---------------------------------------------------------
*/
int
DSTree_readFromFormattedFile (
DSTree *dstree,
FILE *fp
) {
IV *mapIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL || fp == NULL ) {
fprintf(stderr, "\n error in DSTree_readFromFormattedFile(%p,%p)"
"\n bad input\n", dstree, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
DSTree_clearData(dstree) ;
/*
-----------------------
read in the Tree object
-----------------------
*/
tree = Tree_new() ;
Tree_readFromFormattedFile(tree, fp) ;
/*
---------------------
read in the IV object
---------------------
*/
mapIV = IV_new() ;
IV_readFromFormattedFile(mapIV, fp) ;
/*
----------------------------
initialize the DSTree object
----------------------------
*/
DSTree_init2(dstree, tree, mapIV) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- to read an DSTree object from a binary file
return value -- 1 if success, 0 if failure
created -- 96mar10, cca
------------------------------------------------------
*/
int
DSTree_readFromBinaryFile (
DSTree *dstree,
FILE *fp
) {
IV *mapIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_readFromBinaryFile(%p,%p)"
"\n bad input\n", dstree, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
DSTree_clearData(dstree) ;
/*
-----------------------
read in the Tree object
-----------------------
*/
tree = Tree_new() ;
Tree_readFromBinaryFile(tree, fp) ;
/*
---------------------
read in the IV object
---------------------
*/
mapIV = IV_new() ;
IV_readFromBinaryFile(mapIV, fp) ;
/*
----------------------------
initialize the DSTree object
----------------------------
*/
DSTree_init2(dstree, tree, mapIV) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
purpose -- to write an DSTree object to a file
input --
fn -- filename
*.dstreeb -- binary
*.dstreef -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
----------------------------------------------
*/
int
DSTree_writeToFile (
DSTree *dstree,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL || fn == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_writeToFile(%p,%s)"
"\n bad input\n", dstree, fn) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in DSTree_writeToFile(%p,%s)"
"\n unable to open file %s", dstree, fn, fn) ;
rc = 0 ;
} else {
rc = DSTree_writeToBinaryFile(dstree, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "w")) == NULL ) {
fprintf(stderr, "\n error in DSTree_writeToFile(%p,%s)"
"\n unable to open file %s", dstree, fn, fn) ;
rc = 0 ;
} else {
rc = DSTree_writeToFormattedFile(dstree, fp) ;
fclose(fp) ;
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in DSTree_writeToFile(%p,%s)"
"\n unable to open file %s", dstree, fn, fn) ;
rc = 0 ;
} else {
rc = DSTree_writeForHumanEye(dstree, fp) ;
fclose(fp) ;
}
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in DSTree_writeToFile(%p,%s)"
"\n unable to open file %s", dstree, fn, fn) ;
rc = 0 ;
} else {
rc = DSTree_writeForHumanEye(dstree, fp) ;
fclose(fp) ;
}
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- to write an DSTree object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
--------------------------------------------------------
*/
int
DSTree_writeToFormattedFile (
DSTree *dstree,
FILE *fp
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL || fp == NULL || dstree->tree == NULL ) {
fprintf(stderr,
"\n fatal error in DSTree_writeToFormattedFile(%p,%p)"
"\n bad input\n", dstree, fp) ;
exit(-1) ;
}
/*
---------------------------------
write the Tree object to the file
---------------------------------
*/
rc = Tree_writeToFormattedFile(dstree->tree, fp) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in DSTree_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from writing Tree to file\n",
dstree, fp, rc) ;
return(0) ;
}
/*
-------------------------------
write the IV object to the file
-------------------------------
*/
rc = IV_writeToFormattedFile(dstree->mapIV, fp) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in DSTree_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from writing IV to file\n",
dstree, fp, rc) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
purpose -- to write an DSTree object to a binary file
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
-----------------------------------------------------
*/
int
DSTree_writeToBinaryFile (
DSTree *dstree,
FILE *fp
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL || fp == NULL || dstree->tree == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_writeToBinaryFile(%p,%p)"
"\n bad input\n", dstree, fp) ;
exit(-1) ;
}
/*
---------------------------------
write the Tree object to the file
---------------------------------
*/
rc = Tree_writeToBinaryFile(dstree->tree, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in DSTree_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from writing Tree to file\n",
dstree, fp, rc) ;
return(0) ;
}
/*
-------------------------------
write the IV object to the file
-------------------------------
*/
rc = IV_writeToBinaryFile(dstree->mapIV, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in DSTree_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from writing IV to file\n",
dstree, fp, rc) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
purpose -- to write an DSTree object for a human eye
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
----------------------------------------------------
*/
int
DSTree_writeForHumanEye (
DSTree *dstree,
FILE *fp
) {
int rc ;
if ( dstree == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_writeForHumanEye(%p,%p)"
"\n bad input\n", dstree, fp) ;
exit(-1) ;
}
if ( (rc = DSTree_writeStats(dstree, fp)) == 0 ) {
fprintf(stderr, "\n fatal error in DSTree_writeForHumanEye(%p,%p)"
"\n rc = %d, return from DSTree_writeStats(%p,%p)\n",
dstree, fp, rc, dstree, fp) ;
return(0) ;
}
fprintf(fp, "\n\n domain/separator tree") ;
Tree_writeForHumanEye(dstree->tree, fp) ;
fprintf(fp, "\n\n map from vertices to domains and separators") ;
IV_writeForHumanEye(dstree->mapIV, fp) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
purpose -- to write out the statistics for the DSTree object
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
------------------------------------------------------------
*/
int
DSTree_writeStats (
DSTree *dstree,
FILE *fp
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL || fp == NULL ) {
fprintf(stderr, "\n error in DSTree_writeStats(%p,%p)"
"\n bad input\n", dstree, fp) ;
exit(-1) ;
}
rc = fprintf(fp, "\n DSTree : dstree object") ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in DSTree_writeStats(%p,%p)"
"\n rc = %d, return from fprintf\n", dstree, fp, rc) ;
return(0) ;
}
if ( dstree->tree != NULL && dstree->mapIV != NULL ) {
rc = fprintf(fp,
"\n %d domains and separators, %d vertices, occupies %d bytes",
dstree->tree->n, IV_size(dstree->mapIV), DSTree_sizeOf(dstree)) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in DSTree_writeStats(%p,%p)"
"\n rc = %d, return from fprintf\n", dstree, fp, rc) ;
return(0) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
matted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 96mar10, cca
----------------------------------------------
*/
int
DSTree_writeToFile (
DSTree *dstree,
char *fn
) {
FILE DSTree/src/basics.c 0100644 0002055 0007177 00000005630 06534106062 0015424 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../DSTree.h"
#define MYTRACE 0
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
purpose -- create and return a new DSTree object
created -- 96mar10, cca
-----------------------------------------------
*/
DSTree *
DSTree_new (
void
) {
DSTree *dstree ;
#if MYTRACE > 0
fprintf(stdout, "\n just inside DSTree_new()") ;
fflush(stdout) ;
#endif
ALLOCATE(dstree, struct _DSTree, 1) ;
DSTree_setDefaultFields(dstree) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving DSTree_new()") ;
fflush(stdout) ;
#endif
return(dstree) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- set the default fields for the DSTree object
created -- 96mar10, cca
------------------------------------------------------
*/
void
DSTree_setDefaultFields (
DSTree *dstree
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside DSTree_setDefaultFields(%)", g) ;
fflush(stdout) ;
#endif
if ( dstree == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_setDefaultFields(%p)"
"\n dstree is NULL\n", dstree) ;
exit(-1) ;
}
dstree->tree = NULL ;
dstree->mapIV = NULL ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving DSTree_setDefaultFields(%)", dstree) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------
purpose -- clear the data fields
created -- 96mar10, cca
--------------------------------
*/
void
DSTree_clearData (
DSTree *dstree
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside DSTree_clearData(%)", dstree) ;
fflush(stdout) ;
#endif
if ( dstree == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_clearData(%p)"
"\n dstree is NULL\n", dstree) ;
exit(-1) ;
}
if ( dstree->tree != NULL ) {
Tree_clearData(dstree->tree) ;
Tree_free(dstree->tree) ;
}
if ( dstree->mapIV != NULL ) {
IV_free(dstree->mapIV) ;
}
DSTree_setDefaultFields(dstree) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving DSTree_clearData(%)", dstree) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------
purpose -- free the DSTree object
created -- 96mar10, cca
--------------------------------
*/
void
DSTree_free (
DSTree *dstree
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside DSTree_free(%)", dstree) ;
fflush(stdout) ;
#endif
if ( dstree == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_free(%p)"
"\n dstree is NULL\n", dstree) ;
exit(-1) ;
}
DSTree_clearData(dstree) ;
FREE(dstree) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving DSTree_free(%)", dstree) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
DSTree/src/init.c 0100644 0002055 0007177 00000003165 06534106062 0015124 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../DSTree.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
initialize the object given the number of nodes
created -- 96mar10, cca
-----------------------------------------------
*/
void
DSTree_init1 (
DSTree *dstree,
int ndomsep,
int nvtx
) {
/*
---------------
check the input
---------------
*/
if ( dstree == NULL || ndomsep <= 0 ) {
fprintf(stderr, "\n fatal error in DSTree_init1(%p,%d,%d)"
"\n bad input\n", dstree, ndomsep, nvtx) ;
exit(-1) ;
}
DSTree_clearData(dstree) ;
dstree->tree = Tree_new() ;
Tree_init1(dstree->tree, ndomsep) ;
dstree->mapIV = IV_new() ;
IV_init(dstree->mapIV, nvtx, NULL) ;
IV_fill(dstree->mapIV, -1) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
initialize the object given a Tree object and a map IV object
created -- 96mar10, cca
-------------------------------------------------------------
*/
void
DSTree_init2 (
DSTree *dstree,
Tree *tree,
IV *mapIV
) {
/*
---------------
check the input
---------------
*/
if ( dstree == NULL || tree == NULL || tree->n < 1
|| mapIV == NULL || IV_size(mapIV) < 1 ) {
fprintf(stderr, "\n fatal error in DSTree_init2(%p,%p,%p)"
"\n bad input\n", dstree, tree, mapIV) ;
exit(-1) ;
}
DSTree_clearData(dstree) ;
dstree->tree = tree ;
dstree->mapIV = mapIV ;
return ; }
/*--------------------------------------------------------------------*/
rData(dstree) ;
dstree->tree = Tree_new() ;
Tree_init1(dstree->tree, ndomsep) ;
dstree->mapIV = IV_new() ;
IV_init(dstree->mapIV, nvtx, NULL) ;
IV_fill(dstree->mapIV, -1) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
initialize the object given a Tree object and a map IV object
DSTree/src/instance.c 0100644 0002055 0007177 00000002156 06534106063 0015765 0 ustar 00cleve compmath 0000040 0000006 /* instance.c */
#include "../DSTree.h"
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
return a pointer to the internal Tree object
created -- 97jun21, cca
--------------------------------------------
*/
Tree *
DSTree_tree (
DSTree *dstree
) {
/*
---------------
check the input
---------------
*/
if ( dstree == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_tree(%p)"
"\n bad input\n", dstree) ;
exit(-1) ;
}
return(dstree->tree) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------
return a pointer to the map IV object
created -- 97jun21, cca
-------------------------------------
*/
IV *
DSTree_mapIV (
DSTree *dstree
) {
/*
---------------
check the input
---------------
*/
if ( dstree == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_mapIV(%p)"
"\n bad input\n", dstree) ;
exit(-1) ;
}
return(dstree->mapIV) ; }
/*--------------------------------------------------------------------*/
DSTree/src/stages.c 0100644 0002055 0007177 00000031523 06534106062 0015446 0 ustar 00cleve compmath 0000040 0000006 /* stages.c */
#include "../DSTree.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
create a stages vector for a nested dissection ordering
created -- 96mar10, cca
-------------------------------------------------------
*/
IV *
DSTree_NDstages (
DSTree *dstree
) {
int ndomsep, nvtx, v ;
int *hmetric, *map, *stages ;
IV *hmetricIV, *mapIV, *stagesIV, *vmetricIV ;
Tree *tree ;
/*
--------------
check the data
--------------
*/
if ( dstree == NULL
|| (tree = dstree->tree) == NULL
|| (ndomsep = tree->n) < 1
|| (mapIV = dstree->mapIV) == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_NDstages(%p)"
"\n bad input\n", dstree) ;
exit(-1) ;
}
IV_sizeAndEntries(mapIV, &nvtx, &map) ;
if ( map == NULL || nvtx < 1 ) {
fprintf(stderr, "\n fatal error in DSTree_NDstages(%p)"
"\n bad mapIV object\n", dstree) ;
exit(-1) ;
}
/*
----------------------------------
get the height metric for the tree
----------------------------------
*/
vmetricIV = IV_new() ;
IV_init(vmetricIV, ndomsep, NULL) ;
IV_fill(vmetricIV, 1) ;
hmetricIV = Tree_setHeightImetric(tree, vmetricIV) ;
hmetric = IV_entries(hmetricIV) ;
/*
------------------------------------
set the stages for nested dissection
------------------------------------
*/
stagesIV = IV_new() ;
IV_init(stagesIV, nvtx, NULL) ;
stages = IV_entries(stagesIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
stages[v] = hmetric[map[v]] - 1 ;
}
/*
------------------------
free the working storage
------------------------
*/
IV_free(vmetricIV) ;
IV_free(hmetricIV) ;
return(stagesIV) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
create a stages vector for a ``half'' nested dissection ordering
created -- 96mar10, cca
----------------------------------------------------------------
*/
IV *
DSTree_ND2stages (
DSTree *dstree
) {
int ndomsep, nvtx, v ;
int *hmetric, *map, *stages ;
IV *hmetricIV, *mapIV, *stagesIV, *vmetricIV ;
Tree *tree ;
/*
--------------
check the data
--------------
*/
if ( dstree == NULL
|| (tree = dstree->tree) == NULL
|| (ndomsep = tree->n) < 1
|| (mapIV = dstree->mapIV) == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_ND2stages(%p)"
"\n bad input\n", dstree) ;
exit(-1) ;
}
IV_sizeAndEntries(mapIV, &nvtx, &map) ;
if ( map == NULL || nvtx < 1 ) {
fprintf(stderr, "\n fatal error in DSTree_ND2stages(%p)"
"\n bad mapIV object\n", dstree) ;
exit(-1) ;
}
/*
----------------------------------
get the height metric for the tree
----------------------------------
*/
vmetricIV = IV_new() ;
IV_init(vmetricIV, ndomsep, NULL) ;
IV_fill(vmetricIV, 1) ;
hmetricIV = Tree_setHeightImetric(tree, vmetricIV) ;
hmetric = IV_entries(hmetricIV) ;
/*
------------------------------------
set the stages for nested dissection
------------------------------------
*/
stagesIV = IV_new() ;
IV_init(stagesIV, nvtx, NULL) ;
stages = IV_entries(stagesIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
stages[v] = hmetric[map[v]] - 1 ;
if ( stages[v] > 0 ) {
stages[v] = (1 + stages[v])/2 ;
}
}
/*
------------------------
free the working storage
------------------------
*/
IV_free(vmetricIV) ;
IV_free(hmetricIV) ;
return(stagesIV) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
create a stages vector for a two-level multisection ordering
created -- 96mar10, cca
------------------------------------------------------------
*/
IV *
DSTree_MS2stages (
DSTree *dstree
) {
int ndomsep, nvtx, v ;
int *hmetric, *map, *stages ;
IV *hmetricIV, *mapIV, *stagesIV, *vmetricIV ;
Tree *tree ;
/*
--------------
check the data
--------------
*/
if ( dstree == NULL
|| (tree = dstree->tree) == NULL
|| (ndomsep = tree->n) < 1
|| (mapIV = dstree->mapIV) == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_MS2stages(%p)"
"\n bad input\n", dstree) ;
exit(-1) ;
}
IV_sizeAndEntries(mapIV, &nvtx, &map) ;
if ( map == NULL || nvtx < 1 ) {
fprintf(stderr, "\n fatal error in DSTree_MS2stages(%p)"
"\n bad mapIV object\n", dstree) ;
exit(-1) ;
}
/*
----------------------------------
get the height metric for the tree
----------------------------------
*/
vmetricIV = IV_new() ;
IV_init(vmetricIV, ndomsep, NULL) ;
IV_fill(vmetricIV, 1) ;
hmetricIV = Tree_setHeightImetric(tree, vmetricIV) ;
hmetric = IV_entries(hmetricIV) ;
/*
-----------------------------------------
set the stages for two-level multisection
-----------------------------------------
*/
stagesIV = IV_new() ;
IV_init(stagesIV, nvtx, NULL) ;
stages = IV_entries(stagesIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
stages[v] = hmetric[map[v]] - 1 ;
if ( stages[v] > 0 ) {
stages[v] = 1 ;
}
}
/*
------------------------
free the working storage
------------------------
*/
IV_free(vmetricIV) ;
IV_free(hmetricIV) ;
return(stagesIV) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
create a stages vector for a three-level multisection ordering
created -- 96mar10, cca
--------------------------------------------------------------
*/
IV *
DSTree_MS3stages (
DSTree *dstree
) {
int ndomsep, nstage, nvtx, v ;
int *hmetric, *map, *stages ;
IV *hmetricIV, *mapIV, *stagesIV, *vmetricIV ;
Tree *tree ;
/*
--------------
check the data
--------------
*/
if ( dstree == NULL
|| (tree = dstree->tree) == NULL
|| (ndomsep = tree->n) < 1
|| (mapIV = dstree->mapIV) == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_MS3stages(%p)"
"\n bad input\n", dstree) ;
exit(-1) ;
}
IV_sizeAndEntries(mapIV, &nvtx, &map) ;
if ( map == NULL || nvtx < 1 ) {
fprintf(stderr, "\n fatal error in DSTree_MS3stages(%p)"
"\n bad mapIV object\n", dstree) ;
exit(-1) ;
}
/*
----------------------------------
get the height metric for the tree
----------------------------------
*/
vmetricIV = IV_new() ;
IV_init(vmetricIV, ndomsep, NULL) ;
IV_fill(vmetricIV, 1) ;
hmetricIV = Tree_setHeightImetric(tree, vmetricIV) ;
hmetric = IV_entries(hmetricIV) ;
nstage = IV_max(hmetricIV) ;
/*
-------------------------------------------
set the stages for three-level multisection
-------------------------------------------
*/
stagesIV = IV_new() ;
IV_init(stagesIV, nvtx, NULL) ;
stages = IV_entries(stagesIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
stages[v] = hmetric[map[v]] - 1 ;
if ( stages[v] > 0 ) {
if ( 2*stages[v] > nstage ) {
stages[v] = 2 ;
} else {
stages[v] = 1 ;
}
}
}
/*
------------------------
free the working storage
------------------------
*/
IV_free(vmetricIV) ;
IV_free(hmetricIV) ;
return(stagesIV) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
create a stages vector via cutoff on domain weights
created -- 97jun12, cca
---------------------------------------------------
*/
IV *
DSTree_stagesViaDomainWeight (
DSTree *dstree,
int *vwghts,
DV *cutoffDV
) {
double totvwght ;
double *cutoffs, *nodewghts, *subtreewghts ;
DV *nodewghtDV, *subtreeDV ;
int ireg, istage, jstage, ndomsep, nstage, nvtx, v ;
int *map, *mark, *regmap, *stages ;
IV *mapIV, *stagesIV ;
Tree *tree ;
/*
--------------
check the data
--------------
*/
if ( dstree == NULL
|| (tree = dstree->tree) == NULL
|| (ndomsep = tree->n) < 1
|| (mapIV = dstree->mapIV) == NULL
|| cutoffDV == NULL ) {
fprintf(stderr,
"\n fatal error in DSTree_stagesViaDomainWeight(%p,%p,%p)"
"\n bad input\n", dstree, vwghts, cutoffDV) ;
exit(-1) ;
}
IV_sizeAndEntries(mapIV, &nvtx, &map) ;
if ( map == NULL || nvtx < 1 ) {
fprintf(stderr,
"\n fatal error in DSTree_stagesViaDomainWeight(%p,%p,%p)"
"\n bad mapIV object\n", dstree, vwghts, cutoffDV) ;
exit(-1) ;
}
DV_sizeAndEntries(cutoffDV, &nstage, &cutoffs) ;
if ( cutoffs == NULL || nstage < 1 ) {
fprintf(stderr,
"\n fatal error in DSTree_stagesViaDomainWeight(%p,%p,%p)"
"\n bad cutoffDV object\n", dstree, vwghts, cutoffDV) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n %d stages", nstage) ;
DVfprintf(stdout, nstage, cutoffs) ;
#endif
/*
--------------------------------
get the node metric for the tree
--------------------------------
*/
nodewghtDV = DV_new() ;
DV_init(nodewghtDV, ndomsep, NULL) ;
DV_fill(nodewghtDV, 0.0) ;
nodewghts = DV_entries(nodewghtDV) ;
totvwght = 0.0 ;
if ( vwghts == NULL ) {
for ( v = 0 ; v < nvtx ; v++ ) {
nodewghts[map[v]]++ ;
}
totvwght = nvtx ;
} else {
for ( v = 0 ; v < nvtx ; v++ ) {
nodewghts[map[v]] += vwghts[v] ;
totvwght += vwghts[v] ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n node metric") ;
DV_writeForHumanEye(nodewghtDV, stdout) ;
#endif
/*
----------------------------------
get the subtree metric for the tree
----------------------------------
*/
subtreeDV = Tree_setSubtreeDmetric(tree, nodewghtDV) ;
subtreewghts = DV_entries(subtreeDV) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n subtree metric before scale") ;
DV_writeForHumanEye(subtreeDV, stdout) ;
#endif
for ( ireg = 0 ; ireg < ndomsep ; ireg++ ) {
subtreewghts[ireg] /= totvwght ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n subtree metric after scale") ;
DV_writeForHumanEye(subtreeDV, stdout) ;
#endif
/*
----------------------------
mark all stages with support
----------------------------
*/
mark = IVinit(nstage, -1) ;
for ( ireg = 0 ; ireg < ndomsep ; ireg++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n region %d, subtree weight %.4f",
ireg, subtreewghts[ireg]) ;
fflush(stdout) ;
#endif
for ( istage = 0 ; istage < nstage - 1 ; istage++ ) {
if ( cutoffs[istage] <= subtreewghts[ireg]
&& subtreewghts[ireg] < cutoffs[istage+1] ) {
mark[istage] = 1 ;
#if MYDEBUG > 0
fprintf(stdout, ", found in stage %d", istage) ;
fflush(stdout) ;
#endif
break ;
}
}
if ( istage == nstage - 1 ) {
mark[nstage - 1] = 1 ;
}
}
/*
------------------
slide cutoffs down
------------------
*/
for ( istage = jstage = 0 ; istage < nstage ; istage++ ) {
if ( mark[istage] == 1 ) {
#if MYDEBUG > 0
fprintf(stdout, "\n stage %d marked", istage) ;
fflush(stdout) ;
#endif
cutoffs[jstage++] = cutoffs[istage] ;
}
}
nstage = jstage ;
/*
----------------------------------
get the map from regions to stages
----------------------------------
*/
regmap = IVinit(ndomsep, -1) ;
for ( ireg = 0 ; ireg < ndomsep ; ireg++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n region %d, subtree weight %.4f",
ireg, subtreewghts[ireg]) ;
fflush(stdout) ;
#endif
for ( istage = 0 ; istage < nstage - 1 ; istage++ ) {
if ( cutoffs[istage] <= subtreewghts[ireg]
&& subtreewghts[ireg] < cutoffs[istage+1] ) {
#if MYDEBUG > 0
fprintf(stdout, ", found in stage %d", istage) ;
fflush(stdout) ;
#endif
regmap[ireg] = istage ;
break ;
}
}
if ( istage == nstage - 1 ) {
regmap[ireg] = nstage - 1 ;
#if MYDEBUG > 0
fprintf(stdout, ", found in stage %d", nstage - 1) ;
fflush(stdout) ;
#endif
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n region to stage map") ;
IVfp80(stdout, ndomsep, regmap, 80, &ierr) ;
#endif
/*
--------------
set the stages
--------------
*/
stagesIV = IV_new() ;
IV_init(stagesIV, nvtx, NULL) ;
stages = IV_entries(stagesIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
stages[v] = regmap[map[v]] ;
}
#if MYDEBUG > 0
stageWeights = DVinit(nstage, 0.0) ;
for ( ireg = 0 ; ireg < ndomsep ; ireg++ ) {
stageWeights[regmap[ireg]] += nodewghts[ireg] ;
}
fprintf(stdout, "\n\n stageWeights, sum = %.4f",
DVsum(nstage, stageWeights)) ;
DVfprintf(stdout, nstage, stageWeights) ;
for ( istage = nstage - 2 ; istage >= 0 ; istage-- ) {
stageWeights[istage] += stageWeights[istage+1] ;
}
fprintf(stdout, "\n\n stageWeights, sum = %.4f",
DVsum(nstage, stageWeights)) ;
for ( istage = 0 ; istage < nstage ; istage++ ) {
stageWeights[istage] /= totvwght ;
}
fprintf(stdout, "\n\n stageWeights, sum = %.4f",
DVsum(nstage, stageWeights)) ;
DVfprintf(stdout, nstage, stageWeights) ;
DVfree(stageWeights) ;
#endif
/*
------------------------
free the working storage
------------------------
*/
DV_free(nodewghtDV) ;
DV_free(subtreeDV) ;
IVfree(regmap) ;
IVfree(mark) ;
return(stagesIV) ; }
/*--------------------------------------------------------------------*/
hmetricIV = Tree_setHeightImetric(tree, vmetricIV) ;
hmetric = IV_entries(hmetricIV) ;
nstage = IV_max(hmetricIV) ;
/*
-------------------------------------------
setDSTree/src/util.c 0100644 0002055 0007177 00000011632 06534106063 0015135 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../DSTree.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 96mar10, cca
----------------------------------------------
*/
int
DSTree_sizeOf (
DSTree *dstree
) {
int nbytes ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_sizeOf(%p)"
"\n bad input\n", dstree) ;
exit(-1) ;
}
nbytes = sizeof(struct _DSTree) ;
if ( dstree->tree != NULL ) {
nbytes += Tree_sizeOf(dstree->tree) ;
}
if ( dstree->mapIV != NULL ) {
nbytes += IV_sizeOf(dstree->mapIV) ;
}
return(nbytes) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
renumber the fronts by a post-order traversal
created -- 96apr13, cca
---------------------------------------------
*/
void
DSTree_renumberViaPostOT (
DSTree * dstree
) {
int count, J, K, n, nvtx, v ;
int *map, *oldmap, *temp ;
IV *mapIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL
|| (tree = dstree->tree) == NULL
|| (n = tree->n) <= 0
|| (mapIV = dstree->mapIV) == NULL
|| (nvtx = IV_size(mapIV)) <= 0
|| (oldmap = IV_entries(mapIV)) == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_renumberViaPostOT(%p)"
"\n bad input\n", dstree) ;
exit(-1) ;
}
/*
---------------------------------
renumber the Tree object but
preserve the post-order traversal
---------------------------------
*/
map = IVinit(n, -1) ;
temp = IVinit(n, -1) ;
count = 0 ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
map[J] = count++ ;
}
for ( J = 0 ; J < n ; J++ ) {
if ( (K = tree->par[J]) != -1 ) {
temp[map[J]] = map[K] ;
} else {
temp[map[J]] = -1 ;
}
}
IVcopy(n, tree->par, temp) ;
for ( J = 0 ; J < n ; J++ ) {
if ( (K = tree->fch[J]) != -1 ) {
temp[map[J]] = map[K] ;
} else {
temp[map[J]] = -1 ;
}
}
IVcopy(n, tree->fch, temp) ;
for ( J = 0 ; J < n ; J++ ) {
if ( (K = tree->sib[J]) != -1 ) {
temp[map[J]] = map[K] ;
} else {
temp[map[J]] = -1 ;
}
}
IVcopy(n, tree->sib, temp) ;
if ( tree->root != -1 ) {
tree->root = map[tree->root] ;
}
/*
-----------------------------
remap the vertex to front map
-----------------------------
*/
for ( v = 0 ; v < nvtx ; v++ ) {
J = oldmap[v] ;
if ( 0 <= J && J < n ) {
oldmap[v] = map[J] ;
}
}
IVfree(map) ;
IVfree(temp) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- return the weight of the vertices in the domains
created -- 97jun21, cca
-----------------------------------------------------------
*/
int
DSTree_domainWeight (
DSTree *dstree,
int vwghts[]
) {
int domwght, ireg, nvtx, v ;
int *fch, *map ;
IV *mapIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_domainWeight(%p)"
"\n bad input\n", dstree) ;
exit(-1) ;
}
tree = DSTree_tree(dstree) ;
mapIV = DSTree_mapIV(dstree) ;
IV_sizeAndEntries(mapIV, &nvtx, &map) ;
fch = tree->fch ;
if ( vwghts != NULL ) {
for ( v = domwght = 0 ; v < nvtx ; v++ ) {
ireg = map[v] ;
if ( fch[ireg] == -1 ) {
domwght += vwghts[v] ;
}
}
} else {
for ( v = domwght = 0 ; v < nvtx ; v++ ) {
ireg = map[v] ;
if ( fch[ireg] == -1 ) {
domwght++ ;
}
}
}
return(domwght) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
purpose -- return the weight of the vertices in the separators
created -- 97jun21, cca
--------------------------------------------------------------
*/
int
DSTree_separatorWeight (
DSTree *dstree,
int vwghts[]
) {
int ireg, nvtx, sepwght, v ;
int *fch, *map ;
IV *mapIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( dstree == NULL ) {
fprintf(stderr, "\n fatal error in DSTree_separatorWeight(%p)"
"\n bad input\n", dstree) ;
exit(-1) ;
}
tree = DSTree_tree(dstree) ;
mapIV = DSTree_mapIV(dstree) ;
IV_sizeAndEntries(mapIV, &nvtx, &map) ;
fch = tree->fch ;
if ( vwghts != NULL ) {
for ( v = sepwght = 0 ; v < nvtx ; v++ ) {
ireg = map[v] ;
if ( fch[ireg] != -1 ) {
sepwght += vwghts[v] ;
}
}
} else {
for ( v = sepwght = 0 ; v < nvtx ; v++ ) {
ireg = map[v] ;
if ( fch[ireg] != -1 ) {
sepwght++ ;
}
}
}
return(sepwght) ; }
/*--------------------------------------------------------------------*/
temp[map[J]] = map[K] ;
} else {
temp[map[J]] = -1 ;
}
}
IVcopy(n, tree->par, temp) ;DSTree/drivers/do_domWeight 0100755 0002055 0007177 00000000612 06534106064 0017237 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inGraphFile = $matrices/$matrix/orig0.graphf
set inDSTreeFile = $matrices/$matrix/nd.dstreef
set inCutoffFile = cutoff.dvf
set outStagesFile = temp.ivf
set msglvl = 1
set msgFile = stdout
testDomWeightStages $msglvl $msgFile \
$inDSTreeFile \
$inGraphFile \
$inCutoffFile \
$outStagesFile
DSTree/drivers/do_stages 0100755 0002055 0007177 00000000573 06534106064 0016604 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inGraphFile = $matrices/$matrix/orig0.graphf
set inDSTreeFile = $matrices/$matrix/nd.dstreef
set outStagesFile = temp.ivf
set outStagesFile = $matrices/$matrix/ndstages.ivf
set msglvl = 1
set msgFile = stdout
writeStagesIV $msglvl $msgFile \
$inDSTreeFile \
ND \
$outStagesFile
DSTree/drivers/do_testIO 0100755 0002055 0007177 00000000410 06534106064 0016513 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inFile = $matrices/$matrix/nd.dstreef
set outFile = $matrices/$matrix/nd.dstreeb
set outFile = none
set msglvl = 3
set msgFile = stdout
testIO $msglvl $msgFile $inFile $outFile
DSTree/drivers/makefile 0100644 0002055 0007177 00000001055 06653142413 0016402 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = testIO writeStagesIV testDomWeightStages
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
testIO : testIO.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testDomWeightStages : testDomWeightStages.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
writeStagesIV : writeStagesIV.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
DSTree/drivers/testDomWeightStages.c 0100644 0002055 0007177 00000012674 06542223370 0021014 0 ustar 00cleve compmath 0000040 0000006 /* testDomWeightStages.c */
#include "../../Graph.h"
#include "../DSTree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------------
read in a DSTree object, read in a Graph file,
read in a DV cutoffs file, get the stages IV object
based on domain weight and write it to a file.
created -- 97jun12, cca
---------------------------------------------------
*/
{
char *inCutoffDVfileName, *inDSTreeFileName,
*inGraphFileName, *outIVfileName ;
double t1, t2 ;
DV *cutoffDV ;
Graph *graph ;
int msglvl, rc ;
IV *stagesIV ;
DSTree *dstree ;
FILE *msgFile ;
if ( argc != 7 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inDSTreeFile inGraphFile "
"\n inCutoffDVfile outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inDSTreeFile -- input file, must be *.dstreef or *.dstreeb"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n inCutoffDVfile -- input file, must be *.dvf or *.dvb"
"\n outFile -- output file, must be *.ivf or *.ivb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inDSTreeFileName = argv[3] ;
inGraphFileName = argv[4] ;
inCutoffDVfileName = argv[5] ;
outIVfileName = argv[6] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inDSTreeFileName -- %s"
"\n inGraphFileName -- %s"
"\n inCutoffDVfileName -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], inDSTreeFileName,
inGraphFileName, inCutoffDVfileName, outIVfileName) ;
fflush(msgFile) ;
/*
-------------------------
read in the DSTree object
-------------------------
*/
if ( strcmp(inDSTreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
dstree = DSTree_new() ;
MARKTIME(t1) ;
rc = DSTree_readFromFile(dstree, inDSTreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in dstree from file %s",
t2 - t1, inDSTreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from DSTree_readFromFile(%p,%s)",
rc, dstree, inDSTreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading DSTree object from file %s",
inDSTreeFileName) ;
if ( msglvl > 2 ) {
DSTree_writeForHumanEye(dstree, msgFile) ;
} else {
DSTree_writeStats(dstree, msgFile) ;
}
fflush(msgFile) ;
/*
-------------------------
read in the Graph object
-------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
-----------------------------
read in the cutoffs DV object
-----------------------------
*/
if ( strcmp(inCutoffDVfileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
cutoffDV = DV_new() ;
MARKTIME(t1) ;
rc = DV_readFromFile(cutoffDV, inCutoffDVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inCutoffDVfileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from DV_readFromFile(%p,%s)",
rc, cutoffDV, inCutoffDVfileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading DV object from file %s",
inCutoffDVfileName) ;
if ( msglvl > 0 ) {
DV_writeForHumanEye(cutoffDV, msgFile) ;
} else {
DV_writeStats(cutoffDV, msgFile) ;
}
fflush(msgFile) ;
/*
---------------------
get the stages vector
---------------------
*/
stagesIV = DSTree_stagesViaDomainWeight(dstree,
graph->vwghts, cutoffDV) ;
if ( msglvl > 2 ) {
IV_writeForHumanEye(stagesIV, msgFile) ;
} else {
IV_writeStats(stagesIV, msgFile) ;
}
fflush(msgFile) ;
/*
---------------------------
write out the DSTree object
---------------------------
*/
if ( stagesIV != NULL && strcmp(outIVfileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = IV_writeToFile(stagesIV, outIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write dstree to file %s",
t2 - t1, outIVfileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from IV_writeToFile(%p,%s)",
rc, stagesIV, outIVfileName) ;
}
}
/*
----------------------
free the DSTree object
----------------------
*/
DSTree_free(dstree) ;
if ( stagesIV != NULL ) {
IV_free(stagesIV) ;
}
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
f ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from DSTree_DSTree/drivers/testIO.c 0100644 0002055 0007177 00000005740 06542223403 0016256 0 ustar 00cleve compmath 0000040 0000006 /* testIO.c */
#include "../DSTree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
--------------------------------------------------
test DSTree_readFromFile and DSTree_writeToFile,
useful for translating between formatted *.dstreef
and binary *.dstreeb files.
created -- 97feb01, cca
--------------------------------------------------
*/
{
char *inDSTreeFileName, *outDSTreeFileName ;
double t1, t2 ;
int msglvl, rc ;
DSTree *dstree ;
FILE *msgFile ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.dstreef or *.dstreeb"
"\n outFile -- output file, must be *.dstreef or *.dstreeb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inDSTreeFileName = argv[3] ;
outDSTreeFileName = argv[4] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], inDSTreeFileName, outDSTreeFileName) ;
fflush(msgFile) ;
/*
-------------------------
read in the DSTree object
-------------------------
*/
if ( strcmp(inDSTreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
dstree = DSTree_new() ;
MARKTIME(t1) ;
rc = DSTree_readFromFile(dstree, inDSTreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in dstree from file %s",
t2 - t1, inDSTreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from DSTree_readFromFile(%p,%s)",
rc, dstree, inDSTreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading DSTree object from file %s",
inDSTreeFileName) ;
if ( msglvl > 2 ) {
DSTree_writeForHumanEye(dstree, msgFile) ;
} else {
DSTree_writeStats(dstree, msgFile) ;
}
fflush(msgFile) ;
/*
---------------------------
write out the DSTree object
---------------------------
*/
if ( strcmp(outDSTreeFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = DSTree_writeToFile(dstree, outDSTreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write dstree to file %s",
t2 - t1, outDSTreeFileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from DSTree_writeToFile(%p,%s)",
rc, dstree, outDSTreeFileName) ;
}
/*
----------------------
free the DSTree object
----------------------
*/
DSTree_free(dstree) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
DSTree/drivers/writeStagesIV.c 0100644 0002055 0007177 00000007010 06542223421 0017577 0 ustar 00cleve compmath 0000040 0000006 /* writeStagesIV.c */
#include "../DSTree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
--------------------------------------------------
read in a DSTree object, create a stagesIV object
and write it to a file.
created -- 97feb01, cca
--------------------------------------------------
*/
{
char *inDSTreeFileName, *outIVfileName, *type ;
double t1, t2 ;
int msglvl, rc ;
IV *stagesIV ;
DSTree *dstree ;
FILE *msgFile ;
if ( argc != 6 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile type outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.dstreef or *.dstreeb"
"\n type -- type of stages vector"
"\n outFile -- output file, must be *.ivf or *.ivb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inDSTreeFileName = argv[3] ;
type = argv[4] ;
outIVfileName = argv[5] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], inDSTreeFileName, outIVfileName) ;
fflush(msgFile) ;
/*
-------------------------
read in the DSTree object
-------------------------
*/
if ( strcmp(inDSTreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
dstree = DSTree_new() ;
MARKTIME(t1) ;
rc = DSTree_readFromFile(dstree, inDSTreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in dstree from file %s",
t2 - t1, inDSTreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from DSTree_readFromFile(%p,%s)",
rc, dstree, inDSTreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading DSTree object from file %s",
inDSTreeFileName) ;
if ( msglvl > 2 ) {
DSTree_writeForHumanEye(dstree, msgFile) ;
} else {
DSTree_writeStats(dstree, msgFile) ;
}
fflush(msgFile) ;
/*
---------------------
get the stages vector
---------------------
*/
if ( strcmp(type, "ND") == 0 ) {
stagesIV = DSTree_NDstages(dstree) ;
} else if ( strcmp(type, "ND2") == 0 ) {
stagesIV = DSTree_ND2stages(dstree) ;
} else if ( strcmp(type, "MS2") == 0 ) {
stagesIV = DSTree_MS2stages(dstree) ;
} else if ( strcmp(type, "MS3") == 0 ) {
stagesIV = DSTree_MS3stages(dstree) ;
} else {
stagesIV = NULL ;
}
/*
---------------------------
write out the DSTree object
---------------------------
*/
if ( stagesIV != NULL && strcmp(outIVfileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = IV_writeToFile(stagesIV, outIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write dstree to file %s",
t2 - t1, outIVfileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from IV_writeToFile(%p,%s)",
rc, stagesIV, outIVfileName) ;
}
}
/*
----------------------
free the DSTree object
----------------------
*/
DSTree_free(dstree) ;
if ( stagesIV != NULL ) {
IV_free(stagesIV) ;
}
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
eStagesIV.c */
#include "../DSTree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
--------------------------------------------------
read in a DSTree object, create a stagesIV object
and write it to a file.
created -- 97feb01, cca
--------------------------------------------------
*/
{
char *inDSTreeFileName, *outIVfileName, *type ;
double t1, t2 ;
int msglvl, rc ;
IV *sDSTree/drivers/cutoff.dvf 0100644 0002055 0007177 00000000116 06534106064 0016666 0 ustar 00cleve compmath 0000040 0000006 13
0.00
0.000625
0.00125
0.0025
0.005
0.01
0.02
0.04
0.08
0.16
0.32
0.64
1.00
DSTree/doc/ 0042755 0002055 0007177 00000000000 06542767331 0014006 5 ustar 00cleve compmath 0000040 0000006 DSTree/doc/dataStructure.tex 0100640 0002055 0007177 00000001423 06534106063 0017337 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:DSTree:dataStructure}
\par
The {\tt DSTree} object has a very simple data structure.
It contains a {\tt Tree} object to represent the tree fields
of the domains and separators, and an {\tt IV} object to hold the
map from the vertices to the domains and separators.
\begin{itemize}
\item {\tt Tree *tree} : pointer to the {\tt Tree} object
\item {\tt IV *mapIV} : pointer to the {\tt IV} object that holds
the map from vertices to domains and separators.
\end{itemize}
% \begin{center}
% \begin{tabular}{|l|l|}
% \hline
% {\tt tree} & pointer to the {\tt Tree} object \\
% {\tt mapIV} & pointer to the {\tt IV} object that holds \\
% & the map from vertices to domains and separators. \\
% \hline
% \end{tabular}
% \end{center}
DSTree/doc/intro.tex 0100640 0002055 0007177 00000003153 06534106063 0015642 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt DSTree}: \break A Domain/Separator Tree Object}
\label{chapter:DSTree:intro}
\par
The {\tt DSTree} object represents a recursive partition of a
graph, as is constructed during a nested dissection procedure.
The graph is split by a vertex {\it separator} into subgraphs,
and this process continues recursively up to some point.
A subgraph which is not split is a {\tt domain}.
The {\tt DSTree} object is normally created by the {\tt GPart}
graph partitioning object and then used to determine the
stages vector used as input to the {\tt MSMD} multistage minimum
degree object.
\par
The {\tt DSTree} object contains a {\tt Tree} object that stores
the natural tree links between separators and domains.
The top level separator has no parent.
Once a separator $S$ splits a graph, each subgraph is either split
again (in this case $S$ is the parent of the separator that splits the
subgraph) or $S$ is the parent of the subgraph (which is a
domain).
The {\tt DSTree} object also contains an {\tt IV} object that stores
a map from the vertices to the domains and separators.
\par
The {\tt DSTree} object is a natural output from a nested
dissection or other graph partitioning algorithm that uses vertex
separators.
Presently it has only one active function --- it creates a map from
the vertices to the {\it stages} needed as input for the
multi-stage minimum degree algorithm (see the {\tt MSMD} object).
Multisection orders the vertices in two stages: all vertices in the
domains first, then the vertices in the separators.
Nested dissection orders the vertices in as many stages as there
are levels in the {\tt DSTree} object.
DSTree/doc/main.tex 0100644 0002055 0007177 00000001076 06650656202 0015445 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt Tree} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt Tree} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
DSTree/doc/proto.tex 0100644 0002055 0007177 00000043037 06534106063 0015663 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt DSTree} methods}
\label{section:DSTree:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt DSTree} object.
\par
\subsection{Basic methods}
\label{subsection:DSTree:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
DSTree * DSTree_new ( void ) ;
\end{verbatim}
\index{DSTree_new@{\tt DSTree\_new()}}
This method allocates storage for an instance of
the {\tt DSTree} object.
The default fields are set by a call to
{\tt DSTree\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DSTree_setDefaultFields ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_setDefaultFields@{\tt DSTree\_setDefaultFields()}}
This method sets the data fields to default values:
{\tt tree} and {\tt mapIV} are set to {\tt NULL} ;
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DSTree_clearData ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_clearData@{\tt DSTree\_clearData()}}
This method clears the data fields, free'ing storage that has
been allocated by the object and free'ing objects that it owns.
This method checks to see whether {\tt dstree} is {\tt NULL}.
If {\tt tree} is not {\tt NULL}, then {\tt Tree\_free(tree)} is
called.
If {\tt mapIV} is not {\tt NULL}, then {\tt IV\_free(mapIV)} is
called.
Then the structure's default fields are set
via a call to {\tt DSTree\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DSTree_free ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_free@{\tt DSTree\_free()}}
This method checks to see whether {\tt dstree} is {\tt NULL}.
If so, an error message is printed and the program exits.
Otherwise, it releases any storage by a call to
{\tt DSTree\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Instance methods}
\label{subsection:DSTree:proto:instance}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Tree * DSTree_tree ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_tree@{\tt DSTree\_tree()}}
This method returns a pointer to its {\tt Tree} object.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * DSTree_mapIV ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_mapIV@{\tt DSTree\_mapIV()}}
This method returns a pointer to its {\tt IV} object
that maps vertices to domains and separators.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initializer methods}
\label{subsection:DSTree:proto:initializers}
\par
There are three initializers and two helper functions to set the
dimensions of the dstree, allocate the three vectors, and fill the
information.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DSTree_init1 ( DSTree *dstree, int ndomsep, int nvtx ) ;
\end{verbatim}
\index{DSTree_init1@{\tt DSTree\_init1()}}
This method initializes an object given the number of vertices,
(the dimension of {\tt mapIV})
and domains and separators (the number of nodes in {\tt tree}).
It then clears any previous data with a call to
{\tt DSTree\_clearData()}.
The {\tt tree} field is created and initialized via a call to {\tt
Tree\_init1()}.
The {\tt mapIV} field is created and initialized via a call to {\tt
IV\_init1()}.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
or {\tt ndomsep} or {\tt nvtx} are negative,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DSTree_init2 ( DSTree *dstree, Tree *tree, IV *mapIV) ;
\end{verbatim}
\index{DSTree_init2@{\tt DSTree\_init2()}}
Any previous data is cleared with a call to
{\tt DSTree\_clearData()}.
Then the {\tt tree} and {\tt mapIV} fields are set to the pointers
in the calling sequence.
\par \noindent {\it Error checking:}
If {\tt dstree}, {\tt tree} or {\tt mapIV} are {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Stage methods}
\label{subsection:DSTree:proto:stages}
\par
The only active function of a {\tt DSTree} object is to construct
the stages vector needed as input to the multi-stage
minimum degree {\tt MSMD} object.
Each domain and separator has a particular level associated with it.
A domain is a leaf of the domain/separator tree, and has level zero.
Each separator has a level that is one greater than the maximum
level of its children.
\par
%=======================================================================
\begin{enumerate}
\item
\begin{verbatim}
IV * DSTree_NDstages ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_NDstages@{\tt DSTree\_NDstages()}}
This method returns the stages for natural nested dissection.
The levels of the domains and separators are obtained via a call to
{\tt Tree\_setHeightImetric()}.
A {\tt stagesIV} {\tt IV} object is created of size
{\tt nvtx = mapIV->size}, filled and then returned.
The stage of a vertex is the level of the domain or separator which
contains the vertex.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
or if the object has not been initialized,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * DSTree_ND2stages ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_ND2stages@{\tt DSTree\_ND2stages()}}
This method returns the stages for a nested dissection variant,
separators on two adjacent levels are put into the same stage.
The levels of the domains and separators are obtained via a call to
{\tt Tree\_setHeightImetric()}.
A {\tt stagesIV} {\tt IV} object is created of size
{\tt nvtx = mapIV->size}, filled
and then returned.
If a vertex is found in a domain, its stage is zero.
If a vertex is found in a separator at level k, its stage is
$\lceil k/2 \rceil$.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
or if the object has not been initialized,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * DSTree_MS2stages ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_MS2stages@{\tt DSTree\_MS2stages()}}
This method returns the stages for the standard multisection
ordering.
The levels of the domains and separators are obtained via a call to
{\tt Tree\_setHeightImetric()}.
A {\tt stagesIV} {\tt IV} object is created of size
{\tt nvtx = mapIV->size}, filled
and then returned.
If a vertex is found in a domain, its stage is zero.
If a vertex is found in a separator, its stage is one.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
or if the object has not been initialized,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * DSTree_MS3stages ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_MS3stages@{\tt DSTree\_MS3stages()}}
This method returns the stages for a three-stage variant
of the multisection ordering.
The levels of the domains and separators are obtained via a call to
{\tt Tree\_setHeightImetric()}.
A {\tt stagesIV} {\tt IV} object is created of size
{\tt nvtx = mapIV->size}, filled
and then returned.
If a vertex is found in a domain, its stage is zero.
The levels of the separators are split into two sets, the lower
levels and the upper levels.
The stage of a vertex that is found in a separator is either
one (if the separator is in the lower levels)
or two (if the separator is in the upper levels).
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
or if the object has not been initialized,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * DSTree_stagesViaDomainWeight ( DSTree *dstree,
int *vwghts, DV *cutoffDV ) ;
\end{verbatim}
\index{DSTree_stagesViaDomainWeight@{\tt DSTree\_stagesViaDomainWeight()}}
This method sets the stages vector based on subtree (or domain) weights.
Each vertex is mapped to a node in the tree.
We generate the {\it subtree weights} for each subtree, the
fraction of the total vertex weight (based on {\tt vwghts[]})
that is contained in the subtree.
For each node in the tree, its fraction of the node weights lies
between two consectutive values in the {\tt cutoff[]} vector,
and that is the stage for all vertices contained in the node.
\par \noindent {\it Error checking:}
If {\tt dstree} or {\tt cutoffDV} is {\tt NULL},
or if the object has not been initialized,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\par
\subsection{Utility methods}
\label{subsection:DSTree:proto:utilities}
\par
There is one
utility method that returns the number of bytes taken by the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_sizeOf ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_sizeOf@{\tt DSTree\_sizeOf()}}
If {\tt dstree} is {\tt NULL},
an error message is printed and the program exits.
Otherwise, the number of bytes taken by this object is returned.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DSTree_renumberViaPostOT ( DSTree *dstree ) ;
\end{verbatim}
\index{DSTree_renumberViaPostOT@{\tt DSTree\_renumberViaPostOT()}}
This method renumbers the fronts in the tree via a post-order
traversal.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
or if the object has not been initialized,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_domainWeight ( DSTree *dstree, int vwghts[] ) ;
\end{verbatim}
\index{DSTree_domainWeight@{\tt DSTree\_domainWeight()}}
This method returns the weight of the vertices in the domains.
If {\tt vwghts} is {\tt NULL}, the vertices have unit weight.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_separatorWeight ( DSTree *dstree, int vwghts[] ) ;
\end{verbatim}
\index{DSTree_separatorWeight@{\tt DSTree\_separatorWeight()}}
This method returns the weight of the vertices in the separators.
If {\tt vwghts} is {\tt NULL}, the vertices have unit weight.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:DSTree:proto:IO}
\par
There are the usual eight IO routines.
The file structure of a dstree object is simple:
the structure for a {\tt Tree} object
followed by the structure for an {\tt IV} object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_readFromFile ( DSTree *dstree, char *fn ) ;
\end{verbatim}
\index{DSTree_readFromFile@{\tt DSTree\_readFromFile()}}
\par
This method reads a {\tt DSTree} object from a file.
It tries to open the file and if it is successful,
it then calls {\tt DSTree\_readFromFormattedFile()} or
{\tt DSTree\_readFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt dstree} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.dstreef} (for a formatted file)
or {\tt *.dstreeb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_readFromFormattedFile ( DSTree *dstree, FILE *fp ) ;
\end{verbatim}
\index{DSTree_readFromFormattedFile@{\tt DSTree\_readFromFormattedFile()}}
\par
This method reads in a {\tt DSTree} object from a formatted file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fscanf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt dstree} or {\tt fp} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_readFromBinaryFile ( DSTree *dstree, FILE *fp ) ;
\end{verbatim}
\index{DSTree_readFromBinaryFile@{\tt DSTree\_readFromBinaryFile()}}
\par
This method reads in a {\tt DSTree} object from a binary file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fread}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt dstree} or {\tt fp} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_writeToFile ( DSTree *dstree, char *fn ) ;
\end{verbatim}
\index{DSTree_writeToFile@{\tt DSTree\_writeToFile()}}
\par
This method writes a {\tt DSTree} object to a file.
It tries to open the file and if it is successful,
it then calls {\tt DSTree\_writeFromFormattedFile()} or
{\tt DSTree\_writeFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt dstree} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.dstreef} (for a formatted file)
or {\tt *.dstreeb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_writeToFormattedFile ( DSTree *dstree, FILE *fp ) ;
\end{verbatim}
\index{DSTree_writeToFormattedFile@{\tt DSTree\_writeToFormattedFile()}}
\par
This method writes a {\tt DSTree} object to a formatted file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fprintf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt dstree} or {\tt fp} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_writeToBinaryFile ( DSTree *dstree, FILE *fp ) ;
\end{verbatim}
\index{DSTree_writeToBinaryFile@{\tt DSTree\_writeToBinaryFile()}}
\par
This method writes a {\tt DSTree} object to a binary file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fwrite}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt dstree} or {\tt fp} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_writeForHumanEye ( DSTree *dstree, FILE *fp ) ;
\end{verbatim}
\index{DSTree_writeForHumanEye@{\tt DSTree\_writeForHumanEye()}}
\par
This method writes a {\tt DSTree} object to a file in a human
readable format.
The method {\tt DSTree\_writeStats()} is called to write out the
header and statistics.
Then the tree structure is printed via a call to
{\tt Tree\_writeForHumanEye}, followed by the map structure via a
call to
{\tt IV\_writeForHumanEye}.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt dstree} or {\tt fp} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DSTree_writeStats ( DSTree *dstree, FILE *fp ) ;
\end{verbatim}
\index{DSTree_writeStats@{\tt DSTree\_writeStats()}}
\par
This method write the header and statistics to a file.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt dstree} or {\tt fp} is {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
\tt DSTree\_MS2stages()}}
This method returns the stages for the standard multisection
ordering.
The levels of the domains and separators are obtained via a call to
{\tt Tree\_setHeightImetric()}.
A {\tt stagesIV} {\tt IV} object is created of size
{\tt nvtx = mapIV->size}, filled
and then returned.
If a vertex is found in a domain, its stage is zero.
If a vertex is found in a separator, its stage is one.
\par \noindent {\it Error checking:}
If {\tt dstree} is {\tt NULL},
orDSTree/doc/main.log 0100644 0002055 0007177 00000003746 06535771670 0015445 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 5 JUN 1998 06:33
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
)
\@indexfile=\write3
Writing index file main.idx
(main.aux) (intro.tex
Chapter 1.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 1.
) (dataStructure.tex) (proto.tex [1
] [2] [3] [4] [5]) (drivers.tex [6]
Overfull \hbox (42.63402pt too wide) in paragraph at lines 64--69
\elvtt *.dstreef \elvrm or \elvtt *.dstreeb\elvrm . The \elvtt DSTree \elvrm ob
-ject is read from the file via the \elvtt DSTree[]readFromFile()
\hbox(7.60416+2.12917)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt d
.\elvtt s
.\elvtt t
.etc.
Overfull \hbox (19.63927pt too wide) in paragraph at lines 114--119
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
) (main.ind [7] [8
]) (main.aux) )
Here is how much of TeX's memory you used:
211 strings out of 11977
2251 string characters out of 87269
33543 words of memory out of 262141
2145 multiletter control sequences out of 9500
19780 words of font info for 75 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
13i,5n,17p,188b,257s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (8 pages, 25216 bytes).
DSTree/doc/main.aux 0100644 0002055 0007177 00000003457 06535771670 0015460 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}{\string\ptt\space DSTree}: \penalty -\@M A Domain/Separator Tree Object}{1}}
\@writefile{lof}{\string\addvspace\space {10\p@ }}
\@writefile{lot}{\string\addvspace\space {10\p@ }}
\newlabel{chapter:DSTree:intro}{{1}{1}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Data Structure}{1}}
\newlabel{section:DSTree:dataStructure}{{1.1}{1}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Prototypes and descriptions of {\string\ptt\space DSTree} methods}{2}}
\newlabel{section:DSTree:proto}{{1.2}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.1}Basic methods}{2}}
\newlabel{subsection:DSTree:proto:basics}{{1.2.1}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Instance methods}{2}}
\newlabel{subsection:DSTree:proto:instance}{{1.2.2}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.3}Initializer methods}{3}}
\newlabel{subsection:DSTree:proto:initializers}{{1.2.3}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.4}Stage methods}{3}}
\newlabel{subsection:DSTree:proto:stages}{{1.2.4}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.5}Utility methods}{4}}
\newlabel{subsection:DSTree:proto:utilities}{{1.2.5}{4}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.6}IO methods}{5}}
\newlabel{subsection:DSTree:proto:IO}{{1.2.6}{5}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}Driver programs for the {\string\ptt\space DSTree} object}{6}}
\newlabel{section:DSTree:drivers}{{1.3}{6}}
.1}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Instance methods}{2}}
\newlabel{subsection:DSTree:proto:instance}{{1.2.2}{2}}
\@writefile{toc}{\string\contentslDSTree/doc/main.ind 0100644 0002055 0007177 00000001770 06535771666 0015436 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt DSTree\_clearData()}, 2
\item {\tt DSTree\_domainWeight()}, 5
\item {\tt DSTree\_free()}, 2
\item {\tt DSTree\_init1()}, 3
\item {\tt DSTree\_init2()}, 3
\item {\tt DSTree\_mapIV()}, 2
\item {\tt DSTree\_MS2stages()}, 4
\item {\tt DSTree\_MS3stages()}, 4
\item {\tt DSTree\_ND2stages()}, 3
\item {\tt DSTree\_NDstages()}, 3
\item {\tt DSTree\_new()}, 2
\item {\tt DSTree\_readFromBinaryFile()}, 5
\item {\tt DSTree\_readFromFile()}, 5
\item {\tt DSTree\_readFromFormattedFile()}, 5
\item {\tt DSTree\_renumberViaPostOT()}, 4
\item {\tt DSTree\_separatorWeight()}, 5
\item {\tt DSTree\_setDefaultFields()}, 2
\item {\tt DSTree\_sizeOf()}, 4
\item {\tt DSTree\_stagesViaDomainWeight()}, 4
\item {\tt DSTree\_tree()}, 2
\item {\tt DSTree\_writeForHumanEye()}, 6
\item {\tt DSTree\_writeStats()}, 6
\item {\tt DSTree\_writeToBinaryFile()}, 6
\item {\tt DSTree\_writeToFile()}, 5
\item {\tt DSTree\_writeToFormattedFile()}, 6
\end{theindex}
DSTree/doc/main.idx 0100644 0002055 0007177 00000003065 06535771670 0015442 0 ustar 00cleve compmath 0000040 0000006 \indexentry{DSTree_new@{\tt DSTree\_new()}}{2}
\indexentry{DSTree_setDefaultFields@{\tt DSTree\_setDefaultFields()}}{2}
\indexentry{DSTree_clearData@{\tt DSTree\_clearData()}}{2}
\indexentry{DSTree_free@{\tt DSTree\_free()}}{2}
\indexentry{DSTree_tree@{\tt DSTree\_tree()}}{2}
\indexentry{DSTree_mapIV@{\tt DSTree\_mapIV()}}{2}
\indexentry{DSTree_init1@{\tt DSTree\_init1()}}{3}
\indexentry{DSTree_init2@{\tt DSTree\_init2()}}{3}
\indexentry{DSTree_NDstages@{\tt DSTree\_NDstages()}}{3}
\indexentry{DSTree_ND2stages@{\tt DSTree\_ND2stages()}}{3}
\indexentry{DSTree_MS2stages@{\tt DSTree\_MS2stages()}}{4}
\indexentry{DSTree_MS3stages@{\tt DSTree\_MS3stages()}}{4}
\indexentry{DSTree_stagesViaDomainWeight@{\tt DSTree\_stagesViaDomainWeight()}}{4}
\indexentry{DSTree_sizeOf@{\tt DSTree\_sizeOf()}}{4}
\indexentry{DSTree_renumberViaPostOT@{\tt DSTree\_renumberViaPostOT()}}{4}
\indexentry{DSTree_domainWeight@{\tt DSTree\_domainWeight()}}{5}
\indexentry{DSTree_separatorWeight@{\tt DSTree\_separatorWeight()}}{5}
\indexentry{DSTree_readFromFile@{\tt DSTree\_readFromFile()}}{5}
\indexentry{DSTree_readFromFormattedFile@{\tt DSTree\_readFromFormattedFile()}}{5}
\indexentry{DSTree_readFromBinaryFile@{\tt DSTree\_readFromBinaryFile()}}{5}
\indexentry{DSTree_writeToFile@{\tt DSTree\_writeToFile()}}{5}
\indexentry{DSTree_writeToFormattedFile@{\tt DSTree\_writeToFormattedFile()}}{6}
\indexentry{DSTree_writeToBinaryFile@{\tt DSTree\_writeToBinaryFile()}}{6}
\indexentry{DSTree_writeForHumanEye@{\tt DSTree\_writeForHumanEye()}}{6}
\indexentry{DSTree_writeStats@{\tt DSTree\_writeStats()}}{6}
DSTree/doc/main.ilg 0100644 0002055 0007177 00000000457 06535771666 0015440 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (25 entries accepted, 0 rejected).
Sorting entries....done (118 comparisons).
Generating output file main.ind....done (29 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
DSTree/doc/drivers.tex 0100644 0002055 0007177 00000012251 06534106063 0016170 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt DSTree} object}
\label{section:DSTree:drivers}
\par
This section contains brief descriptions of the driver programs.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testIO msglvl msgFile inFile outFile
\end{verbatim}
This driver program reads and write {\tt DSTree} files, useful for
converting formatted files to binary files and vice versa.
One can also read in a {\tt DSTree} file and print out just the
header information (see the {\tt DSTree\_writeStats()} method).
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt DSTree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inFile} parameter is the input file for the {\tt DSTree}
object. It must be of the form {\tt *.dinpmtxf} or {\tt *.dinpmtxb}.
The {\tt DSTree} object is read from the file via the
{\tt DSTree\_readFromFile()} method.
\item
The {\tt outFile} parameter is the output file for the {\tt DSTree}
object.
If {\tt outFile} is {\tt none} then the {\tt DSTree} object is not
written to a file.
Otherwise, the {\tt DSTree\_writeToFile()} method is called to write
the object to
a formatted file (if {\tt outFile} is of the form {\tt *.dinpmtxf}),
or
a binary file (if {\tt outFile} is of the form {\tt *.dinpmtxb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
writeStagesIV msglvl msgFile inFile type outFile
\end{verbatim}
This driver program reads in a {\tt DSTree} from a file,
creates a stages {\tt IV} object and writes it to a file.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt DSTree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inFile} parameter is the input file for the {\tt DSTree}
object. It must be of the form {\tt *.dstreef} or {\tt *.dstreeb}.
The {\tt DSTree} object is read from the file via the
{\tt DSTree\_readFromFile()} method.
\item
The {\tt type} parameter specifies which type of stages vector to
create. There are presently four supported types :
{\tt ND}, {\tt ND2}, {\tt MS2} and {\tt ND3}.
See the stage methods
in Section~\ref{subsection:DSTree:proto:stages}.
\item
The {\tt outFile} parameter is the output file for the stages {\tt IV}
object.
If {\tt outFile} is {\tt none} then the {\tt IV} object is not
written to a file.
Otherwise, the {\tt IV\_writeToFile()} method is called to write
the object to
a formatted file (if {\tt outFile} is of the form {\tt *.ivf}),
or
a binary file (if {\tt outFile} is of the form {\tt *.ivb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testDomWeightStages msglvl msgFile
inDSTreeFile inGraphFile inCutoffDVfile outFile
\end{verbatim}
This driver program is used to create a stages vector based on
subtree weight.
It reads in three objects from files:
a {\tt DSTree} object, a {\tt Graph} object and a {\tt DV} object
that contains the cutoff vector,
then creates a stages {\tt IV} object and writes it to a file.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt DSTree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inDSTreeFile} parameter is the input file for the {\tt DSTree}
object. It must be of the form {\tt *.dstreef} or {\tt *.dstreeb}.
The {\tt DSTree} object is read from the file via the
{\tt DSTree\_readFromFile()} method.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt inCutoffDVfile} parameter is the input file for the cutoff
{\tt DV} object.
It must be of the form {\tt *.dvf} or {\tt *.dvb}.
The {\tt DV} object is read from the file via the
{\tt DV\_readFromFile()} method.
\item
The {\tt outFile} parameter is the output file for the stages {\tt IV}
object.
If {\tt outFile} is {\tt none} then the {\tt IV} object is not
written to a file.
Otherwise, the {\tt IV\_writeToFile()} method is called to write
the object to
a formatted file (if {\tt outFile} is of the form {\tt *.ivf}),
or
a binary file (if {\tt outFile} is of the form {\tt *.ivb}).
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
------------------------------------------------------------
\item
\begin{verbatim}
writeStagesIV msglvl msgFile inFile type outFile
\end{verbatim}
This driver program reads in a {\tt DSTree} from a file,
creates a stages {\tt IV} object and writes it to a file.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of oDSTree/doc/makefile 0100644 0002055 0007177 00000000027 06542767331 0015500 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
DV.h 0100644 0002055 0007177 00000000064 06534106366 0012564 0 ustar 00cleve compmath 0000040 0000006 #ifndef _DV_
#define _DV_
#include "DV/DV.h"
#endif
DV/DV.h 0100644 0002055 0007177 00000032400 06535051720 0013066 0 ustar 00cleve compmath 0000040 0000006 /* DV.h */
#include "../cfiles.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
DV -- double vector object
size -- size of the vector
maxsize -- maximum size of the vector
owned -- owner flag
when == 1, storage pointed to by entries
has been allocated here and can be free'd.
when == 0, storage pointed to by entries
has not been allocated here and cannot be free'd.
vec -- pointer to base address
---------------------------------------------------------
*/
typedef struct _DV DV ;
struct _DV {
int size ;
int maxsize ;
int owned ;
double *vec ;
} ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
constructor method
created -- 96jun23, cca
-----------------------
*/
DV *
DV_new (
void
) ;
/*
-----------------------
set the default fields
created -- 96jun23, cca
-----------------------
*/
void
DV_setDefaultFields (
DV *dv
) ;
/*
-----------------------
clear the data fields
created -- 96jun23, cca
-----------------------
*/
void
DV_clearData (
DV *dv
) ;
/*
-----------------------
destructor
created -- 96jun23, cca
-----------------------
*/
void
DV_free (
DV *dv
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------
simplest initialization method
if entries != NULL
the object does not own the entries,
it just points to the entries base address
else if size > 0
the object will own the entries,
it allocates a vector of size int's.
else
nothing happens
endif
created -- 96aug28, cca
---------------------------------------------
*/
void
DV_init (
DV *iv,
int size,
double *entries
) ;
/*
-------------------------
basic initializion method
created -- 96jun23, cca
-------------------------
*/
void
DV_init1 (
DV *dv,
int Maxsize
) ;
/*
-------------------------
total initializion method
created -- 96jun23, cca
-------------------------
*/
void
DV_init2 (
DV *dv,
int Size,
int Maxsize,
int owned,
double *Dvec
) ;
/*
----------------------------------
set the maximum size of the vector
created -- 96dec08, cca
----------------------------------
*/
void
DV_setMaxsize (
DV *dv,
int newmaxsize
) ;
/*
--------------------------
set the size of the vector
created -- 96dec08, cca
--------------------------
*/
void
DV_setSize (
DV *dv,
int newsize
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in instance.c --------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------
return 1 if the entries are owned by the object
return 0 otherwise
created -- 96jun22, cca
-----------------------------------------------
*/
int
DV_owned (
DV *dv
) ;
/*
-----------------------
return the vector size
created -- 95oct06, cca
-----------------------
*/
int
DV_maxsize (
DV *dv
) ;
/*
-----------------------
return the vector size
created -- 95oct06, cca
-----------------------
*/
int
DV_size (
DV *dv
) ;
/*
-------------------------------------------------
return the loc'th entry of a vector.
note: if loc is out of range then 0.0 is returned
created -- 96jun29, cca
-------------------------------------------------
*/
double
DV_entry (
DV *dv,
int loc
) ;
/*
----------------------------------------------
return a pointer to the object's entries array
created -- 95oct06, cca
----------------------------------------------
*/
double *
DV_entries (
DV *dv
) ;
/*
--------------------------------------------
fill *psize with the vector's size
and *pentries with the address of the vector
created -- 95oct06, cca
--------------------------------------------
*/
void
DV_sizeAndEntries (
DV *dv,
int *psize,
double **pentries
) ;
/*
---------------------------
set and entry in the vector
created -- 96jul14, cca
---------------------------
*/
void
DV_setEntry (
DV *dv,
int loc,
double value
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in util.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------
shift the base of the entries and adjust the dimensions
note: this is a dangerous operation because the dv->vec
does not point to the base of the entries any longer,
and thus if the object owns its entries and it is called
to resize them or to free them, malloc and free will choke.
USE WITH CAUTION!
created -- 96aug25, cca
modified -- 96aug28, cca
structure changed
-----------------------------------------------------------
*/
void
DV_shiftBase (
DV *dv,
int offset
) ;
/*
-----------------------
resize the vector
created -- 96jun22, cca
-----------------------
*/
void
DV_resize (
DV *dv,
int Maxsize
) ;
/*
-----------------------
set the size to be zero
created -- 96jun23, cca
-----------------------
*/
void
DV_clear (
DV *dv
) ;
/*
---------------------------
push an entry onto the list
created -- 96jun23, cca
---------------------------
*/
void
DV_push (
DV *dv,
double val
) ;
/*
------------------------------------
minimum and maximum entries and sum
created -- 96jun23, cca
------------------------------------
*/
double
DV_min (
DV *dv
) ;
double
DV_max (
DV *dv
) ;
double
DV_sum (
DV *dv
) ;
/*
-------------------------------------------------------
sort each index list into ascending or descending order
created -- 96jun23, cca
-------------------------------------------------------
*/
void
DV_sortUp (
DV *dv
) ;
void
DV_sortDown (
DV *dv
) ;
/*
-----------------------
ramp the entries
created -- 96jun23, cca
-----------------------
*/
void
DV_ramp (
DV *dv,
double base,
double incr
) ;
/*
-----------------------
shuffle the list
created -- 96jun23, cca
-----------------------
*/
void
DV_shuffle (
DV *dv,
int seed
) ;
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 96jun23, cca
----------------------------------------------
*/
int
DV_sizeOf (
DV *dv
) ;
/*
--------------------------------------------
iterator :
return the pointer to the head of the vector
created -- 96jun23, cca
--------------------------------------------
*/
double *
DV_first (
DV *dv
) ;
/*
-----------------------------------------------------
iterator :
return the pointer to the next location in the vector
created -- 96jun23, cca
-----------------------------------------------------
*/
double *
DV_next (
DV *dv,
double *pi
) ;
/*
--------------------------
fill a vector with a value
created -- 96jun22, cca
--------------------------
*/
void
DV_fill (
DV *dv,
double value
) ;
/*
--------------------------
fill a vector with zeros
created -- 98jun02, cca
--------------------------
*/
void
DV_zero (
DV *dv
) ;
/*
--------------------------------------
copy entries from dv2 into dv1.
note: this is a "mapped" copy,
dv1 and dv2 need not be the same size.
created -- 96aug31, cca
--------------------------------------
*/
void
DV_copy (
DV *dv1,
DV *dv2
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in profile.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------------
to fill xDV and yDV with a log10 profile of the magnitudes of
the entries in the DV object. tausmall and tau big provide
cutoffs within which to examine the entries. pnzero, pnsmall
and pnbig are addresses to hold the number of entries zero,
smaller than tausmall and larger than taubig, respectively.
created -- 97feb14, cca
------------------------------------------------------------------
*/
void
DV_log10profile (
DV *dv,
int npts,
DV *xDV,
DV *yDV,
double tausmall,
double taubig,
int *pnzero,
int *pnsmall,
int *pnbig
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in IO.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------
purpose -- to read in an DV object from a file
input --
fn -- filename, must be *.dvb or *.dvf
return value -- 1 if success, 0 if failure
created -- 96jun23, cca
----------------------------------------------
*/
int
DV_readFromFile (
DV *dv,
char *fn
) ;
/*
-----------------------------------------------------
purpose -- to read an DV object from a formatted file
return value -- 1 if success, 0 if failure
created -- 96jun23, cca
-----------------------------------------------------
*/
int
DV_readFromFormattedFile (
DV *dv,
FILE *fp
) ;
/*
---------------------------------------------------
purpose -- to read an DV object from a binary file
return value -- 1 if success, 0 if failure
created -- 96jun23, cca
---------------------------------------------------
*/
int
DV_readFromBinaryFile (
DV *dv,
FILE *fp
) ;
/*
-------------------------------------------
purpose -- to write an DV object to a file
input --
fn -- filename
*.dvb -- binary
*.dvf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 96jun23, cca
-------------------------------------------
*/
int
DV_writeToFile (
DV *dv,
char *fn
) ;
/*
-----------------------------------------------------
purpose -- to write an DV object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 96jun23, cca
-----------------------------------------------------
*/
int
DV_writeToFormattedFile (
DV *dv,
FILE *fp
) ;
/*
--------------------------------------------------
purpose -- to write an DV object to a binary file
return value -- 1 if success, 0 otherwise
created -- 96jun23, cca
--------------------------------------------------
*/
int
DV_writeToBinaryFile (
DV *dv,
FILE *fp
) ;
/*
-------------------------------------------------
purpose -- to write an DV object for a human eye
return value -- 1 if success, 0 otherwise
created -- 96jun23, cca
-------------------------------------------------
*/
int
DV_writeForHumanEye (
DV *dv,
FILE *fp
) ;
/*
---------------------------------------------------------
purpose -- to write out the statistics for the DV object
return value -- 1 if success, 0 otherwise
created -- 96jun23, cca
---------------------------------------------------------
*/
int
DV_writeStats (
DV *dv,
FILE *fp
) ;
/*
-------------------------------------------------------------------
purpose -- to write out an integer vector with eighty column lines
input --
fp -- file pointer, must be formatted and write access
column -- present column
pierr -- pointer to int to hold return value,
should be 1 if any print was successful,
if fprintf() failed, then ierr = -1
return value -- present column
created -- 96jun22, cca
-------------------------------------------------------------------
*/
int
DV_fp80 (
DV *dv,
FILE *fp,
int column,
int *pierr
) ;
/*
---------------------------------------------------
purpose -- to write the DV object for a matlab file
return value -- 1 if success, 0 otherwise
created -- 98feb07, cca
---------------------------------------------------
*/
int
DV_writeForMatlab (
DV *dv,
char *name,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
DV/makefile 0100644 0002055 0007177 00000000223 06636223557 0014115 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd drivers ; make clean
cd src ; make clean
cd doc ; make clean
DV/src/makefile 0100644 0002055 0007177 00000000760 06636022220 0014672 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = DV
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(init.o) \
$(OBJ).a(instance.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(profile.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
DV/src/makeGlobalLib 0100644 0002055 0007177 00000000635 06600260770 0015610 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = DV
SRC = basics.c \
init.c \
instance.c \
IO.c \
profile.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
DV/src/IO.c 0100644 0002055 0007177 00000027335 06613655714 0013673 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../DV.h"
static const char *suffixb = ".dvb" ;
static const char *suffixf = ".dvf" ;
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
purpose -- to read in an DV object from a file
input --
fn -- filename, must be *.dvb or *.dvf
return value -- 1 if success, 0 if failure
created -- 96jun23, cca
----------------------------------------------
*/
int
DV_readFromFile (
DV *dv,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( dv == NULL || fn == NULL ) {
fprintf(stderr,
"\n error in DV_readFromFile(%p,%s), file %s, line %d"
"\n bad input\n", dv, fn, __FILE__, __LINE__) ;
return(0) ;
}
/*
-------------
read the file
-------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "rb")) == NULL ) {
fprintf(stderr, "\n error in DV_readFromFile(%p,%s)"
"\n unable to open file %s", dv, fn, fn) ;
rc = 0 ;
} else {
rc = DV_readFromBinaryFile(dv, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "r")) == NULL ) {
fprintf(stderr, "\n error in DV_readFromFile(%p,%s)"
"\n unable to open file %s", dv, fn, fn) ;
rc = 0 ;
} else {
rc = DV_readFromFormattedFile(dv, fp) ;
fclose(fp) ;
}
} else {
fprintf(stderr, "\n error in DV_readFromFile(%p,%s)"
"\n bad DV file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
dv, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
} else {
fprintf(stderr, "\n error in DV_readFromFile(%p,%s)"
"\n bad DV file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
dv, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
purpose -- to read an DV object from a formatted file
return value -- 1 if success, 0 if failure
created -- 96jun23, cca
-----------------------------------------------------
*/
int
DV_readFromFormattedFile (
DV *dv,
FILE *fp
) {
int rc, size ;
/*
---------------
check the input
---------------
*/
if ( dv == NULL || fp == NULL ) {
fprintf(stderr, "\n error in DV_readFromFormattedFile(%p,%p)"
"\n bad input\n", dv, fp) ;
return(0) ;
}
DV_clearData(dv) ;
/*
------------------------------
read in the size of the vector
------------------------------
*/
if ( (rc = fscanf(fp, "%d", &size)) != 1 ) {
fprintf(stderr, "\n error in DV_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", dv, fp, rc, 1) ;
return(0) ;
}
/*
---------------------
initialize the object
---------------------
*/
DV_init(dv, size, NULL) ;
/*
------------------------
read in the vec[] vector
------------------------
*/
if ( (rc = DVfscanf(fp, size, DV_entries(dv))) != size ) {
fprintf(stderr, "\n error in DV_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", dv, fp, rc, size) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
purpose -- to read an DV object from a binary file
return value -- 1 if success, 0 if failure
created -- 96jun23, cca
---------------------------------------------------
*/
int
DV_readFromBinaryFile (
DV *dv,
FILE *fp
) {
int rc, size ;
/*
---------------
check the input
---------------
*/
if ( dv == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in DV_readFromBinaryFile(%p,%p)"
"\n bad input\n", dv, fp) ;
return(0) ;
}
DV_clearData(dv) ;
/*
------------------------------
read in the size of the vector
------------------------------
*/
if ( (rc = fread((void *) &size, sizeof(int), 1, fp)) != 1 ) {
fprintf(stderr, "\n error in DV_readFromBinaryFile(%p,%p)"
"\n itemp(3) : %d items of %d read\n", dv, fp, rc, 1) ;
return(0) ;
}
/*
---------------------
initialize the object
---------------------
*/
DV_init(dv, size, NULL) ;
/*
------------------------
read in the vec[] vector
------------------------
*/
if ( (rc = fread((void *) DV_entries(dv), sizeof(double), size, fp))
!= size ) {
fprintf(stderr, "\n error in DV_readFromBinaryFile(%p,%p)"
"\n sizes(%d) : %d items of %d read\n",
dv, fp, size, rc, size) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------
purpose -- to write an DV object to a file
input --
fn -- filename
*.dvb -- binary
*.dvf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 96jun23, cca
-------------------------------------------
*/
int
DV_writeToFile (
DV *dv,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( dv == NULL || fn == NULL ) {
fprintf(stderr, "\n fatal error in DV_writeToFile(%p,%s)"
"\n bad input\n", dv, fn) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in DV_writeToFile(%p,%s)"
"\n unable to open file %s", dv, fn, fn) ;
rc = 0 ;
} else {
rc = DV_writeToBinaryFile(dv, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "w")) == NULL ) {
fprintf(stderr, "\n error in DV_writeToFile(%p,%s)"
"\n unable to open file %s", dv, fn, fn) ;
rc = 0 ;
} else {
rc = DV_writeToFormattedFile(dv, fp) ;
fclose(fp) ;
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in DV_writeToFile(%p,%s)"
"\n unable to open file %s", dv, fn, fn) ;
rc = 0 ;
} else {
rc = DV_writeForHumanEye(dv, fp) ;
fclose(fp) ;
}
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in DV_writeToFile(%p,%s)"
"\n unable to open file %s", dv, fn, fn) ;
rc = 0 ;
} else {
rc = DV_writeForHumanEye(dv, fp) ;
fclose(fp) ;
}
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
purpose -- to write an DV object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 96jun23, cca
-----------------------------------------------------
*/
int
DV_writeToFormattedFile (
DV *dv,
FILE *fp
) {
int rc, size ;
/*
---------------
check the input
---------------
*/
if ( dv == NULL || fp == NULL || dv->size <= 0 ) {
fprintf(stderr, "\n fatal error in DV_writeToFormattedFile(%p,%p)"
"\n bad input\n", dv, fp) ;
fprintf(stderr, "\n dv->size = %d", dv->size) ;
exit(-1) ;
}
/*
-------------------------------------
write out the size of the vector
-------------------------------------
*/
size = DV_size(dv) ;
rc = fprintf(fp, "\n %d", size) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in DV_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from first fprintf\n", dv, fp, rc) ;
return(0) ;
}
if ( size > 0 ) {
DVfprintf(fp, size, DV_entries(dv)) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
purpose -- to write an DV object to a binary file
return value -- 1 if success, 0 otherwise
created -- 96jun23, cca
--------------------------------------------------
*/
int
DV_writeToBinaryFile (
DV *dv,
FILE *fp
) {
int rc, size ;
/*
---------------
check the input
---------------
*/
if ( dv == NULL || fp == NULL || dv->size <= 0 ) {
fprintf(stderr, "\n fatal error in DV_writeToBinaryFile(%p,%p)"
"\n bad input\n", dv, fp) ;
exit(-1) ;
}
size = DV_size(dv) ;
rc = fwrite((void *) &size, sizeof(int), 1, fp) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in DV_writeToBinaryFile(%p,%p)"
"\n %d of %d scalar items written\n", dv, fp, rc, 1) ;
return(0) ;
}
rc = fwrite((void *) DV_entries(dv), sizeof(double), size, fp) ;
if ( rc != size ) {
fprintf(stderr, "\n error in DV_writeToBinaryFile(%p,%p)"
"\n %d of %d items written\n",
dv, fp, rc, size) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to write an DV object for a human eye
return value -- 1 if success, 0 otherwise
created -- 96jun23, cca
-------------------------------------------------
*/
int
DV_writeForHumanEye (
DV *dv,
FILE *fp
) {
int rc ;
if ( dv == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in DV_writeForHumanEye(%p,%p)"
"\n bad input\n", dv, fp) ;
exit(-1) ;
}
if ( (rc = DV_writeStats(dv, fp)) == 0 ) {
fprintf(stderr, "\n fatal error in DV_writeForHumanEye(%p,%p)"
"\n rc = %d, return from DV_writeStats(%p,%p)\n",
dv, fp, rc, dv, fp) ;
return(0) ;
}
DVfprintf(fp, DV_size(dv), DV_entries(dv)) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
purpose -- to write out the statistics for the DV object
return value -- 1 if success, 0 otherwise
created -- 96jun23, cca
---------------------------------------------------------
*/
int
DV_writeStats (
DV *dv,
FILE *fp
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( dv == NULL || fp == NULL ) {
fprintf(stderr, "\n error in DV_writeStats(%p,%p)"
"\n bad input\n", dv, fp) ;
exit(-1) ;
}
rc = fprintf(fp, "\n DV : double vector object : ") ;
if ( rc < 0 ) { goto IO_error ; }
rc = fprintf(fp,
" size = %d, maxsize = %d, owned = %d",
dv->size, dv->maxsize, dv->owned) ;
if ( rc < 0 ) { goto IO_error ; }
return(1) ;
IO_error :
fprintf(stderr, "\n fatal error in DV_writeStats(%p,%p)"
"\n rc = %d, return from fprintf\n", dv, fp, rc) ;
return(0) ;
}
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
purpose -- to write the DV object for a matlab file
return value -- 1 if success, 0 otherwise
created -- 98feb07, cca
---------------------------------------------------
*/
int
DV_writeForMatlab (
DV *dv,
char *name,
FILE *fp
) {
double *entries ;
int ii, rc, size ;
/*
---------------
check the input
---------------
*/
if ( dv == NULL || fp == NULL ) {
fprintf(stderr, "\n error in DV_writeForMatlab(%p,%p,%p)"
"\n bad input\n", dv, name, fp) ;
exit(-1) ;
}
DV_sizeAndEntries(dv, &size, &entries) ;
fprintf(fp, "\n %s = zeros(%d,%d) ;", name, size, size) ;
for ( ii = 0 ; ii < size ; ii++ ) {
fprintf(fp, "\n %s(%d) = %24.16e ;", name, ii+1, entries[ii]) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
fprintf(stderr, "\n error in DV_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", dv, fp, rc, size) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
DV/src/basics.c 0100644 0002055 0007177 00000003240 06534105757 0014614 0 ustar 00cleve compmath 0000040 0000006 /* basics.C */
#include "../DV.h"
/*--------------------------------------------------------------------*/
/*
-----------------------
constructor method
created -- 95oct06, cca
-----------------------
*/
DV *
DV_new (
void
) {
DV *dv ;
ALLOCATE(dv, struct _DV, 1) ;
DV_setDefaultFields(dv) ;
return(dv) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 95oct06, cca
-----------------------
*/
void
DV_setDefaultFields (
DV *dv
) {
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_setDefaultFields(%p)"
"\n bad input\n", dv) ;
exit(-1) ;
}
dv->size = 0 ;
dv->maxsize = 0 ;
dv->owned = 0 ;
dv->vec = NULL ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
clear the data fields
created -- 95oct06, cca
-----------------------
*/
void
DV_clearData (
DV *dv
) {
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_clearData(%p)"
"\n bad input\n", dv) ;
exit(-1) ;
}
if ( dv->vec != NULL && dv->owned == 1 ) {
DVfree(dv->vec) ;
}
DV_setDefaultFields(dv) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
destructor
created -- 95oct06, cca
-----------------------
*/
void
DV_free (
DV *dv
) {
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_free(%p)"
"\n bad input\n", dv) ;
exit(-1) ;
}
DV_clearData(dv) ;
FREE(dv) ;
return ; }
/*--------------------------------------------------------------------*/
DV/src/init.c 0100644 0002055 0007177 00000014176 06534105757 0014325 0 ustar 00cleve compmath 0000040 0000006 /* init.C */
#include "../DV.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
simplest initialization method
if entries != NULL
the object does not own the entries,
it just points to the entries base address
else if size > 0
the object will own the entries,
it allocates a vector of size doubles's.
else
nothing happens
endif
created -- 96aug28, cca
---------------------------------------------
*/
void
DV_init (
DV *dv,
int size,
double *entries
) {
if ( dv == NULL || size < 0 ) {
fprintf(stderr, "\n fatal error in DV_init(%p,%d,%p)"
"\n bad input\n", dv, size, entries) ;
exit(-1) ;
}
/*
--------------
clear any data
--------------
*/
DV_clearData(dv) ;
/*
-----------------------------
set the size and maximum size
-----------------------------
*/
dv->maxsize = dv->size = size ;
/*
-------------------------
set vector and owner flag
-------------------------
*/
if ( entries != NULL ) {
dv->owned = 0 ;
dv->vec = entries ;
} else if ( size > 0 ) {
dv->owned = 1 ;
/*
dv->vec = DVinit(size, 0.0) ;
*/
dv->vec = DVinit2(size) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------
basic initializion method
created -- 95oct06, cca
-------------------------
*/
void
DV_init1 (
DV *dv,
int size
) {
DV_init(dv, size, NULL) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------
total initializion method
created -- 95oct06, cca
-------------------------
*/
void
DV_init2 (
DV *dv,
int size,
int maxsize,
int owned,
double *vec
) {
/*
---------------
check the input
---------------
*/
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_init2(%p,%d,%d,%d,%p)"
"\n bad input\n", dv, size, maxsize, owned, vec) ;
exit(-1) ;
}
if ( size < 0 || maxsize < size ) {
fprintf(stderr, "\n fatal error in DV_init2(%p,%d,%d,%d,%p)"
"\n size = %d, maxsize = %d \n",
dv, size, maxsize, owned, vec, size, maxsize) ;
exit(-1) ;
}
if ( owned < 0 || 1 < owned ) {
fprintf(stderr, "\n fatal error in DV_init2(%p,%d,%d,%d,%p)"
"\n owned = %d\n", dv, size, maxsize, owned, vec, owned) ;
exit(-1) ;
}
if ( owned == 1 && vec == NULL ) {
fprintf(stderr, "\n fatal error in DV_init2(%p,%d,%d,%d,%p)"
"\n owned = %d and vec = %p",
dv, size, maxsize, owned, vec, owned, vec) ;
exit(-1) ;
}
/*
--------------
clear any data
--------------
*/
DV_clearData(dv) ;
if ( vec == NULL ) {
/*
----------------------------------------------
no entries input, use the simplest initializer
----------------------------------------------
*/
DV_init(dv, size, NULL) ;
} else {
/*
---------------------------------
entries are input, set the fields
---------------------------------
*/
dv->size = size ;
dv->maxsize = maxsize ;
dv->owned = owned ;
dv->vec = vec ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------
set the maximum size of the vector
created -- 96dec08, cca
----------------------------------
*/
void
DV_setMaxsize (
DV *dv,
int newmaxsize
) {
/*
---------------
check the input
---------------
*/
if ( dv == NULL || newmaxsize < 0 ) {
fprintf(stderr, "\n fatal error in DV_setMaxsize(%p,%d)"
"\n bad input\n", dv, newmaxsize) ;
exit(-1) ;
}
if ( dv->maxsize > 0 && dv->owned == 0 ) {
fprintf(stderr, "\n fatal error in DV_setMaxsize(%p,%d)"
"\n dv->maxsize = %d, dv->owned = %d\n",
dv, newmaxsize, dv->maxsize, dv->owned) ;
exit(-1) ;
}
if ( dv->maxsize != newmaxsize ) {
/*
-----------------------------------
allocate new storage for the vector
-----------------------------------
*/
double *vec ;
/*
vec = DVinit(newmaxsize, 0.0) ;
*/
vec = DVinit2(newmaxsize) ;
if ( dv->size > 0 ) {
/*
---------------------------------
copy old entries into new entries
---------------------------------
*/
if ( dv->vec == NULL ) {
fprintf(stderr, "\n fatal error in DV_setMaxsize(%p,%d)"
"\n dv->size = %d, dv->vec is NULL\n",
dv, newmaxsize, dv->size) ;
exit(-1) ;
}
if ( dv->size <= newmaxsize ) {
DVcopy(dv->size, vec, dv->vec) ;
} else {
/*
-----------------------
note, data is truncated
-----------------------
*/
DVcopy(newmaxsize, vec, dv->vec) ;
dv->size = newmaxsize ;
}
}
if ( dv->vec != NULL ) {
/*
----------------
free old entries
----------------
*/
DVfree(dv->vec) ;
}
/*
----------
set fields
----------
*/
dv->maxsize = newmaxsize ;
dv->owned = 1 ;
dv->vec = vec ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------
set the size of the vector
created -- 96dec08, cca
--------------------------
*/
void
DV_setSize (
DV *dv,
int newsize
) {
/*
---------------
check the input
---------------
*/
if ( dv == NULL || newsize < 0 ) {
fprintf(stderr, "\n fatal error in DV_setSize(%p,%d)"
"\n bad input\n", dv, newsize) ;
exit(-1) ;
}
if ( 0 < dv->maxsize && dv->maxsize < newsize && dv->owned == 0 ) {
fprintf(stderr, "\n fatal error in DV_setSize(%p,%d)"
"\n dv->maxsize = %d, newsize = %d, dv->owned = %d\n",
dv, newsize, dv->maxsize, newsize, dv->owned) ;
exit(-1) ;
}
if ( dv->maxsize < newsize ) {
/*
-------------------------------------------------------------
new size requested is more than maxsize, set new maximum size
-------------------------------------------------------------
*/
DV_setMaxsize(dv, newsize) ;
}
dv->size = newsize ;
return ; }
/*--------------------------------------------------------------------*/
wned, vec) ;
exit(-1) ;
}
/*
--------------
clear any data
--------------
*/
DV_clearData(dv) ;
if ( vec == NULL ) {
/*
----------------------------------------------
no entries input, use the simplest initializer
----------------------------------------------
*/
DV_init(dv, size, NULL) ;
} else {
/*
---------------------------------
entries are input,DV/src/instance.c 0100644 0002055 0007177 00000007304 06534105757 0015161 0 ustar 00cleve compmath 0000040 0000006 /* instance.c */
#include "../DV.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
return 1 if the entries are owned by the object
return 0 otherwise
created -- 96jun22, cca
-----------------------------------------------
*/
int
DV_owned (
DV *dv
) {
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_owned(%p)"
"\n bad input\n", dv) ;
exit(-1) ;
}
return(dv->owned) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
return the vector size
created -- 95oct06, cca
-----------------------
*/
int
DV_maxsize (
DV *dv
) {
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_maxsize(%p)"
"\n bad input\n", dv) ;
exit(-1) ;
}
return(dv->maxsize) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
return the vector size
created -- 95oct06, cca
-----------------------
*/
int
DV_size (
DV *dv
) {
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_size(%p)"
"\n bad input\n", dv) ;
exit(-1) ;
}
return(dv->size) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
return the loc'th entry of a vector.
note: if loc is out of range then 0.0 is returned
created -- 96jun29, cca
-------------------------------------------------
*/
double
DV_entry (
DV *dv,
int loc
) {
if ( dv == NULL || dv->vec == NULL ) {
fprintf(stderr, "\n fatal error in DV_entry(%p)"
"\n bad input\n", dv) ;
exit(-1) ;
}
if ( loc < 0 || loc >= dv->size ) {
return(0.0) ;
} else {
return(dv->vec[loc]) ;
}
}
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
return a pointer to the object's entries array
created -- 95oct06, cca
----------------------------------------------
*/
double *
DV_entries (
DV *dv
) {
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_entries(%p)"
"\n bad input\n", dv) ;
exit(-1) ;
}
return(dv->vec) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
fill *psize with the vector's size
and *pentries with the address of the vector
created -- 95oct06, cca
--------------------------------------------
*/
void
DV_sizeAndEntries (
DV *dv,
int *psize,
double **pentries
) {
if ( dv == NULL || psize == NULL || pentries == NULL ) {
fprintf(stderr, "\n fatal error in DV_sizeAndEntries(%p,%p,%p)"
"\n bad input\n", dv, psize, pentries) ;
exit(-1) ;
}
*psize = dv->size ;
*pentries = dv->vec ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------
set and entry in the vector
created -- 96jul14, cca
---------------------------
*/
void
DV_setEntry (
DV *dv,
int loc,
double value
) {
/*
---------------
check the input
---------------
*/
if ( dv == NULL || loc < 0 ) {
fprintf(stderr, "\n fatal error in DV_setEntry(%p,%d,%f)"
"\n bad input\n", dv, loc, value) ;
exit(-1) ;
}
if ( loc >= dv->maxsize ) {
int newmaxsize = (int) 1.25*dv->maxsize ;
if ( newmaxsize < 10 ) {
newmaxsize = 10 ;
}
if ( loc >= newmaxsize ) {
newmaxsize = loc + 1 ;
}
DV_setMaxsize(dv, newmaxsize) ;
}
if ( loc >= dv->size ) {
dv->size = loc + 1 ;
}
dv->vec[loc] = value ;
return ; }
/*--------------------------------------------------------------------*/
DV/src/profile.c 0100644 0002055 0007177 00000006574 06534105757 0015025 0 ustar 00cleve compmath 0000040 0000006 /* profile */
#include "../DV.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
to fill xDV and yDV with a log10 profile of the magnitudes of
the entries in the DV object. tausmall and tau big provide
cutoffs within which to examine the entries. pnzero, pnsmall
and pnbig are addresses to hold the number of entries zero,
smaller than tausmall and larger than taubig, respectively.
created -- 97feb14, cca
------------------------------------------------------------------
*/
void
DV_log10profile (
DV *dv,
int npts,
DV *xDV,
DV *yDV,
double tausmall,
double taubig,
int *pnzero,
int *pnsmall,
int *pnbig
) {
double deltaVal, maxval, minval, val ;
double *dvec, *sums, *x, *y ;
int ii, ipt, nbig, nsmall, nzero, size ;
/*
---------------
check the input
---------------
*/
if ( dv == NULL || npts <= 0 || xDV == NULL || yDV == NULL
|| tausmall < 0.0 || taubig < 0.0 || tausmall > taubig
|| pnzero == NULL || pnsmall == NULL || pnbig == NULL ) {
fprintf(stderr,
"\n fatal error in DV_log10profile(%p,%d,%p,%p,%f,%f,%p,%p,%p)"
"\n bad input\n",
dv, npts, xDV, yDV, tausmall, taubig, pnzero, pnsmall, pnbig) ;
exit(-1) ;
}
/*
-------------------------------------
find the largest and smallest entries
in the range [tausmall, taubig]
-------------------------------------
*/
nbig = nsmall = nzero = 0 ;
minval = maxval = 0.0 ;
DV_sizeAndEntries(dv, &size, &dvec) ;
for ( ii = 0 ; ii < size ; ii++ ) {
val = fabs(dvec[ii]) ;
if ( val == 0.0 ) {
nzero++ ;
} else if ( val <= tausmall ) {
nsmall++ ;
} else if ( val >= taubig ) {
nbig++ ;
} else {
if ( minval == 0.0 || minval > val ) {
minval = val ;
}
if ( maxval < val ) {
maxval = val ;
}
}
}
*pnzero = nzero ;
*pnsmall = nsmall ;
*pnbig = nbig ;
#if MYDEBUG > 0
fprintf(stdout,
"\n nzero = %d, minval = %e, nsmall = %d, maxval = %e, nbig = %d",
nzero, minval, nsmall, maxval, nbig) ;
#endif
/*
------------------
set up the buckets
------------------
*/
DV_setSize(xDV, npts) ;
DV_setSize(yDV, npts) ;
x = DV_entries(xDV) ;
y = DV_entries(yDV) ;
sums = DVinit(npts, 0.0) ;
minval = log10(minval) ;
maxval = log10(maxval) ;
/*
minval = log10(tausmall) ;
maxval = log10(taubig) ;
*/
deltaVal = (maxval - minval)/(npts - 1) ;
DVfill(npts, x, 0.0) ;
DVfill(npts, y, 0.0) ;
/*
--------------------------------
fill the sums and counts vectors
--------------------------------
*/
for ( ii = 0 ; ii < size ; ii++ ) {
val = fabs(dvec[ii]) ;
if ( tausmall < val && val < taubig ) {
ipt = (log10(val) - minval) / deltaVal ;
sums[ipt] += val ;
y[ipt]++ ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n sum(y) = %.0f", DV_sum(yDV)) ;
#endif
/*
---------------------------
set the x-coordinate vector
---------------------------
*/
for ( ipt = 0 ; ipt < npts ; ipt++ ) {
if ( sums[ipt] == 0.0 ) {
x[ipt] = minval + ipt*deltaVal ;
} else {
x[ipt] = log10(sums[ipt]/y[ipt]) ;
}
}
/*
------------------------
free the working storage
------------------------
*/
DVfree(sums) ;
return ; }
/*--------------------------------------------------------------------*/
------------------------
find the largest and smallest entries
in the range [tausmall, taubig]
---------------------------DV/src/util.c 0100644 0002055 0007177 00000020734 06535051767 0014336 0 ustar 00cleve compmath 0000040 0000006 /* basics.C */
#include "../DV.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
shift the base of the entries and adjust the dimensions
note: this is a dangerous operation because the dv->vec
does not point to the base of the entries any longer,
and thus if the object owns its entries and it is called
to resize them or to free them, malloc and free will choke.
USE WITH CAUTION!
created -- 96aug25, cca
modified -- 96aug28, cca
structure changed
-----------------------------------------------------------
*/
void
DV_shiftBase (
DV *dv,
int offset
) {
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_shiftBase(%p,%d)"
"\n bad input\n", dv, offset) ;
exit(-1) ;
}
dv->vec += offset ;
dv->maxsize -= offset ;
dv->size -= offset ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
push an entry onto the list
created -- 95oct06, cca
--------------------------------------
*/
void
DV_push (
DV *dv,
double val
) {
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_push(%p,%f)"
"\n bad input\n", dv, val) ;
exit(-1) ;
}
if ( dv->size == dv->maxsize ) {
if ( dv->maxsize > 0 ) {
DV_setMaxsize(dv, 2*dv->maxsize) ;
} else {
DV_setMaxsize(dv, 10) ;
}
}
dv->vec[dv->size++] = val ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------
minimum and maximum entries and sum
created -- 95oct06, cca
-----------------------------------
*/
double
DV_min (
DV *dv
) {
int i ;
if ( dv == NULL || dv->size <= 0 || dv->vec == NULL ) {
fprintf(stderr, "\n fatal error in DV_min(%p), size = %d, vec = %p",
dv, dv->size, dv->vec) ;
exit(-1) ;
}
return(DVmin(dv->size, dv->vec, &i)) ; }
double
DV_max (
DV *dv
) {
int i ;
if ( dv == NULL || dv->size <= 0 || dv->vec == NULL ) {
fprintf(stderr, "\n fatal error in DV_max(%p), size = %d, vec = %p",
dv, dv->size, dv->vec) ;
exit(-1) ;
}
return(DVmax(dv->size, dv->vec, &i)) ; }
double
DV_sum (
DV *dv
) {
if ( dv == NULL || dv->size <= 0 || dv->vec == NULL ) {
fprintf(stderr, "\n fatal error in DV_sum(%p), size = %d, vec = %p",
dv, dv->size, dv->vec) ;
exit(-1) ;
}
return(DVsum(dv->size, dv->vec)) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
sort each index list into ascending or descending order
created -- 95oct06, cca
-------------------------------------------------------
*/
void
DV_sortUp (
DV *dv
) {
if ( dv == NULL || dv->size <= 0 || dv->vec == NULL ) {
fprintf(stderr,
"\n fatal error in DV_sortUp(%p), size = %d, vec = %p",
dv, dv->size, dv->vec) ;
exit(-1) ;
}
DVqsortUp(dv->size, dv->vec) ;
return ; }
void
DV_sortDown (
DV *dv
) {
if ( dv == NULL || dv->size <= 0 || dv->vec == NULL ) {
fprintf(stderr,
"\n fatal error in DV_sortDown(%p), size = %d, vec = %p",
dv, dv->size, dv->vec) ;
exit(-1) ;
}
DVqsortDown(dv->size, dv->vec) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
ramp the entries
created -- 95oct06, cca
-----------------------
*/
void
DV_ramp (
DV *dv,
double base,
double incr
) {
if ( dv == NULL || dv->size <= 0 || dv->vec == NULL ) {
fprintf(stderr,
"\n fatal error in DV_ramp(%p,%f,%f), size = %d, vec = %p",
dv, base, incr, dv->size, dv->vec) ;
exit(-1) ;
}
DVramp(dv->size, dv->vec, base, incr) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
shuffle the list
created -- 95oct06, cca
-----------------------
*/
void
DV_shuffle (
DV *dv,
int seed
) {
if ( dv == NULL || dv->size <= 0 || dv->vec == NULL ) {
fprintf(stderr,
"\n fatal error in DV_shuffle(%p,%d), size = %d, vec = %p",
dv, seed, dv->size, dv->vec) ;
exit(-1) ;
}
DVshuffle(dv->size, dv->vec, seed) ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 95oct06, cca
----------------------------------------------
*/
int
DV_sizeOf (
DV *dv
) {
int nbytes ;
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_sizeOf(%p)"
"\n bad input \n", dv) ;
exit(-1) ;
}
nbytes = sizeof(struct _DV) ;
if ( dv->owned == 1 ) {
nbytes += + dv->maxsize*sizeof(double) ;
}
return(nbytes) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
iterator :
return the pointer to the head of the vector
created -- 95oct06, cca
--------------------------------------------
*/
double *
DV_first (
DV *dv
) {
double *pd ;
/*
---------------
check the input
---------------
*/
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_first(%p)"
"\n bad input", dv) ;
exit(-1) ;
}
if ( dv->size == 0 ) {
pd = NULL ;
} else {
pd = dv->vec ;
}
return(pd) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
iterator :
return the pointer to the next location in the vector
created -- 95oct06, cca
-----------------------------------------------------
*/
double *
DV_next (
DV *dv,
double *pd
) {
int offset ;
/*
---------------
check the input
---------------
*/
if ( pd == NULL ) {
fprintf(stderr, "\n fatal error in DV_next(%p,%p)"
"\n bad input", dv, pd) ;
fflush(stderr) ;
exit(-1) ;
}
/*
---------------
check the input
---------------
*/
if ( (offset = pd - dv->vec) < 0 || offset >= dv->size ) {
/*
-----------------------------
error, offset is out of range
-----------------------------
*/
fprintf(stderr, "\n fatal error in DV_next(%p,%p)"
"\n offset = %d, must be in [0,%d)",
dv, pd, offset, dv->size) ;
fflush(stderr) ;
exit(-1) ;
} else if ( offset == dv->size - 1 ) {
/*
----------------------------
end of the list, return NULL
----------------------------
*/
pd = NULL ;
} else {
/*
----------------------------------------
middle of the list, return next location
----------------------------------------
*/
pd++ ;
}
return(pd) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------
fill a vector with a value
created -- 96jun22, cca
--------------------------
*/
void
DV_fill (
DV *dv,
double value
) {
/*
---------------
check the input
---------------
*/
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_fill(%p,%f)"
"\n bad input\n", dv, value) ;
exit(-1) ;
}
if ( dv->size > 0 ) {
DVfill(dv->size, dv->vec, value) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------
fill a vector with zeros
created -- 98jun02, cca
--------------------------
*/
void
DV_zero (
DV *dv
) {
/*
---------------
check the input
---------------
*/
if ( dv == NULL ) {
fprintf(stderr, "\n fatal error in DV_zero(%p)"
"\n bad input\n", dv) ;
exit(-1) ;
}
if ( dv->size > 0 ) {
DVzero(dv->size, dv->vec) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
copy entries from dv2 into dv1.
note: this is a "mapped" copy,
dv1 and dv2 need not be the same size.
created -- 96aug31, cca
--------------------------------------
*/
void
DV_copy (
DV *dv1,
DV *dv2
) {
int ii, size ;
double *vec1, *vec2 ;
/*
---------------
check the input
---------------
*/
if ( dv1 == NULL || dv2 == NULL ) {
fprintf(stderr, "\n fatal error in DV_copy(%p,%p)"
"\n bad input\n", dv1, dv2) ;
exit(-1) ;
}
size = dv1->size ;
if ( size > dv2->size ) {
size = dv2->size ;
}
vec1 = dv1->vec ;
vec2 = dv2->vec ;
for ( ii = 0 ; ii < size ; ii++ ) {
vec1[ii] = vec2[ii] ;
}
return ; }
/*--------------------------------------------------------------------*/
USE WITH CAUTION!
created DV/drivers/makefile 0100644 0002055 0007177 00000000451 06653142416 0015567 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = testIO
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
testIO : testIO.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
DV/drivers/testIO.c 0100644 0002055 0007177 00000005437 06535063502 0015450 0 ustar 00cleve compmath 0000040 0000006 /* testIO.c */
#include "../DV.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
----------------------------------------------
test DV_readFromFile and DV_writeToFile,
useful for translating between formatted *.dvf
and binary *.dvb files.
created -- 98jun02, cca
----------------------------------------------
*/
{
char *inDVFileName, *outDVFileName ;
double t1, t2 ;
int msglvl, rc ;
DV *dvobj ;
FILE *msgFile ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.dvf or *.dvb"
"\n outFile -- output file, must be *.dvf or *.dvb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inDVFileName = argv[3] ;
outDVFileName = argv[4] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], inDVFileName, outDVFileName) ;
fflush(msgFile) ;
/*
---------------------
read in the DV object
---------------------
*/
if ( strcmp(inDVFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
dvobj = DV_new() ;
MARKTIME(t1) ;
rc = DV_readFromFile(dvobj, inDVFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in iv from file %s",
t2 - t1, inDVFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from DV_readFromFile(%p,%s)",
rc, dvobj, inDVFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading DV object from file %s",
inDVFileName) ;
if ( msglvl > 2 ) {
DV_writeForHumanEye(dvobj, msgFile) ;
} else {
DV_writeStats(dvobj, msgFile) ;
}
fflush(msgFile) ;
/*
-----------------------
write out the DV object
-----------------------
*/
if ( strcmp(outDVFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = DV_writeToFile(dvobj, outDVFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write iv to file %s",
t2 - t1, outDVFileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from DV_writeToFile(%p,%s)",
rc, dvobj, outDVFileName) ;
}
/*
------------------
free the DV object
------------------
*/
DV_free(dvobj) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
DV/doc/ 0042755 0002055 0007177 00000000000 06542767331 0013171 5 ustar 00cleve compmath 0000040 0000006 DV/doc/dataStructure.tex 0100644 0002055 0007177 00000001601 06534105757 0016535 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:DV:dataStructure}
\par
\par
The {\tt DV} structure has three fields.
\begin{itemize}
\item
{\tt int size} : present size of the vector.
\item
{\tt int maxsize} : maximum size of the vector.
\item
{\tt int owned} : owner flag for the data.
When {\tt owned = 1}, storage for {\tt owned} {\tt double}'s
has been allocated by this object and can be free'd by the object.
When {\tt owned == 0} but {\tt size > 0 }, this object points to
entries that have been allocated elsewhere, and these entries will
not be free'd by this object.
\item
{\tt double *vec} :
pointer to the base address of the {\it double} vector
\end{itemize}
The {\tt size}, {\tt maxsize}, {\tt nowned} and {\tt vec} fields
need never be accessed directly ---
see the
{\tt DV\_size()},
{\tt DV\_maxsize()},
{\tt DV\_owned()},
{\tt DV\_entries()},
{\tt DV\_sizeAndEntries()} methods.
DV/doc/intro.tex 0100644 0002055 0007177 00000003555 06534105757 0015050 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt DV}: Double Vector Object}
\par
The {\tt DV} object is a wrapper around a {\tt double} vector,
thus the acronym {\bf D}ouble {\bf V}ector.
The driving force for its creation is more convenience than
performance.
There are three cases that led to its development.
\begin{itemize}
\item
Often a method will create a vector (allocate storage for and fill
the entries) whose size is not known before the method call.
Instead of having a pointer to {\tt int} and a pointer to {\tt double*}
in the calling sequence, we can return a pointer to an {\tt DV}
object that contains the newly created vector and its size.
\item
In many cases we need a persistent {\tt double} vector object,
and file IO is simplified if we have an object to deal with.
The filename is of the form {\tt *.dvf} for a formatted file
or {\tt *.dvb} for a binary file.
\item
Prototyping can go much faster with this object as opposed to
working with an {\tt double} array.
Consider the case when one wants to accumulate a list of doubles,
but one doesn't know how large the list will be.
The method {\tt DV\_setSize()} can be used to set
the size of the vector to zero.
Another method {\tt DV\_push()} appends an element to the vector,
growing the storage if necessary.
\item
Sometimes an object needs to change its size, i.e., vectors need to
grow or shrink.
It is easier and more robust to tell an {\tt DV} object to resize
itself (see the {\tt DV\_setSize()} and {\tt DV\_setMaxsize()}
methods) than it is to duplicate code to work on an {\tt double}
vector.
\end{itemize}
One must choose where to use this object.
There is a substantial performance penalty for doing the simplest
operations, and so when we need to manipulate an {\tt double} vector
inside a loop, we extract out the size and pointer to the base
array from the {\tt DV} object.
On the other hand, the convenience makes it a widely used object.
\par
DV/doc/main.tex 0100644 0002055 0007177 00000001072 06650656205 0014627 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt DV} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt DV} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
DV/doc/main.ind 0100644 0002055 0007177 00000002511 06535064016 0014573 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt DV\_clearData()}, 2
\item {\tt DV\_copy()}, 6
\item {\tt DV\_entries()}, 3
\item {\tt DV\_entry()}, 3
\item {\tt DV\_fill()}, 6
\item {\tt DV\_first()}, 6
\item {\tt DV\_free()}, 2
\item {\tt DV\_init()}, 4
\item {\tt DV\_init1()}, 4
\item {\tt DV\_init2()}, 4
\item {\tt DV\_log10profile()}, 6
\item {\tt DV\_max()}, 5
\item {\tt DV\_size()}, 3
\item {\tt DV\_min()}, 5
\item {\tt DV\_new()}, 2
\item {\tt DV\_next()}, 6
\item {\tt DV\_owned()}, 3
\item {\tt DV\_push()}, 5
\item {\tt DV\_ramp()}, 5
\item {\tt DV\_readFromBinaryFile()}, 7
\item {\tt DV\_readFromFile()}, 7
\item {\tt DV\_readFromFormattedFile()}, 7
\item {\tt DV\_setDefaultFields()}, 2
\item {\tt DV\_setEntry()}, 3
\item {\tt DV\_setMaxsize()}, 4
\item {\tt DV\_setSize()}, 4
\item {\tt DV\_shiftBase()}, 4
\item {\tt DV\_shuffle()}, 5
\item {\tt DV\_size()}, 3
\item {\tt DV\_sizeAndEntries()}, 3
\item {\tt DV\_sizeOf()}, 5
\item {\tt DV\_sortDown()}, 5
\item {\tt DV\_sortUp()}, 5
\item {\tt DV\_sum()}, 5
\item {\tt DV\_writeForHumanEye()}, 7
\item {\tt DV\_writeForMatlab()}, 8
\item {\tt DV\_writeStats()}, 7
\item {\tt DV\_writeToBinaryFile()}, 7
\item {\tt DV\_writeToFile()}, 7
\item {\tt DV\_writeToFormattedFile()}, 7
\item {\tt DV\_zero()}, 6
\end{theindex}
DV/doc/main.log 0100644 0002055 0007177 00000003225 06535064021 0014601 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 2 JUN 1998 14:01
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
)
\@indexfile=\write3
Writing index file main.idx
(main.aux) (intro.tex
Chapter 1.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 1.
) (dataStructure.tex [1
]) (proto.tex [2] [3] [4] [5]
Overfull \hbox (11.7664pt too wide) in paragraph at lines 413--413
[] \elvtt double taubig, int *pnzero, int *pnsmall, int
*pnbig ) ;[]
\hbox(7.60416+2.43333)x469.75499
.\glue(\leftskip) 27.37506
.\hbox(0.0+0.0)x0.0
.\penalty 10000
.\glue 5.74869
.\penalty 10000
.etc.
[6] [7]) (drivers.tex) (main.ind [8] [9
]) (main.aux) )
Here is how much of TeX's memory you used:
209 strings out of 11977
2165 string characters out of 87269
33539 words of memory out of 262141
2143 multiletter control sequences out of 9500
19780 words of font info for 75 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
14i,5n,17p,179b,258s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (9 pages, 26652 bytes).
DV/doc/main.aux 0100644 0002055 0007177 00000003041 06535064021 0014611 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}{\string\ptt\space DV}: Double Vector Object}{1}}
\@writefile{lof}{\string\addvspace\space {10\p@ }}
\@writefile{lot}{\string\addvspace\space {10\p@ }}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Data Structure}{1}}
\newlabel{section:DV:dataStructure}{{1.1}{1}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Prototypes and descriptions of {\string\ptt\space DV} methods}{2}}
\newlabel{section:DV:proto}{{1.2}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.1}Basic methods}{2}}
\newlabel{subsection:DV:proto:basics}{{1.2.1}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Instance methods}{3}}
\newlabel{subsection:DV:proto:Instance}{{1.2.2}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.3}Initializer methods}{4}}
\newlabel{subsection:DV:proto:initializers}{{1.2.3}{4}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.4}Utility methods}{4}}
\newlabel{subsection:DV:proto:utilities}{{1.2.4}{4}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.5}IO methods}{6}}
\newlabel{subsection:DV:proto:IO}{{1.2.5}{6}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}Driver programs for the {\string\ptt\space DV object}}{8}}
\newlabel{section:DV:drivers}{{1.3}{8}}
DV/doc/main.idx 0100644 0002055 0007177 00000003752 06535064021 0014611 0 ustar 00cleve compmath 0000040 0000006 \indexentry{DV_new@{\tt DV\_new()}}{2}
\indexentry{DV_setDefaultFields@{\tt DV\_setDefaultFields()}}{2}
\indexentry{DV_clearData@{\tt DV\_clearData()}}{2}
\indexentry{DV_free@{\tt DV\_free()}}{2}
\indexentry{DV_owned@{\tt DV\_owned()}}{3}
\indexentry{DV_size@{\tt DV\_size()}}{3}
\indexentry{DV_maxsize@{\tt DV\_size()}}{3}
\indexentry{DV_entry@{\tt DV\_entry()}}{3}
\indexentry{DV_entries@{\tt DV\_entries()}}{3}
\indexentry{DV_sizeAndEntries@{\tt DV\_sizeAndEntries()}}{3}
\indexentry{DV_setEntry@{\tt DV\_setEntry()}}{3}
\indexentry{DV_init@{\tt DV\_init()}}{4}
\indexentry{DV_init1@{\tt DV\_init1()}}{4}
\indexentry{DV_init2@{\tt DV\_init2()}}{4}
\indexentry{DV_setMaxsize@{\tt DV\_setMaxsize()}}{4}
\indexentry{DV_setSize@{\tt DV\_setSize()}}{4}
\indexentry{DV_shiftBase@{\tt DV\_shiftBase()}}{4}
\indexentry{DV_push@{\tt DV\_push()}}{5}
\indexentry{DV_min@{\tt DV\_min()}}{5}
\indexentry{DV_max@{\tt DV\_max()}}{5}
\indexentry{DV_sum@{\tt DV\_sum()}}{5}
\indexentry{DV_sortUp@{\tt DV\_sortUp()}}{5}
\indexentry{DV_sortDown@{\tt DV\_sortDown()}}{5}
\indexentry{DV_ramp@{\tt DV\_ramp()}}{5}
\indexentry{DV_shuffle@{\tt DV\_shuffle()}}{5}
\indexentry{DV_sizeOf@{\tt DV\_sizeOf()}}{5}
\indexentry{DV_first@{\tt DV\_first()}}{6}
\indexentry{DV_next@{\tt DV\_next()}}{6}
\indexentry{DV_fill@{\tt DV\_fill()}}{6}
\indexentry{DV_zero@{\tt DV\_zero()}}{6}
\indexentry{DV_copy@{\tt DV\_copy()}}{6}
\indexentry{DV_log10profile@{\tt DV\_log10profile()}}{6}
\indexentry{DV_readFromFile@{\tt DV\_readFromFile()}}{7}
\indexentry{DV_readFromFormattedFile@{\tt DV\_readFromFormattedFile()}}{7}
\indexentry{DV_readFromBinaryFile@{\tt DV\_readFromBinaryFile()}}{7}
\indexentry{DV_writeToFile@{\tt DV\_writeToFile()}}{7}
\indexentry{DV_writeToFormattedFile@{\tt DV\_writeToFormattedFile()}}{7}
\indexentry{DV_writeToBinaryFile@{\tt DV\_writeToBinaryFile()}}{7}
\indexentry{DV_writeForHumanEye@{\tt DV\_writeForHumanEye()}}{7}
\indexentry{DV_writeStats@{\tt DV\_writeStats()}}{7}
\indexentry{DV_writeForMatlab@{\tt DV\_writeForMatlab()}}{8}
setEntry@{\tt DV\_setEDV/doc/proto.tex 0100644 0002055 0007177 00000054047 06613640371 0015054 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt DV} methods}
\label{section:DV:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt DV} object.
\par
\subsection{Basic methods}
\label{subsection:DV:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
DV * DV_new ( void ) ;
\end{verbatim}
\index{DV_new@{\tt DV\_new()}}
This method simply allocates storage for the {\tt DV} structure
and then sets the default fields by a call to
{\tt DV\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_setDefaultFields ( DV *dv ) ;
\end{verbatim}
\index{DV_setDefaultFields@{\tt DV\_setDefaultFields()}}
This method sets the default fields of the object,
{\tt size = maxsize = owned = 0} and {\tt vec = NULL}.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_clearData ( DV *dv ) ;
\end{verbatim}
\index{DV_clearData@{\tt DV\_clearData()}}
This method releases any data owned by the object.
If {\tt vec} is not {\tt NULL} and {\tt owned = 1},
then the storage for {\tt vec} is free'd by a call to
{\tt DVfree()}.
The structure's default fields are then set
with a call to {\tt DV\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_free ( DV *dv ) ;
\end{verbatim}
\index{DV_free@{\tt DV\_free()}}
This method releases any storage by a call to
{\tt DV\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Instance methods}
\label{subsection:DV:proto:Instance}
\par
These method allow access to information in the data fields without
explicitly following pointers.
There is overhead involved with these method due to the function
call and error checking inside the methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_owned ( DV *dv ) ;
\end{verbatim}
\index{DV_owned@{\tt DV\_owned()}}
This method returns the value of {\tt owned}.
If {\tt owned > 0},
then the object owns the data pointed to by {\tt vec}
and will free this data with a call to {\tt DVfree()} when its data
is cleared by a call to {\tt DV\_free()} or {\tt DV\_clearData()}.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_size ( DV *dv ) ;
\end{verbatim}
\index{DV_size@{\tt DV\_size()}}
This method returns the value of {\tt size},
the present size of the vector.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_maxsize ( DV *dv ) ;
\end{verbatim}
\index{DV_maxsize@{\tt DV\_size()}}
This method returns the value of {\tt size},
the maximum size of the vector.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DV_entry ( DV *dv, int loc ) ;
\end{verbatim}
\index{DV_entry@{\tt DV\_entry()}}
This method returns the value of the {\tt loc}'th entry
in the vector.
If {\tt loc < 0} or {\tt loc >= size}, i.e., if the location is
out of range, we return {\tt 0.0}.
This design {\tt feature} is handy when a list terminates with a
{\tt 0.0} value.
\par \noindent {\it Error checking:}
If {\tt dv} or {\tt vec} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double * DV_entries ( DV *dv ) ;
\end{verbatim}
\index{DV_entries@{\tt DV\_entries()}}
This method returns {\tt vec},
a pointer to the base address of the vector.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_sizeAndEntries ( DV *dv, int *psize, double **pentries ) ;
\end{verbatim}
\index{DV_sizeAndEntries@{\tt DV\_sizeAndEntries()}}
This method fills {\tt *psize} with the size of the vector
and {\tt **pentries} with the base address of the vector.
\par \noindent {\it Error checking:}
If {\tt dv}, {\tt psize} or {\tt pentries} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_setEntry ( DV *dv, int loc, double value ) ;
\end{verbatim}
\index{DV_setEntry@{\tt DV\_setEntry()}}
This method sets the {\tt loc}'th entry of the vector to {\tt value}.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL} or {\tt loc < 0},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initializer methods}
\label{subsection:DV:proto:initializers}
\par
There are three initializer methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_init ( DV *dv, int size, double *entries ) ;
\end{verbatim}
\index{DV_init@{\tt DV\_init()}}
This method initializes the object given a size for the vector
and a possible pointer to the vectors' storage.
Any previous data is cleared with a call to {\tt DV\_clearData()}.
If {\tt entries != NULL} then the {\tt vec} field is set to {\tt
entries}, the {\tt size} and {\tt maxsize} fields are set to
{\tt size}, and {\tt owned} is set to zero
because the object does not own the entries.
If {\tt entries} is {\tt NULL} and {\tt size > 0} then a vector
is allocated by the object, and the object owns this storage.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL} or {\tt size < 0},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_init1 ( DV *dv, int size ) ;
\end{verbatim}
\index{DV_init1@{\tt DV\_init1()}}
This method initializes the object given a size size for the vector
via a call to {\tt DV\_init()}.
\par \noindent {\it Error checking:}
Error checking is done with the call to {\t DV\_init()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_init2 ( DV *dv, int size, int maxsize, int owned, double *vec ) ;
\end{verbatim}
\index{DV_init2@{\tt DV\_init2()}}
This is the total initialization method.
The data is cleared with a call to {\tt DV\_clearData()}.
If {\tt vec} is {\tt NULL}, the object is initialized via a call
to {\tt DV\_init1()}.
Otherwise, the objects remaining fields are set to the input
parameters.
and if {\tt owned} is not {\tt 1}, the data is not owned, so the
object cannot grow.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL},
or if {\tt size < 0},
or if {\tt maxsize < size},
or if {\tt owned} is not equal to {\tt 0} or {\tt 1},
of if { \tt owned = 1} and {\tt vec = NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_setMaxsize ( DV *dv, int newmaxsize ) ;
\end{verbatim}
\index{DV_setMaxsize@{\tt DV\_setMaxsize()}}
This method sets the maximum size of the vector.
If {\tt maxsize}, the present maximum size of the vector,
is not equal to {\tt newmaxsize}, then new storage is allocated.
Only {\tt size}
entries of the old data are copied into the new
storage, so if {\tt size > newmaxsize} then data will be lost.
The {\tt size} field is set to the minimum of {\tt size}
and {\tt newmaxsize}.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL} or {\tt newmaxsize < 0},
or if {\tt 0 < maxsize} and {\tt owned == 0},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_setSize ( DV *dv, int newsize ) ;
\end{verbatim}
\index{DV_setSize@{\tt DV\_setSize()}}
This method sets the size of the vector.
If {\tt newsize > maxsize}, the length of the vector is increased
with a call to {\tt DV\_setMaxsize()}.
The {\tt size} field is set to {\tt newsize}.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}, or {\tt newsize < 0},
or if {\tt 0 < maxsize < newsize} and {\tt owned = 0},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:DV:proto:utilities}
\par
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_shiftBase ( DV *dv, int offset ) ;
\end{verbatim}
\index{DV_shiftBase@{\tt DV\_shiftBase()}}
This method shifts the base entries of the vector and decrements
the present size and maximum size of the vector by {\tt offset}.
This is a dangerous method to use because the state of the vector
is lost, namely {\tt vec}, the base of the entries, is corrupted.
If the object owns its entries and {\tt DV\_free()},
{\tt DV\_setSize()} or {\tt DV\_setMaxsize()} is called before
the base has been shifted back to
its original position, a segmentation violation will likely result.
This is a very useful method, but use with caution.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_push ( DV *dv, double val ) ;
\end{verbatim}
\index{DV_push@{\tt DV\_push()}}
This method pushes an entry onto the vector.
If the vector is full, i.e., if {\tt size == maxsize - 1},
then the size of the vector is doubled if possible.
If the storage cannot grow, i.e., if the object does not own its
storage, an error message is printed and the program exits.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DV_min ( DV *dv ) ;
double DV_max ( DV *dv ) ;
double DV_sun ( DV *dv ) ;
\end{verbatim}
\index{DV_min@{\tt DV\_min()}}
\index{DV_max@{\tt DV\_max()}}
\index{DV_sum@{\tt DV\_sum()}}
These methods simply return the minimum entry, the maximum entry
and the sum of the entries in the vector.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}, {\tt size <= 0} or if {\tt vec == NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_sortUp ( DV *dv ) ;
void DV_sortDown ( DV *dv ) ;
\end{verbatim}
\index{DV_sortUp@{\tt DV\_sortUp()}}
\index{DV_sortDown@{\tt DV\_sortDown()}}
This method sorts the entries in the vector into ascending or
descending order via calls to {\tt DVqsortUp()} and {\tt
DVqsortDown()}.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}, {\tt size <= 0} or if {\tt vec == NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_ramp ( DV *dv, double base, int double ) ;
\end{verbatim}
\index{DV_ramp@{\tt DV\_ramp()}}
This method fills the object with a ramp vector,
i.e., entry {\tt i} is {\tt base + i*incr}.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}, {\tt size <= 0} or if {\tt vec == NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_shuffle ( DV *dv, int seed ) ;
\end{verbatim}
\index{DV_shuffle@{\tt DV\_shuffle()}}
This method shuffles the entries in the vector
using {\tt seed} as a seed to a random number generator.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}, {\tt size <= 0} or if {\tt vec == NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_sizeOf ( DV *dv ) ;
\end{verbatim}
\index{DV_sizeOf@{\tt DV\_sizeOf()}}
This method returns the number of bytes taken by the object.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double * DV_first ( DV *dv ) ;
double * DV_next ( DV *dv, int *pd ) ;
\end{verbatim}
\index{DV_first@{\tt DV\_first()}}
\index{DV_next@{\tt DV\_next()}}
These two methods are used as iterators, e.g.,
\begin{verbatim}
for ( pd = DV_first(dv) ; pd != NULL ; pd = DV_next(dv, pd) ) {
do something with entry *pd
}
\end{verbatim}
Each method checks to see if {\tt dv} or {\tt pd} is {\tt NULL},
if so an error message is printed and the program exits.
In method {\tt DV\_next()}, if {\tt pd} is not in the valid
range, an error message is printed and the program exits.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_fill ( DV *dv, double value ) ;
\end{verbatim}
\index{DV_fill@{\tt DV\_fill()}}
This method fills the vector with a scalar value.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_zero ( DV *dv ) ;
\end{verbatim}
\index{DV_zero@{\tt DV\_zero()}}
This method fills the vector with zeros.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_copy ( DV *dv1, DV *dv2 ) ;
\end{verbatim}
\index{DV_copy@{\tt DV\_copy()}}
This method fills the {\tt dv1} object with entries in the {\tt
iv2} object.
Note, this is a {\it mapped} copy, {\tt dv1} and {\tt dv2} need not
have the same size.
The number of entries that are copied is the smaller of the two sizes.
\par \noindent {\it Error checking:}
If {\tt dv1} or {\tt dv2} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DV_log10profile ( DV *dv, int npts, DV *xDV, DV *yDV, double tausmall,
double taubig, int *pnzero, int *pnsmall, int *pnbig ) ;
\end{verbatim}
\index{DV_log10profile@{\tt DV\_log10profile()}}
This method scans the entries in the {\tt DV} object and fills {\tt
xDV} and {\tt yDV} with data that allows a simple $\log_{10}$
distribution plot.
Only entries whose magnitudes lie in the range {\tt [tausmall, taubig]}
contribute to the distribution.
The number of entries whose magnitudes are zero,
smaller than {\tt tausmall},
or larger than {\tt taubig}
are placed into {\tt pnzero}, {\tt *pnsmall} and {\tt *pnbig},
respectively.
On return, the size of the {\tt xDV} and {\tt yDV} objects
is {\tt npts}.
\par \noindent {\it Error checking:}
If {\tt dv}, {\tt xDV}, {\tt yDV}, {\tt pnsmall} or {\tt pnbig} are
{\tt NULL}, or if ${\tt npts} \le 0$,
or if ${\tt taubig} < 0.0$
or if ${\tt tausmall} > {\tt taubig}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:DV:proto:IO}
\par
There are the usual eight IO routines.
The file structure of a {\tt DV} object is simple:
the first entry is {\tt size}, followed by the {\tt size} entries
found in {\tt vec[]}.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_readFromFile ( DV *dv, char *fn ) ;
\end{verbatim}
\index{DV_readFromFile@{\tt DV\_readFromFile()}}
\par
This method reads a {\tt DV} object from a file.
It tries to open the file and if it is successful,
it then calls {\tt DV\_readFromFormattedFile()} or
{\tt DV\_readFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt dv} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.dvf} (for a formatted file)
or {\tt *.dvb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_readFromFormattedFile ( DV *dv, FILE *fp ) ;
\end{verbatim}
\index{DV_readFromFormattedFile@{\tt DV\_readFromFormattedFile()}}
\par
This method reads in a {\tt DV} object from a formatted file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fscanf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt dv} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_readFromBinaryFile ( DV *dv, FILE *fp ) ;
\end{verbatim}
\index{DV_readFromBinaryFile@{\tt DV\_readFromBinaryFile()}}
\par
This method reads in a {\tt DV} object from a binary file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fread}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt dv} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_writeToFile ( DV *dv, char *fn ) ;
\end{verbatim}
\index{DV_writeToFile@{\tt DV\_writeToFile()}}
\par
This method writes a {\tt DV} object from a file.
It tries to open the file and if it is successful,
it then calls {\tt DV\_writeFromFormattedFile()} or
{\tt DV\_writeFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt dv} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.dvf} (for a formatted file)
or {\tt *.dvb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_writeToFormattedFile ( DV *dv, FILE *fp ) ;
\end{verbatim}
\index{DV_writeToFormattedFile@{\tt DV\_writeToFormattedFile()}}
\par
This method writes a {\tt DV} object to a formatted file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fprintf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt dv} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_writeToBinaryFile ( DV *dv, FILE *fp ) ;
\end{verbatim}
\index{DV_writeToBinaryFile@{\tt DV\_writeToBinaryFile()}}
\par
This method writes a {\tt DV} object to a binary file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fwrite}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt dv} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_writeForHumanEye ( DV *dv, FILE *fp ) ;
\end{verbatim}
\index{DV_writeForHumanEye@{\tt DV\_writeForHumanEye()}}
\par
This method writes a {\tt DV} object to a file in a human
readable format.
is called to write out the
header and statistics.
The entries of the vector then follow in eighty column format
using the {\tt DVfprintf()} method.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt dv} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_writeStats ( DV *dv, FILE *fp ) ;
\end{verbatim}
\index{DV_writeStats@{\tt DV\_writeStats()}}
\par
This method writes the header and statistics to a file.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt dv} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DV_writeForMatlab ( DV *dv, char *name, FILE *fp ) ;
\end{verbatim}
\index{DV_writeForMatlab@{\tt DV\_writeForMatlab()}}
\par
This method writes the entries of the vector to a file
suitable to be read by Matlab.
The character string {\tt name} is the name of the vector,
e.g, if {\tt name = "A"}, then we have lines of the form
\begin{verbatim}
A(1) = 1.000000000000e0 ;
A(2) = 2.000000000000e0 ;
...
\end{verbatim}
for each entry in the vector.
Note, the output indexing is 1-based, not 0-based.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt dv} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
---------------------------------------------
\item
\begin{verbatim}
void DV_ramp ( DV *dv, double base, int double ) ;
\end{verbatim}
\index{DV_ramp@{\tt DV\_ramp()}}
This method fills the object with a ramp vector,
i.e., entry {\tt i} is {\tt base + i*incr}.
\par \noindent {\it Error checking:}
If {\tt dv} is {\tt NULL}, {\tt size <= 0} or if {\tt vec == NULL},
an error message is printed and the program exits.
%------------------------------------------------------DV/doc/main.ilg 0100644 0002055 0007177 00000000457 06535064016 0014603 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (41 entries accepted, 0 rejected).
Sorting entries....done (231 comparisons).
Generating output file main.ind....done (45 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
DV/doc/drivers.tex 0100644 0002055 0007177 00000003027 06535063755 0015367 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt DV object}}
\label{section:DV:drivers}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testIO msglvl msgFile inFile outFile
\end{verbatim}
This driver program tests the {\tt DV} IO methods,
and is useful for translating between the formatted {\tt *.dvf}
and binary {\tt *.dvb} files.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inFile} parameter is the name of the file
from which to read in the object.
{\tt inFile} must be of the form {\tt *.dvf} for a formatted file
or {\tt *.dvb} for a binary file.
\item
The {\tt outFile} parameter is the name of the file
to which to write out the object.
If {\tt outfile} is of the form {\tt *.dvf}, the object is written
to a formatted file.
If {\tt outfile} is of the form {\tt *.dvb}, the object is written
to a binary file.
When {\tt outFile} is {\it not} {\tt "none"},
the object is written to the file in a human readable format.
When {\tt outFile} is {\tt "none"}, the object is not written out.
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
DV/doc/makefile 0100644 0002055 0007177 00000000027 06542767331 0014663 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
DenseMtx.h 0100644 0002055 0007177 00000000114 06567627346 0014012 0 ustar 00cleve compmath 0000040 0000006 #ifndef _DenseMtx_
#define _DenseMtx_
#include "DenseMtx/DenseMtx.h"
#endif
DenseMtx/DenseMtx.h 0100644 0002055 0007177 00000046260 06622344036 0015535 0 ustar 00cleve compmath 0000040 0000006 /* DenseMtx */
#include "../cfiles.h"
#include "../Drand.h"
#include "../A2.h"
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
this object handles a dense real and complex matrix.
type -- type of entries
1 -- real
2 -- complex
rowid -- id for the rows in this matrix
colid -- id for the columns in this matrix
nrow -- # of rows in the matrix
ncol -- # of columns in the matrix
inc1 -- row increment for the entries
inc2 -- column increment for the entries
rowind -- pointer to row indices
colind -- pointer to column indices
entries -- pointer to matrix entries
wrkDV -- DV object to manage workspace
next -- pointer to next DenseMtx object in a singly linked list
-------------------------------------------------------------------
*/
typedef struct _DenseMtx DenseMtx ;
struct _DenseMtx {
int type ;
int rowid ;
int colid ;
int nrow ;
int ncol ;
int inc1 ;
int inc2 ;
int *rowind ;
int *colind ;
double *entries ;
DV wrkDV ;
DenseMtx *next ;
} ;
#define DENSEMTX_IS_REAL(mtx) ((mtx)->type == SPOOLES_REAL)
#define DENSEMTX_IS_COMPLEX(mtx) ((mtx)->type == SPOOLES_COMPLEX)
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
simplest constructor
created -- 98may02, cca
-----------------------
*/
DenseMtx *
DenseMtx_new (
void
) ;
/*
-----------------------
set the default fields
created -- 98may02, cca
-----------------------
*/
void
DenseMtx_setDefaultFields (
DenseMtx *mtx
) ;
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98may02, cca
--------------------------------------------------
*/
void
DenseMtx_clearData (
DenseMtx *mtx
) ;
/*
------------------------------------------
destructor, free's the object and its data
created -- 98may02, cca
------------------------------------------
*/
void
DenseMtx_free (
DenseMtx *mtx
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in instance.c --------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------
return the row id of the object
created -- 98may02, cca
-------------------------------
*/
int
DenseMtx_rowid (
DenseMtx *mtx
) ;
/*
----------------------------------
return the column id of the object
created -- 98may02, cca
----------------------------------
*/
int
DenseMtx_colid (
DenseMtx *mtx
) ;
/*
------------------------------------------
fill *pnrow with nrow and *pncol with ncol
created -- 98may02, cca
------------------------------------------
*/
void
DenseMtx_dimensions (
DenseMtx *mtx,
int *pnrow,
int *pncol
) ;
/*
------------------------
return the row increment
created -- 98may02, cca
------------------------
*/
int
DenseMtx_rowIncrement (
DenseMtx *mtx
) ;
/*
---------------------------
return the column increment
created -- 98may02, cca
---------------------------
*/
int
DenseMtx_columnIncrement (
DenseMtx *mtx
) ;
/*
-------------------------------------------
fill *pnrow with nrow, *prowind with rowind
created -- 98may02, cca
-------------------------------------------
*/
void
DenseMtx_rowIndices (
DenseMtx *mtx,
int *pnrow,
int **prowind
) ;
/*
-------------------------------------------
fill *pncol with ncol, *pcolind with colind
created -- 98may02, cca
-------------------------------------------
*/
void
DenseMtx_columnIndices (
DenseMtx *mtx,
int *pncol,
int **pcolind
) ;
/*
--------------------------------------------
fill *pentries with a pointer to the entries
created -- 98may02, cca
--------------------------------------------
*/
double *
DenseMtx_entries(
DenseMtx *mtx
) ;
/*
---------------------------------
return a pointer to the workspace
created -- 98may02, cca
---------------------------------
*/
void *
DenseMtx_workspace(
DenseMtx *mtx
) ;
/*
------------------------------------------
fill *pValue with the entry in (irow,jcol)
created -- 98jun05, cca
------------------------------------------
*/
void
DenseMtx_realEntry (
DenseMtx *mtx,
int irow,
int jcol,
double *pValue
) ;
/*
----------------------------------------------------
fill *pReal and *pImag with the entry in (irow,jcol)
created -- 98jun05, cca
----------------------------------------------------
*/
void
DenseMtx_complexEntry (
DenseMtx *mtx,
int irow,
int jcol,
double *pReal,
double *pImag
) ;
/*
------------------------------
set entry (irow,jcol) to value
created -- 98jun05, cca
------------------------------
*/
void
DenseMtx_setRealEntry (
DenseMtx *mtx,
int irow,
int jcol,
double value
) ;
/*
------------------------------------
set entry (irow,jcol) to (real,imag)
created -- 98jun05, cca
------------------------------------
*/
void
DenseMtx_setComplexEntry (
DenseMtx *mtx,
int irow,
int jcol,
double real,
double imag
) ;
/*
----------------------------------------------------------
purpose -- fill *prowent with the base address of row irow
return values --
1 -- normal return
-1 -- mtx is NULL
-2 -- invalid type for mtx
-3 -- irow is invalid
-4 -- prowent is NULL
created -- 98nov11, cca
----------------------------------------------------------
*/
int
DenseMtx_row (
DenseMtx *mtx,
int irow,
double **prowent
) ;
/*
-------------------------------------------------------------
purpose -- fill *pcolent with the base address of column jcol
return values --
1 -- normal return
-1 -- mtx is NULL
-2 -- invalid type for mtx
-3 -- jcol is invalid
-4 -- pcolent is NULL
created -- 98nov11, cca
-------------------------------------------------------------
*/
int
DenseMtx_column (
DenseMtx *mtx,
int jcol,
double **pcolent
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------
return the number of bytes needed for an object of this size
created -- 98may02, cca
------------------------------------------------------------
*/
int
DenseMtx_nbytesNeeded (
int type,
int nrow,
int ncol
) ;
/*
----------------------------------------------------------------
return the number of bytes in the workspace owned by this object
created -- 98may02, cca
----------------------------------------------------------------
*/
int
DenseMtx_nbytesInWorkspace (
DenseMtx *mtx
) ;
/*
-------------------------------------------------------------
set the number of bytes in the workspace owned by this object
created -- 98may02, cca
-------------------------------------------------------------
*/
void
DenseMtx_setNbytesInWorkspace (
DenseMtx *mtx,
int nbytes
) ;
/*
---------------------------------------
purpose -- set the fields of the object
created -- 98may02, cca
---------------------------------------
*/
void
DenseMtx_setFields (
DenseMtx *mtx,
int type,
int rowid,
int colid,
int nrow,
int ncol,
int inc1,
int inc2
) ;
/*
----------------------------
purpose -- basic initializer
created -- 98may02, cca
----------------------------
*/
void
DenseMtx_init (
DenseMtx *mtx,
int type,
int rowid,
int colid,
int nrow,
int ncol,
int inc1,
int inc2
) ;
/*
---------------------------------------------------------
purpose -- initialize the object from its working storage
used when the object is a MPI message
created -- 98may02, cca
---------------------------------------------------------
*/
void
DenseMtx_initFromBuffer (
DenseMtx *mtx
) ;
/*
------------------------------------
purpose -- initializer with pointers
created -- 98may02, cca
------------------------------------
*/
void
DenseMtx_initWithPointers (
DenseMtx *mtx,
int type,
int rowid,
int colid,
int nrow,
int ncol,
int inc1,
int inc2,
int *rowind,
int *colind,
double *entries
) ;
/*
-----------------------------------
this method initializes a A2 object
to point into the entries
created -- 98may02, cca
-----------------------------------
*/
void
DenseMtx_setA2 (
DenseMtx *mtx,
A2 *a2
) ;
/*
----------------------------------------------------------------
purpose -- initialize as a submatrix of another DenseMtx object.
B = A(firstrow:lastrow, firstcol:lastcol)
note, B only points into the storage of A.
return values --
1 -- normal return
-1 -- B is NULL
-2 -- A is NULL
-3 -- A has invalid type
-4 -- requested rows are invalid
-5 -- requested columns are invalid
created -- 98nov11, cca
----------------------------------------------------------------
*/
int
DenseMtx_initAsSubmatrix (
DenseMtx *B,
DenseMtx *A,
int firstrow,
int lastrow,
int firstcol,
int lastcol
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in IO.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------
purpose -- to read in the object from a file
input --
fn -- filename, must be *.densemtxb or *.densemtxf
return value -- 1 if success, 0 if failure
created -- 98aug13
-----------------------------------------------------------
*/
int
DenseMtx_readFromFile (
DenseMtx *mtx,
char *fn
) ;
/*
--------------------------------------------------
purpose -- to read an object from a formatted file
return value -- 1 if success, 0 if failure
created -- 98aug13
--------------------------------------------------
*/
int
DenseMtx_readFromFormattedFile (
DenseMtx *mtx,
FILE *fp
) ;
/*
-----------------------------------------------
purpose -- to read an object from a binary file
return value -- 1 if success, 0 if failure
created -- 98aug13
-----------------------------------------------
*/
int
DenseMtx_readFromBinaryFile (
DenseMtx *mtx,
FILE *fp
) ;
/*
---------------------------------------
purpose -- to write an object to a file
input --
fn -- filename
*.densemtxb -- binary
*.densemtxf -- formatted
anything else -- for human eye
error return --
1 -- normal return
-1 -- mtx is NULL
-2 -- fn is NULL
-3 -- unable to open file
created -- 98aug13
---------------------------------------
*/
int
DenseMtx_writeToFile (
DenseMtx *mtx,
char *fn
) ;
/*
-------------------------------------------------
purpose -- to write an object to a formatted file
return value --
1 -- normal return
-1 -- mtx is NULL
-2 -- fn is NULL
created -- 98aug13
-------------------------------------------------
*/
int
DenseMtx_writeToFormattedFile (
DenseMtx *mtx,
FILE *fp
) ;
/*
--------------------------------------------------------
purpose -- to write an adjacency object to a binary file
return value --
1 -- normal return
-1 -- mtx is NULL
-2 -- fn is NULL
created -- 98aug13
--------------------------------------------------------
*/
int
DenseMtx_writeToBinaryFile (
DenseMtx *mtx,
FILE *fp
) ;
/*
-----------------------------------------------------
purpose -- to write the object's statistics to a file
in human readable form
return value --
1 -- normal return
-1 -- mtx is NULL
-2 -- fp is NULL
created -- 98may02, cca
-----------------------------------------------------
*/
int
DenseMtx_writeStats (
DenseMtx *mtx,
FILE *fp
) ;
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
return value --
1 -- normal return
-1 -- mtx is NULL
-2 -- fp is NULL
created -- 98may02, cca
----------------------------------------
*/
int
DenseMtx_writeForHumanEye (
DenseMtx *mtx,
FILE *fp
) ;
/*
-----------------------------------------------
purpose -- to write the object to a matlab file
return value --
1 -- normal return
-1 -- mtx is NULL
-2 -- mtx is NULL
-3 -- fp is NULL
created -- 98may02, cca
-----------------------------------------------
*/
int
DenseMtx_writeForMatlab (
DenseMtx *mtx,
char *mtxname,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in permute.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------
purpose -- to permute the rows of an object
created -- 98may02, cca
-------------------------------------------
*/
void
DenseMtx_permuteRows (
DenseMtx *mtx,
IV *oldToNewIV
) ;
/*
----------------------------------------------
purpose -- to permute the columns of an object
created -- 98may02, cca
----------------------------------------------
*/
void
DenseMtx_permuteColumns (
DenseMtx *mtx,
IV *oldToNewIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in util.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------
sort the rows so the row ids are in ascending order
sort the columns so the column ids are in ascending order
created -- 98may02, cca
---------------------------------------------------------
*/
void
DenseMtx_sort (
DenseMtx *mtx
) ;
/*
-----------------------------------------------
copy row irowA from mtxA into row irowB in mtxB
created -- 98may02, cca
-----------------------------------------------
*/
void
DenseMtx_copyRow (
DenseMtx *mtxB,
int irowB,
DenseMtx *mtxA,
int irowA
) ;
/*
---------------------------------------------------------------
copy row irowA from mtxA into row irowB in mtxB
and copy row index irowB from mtxB into row index irowA of mtxA
created -- 98aug12, cca
---------------------------------------------------------------
*/
void
DenseMtx_copyRowAndIndex (
DenseMtx *mtxB,
int irowB,
DenseMtx *mtxA,
int irowA
) ;
/*
----------------------------------------------
add row irowA from mtxA into row irowB in mtxB
created -- 98aug12, cca
----------------------------------------------
*/
void
DenseMtx_addRow (
DenseMtx *mtxB,
int irowB,
DenseMtx *mtxA,
int irowA
) ;
/*
-----------------------
zero the entries
created -- 98may16, cca
-----------------------
*/
void
DenseMtx_zero (
DenseMtx *mtx
) ;
/*
------------------------
fill with random entries
created -- 98may16, cca
------------------------
*/
void
DenseMtx_fillRandomEntries (
DenseMtx *mtx,
Drand *drand
) ;
/*
-----------------------------------
compute three checksums
sums[0] = sum of row indices
sums[1] = sum of columns indices
sums[2] = sum of entry magnitudes
created -- 98may16, cca
-----------------------------------
*/
void
DenseMtx_checksums (
DenseMtx *mtx,
double sums[]
) ;
/*
-------------------------------------------
return the maximum magnitude of the entries
created -- 98may15, cca
-------------------------------------------
*/
double
DenseMtx_maxabs (
DenseMtx *mtx
) ;
/*
--------------------------------------------
subtract one matrix from another, B := B - A
created -- 98may25, cca
--------------------------------------------
*/
void
DenseMtx_sub (
DenseMtx *mtxB,
DenseMtx *mtxA
) ;
/*
----------------------------------------------------
purpose -- to copy a row of the matrix into a vector
irow -- local row id
vec -- double vector to receive the row entries
created -- 98jul31, cca
----------------------------------------------------
*/
void
DenseMtx_copyRowIntoVector (
DenseMtx *mtx,
int irow,
double *vec
) ;
/*
----------------------------------------------------
purpose -- to copy a row of the matrix into a vector
irow -- local row id
vec -- double vector to supply the row entries
created -- 98jul31, cca
----------------------------------------------------
*/
void
DenseMtx_copyVectorIntoRow (
DenseMtx *mtx,
int irow,
double *vec
) ;
/*
----------------------------------------------------
purpose -- to add a row of the matrix into a vector
irow -- local row id
vec -- double vector to supply the row entries
created -- 98aug12, cca
----------------------------------------------------
*/
void
DenseMtx_addVectorIntoRow (
DenseMtx *mtx,
int irow,
double *vec
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in scale.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------
purpose -- to scale a dense matrix object by a scalar
A := alpha * A ;
return values ---
1 -- normal return
-1 -- A is NULL
-2 -- A has invalid type
-3 -- alpha is NULL
created -- 98nov06, cca
-----------------------------------------------------
*/
int
DenseMtx_scale (
DenseMtx *A,
double alpha[]
) ;
/*--------------------------------------------------------------------*/
int inc2,
int *rowind,
int *colind,
double *entries
) ;
/*
-----------------------------------
this method initializes a A2 object
to point into the entries
created -- 98may02, cca
-----------------------------------
*/
void
DenseMtx_setA2 (
DenseMtx *mtx,
A2 *a2
) ;
DenseMtx/makefile 0100644 0002055 0007177 00000000141 06636223563 0015327 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd doc ; make clean
DenseMtx/src/makefile 0100644 0002055 0007177 00000001061 06636022355 0016114 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = DenseMtx
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(init.o) \
$(OBJ).a(initAsSubmtx.o) \
$(OBJ).a(instance.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(permute.o) \
$(OBJ).a(scale.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
DenseMtx/src/makeGlobalLib 0100644 0002055 0007177 00000000710 06625602011 0017013 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = DenseMtx
SRC = basics.c \
init.c \
initAsSubmtx.c \
instance.c \
IO.c \
permute.c \
scale.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
DenseMtx/src/IO.c 0100644 0002055 0007177 00000043154 06616713765 0015112 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../DenseMtx.h"
static const char *suffixb = ".densemtxb" ;
static const char *suffixf = ".densemtxf" ;
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- to read in the object from a file
input --
fn -- filename, must be *.densemtxb or *.densemtxf
return value -- 1 if success, 0 if failure
created -- 98aug13
-----------------------------------------------------------
*/
int
DenseMtx_readFromFile (
DenseMtx *mtx,
char *fn
) {
FILE *fp ;
int fnlength, rc = 0, sulength ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || fn == NULL ) {
fprintf(stderr, "\n error in DenseMtx_readFromFile(%p,%s)"
"\n bad input", mtx, fn) ;
return(0) ;
}
/*
-------------
read the file
-------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "rb")) == NULL ) {
fprintf(stderr, "\n error in DenseMtx_readFromFile()"
"\n unable to open file %s", fn) ;
} else {
rc = DenseMtx_readFromBinaryFile(mtx, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "r")) == NULL ) {
fprintf(stderr, "\n error in DenseMtx_readFromFile()"
"\n unable to open file %s", fn) ;
} else {
rc = DenseMtx_readFromFormattedFile(mtx, fp) ;
fclose(fp) ;
}
} else {
fprintf(stderr, "\n error in DenseMtx_readFromFile()"
"\n bad DenseMtx file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
fn, suffixb, suffixf) ;
rc = 0 ;
}
} else {
fprintf(stderr,
"\n error in DenseMtx_readFromFile()"
"\n bad DenseMtx file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
fn, suffixb, suffixf) ;
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
purpose -- to read an object from a formatted file
return value -- 1 if success, 0 if failure
created -- 98aug13
--------------------------------------------------
*/
int
DenseMtx_readFromFormattedFile (
DenseMtx *mtx,
FILE *fp
) {
int rc, size ;
int itemp[7] ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || fp == NULL ) {
fprintf(stderr, "\n error in DenseMtx_readFromFormattedFile(%p,%p)"
"\n bad input", mtx, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
DenseMtx_clearData(mtx) ;
/*
--------------------------------------------
read in the seven scalar parameters:
type, rowid, colid, nrow, ncol, inc1, inc2
--------------------------------------------
*/
if ( (rc = IVfscanf(fp, 7, itemp)) != 7 ) {
fprintf(stderr, "\n error in DenseMtx_readFromFormattedFile()"
"\n %d items of %d read\n", rc, 7) ;
return(0) ;
}
/*
---------------------
initialize the object
---------------------
*/
DenseMtx_init(mtx, itemp[0], itemp[1], itemp[2],
itemp[3], itemp[4], itemp[5], itemp[6]) ;
/*
---------------------------
read in the rowind[] vector
---------------------------
*/
if ( (size = mtx->nrow) > 0 ) {
if ( (rc = IVfscanf(fp, size, mtx->rowind)) != size ) {
fprintf(stderr, "\n error in DenseMtx_readFromFormattedFile()"
"\n %d items of %d read for rowind\n", rc, size) ;
return(0) ;
}
}
/*
---------------------------
read in the colind[] vector
---------------------------
*/
if ( (size = mtx->ncol) > 0 ) {
if ( (rc = IVfscanf(fp, size, mtx->colind)) != size ) {
fprintf(stderr, "\n error in DenseMtx_readFromFormattedFile()"
"\n %d items of %d read for colind\n", rc, size) ;
return(0) ;
}
}
/*
----------------------------
read in the entries[] vector
----------------------------
*/
if ( (size = mtx->nrow*mtx->ncol) > 0 ) {
if ( DENSEMTX_IS_REAL(mtx) ) {
if ( (rc = DVfscanf(fp, size, mtx->entries)) != size ) {
fprintf(stderr, "\n error in DenseMtx_readFromFormattedFile()"
"\n %d items of %d read for entries\n", rc, size) ;
return(0) ;
}
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
if ( (rc = DVfscanf(fp, 2*size, mtx->entries)) != 2*size ) {
fprintf(stderr, "\n error in DenseMtx_readFromFormattedFile()"
"\n %d items of %d read for entries\n", rc, 2*size) ;
return(0) ;
}
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
purpose -- to read an object from a binary file
return value -- 1 if success, 0 if failure
created -- 98aug13
-----------------------------------------------
*/
int
DenseMtx_readFromBinaryFile (
DenseMtx *mtx,
FILE *fp
) {
int rc, size ;
int itemp[7] ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || fp == NULL ) {
fprintf(stderr,
"\n fatal error in DenseMtx_readFromBinaryFile(%p,%p)"
"\n bad input", mtx, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
DenseMtx_clearData(mtx) ;
/*
--------------------------------------------
read in the seven scalar parameters:
type, rowid, colid, nrow, ncol, inc1, inc2
--------------------------------------------
*/
if ( (rc = fread((char *) itemp, sizeof(int), 7, fp)) != 7 ) {
fprintf(stderr, "\n error in DenseMtx_readFromBinaryFile()"
"\n %d items of %d read\n", rc, 7) ;
return(0) ;
}
/*
---------------------
initialize the object
---------------------
*/
DenseMtx_init(mtx, itemp[0], itemp[1], itemp[2],
itemp[3], itemp[4], itemp[5], itemp[6]) ;
/*
---------------------------
read in the rowind[] vector
---------------------------
*/
if ( (size = mtx->nrow) > 0 ) {
if ( (rc = fread(mtx->rowind, sizeof(int), size, fp)) != size ) {
fprintf(stderr, "\n error in DenseMtx_readFromBinaryFile()"
"\n %d items of %d read for rowind[]\n", rc, size) ;
return(0) ;
}
}
/*
---------------------------
read in the colind[] vector
---------------------------
*/
if ( (size = mtx->ncol) > 0 ) {
if ( (rc = fread(mtx->colind, sizeof(int), size, fp)) != size ) {
fprintf(stderr, "\n error in DenseMtx_readFromBinaryFile()"
"\n %d items of %d read for colind[]\n", rc, size) ;
return(0) ;
}
}
/*
----------------------------
read in the entries[] vector
----------------------------
*/
if ( (size = mtx->nrow*mtx->ncol) > 0 ) {
if ( DENSEMTX_IS_REAL(mtx) ) {
rc = fread(mtx->entries, sizeof(double), size, fp) ;
if ( rc != size ) {
fprintf(stderr, "\n error in DenseMtx_readFromBinaryFile()"
"\n %d items of %d read for entries\n", rc, size) ;
return(0) ;
}
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
rc = fread(mtx->entries, sizeof(double), 2*size, fp) ;
if ( rc != 2*size ) {
fprintf(stderr, "\n error in DenseMtx_readFromBinaryFile()"
"\n %d items of %d read for entries\n", rc, 2*size) ;
return(0) ;
}
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------
purpose -- to write an object to a file
input --
fn -- filename
*.densemtxb -- binary
*.densemtxf -- formatted
anything else -- for human eye
error return --
1 -- normal return
-1 -- mtx is NULL
-2 -- fn is NULL
-3 -- unable to open file
created -- 98aug13
---------------------------------------
*/
int
DenseMtx_writeToFile (
DenseMtx *mtx,
char *fn
) {
FILE *fp ;
int fnlength, sulength ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeToFile(%p,%s)"
"\n mtx is NULL", mtx, fn) ;
return(-1) ;
}
if ( fn == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeToFile(%p,%s)"
"\n fn is NULL", mtx, fn) ;
return(-2) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in DenseMtx_writeToFile()"
"\n unable to open file %s", fn) ;
return(-3) ;
} else {
DenseMtx_writeToBinaryFile(mtx, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "w")) == NULL ) {
fprintf(stderr, "\n error in DenseMtx_writeToFile()"
"\n unable to open file %s", fn) ;
return(-3) ;
} else {
DenseMtx_writeToFormattedFile(mtx, fp) ;
fclose(fp) ;
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in DenseMtx_writeToFile()"
"\n unable to open file %s", fn) ;
return(-3) ;
} else {
DenseMtx_writeForHumanEye(mtx, fp) ;
fclose(fp) ;
}
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in DenseMtx_writeToFile()"
"\n unable to open file %s", fn) ;
return(-3) ;
} else {
DenseMtx_writeForHumanEye(mtx, fp) ;
fclose(fp) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to write an object to a formatted file
return value --
1 -- normal return
-1 -- mtx is NULL
-2 -- fn is NULL
created -- 98aug13
-------------------------------------------------
*/
int
DenseMtx_writeToFormattedFile (
DenseMtx *mtx,
FILE *fp
) {
int size ;
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeToFormattedFile()"
"\n mtx is NULL") ;
return(-1) ;
}
if ( fp == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeToFormattedFile()"
"\n fp is NULL") ;
return(-2) ;
}
fprintf(fp, "\n %d %d %d %d %d %d %d",
mtx->type, mtx->rowid, mtx->colid,
mtx->nrow, mtx->ncol, mtx->inc1, mtx->inc2) ;
if ( (size = mtx->nrow) > 0 && mtx->rowind != NULL ) {
IVfprintf(fp, size, mtx->rowind) ;
}
if ( (size = mtx->ncol) > 0 && mtx->colind != NULL ) {
IVfprintf(fp, size, mtx->colind) ;
}
if ( (size = mtx->nrow*mtx->ncol) > 0 && mtx->entries != NULL ) {
if ( DENSEMTX_IS_REAL(mtx) ) {
DVfprintf(fp, size, mtx->entries) ;
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
DVfprintf(fp, 2*size, mtx->entries) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- to write an adjacency object to a binary file
return value --
1 -- normal return
-1 -- mtx is NULL
-2 -- fn is NULL
created -- 98aug13
--------------------------------------------------------
*/
int
DenseMtx_writeToBinaryFile (
DenseMtx *mtx,
FILE *fp
) {
int size ;
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeToBinaryFile()"
"\n mtx is NULL") ;
return(-1) ;
}
if ( fp == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeToBinaryFile()"
"\n fp is NULL") ;
return(-2) ;
}
fwrite((void *) &mtx->type, sizeof(int), 1, fp) ;
fwrite((void *) &mtx->rowid, sizeof(int), 1, fp) ;
fwrite((void *) &mtx->colid, sizeof(int), 1, fp) ;
fwrite((void *) &mtx->nrow, sizeof(int), 1, fp) ;
fwrite((void *) &mtx->ncol, sizeof(int), 1, fp) ;
fwrite((void *) &mtx->inc1, sizeof(int), 1, fp) ;
fwrite((void *) &mtx->inc2, sizeof(int), 1, fp) ;
if ( (size = mtx->nrow) > 0 && mtx->rowind != NULL ) {
fwrite((void *) mtx->rowind, sizeof(int), size, fp) ;
}
if ( (size = mtx->ncol) > 0 && mtx->colind != NULL ) {
fwrite((void *) mtx->colind, sizeof(int), size, fp) ;
}
if ( (size = mtx->nrow*mtx->ncol) > 0 && mtx->entries != NULL ) {
if ( DENSEMTX_IS_REAL(mtx) ) {
fwrite((void *) mtx->entries, sizeof(double), size, fp) ;
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
fwrite((void *) mtx->entries, sizeof(double), 2*size, fp) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
purpose -- to write the object's statistics to a file
in human readable form
return value --
1 -- normal return
-1 -- mtx is NULL
-2 -- fp is NULL
created -- 98may02, cca
-----------------------------------------------------
*/
int
DenseMtx_writeStats (
DenseMtx *mtx,
FILE *fp
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeStats()"
"\n mtx is NULL") ;
return(-1) ;
}
if ( fp == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeStats()"
"\n fp is NULL") ;
return(-2) ;
}
fprintf(fp, "\n DenseMtx object at address %p", mtx) ;
switch ( mtx->type ) {
case SPOOLES_REAL :
fprintf(fp, ", real entries") ;
break ;
case SPOOLES_COMPLEX :
fprintf(fp, ", complex entries") ;
break ;
default :
fprintf(fp, ", unknown entries type") ;
break ;
}
fprintf(fp, "\n row id = %d, col id = %d"
"\n nrow = %d, ncol = %d, inc1 = %d, inc2 = %d",
mtx->rowid, mtx->colid,
mtx->nrow, mtx->ncol, mtx->inc1, mtx->inc2) ;
fprintf(fp, "\n rowind = %p, colind = %p, entries = %p",
mtx->rowind, mtx->colind, mtx->entries) ;
fprintf(fp, ", base = %p", DV_entries(&mtx->wrkDV)) ;
fprintf(fp,
"\n rowind - base = %d, colind - base = %d, entries - base = %d",
mtx->rowind - (int *) DV_entries(&mtx->wrkDV),
mtx->colind - (int *) DV_entries(&mtx->wrkDV),
mtx->entries - DV_entries(&mtx->wrkDV)) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
return value --
1 -- normal return
-1 -- mtx is NULL
-2 -- fp is NULL
created -- 98may02, cca
----------------------------------------
*/
int
DenseMtx_writeForHumanEye (
DenseMtx *mtx,
FILE *fp
) {
A2 a2 ;
int ierr, ncol, nrow ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeForHumanEye()"
"\n mtx is NULL\n") ;
return(-1) ;
}
if ( fp == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeForHumanEye()"
"\n mtx is NULL\n") ;
return(-2) ;
}
DenseMtx_writeStats(mtx, fp) ;
DenseMtx_rowIndices(mtx, &nrow, &rowind) ;
if ( nrow > 0 && rowind != NULL ) {
fprintf(fp, "\n mtx's row indices at %p", rowind) ;
IVfp80(fp, nrow, rowind, 80, &ierr) ;
}
DenseMtx_columnIndices(mtx, &ncol, &colind) ;
if ( ncol > 0 && colind != NULL ) {
fprintf(fp, "\n mtx's column indices at %p", colind) ;
IVfp80(fp, ncol, colind, 80, &ierr) ;
}
if ( nrow > 0 && ncol > 0 ) {
A2_setDefaultFields(&a2) ;
DenseMtx_setA2(mtx, &a2) ;
A2_writeForHumanEye(&a2, fp) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
purpose -- to write the object to a matlab file
return value --
1 -- normal return
-1 -- mtx is NULL
-2 -- mtx is NULL
-3 -- fp is NULL
created -- 98may02, cca
-----------------------------------------------
*/
int
DenseMtx_writeForMatlab (
DenseMtx *mtx,
char *mtxname,
FILE *fp
) {
double *entries ;
int inc1, inc2, irow, jcol, ncol, nrow ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeForMatlab()"
"\n mtx is NULL\n") ;
return(-1) ;
}
if ( mtxname == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeForMatlab()"
"\n mtxname is NULL\n") ;
return(-2) ;
}
if ( fp == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_writeForMatlab()"
"\n fp is NULL\n") ;
return(-3) ;
}
DenseMtx_rowIndices(mtx, &nrow, &rowind) ;
DenseMtx_columnIndices(mtx, &ncol, &colind) ;
DenseMtx_dimensions(mtx, &nrow, &ncol) ;
inc1 = DenseMtx_rowIncrement(mtx) ;
inc2 = DenseMtx_columnIncrement(mtx) ;
entries = DenseMtx_entries(mtx) ;
if ( DENSEMTX_IS_REAL(mtx) ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
fprintf(fp, "\n %s(%d,%d) = %24.16e ;",
mtxname, rowind[irow]+1, colind[jcol]+1,
entries[irow*inc1+jcol*inc2]) ;
}
}
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
for ( jcol = 0 ; jcol < ncol ; jcol++ ) {
for ( irow = 0 ; irow < nrow ; irow++ ) {
fprintf(fp, "\n %s(%d,%d) = %24.16e + %24.16e*i ;",
mtxname, rowind[irow]+1, colind[jcol]+1,
entries[2*(irow*inc1+jcol*inc2)],
entries[2*(irow*inc1+jcol*inc2)+1]) ;
}
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
to write an object to a file
input --
fn -- filename
*.densemtxb -- binary
*.densemtxf -- formatted
anything else -- for human eye
error return --
1 -- normal return
-1 -- mtx is NULL
-2 -- fn is NULL
-3 -- unable to open file
created -- 98aug13
---------------------------------------
*/
int
DenseMtx_writeToFile (
DenseMtx *mtxDenseMtx/src/basics.c 0100644 0002055 0007177 00000004526 06560406443 0016035 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../DenseMtx.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------
simplest constructor
created -- 98may02, cca
-----------------------
*/
DenseMtx *
DenseMtx_new (
void
) {
DenseMtx *mtx ;
ALLOCATE(mtx, struct _DenseMtx, 1) ;
DenseMtx_setDefaultFields(mtx) ;
return(mtx) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 98may02, cca
-----------------------
*/
void
DenseMtx_setDefaultFields (
DenseMtx *mtx
) {
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_setDefaultFields(%p)"
"\n bad input", mtx) ;
exit(-1) ;
}
mtx->type = SPOOLES_REAL ;
mtx->rowid = -1 ;
mtx->colid = -1 ;
mtx->nrow = 0 ;
mtx->ncol = 0 ;
mtx->inc1 = 0 ;
mtx->inc2 = 0 ;
mtx->rowind = NULL ;
mtx->colind = NULL ;
mtx->entries = NULL ;
DV_setDefaultFields(&mtx->wrkDV) ;
mtx->next = NULL ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98may02, cca
--------------------------------------------------
*/
void
DenseMtx_clearData (
DenseMtx *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_clearData(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
/*
------------------------
free the working storage
------------------------
*/
DV_clearData(&mtx->wrkDV) ;
/*
----------------------
set the default fields
----------------------
*/
DenseMtx_setDefaultFields(mtx) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
destructor, free's the object and its data
created -- 98may02, cca
------------------------------------------
*/
void
DenseMtx_free (
DenseMtx *mtx
) {
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_free(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
DenseMtx_clearData(mtx) ;
FREE(mtx) ;
return ; }
/*--------------------------------------------------------------------*/
DenseMtx/src/init.c 0100644 0002055 0007177 00000022476 06604717734 0015547 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../DenseMtx.h"
#define MYDEBUG 1
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
return the number of bytes needed for an object of this size
created -- 98may02, cca
------------------------------------------------------------
*/
int
DenseMtx_nbytesNeeded (
int type,
int nrow,
int ncol
) {
int nbytes, ndouble, nint ;
/*
---------------
check the input
---------------
*/
if ( nrow < 0 || ncol < 0 ) {
fprintf(stderr,
"\n fatal error in DenseMtx_nbytesNeeded(%d,%d,%d)"
"\n bad input\n", type, nrow, ncol) ;
exit(-1) ;
}
nint = 7 + nrow + ncol ;
if ( type == SPOOLES_REAL ) {
ndouble = nrow*ncol ;
} else if ( type == SPOOLES_COMPLEX ) {
ndouble = 2*nrow*ncol ;
} else {
fprintf(stderr,
"\n fatal error in DenseMtx_nbytesNeeded(%d,%d,%d)"
"\n bad type %d\n", type, nrow, ncol, type) ;
exit(-1) ;
}
if ( sizeof(int) == sizeof(double) ) {
nbytes = nint*sizeof(int) + ndouble*sizeof(double) ;
} else if ( 2*sizeof(int) == sizeof(double) ) {
nbytes = ((nint + 1)/2 + ndouble)*sizeof(double) ;
} else {
fprintf(stderr, "\n error in DenseMtx_nbytesNeeded(%d,%d)"
"\n sizeof(int) = %d, sizeof(double) = %d",
nrow, ncol, sizeof(int), sizeof(double)) ;
exit(-1) ;
}
return(nbytes) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
return the number of bytes in the workspace owned by this object
created -- 98may02, cca
----------------------------------------------------------------
*/
int
DenseMtx_nbytesInWorkspace (
DenseMtx *mtx
) {
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_nbytesInWorkspace(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(sizeof(double)*DV_maxsize(&mtx->wrkDV)) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
set the number of bytes in the workspace owned by this object
created -- 98may02, cca
-------------------------------------------------------------
*/
void
DenseMtx_setNbytesInWorkspace (
DenseMtx *mtx,
int nbytes
) {
if ( mtx == NULL ) {
fprintf(stderr,
"\n fatal error in DenseMtx_setNbytesInWorkspace(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
DV_setSize(&mtx->wrkDV, nbytes/sizeof(double)) ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------
purpose -- set the fields of the object
created -- 98may02, cca
---------------------------------------
*/
void
DenseMtx_setFields (
DenseMtx *mtx,
int type,
int rowid,
int colid,
int nrow,
int ncol,
int inc1,
int inc2
) {
double *dbuffer ;
int *ibuffer ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || nrow < 0 || ncol < 0
|| !((inc1 == ncol && inc2 == 1) || (inc1 == 1 && inc2 == nrow)) ) {
fprintf(stderr,
"\n fatal error in DenseMtx_setFields(%p,%d,%d,%d,%d,%d,%d)"
"\n bad input\n",
mtx, rowid, colid, nrow, ncol, inc1, inc2) ;
exit(-1) ;
}
dbuffer = DV_entries(&mtx->wrkDV) ;
ibuffer = (int *) dbuffer ;
/*
---------------------
set the scalar fields
---------------------
*/
mtx->type = ibuffer[0] = type ;
mtx->rowid = ibuffer[1] = rowid ;
mtx->colid = ibuffer[2] = colid ;
mtx->nrow = ibuffer[3] = nrow ;
mtx->ncol = ibuffer[4] = ncol ;
mtx->inc1 = ibuffer[5] = inc1 ;
mtx->inc2 = ibuffer[6] = inc2 ;
/*
-------------------
set up the pointers
-------------------
*/
mtx->rowind = ibuffer + 7 ;
mtx->colind = mtx->rowind + nrow ;
if ( sizeof(int) == sizeof(double) ) {
mtx->entries = dbuffer + 7 + nrow + ncol ;
} else if ( 2*sizeof(int) == sizeof(double) ) {
mtx->entries = dbuffer + (8 + nrow + ncol)/2 ;
}
/*
fprintf(stdout,
"\n rowind - ibuffer = %d"
"\n colind - rowind = %d"
"\n entries - dbuffer = %d",
mtx->rowind - ibuffer,
mtx->colind - mtx->rowind,
mtx->entries - dbuffer) ;
*/
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------
purpose -- basic initializer
created -- 98may02, cca
----------------------------
*/
void
DenseMtx_init (
DenseMtx *mtx,
int type,
int rowid,
int colid,
int nrow,
int ncol,
int inc1,
int inc2
) {
int nbytes ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || nrow < 0 || ncol < 0
|| !((inc1 == ncol && inc2 == 1) || (inc1 == 1 && inc2 == nrow)) ) {
fprintf(stderr,
"\n fatal error in DenseMtx_init(%p,%d,%d,%d,%d,%d,%d)"
"\n bad input\n",
mtx, rowid, colid, nrow, ncol, inc1, inc2) ;
exit(-1) ;
}
switch ( type ) {
case SPOOLES_REAL :
case SPOOLES_COMPLEX :
break ;
default :
fprintf(stderr,
"\n fatal error in DenseMtx_init(%p,%d,%d,%d,%d,%d,%d,%d)"
"\n bad type %d\n",
mtx, type, rowid, colid, nrow, ncol, inc1, inc2, type) ;
exit(-1) ;
break ;
}
/*
-------------------------------------------------------
get and set the number of bytes needed in the workspace
-------------------------------------------------------
*/
nbytes = DenseMtx_nbytesNeeded(type, nrow, ncol) ;
DenseMtx_setNbytesInWorkspace(mtx, nbytes) ;
/*
--------------
set the fields
--------------
*/
DenseMtx_setFields(mtx, type, rowid, colid, nrow, ncol, inc1, inc2) ;
if ( nrow > 0 ) {
IVramp(nrow, mtx->rowind, 0, 1) ;
}
if ( ncol > 0 ) {
IVramp(ncol, mtx->colind, 0, 1) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
purpose -- initialize the object from its working storage
used when the object is a MPI message
created -- 98may02, cca
---------------------------------------------------------
*/
void
DenseMtx_initFromBuffer (
DenseMtx *mtx
) {
int *ibuffer ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_initFromBuffer(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
ibuffer = (int *) DV_entries(&mtx->wrkDV) ;
DenseMtx_setFields(mtx, ibuffer[0], ibuffer[1], ibuffer[2],
ibuffer[3], ibuffer[4], ibuffer[5], ibuffer[6]) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
purpose -- initializer with pointers
created -- 98may02, cca
------------------------------------
*/
void
DenseMtx_initWithPointers (
DenseMtx *mtx,
int type,
int rowid,
int colid,
int nrow,
int ncol,
int inc1,
int inc2,
int *rowind,
int *colind,
double *entries
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || nrow <= 0 || ncol <= 0 || inc1 < 0 || inc2 < 0
|| (inc1 != 1 && inc2 != 1)
|| entries == NULL || colind == NULL || rowind == NULL ) {
fprintf(stderr,
"\n fatal error in DenseMtx_initWithPointers()"
"\n mtx = %p, rowid = %d, colid = %d"
"\n nrow = %d, ncol = %d, inc1 = %d, inc2 = %d"
"\n rowind = %p, colind = %p, entries = %p "
"\n bad input\n",
mtx, rowid, colid, nrow, ncol, inc1, inc2,
rowind, colind, entries) ;
exit(-1) ;
}
switch ( type ) {
case SPOOLES_REAL :
case SPOOLES_COMPLEX :
break ;
default :
fprintf(stderr, "\n fatal error in DenseMtx_initWithPointers()"
"\n bad type %d\n", type) ;
break ;
}
/*
---------------------
set the scalar fields
---------------------
*/
mtx->type = type ;
mtx->rowid = rowid ;
mtx->colid = colid ;
mtx->nrow = nrow ;
mtx->ncol = ncol ;
mtx->inc1 = inc1 ;
mtx->inc2 = inc2 ;
/*
--------------------------
set up the working storage
--------------------------
*/
mtx->rowind = rowind ;
mtx->colind = colind ;
mtx->entries = entries ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------
this method initializes a A2 object
to point into the entries
created -- 98may02, cca
-----------------------------------
*/
void
DenseMtx_setA2 (
DenseMtx *mtx,
A2 *a2
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || a2 == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_setZA2(%p,%p)"
"\n bad input\n", mtx, a2) ;
exit(-1) ;
}
/*
if ( DENSEMTX_IS_REAL(mtx) ) {
A2_init(a2, SPOOLES_REAL, mtx->nrow, mtx->ncol, mtx->inc1, mtx->inc2,
mtx->entries) ;
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
A2_init(a2, SPOOLES_COMPLEX, mtx->nrow, mtx->ncol, mtx->inc1, mtx->inc2,
mtx->entries) ;
}
*/
A2_init(a2, mtx->type, mtx->nrow, mtx->ncol,
mtx->inc1, mtx->inc2, mtx->entries) ;
return ; }
/*--------------------------------------------------------------------*/
---
*/
mtx->rowind = ibuffer + 7 ;
mtx->colind = mtx->rowind + nrow ;
if ( sizeof(int) == sizeof(double) ) {
mtx->entries = dbuffer + 7 + nrow + ncol ;
} else if ( 2*sizeof(int) == sizeof(douDenseMtx/src/initAsSubmtx.c 0100644 0002055 0007177 00000004462 06622343630 0017217 0 ustar 00cleve compmath 0000040 0000006 /* initAsSubmtx.c */
#include "../DenseMtx.h"
#define MYDEBUG 1
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose -- initialize as a submatrix of another DenseMtx object.
B = A(firstrow:lastrow, firstcol:lastcol)
note, B only points into the storage of A.
return values --
1 -- normal return
-1 -- B is NULL
-2 -- A is NULL
-3 -- A has invalid type
-4 -- requested rows are invalid
-5 -- requested columns are invalid
created -- 98nov11, cca
----------------------------------------------------------------
*/
int
DenseMtx_initAsSubmatrix (
DenseMtx *B,
DenseMtx *A,
int firstrow,
int lastrow,
int firstcol,
int lastcol
) {
/*
---------------
check the input
---------------
*/
if ( B == NULL ) {
fprintf(stderr, "\n error in DenseMtx_initAsSubmatrix()"
"\n B is NULL\n") ;
return(-1) ;
}
if ( A == NULL ) {
fprintf(stderr, "\n error in DenseMtx_initAsSubmatrix()"
"\n A is NULL\n") ;
return(-2) ;
}
if ( A->type != SPOOLES_REAL && A->type != SPOOLES_COMPLEX ) {
fprintf(stderr, "\n error in DenseMtx_initAsSubmatrix()"
"\n invalid type %d\n", A->type) ;
return(-3) ;
}
if ( firstrow < 0 || lastrow >= A->nrow ) {
fprintf(stderr, "\n error in DenseMtx_initAsSubmatrix()"
"\n %d rows in A, firstrow is %d\n", A->nrow, firstrow) ;
return(-4) ;
}
if ( firstcol < 0 || lastcol >= A->ncol ) {
fprintf(stderr, "\n error in DenseMtx_initAsSubmatrix()"
"\n %d columns in A, firstcol is %d\n", A->ncol, firstcol) ;
return(-5) ;
}
/*
---------------------
set the scalar fields
---------------------
*/
B->type = A->type ;
B->rowid = A->rowid ;
B->colid = A->colid ;
B->nrow = lastrow - firstrow + 1 ;
B->ncol = lastcol - firstcol + 1 ;
B->inc1 = A->inc1 ;
B->inc2 = A->inc2 ;
B->rowind = A->rowind + firstrow ;
B->colind = A->colind + firstcol ;
if ( A->type == SPOOLES_REAL ) {
B->entries = A->entries + firstrow*A->inc1 + firstcol*A->inc2 ;
} else {
B->entries = A->entries + 2*(firstrow*A->inc1 + firstcol*A->inc2) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
DenseMtx/src/instance.c 0100644 0002055 0007177 00000031634 06622344463 0016377 0 ustar 00cleve compmath 0000040 0000006 /* instance.c */
#include "../DenseMtx.h"
/*--------------------------------------------------------------------*/
/*
-------------------------------
return the row id of the object
created -- 98may02, cca
-------------------------------
*/
int
DenseMtx_rowid (
DenseMtx *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_rowid(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(mtx->rowid) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------
return the column id of the object
created -- 98may02, cca
----------------------------------
*/
int
DenseMtx_colid (
DenseMtx *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_colid(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(mtx->colid) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
fill *pnrow with nrow and *pncol with ncol
created -- 98may02, cca
------------------------------------------
*/
void
DenseMtx_dimensions (
DenseMtx *mtx,
int *pnrow,
int *pncol
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || pnrow == NULL || pncol == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_dimensions(%p,%p,%p)"
"\n bad input\n", mtx, pnrow, pncol) ;
exit(-1) ;
}
*pnrow = mtx->nrow ;
*pncol = mtx->ncol ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------
return the row increment
created -- 98may02, cca
------------------------
*/
int
DenseMtx_rowIncrement (
DenseMtx *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_rowIncrement(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(mtx->inc1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------
return the column increment
created -- 98may02, cca
---------------------------
*/
int
DenseMtx_columnIncrement (
DenseMtx *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_columnIncrement(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(mtx->inc2) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------
fill *pnrow with nrow, *prowind with rowind
created -- 98may02, cca
-------------------------------------------
*/
void
DenseMtx_rowIndices (
DenseMtx *mtx,
int *pnrow,
int **prowind
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || pnrow == NULL || prowind == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_rowIndices(%p,%p,%p)"
"\n bad input\n", mtx, pnrow, prowind) ;
exit(-1) ;
}
*pnrow = mtx->nrow ;
*prowind = mtx->rowind ;
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------
fill *pncol with ncol, *pcolind with colind
created -- 98may02, cca
-------------------------------------------
*/
void
DenseMtx_columnIndices (
DenseMtx *mtx,
int *pncol,
int **pcolind
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || pncol == NULL || pcolind == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_columnIndices(%p,%p,%p)"
"\n bad input\n", mtx, pncol, pcolind) ;
exit(-1) ;
}
*pncol = mtx->ncol ;
*pcolind = mtx->colind ;
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------
return a pointer to the entries
created -- 98may02, cca
-------------------------------
*/
double *
DenseMtx_entries(
DenseMtx *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_entries(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(mtx->entries) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------
return a pointer to the workspace
created -- 98may02, cca
---------------------------------
*/
void *
DenseMtx_workspace(
DenseMtx *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_workspace(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
return(DV_entries(&mtx->wrkDV)) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
fill *pValue with the entry in (irow,jcol)
created -- 98jun05, cca
------------------------------------------
*/
void
DenseMtx_realEntry (
DenseMtx *mtx,
int irow,
int jcol,
double *pValue
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || pValue == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_realEntry()"
"\n mtx or pValue is NULL\n") ;
exit(-1) ;
}
if ( mtx->type != SPOOLES_REAL ) {
fprintf(stderr, "\n fatal error in DenseMtx_realEntry()"
"\n mtx type must be SPOOLES_REAL\n") ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->nrow ) {
fprintf(stderr, "\n fatal error in DenseMtx_realEntry()"
"\n irow = %d, mtx->nrow = %d input\n", irow, mtx->nrow) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->ncol ) {
fprintf(stderr, "\n fatal error in DenseMtx_realEntry()"
"\n jcol = %d, mtx->ncol = %d input\n", jcol, mtx->ncol) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_realEntry()"
"\n mtx->entries is NULL \n") ;
exit(-1) ;
}
*pValue = mtx->entries[irow*mtx->inc1 + jcol*mtx->inc2] ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
fill *pReal and *pImag with the entry in (irow,jcol)
created -- 98jun05, cca
----------------------------------------------------
*/
void
DenseMtx_complexEntry (
DenseMtx *mtx,
int irow,
int jcol,
double *pReal,
double *pImag
) {
int loc ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || pReal == NULL || pImag == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_complexEntry()"
"\n mtxm pReal or pImag is NULL\n") ;
exit(-1) ;
}
if ( mtx->type != SPOOLES_COMPLEX ) {
fprintf(stderr, "\n fatal error in DenseMtx_complexEntry()"
"\n mtx type must be SPOOLES_COMPLEX\n") ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->nrow ) {
fprintf(stderr, "\n fatal error in DenseMtx_complexEntry()"
"\n irow = %d, mtx->nrow = %d input\n", irow, mtx->nrow) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->ncol ) {
fprintf(stderr, "\n fatal error in DenseMtx_complexEntry()"
"\n jcol = %d, mtx->ncol = %d input\n", jcol, mtx->ncol) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_complexEntry()"
"\n mtx->entries is NULL \n") ;
exit(-1) ;
}
loc = 2*(irow*mtx->inc1 + jcol*mtx->inc2) ;
*pReal = mtx->entries[loc] ;
*pImag = mtx->entries[loc+1] ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------
set entry (irow,jcol) to value
created -- 98jun05, cca
------------------------------
*/
void
DenseMtx_setRealEntry (
DenseMtx *mtx,
int irow,
int jcol,
double value
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_setRealEntry()"
"\n mtx is NULL\n") ;
exit(-1) ;
}
if ( mtx->type != SPOOLES_REAL ) {
fprintf(stderr, "\n fatal error in DenseMtx_setRealEntry()"
"\n mtx type must be SPOOLES_REAL\n") ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->nrow ) {
fprintf(stderr, "\n fatal error in DenseMtx_setRealEntry()"
"\n irow = %d, mtx->nrow = %d input\n", irow, mtx->nrow) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->ncol ) {
fprintf(stderr, "\n fatal error in DenseMtx_setRealEntry()"
"\n jcol = %d, mtx->ncol = %d input\n", jcol, mtx->ncol) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_setRealEntry()"
"\n mtx->entries is NULL \n") ;
exit(-1) ;
}
mtx->entries[irow*mtx->inc1 + jcol*mtx->inc2] = value ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
set entry (irow,jcol) to (real,imag)
created -- 98jun05, cca
------------------------------------
*/
void
DenseMtx_setComplexEntry (
DenseMtx *mtx,
int irow,
int jcol,
double real,
double imag
) {
int loc ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_setComplexEntry()"
"\n mtx is NULL\n") ;
exit(-1) ;
}
if ( mtx->type != SPOOLES_COMPLEX ) {
fprintf(stderr, "\n fatal error in DenseMtx_setComplexEntry()"
"\n mtx type must be SPOOLES_COMPLEX\n") ;
exit(-1) ;
}
if ( irow < 0 || irow >= mtx->nrow ) {
fprintf(stderr, "\n fatal error in DenseMtx_setComplexEntry()"
"\n irow = %d, mtx->nrow = %d input\n", irow, mtx->nrow) ;
exit(-1) ;
}
if ( jcol < 0 || jcol >= mtx->ncol ) {
fprintf(stderr, "\n fatal error in DenseMtx_setComplexEntry()"
"\n jcol = %d, mtx->ncol = %d input\n", jcol, mtx->ncol) ;
exit(-1) ;
}
if ( mtx->entries == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_setComplexEntry()"
"\n mtx->entries is NULL \n") ;
exit(-1) ;
}
loc = 2*(irow*mtx->inc1 + jcol*mtx->inc2) ;
mtx->entries[loc] = real ;
mtx->entries[loc+1] = imag ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------
purpose -- fill *prowent with the base address of row irow
return values --
1 -- normal return
-1 -- mtx is NULL
-2 -- invalid type for mtx
-3 -- irow is invalid
-4 -- prowent is NULL
created -- 98nov11, cca
----------------------------------------------------------
*/
int
DenseMtx_row (
DenseMtx *mtx,
int irow,
double **prowent
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n error in DenseMtx_row()"
"\n mtx is NULL\n") ;
return(-1) ;
}
if ( mtx->type != SPOOLES_REAL && mtx->type != SPOOLES_COMPLEX ) {
fprintf(stderr, "\n error in DenseMtx_row()"
"\n invalid type %d\n", mtx->type) ;
return(-2) ;
}
if ( irow < 0 || irow >= mtx->nrow ) {
fprintf(stderr, "\n error in DenseMtx_row()"
"\n %d rows, irow = %d\n", mtx->nrow, irow) ;
return(-3) ;
}
if ( prowent == NULL ) {
fprintf(stderr, "\n error in DenseMtx_row()"
"\n prowent is NULL\n") ;
return(-4) ;
}
if ( mtx->type == SPOOLES_REAL ) {
*prowent = mtx->entries + irow*mtx->inc1 ;
} else {
*prowent = mtx->entries + 2*irow*mtx->inc1 ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
purpose -- fill *pcolent with the base address of column jcol
return values --
1 -- normal return
-1 -- mtx is NULL
-2 -- invalid type for mtx
-3 -- jcol is invalid
-4 -- pcolent is NULL
created -- 98nov11, cca
-------------------------------------------------------------
*/
int
DenseMtx_column (
DenseMtx *mtx,
int jcol,
double **pcolent
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n error in DenseMtx_column()"
"\n mtx is NULL\n") ;
return(-1) ;
}
if ( mtx->type != SPOOLES_REAL && mtx->type != SPOOLES_COMPLEX ) {
fprintf(stderr, "\n error in DenseMtx_column()"
"\n invalid type %d\n", mtx->type) ;
return(-2) ;
}
if ( jcol < 0 || jcol >= mtx->ncol ) {
fprintf(stderr, "\n error in DenseMtx_column()"
"\n %d columns, jcol = %d\n", mtx->ncol, jcol) ;
return(-3) ;
}
if ( pcolent == NULL ) {
fprintf(stderr, "\n error in DenseMtx_column()"
"\n pcolent is NULL\n") ;
return(-4) ;
}
if ( mtx->type == SPOOLES_REAL ) {
*pcolent = mtx->entries + jcol*mtx->inc2 ;
} else {
*pcolent = mtx->entries + 2*jcol*mtx->inc2 ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
heck the input
---------------
*/
if ( mtx == NULL || pnrow == NULL || prowind == NULL ) {
fprDenseMtx/src/permute.c 0100644 0002055 0007177 00000006050 06560406444 0016245 0 ustar 00cleve compmath 0000040 0000006 /* permute.c */
#include "../DenseMtx.h"
/*--------------------------------------------------------------------*/
/*
-------------------------------------------
purpose -- to permute the rows of an object
created -- 98may02, cca
-------------------------------------------
*/
void
DenseMtx_permuteRows (
DenseMtx *mtx,
IV *oldToNewIV
) {
A2 a2 ;
int ii, irow, maxnrow, nrow ;
int *oldToNew, *rowind ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || oldToNewIV == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_permuteRows(%p,%p)"
"\n bad input\n", mtx, oldToNewIV) ;
exit(-1) ;
}
DenseMtx_rowIndices(mtx, &nrow, &rowind) ;
if ( nrow <= 0 ) {
return ;
}
/*
----------------------------------------------
overwrite the old row ids with the new row ids
----------------------------------------------
*/
IV_sizeAndEntries(oldToNewIV, &maxnrow, &oldToNew) ;
for ( ii = 0 ; ii < nrow ; ii++ ) {
irow = rowind[ii] ;
if ( irow < 0 || irow >= maxnrow ) {
fprintf(stderr, "\n fatal error in DenseMtx_permuteRows(%p,%p)"
"\n irow = %d, maxnrow = %d",
mtx, oldToNewIV, irow, maxnrow) ;
exit(-1) ;
}
rowind[ii] = oldToNew[rowind[ii]] ;
}
/*
------------------------------------
now sort the rows in ascending order
------------------------------------
*/
A2_setDefaultFields(&a2) ;
DenseMtx_setA2(mtx, &a2) ;
A2_sortRowsUp(&a2, nrow, rowind) ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
purpose -- to permute the columns of an object
created -- 98may02, cca
----------------------------------------------
*/
void
DenseMtx_permuteColumns (
DenseMtx *mtx,
IV *oldToNewIV
) {
A2 a2 ;
int ii, jcol, maxncol, ncol ;
int *oldToNew, *colind ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || oldToNewIV == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_permuteColumns(%p,%p)"
"\n bad input\n", mtx, oldToNewIV) ;
exit(-1) ;
}
DenseMtx_columnIndices(mtx, &ncol, &colind) ;
if ( ncol <= 0 ) {
return ;
}
/*
----------------------------------------------------
overwrite the old column ids with the new column ids
----------------------------------------------------
*/
IV_sizeAndEntries(oldToNewIV, &maxncol, &oldToNew) ;
for ( ii = 0 ; ii < ncol ; ii++ ) {
jcol = colind[ii] ;
if ( jcol < 0 || jcol >= maxncol ) {
fprintf(stderr,
"\n fatal error in DenseMtx_permuteColumns(%p,%p)"
"\n jcol = %d, maxncol = %d",
mtx, oldToNewIV, jcol, maxncol) ;
exit(-1) ;
}
colind[ii] = oldToNew[jcol] ;
}
/*
------------------------------------
now sort the rows in ascending order
------------------------------------
*/
A2_setDefaultFields(&a2) ;
DenseMtx_setA2(mtx, &a2) ;
A2_sortColumnsUp(&a2, ncol, colind) ;
return ; }
/*--------------------------------------------------------------------*/
DenseMtx/src/scale.c 0100644 0002055 0007177 00000007210 06620677431 0015655 0 ustar 00cleve compmath 0000040 0000006 /* scale.c */
#include "../DenseMtx.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
purpose -- to scale a dense matrix object by a scalar
A := alpha * A ;
return values ---
1 -- normal return
-1 -- A is NULL
-2 -- A has invalid type
-3 -- alpha is NULL
created -- 98nov06, cca
-----------------------------------------------------
*/
int
DenseMtx_scale (
DenseMtx *A,
double alpha[]
) {
/*
---------------
check the input
---------------
*/
if ( A == NULL ) {
fprintf(stderr, "\n error in DenseMtx_scale()"
"\n A is NULL\n") ;
return(-1) ;
}
if ( A->type != SPOOLES_REAL && A->type != SPOOLES_COMPLEX ) {
fprintf(stderr, "\n error in DenseMtx_scale()"
"\n A has invalid type\n") ;
return(-2) ;
}
if ( alpha == NULL ) {
fprintf(stderr, "\n error in DenseMtx_scale()"
"\n alpha is NULL\n") ;
return(-3) ;
}
if ( A->type == SPOOLES_REAL ) {
double ralpha = alpha[0] ;
if ( ralpha == 1.0 ) {
return(1) ;
} else {
double *entries ;
int colinc, ncol, nrow, rowinc ;
entries = DenseMtx_entries(A) ;
rowinc = DenseMtx_rowIncrement(A) ;
colinc = DenseMtx_columnIncrement(A) ;
DenseMtx_dimensions(A, &nrow, &ncol) ;
if ( (rowinc == 1 && colinc == nrow)
|| (rowinc == ncol && colinc == 1) ) {
if ( ralpha == 0.0 ) {
DVzero(nrow*ncol, entries) ;
} else {
DVscale(nrow*ncol, entries, ralpha) ;
}
} else {
int ii, jj ;
if ( ralpha == 0.0 ) {
for ( jj = 0 ; jj < ncol ; jj++ ) {
for ( ii = 0 ; ii < nrow ; ii++ ) {
entries[ii*rowinc + jj*colinc] = 0.0 ;
}
}
} else {
for ( jj = 0 ; jj < ncol ; jj++ ) {
for ( ii = 0 ; ii < nrow ; ii++ ) {
entries[ii*rowinc + jj*colinc] *= ralpha ;
}
}
}
}
}
} else if ( A->type == SPOOLES_COMPLEX ) {
double ralpha = alpha[0], ialpha = alpha[1] ;
if ( ralpha == 1.0 && ialpha == 0.0 ) {
return(1) ;
} else {
double *entries ;
int colinc, ncol, nrow, rowinc ;
entries = DenseMtx_entries(A) ;
rowinc = DenseMtx_rowIncrement(A) ;
colinc = DenseMtx_columnIncrement(A) ;
DenseMtx_dimensions(A, &nrow, &ncol) ;
if ( (rowinc == 1 && colinc == nrow)
|| (rowinc == ncol && colinc == 1) ) {
if ( ralpha == 0.0 && ialpha == 0.0 ) {
ZVzero(nrow*ncol, entries) ;
} else {
ZVscale(nrow*ncol, entries, ralpha, ialpha) ;
}
} else {
if ( ralpha == 0.0 && ialpha == 0.0 ) {
int ii, jj, off ;
for ( jj = 0 ; jj < ncol ; jj++ ) {
for ( ii = 0 ; ii < nrow ; ii++ ) {
off = ii*rowinc + jj*colinc ;
entries[2*off] = 0.0 ;
entries[2*off+1] = 0.0 ;
}
}
} else {
double yi, yr ;
int ii, jj, off ;
for ( jj = 0 ; jj < ncol ; jj++ ) {
for ( ii = 0 ; ii < nrow ; ii++ ) {
off = ii*rowinc + jj*colinc ;
yr = entries[2*off] ; yi = entries[2*off+1] ;
entries[2*off] = yr * ralpha - yi * ialpha ;
entries[2*off+1] = yr * ialpha - yi * ralpha ;
}
}
}
}
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
DenseMtx/src/util.c 0100644 0002055 0007177 00000036017 06612222346 0015542 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../DenseMtx.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
sort the rows so the row ids are in ascending order
sort the columns so the column ids are in ascending order
created -- 98may02, cca
---------------------------------------------------------
*/
void
DenseMtx_sort (
DenseMtx *mtx
) {
A2 a2 ;
int ii, ncol, nrow, sortColumns, sortRows ;
int *colind, *rowind ;
/*
----------------
check the output
----------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_sort(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
DenseMtx_rowIndices(mtx, &nrow, &rowind) ;
DenseMtx_columnIndices(mtx, &ncol, &colind) ;
if ( nrow <= 0 || ncol <= 0 ) {
return ;
}
sortRows = sortColumns = 0 ;
for ( ii = 1 ; ii < nrow ; ii++ ) {
if ( rowind[ii-1] > rowind[ii] ) {
sortRows = 1 ;
break ;
}
}
for ( ii = 1 ; ii < ncol ; ii++ ) {
if ( colind[ii-1] > colind[ii] ) {
sortColumns = 1 ;
break ;
}
}
if ( sortRows == 0 && sortColumns == 0 ) {
return ;
}
A2_setDefaultFields(&a2) ;
DenseMtx_setA2(mtx, &a2) ;
if ( sortRows == 1 ) {
A2_sortRowsUp(&a2, nrow, rowind) ;
}
if ( sortColumns == 1 ) {
A2_sortColumnsUp(&a2, ncol, colind) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
copy row irowA from mtxA into row irowB in mtxB
created -- 98may02, cca
-----------------------------------------------
*/
void
DenseMtx_copyRow (
DenseMtx *mtxB,
int irowB,
DenseMtx *mtxA,
int irowA
) {
double *rowA, *rowB ;
int ii, inc2A, inc2B, iA, iB, ncol ;
/*
---------------
check the input
---------------
*/
if ( mtxB == NULL || irowB < 0 || irowB >= mtxB->nrow
|| mtxA == NULL || irowA < 0 || irowA >= mtxA->nrow
|| (ncol = mtxA->ncol) != mtxB->ncol ) {
fprintf(stderr, "\n fatal error in DenseMtx_copyRow(%p,%d,%p,%d)"
"\n bad input\n", mtxB, irowB, mtxA, irowA) ;
exit(-1) ;
}
inc2A = mtxA->inc2 ;
inc2B = mtxB->inc2 ;
/*
mtxB->rowind[irowB] = mtxA->rowind[irowA] ;
*/
if ( DENSEMTX_IS_REAL(mtxB) && DENSEMTX_IS_REAL(mtxA) ) {
rowA = mtxA->entries + irowA*mtxA->inc1 ;
rowB = mtxB->entries + irowB*mtxB->inc1 ;
for ( ii = iA = iB = 0 ; ii < ncol ; ii++, iA += inc2A, iB += inc2B){
rowB[iB] = rowA[iA] ;
}
} else if ( DENSEMTX_IS_COMPLEX(mtxB) && DENSEMTX_IS_COMPLEX(mtxA) ) {
rowA = mtxA->entries + 2*irowA*mtxA->inc1 ;
rowB = mtxB->entries + 2*irowB*mtxB->inc1 ;
for ( ii = iA = iB = 0 ; ii < ncol ; ii++, iA += inc2A, iB += inc2B){
rowB[2*iB] = rowA[2*iA] ;
rowB[2*iB+1] = rowA[2*iA+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
copy row irowA from mtxA into row irowB in mtxB
and copy row index irowB from mtxB into row index irowA of mtxA
created -- 98aug12, cca
---------------------------------------------------------------
*/
void
DenseMtx_copyRowAndIndex (
DenseMtx *mtxB,
int irowB,
DenseMtx *mtxA,
int irowA
) {
/*
---------------
check the input
---------------
*/
if ( mtxB == NULL || irowB < 0 || irowB >= mtxB->nrow
|| mtxA == NULL || irowA < 0 || irowA >= mtxA->nrow
|| mtxA->ncol != mtxB->ncol ) {
fprintf(stderr, "\n fatal error in DenseMtx_copyRow(%p,%d,%p,%d)"
"\n bad input\n", mtxB, irowB, mtxA, irowA) ;
exit(-1) ;
}
DenseMtx_copyRow(mtxB, irowB, mtxA, irowA) ;
mtxB->rowind[irowB] = mtxA->rowind[irowA] ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
add row irowA from mtxA into row irowB in mtxB
created -- 98aug12, cca
----------------------------------------------
*/
void
DenseMtx_addRow (
DenseMtx *mtxB,
int irowB,
DenseMtx *mtxA,
int irowA
) {
double *rowA, *rowB ;
int ii, inc2A, inc2B, iA, iB, ncol ;
/*
---------------
check the input
---------------
*/
if ( mtxB == NULL || irowB < 0 || irowB >= mtxB->nrow
|| mtxA == NULL || irowA < 0 || irowA >= mtxA->nrow
|| (ncol = mtxA->ncol) != mtxB->ncol ) {
fprintf(stderr, "\n fatal error in DenseMtx_addRow(%p,%d,%p,%d)"
"\n bad input\n", mtxB, irowB, mtxA, irowA) ;
exit(-1) ;
}
inc2A = mtxA->inc2 ;
inc2B = mtxB->inc2 ;
if ( DENSEMTX_IS_REAL(mtxB) && DENSEMTX_IS_REAL(mtxA) ) {
rowA = mtxA->entries + irowA*mtxA->inc1 ;
rowB = mtxB->entries + irowB*mtxB->inc1 ;
for ( ii = iA = iB = 0 ; ii < ncol ; ii++, iA += inc2A, iB += inc2B){
rowB[iB] += rowA[iA] ;
}
} else if ( DENSEMTX_IS_COMPLEX(mtxB) && DENSEMTX_IS_COMPLEX(mtxA) ) {
rowA = mtxA->entries + 2*irowA*mtxA->inc1 ;
rowB = mtxB->entries + 2*irowB*mtxB->inc1 ;
for ( ii = iA = iB = 0 ; ii < ncol ; ii++, iA += inc2A, iB += inc2B){
rowB[2*iB] += rowA[2*iA] ;
rowB[2*iB+1] += rowA[2*iA+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
zero the entries
created -- 98may16, cca
-----------------------
*/
void
DenseMtx_zero (
DenseMtx *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_zero(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
if ( DENSEMTX_IS_REAL(mtx) ) {
DVzero(mtx->nrow*mtx->ncol, mtx->entries) ;
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
DVzero(2*mtx->nrow*mtx->ncol, mtx->entries) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------
fill with random entries
created -- 98may16, cca
------------------------
*/
void
DenseMtx_fillRandomEntries (
DenseMtx *mtx,
Drand *drand
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || drand == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_fillRandomEntries(%p,%p)"
"\n bad input\n", mtx, drand) ;
exit(-1) ;
}
if ( DENSEMTX_IS_REAL(mtx) ) {
Drand_fillDvector(drand, mtx->nrow*mtx->ncol, mtx->entries) ;
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
Drand_fillDvector(drand, 2*mtx->nrow*mtx->ncol, mtx->entries) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------
compute three checksums
sums[0] = sum of row indices
sums[1] = sum of columns indices
sums[2] = sum of entry magnitudes
created -- 98may16, cca
-----------------------------------
*/
void
DenseMtx_checksums (
DenseMtx *mtx,
double sums[]
) {
double *entries ;
int ii, ncol, nent, nrow ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || sums == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_checksums(%p,%p)"
"\n bad input\n", mtx, sums) ;
exit(-1) ;
}
sums[0] = sums[1] = sums[2] = 0.0 ;
DenseMtx_rowIndices(mtx, &nrow, &rowind) ;
for ( ii = 0 ; ii < nrow ; ii++ ) {
sums[0] += rowind[ii] ;
}
DenseMtx_columnIndices(mtx, &ncol, &colind) ;
for ( ii = 0 ; ii < ncol ; ii++ ) {
sums[1] += colind[ii] ;
}
entries = DenseMtx_entries(mtx) ;
nent = nrow*ncol ;
if ( DENSEMTX_IS_REAL(mtx) ) {
for ( ii = 0 ; ii < nent ; ii++ ) {
sums[2] += fabs(entries[ii]) ;
}
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
for ( ii = 0 ; ii < nent ; ii++ ) {
sums[2] += Zabs(entries[2*ii], entries[2*ii+1]) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------
return the maximum magnitude of the entries
created -- 98may15, cca
-------------------------------------------
*/
double
DenseMtx_maxabs (
DenseMtx *mtx
) {
double maxabs ;
int loc ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_maxabs(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
if ( DENSEMTX_IS_REAL(mtx) ) {
maxabs = DVmaxabs(mtx->nrow*mtx->ncol, mtx->entries, &loc) ;
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
maxabs = ZVmaxabs(mtx->nrow*mtx->ncol, mtx->entries) ;
} else {
fprintf(stderr, "\n fatal error in DenseMtx_maxabs(%p)"
"\n bad type %d\n", mtx, mtx->type) ;
exit(-1) ;
}
return(maxabs) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
subtract one matrix from another, B := B - A
created -- 98may25, cca
--------------------------------------------
*/
void
DenseMtx_sub (
DenseMtx *mtxB,
DenseMtx *mtxA
) {
/*
---------------
check the input
---------------
*/
if ( mtxB == NULL || mtxA == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_sub(%p,%p)"
"\n bad input\n", mtxB, mtxA) ;
exit(-1) ;
}
if ( mtxB->type != mtxA->type ) {
fprintf(stderr, "\n fatal error in DenseMtx_sub(%p,%p)"
"\n mtxB->type = %d, mtxA->type = %d\n",
mtxB, mtxA, mtxB->type, mtxA->type) ;
exit(-1) ;
}
if ( mtxB->nrow != mtxA->nrow ) {
fprintf(stderr, "\n fatal error in DenseMtx_sub(%p,%p)"
"\n mtxB->nrow = %d, mtxA->nrow = %d\n",
mtxB, mtxA, mtxB->nrow, mtxA->nrow) ;
exit(-1) ;
}
if ( mtxB->ncol != mtxA->ncol ) {
fprintf(stderr, "\n fatal error in DenseMtx_sub(%p,%p)"
"\n mtxB->ncol = %d, mtxA->ncol = %d\n",
mtxB, mtxA, mtxB->ncol, mtxA->ncol) ;
exit(-1) ;
}
if ( mtxB->entries == NULL || mtxA->entries == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_sub(%p,%p)"
"\n mtxB->entries = %p, mtxA->entries = %p\n",
mtxB, mtxA, mtxB->entries, mtxA->entries) ;
exit(-1) ;
}
if ( DENSEMTX_IS_REAL(mtxB) ) {
DVsub(mtxB->nrow*mtxB->ncol, mtxB->entries, mtxA->entries) ;
} else if ( DENSEMTX_IS_COMPLEX(mtxB) ) {
ZVsub(mtxB->nrow*mtxB->ncol, mtxB->entries, mtxA->entries) ;
} else {
fprintf(stderr, "\n fatal error in DenseMtx_sub(%p,%p)"
"\n mtxB->type = %d, mtxA->type = %d\n",
mtxB, mtxA, mtxB->type, mtxA->type) ;
exit(-1) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
purpose -- to copy a row of the matrix into a vector
irow -- local row id
vec -- double vector to receive the row entries
created -- 98jul31, cca
----------------------------------------------------
*/
void
DenseMtx_copyRowIntoVector (
DenseMtx *mtx,
int irow,
double *vec
) {
double *entries ;
int inc1, inc2, jcol, jj, kk, nrow, ncol ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || irow < 0 || vec == NULL ) {
fprintf(stderr,
"\n fatal error in DenseMtx_copyRowIntoVector()"
"\n bad input\n") ;
exit(-1) ;
}
DenseMtx_rowIndices(mtx, &nrow, &rowind) ;
if ( irow >= nrow ) {
fprintf(stderr,
"\n fatal error in DenseMtx_copyRowIntoVector()"
"\n irow = %d, nrow = %d\n", irow, nrow) ;
exit(-1) ;
}
DenseMtx_columnIndices(mtx, &ncol, &colind) ;
inc1 = DenseMtx_rowIncrement(mtx) ;
inc2 = DenseMtx_columnIncrement(mtx) ;
entries = DenseMtx_entries(mtx) ;
if ( DENSEMTX_IS_REAL(mtx) ) {
for ( jcol = jj = 0, kk = irow*inc1 ;
jcol < ncol ;
jcol++, jj++, kk += inc2 ) {
vec[jj] = entries[kk] ;
}
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
for ( jcol = jj = 0, kk = irow*inc1 ;
jcol < ncol ;
jcol++, jj++, kk += inc2 ) {
vec[2*jj] = entries[2*kk] ;
vec[2*jj+1] = entries[2*kk+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
purpose -- to copy a row of the matrix into a vector
irow -- local row id
vec -- double vector to supply the row entries
created -- 98jul31, cca
----------------------------------------------------
*/
void
DenseMtx_copyVectorIntoRow (
DenseMtx *mtx,
int irow,
double *vec
) {
double *entries ;
int inc1, inc2, jcol, jj, kk, nrow, ncol ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || irow < 0 || vec == NULL ) {
fprintf(stderr,
"\n fatal error in DenseMtx_copyVectorIntoRow()"
"\n bad input, mtx %p, irow %d, vec %p\n",
mtx, irow, vec) ;
exit(-1) ;
}
DenseMtx_rowIndices(mtx, &nrow, &rowind) ;
if ( irow >= nrow ) {
fprintf(stderr,
"\n fatal error in DenseMtx_copyVectorIntoRow()"
"\n irow = %d, nrow = %d\n", irow, nrow) ;
exit(-1) ;
}
DenseMtx_columnIndices(mtx, &ncol, &colind) ;
inc1 = DenseMtx_rowIncrement(mtx) ;
inc2 = DenseMtx_columnIncrement(mtx) ;
entries = DenseMtx_entries(mtx) ;
if ( DENSEMTX_IS_REAL(mtx) ) {
for ( jcol = jj = 0, kk = irow*inc1 ;
jcol < ncol ;
jcol++, jj++, kk += inc2 ) {
entries[kk] = vec[jj] ;
}
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
for ( jcol = jj = 0, kk = irow*inc1 ;
jcol < ncol ;
jcol++, jj++, kk += inc2 ) {
entries[2*kk] = vec[2*jj] ;
entries[2*kk+1] = vec[2*jj+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
purpose -- to add a row of the matrix into a vector
irow -- local row id
vec -- double vector to supply the row entries
created -- 98aug12, cca
----------------------------------------------------
*/
void
DenseMtx_addVectorIntoRow (
DenseMtx *mtx,
int irow,
double *vec
) {
double *entries ;
int inc1, inc2, jcol, jj, kk, nrow, ncol ;
int *colind, *rowind ;
/*
---------------
check the input
---------------
*/
if ( mtx == NULL || irow < 0 || vec == NULL ) {
fprintf(stderr,
"\n fatal error in DenseMtx_addVectorIntoRow()"
"\n bad input, mtx %p, irow %d, vec %p\n",
mtx, irow, vec) ;
exit(-1) ;
}
DenseMtx_rowIndices(mtx, &nrow, &rowind) ;
if ( irow >= nrow ) {
fprintf(stderr,
"\n fatal error in DenseMtx_addVectorIntoRow()"
"\n irow = %d, nrow = %d\n", irow, nrow) ;
exit(-1) ;
}
DenseMtx_columnIndices(mtx, &ncol, &colind) ;
inc1 = DenseMtx_rowIncrement(mtx) ;
inc2 = DenseMtx_columnIncrement(mtx) ;
entries = DenseMtx_entries(mtx) ;
if ( DENSEMTX_IS_REAL(mtx) ) {
for ( jcol = jj = 0, kk = irow*inc1 ;
jcol < ncol ;
jcol++, jj++, kk += inc2 ) {
entries[kk] += vec[jj] ;
}
} else if ( DENSEMTX_IS_COMPLEX(mtx) ) {
for ( jcol = jj = 0, kk = irow*inc1 ;
jcol < ncol ;
jcol++, jj++, kk += inc2 ) {
entries[2*kk] += vec[2*jj] ;
entries[2*kk+1] += vec[2*jj+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
*iB] += rowA[2*iA] ;
rowB[2*iB+1] += rowA[2*iA+1] ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
zero the entries
created -- 98may16, cca
-----------------------
*/
void
DenseMtx_zero (
DenseMtx *mtx
) {
/*
---------------
check the input
---------------
*/
if ( mtx == NULL ) {
fprintf(stderr, "\n fatal error in DenseMtx_zero(%p)"
"\n bad input\n", mtx) ;
exit(-1) ;
}
DenseMtx/doc/ 0042755 0002055 0007177 00000000000 06623421765 0014405 5 ustar 00cleve compmath 0000040 0000006 DenseMtx/doc/dataStructure.tex 0100644 0002055 0007177 00000002661 06560406444 0017756 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:DenseMtx:dataStructure}
\par
\par
The {\tt DenseMtx} structure has the following fields.
\begin{itemize}
\item
{\tt int type} : type of entries, {\tt SPOOLES\_REAL}
or {\tt SPOOLES\_COMPLEX}.
\item
{\tt int rowid} : object's row id, default value is {\tt -1}.
\item
{\tt int colid} : object's column id, default value is {\tt -1}.
\item
{\tt int nrow} : number of rows
\item
{\tt int ncol} : number of columns
\item
{\tt int inc1} : row increment,
difference in addresses between entries in the same column
\item
{\tt int inc2} : column increment,
difference in addresses between entries in the same row
\item
{\tt int *rowind} :
pointer to the base address of the {\tt int} vector
that contains row indices.
\item
{\tt int *colind} :
pointer to the base address of the {\tt int} vector
that contains column indices.
\item
{\tt double *entries} :
pointer to the base address of the {\tt double} vector that
contains the entries.
\item
{\tt DV wrkDV} :
object that manages the owned working storage.
\item
{\tt DenseMtx *next} :
link to a next object in a singly linked list.
\end{itemize}
\par
One can query the type of entries via two macros.
\begin{itemize}
\item
{\tt DENSEMTX\_IS\_REAL(mtx)} returns {\tt 1} if the matrix has
real entries, and {\tt 0} otherwise.
\item
{\tt DENSEMTX\_IS\_COMPLEX(mtx)} returns {\tt 1} if the matrix has
complex entries, and {\tt 0} otherwise.
\end{itemize}
DenseMtx/doc/intro.tex 0100644 0002055 0007177 00000001600 06560406444 0016247 0 ustar 00cleve compmath 0000040 0000006 \par
\chapter{{\tt DenseMtx}: Dense matrix object}
\par
The {\tt DenseMtx} object contains a dense matrix along with row and
column indices.
The entries in the matrix can be double precision real or double
precision complex.
It needs to be able to manage its own storage, much like the {\tt
Chv} and {\tt SubMtx} objects that are used during the
factor and solves, so we include
this capability via a contained {\tt DV} object.
A {\tt DenseMtx} object may also be found in a list, so there is
a {\tt next} field that points to another {\tt DenseMtx} object.
\par
The {\tt DenseMtx} object also exists in an MPI environment,
where it holds the solution and right hand side matrices.
Since each of these two matrices is distributed, a processor
{\it owns} only part of the global matrix, and so the need for row
and column indices to specify which rows and columns are present on
which processor.
DenseMtx/doc/main.tex 0100644 0002055 0007177 00000001132 06622330465 0016036 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[10pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\newcommand{\bnd}{{\partial}}
\input psfig
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt DenseMtx} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt DenseMtx} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input main.ind
\end{document}
ght 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\newcommand{\bnd}{{\partial}}
\input psfig
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt DenseMtx} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt DenseMtx} : {\it DRAFT} \quad \today \hrulefill}
\par
\iDenseMtx/doc/proto.tex 0100644 0002055 0007177 00000073417 06622345700 0016272 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt DenseMtx} methods}
\label{section:DenseMtx:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt DenseMtx} object.
\par
\subsection{Basic methods}
\label{subsection:DenseMtx:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
DenseMtx * DenseMtx_new ( void ) ;
\end{verbatim}
\index{DenseMtx_new@{\tt DenseMtx\_new()}}
This method simply allocates storage for the {\tt DenseMtx} structure
and then sets the default fields by a call to
{\tt DenseMtx\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_setDefaultFields ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_setDefaultFields@{\tt DenseMtx\_setDefaultFields()}}
The structure's fields are set to default values:
{\tt type} = {\tt SPOOLES\_REAL},
{\tt rowid} = {\tt colid} = {\tt -1},
{\tt nrow} = {\tt ncol} = {\tt inc1} = {\tt inc2} = 0
and {\tt rowind} = {\tt colind} = {\tt entries} = {\tt next}
= {\tt NULL} .
The {\tt wrkDV} object has its default fields set via a call to
{\tt DV\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_clearData ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_clearData@{\tt DenseMtx\_clearData()}}
This method clears the object and free's any owned data
by invoking the {\tt \_clearData()} methods for its internal
{\tt DV} object.
There is a concluding call to {\tt DenseMtx\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_free ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_free@{\tt DenseMtx\_free()}}
This method releases any storage by a call to
{\tt DenseMtx\_clearData()} and then free the space for {\tt mtx}.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Instance methods}
\label{subsection:DenseMtx:proto:instance}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_rowid ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_rowid@{\tt DenseMtx\_rowid()}}
This method returns the {\it rowid} field of the object.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_colid ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_colid@{\tt DenseMtx\_colid()}}
This method returns the {\it colid} field of the object.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_dimensions ( DenseMtx *mtx, int *pnrow, int *pncol ) ;
\end{verbatim}
\index{DenseMtx_dimensions@{\tt DenseMtx\_dimensions()}}
This method
fills {\tt *pnrow} and {\tt *pncol}
with {\tt nrow} and {\tt ncol}.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_columnIncrement ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_columnIncrement@{\tt DenseMtx\_columnIncrement()}}
This method returns the row increment of the object, the difference
in memory locations of two entries in consecutive columns in the same
row.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_rowIncrement ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_rowIncrement@{\tt DenseMtx\_rowIncrement()}}
This method returns the row increment of the object, the difference
in memory locations of two entries in consecutive rows in the same
column.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_rowIndices ( DenseMtx *mtx, int *pnrow, **prowind ) ;
\end{verbatim}
\index{DenseMtx_rowIndices@{\tt DenseMtx\_rowIndices()}}
This method fills {\tt *pnrow} with {\tt nrow}, the number of rows,
and {\tt *prowind} with {\tt rowind},
a pointer to the row indices.
\par \noindent {\it Error checking:}
If {\tt mtx}, {\tt pnrow} or {\tt prowind} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_columnIndices ( DenseMtx *mtx, int *pncol, **colind ) ;
\end{verbatim}
\index{DenseMtx_columnIndices@{\tt DenseMtx\_columnIndices()}}
This method fills {\tt *pncol} with {\tt ncol}, the number of columns,
and {\tt *pcolind} with {\tt colind},
a pointer to the column indices.
\par \noindent {\it Error checking:}
If {\tt mtx}, {\tt pncol} or {\tt pcolind} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double * DenseMtx_entries ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_entries@{\tt DenseMtx\_entries()}}
This method returns the {\it entries} field of the object.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void * DenseMtx_workspace ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_workspace@{\tt DenseMtx\_workspace()}}
This method returns a pointer to the base address of the object's
workspace.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_realEntry ( DenseMtx *mtx, int irow, int jcol, double *pValue ) ;
\end{verbatim}
\index{DenseMtx_realEntry@{\tt DenseMtx\_realEntry()}}
This method fills {\tt *pValue} with the entry
in row {\tt irow} and column {\tt jcol}.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt pValue} is {\tt NULL},
or if the matrix is not real,
or if {\tt irow} or {\tt jcol} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_complexEntry ( DenseMtx *mtx, int irow, int jcol,
double *pReal, double *pImag ) ;
\end{verbatim}
\index{DenseMtx_complexEntry@{\tt DenseMtx\_complexEntry()}}
This method fills {\tt *pReal} with the real part and
{\tt *pImag} with the imaginary part of the the entry
in row {\tt irow} and column {\tt jcol}.
\par \noindent {\it Error checking:}
If {\tt mtx}, {\tt pReal} or {\tt pImag} is {\tt NULL},
or if the matrix is not complex,
or if {\tt irow} or {\tt jcol} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_setRealEntry ( DenseMtx *mtx, int irow, int jcol, double value) ;
\end{verbatim}
\index{DenseMtx_setRealEntry@{\tt DenseMtx\_setRealEntry()}}
This method sets the entry in row {\tt irow} and column {\tt jcol}
to be {\tt value}.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
or if the matrix is not real,
or if {\tt irow} or {\tt jcol} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_setComplexEntry ( DenseMtx *mtx, int irow, int jcol,
double real, double imag ) ;
\end{verbatim}
\index{DenseMtx_setComplexEntry@{\tt DenseMtx\_setComplexEntry()}}
This method sets the real and imaginary parts of the entry in row
{\tt irow} and column {\tt jcol} to be {\tt (real,imag)}.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
or if the matrix is not complex,
or if {\tt irow} or {\tt jcol} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_row ( DenseMtx *mtx, int irow, double **prowent ) ;
\end{verbatim}
\index{DenseMtx_row@{\tt DenseMtx\_row()}}
This method fills {\tt *prowent} with the first location of the
entries in row {\tt irow}.
\par \noindent {\it Return codes:}
{\tt 1} is a normal return,
{\tt -1} means {\tt mtx} is {\tt NULL},
{\tt -2} means invalid type for {\tt mtx},
{\tt -3} means {\tt irow} is out-of-range,
{\tt -4} means {\tt prowent} is {\tt NULL}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_column ( DenseMtx *mtx, int jcol, double **pcolent ) ;
\end{verbatim}
\index{DenseMtx_column@{\tt DenseMtx\_column()}}
This method fills {\tt *pcolent} with the first location of the
entries in column {\tt jcol}.
\par \noindent {\it Return codes:}
{\tt 1} is a normal return,
{\tt -1} means {\tt mtx} is {\tt NULL},
{\tt -2} means invalid type for {\tt mtx},
{\tt -3} means {\tt jcol} is out-of-range,
{\tt -4} means {\tt pcolent} is {\tt NULL}.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initialization methods}
\label{subsection:DenseMtx:proto:initial}
\par
There are three initializer methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_init( DenseMtx *mtx, int type, int rowid, int colid,
int nrow, int ncol, int inc1, int inc2 ) ;
\end{verbatim}
\index{DenseMtx_init@{\tt DenseMtx\_init()}}
This is the initializer method used when the {\tt DenseMtx}
object is to use its workspace to store indices and entries.
The number of bytes required in the workspace is computed,
the workspace is resized if necessary, and the scalar and pointer
fields are set.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
or if {\tt type} is neither {\tt SPOOLES\_REAL}
nor {\tt SPOOLES\_COMPLEX},
or if {\tt nrow}, {\tt ncol}, {\tt inc1} or {\tt inc2}
is less than or equal to zero,
or if neither {\tt inc1} nor {\tt inc2} are {\tt 1},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_initWithPointers ( DenseMtx *mtx, int type, int rowid, int colid,
int nD, int nL, int nU, int *rowind, int *colind, double *entries ) ;
\end{verbatim}
\index{DenseMtx_initWithPointers@{\tt DenseMtx\_initWithPointers()}}
This is the initializer method used when the {\tt DenseMtx}
object does not own the storage for its indices and entries,
but points into some other storage.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
or if {\tt type} is neither {\tt SPOOLES\_REAL}
nor {\tt SPOOLES\_COMPLEX},
or if {\tt nrow}, {\tt ncol}, {\tt inc1} or {\tt inc2}
is less than or equal to zero,
or if neither {\tt inc1} nor {\tt inc2} are {\tt 1},
or if {\tt rowind}, {\tt colind} or {\tt entries} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_initAsSubmatrix ( DenseMtx *B, DenseMtx *A, int firstrow, int lastrow,
int firstcol, int lastcol ) ;
\end{verbatim}
\index{DenseMtx_initAsSubmatrix@{\tt DenseMtx\_initAsSubmatrix()}}
This method initializes {\tt B} to contain rows {\tt firstrow:lastrow}
and columns {\tt firstcol:lastcol} of {\tt A}.
Note, the {\tt rowind}, {\tt colind} and {\tt entries} fields of
{\tt B} point into the indices and entries for {\tt A}.
\par \noindent {\it Return codes:}
{\tt 1} is the normal return,
{\tt -1} means {\tt B} is {\tt NULL},
{\tt -2} means {\tt A} is {\tt NULL},
{\tt -3} means {\tt A} has invalid type
\begin{center}
\begin{tabular}{ll}
~1 & normal return \\
-1 & {\tt B} is {\tt NULL} \\
-2 & {\tt A} is {\tt NULL}
\end{tabular}
\begin{tabular}{ll}
-3 & {\tt A} has invalid type \\
-4 & requested rows are out-of-range \\
-5 & requested columns are out-of-range
\end{tabular}
\end{center}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_initFromBuffer ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_initFromBuffer@{\tt DenseMtx\_initFromBuffer()}}
This method initializes the object using information present in the
workspace buffer.
This method is used to initialize the {\tt DenseMtx} object when
it has been received as an MPI message.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_setA2 ( DenseMtx *mtx, A2 *a2 ) ;
\end{verbatim}
\index{DenseMtx_setA2@{\tt DenseMtx\_setA2()}}
This method initializes the {\tt a2} object to point
into the entries of the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt a2} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:DenseMtx:proto:utility}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_nbytesNeeded ( int type, int nrow, int ncol ) ;
\end{verbatim}
\index{DenseMtx_nbytesNeeded@{\tt DenseMtx\_nbytesNeeded()}}
\par
This method returns the number of bytes required to store the
object's information in its buffer.
\par \noindent {\it Error checking:}
If {\tt type} is neither {\tt SPOOLES\_REAL}
nor {\tt SPOOLES\_COMPLEX},
or if {\tt nrow} or {\tt ncol} is less than zero,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_nbytesInWorkspace ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_nbytesInWorkspace@{\tt DenseMtx\_nbytesInWorkspace()}}
\par
This method returns the number of bytes in the workspace owned by
this object.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_setNbytesInWorkspace ( DenseMtx *mtx, int nbytes ) ;
\end{verbatim}
\index{DenseMtx_setNbytesInWorkspace@{\tt DenseMtx\_setNbytesInWorkspace()}}
\par
This method sets the number of bytes in the workspace of this object.
If {\tt nbytes} is less than the present number of bytes,
the workspace is not resized.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_setFields( DenseMtx *mtx, int type, int rowid, int colid,
int nrow, int ncol, int inc1, int inc2 ) ;
\end{verbatim}
\index{DenseMtx_setFields@{\tt DenseMtx\_setFields()}}
This method sets the scalar and pointer fields.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
or if {\tt type} is neither {\tt SPOOLES\_REAL}
nor {\tt SPOOLES\_COMPLEX},
or if {\tt nrow}, {\tt ncol}, {\tt inc1} or {\tt inc2}
is less than or equal to zero,
or if neither {\tt inc1} nor {\tt inc2} are {\tt 1},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_permuteRows ( DenseMtx *mtx, IV *oldToNewIV ) ;
void DenseMtx_permuteColumns ( DenseMtx *mtx, IV *oldToNewIV ) ;
\end{verbatim}
\index{DenseMtx_permuteRows@{\tt DenseMtx\_permuteRows()}}
\index{DenseMtx_permuteColumns@{\tt DenseMtx\_permuteColumns()}}
These methods permute the rows or columns using an old-to-new
permutation vector.
The row or column ids are overwritten using the permutation vector,
and then the rows or columns are sorted into ascending order.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt oldToNewIV} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_sort ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_sort@{\tt DenseMtx\_sort()}}
This method sort the rows so the row ids are in ascending order
and sorts the columns so the column ids are in ascending order.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_copyRow ( DenseMtx *mtxB, int irowB, DenseMtx *mtxA, int irowA ) ;
\end{verbatim}
\index{DenseMtx_copyRow@{\tt DenseMtx\_copyRow()}}
This method copies row {\tt irowA} from matrix {\tt mtxA}
into row {\tt irowB} of matrix {\tt mtxB}.
\par \noindent {\it Error checking:}
If {\tt mtxB} is {\tt NULL},
or if {\tt irowB} is out of range,
or if {\tt mtxA} is {\tt NULL},
or if {\tt irowA} is out of range,
or if the number of columns in {\tt mtxB} and {\tt mtxA} are not
the same,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_copyRowAndIndex ( DenseMtx *mtxB, int irowB,
DenseMtx *mtxA, int irowA ) ;
\end{verbatim}
\index{DenseMtx_copyRowAndIndex@{\tt DenseMtx\_copyRowAndIndex()}}
This method copies row {\tt irowA} from matrix {\tt mtxA}
into row {\tt irowB} of matrix {\tt mtxB}, and copies the index of row
{\tt irowA} of {\tt mtxA} into location {\tt irowB} of the row indices
for {\tt mtxB}.
\par \noindent {\it Error checking:}
If {\tt mtxB} is {\tt NULL},
or if {\tt irowB} is out of range,
or if {\tt mtxA} is {\tt NULL},
or if {\tt irowA} is out of range,
or if the number of columns in {\tt mtxB} and {\tt mtxA} are not
the same,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_addRow ( DenseMtx *mtxB, int irowB, DenseMtx *mtxA, int irowA ) ;
\end{verbatim}
\index{DenseMtx_addRow@{\tt DenseMtx\_addRow()}}
This method adds row {\tt irowA} from matrix {\tt mtxA}
into row {\tt irowB} of matrix {\tt mtxB}.
\par \noindent {\it Error checking:}
If {\tt mtxB} is {\tt NULL},
or if {\tt irowB} is out of range,
or if {\tt mtxA} is {\tt NULL},
or if {\tt irowA} is out of range,
or if the number of columns in {\tt mtxB} and {\tt mtxA} are not
the same,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_zero ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_zero@{\tt DenseMtx\_zero()}}
This method zeros the entries in the matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_fillRandomEntries ( DenseMtx *mtx, Drand *drand ) ;
\end{verbatim}
\index{DenseMtx_fillRandomEntries@{\tt DenseMtx\_fillRandomEntries()}}
This method the entries in the matrix with random numbers using the
{\tt drand} object.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt drand} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_checksums ( DenseMtx *mtx, double sums[3] ) ;
\end{verbatim}
\index{DenseMtx_checksums@{\tt DenseMtx\_checksums()}}
This method fills {\tt sums[0]} with the sum of the row indices,
{\tt sums[1]} with the sum of the column indices,
and
{\tt sums[2]} with the sum of the magnitudes of the entries.
This method is used to check the MPI method where a distributed
matrix is re-distributed.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt sums} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_scale ( DenseMtx *mtx, double alpha[] ) ;
\end{verbatim}
\index{DenseMtx_scale@{\tt DenseMtx\_scale()}}
This method scales the entries in {\tt mtx} by {\tt alpha}.
\par \noindent {\it Return values:}
1 for a normal return,
-1 if {\tt mtx} is NULL,
-2 if {\tt mtx} has an invalid type,
-3 if {\tt alpha} is NULL.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DenseMtx_maxabs ( DenseMtx *mtx ) ;
\end{verbatim}
\index{DenseMtx_maxabs@{\tt DenseMtx\_maxabs()}}
This method returns the entry of maximum magnitude of the entries.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DenseMtx_sub ( DenseMtx *mtxB, *DenseMtx *mtxA ) ;
\end{verbatim}
\index{DenseMtx_sub@{\tt DenseMtx\_sub()}}
This method subtracts matrix {\tt mtxA} from {\tt mtxB} .
\par \noindent {\it Error checking:}
If {\tt mtxA} or {\tt mtxB} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DenseMtx_copyRowIntoVector ( DenseMtx *mtx, int irow, double vec[] ) ;
\end{verbatim}
\index{DenseMtx_copyRowIntoVector@{\tt DenseMtx\_copyRowIntoVector()}}
This method copies row {\tt irow} of matrix {\tt mtx} into vector
{\tt vec[]}.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt vec} is {\tt NULL},
or if ${\tt irow} < 0$ or ${\tt irow} \ge {\tt nrow}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DenseMtx_copyVectorIntoRow ( DenseMtx *mtx, int irow, double vec[] ) ;
\end{verbatim}
\index{DenseMtx_copyVectorIntoRow@{\tt DenseMtx\_copyVectorIntoRow()}}
This method copies vector {\tt vec[]} into row {\tt irow}
of matrix {\tt mtx}.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt vec} is {\tt NULL},
or if ${\tt irow} < 0$ or ${\tt irow} \ge {\tt nrow}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DenseMtx_addVectorIntoRow ( DenseMtx *mtx, int irow, double vec[] ) ;
\end{verbatim}
\index{DenseMtx_addVectorIntoRow@{\tt DenseMtx\_addVectorIntoRow()}}
This method adds vector {\tt vec[]} into row {\tt irow}
of matrix {\tt mtx}.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt vec} is {\tt NULL},
or if ${\tt irow} < 0$ or ${\tt irow} \ge {\tt nrow}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:DenseMtx:proto:IO}
\par
The file structure of a {\tt DenseMtx} object is simple.
First comes seven scalars, {\tt type}, {\tt rowid}, {\tt colid},
{\tt nrow}, {\tt ncol}, {\tt inc1} and {\tt inc2},
followed by the row indices,
followed by the column indices, and then
followed by the matrix entries.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_readFromFile ( DenseMtx *mtx, char *fn ) ;
\end{verbatim}
\index{DenseMtx_readFromFile@{\tt DenseMtx\_readFromFile()}}
\par
This method reads an {\tt DenseMtx} object from a file.
If the the file can be opened successfully,
the method calls {\tt DenseMtx\_readFromFormattedFile()} or
{\tt DenseMtx\_readFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.densemtxf} (for a formatted file)
or {\tt *.densemtxb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_readFromFormattedFile ( DenseMtx *mtx, FILE *fp ) ;
\end{verbatim}
\index{DenseMtx_readFromFormattedFile@{\tt DenseMtx\_readFromFormattedFile()}}
\par
This method reads an {\tt DenseMtx} object from a formatted file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fscanf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_readFromBinaryFile ( DenseMtx *mtx, FILE *fp ) ;
\end{verbatim}
\index{DenseMtx_readFromBinaryFile@{\tt DenseMtx\_readFromBinaryFile()}}
\par
This method reads an {\tt DenseMtx} object from a binary file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fread}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_writeToFile ( DenseMtx *mtx, char *fn ) ;
\end{verbatim}
\index{DenseMtx_writeToFile@{\tt DenseMtx\_writeToFile()}}
\par
This method writes an {\tt DenseMtx} object to a file.
If the the file can be opened successfully,
the method calls {\tt DenseMtx\_writeFromFormattedFile()} or
{\tt DenseMtx\_writeFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.densemtxf} (for a formatted file)
or {\tt *.densemtxb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_writeToFormattedFile ( DenseMtx *mtx, FILE *fp ) ;
\end{verbatim}
\index{DenseMtx_writeToFormattedFile@{\tt DenseMtx\_writeToFormattedFile()}}
\par
This method writes an {\tt DenseMtx} object to a formatted file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fprintf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL} an error message is printed and
zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_writeToBinaryFile ( DenseMtx *mtx, FILE *fp ) ;
\end{verbatim}
\index{DenseMtx_writeToBinaryFile@{\tt DenseMtx\_writeToBinaryFile()}}
\par
This method writes an {\tt DenseMtx} object to a binary file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fwrite}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DenseMtx_writeStats ( DenseMtx *mtx, FILE *fp ) ;
\end{verbatim}
\index{DenseMtx_writeStats@{\tt DenseMtx\_writeStats()}}
\par
This method writes out a header and statistics to a file.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_writeForHumanEye ( DenseMtx *mtx, FILE *fp ) ;
\end{verbatim}
\index{DenseMtx_writeForHumanEye@{\tt DenseMtx\_writeForHumanEye()}}
\par
This method writes a {\tt DenseMtx} object to a file in an easily
readable format.
\par \noindent {\it Error checking:}
If {\tt mtx} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_writeForMatlab ( DenseMtx *mtx, char *mtxname, FILE *fp ) ;
\end{verbatim}
\index{DenseMtx_writeForMatlab@{\tt DenseMtx\_writeForMatlab()}}
\par
This method writes out a {\tt DenseMtx} object to a file in a Matlab
format.
A sample line is
\begin{verbatim}
a(10,5) = -1.550328201511e-01 + 1.848033378871e+00*i ;
\end{verbatim}
for complex matrices, or
\begin{verbatim}
a(10,5) = -1.550328201511e-01 ;
\end{verbatim}
for real matrices, where mtxname = {\tt "a"}.
The matrix indices come from the {\tt rowind[]} and {\tt colind[]}
vectors, and are incremented by one to follow the Matlab and
FORTRAN convention.
\par \noindent {\it Error checking:}
If {\tt mtx}, {\tt mtxname} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
he matrix.
\par \noindent {\it Error checking:}
If {\tt mtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DenseMtx_fillDenseMtx/doc/main.log 0100644 0002055 0007177 00000005251 06623357321 0016026 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.14159 (C version 6.1) (format=latex 97.4.4) 14 NOV 1998 11:49
**main
(main.tex
LaTeX2e <1996/12/01> patch level 1
Babel and hyphenation patterns for english, german, loaded.
(/home/tex/teTeX/texmf/tex/latex/base/report.cls
Document Class: report 1996/10/31 v1.3u Standard LaTeX document class
(/home/tex/teTeX/texmf/tex/latex/base/size10.clo
File: size10.clo 1996/10/31 v1.3u Standard LaTeX file (size option)
)
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
\abovecaptionskip=\skip41
\belowcaptionskip=\skip42
\bibindent=\dimen102
)
(/home/tex/teTeX/texmf/tex/generic/local/psfig/psfig.tex
\@unused=\write3
\ps@stream=\read1
\p@intvaluex=\dimen103
\p@intvaluey=\dimen104
psfig/tex 1.10-dvips
)
\@indexfile=\write4
Writing index file main.idx
(main.aux)
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
(intro.tex
Chapter 1.
) (dataStructure.tex
LaTeX Font Info: Try loading font information for OMS+cmr on input line 9.
(/home/tex/teTeX/texmf/tex/latex/base/omscmr.fd
File: omscmr.fd 1997/01/14 v2.5a Standard LaTeX font definitions
)
LaTeX Font Info: Font shape `OMS/cmr/m/n' in size <10> not available
(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 9.
)
(proto.tex [1
] [2] [3]
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <7> on input line 325.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <5> on input line 325.
[4] [5] [6] [7]) (main.ind [8] [9
]) (main.aux) )
Here is how much of TeX's memory you used:
512 strings out of 10908
5200 string characters out of 72189
53614 words of memory out of 262141
3436 multiletter control sequences out of 9500
7603 words of font info for 29 fonts, out of 150000 for 255
14 hyphenation exceptions out of 607
23i,6n,21p,158b,399s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (9 pages, 30248 bytes).
DenseMtx/doc/main.idx 0100644 0002055 0007177 00000006646 06623357321 0016042 0 ustar 00cleve compmath 0000040 0000006 \indexentry{DenseMtx_new@{\tt DenseMtx\_new()}}{2}
\indexentry{DenseMtx_setDefaultFields@{\tt DenseMtx\_setDefaultFields()}}{2}
\indexentry{DenseMtx_clearData@{\tt DenseMtx\_clearData()}}{2}
\indexentry{DenseMtx_free@{\tt DenseMtx\_free()}}{2}
\indexentry{DenseMtx_rowid@{\tt DenseMtx\_rowid()}}{2}
\indexentry{DenseMtx_colid@{\tt DenseMtx\_colid()}}{2}
\indexentry{DenseMtx_dimensions@{\tt DenseMtx\_dimensions()}}{2}
\indexentry{DenseMtx_columnIncrement@{\tt DenseMtx\_columnIncrement()}}{2}
\indexentry{DenseMtx_rowIncrement@{\tt DenseMtx\_rowIncrement()}}{3}
\indexentry{DenseMtx_rowIndices@{\tt DenseMtx\_rowIndices()}}{3}
\indexentry{DenseMtx_columnIndices@{\tt DenseMtx\_columnIndices()}}{3}
\indexentry{DenseMtx_entries@{\tt DenseMtx\_entries()}}{3}
\indexentry{DenseMtx_workspace@{\tt DenseMtx\_workspace()}}{3}
\indexentry{DenseMtx_realEntry@{\tt DenseMtx\_realEntry()}}{3}
\indexentry{DenseMtx_complexEntry@{\tt DenseMtx\_complexEntry()}}{3}
\indexentry{DenseMtx_setRealEntry@{\tt DenseMtx\_setRealEntry()}}{3}
\indexentry{DenseMtx_setComplexEntry@{\tt DenseMtx\_setComplexEntry()}}{3}
\indexentry{DenseMtx_row@{\tt DenseMtx\_row()}}{4}
\indexentry{DenseMtx_column@{\tt DenseMtx\_column()}}{4}
\indexentry{DenseMtx_init@{\tt DenseMtx\_init()}}{4}
\indexentry{DenseMtx_initWithPointers@{\tt DenseMtx\_initWithPointers()}}{4}
\indexentry{DenseMtx_initAsSubmatrix@{\tt DenseMtx\_initAsSubmatrix()}}{4}
\indexentry{DenseMtx_initFromBuffer@{\tt DenseMtx\_initFromBuffer()}}{4}
\indexentry{DenseMtx_setA2@{\tt DenseMtx\_setA2()}}{4}
\indexentry{DenseMtx_nbytesNeeded@{\tt DenseMtx\_nbytesNeeded()}}{5}
\indexentry{DenseMtx_nbytesInWorkspace@{\tt DenseMtx\_nbytesInWorkspace()}}{5}
\indexentry{DenseMtx_setNbytesInWorkspace@{\tt DenseMtx\_setNbytesInWorkspace()}}{5}
\indexentry{DenseMtx_setFields@{\tt DenseMtx\_setFields()}}{5}
\indexentry{DenseMtx_permuteRows@{\tt DenseMtx\_permuteRows()}}{5}
\indexentry{DenseMtx_permuteColumns@{\tt DenseMtx\_permuteColumns()}}{5}
\indexentry{DenseMtx_sort@{\tt DenseMtx\_sort()}}{5}
\indexentry{DenseMtx_copyRow@{\tt DenseMtx\_copyRow()}}{5}
\indexentry{DenseMtx_copyRowAndIndex@{\tt DenseMtx\_copyRowAndIndex()}}{5}
\indexentry{DenseMtx_addRow@{\tt DenseMtx\_addRow()}}{6}
\indexentry{DenseMtx_zero@{\tt DenseMtx\_zero()}}{6}
\indexentry{DenseMtx_fillRandomEntries@{\tt DenseMtx\_fillRandomEntries()}}{6}
\indexentry{DenseMtx_checksums@{\tt DenseMtx\_checksums()}}{6}
\indexentry{DenseMtx_scale@{\tt DenseMtx\_scale()}}{6}
\indexentry{DenseMtx_maxabs@{\tt DenseMtx\_maxabs()}}{6}
\indexentry{DenseMtx_sub@{\tt DenseMtx\_sub()}}{6}
\indexentry{DenseMtx_copyRowIntoVector@{\tt DenseMtx\_copyRowIntoVector()}}{6}
\indexentry{DenseMtx_copyVectorIntoRow@{\tt DenseMtx\_copyVectorIntoRow()}}{6}
\indexentry{DenseMtx_addVectorIntoRow@{\tt DenseMtx\_addVectorIntoRow()}}{6}
\indexentry{DenseMtx_readFromFile@{\tt DenseMtx\_readFromFile()}}{7}
\indexentry{DenseMtx_readFromFormattedFile@{\tt DenseMtx\_readFromFormattedFile()}}{7}
\indexentry{DenseMtx_readFromBinaryFile@{\tt DenseMtx\_readFromBinaryFile()}}{7}
\indexentry{DenseMtx_writeToFile@{\tt DenseMtx\_writeToFile()}}{7}
\indexentry{DenseMtx_writeToFormattedFile@{\tt DenseMtx\_writeToFormattedFile()}}{7}
\indexentry{DenseMtx_writeToBinaryFile@{\tt DenseMtx\_writeToBinaryFile()}}{7}
\indexentry{DenseMtx_writeStats@{\tt DenseMtx\_writeStats()}}{7}
\indexentry{DenseMtx_writeForHumanEye@{\tt DenseMtx\_writeForHumanEye()}}{7}
\indexentry{DenseMtx_writeForMatlab@{\tt DenseMtx\_writeForMatlab()}}{8}
DenseMtx/doc/main.aux 0100644 0002055 0007177 00000002227 06623357321 0016042 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\contentsline {chapter}{\numberline {1}{\tt DenseMtx}: Dense matrix object}{1}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {1.1}Data Structure}{1}}
\newlabel{section:DenseMtx:dataStructure}{{1.1}{1}}
\@writefile{toc}{\contentsline {section}{\numberline {1.2}Prototypes and descriptions of {\tt DenseMtx} methods}{2}}
\newlabel{section:DenseMtx:proto}{{1.2}{2}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.1}Basic methods}{2}}
\newlabel{subsection:DenseMtx:proto:basics}{{1.2.1}{2}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.2}Instance methods}{2}}
\newlabel{subsection:DenseMtx:proto:instance}{{1.2.2}{2}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.3}Initialization methods}{4}}
\newlabel{subsection:DenseMtx:proto:initial}{{1.2.3}{4}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.4}Utility methods}{5}}
\newlabel{subsection:DenseMtx:proto:utility}{{1.2.4}{5}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.5}IO methods}{7}}
\newlabel{subsection:DenseMtx:proto:IO}{{1.2.5}{7}}
file{lot}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {1.1}Data Structure}{1}}
\newlabel{section:DenseMtx:dataStructure}{{1.1}{1}}
\@writefile{toc}{\contentsline {section}{\numberline {1.2}Prototypes and descriptions of {\tt DenseMtx} methods}{2}}
\newlabel{section:DenseMtx:proto}{{1.2}{2}}
\@writefile{toc}{\contentsline {subsecDenseMtx/doc/main.ind 0100644 0002055 0007177 00000004173 06622345570 0016023 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt DenseMtx\_addRow()}, 6
\item {\tt DenseMtx\_addVectorIntoRow()}, 6
\item {\tt DenseMtx\_checksums()}, 6
\item {\tt DenseMtx\_clearData()}, 2
\item {\tt DenseMtx\_colid()}, 2
\item {\tt DenseMtx\_column()}, 4
\item {\tt DenseMtx\_columnIncrement()}, 2
\item {\tt DenseMtx\_columnIndices()}, 3
\item {\tt DenseMtx\_complexEntry()}, 3
\item {\tt DenseMtx\_copyRow()}, 5
\item {\tt DenseMtx\_copyRowAndIndex()}, 5
\item {\tt DenseMtx\_copyRowIntoVector()}, 6
\item {\tt DenseMtx\_copyVectorIntoRow()}, 6
\item {\tt DenseMtx\_dimensions()}, 2
\item {\tt DenseMtx\_entries()}, 3
\item {\tt DenseMtx\_fillRandomEntries()}, 6
\item {\tt DenseMtx\_free()}, 2
\item {\tt DenseMtx\_init()}, 4
\item {\tt DenseMtx\_initAsSubmatrix()}, 4
\item {\tt DenseMtx\_initFromBuffer()}, 4
\item {\tt DenseMtx\_initWithPointers()}, 4
\item {\tt DenseMtx\_maxabs()}, 6
\item {\tt DenseMtx\_nbytesInWorkspace()}, 5
\item {\tt DenseMtx\_nbytesNeeded()}, 5
\item {\tt DenseMtx\_new()}, 2
\item {\tt DenseMtx\_permuteColumns()}, 5
\item {\tt DenseMtx\_permuteRows()}, 5
\item {\tt DenseMtx\_readFromBinaryFile()}, 7
\item {\tt DenseMtx\_readFromFile()}, 7
\item {\tt DenseMtx\_readFromFormattedFile()}, 7
\item {\tt DenseMtx\_realEntry()}, 3
\item {\tt DenseMtx\_row()}, 4
\item {\tt DenseMtx\_rowid()}, 2
\item {\tt DenseMtx\_rowIncrement()}, 3
\item {\tt DenseMtx\_rowIndices()}, 3
\item {\tt DenseMtx\_scale()}, 6
\item {\tt DenseMtx\_setA2()}, 4
\item {\tt DenseMtx\_setComplexEntry()}, 3
\item {\tt DenseMtx\_setDefaultFields()}, 2
\item {\tt DenseMtx\_setFields()}, 5
\item {\tt DenseMtx\_setNbytesInWorkspace()}, 5
\item {\tt DenseMtx\_setRealEntry()}, 3
\item {\tt DenseMtx\_sort()}, 5
\item {\tt DenseMtx\_sub()}, 6
\item {\tt DenseMtx\_workspace()}, 3
\item {\tt DenseMtx\_writeForHumanEye()}, 7
\item {\tt DenseMtx\_writeForMatlab()}, 8
\item {\tt DenseMtx\_writeStats()}, 7
\item {\tt DenseMtx\_writeToBinaryFile()}, 7
\item {\tt DenseMtx\_writeToFile()}, 7
\item {\tt DenseMtx\_writeToFormattedFile()}, 7
\item {\tt DenseMtx\_zero()}, 6
\end{theindex}
DenseMtx/doc/main.ilg 0100644 0002055 0007177 00000000457 06622345570 0016025 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (52 entries accepted, 0 rejected).
Sorting entries....done (300 comparisons).
Generating output file main.ind....done (56 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
DenseMtx/doc/makefile 0100644 0002055 0007177 00000000027 06560406445 0016075 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
Drand.h 0100644 0002055 0007177 00000000100 06534106367 0013273 0 ustar 00cleve compmath 0000040 0000006 #ifndef _Drand_
#define _Drand_
#include "Drand/Drand.h"
#endif
Drand/Drand.h 0100644 0002055 0007177 00000010606 06535052437 0014336 0 ustar 00cleve compmath 0000040 0000006 /* Drand.h */
#include "../cfiles.h"
/*--------------------------------------------------------------------*/
/*
------------------------------------------------
Double precision random number generator object
there are two modes ---
uniform on [lower,upper] and normal(mean, sigma)
created -- 96may26, cca
------------------------------------------------
*/
typedef
struct _Drand {
double seed1 ;
double seed2 ;
double base1 ;
double base2 ;
double lower ;
double upper ;
double mean ;
double sigma ;
int mode ;
} Drand ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
simplest constructor
created -- 96may26, cca
-----------------------
*/
Drand *
Drand_new (
void
) ;
/*
-----------------------
set the default fields
created -- 96may26, cca
-----------------------
*/
void
Drand_setDefaultFields (
Drand *drand
) ;
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 96may26, cca
--------------------------------------------------
*/
void
Drand_clearData (
Drand *drand
) ;
/*
------------------------------------------
destructor, free's the object and its data
created -- 96may26, cca
------------------------------------------
*/
Drand *
Drand_free (
Drand *drand
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------
initialize the Drand object
created -- 96may26, cca
---------------------------
*/
void
Drand_init (
Drand *drand
) ;
/*
----------------------------------
set the seeds using one input seed
created -- 96may26, cca
----------------------------------
*/
void
Drand_setSeed (
Drand *drand,
int u
) ;
/*
-----------------------------------
set the seeds using two input seeds
created -- 96may26, cca
-----------------------------------
*/
void
Drand_setSeeds (
Drand *drand,
int u,
int v
) ;
/*
--------------------------------------------
set the mode to be uniform in [lower, upper]
created -- 96may26, cca
--------------------------------------------
*/
void
Drand_setUniform (
Drand *drand,
double lower,
double upper
) ;
/*
--------------------------------------
set the mode to be normal(mean, sigma)
created -- 96may26, cca
--------------------------------------
*/
void
Drand_setNormal (
Drand *drand,
double mean,
double sigma
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in util.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------
return a random double precision value
created -- 96may26, cca
--------------------------------------
*/
double
Drand_value (
Drand *drand
) ;
/*
----------------------------------------------------------
fill a double precision complex vector with random numbers
created -- 98jun02, cca
----------------------------------------------------------
*/
void
Drand_fillZvector (
Drand *drand,
int size,
double dvec[]
) ;
/*
--------------------------------------------------
fill a double precision vector with random numbers
created -- 96may26, cca
--------------------------------------------------
*/
void
Drand_fillDvector (
Drand *drand,
int size,
double dvec[]
) ;
/*
-----------------------------------------
fill a integer vector with random numbers
created -- 96may26, cca
-----------------------------------------
*/
void
Drand_fillIvector (
Drand *drand,
int size,
int ivec[]
) ;
/*--------------------------------------------------------------------*/
d_clearData (
Drand *drand
) ;
/*
------------------------------------------
destructor, free's the object anDrand/makefile 0100644 0002055 0007177 00000000223 06636223565 0014633 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd drivers ; make clean
cd doc ; make clean
Drand/src/makefile 0100644 0002055 0007177 00000000637 06636022474 0015427 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = Drand
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(init.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
Drand/src/makeGlobalLib 0100644 0002055 0007177 00000000556 06600261002 0016316 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = Drand
SRC = basics.c \
init.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
Drand/src/basics.c 0100644 0002055 0007177 00000004231 06534105771 0015330 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../Drand.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------
simplest constructor
created -- 96may26, cca
-----------------------
*/
Drand *
Drand_new (
void
) {
Drand *drand ;
ALLOCATE(drand, struct _Drand, 1) ;
Drand_setDefaultFields(drand) ;
return(drand) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 96may26, cca
-----------------------
*/
void
Drand_setDefaultFields (
Drand *drand
) {
if ( drand == NULL ) {
fprintf(stderr, "\n fatal error in Drand_setDefaultFields(%p)"
"\n bad input", drand) ;
exit(-1) ;
}
drand->seed1 = 123456789.0 ;
drand->seed2 = 987654321.0 ;
drand->base1 = 2147483563.0 ;
drand->base2 = 2147483399.0 ;
drand->lower = 0.0 ;
drand->upper = 1.0 ;
drand->mean = 0.0 ;
drand->sigma = 1.0 ;
drand->mode = 1 ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 96may26, cca
--------------------------------------------------
*/
void
Drand_clearData (
Drand *drand
) {
/*
---------------
check the input
---------------
*/
if ( drand == NULL ) {
fprintf(stderr, "\n fatal error in Drand_clearData(%p)"
"\n bad input\n", drand) ;
exit(-1) ;
}
/*
----------------------
set the default fields
----------------------
*/
Drand_setDefaultFields(drand) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
destructor, free's the object and its data
created -- 96may26, cca
------------------------------------------
*/
Drand *
Drand_free (
Drand *drand
) {
if ( drand == NULL ) {
fprintf(stderr, "\n fatal error in Drand_free(%p)"
"\n bad input\n", drand) ;
exit(-1) ;
}
Drand_clearData(drand) ;
FREE(drand) ;
return(NULL) ; }
/*--------------------------------------------------------------------*/
Drand/src/init.c 0100644 0002055 0007177 00000006203 06605467377 0015044 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../Drand.h"
/*--------------------------------------------------------------------*/
/*
---------------------------
initialize the Drand object
created -- 96may26, cca
---------------------------
*/
void
Drand_init (
Drand *drand
) {
/*
---------------
check the input
---------------
*/
if ( drand == NULL ) {
fprintf(stderr, "\n fatal error in Drand_init(%p)"
"\n bad input\n", drand) ;
exit(-1) ;
}
/*
----------------------
set the default fields
----------------------
*/
Drand_setDefaultFields(drand) ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------
set the seeds using one input seed
created -- 96may26, cca
----------------------------------
*/
void
Drand_setSeed (
Drand *drand,
int u
) {
if ( drand == NULL || u <= 0 || u >= drand->base1 ) {
fprintf(stderr, "\n fatal error in Drand_setSeed(%p,%d)"
"\n first seed must in in (0,%.0f)",
drand, u, drand->base1) ;
exit(-1) ;
}
drand->seed1 = u ;
drand->seed2 = fmod(2718.*u, drand->base2) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------
set the seeds using two input seeds
created -- 96may26, cca
-----------------------------------
*/
void
Drand_setSeeds (
Drand *drand,
int u,
int v
) {
if ( drand == NULL
|| u <= 0 || u >= drand->base1
|| v <= 0 || v >= drand->base2 ) {
fprintf(stderr, "\n fatal error in Drand_setSeeds(%p,%d,%d)"
"\n first seed must in in (0,%.0f)"
"\n second seed must in in (0,%.0f)\n",
drand, u, v, drand->base1, drand->base2) ;
exit(-1) ;
}
drand->seed1 = u ;
drand->seed2 = v ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
set the mode to be uniform in [lower, upper]
created -- 96may26, cca
--------------------------------------------
*/
void
Drand_setUniform (
Drand *drand,
double lower,
double upper
) {
/*
---------------
check the input
---------------
*/
if ( drand == NULL || lower > upper ) {
fprintf(stderr, "\n fatal error in Drand_setUniform(%p,%f,%f)"
"\n bad input\n", drand, lower, upper) ;
exit(-1) ;
}
drand->mode = 1 ;
drand->lower = lower ;
drand->upper = upper ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
set the mode to be normal(mean, sigma)
created -- 96may26, cca
--------------------------------------
*/
void
Drand_setNormal (
Drand *drand,
double mean,
double sigma
) {
/*
---------------
check the input
---------------
*/
if ( drand == NULL || sigma <= 0 ) {
fprintf(stderr, "\n fatal error in Drand_setNormal(%p,%f,%f)"
"\n bad input\n", drand, mean, sigma) ;
exit(-1) ;
}
drand->mode = 2 ;
drand->mean = mean ;
drand->sigma = sigma ;
return ; }
/*--------------------------------------------------------------------*/
2) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------
set the seeds using two input seeds
created -- 96may26, cca
-----------------------------------
*/
void
Drand_setSeeds (
Drand *drand,
int u,
int v
) {
if ( drand == NULL
|| u <= 0 || u >= drand->base1
|| v <= 0Drand/src/util.c 0100644 0002055 0007177 00000010163 06535052442 0015037 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../Drand.h"
/*--------------------------------------------------------------------*/
/*
--------------------------------------
return a random double precision value
created -- 96may26, cca
--------------------------------------
*/
double
Drand_value (
Drand *drand
) {
double sum, t ;
/*
---------------
check the input
---------------
*/
if ( drand == NULL ) {
fprintf(stderr, "\n fatal error in Drand_value(%p)"
"\n bad input\n", drand) ;
exit(-1) ;
}
/*
--------------------
switch over the mode
--------------------
*/
if ( drand->mode == 1 ) {
/*
------------
uniform mode
------------
*/
drand->seed1 = fmod(40014*drand->seed1, drand->base1) ;
drand->seed2 = fmod(40692*drand->seed2, drand->base2) ;
t = drand->seed1 - drand->seed2 ;
if ( t <= 0 ) {
t = t + (drand->base1 - 1) ;
}
t = drand->lower + (t/drand->base1)*(drand->upper - drand->lower) ;
} else {
/*
-----------
normal mode
-----------
*/
drand->seed1 = fmod(40014*drand->seed1, drand->base1) ;
drand->seed2 = fmod(40692*drand->seed2, drand->base2) ;
t = drand->seed1 - drand->seed2 ;
if ( t <= 0 ) {
t = t + (drand->base1 - 1) ;
}
t = t / drand->base1 ;
sum = t ;
drand->seed1 = fmod(40014*drand->seed1, drand->base1) ;
drand->seed2 = fmod(40692*drand->seed2, drand->base2) ;
t = drand->seed1 - drand->seed2 ;
if ( t <= 0 ) {
t = t + (drand->base1 - 1) ;
}
t = t / drand->base1 ;
sum += t ;
drand->seed1 = fmod(40014*drand->seed1, drand->base1) ;
drand->seed2 = fmod(40692*drand->seed2, drand->base2) ;
t = drand->seed1 - drand->seed2 ;
if ( t <= 0 ) {
t = t + (drand->base1 - 1) ;
}
t = t / drand->base1 ;
sum += t ;
t = drand->mean + drand->sigma*(2.*sum - 3.) ;
}
return(t) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------
fill a double precision complex vector with random numbers
created -- 98jun02, cca
----------------------------------------------------------
*/
void
Drand_fillZvector (
Drand *drand,
int size,
double dvec[]
) {
int i ;
/*
---------------
check the input
---------------
*/
if ( drand == NULL || size < 0 || dvec == NULL ) {
fprintf(stderr, "\n fatal error in Drand_fillZvector(%p,%d,%p)"
"\n bad input\n", drand, size, dvec) ;
exit(-1) ;
}
/*
---------------
fill the vector
---------------
*/
for ( i = 0 ; i < 2*size ; i++ ) {
dvec[i] = Drand_value(drand) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
fill a double precision vector with random numbers
created -- 96may26, cca
--------------------------------------------------
*/
void
Drand_fillDvector (
Drand *drand,
int size,
double dvec[]
) {
int i ;
/*
---------------
check the input
---------------
*/
if ( drand == NULL || size < 0 || dvec == NULL ) {
fprintf(stderr, "\n fatal error in Drand_fillDvector(%p,%d,%p)"
"\n bad input\n", drand, size, dvec) ;
exit(-1) ;
}
/*
---------------
fill the vector
---------------
*/
for ( i = 0 ; i < size ; i++ ) {
dvec[i] = Drand_value(drand) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------
fill a integer vector with random numbers
created -- 96may26, cca
-----------------------------------------
*/
void
Drand_fillIvector (
Drand *drand,
int size,
int ivec[]
) {
int i ;
/*
---------------
check the input
---------------
*/
if ( drand == NULL || size < 0 || ivec == NULL ) {
fprintf(stderr, "\n fatal error in Drand_fillIvector(%p,%d,%p)"
"\n bad input\n", drand, size, ivec) ;
exit(-1) ;
}
/*
---------------
fill the vector
---------------
*/
for ( i = 0 ; i < size ; i++ ) {
ivec[i] = (int) Drand_value(drand) ;
}
return ; }
/*--------------------------------------------------------------------*/
Drand/drivers/do_testDrand 0100755 0002055 0007177 00000000551 06534105772 0017151 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set msglvl = 5
set msgFile = stdout
set distribution = 2
set param1 = 0
set param2 = 10
set distribution = 1
set param1 = -10
set param2 = 10
set seed1 = 10101
set seed2 = 20304
set n = 100
testDrand $msglvl $msgFile \
$distribution $param1 $param2 $seed1 $seed2 $n
Drand/drivers/makefile 0100644 0002055 0007177 00000000467 06653142421 0016311 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = testDrand
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
testDrand : testDrand.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
Drand/drivers/testDrand.c 0100644 0002055 0007177 00000005725 06535054017 0016711 0 ustar 00cleve compmath 0000040 0000006 /* testDrand.c */
#include "../Drand.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------
test the Drand random number generator object
---------------------------------------------
*/
{
double ddot, dmean, param1, param2 ;
double *dvec ;
Drand drand ;
FILE *msgFile ;
int distribution, ierr, imean, msglvl, n, seed1, seed2 ;
int *ivec ;
if ( argc != 9 ) {
fprintf(stderr,
"\n\n usage : testDrand msglvl msgFile "
"\n distribution param1 param2 seed1 seed2 n"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n distribution -- 1 for uniform(param1,param2)"
"\n -- 2 for normal(param1,param2)"
"\n param1 -- first parameter"
"\n param2 -- second parameter"
"\n seed1 -- first random number seed"
"\n seed2 -- second random number seed"
"\n n -- length of the vector"
"\n"
) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
distribution = atoi(argv[3]) ;
if ( distribution < 1 || distribution > 2 ) {
fprintf(stderr, "\n fatal error in testDrand"
"\n distribution must be 1 (uniform) or 2 (normal)") ;
exit(-1) ;
}
param1 = atof(argv[4]) ;
param2 = atof(argv[5]) ;
seed1 = atoi(argv[6]) ;
seed2 = atoi(argv[7]) ;
n = atoi(argv[8]) ;
Drand_init(&drand) ;
Drand_setSeeds(&drand, seed1, seed2) ;
switch ( distribution ) {
case 1 :
fprintf(msgFile, "\n uniform in [%f,%f]", param1, param2) ;
Drand_setUniform(&drand, param1, param2) ;
break ;
case 2 :
fprintf(msgFile, "\n normal(%f,%f)", param1, param2) ;
Drand_setNormal(&drand, param1, param2) ;
break ;
}
/*
---------------------------------------------
fill the integer and double precision vectors
---------------------------------------------
*/
dvec = DVinit(n, 0.0) ;
Drand_fillDvector(&drand, n, dvec) ;
dmean = DVsum(n, dvec)/n ;
ddot = DVdot(n, dvec, dvec) ;
if ( msglvl > 0 ) {
fprintf(msgFile, "\n dvec mean = %.4f, variance = %.4f",
dmean, sqrt(fabs(ddot - n*dmean)/n)) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n dvec") ;
DVfprintf(msgFile, n, dvec) ;
}
DVqsortUp(n, dvec) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n sorted dvec") ;
DVfprintf(msgFile, n, dvec) ;
}
ivec = IVinit(n, 0) ;
Drand_fillIvector(&drand, n, ivec) ;
imean = IVsum(n, ivec)/n ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n ivec") ;
IVfp80(msgFile, n, ivec, 80, &ierr) ;
}
IVqsortUp(n, ivec) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n sorted ivec") ;
IVfp80(msgFile, n, ivec, 80, &ierr) ;
}
fprintf(msgFile, "\n") ;
return(1) ; }
/*--------------------------------------------------------------------*/
Drand/doc/ 0042755 0002055 0007177 00000000000 06542767377 0013722 5 ustar 00cleve compmath 0000040 0000006 Drand/doc/drivers.tex 0100644 0002055 0007177 00000003054 06534105772 0016101 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt Drand} object}
\label{section:Drand:drivers}
\par
This section contains brief descriptions of the driver programs.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testDrand msglvl msgFile distribution param1 param2 seed1 seed2 n
\end{verbatim}
This driver program test the {\tt Drand} random number generator.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt distribution} parameter specifies the mode of the object.
If {\tt 1}, the distribution is uniform.
If {\tt 2}, the distribution is normal.
\item
When {\tt distribution = 1}, {\tt param1} is the lower bound for
the interval.
When {\tt distribution = 2}, {\tt param1} is the mean for the
normal distribution.
\item
When {\tt distribution = 1}, {\tt param2} is the upper bound for
the interval.
When {\tt distribution = 2}, {\tt param2} is the variance for the
normal distribution.
\item
{\tt seed1} is the first random number seed.
\item
{\tt seed2} is the second random number seed.
\item
{\tt n} is the length of the vector of random numbers to be
generated.
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
Drand/doc/dataStructure.tex 0100640 0002055 0007177 00000001175 06534105772 0017253 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:Drand:dataStructure}
\par
The {\tt Drand} object has nine fields.
\begin{itemize}
\item
{\tt double seed1} : first seed
\item
{\tt double seed2} : second seed
\item
{\tt double base1} : first base
\item
{\tt double base2} : second base
\item
{\tt double lower} : lower bound for a uniform distribution
\item
{\tt double upper} : upper bound for a uniform distribution
\item
{\tt double mean} : mean for a normal distribution
\item
{\tt double sigma} : variation for a normal distribution
\item
{\tt int mode}:
mode of the object, uniform is {\tt 1}, normal is {\tt 2}
\end{itemize}
Drand/doc/intro.tex 0100640 0002055 0007177 00000000553 06534105772 0015553 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt Drand}: \break Simple Random Number Generator}
\par
Finding the same random number generator on a variety of UNIX
systems is not guaranteed to be a success.
Therefore, we wrote a simple random number generator object
taken from \cite{and90-random}.
The {\tt Drand} object provides both normally distributed and
uniformly distributed random numbers.
Drand/doc/main.tex 0100644 0002055 0007177 00000001073 06650656215 0015350 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt Drand} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt Drand} : {\it DRAFT} \quad \today \hrulefill}
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
Drand/doc/proto.tex 0100644 0002055 0007177 00000016320 06535052413 0015560 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt Drand} methods}
\label{section:Drand:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt Drand} object.
\par
\subsection{Basic methods}
\label{subsection:Drand:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Drand * Drand_new ( void ) ;
\end{verbatim}
\index{Drand_new@{\tt Drand\_new()}}
This method simply allocates storage for the {\tt Drand} structure
and then sets the default fields by a call to
{\tt Drand\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_setDefaultFields ( Drand *drand ) ;
\end{verbatim}
\index{Drand_setDefaultFields@{\tt Drand\_setDefaultFields()}}
This method sets the structure's fields to default values.
\begin{center}
\begin{verbatim}
drand->seed1 = 123456789.0 ; drand->seed2 = 987654321.0 ;
drand->base1 = 2147483563.0 ; drand->base2 = 2147483399.0 ;
drand->lower = 0.0 ; drand->upper = 1.0 ;
drand->mean = 0.0 ; drand->sigma = 1.0 ;
drand->mode = 1 ;
\end{verbatim}
\end{center}
The default mode is a uniform distribution on {\tt [0,1]}.
\par \noindent {\it Error checking:}
If {\tt drand} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_clearData ( Drand *drand ) ;
\end{verbatim}
\index{Drand_clearData@{\tt Drand\_clearData()}}
This method clears any data owned by the object.
It then sets the default fields
with a call to {\tt Drand\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt drand} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_free ( Drand *drand ) ;
\end{verbatim}
\index{Drand_free@{\tt Drand\_free()}}
This method frees the object.
It releases any storage by a call to
{\tt Drand\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt drand} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initializer methods}
\label{subsection:Drand:proto:initializers}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_init ( Drand *drand ) ;
\end{verbatim}
\index{Drand_init@{\tt Drand\_init()}}
This initializer simply sets the default fields with a call to
{\tt Drand\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt drand} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_setSeed ( Drand *drand, int seed1 ) ;
\end{verbatim}
\index{Drand_setSeed@{\tt Drand\_setSeed()}}
This method sets the random number seeds using a single input seed.
\par \noindent {\it Error checking:}
If {\tt drand} is {\tt NULL},
or if ${\tt seed1} \le 0$,
or if ${\tt seed1} \ge 2147483563$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_setSeeds ( Drand *drand, int seed1, int seed2 ) ;
\end{verbatim}
\index{Drand_setSeeds@{\tt Drand\_setSeeds()}}
This method sets the random number seeds using two input seeds.
\par \noindent {\it Error checking:}
If {\tt drand} is {\tt NULL},
an error message is printed and the program exits.
\par \noindent {\it Error checking:}
If {\tt drand} is {\tt NULL},
or if ${\tt seed1} \le 0$,
or if ${\tt seed1} \ge 2147483563$,
or if ${\tt seed2} \le 0$,
or if ${\tt seed2} \ge 2147483399$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_setNormal ( Drand *drand, double mean, double sigma ) ;
\end{verbatim}
\index{Drand_setNormal@{\tt Drand\_setNormal()}}
This method sets the mode to be a normal distribution with mean
{\tt mean} and variation {\tt sigma}.
\par \noindent {\it Error checking:}
If {\tt drand} is {\tt NULL},
or if ${\tt sigma} \le 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_setUniform ( Drand *drand, double lower, double upper ) ;
\end{verbatim}
\index{Drand_setUniform@{\tt Drand\_setUniform()}}
This method sets the mode to be a uniform distribution over the
interval {\tt [lower,upper]} ;
\par \noindent {\it Error checking:}
If {\tt drand} is {\tt NULL},
or if ${\tt lower} \ge {\tt upper}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:Drand:proto:utilities}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double Drand_value ( Drand *drand ) ;
\end{verbatim}
\index{Drand_value@{\tt Drand\_value()}}
This method returns a double precision random number.
\par \noindent {\it Error checking:}
If {\tt drand} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_fillZvector ( Drand *drand, int n, double vec[] ) ;
\end{verbatim}
\index{Drand_fillZvector@{\tt Drand\_fillZvector()}}
This method fills a double precision complex vector {\tt vec[]}
with {\tt n} complex random numbers.
\par \noindent {\it Error checking:}
If {\tt drand} or {\tt vec} are {\tt NULL} or if {\tt n < 0 },
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_fillDvector ( Drand *drand, int n, double vec[] ) ;
\end{verbatim}
\index{Drand_fillDvector@{\tt Drand\_fillDvector()}}
This method fills double precision vector {\tt vec[]}
with {\tt n} random numbers.
\par \noindent {\it Error checking:}
If {\tt drand} or {\tt vec} are {\tt NULL} or if {\tt n < 0 },
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Drand_fillIvector ( Drand *drand, int n, int vec[] ) ;
\end{verbatim}
\index{Drand_fillIvector@{\tt Drand\_fillIvector()}}
This method fills {\tt vec[]} with {\tt n} {\tt int} random numbers.
\par \noindent {\it Error checking:}
If {\tt drand} or {\tt vec} are {\tt NULL} or if {\tt n < 0 },
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
Drand/doc/main.log 0100644 0002055 0007177 00000004725 06535052074 0015333 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 2 JUN 1998 12:36
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
)
\@indexfile=\write3
Writing index file main.idx
(main.aux) (intro.tex
Chapter 1.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 1.
LaTeX Warning: Citation `and90-random' on page 1 undefined on input line 6.
) (dataStructure.tex) (proto.tex [1
] [2]) (drivers.tex [3]
Overfull \hbox (10.7556pt too wide) in paragraph at lines 29--34
[] []\elvrm When \elvtt distribution = 1\elvrm , \elvtt param1 \elvrm is the lo
wer bound for the in-ter-val. When \elvtt distribution
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\hbox(0.0+0.0)x0.0
.\glue 0.0
.\hbox(4.86667+0.0)x0.0
..\glue 0.0
..\glue -18.61502
..\glue -5.475
..\hbox(4.86667+0.0)x18.61502, glue set 18.61502fil
...\glue 0.0 plus 1.0fil minus 1.0fil
...\hbox(4.86667+0.0)x0.0, glue set - 5.475fil []
..\glue 5.475
.\penalty 0
.\elvrm W
.etc.
Overfull \hbox (13.49315pt too wide) in paragraph at lines 34--39
[] []\elvrm When \elvtt distribution = 1\elvrm , \elvtt param2 \elvrm is the up
-per bound for the in-ter-val. When \elvtt distribution
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\hbox(0.0+0.0)x0.0
.\glue 0.0
.\hbox(4.86667+0.0)x0.0
..\glue 0.0
..\glue -18.61502
..\glue -5.475
..\hbox(4.86667+0.0)x18.61502, glue set 18.61502fil
...\glue 0.0 plus 1.0fil minus 1.0fil
...\hbox(4.86667+0.0)x0.0, glue set - 5.475fil []
..\glue 5.475
.\penalty 0
.\elvrm W
.etc.
) (main.ind [4] [5
]) (main.aux) )
Here is how much of TeX's memory you used:
208 strings out of 11977
2143 string characters out of 87269
33040 words of memory out of 262141
2142 multiletter control sequences out of 9500
19780 words of font info for 75 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
13i,4n,17p,187b,254s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (5 pages, 9336 bytes).
Drand/doc/main.aux 0100644 0002055 0007177 00000002462 06535052074 0015343 0 ustar 00cleve compmath 0000040 0000006 \relax
\citation{and90-random}
\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}{\string\ptt\space Drand}: \penalty -\@M Simple Random Number Generator}{1}}
\@writefile{lof}{\string\addvspace\space {10\p@ }}
\@writefile{lot}{\string\addvspace\space {10\p@ }}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Data Structure}{1}}
\newlabel{section:Drand:dataStructure}{{1.1}{1}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Prototypes and descriptions of {\string\ptt\space Drand} methods}{1}}
\newlabel{section:Drand:proto}{{1.2}{1}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.1}Basic methods}{2}}
\newlabel{subsection:Drand:proto:basics}{{1.2.1}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Initializer methods}{2}}
\newlabel{subsection:Drand:proto:initializers}{{1.2.2}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.3}Utility methods}{3}}
\newlabel{subsection:Drand:proto:utilities}{{1.2.3}{3}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}Driver programs for the {\string\ptt\space Drand} object}{3}}
\newlabel{section:Drand:drivers}{{1.3}{3}}
Drand/doc/main.idx 0100644 0002055 0007177 00000001226 06535052074 0015327 0 ustar 00cleve compmath 0000040 0000006 \indexentry{Drand_new@{\tt Drand\_new()}}{2}
\indexentry{Drand_setDefaultFields@{\tt Drand\_setDefaultFields()}}{2}
\indexentry{Drand_clearData@{\tt Drand\_clearData()}}{2}
\indexentry{Drand_free@{\tt Drand\_free()}}{2}
\indexentry{Drand_init@{\tt Drand\_init()}}{2}
\indexentry{Drand_setSeed@{\tt Drand\_setSeed()}}{2}
\indexentry{Drand_setSeeds@{\tt Drand\_setSeeds()}}{3}
\indexentry{Drand_setNormal@{\tt Drand\_setNormal()}}{3}
\indexentry{Drand_setUniform@{\tt Drand\_setUniform()}}{3}
\indexentry{Drand_value@{\tt Drand\_value()}}{3}
\indexentry{Drand_fillDvector@{\tt Drand\_fillDvector()}}{3}
\indexentry{Drand_fillIvector@{\tt Drand\_fillIvector()}}{3}
Drand/doc/main.ind 0100644 0002055 0007177 00000000707 06535052071 0015315 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt Drand\_clearData()}, 2
\item {\tt Drand\_fillDvector()}, 3
\item {\tt Drand\_fillIvector()}, 3
\item {\tt Drand\_free()}, 2
\item {\tt Drand\_init()}, 2
\item {\tt Drand\_new()}, 2
\item {\tt Drand\_setDefaultFields()}, 2
\item {\tt Drand\_setNormal()}, 3
\item {\tt Drand\_setSeed()}, 2
\item {\tt Drand\_setSeeds()}, 3
\item {\tt Drand\_setUniform()}, 3
\item {\tt Drand\_value()}, 3
\end{theindex}
Drand/doc/main.ilg 0100644 0002055 0007177 00000000456 06535052071 0015317 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (12 entries accepted, 0 rejected).
Sorting entries....done (46 comparisons).
Generating output file main.ind....done (16 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
Drand/doc/makefile 0100644 0002055 0007177 00000000027 06542767377 0015414 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
EGraph.h 0100644 0002055 0007177 00000000104 06534106402 0013403 0 ustar 00cleve compmath 0000040 0000006 #ifndef _EGraph_
#define _EGraph_
#include "EGraph/EGraph.h"
#endif
EGraph/EGraph.h 0100644 0002055 0007177 00000017033 06534106100 0014555 0 ustar 00cleve compmath 0000040 0000006 /* EGraph.h */
#include "../cfiles.h"
#include "../Graph.h"
#include "../IVL.h"
/*====================================================================*/
/*
---------------------------------------------------------------
the EGraph object stores an element graph
type -- type of element graph
0 --> vertices have unit weight
1 --> vertices are weighted
nelem -- # of elements
nvtx -- # of vertices
adj -- IVL object that holds the lists
of elements and their vertices
vwghts -- pointer to vector of vertex weights, NULL if type = 0
created -- 95nov03, cca
---------------------------------------------------------------
*/
typedef struct _EGraph {
int type ;
int nelem ;
int nvtx ;
IVL *adjIVL ;
int *vwghts ;
} EGraph ;
/*====================================================================*/
/*
------------------------------------------------------------------------
------ methods found in basics.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
constructor
created -- 95nov03, cca
-----------------------
*/
EGraph *
EGraph_new (
void
) ;
/*
-----------------------
set the default fields
created -- 95nov03, cca
-----------------------
*/
void
EGraph_setDefaultFields (
EGraph *eg
) ;/*
-----------------------
clear the data fields
created -- 95nov03, cca
-----------------------
*/
void
EGraph_clearData (
EGraph *eg
) ;
/*
-----------------------
destructor
created -- 95nov03, cca
-----------------------
*/
void
EGraph_free (
EGraph *eg
) ;
/*====================================================================*/
/*
------------------------------------------------------------------------
------ methods found in init.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------
purpose -- initialize the EGraph object
created -- 96oct24, cca
---------------------------------------
*/
void
EGraph_init (
EGraph *egraph,
int type,
int nelem,
int nvtx,
int IVL_type
) ;
/*====================================================================*/
/*
------------------------------------------------------------------------
------ methods found in mkAdjGraph.c -----------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------------
create a Graph object that holds the adjacency graph
of the assembled elements.
created -- 95nov03, cca
----------------------------------------------------
*/
Graph *
EGraph_mkAdjGraph (
EGraph *eg
) ;
/*====================================================================*/
/*
------------------------------------------------------------------------
------ methods found in misc.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------------
make an element graph for a n1 x n2 grid with ncomp components
created -- 95nov03, cca
--------------------------------------------------------------
*/
EGraph *
EGraph_make9P (
int n1,
int n2,
int ncomp
) ;
/*
-------------------------------------------------------------------
make an element graph for a n1 x n2 x n3 grid with ncomp
components
created -- 95nov03, cca
-------------------------------------------------------------------
*/
EGraph *
EGraph_make27P (
int n1,
int n2,
int n3,
int ncomp
) ;
/*====================================================================*/
/*
------------------------
IO methods found in IO.c
-----------------------
*/
/*
-------------------------------------------------
purpose -- to read in a EGraph object from a file
input --
fn -- filename, must be *.egraphb or *.egraphf
return value -- 1 if success, 0 if failure
created -- 95nov03, cca
-------------------------------------------------
*/
int
EGraph_readFromFile (
EGraph *egraph,
char *fn
) ;
/*
--------------------------------------------------------
purpose -- to read a EGraph object from a formatted file
return value -- 1 if success, 0 if failure
created -- 95nov03, cca
--------------------------------------------------------
*/
int
EGraph_readFromFormattedFile (
EGraph *egraph,
FILE *fp
) ;
/*
----------------------------------------------------
purpose -- to read a EGraph object from a binary file
return value -- 1 if success, 0 if failure
created -- 95nov03, cca
----------------------------------------------------
*/
int
EGraph_readFromBinaryFile (
EGraph *egraph,
FILE *fp
) ;
/*
--------------------------------------------
purpose -- to write a EGraph object to a file
input --
fn -- filename
*.egraphb -- binary
*.egraphf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 95nov03, cca
--------------------------------------------
*/
int
EGraph_writeToFile (
EGraph *egraph,
char *fn
) ;
/*
------------------------------------------------------
purpose -- to write a EGraph object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 95nov03, cca
------------------------------------------------------
*/
int
EGraph_writeToFormattedFile (
EGraph *egraph,
FILE *fp
) ;
/*
---------------------------------------------------
purpose -- to write a EGraph object to a binary file
return value -- 1 if success, 0 otherwise
created -- 95nov03, cca
---------------------------------------------------
*/
int
EGraph_writeToBinaryFile (
EGraph *egraph,
FILE *fp
) ;
/*
-------------------------------------------------
purpose -- to write a EGraph object for a human eye
return value -- 1 if success, 0 otherwise
created -- 95nov03, cca
-------------------------------------------------
*/
int
EGraph_writeForHumanEye (
EGraph *egraph,
FILE *fp
) ;
/*
-----------------------------------------------------------
purpose -- to write out the statistics for the EGraph object
return value -- 1 if success, 0 otherwise
created -- 95nov03, cca
-----------------------------------------------------------
*/
int
EGraph_writeStats (
EGraph *egraph,
FILE *fp
) ;
/*====================================================================*/
/*
-------------------------------------
miscellaneous methods found in misc.c
-------------------------------------
*/
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
return the element graph for a 9 point operator on a
n1 x n2 grid with ncomp components at each grid point
-----------------------------------------------------
*/
EGraph *
EGraph_make9P ( int n1, int n2, int ncomp ) ;
/*
----------------------------------------------------------
return the element graph for a 27 point operator on a
n1 x n2 x n3 grid with ncomp components at each grid point
----------------------------------------------------------
*/
EGraph *
EGraph_make27P ( int n1, int n2, int n3, int ncomp ) ;
/*--------------------------------------------------------------------*/
EGraph/makefile 0100644 0002055 0007177 00000000223 06636223567 0014753 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd drivers ; make clean
cd doc ; make clean
EGraph/src/makefile 0100644 0002055 0007177 00000000732 06636022552 0015536 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = EGraph
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(init.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(mkAdjGraph.o) \
$(OBJ).a(misc.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
EGraph/src/makeGlobalLib 0100644 0002055 0007177 00000000621 06600261006 0016431 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = EGraph
SRC = basics.c \
init.c \
IO.c \
mkAdjGraph.c \
misc.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
EGraph/src/IO.c 0100644 0002055 0007177 00000042325 06534106100 0014502 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../EGraph.h"
static const char *suffixb = ".egraphb" ;
static const char *suffixf = ".egraphf" ;
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to read in a EGraph object from a file
input --
fn -- filename, must be *.egraphb or *.egraphf
return value -- 1 if success, 0 if failure
created -- 95nov03, cca
-------------------------------------------------
*/
int
EGraph_readFromFile (
EGraph *egraph,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( egraph == NULL || fn == NULL ) {
fprintf(stderr, "\n error in EGraph_readFromFile(%p,%s)"
"\n bad input\n", egraph, fn) ;
return(0) ;
}
/*
-------------
read the file
-------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "rb")) == NULL ) {
fprintf(stderr, "\n error in EGraph_readFromFile(%p,%s)"
"\n unable to open file %s", egraph, fn, fn) ;
rc = 0 ;
} else {
rc = EGraph_readFromBinaryFile(egraph, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "r")) == NULL ) {
fprintf(stderr, "\n error in EGraph_readFromFile(%p,%s)"
"\n unable to open file %s", egraph, fn, fn) ;
rc = 0 ;
} else {
rc = EGraph_readFromFormattedFile(egraph, fp) ;
fclose(fp) ;
}
} else {
fprintf(stderr, "\n error in EGraph_readFromFile(%p,%s)"
"\n bad EGraph file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
egraph, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
} else {
fprintf(stderr, "\n error in EGraph_readFromFile(%p,%s)"
"\n bad EGraph file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
egraph, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- to read a EGraph object from a formatted file
return value -- 1 if success, 0 if failure
created -- 95nov03, cca
--------------------------------------------------------
*/
int
EGraph_readFromFormattedFile (
EGraph *egraph,
FILE *fp
) {
int nelem, nvtx, rc, type ;
int itemp[6] ;
int *vwghts ;
IVL *adjIVL ;
/*
---------------
check the input
---------------
*/
if ( egraph == NULL || fp == NULL ) {
fprintf(stderr, "\n error in EGraph_readFromFormattedFile(%p,%p)"
"\n bad input\n", egraph, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
EGraph_clearData(egraph) ;
/*
-----------------------------------
read in the three scalar parameters
type, nelem, nvtx
-----------------------------------
*/
if ( (rc = IVfscanf(fp, 3, itemp)) != 3 ) {
fprintf(stderr, "\n error in EGraph_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", egraph, fp, rc, 3) ;
return(0) ;
}
type = itemp[0] ;
nelem = itemp[1] ;
nvtx = itemp[2] ;
/*
----------------------------
initialize the EGraph object
----------------------------
*/
EGraph_init(egraph, type, nelem, nvtx, IVL_CHUNKED) ;
/*
--------------------------
read in the adj IVL object
--------------------------
*/
adjIVL = egraph->adjIVL ;
rc = IVL_readFromFormattedFile(adjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in EGraph_readFromFormattedFile(%p,%p)"
"\n trying to read in adjIVL"
"\n return code %d from IVL_readFormattedFile(%p,%p)",
egraph, fp, rc, adjIVL, fp) ;
return(0) ;
}
if ( type % 2 == 1 ) {
/*
--------------------------
vertex weights are present
--------------------------
*/
vwghts = egraph->vwghts ;
if ( (rc = IVfscanf(fp, nvtx, vwghts)) != nvtx ) {
fprintf(stderr, "\n error in EGraph_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", egraph, fp, rc, nvtx) ;
return(0) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
purpose -- to read a EGraph object from a binary file
return value -- 1 if success, 0 if failure
created -- 95nov03, cca
----------------------------------------------------
*/
int
EGraph_readFromBinaryFile (
EGraph *egraph,
FILE *fp
) {
int nelem, nvtx, rc, type ;
int itemp[6] ;
int *vwghts ;
IVL *adjIVL ;
/*
---------------
check the input
---------------
*/
if ( egraph == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in EGraph_readFromBinaryFile(%p,%p)"
"\n bad input\n", egraph, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
EGraph_clearData(egraph) ;
/*
-----------------------------------
read in the three scalar parameters
type, nelem, nvtx
-----------------------------------
*/
if ( (rc = fread((void *) itemp, sizeof(int), 3, fp)) != 3 ) {
fprintf(stderr, "\n error in EGraph_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", egraph, fp, rc, 3) ;
return(0) ;
}
type = itemp[0] ;
nelem = itemp[1] ;
nvtx = itemp[2] ;
/*
----------------------------
initialize the EGraph object
----------------------------
*/
EGraph_init(egraph, type, nelem, nvtx, IVL_CHUNKED) ;
/*
--------------------------
read in the adj IVL object
--------------------------
*/
adjIVL = egraph->adjIVL ;
rc = IVL_readFromBinaryFile(adjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in EGraph_readFromBinaryFile(%p,%p)"
"\n trying to read in adjIVL"
"\n return code %d from IVL_readBinaryFile(%p,%p)",
egraph, fp, rc, adjIVL, fp) ;
return(0) ;
}
if ( type % 2 == 1 ) {
/*
--------------------------
vertex weights are present
--------------------------
*/
vwghts = egraph->vwghts ;
if ( (rc = fread((void *) vwghts, sizeof(int), nvtx, fp)) != nvtx){
fprintf(stderr, "\n error in EGraph_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", egraph, fp, rc, nvtx) ;
return(0) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
purpose -- to write a EGraph object to a file
input --
fn -- filename
*.egraphb -- binary
*.egraphf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 95nov03, cca
--------------------------------------------
*/
int
EGraph_writeToFile (
EGraph *egraph,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( egraph == NULL || fn == NULL ) {
fprintf(stderr, "\n fatal error in EGraph_writeToFile(%p,%s)"
"\n bad input\n", egraph, fn) ;
return(0) ;
}
if ( egraph->type < 0 || 3 < egraph->type ) {
fprintf(stderr, "\n fatal error in EGraph_writeToFile(%p,%s)"
"\n bad type = %d", egraph, fn, egraph->type) ;
return(0) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in EGraph_writeToFile(%p,%s)"
"\n unable to open file %s", egraph, fn, fn) ;
rc = 0 ;
} else {
rc = EGraph_writeToBinaryFile(egraph, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "w")) == NULL ) {
fprintf(stderr, "\n error in EGraph_writeToFile(%p,%s)"
"\n unable to open file %s", egraph, fn, fn) ;
rc = 0 ;
} else {
rc = EGraph_writeToFormattedFile(egraph, fp) ;
fclose(fp) ;
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in EGraph_writeToFile(%p,%s)"
"\n unable to open file %s", egraph, fn, fn) ;
rc = 0 ;
} else {
rc = EGraph_writeForHumanEye(egraph, fp) ;
fclose(fp) ;
}
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in EGraph_writeToFile(%p,%s)"
"\n unable to open file %s", egraph, fn, fn) ;
rc = 0 ;
} else {
rc = EGraph_writeForHumanEye(egraph, fp) ;
fclose(fp) ;
}
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- to write a EGraph object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 95nov03, cca
------------------------------------------------------
*/
int
EGraph_writeToFormattedFile (
EGraph *egraph,
FILE *fp
) {
int ierr, rc ;
/*
---------------
check the input
---------------
*/
if ( egraph == NULL || fp == NULL ) {
fprintf(stderr,
"\n fatal error in EGraph_writeToFormattedFile(%p,%p)"
"\n bad input\n", egraph, fp) ;
return(0) ;
}
if ( egraph->type < 0 || 1 < egraph->type ) {
fprintf(stderr,
"\n fatal error in EGraph_writeToFormattedFile(%p,%p)"
"\n bad type = %d", egraph, fp, egraph->type) ;
return(0) ;
}
/*
-------------------------------------
write out the three scalar parameters
-------------------------------------
*/
rc = fprintf(fp, "\n %d %d %d",
egraph->type, egraph->nelem, egraph->nvtx) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in EGraph_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from first fprintf\n", egraph, fp, rc) ;
return(0) ;
}
/*
---------------------------------
write out the adjacency structure
---------------------------------
*/
rc = IVL_writeToFormattedFile(egraph->adjIVL, fp) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in EGraph_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from IVL_writeToFormattedFile(%p,%p)"
"\n while attempting to write out adjIVL\n",
egraph, fp, rc, egraph->adjIVL, fp) ;
return(0) ;
}
/*
-----------------------------------------
write out the vwghts[] vector, if present
-----------------------------------------
*/
if ( egraph->type % 2 == 1 ) {
if ( egraph->vwghts == NULL ) {
fprintf(stderr,
"\n fatal error in EGraph_writeToFormattedFile(%p,%p)"
"\n egraph->type = %d, egraph->vwghts == NULL\n",
egraph, fp, egraph->type) ;
return(0) ;
}
IVfp80(fp, egraph->nvtx, egraph->vwghts, 80, &ierr) ;
if ( ierr < 0 ) {
fprintf(stderr,
"\n fatal error in EGraph_writeToFormattedFile(%p,%p)"
"\n ierr = %d, return from vwghts[] IVfp80\n",
egraph, fp, ierr) ;
return(0) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
purpose -- to write a EGraph object to a binary file
return value -- 1 if success, 0 otherwise
created -- 95nov03, cca
---------------------------------------------------
*/
int
EGraph_writeToBinaryFile (
EGraph *egraph,
FILE *fp
) {
int rc ;
int itemp[6] ;
/*
---------------
check the input
---------------
*/
if ( egraph == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in EGraph_writeToBinaryFile(%p,%p)"
"\n bad input\n", egraph, fp) ;
return(0) ;
}
if ( egraph->type < 0 || 3 < egraph->type ) {
fprintf(stderr, "\n fatal error in EGraph_writeToBinaryFile(%p,%p)"
"\n bad type = %d", egraph, fp, egraph->type) ;
return(0) ;
}
/*
-------------------------------------
write out the three scalar parameters
-------------------------------------
*/
itemp[0] = egraph->type ;
itemp[1] = egraph->nelem ;
itemp[2] = egraph->nvtx ;
rc = fwrite((void *) itemp, sizeof(int), 6, fp) ;
if ( rc != 6 ) {
fprintf(stderr, "\n error in EGraph_writeToBinaryFile(%p,%p)"
"\n %d of %d scalar items written\n", egraph, fp, rc, 6) ;
return(0) ;
}
/*
---------------------------------
write out the adjacency structure
---------------------------------
*/
rc = IVL_writeToBinaryFile(egraph->adjIVL, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in EGraph_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from IVL_writeToBinaryFile(%p,%p)"
"\n while attempting to write out adj\n",
egraph, fp, rc, egraph->adjIVL, fp) ;
return(0) ;
}
/*
-----------------------------------------
write out the vwghts[] vector, if present
-----------------------------------------
*/
if ( egraph->type % 2 == 1 ) {
if ( egraph->vwghts == NULL ) {
fprintf(stderr,
"\n fatal error in EGraph_writeToBinaryFile(%p,%p)"
"\n egraph->type = %d, egraph->vwghts == NULL\n",
egraph, fp, egraph->type) ;
return(0) ;
}
rc = fwrite((void *) egraph->vwghts, sizeof(int), egraph->nvtx, fp) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in EGraph_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from vwghts[] fwrite\n",
egraph, fp, rc) ;
return(0) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to write a EGraph object for a human eye
return value -- 1 if success, 0 otherwise
created -- 95nov03, cca
-------------------------------------------------
*/
int
EGraph_writeForHumanEye (
EGraph *egraph,
FILE *fp
) {
int ierr, rc ;
/*
---------------
check the input
---------------
*/
if ( egraph == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in EGraph_writeForHumanEye(%p,%p)"
"\n bad input\n", egraph, fp) ;
exit(-1) ;
}
/*
------------------------
write out the statistics
------------------------
*/
if ( (rc = EGraph_writeStats(egraph, fp)) == 0 ) {
fprintf(stderr, "\n fatal error in EGraph_writeForHumanEye(%p,%p)"
"\n rc = %d, return from EGraph_writeStats(%p,%p)\n",
egraph, fp, rc, egraph, fp) ;
return(0) ;
}
if ( egraph->adjIVL != NULL ) {
/*
----------------------------------
write out the adjacency IVL object
----------------------------------
*/
fprintf(fp, "\n\n adjacency IVL object") ;
rc = IVL_writeForHumanEye(egraph->adjIVL, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in EGraph_writeForHumanEye(%p,%p)"
"\n rc = %d, return from IVL_writeForHumanEye(%p,%p)"
"\n while attempting to write out adjIVL\n",
egraph, fp, rc, egraph->adjIVL, fp) ;
return(0) ;
}
}
/*
----------------------------------------------
write out the vertex weights vector if present
----------------------------------------------
*/
if ( egraph->type % 2 == 1 ) {
if ( egraph->vwghts == NULL ) {
fprintf(stderr,
"\n fatal error in EGraph_writeForHumanEye(%p,%p)"
"\n egraph->type = %d, egraph->vwghts == NULL\n",
egraph, fp, egraph->type) ;
return(0) ;
}
fprintf(fp, "\n\n vertex weights ") ;
IVfp80(fp, egraph->nvtx, egraph->vwghts, 80, &ierr) ;
if ( ierr < 0 ) {
fprintf(stderr,
"\n fatal error in EGraph_writeForHumanEye(%p,%p)"
"\n ierr = %d, return from vwghts[] IVfp80\n",
egraph, fp, ierr) ;
return(0) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- to write out the statistics for the EGraph object
return value -- 1 if success, 0 otherwise
created -- 95nov03, cca
-----------------------------------------------------------
*/
int
EGraph_writeStats (
EGraph *egraph,
FILE *fp
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( egraph == NULL || fp == NULL ) {
fprintf(stderr, "\n error in EGraph_writeStats(%p,%p)"
"\n bad input\n", egraph, fp) ;
exit(-1) ;
}
switch ( egraph->type ) {
case 0 :
rc = fprintf(fp, "\n EGraph : unweighted egraph object :") ;
break ;
case 1 :
rc = fprintf(fp, "\n EGraph : vertices weighted egraph object :") ;
break ;
default :
fprintf(stderr, "\n fatal error in EGraph_writeStats(%p,%p)"
"\n invalid egraph->type = %d\n", egraph, fp, egraph->type) ;
return(0) ;
}
if ( rc < 0 ) { goto IO_error ; }
fflush(fp) ;
rc = fprintf(fp, " %d elements, %d vertices",
egraph->nelem, egraph->nvtx) ;
if ( rc < 0 ) { goto IO_error ; }
fflush(fp) ;
return(1) ;
IO_error :
fprintf(stderr, "\n fatal error in EGraph_writeStats(%p,%p)"
"\n rc = %d, return from fprintf\n", egraph, fp, rc) ;
return(0) ;
}
/*--------------------------------------------------------------------*/
or in EGraph_writeToFile(%p,%s)"
"\n bad type = %d", egraph, fn, egraph->type) ;
return(0) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulengthEGraph/src/basics.c 0100644 0002055 0007177 00000004421 06534106100 0015432 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../EGraph.h"
/*--------------------------------------------------------------------*/
/*
-----------------------
constructor
created -- 95nov03, cca
-----------------------
*/
EGraph *
EGraph_new (
void
) {
EGraph *eg ;
ALLOCATE(eg, struct _EGraph, 1) ;
EGraph_setDefaultFields(eg) ;
return(eg) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 95nov03, cca
-----------------------
*/
void
EGraph_setDefaultFields (
EGraph *eg
) {
if ( eg == NULL ) {
fprintf(stderr, "\n fatal error in Egraph_setDefaultFields(%p)"
"\n bad input\n", eg) ;
exit(-1) ;
}
eg->type = 0 ;
eg->nelem = 0 ;
eg->nvtx = 0 ;
eg->adjIVL = NULL ;
eg->vwghts = NULL ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
clear the data fields
created -- 95nov03, cca
-----------------------
*/
void
EGraph_clearData (
EGraph *eg
) {
if ( eg == NULL ) {
fprintf(stderr, "\n fatal error in Egraph_clearData(%p)"
"\n bad input\n", eg) ;
exit(-1) ;
}
if ( eg->adjIVL != NULL ) {
IVL_free(eg->adjIVL) ;
}
if ( eg->vwghts != NULL ) {
IVfree(eg->vwghts) ;
}
EGraph_setDefaultFields(eg) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
destructor
created -- 95nov03, cca
-----------------------
*/
void
EGraph_free (
EGraph *eg
) {
if ( eg == NULL ) {
fprintf(stderr, "\n fatal error in Egraph_free(%p)"
"\n bad input\n", eg) ;
exit(-1) ;
}
EGraph_clearData(eg) ;
FREE(eg) ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 95nov03, cca
----------------------------------------------
*/
int
EGraph_sizeOf (
EGraph *eg
) {
int bytes ;
bytes = sizeof(struct _EGraph) ;
if ( eg->adjIVL != NULL ) {
bytes += IVL_sizeOf(eg->adjIVL) ;
}
if ( eg->vwghts != NULL ) {
bytes += eg->nvtx * sizeof(int) ;
}
return(bytes) ; }
/*--------------------------------------------------------------------*/
EGraph/src/init.c 0100644 0002055 0007177 00000002246 06534106100 0015134 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../EGraph.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------
purpose -- initialize the EGraph object
created -- 96oct24, cca
---------------------------------------
*/
void
EGraph_init (
EGraph *egraph,
int type,
int nelem,
int nvtx,
int IVL_type
) {
/*
---------------
check the input
---------------
*/
if ( egraph == NULL || type < 0 || type > 1
|| nelem <= 0 || nvtx <= 0 ) {
fprintf(stderr, "\n fatal error in EGraph_init(%p,%d,%d,%d,%d)"
"\n bad input\n", egraph, type, nelem, nvtx, IVL_type) ;
exit(-1) ;
}
/*
----------------------------
clear the data in the object
----------------------------
*/
EGraph_clearData(egraph) ;
/*
---------------------
initialize the object
---------------------
*/
egraph->type = type ;
egraph->nelem = nelem ;
egraph->nvtx = nvtx ;
egraph->adjIVL = IVL_new() ;
IVL_init1(egraph->adjIVL, IVL_type, nelem) ;
if ( type == 1 ) {
egraph->vwghts = IVinit(nvtx, 0) ;
}
return ; }
/*--------------------------------------------------------------------*/
EGraph/src/misc.c 0100644 0002055 0007177 00000012107 06534106100 0015121 0 ustar 00cleve compmath 0000040 0000006 /* misc.C */
#include "../EGraph.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
make an element graph for a n1 x n2 grid with ncomp components
created -- 95nov03, cca
--------------------------------------------------------------
*/
EGraph *
EGraph_make9P (
int n1,
int n2,
int ncomp
) {
EGraph *egraph ;
int eid, icomp, ij, ielem, jelem, m, nelem, nvtx ;
int *list ;
#if MYDEBUG > 0
fprintf(stdout, "\n inside EGraph_make9P(%d,%d,%d)", n1, n2, ncomp) ;
fflush(stdout) ;
#endif
/*
---------------
check the input
---------------
*/
if ( n1 <= 0 || n2 <= 0 || ncomp <= 0 ) {
fprintf(stderr, "\n fatal error in EGraph_make9P(%d,%d,%d)"
"\n bad input\n", n1, n2, ncomp) ;
exit(-1) ;
}
/*
-----------------
create the object
-----------------
*/
nelem = (n1 - 1)*(n2 - 1) ;
nvtx = n1*n2*ncomp ;
egraph = EGraph_new() ;
if ( ncomp == 1 ) {
EGraph_init(egraph, 0, nelem, nvtx, IVL_CHUNKED) ;
} else {
EGraph_init(egraph, 1, nelem, nvtx, IVL_CHUNKED) ;
IVfill(nvtx, egraph->vwghts, ncomp) ;
}
/*
----------------------------
fill the adjacency structure
----------------------------
*/
list = IVinit(4*ncomp, -1) ;
for ( jelem = 0 ; jelem < n2 - 1 ; jelem++ ) {
for ( ielem = 0 ; ielem < n1 - 1 ; ielem++ ) {
eid = ielem + jelem * (n1 - 1) ;
m = 0 ;
ij = ncomp*(ielem + jelem*n1) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ij++ ;
}
ij = ncomp*(ielem + 1 + jelem*n1) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ij++ ;
}
ij = ncomp*(ielem + (jelem+1)*n1) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ij++ ;
}
ij = ncomp*(ielem + 1 + (jelem+1)*n1) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ij++ ;
}
IVqsortUp(m, list) ;
IVL_setList(egraph->adjIVL, eid, m, list) ;
}
}
IVfree(list) ;
return(egraph) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
make an element graph for a n1 x n2 x n3 grid with ncomp components
created -- 95nov03, cca
-------------------------------------------------------------------
*/
EGraph *
EGraph_make27P (
int n1,
int n2,
int n3,
int ncomp
) {
EGraph *egraph ;
int eid, icomp, ijk, ielem, jelem, kelem, m, nelem, nvtx ;
int *list ;
/*
---------------
check the input
---------------
*/
if ( n1 <= 0 || n2 <= 0 || n3 <= 0 || ncomp <= 0 ) {
fprintf(stderr, "\n fatal error in EGraph_make27P(%d,%d,%d,%d)"
"\n bad input\n", n1, n2, n3, ncomp) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n inside EGraph_make27P(%d,%d,%d,%d)",
n1, n2, n3, ncomp) ;
fflush(stdout) ;
#endif
/*
-----------------
create the object
-----------------
*/
nelem = (n1 - 1)*(n2 - 1)*(n3 - 1) ;
nvtx = n1*n2*n3*ncomp ;
egraph = EGraph_new() ;
if ( ncomp == 1 ) {
EGraph_init(egraph, 0, nelem, nvtx, IVL_CHUNKED) ;
} else {
EGraph_init(egraph, 1, nelem, nvtx, IVL_CHUNKED) ;
IVfill(nvtx, egraph->vwghts, ncomp) ;
}
/*
----------------------------
fill the adjacency structure
----------------------------
*/
list = IVinit(8*ncomp, -1) ;
for ( kelem = 0 ; kelem < n3 - 1 ; kelem++ ) {
for ( jelem = 0 ; jelem < n2 - 1 ; jelem++ ) {
for ( ielem = 0 ; ielem < n1 - 1 ; ielem++ ) {
eid = ielem + jelem*(n1-1) + kelem*(n1-1)*(n2-1);
m = 0 ;
ijk = ncomp*(ielem + jelem*n1 + kelem*n1*n2) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ijk++ ;
}
ijk = ncomp*(ielem + 1 + jelem*n1 + kelem*n1*n2) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ijk++ ;
}
ijk = ncomp*(ielem + (jelem+1)*n1 + kelem*n1*n2) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ijk++ ;
}
ijk = ncomp*(ielem + 1 + (jelem+1)*n1 + kelem*n1*n2) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ijk++ ;
}
ijk = ncomp*(ielem + jelem*n1 + (kelem+1)*n1*n2) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ijk++ ;
}
ijk = ncomp*(ielem + 1 + jelem*n1 + (kelem+1)*n1*n2) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ijk++ ;
}
ijk = ncomp*(ielem + (jelem+1)*n1 + (kelem+1)*n1*n2) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ijk++ ;
}
ijk = ncomp*(ielem + 1 + (jelem+1)*n1 + (kelem+1)*n1*n2) ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
list[m++] = ijk++ ;
}
IVqsortUp(m, list) ;
IVL_setList(egraph->adjIVL, eid, m, list) ;
}
}
}
IVfree(list) ;
return(egraph) ; }
/*--------------------------------------------------------------------*/
EGraph/src/mkAdjGraph.c 0100644 0002055 0007177 00000006411 06535772440 0016220 0 ustar 00cleve compmath 0000040 0000006 /* mkAdjGraph.c.c */
#include "../EGraph.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
create a Graph object that holds the adjacency graph
of the assembled elements.
created -- 95nov03, cca
----------------------------------------------------
*/
Graph *
EGraph_mkAdjGraph (
EGraph *egraph
) {
int elem, esize, i, nelem, nvtx, v, vsize, w ;
int *eind, *head, *link, *marker, *offsets, *vind ;
IVL *eadjIVL, *gadjIVL ;
Graph *graph ;
/*
---------------
check the input
---------------
*/
if ( egraph == NULL || (eadjIVL = egraph->adjIVL) == NULL ) {
fprintf(stderr, "\n fatal error in EGraph_mkAdjGraph(%p)"
"\n bad input\n", egraph) ;
exit(-1) ;
}
nelem = egraph->nelem ;
nvtx = egraph->nvtx ;
/*
--------------------------------
set up the linked list structure
--------------------------------
*/
head = IVinit(nvtx, -1) ;
link = IVinit(nelem, -1) ;
offsets = IVinit(nelem, 0) ;
/*
-----------------------------------------------------------
sort the vertices in each element list into ascending order
and link them into their first vertex
-----------------------------------------------------------
*/
for ( elem = 0 ; elem < nelem ; elem++ ) {
IVL_listAndSize(eadjIVL, elem, &esize, &eind) ;
if ( esize > 0 ) {
IVqsortUp(esize, eind) ;
v = eind[0] ;
link[elem] = head[v] ;
head[v] = elem ;
}
}
/*
---------------------------
create the new Graph object
---------------------------
*/
graph = Graph_new() ;
Graph_init1(graph, egraph->type, nvtx, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ;
gadjIVL = graph->adjIVL ;
/*
----------------------
loop over the vertices
----------------------
*/
vind = IVinit(nvtx, -1) ;
marker = IVinit(nvtx, -1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
/*
---------------------------------
loop over the supporting elements
---------------------------------
*/
vsize = 0 ;
vind[vsize++] = v ;
marker[v] = v ;
while ( (elem = head[v]) != -1 ) {
/*
fprintf(stdout, "\n checking out element %d :", jelem) ;
*/
head[v] = link[elem] ;
IVL_listAndSize(eadjIVL, elem, &esize, &eind) ;
for ( i = 0 ; i < esize ; i++ ) {
w = eind[i] ;
if ( marker[w] != v ) {
marker[w] = v ;
vind[vsize++] = w ;
}
}
if ( (i = ++offsets[elem]) < esize ) {
w = eind[i] ;
link[elem] = head[w] ;
head[w] = elem ;
}
}
IVqsortUp(vsize, vind) ;
IVL_setList(gadjIVL, v, vsize, vind) ;
}
graph->nedges = gadjIVL->tsize ;
if ( egraph->type == 0 ) {
graph->totvwght = nvtx ;
} else if ( egraph->type == 1 ) {
/*
------------------------------
fill the vertex weights vector
------------------------------
*/
IVcopy(nvtx, graph->vwghts, egraph->vwghts) ;
graph->totvwght = IVsum(nvtx, graph->vwghts) ;
}
graph->totewght = graph->nedges ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(head) ;
IVfree(link) ;
IVfree(marker) ;
IVfree(vind) ;
IVfree(offsets) ;
return(graph) ; }
/*--------------------------------------------------------------------*/
EGraph/drivers/do_mkGraph 0100755 0002055 0007177 00000000423 06534106077 0016725 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inFile = $matrices/$matrix/orig.egraphf
set outFile = $matrices/$matrix/orig0.graphf
set outFile = temp.graphf
set msglvl = 3
set msgFile = stdout
mkGraph $msglvl $msgFile $inFile $outFile
EGraph/drivers/do_mkGridEGraph 0100755 0002055 0007177 00000000305 06534106077 0017637 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set msglvl = 3
set msgFile = stdout
set n1 = 3
set n2 = 3
set n3 = 3
set ncomp = 1
set outFile = temp.egraphf
mkGridEGraph $msglvl $msgFile $n1 $n2 $n3 $ncomp $outFile
EGraph/drivers/do_testIO 0100755 0002055 0007177 00000000413 06534106077 0016542 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inFile = $matrices/$matrix/orig.egraphf
set outFile = $matrices/$matrix/orig.egraphb
set outFile = none
set msglvl = 3
set msgFile = stdout
testIO $msglvl $msgFile $inFile $outFile
EGraph/drivers/makefile 0100644 0002055 0007177 00000001036 06653142426 0016425 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = testIO \
mkGraph \
mkGridEGraph
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
mkGraph : mkGraph.o ../../spooles.a
$(PURIFY) $(CC) $@.o -o $@ $(PURIFY_GCC_VERSION) $(LIBS)
mkGridEGraph : mkGridEGraph.o ../../spooles.a
$(PURIFY) $(CC) $@.o -o $@ $(PURIFY_GCC_VERSION)$(LIBS)
testIO : testIO.o ../../spooles.a
$(PURIFY) $(CC) $@.o -o $@ $(PURIFY_GCC_VERSION) $(LIBS)
EGraph/drivers/mkGraph.c 0100644 0002055 0007177 00000005767 06542224021 0016466 0 ustar 00cleve compmath 0000040 0000006 /* mkGraph.c */
#include "../EGraph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
--------------------------------------------------
1. read in EGraph object
2. convert to Graph object
3. write Graph object to file
created -- 96feb09, cca
--------------------------------------------------
*/
{
double t1, t2 ;
int msglvl, rc ;
EGraph *egraph ;
FILE *msgFile ;
Graph *graph ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inEGraphFile outGraphFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inEGraphFile -- input file, must be *.egraphf or *.egraphb"
"\n outGraphFile -- output file, must be *.graphf or *.graphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], argv[3], argv[4]) ;
fflush(msgFile) ;
/*
-------------------------
read in the EGraph object
-------------------------
*/
if ( strcmp(argv[3], "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
egraph = EGraph_new() ;
EGraph_setDefaultFields(egraph) ;
rc = EGraph_readFromFile(egraph, argv[3]) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in egraph from file %s",
t2 - t1, argv[3]) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from EGraph_readFromFile(%p,%s)",
rc, egraph, argv[3]) ;
exit(-1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n after reading EGraph object from file %s",
argv[3]) ;
EGraph_writeForHumanEye(egraph, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------
create the Graph object
-----------------------
*/
MARKTIME(t1) ;
graph = EGraph_mkAdjGraph(egraph) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : convert to Graph object", t2 - t1) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n Graph object") ;
Graph_writeForHumanEye(graph, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------
write out the Graph object
--------------------------
*/
if ( strcmp(argv[4], "none") != 0 ) {
MARKTIME(t1) ;
rc = Graph_writeToFile(graph, argv[4]) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write graph to file %s",
t2 - t1, argv[4]) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_writeToFile(%p,%s)",
rc, graph, argv[4]) ;
}
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
EGraph/drivers/mkGridEGraph.c 0100644 0002055 0007177 00000005331 06542223763 0017400 0 ustar 00cleve compmath 0000040 0000006 /* mkGridEgraph.c */
#include "../EGraph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------
generate an Egraph object for a 9pt or 27pt grid
optionally write out to a file
created -- 95nov08, cca
-------------------------------------------------
*/
{
double t1, t2 ;
int msglvl, n1, n2, n3, ncomp, rc ;
EGraph *eg ;
FILE *msgFile ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile n1 n2 n3 ncomp outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n n1 -- # of points in first grid direction"
"\n n2 -- # of points in second grid direction"
"\n n3 -- # of points in third grid direction"
"\n ncomp -- # of components per grid point"
"\n outFile -- output file, must be *.egraphf or *.egraphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
n1 = atoi(argv[3]) ;
n2 = atoi(argv[4]) ;
n3 = atoi(argv[5]) ;
ncomp = atoi(argv[6]) ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n n1 -- %d"
"\n n2 -- %d"
"\n n3 -- %d"
"\n ncomp -- %d"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], n1, n2, n3, ncomp, argv[7]) ;
fflush(msgFile) ;
/*
---------------------------
create in the EGraph object
---------------------------
*/
MARKTIME(t1) ;
if ( n3 == 1 ) {
eg = EGraph_make9P(n1, n2, ncomp) ;
} else {
eg = EGraph_make27P(n1, n2, n3, ncomp) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : create the Egraph object", t2 - t1) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n EGraph object") ;
EGraph_writeForHumanEye(eg, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
write out the EGraph object
---------------------------
*/
if ( strcmp(argv[7], "none") != 0 ) {
MARKTIME(t1) ;
rc = EGraph_writeToFile(eg, argv[7]) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write graph to file %s",
t2 - t1, argv[7]) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from Graph_writeToFile(%p,%s)",
rc, eg, argv[7]) ;
}
}
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
EGraph/drivers/testIO.c 0100644 0002055 0007177 00000005565 06542223776 0016320 0 ustar 00cleve compmath 0000040 0000006 /* testIO.c */
#include "../EGraph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
--------------------------------------------------
test EGraph_readFromFile and EGraph_writeToFile,
useful for translating between formatted *.egraphf
and binary *.egraphb files.
created -- 95nov03, cca
--------------------------------------------------
*/
{
double t1, t2 ;
int msglvl, rc ;
EGraph egraph ;
FILE *msgFile ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.egraphf or *.egraphb"
"\n outFile -- output file, must be *.egraphf or *.egraphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], argv[3], argv[4]) ;
fflush(msgFile) ;
/*
----------------------
set the default fields
----------------------
*/
EGraph_setDefaultFields(&egraph) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n after setting default fields") ;
EGraph_writeForHumanEye(&egraph, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------
read in the EGraph object
-------------------------
*/
if ( strcmp(argv[3], "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
rc = EGraph_readFromFile(&egraph, argv[3]) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in egraph from file %s",
t2 - t1, argv[3]) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from EGraph_readFromFile(%p,%s)",
rc, &egraph, argv[3]) ;
exit(-1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n after reading EGraph object from file %s",
argv[3]) ;
EGraph_writeForHumanEye(&egraph, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
write out the EGraph object
---------------------------
*/
if ( strcmp(argv[4], "none") != 0 ) {
MARKTIME(t1) ;
rc = EGraph_writeToFile(&egraph, argv[4]) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write egraph to file %s",
t2 - t1, argv[4]) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from EGraph_writeToFile(%p,%s)",
rc, &egraph, argv[4]) ;
}
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
EGraph/doc/ 0042755 0002055 0007177 00000000000 06542767377 0014040 5 ustar 00cleve compmath 0000040 0000006 EGraph/doc/dataStructure.tex 0100640 0002055 0007177 00000001544 06534106100 0017353 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\par
The {\tt EGraph} object has five fields.
\begin{itemize}
\item {\tt int type} :
type of graph.
When {\tt type = 0}, the vertices have unit weight
When {\tt type = 1}, the vertices have possibly non-unit weight
and the {\tt vwghts} field is not {\tt NULL}.
\item {\tt int nelem} :
number of elements in the graph
\item {\tt int nvtx} :
number of vertices in the graph
\item {\tt IVL *adjIVL} :
pointer to a {\tt IVL} structure that holds the vertex lists for
the elements.
\item {\tt int *vwghts} :
when {\tt type = 1}, {\tt vwghts}
points to an {\tt int} vector of size {\tt nvtx}
that holds the
node weights.
\end{itemize}
A correctly initialized and nontrivial {\tt EGraph} object
will have positive {\tt nelem} and {\tt nvtx} values,
a valid {\tt adjIVL} field.
If {\tt type = 1}, the {\tt vwghts} will be non-{\tt NULL}.
EGraph/doc/intro.tex 0100640 0002055 0007177 00000002371 06534106100 0015653 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt EGraph}: Element Graph Object}
\par
The {\tt EGraph} object is used to model a graph that has a natural
element structure (as from finite elements) or a natural covering
clique structure (e.g., the rows of $A$ are natural cliques for
the graph of $A^TA$).
\par
Translating an element graph {\tt EGraph} object
into an adjacency list {\tt Graph} object is an easy task ---
we provide a method to do so --- but the process in reverse is much
more difficult.
Given a {\tt Graph} object, it is simple to construct a trivial
element graph object, simply take each $(i,j)$ edge to be an element.
Constructing an element graph with a smaller number of elements
is more difficult.
\par
Element graphs, when they arise naturally or are constructed from
an adjacency graph, have great potential.
The element model for sparse elimination {\it appears} to be more
powerful than the vertex adjacency list model in the sense that
concepts like indistinguishability, outmatching and deficiency are
more naturally defined with elements.
An element graph might be a more natural vehicle for partitioning
graphs, because if one consider elements as the ``nodes'' in a
Kernighan-Lin type algorithm, then the ``edge'' separators are
formed of vertices of the original graph.
EGraph/doc/main.tex 0100644 0002055 0007177 00000001102 06650656217 0015461 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt EGraph} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt EGraph} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
EGraph/doc/main.ind 0100644 0002055 0007177 00000001232 06535772277 0015446 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt EGraph\_clearData()}, 2
\item {\tt EGraph\_free()}, 2
\item {\tt EGraph\_init()}, 2
\item {\tt EGraph\_make27P()}, 3
\item {\tt EGraph\_make9P()}, 3
\item {\tt EGraph\_mkAdjGraph()}, 3
\item {\tt EGraph\_new()}, 2
\item {\tt EGraph\_readFromBinaryFile()}, 3
\item {\tt EGraph\_readFromFile()}, 3
\item {\tt EGraph\_readFromFormattedFile()}, 3
\item {\tt EGraph\_setDefaultFields()}, 2
\item {\tt EGraph\_writeForHumanEye()}, 4
\item {\tt EGraph\_writeStats()}, 4
\item {\tt EGraph\_writeToBinaryFile()}, 4
\item {\tt EGraph\_writeToFile()}, 4
\item {\tt EGraph\_writeToFormattedFile()}, 4
\end{theindex}
EGraph/doc/main.log 0100644 0002055 0007177 00000006272 06535772302 0015453 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 5 JUN 1998 06:38
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
)
\@indexfile=\write3
Writing index file main.idx
(main.aux) (intro.tex
Chapter 1.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 1.
) (dataStructure.tex) (proto.tex [1
]
Overfull \hbox (12.76239pt too wide) in paragraph at lines 43--53
\elvrm is not \elvtt NULL\elvrm , then \elvtt IVL[]free(egraph->adjIVL) \elvrm
is called to free the \elvtt IVL \elvrm ob-ject. If \elvtt egraph->vwghts
\hbox(7.60416+2.43333)x442.37993, glue set - 1.0
.\elvrm i
.\elvrm s
.\glue 3.65 plus 1.825 minus 1.21666
.\elvrm n
.\elvrm o
.etc.
[2]
Overfull \hbox (3.0602pt too wide) in paragraph at lines 138--145
\elvrm the grid points. The re-sult-ing graph has \elvtt n1*n2*n3*ncomp \elvrm
ver-tices and \elvtt (n1-1)*(n2-1)*(n3-1)
\hbox(7.60416+2.43333)x442.37993, glue set - 1.0
.\elvrm t
.\elvrm h
.\elvrm e
.\glue 3.65 plus 1.825 minus 1.21666
.\elvrm g
.etc.
[3]) (drivers.tex
Overfull \hbox (42.63402pt too wide) in paragraph at lines 30--35
\elvtt *.egraphf \elvrm or \elvtt *.egraphb\elvrm . The \elvtt EGraph \elvrm ob
-ject is read from the file via the \elvtt EGraph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt e
.\elvtt g
.\elvtt r
.etc.
[4]
Overfull \hbox (1.44826pt too wide) in paragraph at lines 114--122
[] []\elvrm The \elvtt outEGraphFile \elvrm pa-ram-e-ter is the out-put file fo
r the \elvtt EGraph \elvrm ob-ject. If \elvtt outEGraphFile
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\hbox(0.0+0.0)x0.0
.\glue 0.0
.\hbox(4.86667+0.0)x0.0
..\glue 0.0
..\glue -18.61502
..\glue -5.475
..\hbox(4.86667+0.0)x18.61502, glue set 18.61502fil
...\glue 0.0 plus 1.0fil minus 1.0fil
...\hbox(4.86667+0.0)x0.0, glue set - 5.475fil []
..\glue 5.475
.\penalty 0
.\elvrm T
.etc.
Overfull \hbox (18.78839pt too wide) in paragraph at lines 114--122
\elvrm is \elvtt none \elvrm then the \elvtt EGraph \elvrm ob-ject is not writ-
ten to a file. Oth-er-wise, the \elvtt EGraph[]writeToFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvrm i
.\elvrm s
.\glue 3.65 plus 1.825 minus 1.21666
.\elvtt n
.\elvtt o
.etc.
[5]) (main.ind [6] [7
]) (main.aux) )
Here is how much of TeX's memory you used:
207 strings out of 11977
2133 string characters out of 87269
33495 words of memory out of 262141
2141 multiletter control sequences out of 9500
19780 words of font info for 75 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
14i,4n,17p,183b,260s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (7 pages, 18668 bytes).
EGraph/doc/main.aux 0100644 0002055 0007177 00000002564 06535772302 0015467 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}{\string\ptt\space EGraph}: Element Graph Object}{1}}
\@writefile{lof}{\string\addvspace\space {10\p@ }}
\@writefile{lot}{\string\addvspace\space {10\p@ }}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Data Structure}{1}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Prototypes and descriptions of {\string\ptt\space EGraph} methods}{2}}
\newlabel{section:EGraph:proto}{{1.2}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.1}Basic methods}{2}}
\newlabel{subsection:EGraph:proto:basics}{{1.2.1}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Initializer methods}{2}}
\newlabel{subsection:EGraph:proto:initializers}{{1.2.2}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.3}Utility methods}{3}}
\newlabel{subsection:EGraph:proto:utilities}{{1.2.3}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.4}IO methods}{3}}
\newlabel{subsection:EGraph:proto:IO}{{1.2.4}{3}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}Driver programs for the {\string\ptt\space EGraph} object}{4}}
\newlabel{section:EGraph:drivers}{{1.3}{4}}
EGraph/doc/main.idx 0100644 0002055 0007177 00000002000 06535772302 0015437 0 ustar 00cleve compmath 0000040 0000006 \indexentry{EGraph_new@{\tt EGraph\_new()}}{2}
\indexentry{EGraph_setDefaultFields@{\tt EGraph\_setDefaultFields()}}{2}
\indexentry{EGraph_clearData@{\tt EGraph\_clearData()}}{2}
\indexentry{EGraph_free@{\tt EGraph\_free()}}{2}
\indexentry{EGraph_init@{\tt EGraph\_init()}}{2}
\indexentry{EGraph_mkAdjGraph@{\tt EGraph\_mkAdjGraph()}}{3}
\indexentry{EGraph_make9P@{\tt EGraph\_make9P()}}{3}
\indexentry{EGraph_make27P@{\tt EGraph\_make27P()}}{3}
\indexentry{EGraph_readFromFile@{\tt EGraph\_readFromFile()}}{3}
\indexentry{EGraph_readFromFormattedFile@{\tt EGraph\_readFromFormattedFile()}}{3}
\indexentry{EGraph_readFromBinaryFile@{\tt EGraph\_readFromBinaryFile()}}{3}
\indexentry{EGraph_writeToFile@{\tt EGraph\_writeToFile()}}{4}
\indexentry{EGraph_writeToFormattedFile@{\tt EGraph\_writeToFormattedFile()}}{4}
\indexentry{EGraph_writeToBinaryFile@{\tt EGraph\_writeToBinaryFile()}}{4}
\indexentry{EGraph_writeForHumanEye@{\tt EGraph\_writeForHumanEye()}}{4}
\indexentry{EGraph_writeStats@{\tt EGraph\_writeStats()}}{4}
EGraph/doc/proto.tex 0100644 0002055 0007177 00000026250 06534106100 0015671 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt EGraph} methods}
\label{section:EGraph:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt EGraph} object.
\par
\subsection{Basic methods}
\label{subsection:EGraph:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
EGraph * EGraph_new ( void ) ;
\end{verbatim}
\index{EGraph_new@{\tt EGraph\_new()}}
This method simply allocates storage for the {\tt EGraph} structure
and then sets the default fields by a call to
{\tt EGraph\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void EGraph_setDefaultFields ( EGraph *egraph ) ;
\end{verbatim}
\index{EGraph_setDefaultFields@{\tt EGraph\_setDefaultFields()}}
This method sets the structure's fields are set to default values:
{\tt type = nelem = nvtx = 0}, {\tt adjIVL = vwghts = NULL}.
\par \noindent {\it Error checking:}
If {\tt egraph} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void EGraph_clearData ( EGraph *egraph ) ;
\end{verbatim}
\index{EGraph_clearData@{\tt EGraph\_clearData()}}
This method clears data and releases any storage allocated by the
object.
If {\tt egraph->adjIVL} is not {\tt NULL},
then {\tt IVL\_free(egraph->adjIVL)} is called to free the {\tt IVL}
object.
If {\tt egraph->vwghts} is not {\tt NULL},
then {\tt IVfree(egraph->vwghts)} is called to free the {\tt int}
vector.
It then sets the structure's default fields
with a call to {\tt EGraph\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt egraph} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void EGraph_free ( EGraph *egraph ) ;
\end{verbatim}
\index{EGraph_free@{\tt EGraph\_free()}}
This method releases any storage by a call to
{\tt EGraph\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt egraph} is {\tt NULL}
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initializer methods}
\label{subsection:EGraph:proto:initializers}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void EGraph_init ( EGraph *egraph, int type, int nelem, int nvtx,
int IVL_type ) ;
\end{verbatim}
\index{EGraph_init@{\tt EGraph\_init()}}
This method initializes an {\tt EGraph} object given
the type of vertices, number of elements, number of vertices,
and storage type for the {\tt IVL} element list object.
It then clears any previous data with a call to
{\tt EGraph\_clearData()}.
The {\tt IVL} object is initialized by a call to {\tt IVL\_init1()}.
If {\tt type = 1}, the {\tt vwghts} is initialized via a call to
{\tt IVinit()}.
See the {\tt IVL} object for a description of the {\tt IVL\_type}
parameter.
\par \noindent {\it Error checking:}
If {\tt egraph} is {\tt NULL} or {\tt type} is not zero or one,
or if either {\tt nelem} or {\tt nvtx} are nonpositive,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:EGraph:proto:utilities}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Graph EGraph_mkAdjGraph ( EGraph *egraph ) ;
\end{verbatim}
\index{EGraph_mkAdjGraph@{\tt EGraph\_mkAdjGraph()}}
This method creates and returns a {\tt Graph} object
with vertex adjacency lists from the element graph object.
\par \noindent {\it Error checking:}
If {\tt egraph} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
EGraph * EGraph_make9P ( int n1, int n2, int ncomp ) ;
\end{verbatim}
\index{EGraph_make9P@{\tt EGraph\_make9P()}}
This method creates and returns a {\tt EGraph} object
for a $\mbox{\tt n1} \times \mbox{\tt n2}$ grid for a 9-point
operator matrix.
Each element is a linear quadrilateral finite element with {\tt
ncomp} degrees of freedom at the grid points.
The resulting graph has {\tt n1*n2*ncomp} vertices and
{\tt (n1-1)*(n2-1)} elements.
\par \noindent {\it Error checking:}
If {\tt n1}, {\tt n2} or {\tt ncomp} is less than or equal to zero,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
EGraph * EGraph_make27P ( int n1, int n2, int n3, int ncomp ) ;
\end{verbatim}
\index{EGraph_make27P@{\tt EGraph\_make27P()}}
This method creates and returns a {\tt EGraph} object
for a $\mbox{\tt n1} \times \mbox{\tt n2} \times \mbox{\tt n3}$ grid
for a 27-point operator matrix.
Each element is a linear hexahedral finite element with {\tt
ncomp} degrees of freedom at the grid points.
The resulting graph has {\tt n1*n2*n3*ncomp} vertices and
{\tt (n1-1)*(n2-1)*(n3-1)} elements.
\par \noindent {\it Error checking:}
If {\tt n1}, {\tt n2}, {\tt n3} or {\tt ncomp}
is less than or equal to zero,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:EGraph:proto:IO}
\par
There are the usual eight IO routines.
The file structure of a EGraph object is simple:
{\tt type}, {\tt nelem}, {\tt nvtx},
an {\tt IVL} object,
and an {\tt int} vector if {\tt vwghts} is not {\tt NULL}.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int EGraph_readFromFile ( EGraph *egraph, char *fn ) ;
\end{verbatim}
\index{EGraph_readFromFile@{\tt EGraph\_readFromFile()}}
\par
This method reads an {\tt EGraph} object from a file.
It tries to open the file and if it is successful,
it then calls {\tt EGraph\_readFromFormattedFile()} or
{\tt EGraph\_readFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt egraph} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.egraphf} (for a formatted file)
or {\tt *.egraphb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int EGraph_readFromFormattedFile ( EGraph *egraph, FILE *fp ) ;
\end{verbatim}
\index{EGraph_readFromFormattedFile@{\tt EGraph\_readFromFormattedFile()}}
\par
This method reads in an {\tt EGraph} object from a formatted file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fscanf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt egraph} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int EGraph_readFromBinaryFile ( EGraph *egraph, FILE *fp ) ;
\end{verbatim}
\index{EGraph_readFromBinaryFile@{\tt EGraph\_readFromBinaryFile()}}
\par
This method reads in an {\tt EGraph} object from a binary file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fread}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt egraph} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int EGraph_writeToFile ( EGraph *egraph, char *fn ) ;
\end{verbatim}
\index{EGraph_writeToFile@{\tt EGraph\_writeToFile()}}
\par
This method writes an {\tt EGraph} object to a file.
It tries to open the file and if it is successful,
it then calls {\tt EGraph\_writeFromFormattedFile()} or
{\tt EGraph\_writeFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt egraph} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.egraphf} (for a formatted file)
or {\tt *.egraphb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int EGraph_writeToFormattedFile ( EGraph *egraph, FILE *fp ) ;
\end{verbatim}
\index{EGraph_writeToFormattedFile@{\tt EGraph\_writeToFormattedFile()}}
\par
This method writes an {\tt EGraph} object to a formatted file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fprintf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt egraph} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int EGraph_writeToBinaryFile ( EGraph *egraph, FILE *fp ) ;
\end{verbatim}
\index{EGraph_writeToBinaryFile@{\tt EGraph\_writeToBinaryFile()}}
\par
This method writes an {\tt EGraph} object to a binary file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fwrite}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt egraph} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int EGraph_writeForHumanEye ( EGraph *egraph, FILE *fp ) ;
\end{verbatim}
\index{EGraph_writeForHumanEye@{\tt EGraph\_writeForHumanEye()}}
\par
This method writes an {\tt EGraph} object to a file in a human
readable format.
The method {\tt EGraph\_writeStats()}
is called to write out the
header and statistics.
Then the {\tt adjIVL} object is written out using
{\tt IVL\_writeForHumanEye()}.
If the {\tt vwghts} vector is present, the vertex weights are
written out.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt egraph} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int EGraph_writeStats ( EGraph *egraph, FILE *fp ) ;
\end{verbatim}
\index{EGraph_writeStats@{\tt EGraph\_writeStats()}}
\par
This method writes a header and statistics to a file.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt egraph} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
us data with a call to
{\tt EGraph\_clearData()}.
The {\tt IVL} object is initialized by a call to {\tt IVL\_init1()}.
If {\tt type = 1}, the {\tt vwghts} is initialized via a call to
{\tt IVinit()}.
See the {\tt IVL} object for a description of the {\tt IVL\_type}
parameter.
\par \noindent {\it Error checking:}
If {\tt egraph} is {\tt NULLEGraph/doc/main.ilg 0100644 0002055 0007177 00000000456 06535772277 0015456 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (16 entries accepted, 0 rejected).
Sorting entries....done (58 comparisons).
Generating output file main.ind....done (20 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
EGraph/doc/drivers.tex 0100644 0002055 0007177 00000011325 06534106100 0016201 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt EGraph} object}
\label{section:EGraph:drivers}
\par
This section contains brief descriptions of the driver programs.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testIO msglvl msgFile inFile outFile
\end{verbatim}
This driver program reads and writes {\tt EGraph} files, useful for
converting formatted files to binary files and vice versa.
One can also read in a {\tt EGraph} file and print out just the
header information (see the {\tt EGraph\_writeStats()} method).
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt EGraph} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inFile} parameter is the input file for the {\tt EGraph}
object. It must be of the form {\tt *.egraphf} or {\tt *.egraphb}.
The {\tt EGraph} object is read from the file via the
{\tt EGraph\_readFromFile()} method.
\item
The {\tt outFile} parameter is the output file for the {\tt EGraph}
object.
If {\tt outFile} is {\tt none} then the {\tt EGraph} object is not
written to a file.
Otherwise, the {\tt EGraph\_writeToFile()} method is called to write
the object to
a formatted file (if {\tt outFile} is of the form {\tt *.egraphf}),
or
a binary file (if {\tt outFile} is of the form {\tt *.egraphb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
mkGraph msglvl msgFile inEGraphFile outGraphFile
\end{verbatim}
This driver program reads in an {\tt EGraph} object and creates a
{\tt Graph} object, which is then optionally written out to a file.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt EGraph} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inEGraphFile} parameter is the input file for the {\tt EGraph}
object. It must be of the form {\tt *.egraphf} or {\tt *.egraphb}.
The {\tt EGraph} object is read from the file via the
{\tt EGraph\_readFromFile()} method.
\item
The {\tt outGraphFile} parameter is the output file for the
{\tt Graph} object.
If {\tt outGraphFile} is {\tt none} then the {\tt Graph} object is not
written to a file.
Otherwise, the {\tt Graph\_writeToFile()} method is called to write
the object to
a formatted file (if {\tt outGraphFile} is of the form
{\tt *.graphf}),
or
a binary file (if {\tt outGraphFile} is of the form {\tt *.graphb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
mkGridEGraph msglvl msgFile n1 n2 n3 ncomp outEGraphFile
\end{verbatim}
This driver program creates an element graph for linear
quadrilateral elements if {\tt n3 = 1} or for linear hexahedral
elements if {\tt n3 > 1}.
There are {\tt ncomp} degrees of freedom at each grid point.
The {\tt EGraph} object is optionally written out to a file.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means that all objects are written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
message data.
\item
{\tt n1} is the number of grid points in the first direction,
must be greater than one.
\item
{\tt n2} is the number of grid points in the second direction,
must be greater than one.
\item
{\tt n3} is the number of grid points in the third direction,
must be greater than or equal to one.
\item
{\tt ncomp} is the number of components (i.e., the number of
degrees of freedom) at each grid point,
must be greater than or equal to one.
\item
The {\tt outEGraphFile} parameter
is the output file for the {\tt EGraph} object.
If {\tt outEGraphFile} is {\tt none} then
the {\tt EGraph} object is not written to a file.
Otherwise, the {\tt EGraph\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outEGraphFile}
is of the form {\tt *.egraphf}), or
a binary file (if {\tt outEGraphFile} is of the form {\tt *.egraphb}).
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
EGraph/doc/makefile 0100644 0002055 0007177 00000000027 06542767377 0015532 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
ETree.h 0100644 0002055 0007177 00000000100 06534106401 0013234 0 ustar 00cleve compmath 0000040 0000006 #ifndef _ETree_
#define _ETree_
#include "ETree/ETree.h"
#endif
ETree/ETree.h 0100644 0002055 0007177 00000112053 06636735054 0014272 0 ustar 00cleve compmath 0000040 0000006 /* ETree.h */
#include "../SPOOLES.h"
#include "../cfiles.h"
#include "../Graph.h"
#include "../Tree.h"
#include "../IV.h"
#include "../DV.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
the ETree object is a tree that has a weight associated with
each node and a weight associated with each node's boundary.
it is useful to model:
(1) a vertex elimination tree (for a unit weight graph),
(2) a compressed vertex elimination tree (for a compressed graph),
(3) a front tree (for a factor graph)
nfront -- # of fronts
nvtx -- # of vertices
tree -- pointer to a Tree object, size nfront
nodwghtsIV -- IV object of node weights, size nfront
bnwwghtsIV -- IV object of node boundary weights, size nfront
vtxToFrontIV -- IV object that holds the map from vertices to fronts,
size nvtx
created -- 96jun23, cca
---------------------------------------------------------------------
*/
typedef struct _ETree ETree ;
struct _ETree {
int nfront ;
int nvtx ;
Tree *tree ;
IV *nodwghtsIV ;
IV *bndwghtsIV ;
IV *vtxToFrontIV ;
} ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in basics.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------
purpose -- create and return a new ETree object
created -- 95nov15, cca
-----------------------------------------------
*/
ETree *
ETree_new (
void
) ;
/*
------------------------------------------------------
purpose -- set the default fields for the ETree object
created -- 95nov15, cca
------------------------------------------------------
*/
void
ETree_setDefaultFields (
ETree *etree
) ;
/*
--------------------------------
purpose -- clear the data fields
created -- 95nov15, cca
--------------------------------
*/
void
ETree_clearData (
ETree *etree
) ;
/*
--------------------------------
purpose -- free the ETree object
created -- 95nov15, cca
--------------------------------
*/
void
ETree_free (
ETree *etree
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in instance.c -------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------
return the number of fronts
created -- 97feb28, cca
---------------------------
*/
int
ETree_nfront (
ETree *etree
) ;
/*
-----------------------------
return the number of vertices
created -- 97feb28, cca
-----------------------------
*/
int
ETree_nvtx (
ETree *etree
) ;
/*
-----------------------------------
return a pointer to the Tree object
created -- 97feb28, cca
-----------------------------------
*/
Tree *
ETree_tree (
ETree *etree
) ;
/*
---------------------------
return the root of the tree
created -- 97feb28, cca
---------------------------
*/
int
ETree_root (
ETree *etree
) ;
/*
-------------------------------------
return a pointer to the parent vector
created -- 97feb28, cca
-------------------------------------
*/
int *
ETree_par (
ETree *etree
) ;
/*
------------------------------------------
return a pointer to the first child vector
created -- 97feb28, cca
------------------------------------------
*/
int *
ETree_fch (
ETree *etree
) ;
/*
--------------------------------------
return a pointer to the sibling vector
created -- 97feb28, cca
--------------------------------------
*/
int *
ETree_sib (
ETree *etree
) ;
/*
------------------------------------------
return a pointer to the nodwghts IV object
created -- 97feb28, cca
------------------------------------------
*/
IV *
ETree_nodwghtsIV (
ETree *etree
) ;
/*
-------------------------------------------
return a pointer to the nodwghts int vector
created -- 97feb28, cca
-------------------------------------------
*/
int *
ETree_nodwghts (
ETree *etree
) ;
/*
------------------------------------------
return a pointer to the bndwghts IV object
created -- 97feb28, cca
------------------------------------------
*/
IV *
ETree_bndwghtsIV (
ETree *etree
) ;
/*
-------------------------------------------
return a pointer to the bndwghts int vector
created -- 97feb28, cca
-------------------------------------------
*/
int *
ETree_bndwghts (
ETree *etree
) ;
/*
--------------------------------------------
return a pointer to the vtxToFront IV object
created -- 97feb28, cca
--------------------------------------------
*/
IV *
ETree_vtxToFrontIV (
ETree *etree
) ;
/*
---------------------------------------------
return a pointer to the vtxToFront int vector
created -- 97feb28, cca
---------------------------------------------
*/
int *
ETree_vtxToFront (
ETree *etree
) ;
/*
------------------------------------------------
purpose -- return the number of internal degrees
of freedom in front J
created -- 97may23, cca
------------------------------------------------
*/
int
ETree_frontSize (
ETree *etree,
int J
) ;
/*
------------------------------------------------
purpose -- return the number of external degrees
of freedom in front J
created -- 97may23, cca
------------------------------------------------
*/
int
ETree_frontBoundarySize (
ETree *etree,
int J
) ;
/*
------------------------------------------------------------
purpose -- compute the maximum number of indices and entries
in a front
symflag = 1 -->
count only column indices
count upper entries in (1,1) block and (1,2) block
symflag = 2 -->
count row and column indices
count entries in (1,1), (1,2) and (2,1) blocks
created -- 97may23, cca
------------------------------------------------------------
*/
void
ETree_maxNindAndNent (
ETree *etree,
int symflag,
int *pmaxnind,
int *pmaxnent
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in util.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 95nov15, cca
----------------------------------------------
*/
int
ETree_sizeOf (
ETree *etree
) ;
/*
----------------------------------------
return the number of factor indices
created -- 95nov15, cca
modified -- 96jan11, cca
----------------------------------------
*/
int
ETree_nFactorIndices (
ETree *etree
) ;
/*
------------------------------------------
return the number of factor entries
symflag -- symmetry flag
0 (SPOOLES_SYMMETRIC) -- symmetric
1 (SPOOLES_HERMITIAN) -- hermitian
2 (SPOOLES_NONSYMMETRIC) -- nonsymmetric
created -- 98jun05, cca
------------------------------------------
*/
int
ETree_nFactorEntries (
ETree *etree,
int symflag
) ;
/*
------------------------------------------
return the number of factor operations
type -- type of matrix entries
1 (SPOOLES_REAL) -- real entries
2 (SPOOLES_COMPLEX) -- complex entries
symflag -- symmetry flag
0 (SPOOLES_SYMMETRIC) -- symmetric
1 (SPOOLES_HERMITIAN) -- hermitian
2 (SPOOLES_NONSYMMETRIC) -- nonsymmetric
created -- 98jun05, cca
------------------------------------------
*/
double
ETree_nFactorOps (
ETree *etree,
int type,
int symflag
) ;
/*
----------------------------------------
return the number of entries an LU front
created -- 96dec04, cca
----------------------------------------
*/
double
ETree_nFactorEntriesInFront (
ETree *etree,
int symflag,
int J
) ;
/*
-------------------------------------------------------
return the number of internal LU operations for a front
created -- 96dec04, cca
-------------------------------------------------------
*/
double
ETree_nInternalOpsInFront (
ETree *etree,
int type,
int symflag,
int J
) ;
/*
-------------------------------------------------------
return the number of external LU operations for a front
created -- 96dec04, cca
-------------------------------------------------------
*/
double
ETree_nExternalOpsInFront (
ETree *etree,
int type,
int symflag,
int J
) ;
/*
------------------------------------
return an IV object that contains
the number of entries for each front
created -- 98jan30, cca
------------------------------------
*/
IV *
ETree_factorEntriesIV (
ETree *etree,
int symflag
) ;
/*
---------------------------------------------------------
return a DV object that contains the number of operations
for each front using a backward looking algorithm
created -- 96dec04, cca
---------------------------------------------------------
*/
DV *
ETree_backwardOps (
ETree *etree,
int type,
int symflag,
int *vwghts,
IVL *symbfacIVL
) ;
/*
---------------------------------------------------------
return a DV object that contains the number of operations
for each front using a forward-looking algorithm
created -- 96dec04, cca
---------------------------------------------------------
*/
DV *
ETree_forwardOps (
ETree *etree,
int type,
int symflag
) ;
/*
---------------------------------------------------------------
given an IV object that maps uncompressed vertices to vertices,
create and return an ETree object that is relative to the
uncompressed graph.
created -- 97feb13, cca
---------------------------------------------------------------
*/
ETree *
ETree_expand (
ETree *etree,
IV *eqmapIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in init.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------
initialize the object given the number of nodes
created -- 95nov15, cca
-----------------------------------------------
*/
void
ETree_init1 (
ETree *etree,
int nfront,
int nvtx
) ;
/*
----------------------------------------
initialize the ETree object from a graph
created -- 95nov15, cca
----------------------------------------
*/
void
ETree_initFromGraph (
ETree *etree,
Graph *g
) ;
/*
--------------------------------------------------------
initialize the ETree object from a graph and permutation
created -- 95nov15, cca
--------------------------------------------------------
*/
void
ETree_initFromGraphWithPerms (
ETree *etree,
Graph *g,
int newToOld[],
int oldToNew[]
) ;
/*
--------------------------------------------------------------
purpose -- initialize the front tree for a dense matrix
n -- size of the matrix
option -- mapping option
1 --> have all fronts (save the last) contain the same
number of vertices
2 --> have all fronts have roughly equal numbers of entries
created -- 96aug19, cca
--------------------------------------------------------------
*/
void
ETree_initFromDenseMatrix (
ETree *etree,
int n,
int option,
int param
) ;
/*
-------------------------------------
initialize the ETree object
(1) read ETree object from file
(2) get the old-to-new permutation
(3) permute the ETree
(4) return the old-to-new permutation
created -- 97jul13, cca
-------------------------------------
*/
IV *
ETree_initFromFile (
ETree *frontETree,
char *inETreeFileName,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in ms.c -------------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------
returns a compidsIV IV object that maps the
vertices to a domain (compids[v] > 1)
or to the multisector (compids[v] = 0).
the vertices in the multisector is specified
by their depth of their front in the tree.
created -- 96jan04, cca
------------------------------------------------
*/
IV *
ETree_msByDepth (
ETree *etree,
int depth
) ;
/*
----------------------------------------------------------------
construct a multisector based on vertices found in a subtree.
created -- 96jan04, cca
----------------------------------------------------------------
*/
IV *
ETree_msByNvtxCutoff (
ETree *etree,
double cutoff
) ;
/*
--------------------------------------------------
construct a multisector based on the number
of factor entries found in a subtree.
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 96jan04, cca
--------------------------------------------------
*/
IV *
ETree_msByNentCutoff (
ETree *etree,
double cutoff,
int symflag
) ;
/*
--------------------------------------------------
construct a multisector based on the number
of factor operations found in a subtree.
type -- type of entries,
SPOOLES_REAL or SPOOLES_COMPLEX
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 96jan04, cca
--------------------------------------------------
*/
IV *
ETree_msByNopsCutoff (
ETree *etree,
double cutoff,
int type,
int symflag
) ;
/*
--------------------------------------------------------------
purpose -- given a front tree and a multisector map vector,
fill the map vector with domain ids and the three statistics
arrays with domain and schur complement statistics.
frontETree -- front tree object, unchanged on output
msIV -- map from fronts to domains or schur complement
on input, ms[J] = 0 --> J is in the schur complement
ms[J] = 1 --> J is not in the schur complement
on output, ms[J] = 0 --> J is in the schur complement
ms[J] != 0 --> J is in domain ms[J]
on output
nvtxIV -- nvtx[ireg] = # of dof in region ireg
nzfIV -- nzf[ireg] = # of factor entries in region ireg
opsIV -- ops[ireg] = # of factor ops in region ireg
type -- type of entries, SPOOLES_REAL or SPOOLES_COMPLEX
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 98jan30, cca
--------------------------------------------------------------
*/
void
ETree_msStats (
ETree *frontETree,
IV *msIV,
IV *nvtxIV,
IV *nzfIV,
DV *opsDV,
int type,
int symlag
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in permute.c --------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------
fill the new-to-old permutation vector for the fronts
created -- 96jun23, cca
-----------------------------------------------------
*/
IV *
ETree_newToOldFrontPerm (
ETree *etree
) ;
/*
-----------------------------------------------------
fill the old-to-new permutation vector for the fronts
created -- 96jun23, cca
-----------------------------------------------------
*/
IV *
ETree_oldToNewFrontPerm (
ETree *etree
) ;
/*
-------------------------------------------------------
fill the new-to-old permutation vector for the vertices
created -- 96jun23, cca
-------------------------------------------------------
*/
IV *
ETree_newToOldVtxPerm (
ETree *etree
) ;
/*
-------------------------------------------------------
fill the old-to-new permutation vector for the vertices
created -- 96jun23, cca
-------------------------------------------------------
*/
IV *
ETree_oldToNewVtxPerm (
ETree *etree
) ;
/*
-------------------------------------------------------
purpose -- permute the vertices,
overwrite entries in the vertex-to-front map
created -- 96oct03, cca
-------------------------------------------------------
*/
void
ETree_permuteVertices (
ETree *etree,
IV *vtxOldToNewIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in compress.c -------------------------------------
------------------------------------------------------------------------
*/
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
purpose --
to create and return an IV object that contains the map
from old to new fronts that are fundamental chains.
created -- 96jun23, cca
-------------------------------------------------------
*/
IV *
ETree_fundChainMap (
ETree *etree
) ;
/*
-------------------------------------------------------
purpose --
to create and return an IV object that contains the map
from old to new fronts that are fundamental supernodes.
created -- 96jun23, cca
-------------------------------------------------------
*/
IV *
ETree_fundSupernodeMap (
ETree *etree
) ;
/*
-----------------------------------------------------------
compress an ETree object given a map from old to new nodes.
note, a new node must be a connected set of the old nodes.
return value -- pointer to new ETree object
created -- 96jun23, cca.
-----------------------------------------------------------
*/
ETree *
ETree_compress (
ETree *etree,
IV *frontmapIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in justify.c --------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------
left-justify a tree by subtree size
children are linked in ascending order of their subtree size
created -- 96jan11, cca
------------------------------------------------------------
*/
void
ETree_leftJustify (
ETree *etree
) ;
/*
------------------------------------------------------
left-justify a etree by a metric
children are linked in ascending order of their metric
created -- 96jan11, cca
------------------------------------------------------
*/
void
ETree_leftJustifyI (
ETree *etree,
IV *metricIV
) ;
/*
------------------------------------------------------
left-justify a etree by a metric
children are linked in ascending order of their metric
created -- 96jan11, cca
------------------------------------------------------
*/
void
ETree_leftJustifyD (
ETree *etree,
DV *metricDV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in metrics.c --------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------
return an IV object with the weights
of the vertices in each front.
created -- 96jun23, cca
------------------------------------
*/
IV *
ETree_nvtxMetric (
ETree *etree
) ;
/*
---------------------------------------------------------------
return an IV object with the number
of factor entries in each front.
symflag -- symmetryflag
SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 96jun23, cca
---------------------------------------------------------------
*/
IV *
ETree_nentMetric (
ETree *etree,
int flag
) ;
/*
---------------------------------------------------------------
return a DV object with the number
of factor operations in each front.
type -- type of entries,
SPOOLES_REAL or SPOOLES_COMPLEX
symflag -- symmetryflag,
SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 96jun23, cca
---------------------------------------------------------------
*/
DV *
ETree_nopsMetric (
ETree *etree,
int type,
int symflag
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in stages.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------------------------
generate a stages vector to be used by the CMD object.
(1) if v = par[u] then
stages[v] >= stages[u]
endif
(2) if v is a leaf then
stages[v] = 0
endif
(3) if u and v belong to the same fundamental supernode then
stages[v] = stages[u]
endif
basically, all nodes in a domain (a subtree) have stage zero,
and the stages of all fundamental supernodes ancestor to that
subtree are distinct.
input --
msIV -- IV object that contains the vertices in the
multisector (non-domain vertices)
return value --
stagesIV -- an IV object that contains the stage for each vertex
created -- 96feb19, cca
-------------------------------------------------------------------
*/
IV *
ETree_stagesViaMS (
ETree *etree,
IV *msIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in transform.c ------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------
transform an ETree object by
(1) merging small fronts into larger fronts
using the ETree_mergeFrontsOne() method
(2) merging small fronts into larger fronts
using the ETree_mergeFrontsAll() method
(3) merging small fronts into larger fronts
using the ETree_mergeFrontsAny() method
(4) split a large front into a chain of smaller fronts
using the ETree_splitFronts() method
created -- 96jun27, cca
------------------------------------------------------
*/
ETree *
ETree_transform (
ETree *etree,
int vwghts[],
int maxzeros,
int maxfrontsize,
int seed
) ;
/*
------------------------------------------------------
transform an ETree object by
(1) merging small fronts into larger fronts
using the ETree_mergeFrontsOne() method
(2) merging small fronts into larger fronts
using the ETree_mergeFrontsAll() method
(3) split a large front into a chain of smaller fronts
using the ETree_splitFronts() method
created -- 96jun27, cca
------------------------------------------------------
*/
ETree *
ETree_transform2 (
ETree *etree,
int vwghts[],
int maxzeros,
int maxfrontsize,
int seed
) ;
/*
--------------------------------------------------------------------
purpose -- merge the front tree allowing only chains of nodes to
merge that create at most maxzeros zero entries inside a front
return --
IV object that has the old front to new front map
created -- 98jan29, cca
--------------------------------------------------------------------
*/
ETree *
ETree_mergeFrontsOne (
ETree *etree,
int maxzeros,
IV *nzerosIV
) ;
/*
-------------------------------------------------------
purpose -- merge the front tree allowing a parent
to absorb all children when that creates
at most maxzeros zero entries inside a front
return --
IV object that has the old front to new front map
created -- 98jan29, cca
-------------------------------------------------------
*/
ETree *
ETree_mergeFrontsAll (
ETree *etree,
int maxzeros,
IV *nzerosIV
) ;
/*
--------------------------------------------------------------------
purpose -- merge the front tree allowing at most
maxzeros zero entries inside a front
return --
IV object that has the old front to new front map
created -- 96jun23, cca
modified -- 97dec18, cca
bug fixed that incorrectly counted the number of zeros in a front
--------------------------------------------------------------------
*/
ETree *
ETree_mergeFrontsAny (
ETree *etree,
int maxzeros,
IV *nzerosIV
) ;
/*
-------------------------------------------------
expand an ETree object by splitting a large front
into a chain of smaller fronts.
created -- 96jun27, cca
-------------------------------------------------
*/
ETree *
ETree_splitFronts (
ETree *etree,
int vwghts[],
int maxfrontsize,
int seed
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in maps.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------------
this method constructs and returns an IV object that holds the
map from fronts to threads for a wrap map of the front tree.
created -- 96dec12, cca
--------------------------------------------------------------
*/
IV *
ETree_wrapMap (
ETree *frontTree,
int type,
int symflag,
DV *cumopsDV
) ;
/*
----------------------------------------------------------------
this method constructs and returns an IV object that holds the
map from fronts to threads for a balanced map of the front tree.
the fronts are visited in the post-order traversal.
created -- 96dec12, cca
----------------------------------------------------------------
*/
IV *
ETree_balancedMap (
ETree *frontTree,
int type,
int symflag,
DV *cumopsDV
) ;
/*
-----------------------------------------------
this method constructs and returns an IV object
that holds the map from fronts to threads for a
"subtree-subset" map of the front tree.
created -- 97jan15, cca
-----------------------------------------------
*/
IV *
ETree_subtreeSubsetMap (
ETree *frontTree,
int type,
int symflag,
DV *cumopsDV
) ;
/*
----------------------------------------------------------------
this method constructs and returns an IV object that holds the
map from fronts to threads for a domain decomposition
balanced map of the front tree.
the domains are mapped to threads using a balanced map,
and the schur complement fronts are mapped to threads
using a balanced map, but the two balanced maps are independent.
created -- 97jan17, cca
----------------------------------------------------------------
*/
IV *
ETree_ddMap (
ETree *frontTree,
int type,
int symflag,
DV *cumopsDV,
double cutoff
) ;
/*
----------------------------------------------------------------
this method constructs and returns an IV object that holds the
map from fronts to threads for a domain decomposition
balanced map of the front tree.
the domains are mapped to threads using a balanced map,
and the schur complement fronts are mapped to threads
using a balanced map, but the two balanced maps are independent.
created -- 97jan17, cca
----------------------------------------------------------------
*/
IV *
ETree_ddMapNew (
ETree *frontTree,
int type,
int symflag,
IV *msIV,
DV *cumopsDV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in splice.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------------------
this method is used to splice together two front trees
when the domain vertices and schur complement vertices
have been ordered separately.
etree0 -- the lower front tree is for vertices in the domain.
graph0 -- graph for all the vertices
mapIV -- IV object that maps vertices to schur complement
vertices, if IV_entry(mapIV, v) < 0 then v is
a domain vertex.
etree1 -- the upper front tree is for vertices in the schur
complement.
created -- 97feb01, cca
-------------------------------------------------------------
*/
ETree *
ETree_spliceTwoETrees (
ETree *etree0,
Graph *graph0,
IV *mapIV,
ETree *etree1
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in initFromSubtree.c ------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------
purpose -- to initialize subtree with the subtree
of the front tree using nodes in nodeidsIV.
vtxIV is filled with the vertices in the subtree
return values ---
1 -- normal return
-1 -- subtree is NULL
-2 -- nodeidsIV is NULL
-3 -- etree is NULL
-4 -- nodeidsIV is invalid
-5 -- vtxIV is NULL
created -- 98oct15, cca
-----------------------------------------------------------
*/
int
ETree_initFromSubtree (
ETree *subtree,
IV *nodeidsIV,
ETree *etree,
IV *vtxIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in semi.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------
purpose --
to find the optimal domain/schur complement partition
for a semi-implict factorization.
the gain of a subtree sbt(J) is equal to
|L_{bnd{J},sbt{J}}| - |A_{bnd{J},sbt{J}}|
- alpha *|L_{sbt{J},sbt{J}}|
when alpha = 0 we minimize active storage
when alpha = 1 we minimize solve operations
*ptotalgain is filled with the total gain
the return value is compidsIV,
compids[J] = 0 --> J is in the schur complement
compids[J] != 0 --> J is in domain compids[J]
created -- 98jun20, cca
-----------------------------------------------------
*/
IV *
ETree_optPart (
ETree *etree,
Graph *graph,
IVL *symbfacIVL,
double alpha,
int *ptotalgain,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in storage.c --------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------------
purpose -- fill dvec[J] with the active storage to eliminate J
using the multifrontal method
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC,
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 97may21, cca
---------------------------------------------------------------
*/
void
ETree_MFstackProfile (
ETree *etree,
int symflag,
double dvec[]
) ;
/*
---------------------------------------------------------------
purpose -- fill dvec[J] with the active storage to eliminate J
using the left-looking general sparse method
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC,
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 97may21, cca
---------------------------------------------------------------
*/
void
ETree_GSstorageProfile (
ETree *etree,
int symflag,
IVL *symbfacIVL,
int *vwghts,
double dvec[]
) ;
/*
---------------------------------------------------------------
purpose -- fill dvec[J] with the active storage to eliminate J
using the right-looking general sparse method
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC,
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 98dec19, cca
---------------------------------------------------------------
*/
void
ETree_FSstorageProfile (
ETree *etree,
int symflag,
IVL *symbfacIVL,
double dvec[]
) ;
/*
---------------------------------------------------------------
purpose -- fill dvec[J] with the stack storage to solve for J
in a forward solve
created -- 97nov30, cca
---------------------------------------------------------------
*/
void
ETree_forwSolveProfile (
ETree *etree,
double dvec[]
) ;
/*
---------------------------------------------------------------
purpose -- fill dvec[J] with the stack storage to solve for J
in a backward solve
created -- 97nov30, cca
---------------------------------------------------------------
*/
void
ETree_backSolveProfile (
ETree *etree,
double dvec[]
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods founds in IO.c -------------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------
purpose -- to read in an ETree object from a file
input --
fn -- filename, must be *.etreeb or *.etreef
return value -- 1 if success, 0 if failure
created -- 95nov15, cca
-------------------------------------------------
*/
int
ETree_readFromFile (
ETree *etree,
char *fn
) ;
/*
--------------------------------------------------------
purpose -- to read an ETree object from a formatted file
return value -- 1 if success, 0 if failure
created -- 95nov15, cca
--------------------------------------------------------
*/
int
ETree_readFromFormattedFile (
ETree *etree,
FILE *fp
) ;
/*
----------------------------------------------------
purpose -- to read an ETree object from a binary file
return value -- 1 if success, 0 if failure
created -- 95nov15, cca
----------------------------------------------------
*/
int
ETree_readFromBinaryFile (
ETree *etree,
FILE *fp
) ;
/*
--------------------------------------------
purpose -- to write an ETree object to a file
input --
fn -- filename
*.etreeb -- binary
*.etreef -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 95nov15, cca
--------------------------------------------
*/
int
ETree_writeToFile (
ETree *etree,
char *fn
) ;
/*
------------------------------------------------------
purpose -- to write an ETree object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 95nov15, cca
------------------------------------------------------
*/
int
ETree_writeToFormattedFile (
ETree *etree,
FILE *fp
) ;
/*
---------------------------------------------------
purpose -- to write an ETree object to a binary file
return value -- 1 if success, 0 otherwise
created -- 95nov15, cca
---------------------------------------------------
*/
int
ETree_writeToBinaryFile (
ETree *etree,
FILE *fp
) ;
/*
---------------------------------------------------
purpose -- to write an ETree object for a human eye
return value -- 1 if success, 0 otherwise
created -- 95nov15, cca
---------------------------------------------------
*/
int
ETree_writeForHumanEye (
ETree *etree,
FILE *fp
) ;
/*
-----------------------------------------------------------
purpose -- to write out the statistics for the ETree object
return value -- 1 if success, 0 otherwise
created -- 95nov15, cca
-----------------------------------------------------------
*/
int
ETree_writeStats (
ETree *etree,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
-----------------------------
*/
IV *
ETree_subtreeSubsetMap (
ETree *frontTree,
int type,
int symflag,
DV *cumopsDV
) ;
/*
----------------------------------------------------------------
this method constructs and returns an IV object that holds the
map from fronts to threads for a domain decomposition
balanced map of the front tree.
the domains are mapped to threads using a balanced map,
and the schur complement fronETree/makefile 0100644 0002055 0007177 00000000223 06636223571 0014604 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd drivers ; make clean
cd doc ; make clean
ETree/src/makefile 0100644 0002055 0007177 00000001302 06636022660 0015366 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = ETree
$(OBJ).a : \
$(OBJ).a(IO.o) \
$(OBJ).a(basics.o) \
$(OBJ).a(compress.o) \
$(OBJ).a(init.o) \
$(OBJ).a(initFromSubtree.o) \
$(OBJ).a(instance.o) \
$(OBJ).a(justify.o) \
$(OBJ).a(maps.o) \
$(OBJ).a(metrics.o) \
$(OBJ).a(ms.o) \
$(OBJ).a(permute.o) \
$(OBJ).a(semi.o) \
$(OBJ).a(storage.o) \
$(OBJ).a(transform.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
ETree/src/makeGlobalLib 0100644 0002055 0007177 00000001050 06600261015 0016264 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = ETree
SRC = IO.c \
basics.c \
compress.c \
init.c \
instance.c \
justify.c \
maps.c \
metrics.c \
ms.c \
permute.c \
semi.c \
storage.c \
transform.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
ETree/src/IO.c 0100644 0002055 0007177 00000036527 06534106073 0014360 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../ETree.h"
static const char *suffixb = ".etreeb" ;
static const char *suffixf = ".etreef" ;
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to read in an ETree object from a file
input --
fn -- filename, must be *.etreeb or *.etreef
return value -- 1 if success, 0 if failure
created -- 95nov15, cca
-------------------------------------------------
*/
int
ETree_readFromFile (
ETree *etree,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || fn == NULL ) {
fprintf(stderr, "\n error in ETree_readFromFile(%p,%s)"
"\n bad input\n", etree, fn) ;
return(0) ;
}
/*
-------------
read the file
-------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "rb")) == NULL ) {
fprintf(stderr, "\n error in ETree_readFromFile(%p,%s)"
"\n unable to open file %s", etree, fn, fn) ;
rc = 0 ;
} else {
rc = ETree_readFromBinaryFile(etree, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "r")) == NULL ) {
fprintf(stderr, "\n error in ETree_readFromFile(%p,%s)"
"\n unable to open file %s", etree, fn, fn) ;
rc = 0 ;
} else {
rc = ETree_readFromFormattedFile(etree, fp) ;
fclose(fp) ;
}
} else {
fprintf(stderr, "\n error in ETree_readFromFile(%p,%s)"
"\n bad ETree file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
etree, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
} else {
fprintf(stderr, "\n error in ETree_readFromFile(%p,%s)"
"\n bad ETree file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
etree, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- to read an ETree object from a formatted file
return value -- 1 if success, 0 if failure
created -- 95nov15, cca
--------------------------------------------------------
*/
int
ETree_readFromFormattedFile (
ETree *etree,
FILE *fp
) {
int rc ;
int itemp[2] ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || fp == NULL ) {
fprintf(stderr, "\n error in ETree_readFromFormattedFile(%p,%p)"
"\n bad input\n", etree, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
ETree_clearData(etree) ;
/*
---------------------------
initialize the ETree object
---------------------------
*/
ETree_init1(etree, 0, 0) ;
/*
-----------------------------
read in the two scalar fields
-----------------------------
*/
if ( (rc = IVfscanf(fp, 2, itemp)) != 2 ) {
fprintf(stderr, "\n error in ETree_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", etree, fp, rc, 2) ;
return(0) ;
}
etree->nfront = itemp[0] ;
etree->nvtx = itemp[1] ;
/*
-----------------------
read in the Tree object
-----------------------
*/
Tree_readFromFormattedFile(etree->tree, fp) ;
/*
------------------------------
read in the nodwghts IV object
------------------------------
*/
IV_readFromFormattedFile(etree->nodwghtsIV, fp) ;
/*
------------------------------
read in the bndwghts IV object
------------------------------
*/
IV_readFromFormattedFile(etree->bndwghtsIV, fp) ;
/*
--------------------------------
read in the vtxToFront IV object
--------------------------------
*/
IV_readFromFormattedFile(etree->vtxToFrontIV, fp) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
purpose -- to read an ETree object from a binary file
return value -- 1 if success, 0 if failure
created -- 95nov15, cca
----------------------------------------------------
*/
int
ETree_readFromBinaryFile (
ETree *etree,
FILE *fp
) {
int rc ;
int itemp[2] ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in ETree_readFromBinaryFile(%p,%p)"
"\n bad input\n", etree, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
ETree_clearData(etree) ;
/*
---------------------------
initialize the ETree object
---------------------------
*/
ETree_init1(etree, 0, 0) ;
/*
-----------------------------
read in the two scalar fields
-----------------------------
*/
if ( (rc = fread((void *) itemp, sizeof(int), 2, fp)) != 2 ) {
fprintf(stderr, "\n error in ETree_readFromBinaryFile(%p,%p)"
"\n itemp(2) : %d items of %d read\n", etree, fp, rc, 2) ;
return(0) ;
}
etree->nfront = itemp[0] ;
etree->nvtx = itemp[1] ;
/*
-----------------------
read in the Tree object
-----------------------
*/
Tree_readFromBinaryFile(etree->tree, fp) ;
/*
------------------------------
read in the nodwghts IV object
------------------------------
*/
IV_readFromBinaryFile(etree->nodwghtsIV, fp) ;
/*
------------------------------
read in the bndwghts IV object
------------------------------
*/
IV_readFromBinaryFile(etree->bndwghtsIV, fp) ;
/*
--------------------------------
read in the vtxToFront IV object
--------------------------------
*/
IV_readFromBinaryFile(etree->vtxToFrontIV, fp) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
purpose -- to write an ETree object to a file
input --
fn -- filename
*.etreeb -- binary
*.etreef -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 95nov15, cca
--------------------------------------------
*/
int
ETree_writeToFile (
ETree *etree,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || fn == NULL ) {
fprintf(stderr, "\n fatal error in ETree_writeToFile(%p,%s)"
"\n bad input\n", etree, fn) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in ETree_writeToFile(%p,%s)"
"\n unable to open file %s", etree, fn, fn) ;
rc = 0 ;
} else {
rc = ETree_writeToBinaryFile(etree, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "w")) == NULL ) {
fprintf(stderr, "\n error in ETree_writeToFile(%p,%s)"
"\n unable to open file %s", etree, fn, fn) ;
rc = 0 ;
} else {
rc = ETree_writeToFormattedFile(etree, fp) ;
fclose(fp) ;
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in ETree_writeToFile(%p,%s)"
"\n unable to open file %s", etree, fn, fn) ;
rc = 0 ;
} else {
rc = ETree_writeForHumanEye(etree, fp) ;
fclose(fp) ;
}
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in ETree_writeToFile(%p,%s)"
"\n unable to open file %s", etree, fn, fn) ;
rc = 0 ;
} else {
rc = ETree_writeForHumanEye(etree, fp) ;
fclose(fp) ;
}
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- to write an ETree object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 95nov15, cca
------------------------------------------------------
*/
int
ETree_writeToFormattedFile (
ETree *etree,
FILE *fp
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || fp == NULL || etree->tree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_writeToFormattedFile(%p,%p)"
"\n bad input\n", etree, fp) ;
exit(-1) ;
}
/*
---------------------------
write the two scalar fields
---------------------------
*/
rc = fprintf(fp, "\n %d %d", etree->nfront, etree->nvtx) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from first fprintf\n", etree, fp, rc) ;
return(0) ;
}
/*
---------------------------------
write the Tree object to the file
---------------------------------
*/
rc = Tree_writeToFormattedFile(etree->tree, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from writing Tree to file\n",
etree, fp, rc) ;
return(0) ;
}
/*
----------------------------------------
write the nodwghts IV object to the file
----------------------------------------
*/
rc = IV_writeToFormattedFile(etree->nodwghtsIV, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from writing nodwghtsIV to file\n",
etree, fp, rc) ;
return(0) ;
}
/*
----------------------------------------
write the bndwghts IV object to the file
----------------------------------------
*/
rc = IV_writeToFormattedFile(etree->bndwghtsIV, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from writing bndwghtsIV to file\n",
etree, fp, rc) ;
return(0) ;
}
/*
------------------------------------------
write the vtxToFront IV object to the file
------------------------------------------
*/
rc = IV_writeToFormattedFile(etree->vtxToFrontIV, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from writing vtxToFrontIV to file\n",
etree, fp, rc) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
purpose -- to write an ETree object to a binary file
return value -- 1 if success, 0 otherwise
created -- 95nov15, cca
---------------------------------------------------
*/
int
ETree_writeToBinaryFile (
ETree *etree,
FILE *fp
) {
int rc ;
int itemp[2] ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || fp == NULL || etree->tree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_writeToBinaryFile(%p,%p)"
"\n bad input\n", etree, fp) ;
exit(-1) ;
}
/*
---------------------------
write the two scalar fields
---------------------------
*/
itemp[0] = etree->nfront ;
itemp[1] = etree->nvtx ;
rc = fwrite((void *) itemp, sizeof(int), 2, fp) ;
if ( rc != 2 ) {
fprintf(stderr, "\n error in ETree_writeToBinaryFile(%p,%p)"
"\n %d of %d scalar items written\n", etree, fp, rc, 2) ;
return(0) ;
}
/*
---------------------------------
write the Tree object to the file
---------------------------------
*/
rc = Tree_writeToBinaryFile(etree->tree, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from writing Tree to file\n",
etree, fp, rc) ;
return(0) ;
}
/*
----------------------------------------
write the nodwghts IV object to the file
----------------------------------------
*/
rc = IV_writeToBinaryFile(etree->nodwghtsIV, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from writing nodwghtsIV to file\n",
etree, fp, rc) ;
return(0) ;
}
/*
----------------------------------------
write the bndwghts IV object to the file
----------------------------------------
*/
rc = IV_writeToBinaryFile(etree->bndwghtsIV, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from writing bndwghtsIV to file\n",
etree, fp, rc) ;
return(0) ;
}
/*
------------------------------------------
write the vtxToFront IV object to the file
------------------------------------------
*/
rc = IV_writeToBinaryFile(etree->vtxToFrontIV, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from writing vtxToFrontIV to file\n",
etree, fp, rc) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
purpose -- to write an ETree object for a human eye
return value -- 1 if success, 0 otherwise
created -- 95nov15, cca
---------------------------------------------------
*/
int
ETree_writeForHumanEye (
ETree *etree,
FILE *fp
) {
int nfront, rc, v ;
int *bndwghts, *fch, *nodwghts, *par, *sib ;
if ( etree == NULL || fp == NULL || (nfront = etree->nfront) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeForHumanEye(%p,%p)"
"\n bad input\n", etree, fp) ;
exit(-1) ;
}
if ( (rc = ETree_writeStats(etree, fp)) == 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeForHumanEye(%p,%p)"
"\n rc = %d, return from ETree_writeStats(%p,%p)\n",
etree, fp, rc, etree, fp) ;
return(0) ;
}
par = etree->tree->par ;
fch = etree->tree->fch ;
sib = etree->tree->sib ;
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
fprintf(fp,
"\n front parent fchild sibling nodwght bndwght") ;
for ( v = 0 ; v < nfront ; v++ ) {
fprintf(fp, "\n %5d %9d %9d %9d %9d %9d ",
v, par[v], fch[v], sib[v], nodwghts[v], bndwghts[v]) ;
}
fflush(fp) ;
fprintf(fp, "\n\n vtxToFront IV object") ;
IV_writeForHumanEye(etree->vtxToFrontIV, fp) ;
fflush(fp) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- to write out the statistics for the ETree object
return value -- 1 if success, 0 otherwise
created -- 95nov15, cca
-----------------------------------------------------------
*/
int
ETree_writeStats (
ETree *etree,
FILE *fp
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || fp == NULL ) {
fprintf(stderr, "\n error in ETree_writeStats(%p,%p)"
"\n bad input\n", etree, fp) ;
exit(-1) ;
}
rc = fprintf(fp,
"\n ETree : etree object, %d fronts, %d vertices, takes %d bytes",
etree->nfront, etree->nvtx, ETree_sizeOf(etree)) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in ETree_writeStats(%p,%p)"
"\n rc = %d, return from fprintf\n", etree, fp, rc) ;
return(0) ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
ETree/src/basics.c 0100644 0002055 0007177 00000006127 06534106073 0015306 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../ETree.h"
#define MYTRACE 0
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
purpose -- create and return a new ETree object
created -- 95nov15, cca
-----------------------------------------------
*/
ETree *
ETree_new (
void
) {
ETree *etree ;
#if MYTRACE > 0
fprintf(stdout, "\n just inside ETree_new()") ;
fflush(stdout) ;
#endif
ALLOCATE(etree, struct _ETree, 1) ;
ETree_setDefaultFields(etree) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving ETree_new()") ;
fflush(stdout) ;
#endif
return(etree) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- set the default fields for the ETree object
created -- 95nov15, cca
------------------------------------------------------
*/
void
ETree_setDefaultFields (
ETree *etree
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside ETree_setDefaultFields(%)", g) ;
fflush(stdout) ;
#endif
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_setDefaultFields(%p)"
"\n etree is NULL\n", etree) ;
exit(-1) ;
}
etree->nfront = 0 ;
etree->nvtx = 0 ;
etree->tree = NULL ;
etree->nodwghtsIV = NULL ;
etree->bndwghtsIV = NULL ;
etree->vtxToFrontIV = NULL ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving ETree_setDefaultFields(%)", etree) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------
purpose -- clear the data fields
created -- 95nov15, cca
--------------------------------
*/
void
ETree_clearData (
ETree *etree
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside ETree_clearData(%)", etree) ;
fflush(stdout) ;
#endif
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_clearData(%p)"
"\n etree is NULL\n", etree) ;
exit(-1) ;
}
if ( etree->tree != NULL ) {
Tree_free(etree->tree) ;
}
if ( etree->nodwghtsIV != NULL ) {
IV_free(etree->nodwghtsIV) ;
}
if ( etree->bndwghtsIV != NULL ) {
IV_free(etree->bndwghtsIV) ;
}
if ( etree->vtxToFrontIV != NULL ) {
IV_free(etree->vtxToFrontIV) ;
}
ETree_setDefaultFields(etree) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving ETree_clearData(%)", etree) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------
purpose -- free the ETree object
created -- 95nov15, cca
--------------------------------
*/
void
ETree_free (
ETree *etree
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside ETree_free(%)", etree) ;
fflush(stdout) ;
#endif
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_free(%p)"
"\n etree is NULL\n", etree) ;
exit(-1) ;
}
ETree_clearData(etree) ;
FREE(etree) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving ETree_free(%)", etree) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
ETree/src/compress.c 0100644 0002055 0007177 00000014145 06534106074 0015675 0 ustar 00cleve compmath 0000040 0000006 /* compress.c */
#include "../ETree.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
purpose --
to create and return an IV object that contains the map
from old to new fronts that are fundamental chains.
created -- 96jun23, cca
-------------------------------------------------------
*/
IV *
ETree_fundChainMap (
ETree *etree
) {
int nfront, nvtx ;
IV *frontmapIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->tree == NULL
|| (nfront = etree->nfront) <= 0 || (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_fundChainMap(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
/*
-------------------------------------
call the Tree object's method to get
the map from old fronts to new fronts
-------------------------------------
*/
frontmapIV = Tree_fundChainMap(etree->tree) ;
return(frontmapIV) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
purpose --
to create and return an IV object that contains the map
from old to new fronts that are fundamental supernodes
created -- 96jun23, cca
-------------------------------------------------------
*/
IV *
ETree_fundSupernodeMap (
ETree *etree
) {
int child, front, nfront, nfs, nvtx ;
int *bndwghts, *fch, *frontmap, *nodwghts, *par, *sib ;
IV *frontmapIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->tree == NULL
|| (nfront = etree->nfront) <= 0 || (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_fundSupernodeMap(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
par = etree->tree->par ;
fch = etree->tree->fch ;
sib = etree->tree->sib ;
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
/*
------------------------------------------
fill the map from old fronts to new fronts
------------------------------------------
*/
frontmapIV = IV_new() ;
IV_init(frontmapIV, nfront, NULL) ;
frontmap = IV_entries(frontmapIV) ;
nfs = 0 ;
front = etree->tree->root ;
while ( front != -1 ) {
while ( fch[front] != -1 ) {
front = fch[front] ;
}
frontmap[front] = nfs++ ;
while ( sib[front] == -1 && par[front] != -1 ) {
front = par[front] ;
child = fch[front] ;
if ( sib[child] != -1
|| (nodwghts[front] + bndwghts[front] != bndwghts[child]) ) {
frontmap[front] = nfs++ ;
} else {
frontmap[front] = frontmap[child] ;
}
}
front = sib[front] ;
}
return(frontmapIV) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
compress an ETree object given a map from old to new nodes.
note, a new node must be a connected set of the old nodes.
return value -- pointer to new ETree object
created -- 96jun23, cca.
-----------------------------------------------------------
*/
ETree *
ETree_compress (
ETree *etree,
IV *frontmapIV
) {
ETree *etree2 ;
int nfront, newfront, newnfront, newparfront, nvtx, oldfront,
parfront, v ;
int *bndwghts, *frontmap, *newbndwghts, *newnodwghts, *newpar,
*newvtxToFront, *nodwghts, *par, *vtxToFront ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 || frontmapIV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_compress(%p,%p)"
"\n bad input\n", etree, frontmapIV) ;
exit(-1) ;
}
/*
--------------------------------
pull out pointers and dimensions
--------------------------------
*/
nfront = etree->nfront ;
nvtx = etree->nvtx ;
par = etree->tree->par ;
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
newnfront = 1 + IV_max(frontmapIV) ;
frontmap = IV_entries(frontmapIV) ;
#if MYDEBUG > 0
fprintf(stdout, "\n newnfront = %d", newnfront) ;
#endif
/*
-------------------------------
initialize the new ETree object
-------------------------------
*/
etree2 = ETree_new() ;
ETree_init1(etree2, newnfront, nvtx) ;
newpar = etree2->tree->par ;
newnodwghts = IV_entries(etree2->nodwghtsIV) ;
newbndwghts = IV_entries(etree2->bndwghtsIV) ;
newvtxToFront = IV_entries(etree2->vtxToFrontIV) ;
#if MYDEBUG > 0
fprintf(stdout, "\n newnodwghts") ;
IV_writeForHumanEye(etree2->nodwghtsIV, stdout) ;
#endif
/*
------------------------
fill the new tree fields
------------------------
*/
for ( oldfront = 0 ; oldfront < nfront ; oldfront++ ) {
newfront = frontmap[oldfront] ;
parfront = par[oldfront] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n oldfront = %d, nodwght = %d, parfront = %d, newfront = %d",
oldfront, nodwghts[oldfront], parfront, newfront) ;
fflush(stdout) ;
#endif
newnodwghts[newfront] += nodwghts[oldfront] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n nodwghts[%d] = %d, newnodwghts[%d] = %d",
oldfront, nodwghts[oldfront],
newfront, newnodwghts[newfront]) ;
fflush(stdout) ;
#endif
if ( parfront != -1
&& (newparfront = frontmap[parfront]) != newfront ) {
newpar[newfront] = newparfront ;
newbndwghts[newfront] = bndwghts[oldfront] ;
#if MYDEBUG > 0
fprintf(stdout, "\n newparfront = %d", newparfront) ;
fprintf(stdout,
"\n setting newpar[%d] = %d, newbndwghts[%d] = %d",
newfront, newpar[newfront],
newfront, newbndwghts[newfront]) ;
fflush(stdout) ;
#endif
}
}
Tree_setFchSibRoot(etree2->tree) ;
/*
---------------------------------------
set the map from vertices to new fronts
---------------------------------------
*/
for ( v = 0 ; v < nvtx ; v++ ) {
newvtxToFront[v] = frontmap[vtxToFront[v]] ;
}
return(etree2) ; }
/*--------------------------------------------------------------------*/
|| (nfront = etree->nfront) <= 0 || (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_fundChainMap(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
/*
-------------------------------------
call the Tree object's method to get
the map from old fronts to new fronts
-------------------------------------
*/
frontmapIV = Tree_fundChainMap(etree->tree) ;
return(frETree/src/init.c 0100644 0002055 0007177 00000031044 06636030037 0015000 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../ETree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
/*
-------------------------------
initialize the object given the
number of fronts and vertices
created -- 96jun23, cca
-------------------------------
*/
void
ETree_init1 (
ETree *etree,
int nfront,
int nvtx
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || nfront < 0 || nvtx < nfront ) {
fprintf(stderr, "\n fatal error in ETree_init1(%p,%d,%d)"
"\n bad input\n", etree, nfront, nvtx) ;
exit(-1) ;
}
ETree_clearData(etree) ;
etree->nfront = nfront ;
etree->nvtx = nvtx ;
etree->tree = Tree_new() ;
Tree_init1(etree->tree, nfront) ;
etree->nodwghtsIV = IV_new() ;
IV_init(etree->nodwghtsIV, nfront, NULL) ;
IV_fill(etree->nodwghtsIV, 0) ;
etree->bndwghtsIV = IV_new() ;
IV_init(etree->bndwghtsIV, nfront, NULL) ;
IV_fill(etree->bndwghtsIV, 0) ;
etree->vtxToFrontIV = IV_new() ;
IV_init(etree->vtxToFrontIV, nvtx, NULL) ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------
initialize the ETree object from a graph
created -- 95nov15, cca
----------------------------------------
*/
void
ETree_initFromGraph (
ETree *etree,
Graph *g
) {
int ii, nfront, nvtx, u, v, vsize ;
int *bndwghts, *mark, *nodwghts, *par, *vadj ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || g == NULL || (nvtx = g->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_initFromGraph(%p,%p)"
"\n bad input\n", etree, g) ;
exit(-1) ;
}
/*
-----------------
set up the object
-----------------
*/
nfront = nvtx ;
ETree_init1(etree, nfront, nvtx) ;
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
par = etree->tree->par ;
IV_ramp(etree->vtxToFrontIV, 0, 1) ;
/*
--------------------------------------------------------
fill the parent, node weight and boundary weight vectors
--------------------------------------------------------
*/
if ( g->vwghts == NULL ) {
IVfill(nvtx, nodwghts, 1) ;
} else {
IVcopy(nvtx, nodwghts, g->vwghts) ;
}
mark = IVinit(nvtx, -1) ;
IVramp(nvtx, mark, 0, 1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
u = vadj[ii] ;
while ( u < v && mark[u] != v ) {
bndwghts[u] += nodwghts[v] ;
if ( mark[u] == u ) {
par[u] = v ;
}
mark[u] = v ;
u = par[u] ;
}
}
}
IVfree(mark) ;
/*
------------------------------------
set the fch[], sub[] and root fields
------------------------------------
*/
Tree_setFchSibRoot(etree->tree) ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
initialize the ETree object from a graph and permutation
created -- 95nov15, cca
--------------------------------------------------------
*/
void
ETree_initFromGraphWithPerms (
ETree *etree,
Graph *g,
int newToOld[],
int oldToNew[]
) {
int ii, nfront, nvtx, unew, uold, vold, vnew, vsize ;
int *bndwghts, *mark, *nodwghts, *par, *vadj ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || g == NULL || (nvtx = g->nvtx) <= 0
|| newToOld == NULL || oldToNew == NULL ) {
fprintf(stderr, "\n fatal error in ETree_initFromGraph(%p,%p,%p,%p)"
"\n bad input\n", etree, g, newToOld, oldToNew) ;
exit(-1) ;
}
nfront = nvtx ;
/*
--------------------------------------------------
check that the permutation is really a permutation
--------------------------------------------------
*/
for ( unew = 0 ; unew < nvtx ; unew++ ) {
if ( (uold = newToOld[unew]) < 0
|| uold >= nvtx
|| oldToNew[uold] != unew ) {
fprintf(stderr,
"\n fatal error in ETree_initFromGraphWithPerms(%p,%p,%p,%p)"
"\n uold = %d, unew = %d",
etree, g, newToOld, oldToNew, uold, unew) ;
if ( 0 <= uold && uold < nvtx ) {
fprintf(stderr, "\n oldToNew[%d] = %d", uold, oldToNew[uold]) ;
}
if ( 0 <= unew && unew < nvtx ) {
fprintf(stderr, "\n newToOld[%d] = %d", unew, newToOld[unew]) ;
}
exit(-1) ;
}
}
/*
-----------------
set up the object
-----------------
*/
nfront = nvtx ;
ETree_init1(etree, nfront, nvtx) ;
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
par = etree->tree->par ;
IVcopy(nvtx, IV_entries(etree->vtxToFrontIV), oldToNew) ;
/*
--------------------------------------------------------
fill the parent, node weight and boundary weight vectors
--------------------------------------------------------
*/
if ( g->vwghts == NULL ) {
IVfill(nvtx, nodwghts, 1) ;
} else {
for ( vold = 0 ; vold < nvtx ; vold++ ) {
nodwghts[oldToNew[vold]] = g->vwghts[vold] ;
}
}
mark = IVinit(nvtx, -1) ;
IVramp(nvtx, mark, 0, 1) ;
for ( vnew = 0 ; vnew < nvtx ; vnew++ ) {
vold = newToOld[vnew] ;
Graph_adjAndSize(g, vold, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
uold = vadj[ii] ;
if ( uold < nvtx ) {
unew = oldToNew[uold] ;
while ( unew < vnew && mark[unew] != vnew ) {
bndwghts[unew] += nodwghts[vnew] ;
if ( mark[unew] == unew ) {
par[unew] = vnew ;
}
mark[unew] = vnew ;
unew = par[unew] ;
}
}
}
}
IVfree(mark) ;
/*
------------------------------------
set the fch[], sub[] and root fields
------------------------------------
*/
Tree_setFchSibRoot(etree->tree) ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
purpose -- initialize the front tree for a dense matrix
n -- size of the matrix
option -- mapping option
1 --> have all fronts (save the last) contain the same
number of vertices
2 --> have all fronts have roughly equal numbers of entries
created -- 96aug19, cca
--------------------------------------------------------------
*/
void
ETree_initFromDenseMatrix (
ETree *etree,
int n,
int option,
int param
) {
int b, bnd, first, front, ii, last, nent, nfront, target ;
int *bndwghts, *nodwghts, *par, *vtxToFront ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || n <= 0
|| option < 1 || option > 2 || param <= 0 ) {
fprintf(stderr,
"\n fatal error in ETree_initFromDenseMatrix(%p,%d,%d,%d)"
"\n bad input\n", etree, n, option, param) ;
exit(-1) ;
}
ETree_clearData(etree) ;
if ( option == 1 ) {
/*
------------------------------------------------------------------
first option, let all front be size b except for possibly the root
------------------------------------------------------------------
*/
b = param ;
nfront = (n + b - 1)/b ;
ETree_init1(etree, nfront, n) ;
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
for ( ii = 0 ; ii < n ; ii++ ) {
vtxToFront[ii] = ii / b ;
}
for ( ii = 0, bnd = n ; ii < nfront ; ii++ ) {
nodwghts[ii] = (b <= bnd) ? b : bnd ;
bnd -= nodwghts[ii] ;
bndwghts[ii] = bnd ;
}
} else if ( option == 2 ) {
/*
------------------------------------------------------------
second option, let each front have the same number of entries
------------------------------------------------------------
*/
target = param ;
first = 0 ;
bnd = n - 1 ;
nfront = 0 ;
while ( first < n ) {
nent = 2*(n - first) - 1 ;
last = first + 1 ;
while ( last < n && (nent + 2*(n - last) - 1) <= target ) {
nent += 2*(n - last) - 1 ;
last++ ;
}
first = last ;
nfront++ ;
}
ETree_init1(etree, nfront, n) ;
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
first = 0 ;
bnd = n - 1 ;
front = 0 ;
while ( first < n ) {
nent = 2*(n - first) - 1 ;
vtxToFront[first] = front ;
last = first + 1 ;
while ( last < n && (nent + 2*(n - last) - 1) <= target ) {
vtxToFront[last] = front ;
nent += 2*(n - last) - 1 ;
last++ ;
}
last-- ;
fprintf(stdout, "\n front = %d, first = %d, last = %d, nent = %d",
front, first, last, nent) ;
nodwghts[front] = last - first + 1 ;
bndwghts[front] = n - last - 1 ;
first = last + 1 ;
front++ ;
}
}
par = etree->tree->par ;
IVramp(nfront, par, 1, 1) ;
par[nfront-1] = -1 ;
Tree_setFchSibRoot(etree->tree) ;
{
int bndJ, count, ierr, I, J, sizeI, sizeJ ;
int *tmp ;
double facops, solops, updops ;
facops = solops = updops = 0.0 ;
tmp = IVinit((nfront*(nfront+1))/2, -1) ;
count = 0 ;
for ( J = 0 ; J < nfront ; J++ ) {
sizeJ = nodwghts[J] ;
bndJ = bndwghts[J] ;
facops += 2*(sizeJ * sizeJ * sizeJ)/3 ;
solops += 2 * sizeJ * sizeJ * bndJ ;
tmp[count++] = facops + solops ;
for ( I = 0 ; I < J ; I++ ) {
sizeI = nodwghts[I] ;
updops += 2 * sizeI * sizeJ * (sizeJ + 2*bndJ) ;
tmp[count++] = updops ;
}
}
IVqsortUp(count, tmp) ;
/*
IVfp80(stdout, count, tmp, 80, &ierr) ;
*/
IVfree(tmp) ;
fprintf(stdout,
"\n factor ops = %.0f, %5.1f per cent of total"
"\n solve ops = %.0f, %5.1f per cent of total"
"\n update ops = %.0f, %5.1f per cent of total",
facops, 100.*facops/(facops + solops + updops),
solops, 100.*solops/(facops + solops + updops),
updops, 100.*updops/(facops + solops + updops)) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------
initialize the ETree object
(1) read ETree object from file
(2) get the old-to-new permutation
(3) permute the ETree
(4) return the old-to-new permutation
created -- 97jul13, cca
-------------------------------------
*/
IV *
ETree_initFromFile (
ETree *frontETree,
char *inETreeFileName,
int msglvl,
FILE *msgFile
) {
double t1, t2 ;
int neqns, rc ;
IV *oldToNewIV ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
ETree_setDefaultFields(frontETree) ;
rc = ETree_readFromFile(frontETree, inETreeFileName) ;
MARKTIME(t2) ;
neqns = frontETree->nvtx ;
fprintf(msgFile, "\n CPU %8.3f : read in frontETree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, frontETree, inETreeFileName) ;
exit(-1) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl == 2 ) {
ETree_writeStats(frontETree, msgFile) ;
} else {
ETree_writeForHumanEye(frontETree, msgFile) ;
}
}
fflush(msgFile) ;
/*
-----------------------------
get the permutation IV object
-----------------------------
*/
MARKTIME(t1) ;
oldToNewIV = ETree_oldToNewVtxPerm(frontETree) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get permutation", t2 - t1) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n vertex old-to-new IV object") ;
if ( msglvl == 2 ) {
IV_writeStats(oldToNewIV, msgFile) ;
} else {
IV_writeForHumanEye(oldToNewIV, msgFile) ;
}
fflush(msgFile) ;
}
/*
----------------------------------------
permute the vertices in the ETree object
----------------------------------------
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n before permuting the vertex map") ;
if ( msglvl == 2 ) {
ETree_writeStats(frontETree, msgFile) ;
} else {
ETree_writeForHumanEye(frontETree, msgFile) ;
}
fflush(msgFile) ;
}
MARKTIME(t1) ;
ETree_permuteVertices(frontETree, oldToNewIV) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : permute ETree", t2 - t1) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n after permuting the vertex map") ;
if ( msglvl == 2 ) {
ETree_writeStats(frontETree, msgFile) ;
} else {
ETree_writeForHumanEye(frontETree, msgFile) ;
}
fflush(msgFile) ;
}
return(oldToNewIV) ; }
/*--------------------------------------------------------------------*/
d = %d, unew = %d",
etree, g, newToOld, oldToNew, uold, unew) ;
if ( 0 <= uold && uold < nvtx ) {
fprintf(stderr, "\n oldToNew[%d] = %d", uold, oldToNew[uold]) ;
}
if ( 0 <= unew && unew < nvtx ) {
fprintf(stderr, "\n newToOld[%d] = %d", unew, newToOld[unew]) ;
}
exit(-1) ;
}
}
/*
-----------------
set up the object
-----------------
*/
nfront = nvtx ;
ETree_init1(etree, nfront, nvtx) ;
nodwghts = IV_entETree/src/initFromSubtree.c 0100644 0002055 0007177 00000010346 06636030037 0017160 0 ustar 00cleve compmath 0000040 0000006 /* initFromSubtree.c */
#include "../ETree.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- to initialize subtree with the subtree
of the front tree using nodes in nodeidsIV.
vtxIV is filled with the vertices in the subtree
return values ---
1 -- normal return
-1 -- subtree is NULL
-2 -- nodeidsIV is NULL
-3 -- etree is NULL
-4 -- nodeidsIV is invalid
-5 -- vtxIV is NULL
created -- 98oct15, cca
-----------------------------------------------------------
*/
int
ETree_initFromSubtree (
ETree *subtree,
IV *nodeidsIV,
ETree *etree,
IV *vtxIV
) {
int J, Jsub, nfrontInETree, nfrontInSubtree,
nvtxInETree, nvtxInSubtree, v, vSub ;
int *bndwghts, *bndwghtsSub, *localmap, *nodwghts, *nodwghtsSub,
*subtreeNodes, *vtxInSubtree, *vtxToFront, *vtxToFrontSub ;
/*
---------------
check the input
---------------
*/
if ( subtree == NULL ) {
fprintf(stderr, "\n\n error in ETree_initFromSubtree()"
"\n subtree is NULL\n") ;
return(-1) ;
}
if ( nodeidsIV == NULL ) {
fprintf(stderr, "\n\n error in ETree_initFromSubtree()"
"\n nodeidsIV is NULL\n") ;
return(-2) ;
}
if ( etree == NULL ) {
fprintf(stderr, "\n\n error in ETree_initFromSubtree()"
"\n etree is NULL\n") ;
return(-3) ;
}
nfrontInETree = ETree_nfront(etree) ;
IV_sizeAndEntries(nodeidsIV, &nfrontInSubtree, &subtreeNodes) ;
if ( nfrontInSubtree < 0 || nfrontInSubtree >= nfrontInETree ) {
fprintf(stderr, "\n\n error in ETree_initFromSubtree()"
"\n nfrontInETree = %d, nfrontInSubtree = %d\n",
nfrontInETree, nfrontInSubtree) ;
return(-4) ;
}
for ( Jsub = 0 ; Jsub < nfrontInSubtree ; Jsub++ ) {
J = subtreeNodes[Jsub] ;
if ( J < 0 || J >= nfrontInETree ) {
fprintf(stderr, "\n\n error in ETree_initFromSubtree()"
"\n nfrontInETree = %d, subtreeNodes[%d] = %d\n",
nfrontInETree, Jsub, subtreeNodes[Jsub]) ;
return(-4) ;
}
}
if ( vtxIV == NULL ) {
fprintf(stderr, "\n\n error in ETree_initFromSubtree()"
"\n vtxIV is NULL\n") ;
return(-5) ;
}
nvtxInETree = ETree_nvtx(etree) ;
vtxToFront = ETree_vtxToFront(etree) ;
/*
----------------------------
create a global-to-local map
----------------------------
*/
localmap = IVinit(nfrontInETree, -1) ;
for ( Jsub = 0 ; Jsub < nfrontInSubtree ; Jsub++ ) {
J = subtreeNodes[Jsub] ;
localmap[J] = Jsub ;
}
/*
---------------------------------------------
compute the number of vertices in the subtree
---------------------------------------------
*/
nvtxInSubtree = 0 ;
for ( v = 0 ; v < nvtxInETree ; v++ ) {
J = vtxToFront[v] ;
if ( (Jsub = localmap[J]) != -1 ) {
nvtxInSubtree++ ;
}
}
/*
----------------------
initialize the subtree
----------------------
*/
ETree_init1(subtree, nfrontInSubtree, nvtxInSubtree) ;
/*
-----------------------------
initialize the subtree's tree
-----------------------------
*/
Tree_initFromSubtree(subtree->tree, nodeidsIV, etree->tree) ;
/*
-----------------------------------
set the nodwght and bndwght vectors
-----------------------------------
*/
nodwghts = ETree_nodwghts(etree) ;
bndwghts = ETree_bndwghts(etree) ;
nodwghtsSub = ETree_nodwghts(subtree) ;
bndwghtsSub = ETree_bndwghts(subtree) ;
for ( Jsub = 0 ; Jsub < nfrontInSubtree ; Jsub++ ) {
J = subtreeNodes[Jsub] ;
nodwghtsSub[Jsub] = nodwghts[J] ;
bndwghtsSub[Jsub] = bndwghts[J] ;
}
/*
-------------------------------------
set the subtree's vtxToFront[] vector
and fill vtxIV with the vertices
-------------------------------------
*/
IV_init(vtxIV, nvtxInSubtree, NULL) ;
vtxInSubtree = IV_entries(vtxIV) ;
vtxToFrontSub = ETree_vtxToFront(subtree) ;
for ( v = vSub = 0 ; v < nvtxInETree ; v++ ) {
J = vtxToFront[v] ;
if ( (Jsub = localmap[J]) != -1 ) {
vtxInSubtree[vSub] = v ;
vtxToFrontSub[vSub] = Jsub ;
vSub++ ;
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(localmap) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ETree/src/instance.c 0100644 0002055 0007177 00000023362 06536016544 0015653 0 ustar 00cleve compmath 0000040 0000006 /* instance.c */
#include "../ETree.h"
/*--------------------------------------------------------------------*/
/*
---------------------------
return the number of fronts
created -- 97feb28, cca
---------------------------
*/
int
ETree_nfront (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_nfront(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(etree->nfront) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------
return the number of vertices
created -- 97feb28, cca
-----------------------------
*/
int
ETree_nvtx (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_nvtx(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(etree->nvtx) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------
return a pointer to the Tree object
created -- 97feb28, cca
-----------------------------------
*/
Tree *
ETree_tree (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_tree(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(etree->tree) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------
return the root of the tree
created -- 97feb28, cca
---------------------------
*/
int
ETree_root (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->tree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_root(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(etree->tree->root) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------
return a pointer to the parent vector
created -- 97feb28, cca
-------------------------------------
*/
int *
ETree_par (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->tree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_par(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(etree->tree->par) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
return a pointer to the first child vector
created -- 97feb28, cca
------------------------------------------
*/
int *
ETree_fch (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->tree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_fch(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(etree->tree->fch) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
return a pointer to the sibling vector
created -- 97feb28, cca
--------------------------------------
*/
int *
ETree_sib (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->tree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_sib(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(etree->tree->sib) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
return a pointer to the nodwghts IV object
created -- 97feb28, cca
------------------------------------------
*/
IV *
ETree_nodwghtsIV (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_nodwghtsIV(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(etree->nodwghtsIV) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------
return a pointer to the nodwghts int vector
created -- 97feb28, cca
-------------------------------------------
*/
int *
ETree_nodwghts (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->nodwghtsIV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_nodwghts(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(IV_entries(etree->nodwghtsIV)) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
return a pointer to the bndwghts IV object
created -- 97feb28, cca
------------------------------------------
*/
IV *
ETree_bndwghtsIV (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_bndwghtsIV(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(etree->bndwghtsIV) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------
return a pointer to the bndwghts int vector
created -- 97feb28, cca
-------------------------------------------
*/
int *
ETree_bndwghts (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->bndwghtsIV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_bndwghts(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(IV_entries(etree->bndwghtsIV)) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
return a pointer to the vtxToFront IV object
created -- 97feb28, cca
--------------------------------------------
*/
IV *
ETree_vtxToFrontIV (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_vtxToFrontIV(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(etree->vtxToFrontIV) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
return a pointer to the vtxToFront int vector
created -- 97feb28, cca
---------------------------------------------
*/
int *
ETree_vtxToFront (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->vtxToFrontIV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_vtxToFront(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
return(IV_entries(etree->vtxToFrontIV)) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------
purpose -- return the number of internal degrees
of freedom in front J
created -- 97may23, cca
------------------------------------------------
*/
int
ETree_frontSize (
ETree *etree,
int J
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || J < 0 || J >= etree->nfront ) {
fprintf(stderr, "\n fatal error in ETree_frontSize(%p,%d)"
"\n bad input\n", etree, J) ;
exit(-1) ;
}
return(etree->nodwghtsIV->vec[J]) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------
purpose -- return the number of external degrees
of freedom in front J
created -- 97may23, cca
------------------------------------------------
*/
int
ETree_frontBoundarySize (
ETree *etree,
int J
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || J < 0 || J >= etree->nfront ) {
fprintf(stderr, "\n fatal error in ETree_frontBoundarySize(%p,%d)"
"\n bad input\n", etree, J) ;
exit(-1) ;
}
return(etree->bndwghtsIV->vec[J]) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
purpose -- compute the maximum number of indices and entries
in a front
symflag = SPOOLES_SYMMETRIC or SPOOLES_HERMITIAN -->
count only column indices
count upper entries in (1,1) block and (1,2) block
symflag = SPOOLES_NONSYMMETRIC -->
count row and column indices
count entries in (1,1), (1,2) and (2,1) blocks
created -- 97may23, cca
------------------------------------------------------------
*/
void
ETree_maxNindAndNent (
ETree *etree,
int symflag,
int *pmaxnind,
int *pmaxnent
) {
int J, maxnent, maxnind, nDJ, nent, nfront, nind, nUJ ;
int *nodwghts, *bndwghts ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_maxNindAndNent(%p,%d)"
"\n bad input\n", etree, symflag) ;
exit(-1) ;
}
nfront = etree->nfront ;
nodwghts = ETree_nodwghts(etree) ;
bndwghts = ETree_bndwghts(etree) ;
for ( J = 0, maxnent = maxnind = 0 ; J < nfront ; J++ ) {
nDJ = nodwghts[J] ;
nUJ = bndwghts[J] ;
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
nind = nDJ + nUJ ;
nent = (nDJ*(nDJ+1))/2 + nDJ*nUJ ;
break ;
case SPOOLES_NONSYMMETRIC :
nind = 2*(nDJ + nUJ) ;
nent = nDJ*(nDJ + 2*nUJ) ;
break ;
default :
fprintf(stderr, "\n fatal error in ETree_maxNindAndNent(%p,%d)"
"\n bad symflag\n", etree, symflag) ;
exit(-1) ;
break ;
}
if ( maxnind < nind ) {
maxnind = nind ;
}
if ( maxnent < nent ) {
maxnent = nent ;
}
}
*pmaxnind = maxnind ;
*pmaxnent = maxnent ;
return ; }
/*--------------------------------------------------------------------*/
ETree/src/justify.c 0100644 0002055 0007177 00000004526 06534106074 0015541 0 ustar 00cleve compmath 0000040 0000006 /* justify.c */
#include "../ETree.h"
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
left-justify a tree by subtree size
children are linked in ascending order of their subtree size
created -- 96jan11, cca
------------------------------------------------------------
*/
void
ETree_leftJustify (
ETree *etree
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->tree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_leftJustify(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
Tree_leftJustify(etree->tree) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
left-justify a etree by a metric
children are linked in ascending order of their metric
created -- 96jan11, cca
------------------------------------------------------
*/
void
ETree_leftJustifyI (
ETree *etree,
IV *metricIV
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| etree->nfront <= 0
|| etree->nvtx <= 0
|| metricIV == NULL
|| IV_size(metricIV) != etree->nfront
|| IV_entries(metricIV) == NULL ) {
fprintf(stderr, "\n fatal error in ETree_leftJustifyI(%p,%p)"
"\n bad input\n", etree, metricIV) ;
exit(-1) ;
}
Tree_leftJustifyI(etree->tree, metricIV) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
left-justify a etree by a metric
children are linked in ascending order of their metric
created -- 96jan11, cca
------------------------------------------------------
*/
void
ETree_leftJustifyD (
ETree *etree,
DV *metricDV
) {
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| etree->nfront <= 0
|| etree->nvtx <= 0
|| metricDV == NULL
|| DV_size(metricDV) != etree->nfront
|| DV_entries(metricDV) == NULL ) {
fprintf(stderr, "\n fatal error in ETree_leftJustifyD(%p,%p)"
"\n bad input\n", etree, metricDV) ;
exit(-1) ;
}
Tree_leftJustifyD(etree->tree, metricDV) ;
return ; }
/*--------------------------------------------------------------------*/
ETree/src/maps.c 0100644 0002055 0007177 00000055300 06651177603 0015006 0 ustar 00cleve compmath 0000040 0000006 /* maps.c */
#include "../ETree.h"
#define MYDEBUG 0
#define SUBTREE_SIZE 1
#define SUBTREE_OPS 2
#define SUBTREE_DEFINITION SUBTREE_OPS
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
this method constructs and returns an IV object that holds the
map from fronts to threads for a wrap map of the front tree.
created -- 96dec12, cca
--------------------------------------------------------------
*/
IV *
ETree_wrapMap (
ETree *frontETree,
int type,
int symflag,
DV *cumopsDV
) {
double *cumops, *forwardOps ;
DV *forwardOpsDV ;
int jthread, J, nfront, nthread ;
int *owners ;
IV *ownersIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( frontETree == NULL || cumopsDV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_wrapMap(%p,%p)"
"\n bad input\n", frontETree, cumopsDV) ;
exit(-1) ;
}
tree = frontETree->tree ;
DV_sizeAndEntries(cumopsDV, &nthread, &cumops) ;
DV_zero(cumopsDV) ;
/*
---------------------------------
get a vector of forward op counts
---------------------------------
*/
forwardOpsDV = ETree_forwardOps(frontETree, type, symflag) ;
DV_sizeAndEntries(forwardOpsDV, &nfront, &forwardOps) ;
/*
-------------------
load the map vector
-------------------
*/
ownersIV = IV_new() ;
IV_init(ownersIV, nfront, NULL) ;
owners = IV_entries(ownersIV) ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
jthread = J % nthread ;
owners[J] = jthread ;
cumops[jthread] += forwardOps[J] ;
}
/*
------------------------
free the working storage
------------------------
*/
DV_free(forwardOpsDV) ;
return(ownersIV) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
this method constructs and returns an IV object that holds the
map from fronts to threads for a balanced map of the front tree.
the fronts are visited in the post-order traversal.
created -- 96dec12, cca
----------------------------------------------------------------
*/
IV *
ETree_balancedMap (
ETree *frontETree,
int type,
int symflag,
DV *cumopsDV
) {
double minops ;
double *cumops, *forwardOps ;
DV *forwardOpsDV ;
int ithread, jthread, J, nfront, nthread ;
int *owners ;
IV *ownersIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( frontETree == NULL || cumopsDV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_balancedMap(%p,%p)"
"\n bad input\n", frontETree, cumopsDV) ;
exit(-1) ;
}
tree = frontETree->tree ;
DV_sizeAndEntries(cumopsDV, &nthread, &cumops) ;
DV_zero(cumopsDV) ;
/*
---------------------------------
get a vector of forward op counts
---------------------------------
*/
forwardOpsDV = ETree_forwardOps(frontETree, type, symflag) ;
DV_sizeAndEntries(forwardOpsDV, &nfront, &forwardOps) ;
/*
-------------------
load the map vector
-------------------
*/
ownersIV = IV_new() ;
IV_init(ownersIV, nfront, NULL) ;
owners = IV_entries(ownersIV) ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
jthread = 0 ;
minops = cumops[0] ;
for ( ithread = 1 ; ithread < nthread ; ithread++ ) {
if ( minops > cumops[ithread] ) {
jthread = ithread ;
minops = cumops[ithread] ;
}
}
owners[J] = jthread ;
cumops[jthread] += forwardOps[J] ;
}
/*
------------------------
free the working storage
------------------------
*/
DV_free(forwardOpsDV) ;
return(ownersIV) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
this method constructs and returns an IV object
that holds the map from fronts to threads for a
"subtree-subset" map of the front tree.
created -- 97jan15, cca
-----------------------------------------------
*/
IV *
ETree_subtreeSubsetMap (
ETree *frontETree,
int type,
int symflag,
DV *cumopsDV
) {
double offset, total ;
double *cumops, *forwardOps, *tmetric ;
DV *forwardOpsDV, *tmetricDV ;
int I, J, mthread, nfront, nthread, q, qmin ;
int *fch, *firsts, *lasts, *owners, *par, *sib ;
IV *ownersIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( frontETree == NULL || cumopsDV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_subtreeSubsetMap(%p,%p)"
"\n bad input\n", frontETree, cumopsDV) ;
exit(-1) ;
}
tree = frontETree->tree ;
fch = tree->fch ;
par = tree->par ;
sib = tree->sib ;
DV_sizeAndEntries(cumopsDV, &nthread, &cumops) ;
DV_zero(cumopsDV) ;
/*
---------------------------------
get a vector of forward op counts
---------------------------------
*/
forwardOpsDV = ETree_forwardOps(frontETree, type, symflag) ;
DV_sizeAndEntries(forwardOpsDV, &nfront, &forwardOps) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n forwardOpsDV") ;
DV_writeForHumanEye(forwardOpsDV, stdout) ;
fflush(stdout) ;
#endif
/*
--------------------------------
get the subtree metric DV object
--------------------------------
*/
tmetricDV = Tree_setSubtreeDmetric(tree, forwardOpsDV) ;
tmetric = DV_entries(tmetricDV) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n tmetricDV") ;
DV_writeForHumanEye(tmetricDV, stdout) ;
fflush(stdout) ;
#endif
/*
-----------------------------------
left justify the tree to make the
assignment algorithm work correctly
-----------------------------------
*/
ETree_leftJustifyD(frontETree, tmetricDV) ;
/*
-----------------------------------------------------
fill two vectors that hold the first and last threads
that are eligible to own a front
-----------------------------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n\n pre-order traversal to determine eligible sets") ;
fflush(stdout) ;
#endif
firsts = IVinit(nfront, -1) ;
lasts = IVinit(nfront, -1) ;
for ( J = Tree_preOTfirst(tree) ;
J != -1 ;
J = Tree_preOTnext(tree, J) ) {
#if MYDEBUG > 0
fprintf(stdout, "\n\n visiting front %d", J) ;
fflush(stdout) ;
#endif
if ( par[J] == -1 ) {
firsts[J] = 0 ;
lasts[J] = nthread - 1 ;
#if MYDEBUG > 0
fprintf(stdout, ", root front") ;
fflush(stdout) ;
#endif
}
#if MYDEBUG > 0
fprintf(stdout, "\n first = %d, last = %d", firsts[J], lasts[J]) ;
fflush(stdout) ;
#endif
if ( fch[J] != -1 ) {
mthread = lasts[J] - firsts[J] + 1 ;
total = tmetric[J] - forwardOps[J] ;
#if MYDEBUG > 0
fprintf(stdout, "\n mthread = %d, total = %.0f", mthread, total) ;
fflush(stdout) ;
#endif
for ( I = fch[J], offset = 0.0 ; I != -1 ; I = sib[I] ) {
firsts[I] = firsts[J] + (int) (mthread*offset/total) ;
#if MYDEBUG > 0
fprintf(stdout, "\n child %d, offset = %.0f, firsts[%d] = %d",
I, offset, I, firsts[I]) ;
fflush(stdout) ;
#endif
offset += tmetric[I] ;
lasts[I] = firsts[J] + (int) (mthread*offset/total) - 1 ;
if ( lasts[I] < firsts[I] ) {
lasts[I] = firsts[I] ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n child %d, offset = %.0f, lasts[%d] = %d",
I, offset, I, lasts[I]) ;
fflush(stdout) ;
#endif
}
}
}
/*
---------------------------------------------------------------
now fill the map IV object and cumops[*] vector with a
balanced map using the candidate sets via a postorder traversal
---------------------------------------------------------------
*/
ownersIV = IV_new() ;
IV_init(ownersIV, nfront, NULL) ;
owners = IV_entries(ownersIV) ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
#if MYDEBUG > 0
fprintf(stdout, "\n front %d, firsts[%d] = %d, lasts[%d] = %d",
J, J, firsts[J], J, lasts[J]) ;
fflush(stdout) ;
#endif
qmin = firsts[J] ;
for ( q = firsts[J] + 1 ; q <= lasts[J] ; q++ ) {
if ( cumops[qmin] > cumops[q] ) {
qmin = q ;
}
}
owners[J] = qmin ;
cumops[qmin] += forwardOps[J] ;
#if MYDEBUG > 0
fprintf(stdout, ", owners[%d] = %d, cumops[%d] = %.0f",
J, owners[J], qmin, cumops[qmin]) ;
fflush(stdout) ;
#endif
}
/*
------------------------
free the working storage
------------------------
*/
DV_free(forwardOpsDV) ;
DV_free(tmetricDV) ;
IVfree(firsts) ;
IVfree(lasts) ;
return(ownersIV) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
this method constructs and returns an IV object that holds the
map from fronts to threads for a domain decomposition
balanced map of the front tree.
the domains are mapped to threads using a balanced map,
and the schur complement fronts are mapped to threads
using a balanced map, but the two balanced maps are independent.
created -- 97jan17, cca
----------------------------------------------------------------
*/
IV *
ETree_ddMap (
ETree *frontETree,
int type,
int symflag,
DV *cumopsDV,
double cutoff
) {
double minops ;
double *cumops, *domainops, *forwardOps, *schurops, *tmetric ;
DV *forwardOpsDV, *tmetricDV ;
int ithread, jthread, J, K, ndom, nfront, nthread, root ;
int *ms, *owners, *par, *rootAnc ;
IV *msIV, *ownersIV, *rootAncIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( frontETree == NULL || cumopsDV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_ddMap(%p,%p,%f)"
"\n bad input\n", frontETree, cumopsDV, cutoff) ;
exit(-1) ;
}
nfront = frontETree->nfront ;
tree = frontETree->tree ;
par = tree->par ;
DV_sizeAndEntries(cumopsDV, &nthread, &cumops) ;
DV_zero(cumopsDV) ;
/*
---------------------------------
get a vector of forward op counts
---------------------------------
*/
forwardOpsDV = ETree_forwardOps(frontETree, type, symflag) ;
DV_sizeAndEntries(forwardOpsDV, &nfront, &forwardOps) ;
#if MYDEBUG > 0
fprintf(stdout, "\n forwardOpsDV") ;
DV_writeForHumanEye(forwardOpsDV, stdout) ;
fflush(stdout) ;
#endif
#if SUBTREE_DEFINITION == SUBTREE_SIZE
/*
-----------------------------
get a vector of subtree sizes
-----------------------------
*/
{
DV *tempDV ;
IV *tempIV ;
tempIV = ETree_nvtxMetric(frontETree) ;
fprintf(stdout, "\n\n nvtx metric") ;
IV_writeForHumanEye(tempIV, stdout) ;
tempDV = DV_new() ;
for ( J = 0 ; J < nfront ; J++ ) {
DV_setEntry(tempDV, J, (double) IV_entry(tempIV, J)) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n double nvtx metric") ;
DV_writeForHumanEye(tempDV, stdout) ;
#endif
tmetricDV = Tree_setSubtreeDmetric(tree, tempDV) ;
IV_free(tempIV) ;
DV_free(tempDV) ;
}
#endif
#if SUBTREE_DEFINITION == SUBTREE_OPS
tmetricDV = Tree_setSubtreeDmetric(tree, forwardOpsDV) ;
#endif
/*
------------------------
get a multisector vector
------------------------
*/
msIV = IV_new() ;
IV_init(msIV, nfront, NULL) ;
IV_fill(msIV, 0) ;
ms = IV_entries(msIV) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n double nvtx subtree metric") ;
DV_writeForHumanEye(tmetricDV, stdout) ;
#endif
tmetric = DV_entries(tmetricDV) ;
cutoff = cutoff * DV_max(tmetricDV) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( tmetric[J] < cutoff ) {
ms[J] = 1 ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n msIV") ;
IV_writeForHumanEye(msIV, stdout) ;
fflush(stdout) ;
#endif
/*
--------------------------------------------
create a rootAnc vector,
if J is in a domain then
rootAnc[J] is the root node of the domain
else
rootAnc[J] is the root node of the tree
endif
--------------------------------------------
*/
rootAncIV = IV_new() ;
IV_init(rootAncIV, nfront, NULL) ;
rootAnc = IV_entries(rootAncIV) ;
for ( J = nfront - 1 ; J >= 0 ; J-- ) {
if ( (K = par[J]) == -1 || ms[J] != ms[K] ) {
rootAnc[J] = J ;
} else {
rootAnc[J] = rootAnc[K] ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n rootAncIV") ;
IV_writeForHumanEye(rootAncIV, stdout) ;
fflush(stdout) ;
#endif
/*
------------------------------
initialize the ownersIV object
------------------------------
*/
ownersIV = IV_new() ;
IV_init(ownersIV, nfront, NULL) ;
owners = IV_entries(ownersIV) ;
/*
--------------------------------------------------
assign the domains to threads using a balanced map
--------------------------------------------------
*/
domainops = DVinit(nthread, 0.0) ;
root = -1 ;
ndom = 0 ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
if ( ms[J] == 1 ) {
if ( root != rootAnc[J] ) {
ndom++ ;
root = rootAnc[J] ;
jthread = 0 ;
minops = domainops[0] ;
for ( ithread = 1 ; ithread < nthread ; ithread++ ) {
if ( minops > domainops[ithread] ) {
jthread = ithread ;
minops = domainops[ithread] ;
}
}
}
owners[J] = jthread ;
domainops[jthread] += forwardOps[J] ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n %d domains", ndom) ;
fprintf(stdout, "\n domainops") ;
DVfprintf(stdout, nthread, domainops) ;
fflush(stdout) ;
#endif
/*
------------------------------------------------------------------
assign the schur complement fronts to threads using a balanced map
------------------------------------------------------------------
*/
schurops = DVinit(nthread, 0.0) ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
if ( ms[J] == 0 ) {
jthread = 0 ;
minops = schurops[0] ;
for ( ithread = 1 ; ithread < nthread ; ithread++ ) {
if ( minops > schurops[ithread] ) {
jthread = ithread ;
minops = schurops[ithread] ;
}
}
owners[J] = jthread ;
schurops[jthread] += forwardOps[J] ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n schurops") ;
DVfprintf(stdout, nthread, schurops) ;
fflush(stdout) ;
#endif
/*
-------------------------------------
fill the cumulative operations vector
-------------------------------------
*/
for ( jthread = 0 ; jthread < nthread ; jthread++ ) {
cumops[jthread] = domainops[jthread] + schurops[jthread] ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n cumops") ;
DVfprintf(stdout, nthread, cumops) ;
fflush(stdout) ;
#endif
/*
------------------------
free the working storage
------------------------
*/
DV_free(forwardOpsDV) ;
DV_free(tmetricDV) ;
IV_free(msIV) ;
IV_free(rootAncIV) ;
DVfree(domainops) ;
DVfree(schurops) ;
return(ownersIV) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
this method constructs and returns an IV object that holds the
map from fronts to threads for a domain decomposition
balanced map of the front tree.
the domains are mapped to threads using a balanced map,
and the schur complement fronts are mapped to threads
using a balanced map, but the two balanced maps are independent.
created -- 97jan17, cca
----------------------------------------------------------------
*/
IV *
ETree_ddMapNew (
ETree *frontETree,
int type,
int symflag,
IV *msIV,
DV *cumopsDV
) {
double minops ;
double *cumops, *domprios, *domops, *forwardOps,
*schurprios, *schurops ;
DV *forwardOpsDV ;
int domid, idom, ireg, ithread, jthread, J, K, nbndJ,
ndom, nfront, nJ, nschur, nthread,
nvtx, v ;
int *bndwghts, *domids, *dommap, *frontToRegion, *ms,
*nodwghts, *owners, *par, *schurids, *vtxToFront ;
IV *ownersIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( frontETree == NULL || cumopsDV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_ddMapNew(%p,%p,%p)"
"\n bad input\n", frontETree, msIV, cumopsDV) ;
exit(-1) ;
}
nfront = ETree_nfront(frontETree) ;
nvtx = ETree_nvtx(frontETree) ;
tree = ETree_tree(frontETree) ;
vtxToFront = ETree_vtxToFront(frontETree) ;
nodwghts = ETree_nodwghts(frontETree) ;
bndwghts = ETree_bndwghts(frontETree) ;
par = ETree_par(frontETree) ;
DV_sizeAndEntries(cumopsDV, &nthread, &cumops) ;
DV_zero(cumopsDV) ;
ms = IV_entries(msIV) ;
ownersIV = IV_new() ;
IV_init(ownersIV, nfront, NULL) ;
owners = IV_entries(ownersIV) ;
/*
--------------------------------------
compute the frontToRegion[] map vector
--------------------------------------
*/
frontToRegion = IVinit(nfront, -1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
J = vtxToFront[v] ;
frontToRegion[J] = ms[v] ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n frontToRegion[] from msIV") ;
IVfprintf(stdout, nfront, frontToRegion) ;
#endif
ndom = 0 ;
for ( J = Tree_preOTfirst(tree) ;
J != -1 ;
J = Tree_preOTnext(tree, J) ) {
if ( frontToRegion[J] != 0 ) {
if ( (K = par[J]) != -1 ) {
if ( frontToRegion[K] == 0 ) {
frontToRegion[J] = ++ndom ;
} else {
frontToRegion[J] = frontToRegion[K] ;
}
} else {
frontToRegion[J] = ++ndom ;
}
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n frontToRegion[], separate domains") ;
IVfprintf(stdout, nfront, frontToRegion) ;
#endif
/*
---------------------------------
get a vector of forward op counts
---------------------------------
*/
forwardOpsDV = ETree_forwardOps(frontETree, type, symflag) ;
forwardOps = DV_entries(forwardOpsDV) ;
#if MYDEBUG > 0
fprintf(stdout, "\n forwardOpsDV") ;
DV_writeForHumanEye(forwardOpsDV, stdout) ;
#endif
/*
----------------------------------------
for each domain, compute the forward ops
----------------------------------------
*/
domprios = DVinit(ndom+1, 0.0) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (ireg = frontToRegion[J]) > 0 ) {
domprios[ireg] += forwardOps[J] ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n domprios[], sum = %.0f",
DVsum(ndom, domprios+1)) ;
DVfprintf(stdout, ndom+1, domprios) ;
#endif
/*
--------------------------------------------------------
sort the domains by descending order of their operations
--------------------------------------------------------
*/
domids = IVinit(ndom, -1) ;
IVramp(ndom, domids, 1, 1) ;
#if MYDEBUG > 0
fprintf(stdout, "\n before sort: domids") ;
IVfprintf(stdout, ndom, domids) ;
fprintf(stdout, "\n before sort: domprios") ;
DVfprintf(stdout, ndom, domprios+1) ;
#endif
DVIVqsortDown(ndom, domprios + 1, domids) ;
#if MYDEBUG > 0
fprintf(stdout, "\n after sort: domids") ;
IVfprintf(stdout, ndom, domids) ;
fprintf(stdout, "\n after sort: domprios") ;
DVfprintf(stdout, ndom, domprios+1) ;
#endif
/*
----------------------------
assign domains to processors
----------------------------
*/
dommap = IVinit(ndom+1, -1) ;
domops = DVinit(nthread, 0.0) ;
for ( idom = 0 ; idom < ndom ; idom++ ) {
domid = domids[idom] ;
jthread = 0 ;
minops = domops[0] ;
for ( ithread = 1 ; ithread < nthread ; ithread++ ) {
if ( domops[ithread] < minops ) {
jthread = ithread ;
minops = domops[ithread] ;
}
}
dommap[domid] = jthread ;
domops[jthread] += domprios[idom+1] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n assigning domain %d with ops %.0f to thread %d, new ops = %.0f",
domid, domprios[idom+1], jthread, domops[jthread]) ;
#endif
}
#if MYDEBUG > 0
fprintf(stdout, "\n domops[]") ;
DVfprintf(stdout, nthread, domops) ;
#endif
/*
-------------------------------------
assign fronts in domains to processes
-------------------------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
if ( (idom = frontToRegion[J]) > 0 ) {
owners[J] = dommap[idom] ;
}
}
/*
-----------------------------------------------------
now compute priorities of the schur complement fronts
-----------------------------------------------------
*/
schurprios = DVinit(nfront, 0.0) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( frontToRegion[J] == 0 ) {
nJ = nodwghts[J] ;
nbndJ = bndwghts[J] ;
schurprios[J] = nJ*nJ*(nJ + nbndJ) ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n schur front ops") ;
DVfprintf(stdout, nfront, schurprios) ;
#endif
for ( J = Tree_preOTfirst(tree) ;
J != -1 ;
J = Tree_preOTnext(tree, J) ) {
if ( frontToRegion[J] == 0 ) {
if ( (K = par[J]) != -1 ) {
schurprios[J] += schurprios[K] ;
}
}
}
/*
--------------------------------------------------
sort the priorities of the schur complement fronts
in descending order of their priorities
--------------------------------------------------
*/
schurids = IVinit(nfront, -1) ;
for ( J = nschur = 0 ; J < nfront ; J++ ) {
if ( frontToRegion[J] == 0 ) {
schurids[nschur] = J ;
schurprios[nschur] = schurprios[J] ;
nschur++ ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n before sort: schurids") ;
IVfprintf(stdout, nschur, schurids) ;
fprintf(stdout, "\n before sort: schurprios") ;
DVfprintf(stdout, nschur, schurprios) ;
#endif
DVIVqsortDown(nschur, schurprios, schurids) ;
#if MYDEBUG > 0
fprintf(stdout, "\n after sort: schurids") ;
IVfprintf(stdout, nschur, schurids) ;
fprintf(stdout, "\n after sort: schurprios") ;
DVfprintf(stdout, nschur, schurprios) ;
#endif
/*
---------------------------------
assign schur fronts to processors
---------------------------------
*/
schurops = DVinit(nthread, 0.0) ;
for ( ireg = 0 ; ireg < nschur ; ireg++ ) {
J = schurids[ireg] ;
jthread = 0 ;
minops = schurops[0] ;
for ( ithread = 1 ; ithread < nthread ; ithread++ ) {
if ( schurops[ithread] < minops ) {
jthread = ithread ;
minops = schurops[ithread] ;
}
}
owners[J] = jthread ;
schurops[jthread] += forwardOps[J] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n assigning schur front %d to thread %d, new ops = %.0f",
J, jthread, schurops[jthread]) ;
#endif
}
/*
------------------------------
fill the cumulative ops vector
------------------------------
*/
for ( jthread = 0 ; jthread < nthread ; jthread++ ) {
cumops[jthread] = domops[jthread] + schurops[jthread] ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n domops[]") ;
DVfprintf(stdout, nthread, domops) ;
fprintf(stdout, "\n schurops[]") ;
DVfprintf(stdout, nthread, schurops) ;
fprintf(stdout, "\n sum(domops) = %.0f", DVsum(nthread, domops)) ;
fprintf(stdout, "\n sum(schurops) = %.0f", DVsum(nthread, schurops)) ;
fprintf(stdout, "\n sum(cumops) = %.0f", DV_sum(cumopsDV)) ;
#endif
/*
------------------------
free the working storage
------------------------
*/
IVfree(frontToRegion) ;
IVfree(domids) ;
IVfree(dommap) ;
IVfree(schurids) ;
DV_free(forwardOpsDV) ;
DVfree(domprios) ;
DVfree(domops) ;
DVfree(schurprios) ;
DVfree(schurops) ;
return(ownersIV) ; }
/*--------------------------------------------------------------------*/
;
minops = domainops[0] ;
for ( ithread = 1 ; ithread < nthread ; ithread++ ) {
if ( minops > domainops[ithread] ) {
jthread = ithread ;
minops = domainops[ithread] ;
}
}
}
owners[J] = jthread ;
domainops[jthread] += fETree/src/metrics.c 0100644 0002055 0007177 00000006122 06536012361 0015501 0 ustar 00cleve compmath 0000040 0000006 /* metrics.c */
#include "../ETree.h"
/*--------------------------------------------------------------------*/
/*
------------------------------------
return an IV object with the weights
of the vertices in each front.
created -- 96jun23, cca
------------------------------------
*/
IV *
ETree_nvtxMetric (
ETree *etree
) {
IV *metricIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->nfront <= 0 || etree->nvtx <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_nvtxMetric(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
metricIV = IV_new() ;
IV_init(metricIV, etree->nfront, NULL) ;
IVcopy(etree->nfront, IV_entries(metricIV),
IV_entries(etree->nodwghtsIV)) ;
return(metricIV) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
return an IV object with the number
of factor entries in each front.
symflag -- symmetryflag
SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 96jun23, cca
---------------------------------------------------------------
*/
IV *
ETree_nentMetric (
ETree *etree,
int flag
) {
int front, nfront, nb, nv ;
int *bndwghts, *metric, *nodwghts ;
IV *metricIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0 || etree->nvtx <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_nentMetric(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
metricIV = IV_new() ;
IV_init(metricIV, nfront, NULL) ;
metric = IV_entries(metricIV) ;
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
if ( flag == 1 ) {
for ( front = 0 ; front < nfront ; front++ ) {
nv = nodwghts[front] ;
nb = bndwghts[front] ;
metric[front] = (nv*(nv+1))/2 + nv*nb ;
}
} else if ( flag == 2 ) {
for ( front = 0 ; front < nfront ; front++ ) {
nv = nodwghts[front] ;
nb = bndwghts[front] ;
metric[front] = nv*nv + 2*nv*nb ;
}
}
return(metricIV) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
return a DV object with the number
of factor operations in each front.
type -- type of entries,
SPOOLES_REAL or SPOOLES_COMPLEX
symflag -- symmetryflag,
SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 96jun23, cca
---------------------------------------------------------------
*/
DV *
ETree_nopsMetric (
ETree *etree,
int type,
int symflag
) {
DV *metricDV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->nfront <= 0 || etree->nvtx <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_nopsMetric(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
metricDV = ETree_forwardOps(etree, type, symflag) ;
return(metricDV) ; }
/*--------------------------------------------------------------------*/
------------------------------*/
/*
------------------------------------
return an IV object with the weights
of the vertices in each front.
created -- 96jun23, cca
------------------------------------
*/
IV *
ETree_nvtxMetric (
ETree *etree
) {
IV *metricIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || etree->nfront <= 0 || etree->nvtx <= 0 ) {
fprintf(stderETree/src/ms.c 0100644 0002055 0007177 00000031153 06536044730 0014461 0 ustar 00cleve compmath 0000040 0000006 /* ms.c */
#include "../ETree.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
------------------------------------------------
returns a compidsIV IV object that maps the
vertices to a domain (compids[v] > 1)
or to the multisector (compids[v] = 0).
the vertices in the multisector is specified
by their depth of their front in the tree.
created -- 96jan04, cca
------------------------------------------------
*/
IV *
ETree_msByDepth (
ETree *etree,
int depth
) {
int front, nfront, nvtx, v ;
int *compids, *dmetric, *vtxToFront ;
IV *compidsIV, *vmetricIV, *dmetricIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0
|| depth <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_msByDepth(%p,%d)"
"\n bad input\n", etree, depth) ;
exit(-1) ;
}
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
/*
--------------------
get the depth metric
--------------------
*/
vmetricIV = IV_new() ;
IV_init(vmetricIV, nfront, NULL) ;
IV_fill(vmetricIV, 1) ;
dmetricIV = Tree_setDepthImetric(etree->tree, vmetricIV) ;
dmetric = IV_entries(dmetricIV) ;
#if MYDEBUG > 0
{ int ierr ;
fprintf(stdout, "\n ETree_msByDepth") ;
fprintf(stdout, "\n vmetric") ;
IV_writeForHumanEye(vmetricIV, stdout) ;
fprintf(stdout, "\n dmetric") ;
IV_writeForHumanEye(dmetricIV, stdout) ;
}
#endif
IV_free(vmetricIV) ;
/*
--------------------------------------------------
fill the IV object with the ids in the multisector
--------------------------------------------------
*/
compidsIV = IV_new() ;
IV_init(compidsIV, nvtx, NULL) ;
compids = IV_entries(compidsIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
front = vtxToFront[v] ;
if ( dmetric[front] <= depth ) {
compids[v] = 0 ;
} else {
compids[v] = 1 ;
}
}
IV_free(dmetricIV) ;
return(compidsIV) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
construct a multisector based on vertices found in a subtree.
created -- 96jan04, cca
----------------------------------------------------------------
*/
IV *
ETree_msByNvtxCutoff (
ETree *etree,
double cutoff
) {
int front, nfront, nvtx, v ;
int *compids, *tmetric, *vtxToFront ;
IV *compidsIV, *tmetricIV, *vmetricIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_msByCutoff(%p,%f)"
"\n bad input\n", etree, cutoff) ;
exit(-1) ;
}
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
/*
----------------------
get the subtree metric
----------------------
*/
vmetricIV = ETree_nvtxMetric(etree) ;
tmetricIV = Tree_setSubtreeImetric(etree->tree, vmetricIV) ;
#if MYDEBUG > 0
fprintf(stdout, "\n ETree_msByNvtxCutoff") ;
fprintf(stdout, "\n vmetric") ;
IV_writeForHumanEye(vmetricIV, stdout) ;
fprintf(stdout, "\n tmetric") ;
IV_writeForHumanEye(tmetricIV, stdout) ;
fflush(stdout) ;
#endif
IV_free(vmetricIV) ;
cutoff = cutoff * IV_max(tmetricIV) ;
/*
--------------------------------------------------
fill the IV object with the ids in the multisector
--------------------------------------------------
*/
compidsIV = IV_new() ;
IV_init(compidsIV, nvtx, NULL) ;
compids = IV_entries(compidsIV) ;
tmetric = IV_entries(tmetricIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
front = vtxToFront[v] ;
if ( tmetric[front] >= cutoff ) {
compids[v] = 0 ;
} else {
compids[v] = 1 ;
}
}
IV_free(tmetricIV) ;
return(compidsIV) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
construct a multisector based on the number
of factor entries found in a subtree.
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 96jan04, cca
--------------------------------------------------
*/
IV *
ETree_msByNentCutoff (
ETree *etree,
double cutoff,
int symflag
) {
int front, nfront, nvtx, v ;
int *compids, *tmetric, *vtxToFront ;
IV *compidsIV, *tmetricIV, *vmetricIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_msByCutoff(%p,%f,%d)"
"\n bad input\n", etree, cutoff, symflag) ;
exit(-1) ;
}
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
/*
----------------------
get the subtree metric
----------------------
*/
vmetricIV = ETree_nentMetric(etree, symflag) ;
tmetricIV = Tree_setSubtreeImetric(etree->tree, vmetricIV) ;
#if MYDEBUG > 0
fprintf(stdout, "\n ETree_msByNentCutoff") ;
fprintf(stdout, "\n vmetric") ;
IV_writeForHumanEye(vmetricIV, stdout) ;
fprintf(stdout, "\n tmetric") ;
IV_writeForHumanEye(tmetricIV, stdout) ;
fflush(stdout) ;
#endif
IV_free(vmetricIV) ;
cutoff = cutoff * IV_max(tmetricIV) ;
/*
--------------------------------------------------
fill the IV object with the ids in the multisector
--------------------------------------------------
*/
compidsIV = IV_new() ;
IV_init(compidsIV, nvtx, NULL) ;
compids = IV_entries(compidsIV) ;
tmetric = IV_entries(tmetricIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
front = vtxToFront[v] ;
if ( tmetric[front] >= cutoff ) {
compids[v] = 0 ;
} else {
compids[v] = 1 ;
}
}
IV_free(tmetricIV) ;
return(compidsIV) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
construct a multisector based on the number
of factor operations found in a subtree.
type -- type of entries,
SPOOLES_REAL or SPOOLES_COMPLEX
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 96jan04, cca
--------------------------------------------------
*/
IV *
ETree_msByNopsCutoff (
ETree *etree,
double cutoff,
int type,
int symflag
) {
double *tmetric ;
DV *tmetricDV, *vmetricDV ;
int front, nfront, nvtx, v ;
int *compids, *vtxToFront ;
IV *compidsIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_msByCutoff(%p,%f,%d)"
"\n bad input\n", etree, cutoff, symflag) ;
exit(-1) ;
}
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
/*
----------------------
get the subtree metric
----------------------
*/
vmetricDV = ETree_nopsMetric(etree, type, symflag) ;
tmetricDV = Tree_setSubtreeDmetric(etree->tree, vmetricDV) ;
#if MYDEBUG >= 0
fprintf(stdout, "\n ETree_msByNopsCutoff") ;
fprintf(stdout, "\n vmetric") ;
DV_writeForHumanEye(vmetricDV, stdout) ;
fprintf(stdout, "\n tmetric") ;
DV_writeForHumanEye(tmetricDV, stdout) ;
fflush(stdout) ;
fprintf(stdout, "\n max(tmetricDV) = %.0f, sum(vmetricDV) = %.0f",
DV_max(tmetricDV), DV_sum(vmetricDV)) ;
fprintf(stdout, "\n cutoff = %.0f", cutoff * DV_max(tmetricDV)) ;
#endif
cutoff = cutoff * DV_max(tmetricDV) ;
/*
--------------------------------------------------
fill the IV object with the ids in the multisector
--------------------------------------------------
*/
compidsIV = IV_new() ;
IV_init(compidsIV, nvtx, NULL) ;
compids = IV_entries(compidsIV) ;
tmetric = DV_entries(tmetricDV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
front = vtxToFront[v] ;
if ( tmetric[front] >= cutoff ) {
compids[v] = 0 ;
} else {
compids[v] = 1 ;
}
}
{
double domops, schurops ;
double *vmetric ;
int J ;
vmetric = DV_entries(vmetricDV) ;
domops = schurops = 0.0 ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( tmetric[J] >= cutoff ) {
schurops += vmetric[J] ;
} else {
domops += vmetric[J] ;
}
}
fprintf(stdout, "\n domops = %.0f, schurops = %.0f, total = %.0f",
domops, schurops, domops + schurops) ;
}
/*
------------------------
free the working storage
------------------------
*/
DV_free(vmetricDV) ;
DV_free(tmetricDV) ;
return(compidsIV) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
purpose -- given a front tree and a multisector map vector,
fill the map vector with domain ids and the three statistics
arrays with domain and schur complement statistics.
frontETree -- front tree object, unchanged on output
msIV -- map from fronts to domains or schur complement
on input, ms[v] = 0 --> v is in the schur complement
ms[v] = 1 --> v is not in the schur complement
on output, ms[v] = 0 --> v is in the schur complement
ms[v] != 0 --> v is in domain ms[v]
on output
nvtxIV -- nvtx[ireg] = # of dof in region ireg
nzfIV -- nzf[ireg] = # of factor entries in region ireg
opsIV -- ops[ireg] = # of factor ops in region ireg
type -- type of entries, SPOOLES_REAL or SPOOLES_COMPLEX
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 98jan30, cca
--------------------------------------------------------------
*/
void
ETree_msStats (
ETree *frontETree,
IV *msIV,
IV *nvtxIV,
IV *nzfIV,
DV *opsDV,
int type,
int symflag
) {
double *opsreg, *opsvec ;
DV *opsvecDV ;
int J, K, ndom, nfront, nvtx, reg, v ;
int *map, *ms, *nodwghts, *nvtxreg,
*nzfreg, *nzfvec, *par, *vtxToFront ;
IV *nzfvecIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( frontETree == NULL || msIV == NULL || nvtxIV == NULL
|| nzfIV == NULL || opsDV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_msStats()"
"\n frontETree = %p, msIV = %p, nvtxIV = %p"
"\n nzfIV = %p, opsDV = %p, symflag = %d\n",
frontETree, msIV, nvtxIV, nzfIV, opsDV, symflag) ;
exit(-1) ;
}
nfront = ETree_nfront(frontETree) ;
nvtx = ETree_nvtx(frontETree) ;
tree = ETree_tree(frontETree) ;
par = ETree_par(frontETree) ;
vtxToFront = ETree_vtxToFront(frontETree) ;
ms = IV_entries(msIV) ;
/*
----------------------------------------
if J is not in the schur complement then
fill ms[J] with its domain id
endif
----------------------------------------
*/
map = IVinit(nfront, -1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
J = vtxToFront[v] ;
map[J] = ms[v] ;
/*
fprintf(stdout, "\n vertex %d, front %d, map %d", v, J, map[J]) ;
*/
}
ndom = 0 ;
for ( J = Tree_preOTfirst(tree) ;
J != -1 ;
J = Tree_preOTnext(tree, J) ) {
/*
fprintf(stdout, "\n J = %d", J) ;
*/
if ( map[J] != 0 ) {
if ( (K = par[J]) != -1 ) {
if ( map[K] == 0 ) {
map[J] = ++ndom ;
} else {
map[J] = map[K] ;
}
} else {
map[J] = ++ndom ;
}
/*
fprintf(stdout, ", in domain %d", map[J]) ;
} else {
fprintf(stdout, ", schur complement front") ;
*/
}
}
for ( v = 0 ; v < nvtx ; v++ ) {
J = vtxToFront[v] ;
ms[v] = map[J] ;
/*
fprintf(stdout, "\n vertex %d, front %d, region %d", v, J, map[J]) ;
*/
}
/*
--------------------------------------------------
set sizes of the nvtxIV, nzfIV and opsV vectors
to hold the domain and schur complement statistics
--------------------------------------------------
*/
IV_setSize(nvtxIV, ndom+1) ;
IV_setSize(nzfIV, ndom+1) ;
DV_setSize(opsDV, ndom+1) ;
nvtxreg = IV_entries(nvtxIV) ;
nzfreg = IV_entries(nzfIV) ;
opsreg = DV_entries(opsDV) ;
IVzero(ndom+1, nvtxreg) ;
IVzero(ndom+1, nzfreg) ;
DVzero(ndom+1, opsreg) ;
/*
---------------------------------
get the statistics for the fronts
---------------------------------
*/
nodwghts = ETree_nodwghts(frontETree) ;
nzfvecIV = ETree_factorEntriesIV(frontETree, symflag) ;
nzfvec = IV_entries(nzfvecIV) ;
opsvecDV = ETree_forwardOps(frontETree, type, symflag) ;
opsvec = DV_entries(opsvecDV) ;
/*
----------------------------------
fill the region statistics vectors
----------------------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
reg = map[J] ;
nvtxreg[reg] += nodwghts[J] ;
nzfreg[reg] += nzfvec[J] ;
opsreg[reg] += opsvec[J] ;
}
/*
------------------------
free the working storage
------------------------
*/
IV_free(nzfvecIV) ;
DV_free(opsvecDV) ;
IVfree(map) ;
return ; }
/*--------------------------------------------------------------------*/
= 0 ;
} else {
compids[v] = 1 ;
}
}
IV_free(tmetricIV) ;
return(compidsIV) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
construct a multisector based on the number
of factor entries found in a subtree.
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC
SPOOLES_HERMITIAN or SPOOLES_NONETree/src/permute.c 0100644 0002055 0007177 00000015440 06534106074 0015522 0 ustar 00cleve compmath 0000040 0000006 /* permute.c */
#include "../ETree.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
fill the new-to-old permutation vector for the fronts
created -- 96jun23, cca
-----------------------------------------------------
*/
IV *
ETree_newToOldFrontPerm (
ETree *etree
) {
int nfront, nvtx ;
IV *newToOldIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_newToOldFrontPerm(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
newToOldIV = IV_new() ;
IV_init(newToOldIV, nfront, NULL) ;
/*
------------------------------------------------------
fill the permutation vector by calling the Tree method
------------------------------------------------------
*/
Tree_fillNewToOldPerm(etree->tree, IV_entries(newToOldIV)) ;
return(newToOldIV) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
fill the old-to-new permutation vector for the fronts
created -- 96jun23, cca
-----------------------------------------------------
*/
IV *
ETree_oldToNewFrontPerm (
ETree *etree
) {
int nfront, nvtx ;
IV *oldToNewIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_oldToNewFrontPerm(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
oldToNewIV = IV_new() ;
IV_init(oldToNewIV, nfront, NULL) ;
/*
------------------------------------------------------
fill the permutation vector by calling the Tree method
------------------------------------------------------
*/
Tree_fillOldToNewPerm(etree->tree, IV_entries(oldToNewIV)) ;
return(oldToNewIV) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
fill the new-to-old permutation vector for the vertices
created -- 96oct05, cca
-------------------------------------------------------
*/
IV *
ETree_newToOldVtxPerm (
ETree *etree
) {
int count, front, nfront, nvtx, v ;
int *head, *link, *newToOld, *vtxToFront ;
IV *newToOldVtxIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_newToOldVtxPerm(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
/*
----------------------------------------------------
allocate the old-to-new vertex permutation IV object
----------------------------------------------------
*/
newToOldVtxIV = IV_new() ;
IV_init(newToOldVtxIV, nvtx, NULL) ;
newToOld = IV_entries(newToOldVtxIV) ;
/*
-------------------------------------------------------
get the head/link structure for the vertices and fronts
-------------------------------------------------------
*/
head = IVinit(nfront, -1) ;
link = IVinit(nvtx, -1) ;
for ( v = nvtx - 1 ; v >= 0 ; v-- ) {
front = vtxToFront[v] ;
link[v] = head[front] ;
head[front] = v ;
}
/*
----------------------------------------------
loop over the fronts in a post-order traversal
----------------------------------------------
*/
count = 0 ;
for ( front = Tree_postOTfirst(etree->tree) ;
front != -1 ;
front = Tree_postOTnext(etree->tree, front) ) {
for ( v = head[front] ; v != -1 ; v = link[v] ) {
newToOld[count++] = v ;
}
}
IVfree(head) ;
IVfree(link) ;
return(newToOldVtxIV) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
fill the old-to-new permutation vector for the vertices
created -- 96jun23, cca
-------------------------------------------------------
*/
IV *
ETree_oldToNewVtxPerm (
ETree *etree
) {
int count, front, nfront, nvtx, v ;
int *head, *link, *oldToNew, *vtxToFront ;
IV *oldToNewVtxIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_oldToNewVtxPerm(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
/*
----------------------------------------------------
allocate the old-to-new vertex permutation IV object
----------------------------------------------------
*/
oldToNewVtxIV = IV_new() ;
IV_init(oldToNewVtxIV, nvtx, NULL) ;
oldToNew = IV_entries(oldToNewVtxIV) ;
/*
-------------------------------------------------------
get the head/link structure for the vertices and fronts
-------------------------------------------------------
*/
head = IVinit(nfront, -1) ;
link = IVinit(nvtx, -1) ;
for ( v = nvtx - 1 ; v >= 0 ; v-- ) {
front = vtxToFront[v] ;
link[v] = head[front] ;
head[front] = v ;
}
/*
----------------------------------------------
loop over the fronts in a post-order traversal
----------------------------------------------
*/
count = 0 ;
for ( front = Tree_postOTfirst(etree->tree) ;
front != -1 ;
front = Tree_postOTnext(etree->tree, front) ) {
for ( v = head[front] ; v != -1 ; v = link[v] ) {
oldToNew[v] = count++ ;
}
}
IVfree(head) ;
IVfree(link) ;
return(oldToNewVtxIV) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
purpose -- permute the vertices,
overwrite entries in the vertex-to-front map
created -- 96oct03, cca
-------------------------------------------------------
*/
void
ETree_permuteVertices (
ETree *etree,
IV *vtxOldToNewIV
) {
int nvtx, v ;
int *oldToNew, *temp, *vtxToFront ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || vtxOldToNewIV == NULL
|| (nvtx = etree->nvtx) <= 0 || nvtx != IV_size(vtxOldToNewIV) ) {
fprintf(stderr, "\n fatal error in ETree_permuteVertices(%p,%p)"
"\n bad input\n", etree, vtxOldToNewIV) ;
if ( etree != NULL && vtxOldToNewIV != NULL ) {
fprintf(stderr,
"\n etree->nvtx = %d, IV_size(vtxOldToNewIV) = %d\n",
etree->nvtx, IV_size(vtxOldToNewIV)) ;
}
exit(-1) ;
}
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
oldToNew = IV_entries(vtxOldToNewIV) ;
temp = IVinit(nvtx, -1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
temp[oldToNew[v]] = vtxToFront[v] ;
}
IVcopy(nvtx, vtxToFront, temp) ;
IVfree(temp) ;
return ; }
/*--------------------------------------------------------------------*/
wFrontPerm (
ETree *etree
) {
int nfront, nvtx ;
IV *oldToNewIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <=ETree/src/semi.c 0100644 0002055 0007177 00000014226 06543036443 0015001 0 ustar 00cleve compmath 0000040 0000006 /* semi.c */
#include "../ETree.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
purpose --
to find the optimal domain/schur complement partition
for a semi-implict factorization.
the gain of a subtree sbt(J) is equal to
|L_{bnd{J},sbt{J}}| - |A_{bnd{J},sbt{J}}|
- alpha *|L_{sbt{J},sbt{J}}|
when alpha = 0 we minimize active storage
when alpha = 1 we minimize solve operations
*ptotalgain is filled with the total gain
the return value is compidsIV,
compids[J] = 0 --> J is in the schur complement
compids[J] != 0 --> J is in domain compids[J]
created -- 98jun20, cca
-----------------------------------------------------
*/
IV *
ETree_optPart (
ETree *etree,
Graph *graph,
IVL *symbfacIVL,
double alpha,
int *ptotalgain,
int msglvl,
FILE *msgFile
) {
int ii, I, J, K, nfront, nvtx, sizeJ, v, vsize, w, wght, wghtJ ;
int *adjJ, *colCountsA, *colCountsL, *colSbtCountsA, *colSbtCountsL,
*diagCountsL, *diagSbtCountsL, *fch, *gain, *nodwghts,
*rowCountsA, *rowCountsL, *sib, *vadj, *vtxToFront, *vwghts ;
IV *compidsIV, *gainIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || graph == NULL || symbfacIVL == NULL
|| (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr, "\n fatal error in ETree_optPart()"
"\n bad input\n") ;
exit(-1) ;
}
nfront = etree->nfront ;
nodwghts = ETree_nodwghts(etree) ;
vtxToFront = ETree_vtxToFront(etree) ;
tree = etree->tree ;
fch = tree->fch ;
sib = tree->sib ;
if ( (nvtx = graph->nvtx) != etree->nvtx ) {
fprintf(stderr, "\n fatal error in ETree_optPart()"
"\n etree->nvtx = %d, graph->nvtx = %d\n",
etree->nvtx, graph->nvtx) ;
exit(-1) ;
}
vwghts = graph->vwghts ;
/*
---------------------------------------
compute the # of entries in the
offdiagonal front rows and columns of A
---------------------------------------
*/
rowCountsA = IVinit(nfront, 0) ;
colCountsA = IVinit(nfront, 0) ;
for ( v = 0 ; v < nvtx ; v++ ) {
J = vtxToFront[v] ;
Graph_adjAndSize(graph, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( (K = vtxToFront[w]) > J ) {
wght = (vwghts == NULL) ? 1 : vwghts[v]*vwghts[w] ;
colCountsA[J] += wght ;
rowCountsA[K] += wght ;
}
}
}
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n rowCountsA") ;
IVfprintf(msgFile, nfront, rowCountsA) ;
fprintf(msgFile, "\n\n colCountsA") ;
IVfprintf(msgFile, nfront, colCountsA) ;
}
/*
---------------------------------------------------------
compute colSbtCountsA[J] = # entries in A_{bnd{J},sbt{J}}
---------------------------------------------------------
*/
colSbtCountsA = IVinit(nfront, 0) ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
colSbtCountsA[J] = colCountsA[J] - rowCountsA[J] ;
for ( I = fch[J] ; I != -1 ; I = sib[I] ) {
colSbtCountsA[J] += colSbtCountsA[I] ;
}
}
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n colSbtCountsA") ;
IVfprintf(msgFile, nfront, colSbtCountsA) ;
}
/*
---------------------------------------
compute the # of entries in the
offdiagonal front rows and columns of L
---------------------------------------
*/
rowCountsL = IVinit(nfront, 0) ;
colCountsL = IVinit(nfront, 0) ;
diagCountsL = IVinit(nfront, 0) ;
for ( J = 0 ; J < nfront ; J++ ) {
IVL_listAndSize(symbfacIVL, J, &sizeJ, &adjJ) ;
wghtJ = nodwghts[J] ;
diagCountsL[J] = (wghtJ*(wghtJ+1))/2 ;
for ( ii = 0 ; ii < sizeJ ; ii++ ) {
v = adjJ[ii] ;
if ( (K = vtxToFront[J]) > J ) {
wght = (vwghts == NULL) ? 1 : wghtJ*vwghts[v] ;
colCountsL[J] += wght ;
rowCountsL[K] += wght ;
}
}
}
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n rowCountsL") ;
IVfprintf(msgFile, nfront, rowCountsL) ;
fprintf(msgFile, "\n\n colCountsL") ;
IVfprintf(msgFile, nfront, colCountsL) ;
fprintf(msgFile, "\n\n diagCountsL") ;
IVfprintf(msgFile, nfront, diagCountsL) ;
}
/*
---------------------------------------------------------
compute colSbtCountsL[J] = # entries in L_{bnd{J},sbt{J}}
compute diagSbtCountsL[J] = # entries in L_{sbt{J},sbt{J}}
---------------------------------------------------------
*/
colSbtCountsL = IVinit(nfront, 0) ;
diagSbtCountsL = IVinit(nfront, 0) ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
colSbtCountsL[J] = colCountsL[J] - rowCountsL[J] ;
diagSbtCountsL[J] = rowCountsL[J] ;
for ( I = fch[J] ; I != -1 ; I = sib[I] ) {
colSbtCountsL[J] += colSbtCountsL[I] ;
diagSbtCountsL[J] += diagSbtCountsL[I] ;
}
}
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n colSbtCountsL") ;
IVfprintf(msgFile, nfront, colSbtCountsL) ;
fprintf(msgFile, "\n\n diagSbtCountsL") ;
IVfprintf(msgFile, nfront, diagSbtCountsL) ;
}
/*
-----------------------
compute the gain vector
-----------------------
*/
gainIV = IV_new() ;
IV_init(gainIV, nfront, NULL) ;
gain = IV_entries(gainIV) ;
for ( J = 0 ; J < nfront ; J++ ) {
gain[J] = colSbtCountsL[J] - colSbtCountsA[J]
- alpha*diagCountsL[J] ;
}
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n gain") ;
IVfprintf(msgFile, nfront, gain) ;
}
/*
----------------------------------------------
get the component ids of the optimal partition
----------------------------------------------
*/
compidsIV = Tree_maximizeGainIV(tree, gainIV, ptotalgain,
msglvl, msgFile) ;
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n total gain = %d", *ptotalgain) ;
fprintf(msgFile, "\n\n compidsIV") ;
IV_writeForHumanEye(compidsIV, msgFile) ;
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(colCountsA) ;
IVfree(rowCountsA) ;
IVfree(colSbtCountsA) ;
IVfree(colCountsL) ;
IVfree(rowCountsL) ;
IVfree(diagCountsL) ;
IVfree(colSbtCountsL) ;
IVfree(diagSbtCountsL) ;
IV_free(gainIV) ;
return(compidsIV) ; }
/*--------------------------------------------------------------------*/
ETree/src/storage.c 0100644 0002055 0007177 00000034301 06636735131 0015507 0 ustar 00cleve compmath 0000040 0000006 /* storage.c */
#include "../ETree.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
purpose -- fill dvec[J] with the active storage to eliminate J
using the multifrontal method
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC,
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 97may21, cca
---------------------------------------------------------------
*/
void
ETree_MFstackProfile (
ETree *etree,
int symflag,
double dvec[]
) {
int I, J, nDJ, nUI, nUJ, stack ;
int *bndwghts, *fch, *nodwghts, *sib ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || dvec == NULL ) {
fprintf(stderr, "\n fatal error in ETree_MFstackProfile(%p,%p)"
"\n bad input\n", etree, dvec) ;
exit(-1) ;
}
tree = ETree_tree(etree) ;
nodwghts = ETree_nodwghts(etree) ;
bndwghts = ETree_bndwghts(etree) ;
fch = ETree_fch(etree) ;
sib = ETree_sib(etree) ;
/*
---------------------------------------------
loop over the nodes in a post-order traversal
---------------------------------------------
*/
stack = 0 ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
nDJ = nodwghts[J] ;
nUJ = bndwghts[J] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n working on front %d, nD = %d, nU = %d, stack = %d",
J, nDJ, nUJ, stack) ;
#endif
if ( (I = fch[J]) != -1 ) {
/*
--------------------------------
remove last child from the stack
--------------------------------
*/
while ( sib[I] != -1 ) {
I = sib[I] ;
}
nUI = bndwghts[I] ;
if ( symflag == SPOOLES_SYMMETRIC
|| symflag == SPOOLES_HERMITIAN ) {
stack -= (nUI*(nUI+1))/2 ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
stack -= nUI*nUI ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n removing last child %d, stack = %d", I, stack) ;
#endif
}
/*
---------------------------------
add frontal matrix for J to stack
and store as the storage for J
---------------------------------
*/
dvec[J] = stack + (nDJ + nUJ)*(nDJ + nUJ) ;
if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) {
dvec[J] = stack + ((nDJ + nUJ)*(nDJ + nUJ+1))/2 ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
dvec[J] = stack + (nDJ + nUJ)*(nDJ + nUJ) ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n working storage = %.0f", dvec[J]) ;
#endif
if ( (I = fch[J]) != -1 ) {
/*
------------------------------------
remove other children from the stack
------------------------------------
*/
while ( sib[I] != -1 ) {
nUI = bndwghts[I] ;
if ( symflag == SPOOLES_SYMMETRIC
|| symflag == SPOOLES_HERMITIAN ) {
stack -= (nUI*(nUI+1))/2 ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
stack -= nUI*nUI ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n removing child %d, stack = %d", I, stack) ;
#endif
I = sib[I] ;
}
}
/*
--------------------------------
add update matrix for J to stack
--------------------------------
*/
if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) {
stack += (nUJ*(nUJ+1))/2 ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
stack += nUJ*nUJ ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n adding update matrix, stack = %d", stack) ;
#endif
}
#if MYDEBUG >= 0
fprintf(stdout, "\n MF: final stack = %d", stack) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
purpose -- fill dvec[J] with the active storage to eliminate J
using the left-looking general sparse method
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC,
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 97may21, cca
---------------------------------------------------------------
*/
void
ETree_GSstorageProfile (
ETree *etree,
int symflag,
IVL *symbfacIVL,
int *vwghts,
double dvec[]
) {
int count, ii, I, J, K, nDJ, nfront, nUJ, sizeI, sizeJ, storage, v ;
int *bndwghts, *head, *indI, *indJ,
*link, *nodwghts, *offsets, *vtxToFront ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || symbfacIVL == NULL || dvec == NULL ) {
fprintf(stderr,
"\n fatal error in ETree_GSstorageProfile(%p,%p,%p,%p)"
"\n bad input\n", etree, symbfacIVL, vwghts, dvec) ;
exit(-1) ;
}
tree = ETree_tree(etree) ;
nodwghts = ETree_nodwghts(etree) ;
bndwghts = ETree_bndwghts(etree) ;
vtxToFront = ETree_vtxToFront(etree) ;
nfront = ETree_nfront(etree) ;
head = IVinit(nfront, -1) ;
link = IVinit(nfront, -1) ;
offsets = IVinit(nfront, 0) ;
/*
---------------------------------------------
loop over the nodes in a post-order traversal
---------------------------------------------
*/
storage = 0 ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
nDJ = nodwghts[J] ;
nUJ = bndwghts[J] ;
if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) {
storage += (nDJ*(nDJ + 1))/2 + nDJ*nUJ ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
storage += nDJ*nDJ + 2*nDJ*nUJ ;
}
dvec[J] = storage ;
#if MYDEBUG > 0
fprintf(stdout,
"\n working on front %d, nD = %d, nU = %d, storage = %d",
J, nDJ, nUJ, storage) ;
#endif
/*
-----------------------------
loop over the updating fronts
-----------------------------
*/
while ( (I = head[J]) != -1 ) {
head[J] = link[I] ;
IVL_listAndSize(symbfacIVL, I, &sizeI, &indI) ;
#if MYDEBUG > 0
fprintf(stdout,
"\n updating front %d, offset = %d, sizeI = %d",
I, offsets[I], sizeI) ;
IVfprintf(stdout, sizeI, indI) ;
#endif
for ( ii = offsets[I], count = 0, K = -1 ; ii < sizeI ; ii++ ) {
v = indI[ii] ;
#if MYDEBUG > 0
fprintf(stdout, "\n ii = %d, v = %d, K = %d",
ii, v, vtxToFront[v]) ;
fflush(stdout) ;
#endif
K = vtxToFront[v] ;
if ( K < 0 || K >= nfront ) {
fprintf(stderr, "\n\n fatal error"
"\n ii = %d, v = %d, K = %d", ii, v, K) ;
exit(-1) ;
}
if ( (K = vtxToFront[v]) != J ) {
#if MYDEBUG > 0
fprintf(stdout, "\n linking to next ancestor %d", K) ;
#endif
link[I] = head[K] ;
head[K] = I ;
offsets[I] = ii ;
break ;
}
count += (vwghts == NULL) ? 1 : vwghts[v] ;
#if MYDEBUG > 0
fprintf(stdout, "\n count = %d", count) ;
fflush(stdout) ;
#endif
}
if ( symflag == SPOOLES_SYMMETRIC
|| symflag == SPOOLES_HERMITIAN ) {
storage -= count*nodwghts[I] ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
storage -= 2*count*nodwghts[I] ;
}
}
if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) {
storage -= (nDJ*(nDJ+1))/2 ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
storage -= nDJ*nDJ ;
}
if ( nUJ > 0 ) {
IVL_listAndSize(symbfacIVL, J, &sizeJ, &indJ) ;
for ( ii = 0 ; ii < sizeJ ; ii++ ) {
v = indJ[ii] ;
if ( (K = vtxToFront[v]) != J ) {
break ;
}
}
offsets[J] = ii ;
#if MYDEBUG > 0
fprintf(stdout, "\n linking to next ancestor %d", K) ;
#endif
IVL_listAndSize(symbfacIVL, J, &sizeJ, &indJ) ;
link[J] = head[K] ;
head[K] = J ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n at end of step %d, storage = %d",
J, storage) ;
#endif
}
#if MYDEBUG >= 0
fprintf(stdout, "\n GS: final storage = %d", storage) ;
#endif
IVfree(head) ;
IVfree(link) ;
IVfree(offsets) ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
purpose -- fill dvec[J] with the active storage to eliminate J
using the right-looking general sparse method
symflag -- symmetry flag, one of SPOOLES_SYMMETRIC,
SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
created -- 98dec19, cca
---------------------------------------------------------------
*/
void
ETree_FSstorageProfile (
ETree *etree,
int symflag,
IVL *symbfacIVL,
double dvec[]
) {
char *incore ;
int ii, J, K, nDJ, nfront, nUJ, sizeJ, storage ;
int *bndwghts, *indJ, *mark, *nodwghts, *stor, *vtxToFront ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || symbfacIVL == NULL || dvec == NULL ) {
fprintf(stderr,
"\n fatal error in ETree_FSstorageProfile(%p,%p,%p)"
"\n bad input\n", etree, symbfacIVL, dvec) ;
exit(-1) ;
}
tree = ETree_tree(etree) ;
nodwghts = ETree_nodwghts(etree) ;
bndwghts = ETree_bndwghts(etree) ;
vtxToFront = ETree_vtxToFront(etree) ;
nfront = ETree_nfront(etree) ;
incore = CVinit(nfront, 'F') ;
stor = IVinit(nfront, 0) ;
mark = IVinit(nfront, -1) ;
/*
--------------------------------------------
compute the storage for each front's chevron
--------------------------------------------
*/
if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) {
for ( J = 0 ; J < nfront ; J++ ) {
nDJ = nodwghts[J] ;
nUJ = bndwghts[J] ;
stor[J] = (nDJ*(nDJ+1))/2 + nDJ*nUJ ;
}
} else {
for ( J = 0 ; J < nfront ; J++ ) {
nDJ = nodwghts[J] ;
nUJ = bndwghts[J] ;
stor[J] = nDJ*nDJ + 2*nDJ*nUJ ;
}
}
/*
---------------------------------------------
loop over the nodes in a post-order traversal
---------------------------------------------
*/
storage = 0 ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
if ( incore[J] == 'F' ) {
storage += stor[J] ;
incore[J] = 'T' ;
}
IVL_listAndSize(symbfacIVL, J, &sizeJ, &indJ) ;
mark[J] = J ;
for ( ii = 0 ; ii < sizeJ ; ii++ ) {
K = vtxToFront[indJ[ii]] ;
if ( mark[K] != J ) {
mark[K] = J ;
if ( incore[K] == 'F' ) {
storage += stor[K] ;
incore[K] = 'T' ;
}
}
}
dvec[J] = storage ;
storage -= stor[J] ;
}
IVfree(mark) ;
IVfree(stor) ;
CVfree(incore) ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
purpose -- fill dvec[J] with the stack storage to solve for J
in a forward solve
created -- 97nov30, cca
---------------------------------------------------------------
*/
void
ETree_forwSolveProfile (
ETree *etree,
double dvec[]
) {
int I, J, maxstack, nDJ, nfront, nUJ, stack ;
int *bndwghts, *fch, *nodwghts, *sib ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || dvec == NULL ) {
fprintf(stderr,
"\n fatal error in ETree_forwSolveProfile(%p,%p)"
"\n bad input\n", etree, dvec) ;
exit(-1) ;
}
tree = ETree_tree(etree) ;
nodwghts = ETree_nodwghts(etree) ;
bndwghts = ETree_bndwghts(etree) ;
nfront = ETree_nfront(etree) ;
fch = ETree_fch(etree) ;
sib = ETree_sib(etree) ;
/*
---------------------------------------------
loop over the nodes in a post-order traversal
---------------------------------------------
*/
maxstack = stack = 0 ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
nDJ = nodwghts[J] ;
nUJ = bndwghts[J] ;
stack += nDJ + nUJ ;
dvec[J] = stack ;
if ( maxstack < stack ) {
maxstack = stack ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n working on front %d, nD = %d, nU = %d, stack = %d",
J, nDJ, nUJ, stack) ;
#endif
for ( I = fch[J] ; I != -1 ; I = sib[I] ) {
stack -= bndwghts[I] ;
}
stack -= nDJ ;
}
#if MYDEBUG >= 0
fprintf(stdout,
"\n forward solve : final stack = %d, max stack = %d",
stack, maxstack) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
purpose -- fill dvec[J] with the stack storage to solve for J
in a backward solve
created -- 97nov30, cca
---------------------------------------------------------------
*/
void
ETree_backSolveProfile (
ETree *etree,
double dvec[]
) {
int J, K, maxstack, nDJ, nfront, nUJ, stack ;
int *bndwghts, *fch, *nodwghts, *par, *sib ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || dvec == NULL ) {
fprintf(stderr,
"\n fatal error in ETree_backSolveProfile(%p,%p)"
"\n bad input\n", etree, dvec) ;
exit(-1) ;
}
tree = ETree_tree(etree) ;
nodwghts = ETree_nodwghts(etree) ;
bndwghts = ETree_bndwghts(etree) ;
nfront = ETree_nfront(etree) ;
par = ETree_par(etree) ;
fch = ETree_fch(etree) ;
sib = ETree_sib(etree) ;
/*
---------------------------------------------
loop over the nodes in a post-order traversal
---------------------------------------------
*/
maxstack = stack = 0 ;
for ( J = Tree_preOTfirst(tree) ;
J != -1 ;
J = Tree_preOTnext(tree, J) ) {
nDJ = nodwghts[J] ;
nUJ = bndwghts[J] ;
stack += nDJ + nUJ ;
dvec[J] = stack ;
if ( maxstack < stack ) {
maxstack = stack ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n working on front %d, nD = %d, nU = %d, stack = %d",
J, nDJ, nUJ, stack) ;
#endif
if ( (K = par[J]) != -1 && sib[J] == -1 ) {
stack -= nodwghts[K] + bndwghts[K] ;
}
if ( fch[J] == -1 ) {
stack -= nodwghts[J] + bndwghts[J] ;
}
}
#if MYDEBUG >= 0
fprintf(stdout,
"\n forward solve : final stack = %d, max stack = %d",
stack, maxstack) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
symflag,
IVL *symbfacIVL,
int *vwghts,
double dvec[]
) {
int count, ii, I, J, K, nDJ, nfront, nUJ, sizeI, sizeJ, storage, v ;
int *bndwghts, *head, *indI, *indJ,
*link, *nodwghts, *offsets, *vtxToFront ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
iETree/src/transform.c 0100644 0002055 0007177 00000064262 06633021244 0016055 0 ustar 00cleve compmath 0000040 0000006 /* transform.c */
#include "../ETree.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
transform an ETree object by
(1) merging small fronts into larger fronts
using the ETree_mergeFrontsOne() method
(2) merging small fronts into larger fronts
using the ETree_mergeFrontsAll() method
(3) merging small fronts into larger fronts
using the ETree_mergeFrontsAny() method
(4) split a large front into a chain of smaller fronts
using the ETree_splitFronts() method
created -- 96jun27, cca
------------------------------------------------------
*/
ETree *
ETree_transform (
ETree *etree,
int vwghts[],
int maxzeros,
int maxfrontsize,
int seed
) {
ETree *etree2 ;
int nfront, nvtx ;
IV *nzerosIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0
|| maxfrontsize <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_transform(%p,%p,%d,%d,%d)"
"\n bad input\n", etree, vwghts, maxzeros, maxfrontsize,
seed) ;
exit(-1) ;
}
nzerosIV = IV_new();
IV_init(nzerosIV, nfront, NULL) ;
IV_fill(nzerosIV, 0) ;
/*
--------------------------
first, merge only children
--------------------------
*/
etree2 = ETree_mergeFrontsOne(etree, maxzeros, nzerosIV) ;
ETree_free(etree) ;
etree = etree2 ;
/*
--------------------------
second, merge all children
--------------------------
*/
etree2 = ETree_mergeFrontsAll(etree, maxzeros, nzerosIV) ;
ETree_free(etree) ;
etree = etree2 ;
/*
-------------------------
third, merge any children
-------------------------
*/
etree2 = ETree_mergeFrontsAny(etree, maxzeros, nzerosIV) ;
ETree_free(etree) ;
etree = etree2 ;
/*
-----------------------------------
fourth, split large interior fronts
-----------------------------------
*/
etree2 = ETree_splitFronts(etree, vwghts, maxfrontsize, seed) ;
ETree_free(etree) ;
etree = etree2 ;
/*
------------------------
free the working storage
------------------------
*/
IV_free(nzerosIV) ;
return(etree) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
transform an ETree object by
(1) merging small fronts into larger fronts
using the ETree_mergeFrontsOne() method
(2) merging small fronts into larger fronts
using the ETree_mergeFrontsAll() method
(3) split a large front into a chain of smaller fronts
using the ETree_splitFronts() method
created -- 96jun27, cca
------------------------------------------------------
*/
ETree *
ETree_transform2 (
ETree *etree,
int vwghts[],
int maxzeros,
int maxfrontsize,
int seed
) {
ETree *etree2 ;
int nfront, nvtx ;
IV *nzerosIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0
|| maxfrontsize <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_transform2(%p,%p,%d,%d,%d)"
"\n bad input\n", etree, vwghts, maxzeros, maxfrontsize,
seed) ;
exit(-1) ;
}
nzerosIV = IV_new();
IV_init(nzerosIV, nfront, NULL) ;
IV_fill(nzerosIV, 0) ;
/*
--------------------------
first, merge only children
--------------------------
*/
etree2 = ETree_mergeFrontsOne(etree, maxzeros, nzerosIV) ;
ETree_free(etree) ;
etree = etree2 ;
/*
--------------------------
second, merge all children
--------------------------
*/
etree2 = ETree_mergeFrontsAll(etree, maxzeros, nzerosIV) ;
ETree_free(etree) ;
etree = etree2 ;
/*
-----------------------------------
fourth, split large interior fronts
-----------------------------------
*/
etree2 = ETree_splitFronts(etree, vwghts, maxfrontsize, seed) ;
ETree_free(etree) ;
etree = etree2 ;
/*
------------------------
free the working storage
------------------------
*/
IV_free(nzerosIV) ;
return(etree) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
purpose -- merge the front tree allowing only chains of nodes to
merge that create at most maxzeros zero entries inside a front
return --
IV object that has the old front to new front map
created -- 98jan29, cca
--------------------------------------------------------------------
*/
ETree *
ETree_mergeFrontsOne (
ETree *etree,
int maxzeros,
IV *nzerosIV
) {
ETree *etree2 ;
int costJ, J, K, nfront, nvtx, nnew ;
int *bndwghts, *fch, *map, *nodwghts, *nzeros, *rep, *sib, *temp ;
IV *mapIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || nzerosIV == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_mergeFrontsOne(%p,%d,%p)"
"\n bad input\n", etree, maxzeros, nzerosIV) ;
exit(-1) ;
}
if ( IV_size(nzerosIV) != nfront ) {
fprintf(stderr, "\n fatal error in ETree_mergeFrontsOne(%p,%d,%p)"
"\n size(nzerosIV) = %d, nfront = %d\n",
etree, maxzeros, nzerosIV, IV_size(nzerosIV), nfront) ;
exit(-1) ;
}
nzeros = IV_entries(nzerosIV) ;
tree = etree->tree ;
fch = ETree_fch(etree) ;
sib = ETree_sib(etree) ;
/*
----------------------
set up working storage
----------------------
*/
nodwghts = IVinit(nfront, 0) ;
IVcopy(nfront, nodwghts, ETree_nodwghts(etree)) ;
bndwghts = ETree_bndwghts(etree) ;
rep = IVinit(nfront, -1) ;
IVramp(nfront, rep, 0, 1) ;
/*
------------------------------------------
perform a post-order traversal of the tree
------------------------------------------
*/
for ( K = Tree_postOTfirst(tree) ;
K != -1 ;
K = Tree_postOTnext(tree, K) ) {
#if MYDEBUG > 0
fprintf(stdout, "\n\n ##### visiting front %d", K) ;
fflush(stdout) ;
#endif
if ( (J = fch[K]) != -1 && sib[J] == -1 ) {
costJ = nodwghts[J]*(nodwghts[K] + bndwghts[K] - bndwghts[J]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n nzeros[%d] = %d, costJ = %d",
J, nzeros[J], costJ) ;
fflush(stdout) ;
#endif
if ( nzeros[J] + costJ <= maxzeros ) {
rep[J] = K ;
nodwghts[K] += nodwghts[J] ;
nzeros[K] = nzeros[J] + costJ ;
#if MYDEBUG > 0
fprintf(stdout,
"\n merging %d into %d, |%d| = %d, nzeros = %d",
J, K, K, nodwghts[K], nzeros[K]) ;
fflush(stdout) ;
#endif
}
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n whoa, finished") ;
fflush(stdout) ;
#endif
/*
-------------------------------------------------
take the map from fronts to representative fronts
and make the map from old fronts to new fronts
-------------------------------------------------
*/
mapIV = IV_new() ;
IV_init(mapIV, nfront, NULL) ;
map = IV_entries(mapIV) ;
for ( J = 0, nnew = 0 ; J < nfront ; J++ ) {
if ( rep[J] == J ) {
map[J] = nnew++ ;
} else {
K = J ;
while ( rep[K] != K ) {
K = rep[K] ;
}
rep[J] = K ;
}
}
for ( J = 0 ; J < nfront ; J++ ) {
if ( (K = rep[J]) != J ) {
map[J] = map[K] ;
}
}
/*
-------------------------------
get the compressed ETree object
-------------------------------
*/
etree2 = ETree_compress(etree, mapIV) ;
/*
-------------------------
remap the nzeros[] vector
-------------------------
*/
temp = IVinit(nfront, NULL) ;
IVcopy(nfront, temp, nzeros) ;
IV_setSize(nzerosIV, nnew) ;
nzeros = IV_entries(nzerosIV) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( rep[J] == J ) {
nzeros[map[J]] = temp[J] ;
}
}
IVfree(temp) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(nodwghts) ;
IVfree(rep) ;
IV_free(mapIV) ;
return(etree2) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
purpose -- merge the front tree allowing a parent
to absorb all children when that creates
at most maxzeros zero entries inside a front
return --
IV object that has the old front to new front map
created -- 98jan29, cca
-------------------------------------------------------
*/
ETree *
ETree_mergeFrontsAll (
ETree *etree,
int maxzeros,
IV *nzerosIV
) {
ETree *etree2 ;
int cost, J, Jall, K, KandBnd, nfront, nvtx, nnew ;
int *bndwghts, *fch, *map, *nodwghts, *nzeros, *rep, *sib, *temp ;
IV *mapIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || nzerosIV == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_mergeFrontsAll(%p,%d,%p)"
"\n bad input\n", etree, maxzeros, nzerosIV) ;
if ( etree != NULL ) {
fprintf(stderr, "\n nfront = %d, nvtx = %d",
etree->nfront, etree->nvtx) ;
}
exit(-1) ;
}
if ( IV_size(nzerosIV) != nfront ) {
fprintf(stderr, "\n fatal error in ETree_mergeFrontsAll(%p,%d,%p)"
"\n size(nzerosIV) = %d, nfront = %d\n",
etree, maxzeros, nzerosIV, IV_size(nzerosIV), nfront) ;
exit(-1) ;
}
nzeros = IV_entries(nzerosIV) ;
/*
----------------------
set up working storage
----------------------
*/
tree = etree->tree ;
fch = ETree_fch(etree) ;
sib = ETree_sib(etree) ;
nodwghts = IVinit(nfront, 0) ;
IVcopy(nfront, nodwghts, ETree_nodwghts(etree)) ;
bndwghts = ETree_bndwghts(etree) ;
rep = IVinit(nfront, -1) ;
IVramp(nfront, rep, 0, 1) ;
/*
------------------------------------------
perform a post-order traversal of the tree
------------------------------------------
*/
for ( K = Tree_postOTfirst(tree) ;
K != -1 ;
K = Tree_postOTnext(tree, K) ) {
#if MYDEBUG > 0
fprintf(stdout, "\n\n ##### visiting front %d", K) ;
fflush(stdout) ;
#endif
if ( (J = fch[K]) != -1 ) {
KandBnd = nodwghts[K] + bndwghts[K] ;
Jall = 0 ;
cost = 2*nzeros[K] ;
for ( J = fch[K] ; J != -1 ; J = sib[J] ) {
Jall += nodwghts[J] ;
cost -= nodwghts[J]*nodwghts[J] ;
cost += 2*nodwghts[J]*(KandBnd - bndwghts[J]) ;
cost += 2*nzeros[J] ;
}
cost += Jall*Jall ;
cost = cost/2 ;
#if MYDEBUG > 0
fprintf(stdout, "\n cost = %d", cost) ;
fflush(stdout) ;
#endif
if ( cost <= maxzeros ) {
for ( J = fch[K] ; J != -1 ; J = sib[J] ) {
#if MYDEBUG > 0
fprintf(stdout, "\n merging %d into %d", J, K) ;
fflush(stdout) ;
#endif
rep[J] = K ;
nodwghts[K] += nodwghts[J] ;
}
nzeros[K] = cost ;
}
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n whoa, finished") ;
fflush(stdout) ;
#endif
/*
-------------------------------------------------
take the map from fronts to representative fronts
and make the map from old fronts to new fronts
-------------------------------------------------
*/
mapIV = IV_new() ;
IV_init(mapIV, nfront, NULL) ;
map = IV_entries(mapIV) ;
for ( J = 0, nnew = 0 ; J < nfront ; J++ ) {
if ( rep[J] == J ) {
map[J] = nnew++ ;
} else {
K = J ;
while ( rep[K] != K ) {
K = rep[K] ;
}
rep[J] = K ;
}
}
for ( J = 0 ; J < nfront ; J++ ) {
if ( (K = rep[J]) != J ) {
map[J] = map[K] ;
}
}
/*
-------------------------------
get the compressed ETree object
-------------------------------
*/
etree2 = ETree_compress(etree, mapIV) ;
/*
-------------------------
remap the nzeros[] vector
-------------------------
*/
temp = IVinit(nfront, NULL) ;
IVcopy(nfront, temp, nzeros) ;
IV_setSize(nzerosIV, nnew) ;
nzeros = IV_entries(nzerosIV) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( rep[J] == J ) {
nzeros[map[J]] = temp[J] ;
}
}
IVfree(temp) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(nodwghts) ;
IVfree(rep) ;
IV_free(mapIV) ;
return(etree2) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------
static prototype definition
---------------------------
*/
static void visitAny ( int K, int par[], int fch[], int sib[],
int nodwghts[], int bndwghts[], int map[],
int cost[], int nzeros[], int maxzeros) ;
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
purpose -- merge the front tree allowing at most
maxzeros zero entries inside a front
return --
IV object that has the old front to new front map
created -- 96jun23, cca
modified -- 97dec18, cca
bug fixed that incorrectly counted the number of zeros in a front
--------------------------------------------------------------------
*/
ETree *
ETree_mergeFrontsAny (
ETree *etree,
int maxzeros,
IV *nzerosIV
) {
ETree *etree2 ;
int J, K, nfront, nvtx, nnew ;
int *bndwghts, *cost, *fch, *map, *nodwghts,
*nzeros, *par, *place, *rep, *sib, *temp ;
IV *mapIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_mergeFrontsAny(%p,%d)"
"\n bad input\n", etree, maxzeros) ;
exit(-1) ;
}
if ( IV_size(nzerosIV) != nfront ) {
fprintf(stderr, "\n fatal error in ETree_mergeFrontsAny(%p,%d,%p)"
"\n size(nzerosIV) = %d, nfront = %d\n",
etree, maxzeros, nzerosIV, IV_size(nzerosIV), nfront) ;
exit(-1) ;
}
nzeros = IV_entries(nzerosIV) ;
tree = etree->tree ;
nodwghts = IVinit(nfront, 0) ;
bndwghts = IVinit(nfront, 0) ;
par = IVinit(nfront, -1) ;
fch = IVinit(nfront, -1) ;
sib = IVinit(nfront, -1) ;
IVcopy(nfront, par, tree->par) ;
IVcopy(nfront, fch, tree->fch) ;
IVcopy(nfront, sib, tree->sib) ;
IVcopy(nfront, nodwghts, IV_entries(etree->nodwghtsIV)) ;
IVcopy(nfront, bndwghts, IV_entries(etree->bndwghtsIV)) ;
/*
----------------------
set up working storage
----------------------
*/
rep = IVinit(nfront, -1) ;
IVramp(nfront, rep, 0, 1) ;
cost = IVinit(nfront, 0) ;
/*
------------------------------------------
perform a post-order traversal of the tree
------------------------------------------
*/
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
#if MYDEBUG > 0
fprintf(stdout, "\n\n ##### visiting front %d", J) ;
fflush(stdout) ;
#endif
visitAny(J, par, fch, sib, nodwghts, bndwghts,
rep, cost, nzeros, maxzeros) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n whoa, finished") ;
fflush(stdout) ;
#endif
/*
-------------------------------------------------
take the map from fronts to representative fronts
and make the map from old fronts to new fronts
-------------------------------------------------
*/
mapIV = IV_new() ;
IV_init(mapIV, nfront, NULL) ;
map = IV_entries(mapIV) ;
place = IVinit(nfront, -1) ;
for ( J = 0, nnew = 0 ; J < nfront ; J++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n rep[%d] = %d", J, rep[J]) ;
fflush(stdout) ;
#endif
if ( rep[J] != J ) {
K = J ;
while ( rep[K] != K ) {
#if MYDEBUG > 0
fprintf(stdout, "\n rep[%d] = %d", K, rep[K]) ;
fflush(stdout) ;
#endif
K = rep[K] ;
}
rep[J] = K ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting rep[%d] = %d", J, rep[J]) ;
fflush(stdout) ;
#endif
} else {
place[J] = nnew++ ;
}
}
for ( J = 0 ; J < nfront ; J++ ) {
K = rep[J] ;
map[J] = place[K] ;
}
/*
-------------------------------
get the compressed ETree object
-------------------------------
*/
etree2 = ETree_compress(etree, mapIV) ;
/*
-------------------------
remap the nzeros[] vector
-------------------------
*/
temp = IVinit(nfront, NULL) ;
IVcopy(nfront, temp, nzeros) ;
IV_setSize(nzerosIV, nnew) ;
nzeros = IV_entries(nzerosIV) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( rep[J] == J ) {
nzeros[map[J]] = temp[J] ;
}
}
IVfree(temp) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(par) ;
IVfree(fch) ;
IVfree(sib) ;
IVfree(nodwghts) ;
IVfree(bndwghts) ;
IVfree(rep) ;
IVfree(cost) ;
IVfree(place) ;
IV_free(mapIV) ;
return(etree2) ; }
/*--------------------------------------------------------------------*/
static void
visitAny (
int K,
int par[],
int fch[],
int sib[],
int nodwghts[],
int bndwghts[],
int rep[],
int cost[],
int nzeros[],
int maxzeros
) {
int bestJ, firstI, J, lastI, nextJ, prevJ ;
if ( fch[K] == -1 ) {
return ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n inside visitAny(%d), nzeros(%d) = %d",
K, K, nzeros[K]) ;
#endif
/*
----------------------------------
find the child with the least cost
----------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n nodwght %d, bndwght %d",
nodwghts[K], bndwghts[K]) ;
#endif
bestJ = -1 ;
for ( J = fch[K] ; J != -1 ; J = sib[J] ) {
cost[J] = nzeros[J]
+ nodwghts[J] * (nodwghts[K] + bndwghts[K] - bndwghts[J]) ;
#if MYDEBUG > 0
fprintf(stdout, "\n child %d, nodwght %d, bndwght %d, cost %d",
J, nodwghts[J], bndwghts[J], cost[J]) ;
#endif
if ( bestJ == -1
|| cost[J] < cost[bestJ]
|| (cost[J] == cost[bestJ] && nodwghts[J] < nodwghts[bestJ]) ) {
bestJ = J ;
}
}
if ( (cost[bestJ] + nzeros[K] > maxzeros)
|| (sib[fch[K]] != -1 && par[K] == -1) ) {
#if MYDEBUG > 0
fprintf(stdout,
"\n no merge: cost[%d] + nzeros[%d] = %d + %d > %d",
bestJ, K, cost[bestJ], nzeros[K], maxzeros) ;
#endif
/*
--------------------------------
no child can be absorbed, return
--------------------------------
*/
return ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n merging child %d into %d", bestJ, K) ;
#endif
/*
-------------------------
absorb child bestJ into K
-------------------------
*/
for ( J = fch[K], prevJ = -1 ; J != bestJ ; J = sib[J] ) {
prevJ = J ;
}
nextJ = sib[bestJ] ;
#if MYDEBUG > 0
fprintf(stdout, "\n previous sibling = %d, next sibling = %d",
prevJ, nextJ) ;
#endif
if ( (firstI = fch[bestJ]) == -1 ) {
if ( prevJ == -1 ) {
fch[K] = nextJ ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting fch[%d] = %d", K, fch[K]) ;
#endif
} else {
sib[prevJ] = nextJ ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting sib[%d] = %d", prevJ, sib[prevJ]) ;
#endif
}
} else {
firstI = fch[bestJ] ;
par[firstI] = K ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting par[%d] = %d", firstI, par[firstI]) ;
#endif
if ( (lastI = sib[firstI]) != -1 ) {
while ( sib[lastI] != -1 ) {
par[lastI] = K ;
#if MYDEBUG > 0
fprintf(stdout,
"\n setting par[%d] = %d", lastI, par[lastI]) ;
#endif
lastI = sib[lastI] ;
}
par[lastI] = K ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting par[%d] = %d", lastI, par[lastI]) ;
#endif
}
if ( prevJ == -1 ) {
fch[K] = firstI ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting fch[%d] = %d", K, fch[K]) ;
#endif
} else {
sib[prevJ] = firstI ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting sib[%d] = %d", prevJ, sib[prevJ]) ;
#endif
}
if ( lastI != -1 ) {
sib[lastI] = nextJ ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting sib[%d] = %d", lastI, sib[lastI]) ;
#endif
}
}
rep[bestJ] = K ;
nodwghts[K] += nodwghts[bestJ] ;
nzeros[K] += cost[bestJ] ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting rep[%d] = %d", bestJ, rep[bestJ]) ;
fprintf(stdout, "\n setting nodwghts[%d] = %d", K, nodwghts[K]) ;
fprintf(stdout, "\n setting nzeros[%d] = %d", K, nzeros[K]) ;
#endif
/*
-------------
visit K again
-------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n\n ### visiting front %d", K) ;
fflush(stdout) ;
#endif
visitAny(K, par, fch, sib, nodwghts, bndwghts,
rep, cost, nzeros, maxzeros) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
expand an ETree object by splitting a large front
into a chain of smaller fronts.
created -- 96jun27, cca
-------------------------------------------------
*/
ETree *
ETree_splitFronts (
ETree *etree,
int vwghts[],
int maxfrontsize,
int seed
) {
ETree *etree2 ;
int count, front, ii, I, Inew, J, Jnew, nbnd, newsize, nint, nfront,
nfront2, nsplit, nvtx, prev, size, sizeJ, v, vwght ;
int *bndwghts, *fch, *head, *indices, *link, *newbndwghts, *newmap,
*newnodwghts, *newpar, *nodwghts, *roots, *sib, *vtxToFront ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0
|| maxfrontsize <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_splitFronts(%p,%p,%d,%d)"
"\n bad input\n", etree, vwghts, maxfrontsize, seed) ;
exit(-1) ;
}
tree = etree->tree ;
fch = tree->fch ;
sib = tree->sib ;
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
/*
--------------------------
set up the working storage
--------------------------
*/
newpar = IVinit(nvtx, -1) ;
roots = IVinit(nfront, -1) ;
newmap = IVinit(nvtx, -1) ;
newnodwghts = IVinit(nvtx, -1) ;
newbndwghts = IVinit(nvtx, -1) ;
head = IVinit(nfront, -1) ;
link = IVinit(nvtx, -1) ;
indices = IVinit(nvtx, -1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
front = vtxToFront[v] ;
link[v] = head[front] ;
head[front] = v ;
}
/*
------------------------------------------------
execute a post-order traversal of the front tree
------------------------------------------------
*/
nfront2 = 0 ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
sizeJ = 0 ;
for ( v = head[J], count = 0 ; v != -1 ; v = link[v] ) {
indices[count++] = v ;
vwght = (vwghts != NULL) ? vwghts[v] : 1 ;
sizeJ += vwght ;
}
if ( sizeJ != nodwghts[J] ) {
fprintf(stderr, "\n fatal error in ETree_splitFronts(%p,%p,%d,%d)"
"\n J = %d, sizeJ = %d, nodwght = %d\n",
etree, vwghts, maxfrontsize, seed, J, sizeJ, nodwghts[J]) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n checking out front %d, size %d", J, sizeJ) ;
#endif
if ( sizeJ <= maxfrontsize || fch[J] == -1 ) {
/*
-------------------------------------------
this front is small enough (or is a domain)
-------------------------------------------
*/
Jnew = nfront2++ ;
for ( ii = 0 ; ii < count ; ii++ ) {
v = indices[ii] ;
newmap[v] = Jnew ;
#if MYDEBUG > 1
fprintf(stdout, "\n mapping vertex %d into new front %d",
v, Jnew) ;
#endif
}
for ( I = fch[J] ; I != -1 ; I = sib[I] ) {
Inew = roots[I] ;
newpar[Inew] = Jnew ;
}
newnodwghts[Jnew] = nodwghts[J] ;
newbndwghts[Jnew] = bndwghts[J] ;
roots[J] = Jnew ;
#if MYDEBUG > 0
fprintf(stdout, "\n front is small enough, Jnew = %d", Jnew) ;
#endif
} else {
/*
------------------------------------------
this front is too large, split into pieces
whose size differs by one vertex
------------------------------------------
*/
nsplit = (sizeJ + maxfrontsize - 1)/maxfrontsize ;
newsize = sizeJ / nsplit ;
if ( sizeJ % nsplit != 0 ) {
newsize++ ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n front is too large, %d target fronts, target size = %d",
nsplit, newsize) ;
#endif
prev = -1 ;
nint = nodwghts[J] ;
nbnd = nint + bndwghts[J] ;
if ( seed > 0 ) {
IVshuffle(count, indices, seed) ;
}
ii = 0 ;
while ( ii < count ) {
Jnew = nfront2++ ;
size = 0 ;
while ( ii < count ) {
v = indices[ii] ;
vwght = (vwghts != NULL) ? vwghts[v] : 1 ;
#if MYDEBUG > 0
fprintf(stdout,
"\n ii = %d, v = %d, vwght = %d, size = %d",
ii, v, vwght, size) ;
#endif
/*
-----------------------------------------------
97aug28, cca
bug fix. front is created even if it is too big
-----------------------------------------------
*/
if ( newsize >= size + vwght || size == 0 ) {
newmap[v] = Jnew ;
size += vwght ;
#if MYDEBUG > 0
fprintf(stdout,
"\n mapping vertex %d into new front %d, size = %d",
v, Jnew, size) ;
#endif
ii++ ;
} else {
break ;
}
}
if ( prev == -1 ) {
for ( I = fch[J] ; I != -1 ; I = sib[I] ) {
Inew = roots[I] ;
newpar[Inew] = Jnew ;
}
} else {
newpar[prev] = Jnew ;
}
prev = Jnew ;
newnodwghts[Jnew] = size ;
nbnd = nbnd - size ;
newbndwghts[Jnew] = nbnd ;
#if MYDEBUG > 0
fprintf(stdout, "\n new front %d, size %d, bnd %d",
Jnew, newnodwghts[Jnew], newbndwghts[Jnew]) ;
#endif
}
roots[J] = Jnew ;
}
}
/*
---------------------------
create the new ETree object
---------------------------
*/
etree2 = ETree_new() ;
ETree_init1(etree2, nfront2, nvtx) ;
IVcopy(nfront2, etree2->tree->par, newpar) ;
Tree_setFchSibRoot(etree2->tree) ;
IVcopy(nvtx, IV_entries(etree2->vtxToFrontIV), newmap) ;
IVcopy(nfront2, IV_entries(etree2->nodwghtsIV), newnodwghts) ;
IVcopy(nfront2, IV_entries(etree2->bndwghtsIV), newbndwghts) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(newpar) ;
IVfree(roots) ;
IVfree(newmap) ;
IVfree(newnodwghts) ;
IVfree(newbndwghts) ;
IVfree(head) ;
IVfree(link) ;
IVfree(indices) ;
return(etree2) ; }
/*--------------------------------------------------------------------*/
---------------------
free the working storage
------------------------
*/
IVfree(par) ;
IVfree(fch) ;
IVfree(sib) ;
IVfree(nodwghts) ;
IVfree(bndwghts) ;
IVfree(rep) ;
IVfree(cost) ;
IVfree(place) ;
IV_free(mapIV) ;
return(etree2) ; }
/*--------------------------------------------------------ETree/src/util.c 0100644 0002055 0007177 00000046430 06536062013 0015015 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../ETree.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 95nov15, cca
----------------------------------------------
*/
int
ETree_sizeOf (
ETree *etree
) {
int nbytes ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_sizeOf(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
nbytes = sizeof(struct _ETree) ;
if ( etree->tree != NULL ) {
nbytes += Tree_sizeOf(etree->tree) ;
}
if ( etree->nodwghtsIV != NULL ) {
nbytes += IV_sizeOf(etree->nodwghtsIV) ;
}
if ( etree->nodwghtsIV != NULL ) {
nbytes += IV_sizeOf(etree->bndwghtsIV) ;
}
if ( etree->vtxToFrontIV != NULL ) {
nbytes += IV_sizeOf(etree->vtxToFrontIV) ;
}
return(nbytes) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------
return the number of factor indices
created -- 95nov15, cca
modified -- 96jan11, cca
----------------------------------------
*/
int
ETree_nFactorIndices (
ETree *etree
) {
int nb, nfront, nv, nind, nvtx, v ;
int *bndwghts, *nodwghts ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_nFactorIndices(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
nind = 0 ;
for ( v = 0 ; v < nfront ; v++ ) {
nv = nodwghts[v] ;
nb = bndwghts[v] ;
nind += nv + nb ;
}
return(nind) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
return the number of factor entries
symflag -- symmetry flag
0 (SPOOLES_SYMMETRIC) -- symmetric
1 (SPOOLES_HERMITIAN) -- hermitian
2 (SPOOLES_NONSYMMETRIC) -- nonsymmetric
created -- 98jun05, cca
------------------------------------------
*/
int
ETree_nFactorEntries (
ETree *etree,
int symflag
) {
int J, nfront, nvtx, nzf ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_nFactorEntries(%p,%d)"
"\n bad input\n", etree, symflag) ;
exit(-1) ;
}
nzf = 0 ;
for ( J = 0 ; J < nfront ; J++ ) {
nzf += ETree_nFactorEntriesInFront(etree, symflag, J) ;
}
return(nzf) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
return the number of factor operations
type -- type of matrix entries
1 (SPOOLES_REAL) -- real entries
2 (SPOOLES_COMPLEX) -- complex entries
symflag -- symmetry flag
0 (SPOOLES_SYMMETRIC) -- symmetric
1 (SPOOLES_HERMITIAN) -- hermitian
2 (SPOOLES_NONSYMMETRIC) -- nonsymmetric
created -- 98jun05, cca
------------------------------------------
*/
double
ETree_nFactorOps (
ETree *etree,
int type,
int symflag
) {
double ops ;
int J, nfront, nvtx ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_nFactorOps(%p,%d,%d)"
"\n bad input\n", etree, type, symflag) ;
exit(-1) ;
}
ops = 0 ;
for ( J = 0 ; J < nfront ; J++ ) {
ops += ETree_nInternalOpsInFront(etree, type, symflag, J)
+ ETree_nExternalOpsInFront(etree, type, symflag, J) ;
}
return(ops) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------
return the number of entries an LU front
created -- 96dec04, cca
----------------------------------------
*/
double
ETree_nFactorEntriesInFront (
ETree *etree,
int symflag,
int J
) {
int b, m, nent ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| etree->nfront <= 0
|| J < 0 || J >= etree->nfront ) {
fprintf(stderr,
"\n fatal error in ETree_nFactorEntriesInFront(%p,%d,%d)"
"\n bad input\n", etree, symflag, J) ;
exit(-1) ;
}
b = IV_entry(etree->nodwghtsIV, J) ;
m = IV_entry(etree->bndwghtsIV, J) ;
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
nent = (b*(b+1))/2 + b*m ;
break ;
case SPOOLES_NONSYMMETRIC :
nent = b*b + 2*b*m ;
break ;
default :
fprintf(stderr,
"\n fatal error in ETree_nFactorEntriesInFront(%p,%d,%d)"
"\n bad symflag\n", etree, symflag, J) ;
break ;
}
return(nent) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
return the number of internal LU operations for a front
created -- 96dec04, cca
-------------------------------------------------------
*/
double
ETree_nInternalOpsInFront (
ETree *etree,
int type,
int symflag,
int J
) {
double b, m, ops ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| etree->nfront <= 0
|| J < 0 || J >= etree->nfront ) {
fprintf(stderr,
"\n fatal error in ETree_nInternalOpsInFront(%p,%d,%d,%d)"
"\n bad input\n", etree, type, symflag, J) ;
exit(-1) ;
}
b = ETree_frontSize(etree, J) ;
m = ETree_frontBoundarySize(etree, J) ;
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
ops = (b*(b+1)*(2*b+1))/6. + m*b*b ;
break ;
case SPOOLES_NONSYMMETRIC :
ops = b*(2*b*b+1)/3. + 2*m*b*b ;
break ;
default :
fprintf(stderr,
"\n fatal error in ETree_nInternalOpsInFront(%p,%d,%d,%d)"
"\n bad symflag\n", etree, type, symflag, J) ;
break ;
}
switch ( type ) {
case SPOOLES_REAL :
break ;
case SPOOLES_COMPLEX :
ops = 4*ops ;
break ;
default :
fprintf(stderr,
"\n fatal error in ETree_nInternalOpsInFront(%p,%d,%d,%d)"
"\n bad type\n", etree, type, symflag, J) ;
break ;
}
return(ops) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
return the number of external LU operations for a front
created -- 96dec04, cca
-------------------------------------------------------
*/
double
ETree_nExternalOpsInFront (
ETree *etree,
int type,
int symflag,
int J
) {
double b, m, ops ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| etree->nfront <= 0
|| J < 0 || J >= etree->nfront ) {
fprintf(stderr,
"\n fatal error in ETree_nExternalOpsInFront(%p,%d,%d,%d)"
"\n bad input\n", etree, J, type, symflag) ;
exit(-1) ;
}
b = IV_entry(etree->nodwghtsIV, J) ;
m = IV_entry(etree->bndwghtsIV, J) ;
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
ops = m*(m+1)*b ;
break ;
case SPOOLES_NONSYMMETRIC :
ops = 2*b*m*m ;
break ;
default :
break ;
}
switch ( type ) {
case SPOOLES_REAL :
break ;
case SPOOLES_COMPLEX :
ops = 4*ops ;
break ;
default :
fprintf(stderr,
"\n fatal error in ETree_nExternalOpsInFront(%p,%d,%d,%d)"
"\n bad input\n", etree, J, type, symflag) ;
break ;
}
return(ops) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
return a DV object that contains the number of operations
for each front using a backward looking algorithm
created -- 96dec04, cca
---------------------------------------------------------
*/
DV *
ETree_backwardOps (
ETree *etree,
int type,
int symflag,
int *vwghts,
IVL *symbfacIVL
) {
double extops, opsKbndK, opsKK ;
double *ops ;
DV *opsDV ;
int bndwghtJ, ii, J, k, K, kwght,
nadj, nfront, size, wghtJ, wghtK ;
int *counts, *indices, *list, *mark, *vtxToFront ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || symbfacIVL == NULL ) {
fprintf(stderr, "\n fatal error in ETree_backwardOps(%p,%p,%p)"
"\n bad input\n", etree, vwghts, symbfacIVL) ;
exit(-1) ;
}
nfront = etree->nfront ;
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
list = IVinit(nfront, -1) ;
mark = IVinit(nfront, -1) ;
counts = IVinit(nfront, 0) ;
/*
----------------------------
initialize the ops DV object
----------------------------
*/
opsDV = DV_new() ;
DV_init(opsDV, nfront, NULL) ;
ops = DV_entries(opsDV) ;
DV_fill(opsDV, 0.0) ;
/*
-------------------
fill the ops vector
-------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
ops[J] += ETree_nInternalOpsInFront(etree, type, symflag, J) ;
wghtJ = ETree_frontSize(etree, J) ;
bndwghtJ = ETree_frontBoundarySize(etree, J) ;
IVL_listAndSize(symbfacIVL, J, &size, &indices) ;
for ( ii = nadj = 0 ; ii < size ; ii++ ) {
k = indices[ii] ;
if ( (K = vtxToFront[k]) != J ) {
kwght = (vwghts == NULL) ? 1 : vwghts[k] ;
if ( mark[K] != J ) {
counts[K] = 0 ;
mark[K] = J ;
list[nadj++] = K ;
}
counts[K] += kwght ;
}
}
IVqsortUp(nadj, list) ;
extops = 0.0 ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = list[ii] ;
wghtK = counts[K] ;
bndwghtJ -= wghtK ;
if ( type == SPOOLES_REAL ) {
opsKbndK = 2*wghtJ*wghtK*bndwghtJ ;
if ( symflag == SPOOLES_SYMMETRIC ) {
opsKK = wghtJ*wghtK*(wghtK+1) ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
opsKK = 2*wghtJ*wghtK*wghtK ;
}
} else if ( type == SPOOLES_COMPLEX ) {
opsKbndK = 8*wghtJ*wghtK*bndwghtJ ;
if ( symflag == SPOOLES_SYMMETRIC
|| symflag == SPOOLES_HERMITIAN ) {
opsKK = 4*wghtJ*wghtK*(wghtK+1) ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
opsKK = 8*wghtJ*wghtK*wghtK ;
}
}
extops += opsKK + opsKbndK ;
ops[K] += opsKK + opsKbndK ;
if ( symflag == SPOOLES_NONSYMMETRIC ) {
extops += opsKbndK ;
ops[K] += opsKbndK ;
}
}
/*
fprintf(stdout,
"\n front %d, %.0f internal ops, %.0f external ops, %.0f extops",
J, ETree_nInternalOpsInFront(etree, type, symflag, J),
ETree_nExternalOpsInFront(etree, type, symflag, J), extops) ;
*/
}
IVfree(list) ;
IVfree(mark) ;
IVfree(counts) ;
return(opsDV) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
return an IV object that contains
the number of entries for each front
created -- 98jan30, cca
------------------------------------
*/
IV *
ETree_factorEntriesIV (
ETree *etree,
int symflag
) {
int J, nfront ;
int *nzf ;
IV *nzfIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_factorEntriesIV(%p,%d)"
"\n bad input\n", etree, symflag) ;
exit(-1) ;
}
nfront = ETree_nfront(etree) ;
/*
------------------------
initialize the IV object
------------------------
*/
nzfIV = IV_new() ;
IV_init(nzfIV, nfront, NULL) ;
nzf = IV_entries(nzfIV) ;
IV_fill(nzfIV, 0) ;
/*
-------------------
fill the nzf vector
-------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
nzf[J] = ETree_nFactorEntriesInFront(etree, symflag, J) ;
}
return(nzfIV) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
return a DV object that contains the number of operations
for each front using a forward-looking algorithm
created -- 96dec04, cca
---------------------------------------------------------
*/
DV *
ETree_forwardOps (
ETree *etree,
int type,
int symflag
) {
double *ops ;
DV *opsDV ;
int J, nfront ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_forwardOps(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
nfront = etree->nfront ;
opsDV = DV_new() ;
DV_init(opsDV, nfront, NULL) ;
ops = DV_entries(opsDV) ;
DV_fill(opsDV, 0.0) ;
for ( J = 0 ; J < nfront ; J++ ) {
ops[J] += ETree_nInternalOpsInFront(etree, type, symflag, J)
+ ETree_nExternalOpsInFront(etree, type, symflag, J) ;
}
return(opsDV) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
given an IV object that maps uncompressed vertices to vertices,
create and return an ETree object that is relative to the
uncompressed graph.
created -- 97feb13, cca
---------------------------------------------------------------
*/
ETree *
ETree_expand (
ETree *etree,
IV *eqmapIV
) {
ETree *etree2 ;
int ii, ndof, nfront ;
int *map, *vtxToFront, *vtxToFront2 ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || eqmapIV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_expand(%p,%p)"
"\n bad input\n", etree, eqmapIV) ;
exit(-1) ;
}
nfront = etree->nfront ;
IV_sizeAndEntries(eqmapIV, &ndof, &map) ;
/*
---------------------------
create the new ETree object
---------------------------
*/
etree2 = ETree_new() ;
ETree_init1(etree2, nfront, ndof) ;
IV_copy(etree2->nodwghtsIV, etree->nodwghtsIV) ;
IV_copy(etree2->bndwghtsIV, etree->bndwghtsIV) ;
etree2->tree->root = etree->tree->root ;
IVcopy(nfront, etree2->tree->par, etree->tree->par) ;
IVcopy(nfront, etree2->tree->fch, etree->tree->fch) ;
IVcopy(nfront, etree2->tree->sib, etree->tree->sib) ;
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
vtxToFront2 = IV_entries(etree2->vtxToFrontIV) ;
for ( ii = 0 ; ii < ndof ; ii++ ) {
vtxToFront2[ii] = vtxToFront[map[ii]] ;
}
return(etree2) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
this method is used to splice together two front trees
when the domain vertices and schur complement vertices
have been ordered separately.
etree0 -- the lower front tree is for vertices in the domains.
graph0 -- graph for all the vertices
mapIV -- IV object that maps vertices to schur complement
vertices, if IV_entry(mapIV, v) < 0 then v is
a domain vertex.
etree1 -- the upper front tree is for vertices in the schur
complement.
created -- 97feb01, cca
--------------------------------------------------------------
*/
ETree *
ETree_spliceTwoETrees (
ETree *etree0,
Graph *graph0,
IV *mapIV,
ETree *etree1
) {
ETree *etree2 ;
int *bndwghts0, *bndwghts1, *bndwghts2, *fch0, *head0, *link0,
*map, *mark, *nodwghts0, *nodwghts1, *nodwghts2, *par0,
*par1, *par2, *sib0, *vadj, *vtxToFront0, *vtxToFront1,
*vtxToFront2 ;
int ii, J, K, nfront0, nfront1, nfront2, nvtx, phi, v, vsize, w ;
/*
---------------
check the input
---------------
*/
if ( etree0 == NULL || graph0 == NULL
|| mapIV == NULL || etree1 == NULL ) {
fprintf(stderr,
"\n fatal error in ETree_spliceTwoETrees(%p,%p,%p,%p)"
"\n bad input\n",
etree0, graph0, mapIV, etree1) ;
exit(-1) ;
}
nfront0 = etree0->nfront ;
nvtx = etree0->nvtx ;
par0 = etree0->tree->par ;
fch0 = etree0->tree->fch ;
sib0 = etree0->tree->sib ;
nodwghts0 = IV_entries(etree0->nodwghtsIV) ;
bndwghts0 = IV_entries(etree0->bndwghtsIV) ;
vtxToFront0 = IV_entries(etree0->vtxToFrontIV) ;
nfront1 = etree1->nfront ;
par1 = etree1->tree->par ;
bndwghts1 = IV_entries(etree1->bndwghtsIV) ;
nodwghts1 = IV_entries(etree1->nodwghtsIV) ;
vtxToFront1 = IV_entries(etree1->vtxToFrontIV) ;
map = IV_entries(mapIV) ;
/*
-------------------------
create the new front tree
-------------------------
*/
nfront2 = nfront0 + nfront1 ;
etree2 = ETree_new() ;
ETree_init1(etree2, nfront2, etree0->nvtx) ;
par2 = etree2->tree->par ;
nodwghts2 = IV_entries(etree2->nodwghtsIV) ;
bndwghts2 = IV_entries(etree2->bndwghtsIV) ;
vtxToFront2 = IV_entries(etree2->vtxToFrontIV) ;
/*
--------------------------------------------------
fill the parent fields for fronts in the same tree
--------------------------------------------------
*/
for ( J = 0 ; J < nfront0 ; J++ ) {
par2[J] = par0[J] ;
nodwghts2[J] = nodwghts0[J] ;
bndwghts2[J] = bndwghts0[J] ;
}
for ( J = 0 ; J < nfront1 ; J++ ) {
par2[J+nfront0] = nfront0 + par1[J] ;
nodwghts2[J+nfront0] = nodwghts1[J] ;
bndwghts2[J+nfront0] = bndwghts1[J] ;
}
/*
---------------------------
set the vertex to front map
---------------------------
*/
for ( v = 0 ; v < nvtx ; v++ ) {
if ( (J = vtxToFront0[v]) >= 0 ) {
vtxToFront2[v] = J ;
} else {
vtxToFront2[v] = vtxToFront1[map[v]] + nfront0 ;
}
}
/*
---------------------------------------------
link the vertices to fronts in the lower tree
---------------------------------------------
*/
head0 = IVinit(nfront0, -1) ;
link0 = IVinit(nvtx, -1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( (J = vtxToFront0[v]) >= 0 ) {
link0[v] = head0[J] ;
head0[J] = v ;
}
}
/*
-------------------------------------------------------
link roots of the lower tree to nodes in the upper tree
-------------------------------------------------------
*/
mark = IVinit(nvtx, -1) ;
for ( J = etree0->tree->root ; J != -1 ; J = sib0[J] ) {
/*
---------------------------------------
K is the parent front in the upper tree
---------------------------------------
*/
K = nfront1 ;
/*
---------------------------------------
loop over vertices in the lower front J
---------------------------------------
*/
for ( v = head0[J] ; v != -1 ; v = link0[v] ) {
Graph_adjAndSize(graph0, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( vtxToFront0[w] < 0 ) {
phi = map[w] ;
/*
---------------------------------------------------
w is a vertex that belongs to phi in the upper tree
---------------------------------------------------
*/
if ( mark[phi] != J ) {
mark[phi] = J ;
if ( K > vtxToFront1[phi] ) {
/*
------------------------------------
least numbered adjacent front so far
------------------------------------
*/
K = vtxToFront1[phi] ;
}
}
}
}
}
if ( K < nfront1 ) {
/*
--------------------
set the parent field
--------------------
*/
par2[J] = nfront0 + K ;
}
}
/*
-----------------------------
set the remaining tree fields
-----------------------------
*/
Tree_setFchSibRoot(etree2->tree) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(head0) ;
IVfree(link0) ;
IVfree(mark) ;
return(etree2) ; }
/*--------------------------------------------------------------------*/
= J ;
list[nadj++] = K ;
}
counts[K] += kwght ;
}
}
IVqsortUp(nadj, list) ;
extops = 0.0 ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = list[ii] ;
wghtK = counts[K] ;
bndETree/drivers/do_createETree 0100755 0002055 0007177 00000000713 06542757445 0017376 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = GRD7x7
set inGraphFile = $matrices/$matrix/orig0.graphf
set inPermFile = $matrices/$matrix/nd.permf
set outIVfile = temp.ivf
set outIVfile = none
set outETreeFile = $matrices/$matrix/nd.etreeb
set outETreeFile = temp.etreef
set outETreeFile = none
set msglvl = 1
set msgFile = stdout
createETree $msglvl $msgFile \
$inGraphFile $inPermFile $outIVfile $outETreeFile
ETree/drivers/do_expand 0100755 0002055 0007177 00000001213 06602526440 0016443 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set number = 8
set inETreeFile = $matrices/$matrix/nd.etreef
set inETreeFile = nd.etreef
set inETreeFile = /local1/ARPA/matrices/i4a/best1.etreef
set inETreeFile = /local1/ARPA/matrices/SFTC$number/best1.etreef
set inEqmapFile = /local1/ARPA/matrices/i4a/map1.ivb
set inEqmapFile = /local1/ARPA/matrices/SFTC$number/eqmap.ivb
set outETreeFile = $matrices/$matrix/nd.etreeb
set outETreeFile = none
set outETreeFile = /local1/ARPA/matrices/SFTC$number/best0.etreef
set msglvl = 1
set msgFile = stdout
testExpand $msglvl $msgFile $inETreeFile $inEqmapFile $outETreeFile
ETree/drivers/do_extractTopSep 0100755 0002055 0007177 00000000420 06534106070 0017765 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inETreeFile = $matrices/$matrix/nd.etreef
set outIVfile = none
set outIVfile = temp.ivf
set msglvl = 3
set msgFile = stdout
extractTopSep $msglvl $msgFile $inETreeFile $outIVfile
ETree/drivers/do_mkNDETree 0100755 0002055 0007177 00000002045 06652147373 0016757 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrices = ../../../matrices
set matrix = GRD3x2
set matrix = GRD15x15x15
set matrix = GRD7x7x7
set matrix = GRD31x31x31
set msglvl = 1
set msgFile = nd.res
set msgFile = stdout
set n1 = 33
set n2 = 33
set n3 = 33
set maxzeros = 16384
set maxzeros = 64
set maxsize = 32
set maxzeros = 0
set maxzeros = 1000
set maxsize = 100000
set maxsize = 64
set outFile = none
set outFile = $matrices/$matrix/nd2.etreef
set outFile = nd.etreef
# foreach n ( 10 12 14 17 20 24 28 34 40 48 56 )
foreach n ( 31 )
set n1 = $n
set n2 = $n
set n3 = 1
set n3 = $n
mkNDETree $msglvl $msgFile $n1 $n2 $n3 $maxzeros $maxsize $outFile
end
exit
# foreach maxzeros ( 0 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 )
mkNDETree $msglvl $msgFile $n1 $n2 $n3 $maxzeros $maxsize $outFile
# end
exit
set nmax = 70
set nmin = 66
@ n = $nmin
while ( $n <= $nmax )
echo n = $n
mkNDETree $msglvl $msgFile $n $n $n $maxzeros $maxsize $outFile
@ n = $n + 1
end
ETree/drivers/do_mkNDoutput 0100755 0002055 0007177 00000001072 06542760022 0017300 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = GRD3x2
set matrix = GRD15x15
set msglvl = 1
set msgFile = nd.res
set msgFile = stdout
set n1 = 15
set n2 = 15
set n3 = 15
set maxzeros = 1000
set maxsize = 32
set outETreeFile = none
set outETreeFile = $matrices/$matrix/nd.etreef
set nthread = 4
set maptype = 4
set cutoff = 0.125
set outOwnersFile = $matrices/$matrix/ndowners.ivf
set outOwnersFile = none
mkNDoutput $msglvl $msgFile $n1 $n2 $n3 $maxzeros $maxsize \
$nthread $maptype $cutoff $outETreeFile $outOwnersFile
ETree/drivers/do_permuteETree 0100755 0002055 0007177 00000000561 06534106070 0017574 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inETreeFile = $matrices/$matrix/nd.etreef
set inEqmapFile = none
set outETreeFile = $matrices/$matrix/nd.etreeb
set outETreeFile = none
set outIVfile = none
set msglvl = 3
set msgFile = stdout
permuteETree $msglvl $msgFile \
$inETreeFile $inEqmapFile $outETreeFile $outIVfile
ETree/drivers/do_temp 0100755 0002055 0007177 00000001157 06645206455 0016150 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set msglvl = 1
set msgFile = stdout
set msgFile = nd3d.res
set n1 = 33
set n2 = 33
set n3 = 33
set maxzeros = 16384
set maxzeros = 64
set maxsize = 32
set maxzeros = 1000
set maxzeros = 0
set maxsize = 64
set maxsize = 100000
# foreach n ( 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 )
# foreach n ( 10 12 14 17 20 24 28 34 40 48 56 )
foreach n ( 31 )
set n1 = $n
set n2 = $n
# set n3 = 1
set n3 = $n
echo $n1 x $n2 x $n3
mkNDETree $msglvl $msgFile $n1 $n2 $n3 $maxzeros $maxsize nd.etreef
testHeight $msglvl $msgFile nd.etreef
rm nd.etreef
end
ETree/drivers/do_testFS 0100755 0002055 0007177 00000001754 06652456733 0016422 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inETreeFile = $matrices/$matrix/nd.etreef
set inGraphFile = $matrices/$matrix/orig0.graphf
set matrices = ../../../matrices
set matrix = BCSSTK24
set matrix = GRD15x15x127
set matrix = BCSSTK37
set matrix = BCSSTK30
set matrix = MN12
set matrix = GRD31x31x31
set matrix = GRD7x7
# set matrices = /local1/ARPA/matrices
# set matrix = i4a
set inETreeFile = $matrices/$matrix/nd2.etreef
set inETreeFile = $matrices/$matrix/msmd.etreef
set inETreeFile = $matrices/$matrix/best0.etreef
set inETreeFile = $matrices/$matrix/ms.etreef
set inETreeFile = $matrices/$matrix/mmd.etreef
set inETreeFile = $matrices/$matrix/nd.etreef
set firstEPSfile = temp1.eps
set secondEPSfile = temp2.eps
set labelflag = 1
set radius = 10
set msglvl = 1
set msgFile = stdout
testFS $msglvl $msgFile $inETreeFile \
$labelflag $radius $firstEPSfile $secondEPSfile
ETree/drivers/do_testHeight 0100755 0002055 0007177 00000001517 06645162254 0017311 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inETreeFile = $matrices/$matrix/nd.etreef
set inGraphFile = $matrices/$matrix/orig0.graphf
set matrices = ../../../matrices
set matrix = BCSSTK24
set matrix = GRD15x15x127
set matrix = GRD7x7
set matrix = GRD31x31x31
set matrix = BCSSTK37
set matrix = BCSSTK30
set matrix = MN12
# set matrices = /local1/ARPA/matrices
# set matrix = i4a
set inETreeFile = $matrices/$matrix/nd2.etreef
set inETreeFile = $matrices/$matrix/msmd.etreef
set inETreeFile = $matrices/$matrix/best0.etreef
set inETreeFile = $matrices/$matrix/mmd.etreef
set inETreeFile = $matrices/$matrix/nd.etreef
set inETreeFile = $matrices/$matrix/ms.etreef
set msglvl = 1
set msgFile = stdout
testHeight $msglvl $msgFile $inETreeFile
ETree/drivers/do_testIO 0100755 0002055 0007177 00000000434 06632074614 0016403 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inFile = nd.etreef
set inFile = $matrices/$matrix/nd.etreef
set outFile = $matrices/$matrix/nd.etreeb
set outFile = none
set msglvl = 3
set msgFile = stdout
testIO $msglvl $msgFile $inFile $outFile
ETree/drivers/do_testMS 0100755 0002055 0007177 00000001066 06605237510 0016411 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set matrices = ../../../matrices
set matrix = R10KV
set inFile = $matrices/$matrix/best0.etreef
set msglvl = 1
set msgFile = res
set msgFile = stdout
set outFile = none
set outFile = $matrices/$matrix/ndms.ivf
set flag = 1
set cutoff = 4
set flag = 2
set cutoff = 0.015625
set cutoff = 0.0625
set cutoff = 0.125
set cutoff = 0.03125
# foreach cutoff ( 0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125 )
testMS $msglvl $msgFile $inFile $outFile $flag $cutoff
# end
ETree/drivers/do_testMaps 0100755 0002055 0007177 00000001151 06614443753 0016775 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D10000
set matrices = ../../../matrices
set matrix = GRD7x7
set matrix = R2D100
set matrix = GRD31x31x31
set msglvl = 1
set msgFile = stdout
set inFile = nd.etreef
set inFile = $matrices/$matrix/nd.1024.64.etreef
set inFile = $matrices/$matrix/ndnew.etreef
set outFile = temp.ivf
set outFile = $matrices/$matrix/nd.1024.64.dd4.ivf
set outFile = none
set outFile = $matrices/$matrix/ndowners.ivf
set nthread = 16
set type = 3
set cutoff = 0.031250
testMaps $msglvl $msgFile $inFile $outFile $nthread $type $cutoff
ETree/drivers/do_testStats 0100755 0002055 0007177 00000002056 06652461127 0017175 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set matrices = ../../../matrices
set matrix = GRD7x7
set matrix = GRD127x127
set matrix = GRD31x31x31
set matrix = BCSSTK39
set matrix = GRD7x7x7
set inETreeFile = nd.etreef
set inETreeFile = $matrices/$matrix/nd.etreef
set inGraphFile = $matrices/$matrix/orig0.graphb
set inGraphFile = $matrices/$matrix/orig1.graphb
set inGraphFile = $matrices/$matrix/orig0.graphf
set msglvl = 1
set msgFile = res
set msgFile = stdout
set outEPSfile = none
set outEPSfile = temp.eps
#
# metricType
# 0 -- no metric
# 1 -- size of front
# 2 -- # original matrix entries in front
# 3 -- # factor matrix entries in front
# 4 -- # forward factor ops in front
# 5 -- # backward factor ops in front
#
set metricType = 5
set heightflag = D
set coordflag = P
set rmax = 20
set labelflag = 0
set fontscale = 6
testStats $msglvl $msgFile $inETreeFile $inGraphFile $outEPSfile \
$metricType $heightflag $coordflag $rmax $labelflag $fontscale
ETree/drivers/do_testStorage 0100755 0002055 0007177 00000001445 06643464077 0017513 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inETreeFile = $matrices/$matrix/nd.etreef
set inGraphFile = $matrices/$matrix/orig0.graphf
set matrices = ../../../matrices
set matrix = GRD31x31x31
set matrix = BCSSTK24
set matrix = BCSSTK30
set matrix = GRD15x15x127
set inETreeFile = $matrices/$matrix/nd2.etreef
set inETreeFile = $matrices/$matrix/best0.etreef
set inETreeFile = $matrices/$matrix/msmd.etreef
set inETreeFile = $matrices/$matrix/mmd.etreef
set inETreeFile = $matrices/$matrix/nd.etreef
set inETreeFile = $matrices/$matrix/ms.etreef
set inGraphFile = $matrices/$matrix/orig1.graphb
set inGraphFile = $matrices/$matrix/orig0.graphb
set msglvl = 1
set msgFile = stdout
testStorage $msglvl $msgFile $inETreeFile $inGraphFile
30
set matrix = GRD15x15x127
set inETreeFile = $matrices/$matrix/nd2.etreef
set inETreeFile = $matrices/$matrix/best0.etreef
set inETreeFile = $matrices/$matrix/msmd.etreef
set inETreeFile = $matrices/$matrix/mmd.ETree/drivers/do_testTransform 0100755 0002055 0007177 00000001611 06633034576 0020051 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D10000
set matrices = ../../../matrices
set matrix = R3D13824
set msglvl = 1
set msgFile = $matrix.mmd.old
set msgFile = $matrix.nd.old
set msgFile = stdout
set inGraphFile = $matrices/$matrix/orig1.graphb
set inGraphFile = $matrices/$matrix/orig0.graphf
set inGraphFile = $matrices/$matrix/orig0.graphb
set inETreeFile = $matrices/$matrix/nd.etreef
set outETreeFile = none
set maxzeros = 10
set maxsize = 100000
set seed = 10101
set outETreeFile = none
set outETreeFile = $matrices/$matrix/nd.$maxzeros.$maxsize.etreef
foreach maxzeros ( 0 )
echo maxzeros = $maxzeros
foreach maxsize ( 100000 )
echo maxsize = $maxsize
set outETreeFile = $matrices/$matrix/nd.$maxzeros.$maxsize.etreef
testTransform $msglvl $msgFile $inETreeFile $inGraphFile \
$outETreeFile $maxzeros $maxsize $seed
end
end
ETree/drivers/makefile 0100644 0002055 0007177 00000004405 06653404251 0016263 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = createETree \
extractTopSep \
mkNDETree \
mkNDoutput \
permuteETree \
testExpand \
testFS \
testHeight \
testIO \
testMaps \
testMS \
testStats \
testStorage \
testTransform
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
createETree : createETree.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
extractTopSep : extractTopSep.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
mkNDETree : mkNDETree.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
mkNDoutput : mkNDoutput.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
mkNDoutput2 : mkNDoutput2.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
permuteETree : permuteETree.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testBalance : testBalance.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testBounds : testBounds.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testDense : testDense.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testExpand : testExpand.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testFS : testFS.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testHeight : testHeight.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testIO : testIO.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testMaps : testMaps.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testMS : testMS.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testStats : testStats.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testStorage : testStorage.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testTransform : testTransform.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
ETree/drivers/createETree.c 0100644 0002055 0007177 00000017160 06536022062 0017115 0 ustar 00cleve compmath 0000040 0000006 /* createETree.c */
#include "../ETree.h"
#include "../../Perm.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------
read in a Graph and a Perm object.
create the ETree object and fill an IV object
with the compids of the two-set partition
created -- 96may02, cca
---------------------------------------------
*/
{
char *inGraphFileName, *inPermFileName,
*outETreeFileName, *outIVfileName ;
double t1, t2 ;
int msglvl, rc ;
ETree *etree, *fsETree ;
IV *fsMapIV ;
FILE *msgFile ;
Graph *graph ;
Perm *perm ;
if ( argc != 7 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile inPermFile "
"\n outIVfile outETreeFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n inPermFile -- input file, must be *.permf or *.permb"
"\n outIVfile -- output file for compids[]"
"\n must be *.ivf or *.ivf"
"\n outETreeFile -- output file, must be *.etreef or *.etreeb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
inPermFileName = argv[4] ;
outIVfileName = argv[5] ;
outETreeFileName = argv[6] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n inPermFile -- %s"
"\n outIVfile -- %s"
"\n outETreeFile -- %s"
"\n",
argv[0], msglvl, argv[2],
inGraphFileName, inPermFileName,
outIVfileName, outETreeFileName) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
------------------------
read in the Perm object
------------------------
*/
if ( strcmp(inPermFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
/*
exit(0) ;
*/
perm = NULL ;
} else {
perm = Perm_new() ;
MARKTIME(t1) ;
rc = Perm_readFromFile(perm, inPermFileName) ;
Perm_fillOldToNew(perm) ;
Perm_fillNewToOld(perm) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in perm from file %s",
t2 - t1, inPermFileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from Perm_readFromFile(%p,%s)",
rc, perm, inPermFileName) ;
exit(-1) ;
}
rc = Perm_checkPerm(perm) ;
if ( rc != 1 ) {
fprintf(stderr, "\n fatal error, Perm not valid") ;
Perm_writeForHumanEye(perm, stderr) ;
exit(0) ;
}
fprintf(msgFile, "\n\n after reading Perm object from file %s",
inPermFileName) ;
if ( msglvl > 0 ) {
Perm_writeForHumanEye(perm, msgFile) ;
} else {
Perm_writeStats(perm, msgFile) ;
}
fflush(msgFile) ;
}
fprintf(msgFile, "\n newToOld") ;
IVfprintf(msgFile, perm->size, perm->newToOld) ;
fprintf(msgFile, "\n oldToNew") ;
IVfprintf(msgFile, perm->size, perm->oldToNew) ;
/*
-----------------------
create the ETree object
-----------------------
*/
etree = ETree_new() ;
if ( perm == NULL ) {
ETree_initFromGraph(etree, graph) ;
} else {
ETree_initFromGraphWithPerms(etree, graph, perm->newToOld,
perm->oldToNew) ;
}
fprintf(msgFile, "\n\n vertex etree") ;
fprintf(msgFile, "\n %d factor indices",
ETree_nFactorIndices(etree)) ;
fprintf(msgFile, "\n symmetric: %d factor entries",
ETree_nFactorEntries(etree, SPOOLES_SYMMETRIC)) ;
fprintf(msgFile, "\n nonsymmetric: %d factor entries",
ETree_nFactorEntries(etree, SPOOLES_NONSYMMETRIC)) ;
fprintf(msgFile, "\n real symmetric : %.0f factor operations",
ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC)) ;
fprintf(msgFile, "\n real nonsymmetric : %.0f factor operations",
ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_NONSYMMETRIC)) ;
fprintf(msgFile, "\n complex symmetric : %.0f factor operations",
ETree_nFactorOps(etree, SPOOLES_COMPLEX, SPOOLES_SYMMETRIC)) ;
fprintf(msgFile, "\n complex nonsymmetric : %.0f factor operations",
ETree_nFactorOps(etree, SPOOLES_COMPLEX, SPOOLES_NONSYMMETRIC));
fsMapIV = ETree_fundSupernodeMap(etree) ;
fsETree = ETree_compress(etree, fsMapIV) ;
fprintf(msgFile, "\n\n fundamental supernode etree") ;
fprintf(msgFile, "\n %d factor indices",
ETree_nFactorIndices(fsETree)) ;
fprintf(msgFile, "\n symmetric: %d factor entries",
ETree_nFactorEntries(fsETree, SPOOLES_SYMMETRIC)) ;
fprintf(msgFile, "\n nonsymmetric: %d factor entries",
ETree_nFactorEntries(fsETree, SPOOLES_NONSYMMETRIC)) ;
fprintf(msgFile, "\n real symmetric : %.0f factor operations",
ETree_nFactorOps(fsETree, SPOOLES_REAL, SPOOLES_SYMMETRIC)) ;
fprintf(msgFile, "\n real nonsymmetric : %.0f factor operations",
ETree_nFactorOps(fsETree, SPOOLES_REAL, SPOOLES_NONSYMMETRIC)) ;
fprintf(msgFile, "\n complex symmetric : %.0f factor operations",
ETree_nFactorOps(fsETree, SPOOLES_COMPLEX, SPOOLES_SYMMETRIC)) ;
fprintf(msgFile, "\n complex nonsymmetric : %.0f factor operations",
ETree_nFactorOps(fsETree, SPOOLES_COMPLEX, SPOOLES_NONSYMMETRIC));
fprintf(msgFile, "\n %.0f factor operations",
ETree_nFactorOps(fsETree, SPOOLES_REAL, SPOOLES_SYMMETRIC)) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(fsETree, msgFile) ;
} else {
ETree_writeStats(fsETree, msgFile) ;
}
fflush(msgFile) ;
/*
--------------------------
write out the ETree object
--------------------------
*/
if ( strcmp(outETreeFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = ETree_writeToFile(fsETree, outETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write etree to file %s",
t2 - t1, outETreeFileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_writeToFile(%p,%s)",
rc, fsETree, outETreeFileName) ;
}
/*
-------------------------------
write out the compids IV object
-------------------------------
*/
if ( strcmp(outIVfileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = IV_writeToFile(fsETree->vtxToFrontIV, outIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write etree to file %s",
t2 - t1, outIVfileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from IV_writeToFile(%p,%s)",
rc, fsETree->vtxToFrontIV, outIVfileName) ;
}
/*
----------------
free the objects
----------------
*/
Graph_free(graph) ;
Perm_free(perm) ;
ETree_free(etree) ;
ETree_free(fsETree) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
(perm) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in perm from file %s",
t2 - t1, inPermFileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from Perm_readFromFile(%p,%s)",
rc, perm, inPermFileName) ;
exit(-1) ;
}
rc = Perm_checkPerm(perm) ;
if ( rc != 1 ) {
fprintf(stderr, "\n fatal error, Perm noETree/drivers/extractTopSep.c 0100644 0002055 0007177 00000011273 06536022672 0017540 0 ustar 00cleve compmath 0000040 0000006 /* extractTopSep.c */
#include "../ETree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------------------------
read in a ETree object, create an IV object with the same size,
mark the vertices in the top level separator(s), write the IV
object to a file
created -- 96may02, cca
---------------------------------------------------------------
*/
{
char *inETreeFileName, *outIVfileName ;
double t1, t2 ;
int msglvl, rc, J, K, ncomp, nfront, nvtx, v ;
int *bndwghts, *compids, *fch, *map, *nodwghts,
*par, *sib, *vtxToFront ;
IV *compidsIV, *mapIV ;
ETree *etree ;
FILE *msgFile ;
Tree *tree ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inETreeFile outIVfile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inETreeFile -- input file, must be *.etreef or *.etreeb"
"\n outIVfile -- output file, must be *.ivf or *.ivb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
outIVfileName = argv[4] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n outIVfile -- %s"
"\n",
argv[0], msglvl, argv[2], inETreeFileName, outIVfileName) ;
fflush(msgFile) ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
fflush(msgFile) ;
nfront = ETree_nfront(etree) ;
nvtx = ETree_nvtx(etree) ;
bndwghts = ETree_bndwghts(etree) ;
vtxToFront = ETree_vtxToFront(etree) ;
nodwghts = ETree_nodwghts(etree) ;
par = ETree_par(etree) ;
fch = ETree_fch(etree) ;
sib = ETree_sib(etree) ;
tree = ETree_tree(etree) ;
/*
-----------------------------------------
create the map from fronts to components,
top level separator(s) are component zero
-----------------------------------------
*/
mapIV = IV_new() ;
IV_init(mapIV, nfront, NULL) ;
map = IV_entries(mapIV) ;
ncomp = 0 ;
for ( J = Tree_preOTfirst(tree) ;
J != -1 ;
J = Tree_preOTnext(tree, J) ) {
if ( (K = par[J]) == -1 ) {
map[J] = 0 ;
} else if ( map[K] != 0 ) {
map[J] = map[K] ;
} else if ( J == fch[K] && sib[J] == -1
&& bndwghts[J] == nodwghts[K] + bndwghts[K] ) {
map[J] = 0 ;
} else {
map[J] = ++ncomp ;
}
}
fprintf(msgFile, "\n\n mapIV object") ;
if ( msglvl > 2 ) {
IV_writeForHumanEye(mapIV, msgFile) ;
} else {
IV_writeStats(mapIV, msgFile) ;
}
/*
----------------------------------------
fill the map from vertices to components
----------------------------------------
*/
compidsIV = IV_new() ;
IV_init(compidsIV, nvtx, NULL) ;
compids = IV_entries(compidsIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
compids[v] = map[vtxToFront[v]] ;
}
fprintf(msgFile, "\n\n compidsIV object") ;
if ( msglvl > 2 ) {
IV_writeForHumanEye(compidsIV, msgFile) ;
} else {
IV_writeStats(compidsIV, msgFile) ;
}
fflush(msgFile) ;
/*
-----------------------
write out the IV object
-----------------------
*/
if ( strcmp(outIVfileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = IV_writeToFile(compidsIV, outIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write etree to file %s",
t2 - t1, outIVfileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from IV_writeToFile(%p,%s)",
rc, compidsIV, outIVfileName) ;
}
/*
----------------
free the objects
----------------
*/
ETree_free(etree) ;
IV_free(mapIV) ;
IV_free(compidsIV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ETree/drivers/mkNDETree.c 0100644 0002055 0007177 00000021673 06616136073 0016516 0 ustar 00cleve compmath 0000040 0000006 /* mkNDETreeNew.c */
#include "../../ETree.h"
#include "../../EGraph.h"
#include "../../misc.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
------------------------------------------------------------
make ETree objects for nested dissection on a regular grid
1 -- vertex elimination tree
2 -- fundamental supernode front tree
3 -- merge only children if possible
4 -- merge all children if possible
5 -- split large non-leaf fronts
created -- 98feb05, cca
------------------------------------------------------------
*/
{
char *outETreeFileName ;
double ops[6] ;
double t1, t2 ;
EGraph *egraph ;
ETree *etree0, *etree1, *etree2, *etree3, *etree4, *etree5 ;
FILE *msgFile ;
Graph *graph ;
int nfronts[6], nfind[6], nzf[6] ;
int maxsize, maxzeros, msglvl, n1, n2, n3, nvtx, rc, v ;
int *newToOld, *oldToNew ;
IV *nzerosIV ;
if ( argc != 9 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile n1 n2 n3 maxzeros maxsize outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n n1 -- number of points in the first direction"
"\n n2 -- number of points in the second direction"
"\n n3 -- number of points in the third direction"
"\n maxzeros -- number of points in the third direction"
"\n maxsize -- maximum number of vertices in a front"
"\n outFile -- output file, must be *.etreef or *.etreeb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
n1 = atoi(argv[3]) ;
n2 = atoi(argv[4]) ;
n3 = atoi(argv[5]) ;
maxzeros = atoi(argv[6]) ;
maxsize = atoi(argv[7]) ;
outETreeFileName = argv[8] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n n1 -- %d"
"\n n2 -- %d"
"\n n3 -- %d"
"\n maxzeros -- %d"
"\n maxsize -- %d"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], n1, n2, n3,
maxzeros, maxsize, outETreeFileName) ;
fflush(msgFile) ;
/*
----------------------------
create the grid graph object
----------------------------
*/
if ( n1 == 1 ) {
egraph = EGraph_make9P(n2, n3, 1) ;
} else if ( n2 == 1 ) {
egraph = EGraph_make9P(n1, n3, 1) ;
} else if ( n3 == 1 ) {
egraph = EGraph_make9P(n1, n2, 1) ;
} else {
egraph = EGraph_make27P(n1, n2, n3, 1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n %d x %d x %d grid EGraph", n1, n2, n3) ;
EGraph_writeForHumanEye(egraph, msgFile) ;
fflush(msgFile) ;
}
graph = EGraph_mkAdjGraph(egraph) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n %d x %d x %d grid Graph", n1, n2, n3) ;
Graph_writeForHumanEye(graph, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------
get the nested dissection ordering
----------------------------------
*/
nvtx = n1*n2*n3 ;
newToOld = IVinit(nvtx, -1) ;
oldToNew = IVinit(nvtx, -1) ;
mkNDperm(n1, n2, n3, newToOld, 0, n1-1, 0, n2-1, 0, n3-1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
oldToNew[newToOld[v]] = v ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n %d x %d x %d nd ordering", n1, n2, n3) ;
IVfprintf(msgFile, nvtx, oldToNew) ;
fflush(msgFile) ;
}
/*
------------------------------------------
create the vertex elimination ETree object
------------------------------------------
*/
etree0 = ETree_new() ;
ETree_initFromGraphWithPerms(etree0, graph, newToOld, oldToNew) ;
nfronts[0] = ETree_nfront(etree0) ;
nfind[0] = ETree_nFactorIndices(etree0) ;
nzf[0] = ETree_nFactorEntries(etree0, SPOOLES_SYMMETRIC) ;
ops[0] = ETree_nFactorOps(etree0, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n vtx tree : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[0], nfind[0], nzf[0], ops[0]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n vertex elimination tree") ;
ETree_writeForHumanEye(etree0, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------------------------
create the fundamental supernode ETree object
---------------------------------------------
*/
nzerosIV = IV_new() ;
IV_init(nzerosIV, nvtx, NULL) ;
IV_fill(nzerosIV, 0) ;
etree1 = ETree_mergeFrontsOne(etree0, 0, nzerosIV) ;
nfronts[1] = ETree_nfront(etree1) ;
nfind[1] = ETree_nFactorIndices(etree1) ;
nzf[1] = ETree_nFactorEntries(etree1, SPOOLES_SYMMETRIC) ;
ops[1] = ETree_nFactorOps(etree1, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n fs tree : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[1], nfind[1], nzf[1], ops[1]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n fundamental supernode front tree") ;
ETree_writeForHumanEye(etree1, msgFile) ;
fprintf(msgFile, "\n\n nzerosIV") ;
IV_writeForHumanEye(nzerosIV, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
try to absorb only children
---------------------------
*/
etree2 = ETree_mergeFrontsOne(etree1, maxzeros, nzerosIV) ;
nfronts[2] = ETree_nfront(etree2) ;
nfind[2] = ETree_nFactorIndices(etree2) ;
nzf[2] = ETree_nFactorEntries(etree2, SPOOLES_SYMMETRIC) ;
ops[2] = ETree_nFactorOps(etree2, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n merge one : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[2], nfind[2], nzf[2], ops[2]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after mergeOne") ;
ETree_writeForHumanEye(etree2, msgFile) ;
fprintf(msgFile, "\n\n nzerosIV") ;
IV_writeForHumanEye(nzerosIV, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------
try to absorb all children
--------------------------
*/
etree3 = ETree_mergeFrontsAll(etree2, maxzeros, nzerosIV) ;
nfronts[3] = ETree_nfront(etree3) ;
nfind[3] = ETree_nFactorIndices(etree3) ;
nzf[3] = ETree_nFactorEntries(etree3, SPOOLES_SYMMETRIC) ;
ops[3] = ETree_nFactorOps(etree3, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n merge all : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[3], nfind[3], nzf[3], ops[3]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after mergeAll") ;
ETree_writeForHumanEye(etree3, msgFile) ;
fprintf(msgFile, "\n\n nzerosIV") ;
IV_writeForHumanEye(nzerosIV, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------------
try to absorb any other children
--------------------------------
*/
etree4 = etree3 ;
/*
etree4 = ETree_mergeFrontsAny(etree3, maxzeros, nzerosIV) ;
nfronts[4] = ETree_nfront(etree4) ;
nfind[4] = ETree_nFactorIndices(etree4) ;
nzf[4] = ETree_nFactorEntries(etree4, SPOOLES_SYMMETRIC) ;
ops[4] = ETree_nFactorOps(etree4, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n merge any : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[4], nfind[4], nzf[4], ops[4]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after mergeAny") ;
ETree_writeForHumanEye(etree3, msgFile) ;
fprintf(msgFile, "\n\n nzerosIV") ;
IV_writeForHumanEye(nzerosIV, msgFile) ;
fflush(msgFile) ;
}
*/
/*
--------------------
split the front tree
--------------------
*/
etree5 = ETree_splitFronts(etree4, NULL, maxsize, 0) ;
nfronts[5] = ETree_nfront(etree5) ;
nfind[5] = ETree_nFactorIndices(etree5) ;
nzf[5] = ETree_nFactorEntries(etree5, SPOOLES_SYMMETRIC) ;
ops[5] = ETree_nFactorOps(etree5, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n split : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[5], nfind[5], nzf[5], ops[5]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after split") ;
ETree_writeForHumanEye(etree4, msgFile) ;
fflush(msgFile) ;
}
fprintf(msgFile, "\n\n complex symmetric ops %.0f",
ETree_nFactorOps(etree5, SPOOLES_COMPLEX, SPOOLES_SYMMETRIC)) ;
/*
--------------------------
write out the ETree object
--------------------------
*/
if ( strcmp(outETreeFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = ETree_writeToFile(etree5, outETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write etree to file %s",
t2 - t1, outETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from ETree_writeToFile(%p,%s)",
rc, etree5, outETreeFileName) ;
}
}
/*
----------------
free the objects
----------------
*/
ETree_free(etree0) ;
ETree_free(etree1) ;
ETree_free(etree2) ;
ETree_free(etree3) ;
/*
ETree_free(etree4) ;
*/
ETree_free(etree5) ;
EGraph_free(egraph) ;
Graph_free(graph) ;
IVfree(newToOld) ;
IVfree(oldToNew) ;
IV_free(nzerosIV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ETree/drivers/mkNDoutput.c 0100644 0002055 0007177 00000026061 06542224412 0017037 0 ustar 00cleve compmath 0000040 0000006 /* mkNDoutput.c */
#include "../../ETree.h"
#include "../../SymbFac.h"
#include "../../EGraph.h"
#include "../../misc.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------------------------
create
(1) an ETree object for nested dissection on a regular grid
using a bound on zeros in a front and a bound on front size
(2) an IV object that maps fronts to threads using a wrap map,
a balanced map, a subtree-subset map, or a domain
decomposition map
created -- 98feb05, cca
---------------------------------------------------------------
*/
{
char *outETreeFileName, *outMapIVfileName ;
double cutoff, t1, t2 ;
double ops[5] ;
DV *cumopsDV ;
int maptype, maxsize, maxzeros, msglvl, n1, n2, n3, nthread, nvtx,
rc, v ;
int nfind[5], nfronts[5], nzf[5] ;
int *newToOld, *oldToNew ;
IV *msIV, *nzerosIV, *ownersIV ;
IVL *symbfacIVL ;
EGraph *egraph ;
ETree *etree0, *etree1, *etree2, *etree3, *etree4 ;
FILE *msgFile ;
Graph *graph ;
if ( argc != 13 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile n1 n2 n3 maxzeros maxsize "
"\n nthread maptype cutoff etreeFile mapFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n n1 -- number of points in the first direction"
"\n n2 -- number of points in the second direction"
"\n n3 -- number of points in the third direction"
"\n maxzeros -- number of points in the third direction"
"\n maxsize -- maximum number of vertices in a front"
"\n nthread -- number of threads"
"\n maptype -- map type"
"\n 1 -- wrap map"
"\n 2 -- balanced map"
"\n 3 -- subtree-subset map"
"\n 4 -- domain decomposition map"
"\n cutoff -- cutoff for domain size w.r.t. # vertices"
"\n used only for the domain decomposition map"
"\n etreeFile -- output file, must be *.etreef or *.etreeb"
"\n mapFile -- output file, must be *.ivf or *.ivb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
n1 = atoi(argv[3]) ;
n2 = atoi(argv[4]) ;
n3 = atoi(argv[5]) ;
maxzeros = atoi(argv[6]) ;
maxsize = atoi(argv[7]) ;
nthread = atoi(argv[8]) ;
maptype = atof(argv[9]) ;
cutoff = atof(argv[10]) ;
outETreeFileName = argv[11] ;
outMapIVfileName = argv[12] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n n1 -- %d"
"\n n2 -- %d"
"\n n3 -- %d"
"\n maxzeros -- %d"
"\n maxsize -- %d"
"\n nthread -- %d"
"\n maptype -- %d"
"\n cutoff -- %f"
"\n etreeFile -- %s"
"\n mapFile -- %s"
"\n",
argv[0], msglvl, argv[2], n1, n2, n3,
maxzeros, maxsize, nthread, maptype, cutoff,
outETreeFileName, outMapIVfileName) ;
fflush(msgFile) ;
if ( maptype < 0 || maptype > 4 ) {
fprintf(stderr, "\n fatal error, maptype = %d, use "
"\n 1 -- wrap map"
"\n 2 -- balanced map"
"\n 3 -- subtree-subset map"
"\n 4 -- domain decomposition map\n", maptype) ;
exit(-1) ;
}
/*
----------------------------
create the grid graph object
----------------------------
*/
if ( n3 == 1 ) {
egraph = EGraph_make9P(n1, n2, 1) ;
} else {
egraph = EGraph_make27P(n1, n2, n3, 1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n %d x %d x %d grid EGraph", n1, n2, n3) ;
EGraph_writeForHumanEye(egraph, msgFile) ;
fflush(msgFile) ;
}
graph = EGraph_mkAdjGraph(egraph) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n %d x %d x %d grid Graph", n1, n2, n3) ;
Graph_writeForHumanEye(graph, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------
get the nested dissection ordering
----------------------------------
*/
nvtx = n1*n2*n3 ;
newToOld = IVinit(nvtx, -1) ;
oldToNew = IVinit(nvtx, -1) ;
mkNDperm(n1, n2, n3, newToOld, 0, n1-1, 0, n2-1, 0, n3-1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
oldToNew[newToOld[v]] = v ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n %d x %d x %d nd ordering", n1, n2, n3) ;
IVfprintf(msgFile, nvtx, oldToNew) ;
fflush(msgFile) ;
}
/*
---------------------------------------------
create the fundamental supernode ETree object
---------------------------------------------
*/
nzerosIV = IV_new() ;
IV_init(nzerosIV, nvtx, NULL) ;
IV_fill(nzerosIV, 0) ;
etree0 = ETree_new() ;
ETree_initFromGraphWithPerms(etree0, graph, newToOld, oldToNew) ;
etree1 = ETree_mergeFrontsOne(etree0, 0, nzerosIV) ;
nfronts[0] = ETree_nfront(etree1) ;
nfind[0] = ETree_nFactorIndices(etree1) ;
nzf[0] = ETree_nFactorEntries(etree1, SPOOLES_SYMMETRIC) ;
ops[0] = ETree_nFactorOps(etree1, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n\n fs tree : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[0], nfind[0], nzf[0], ops[0]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n fundamental elimination tree") ;
ETree_writeForHumanEye(etree1, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------------------
first step: try to absorb an only child
---------------------------------------
*/
etree2 = ETree_mergeFrontsOne(etree1, maxzeros, nzerosIV) ;
nfronts[1] = ETree_nfront(etree2) ;
nfind[1] = ETree_nFactorIndices(etree2) ;
nzf[1] = ETree_nFactorEntries(etree2, SPOOLES_SYMMETRIC) ;
ops[1] = ETree_nFactorOps(etree2, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n merge 1 : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[1], nfind[1], nzf[1], ops[1]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after first merge") ;
ETree_writeForHumanEye(etree2, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------------------
second step: try to absorb all children
---------------------------------------
*/
etree3 = ETree_mergeFrontsAll(etree2, maxzeros, nzerosIV) ;
nfronts[2] = ETree_nfront(etree3) ;
nfind[2] = ETree_nFactorIndices(etree3) ;
nzf[2] = ETree_nFactorEntries(etree3, SPOOLES_SYMMETRIC) ;
ops[2] = ETree_nFactorOps(etree3, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n merge 2 : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[2], nfind[2], nzf[2], ops[2]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after second merge") ;
ETree_writeForHumanEye(etree3, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------------
third step: split the front tree
--------------------------------
*/
etree4 = ETree_splitFronts(etree3, NULL, maxsize, 0) ;
nfronts[3] = ETree_nfront(etree4) ;
nfind[3] = ETree_nFactorIndices(etree4) ;
nzf[3] = ETree_nFactorEntries(etree4, SPOOLES_SYMMETRIC) ;
ops[3] = ETree_nFactorOps(etree4, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n split : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[3], nfind[3], nzf[3], ops[3]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after split") ;
ETree_writeForHumanEye(etree4, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------------
create the symbolic factorization object
----------------------------------------
*/
symbfacIVL = SymbFac_initFromGraph(etree4, graph) ;
nfronts[4] = ETree_nfront(etree4) ;
nfind[4] = ETree_nFactorIndices(etree4) ;
nzf[4] = ETree_nFactorEntries(etree4, SPOOLES_SYMMETRIC) ;
ops[4] = ETree_nFactorOps(etree4, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n final : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[4], nfind[4], nzf[4], ops[4]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n after symbolic factorization") ;
ETree_writeForHumanEye(etree4, msgFile) ;
fprintf(msgFile, "\n\n after symbolic factorization") ;
IVL_writeForHumanEye(symbfacIVL, msgFile) ;
}
/*
--------------------------
write out the ETree object
--------------------------
*/
if ( strcmp(outETreeFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = ETree_writeToFile(etree4, outETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write etree to file %s",
t2 - t1, outETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from ETree_writeToFile(%p,%s)",
rc, etree4, outETreeFileName) ;
}
}
/*
----------------------------
get the owners map IV object
----------------------------
*/
cumopsDV = DV_new() ;
DV_init(cumopsDV, nthread, NULL) ;
DV_fill(cumopsDV, 0.0) ;
switch ( maptype ) {
case 1 : /* wrap map */
ownersIV = ETree_wrapMap(etree4, SPOOLES_REAL,
SPOOLES_SYMMETRIC, cumopsDV) ;
break ;
case 2 : /* balanced map */
ownersIV = ETree_balancedMap(etree4, SPOOLES_REAL,
SPOOLES_SYMMETRIC, cumopsDV) ;
break ;
case 3 : /* subtree-subset map */
ownersIV = ETree_subtreeSubsetMap(etree4, SPOOLES_REAL,
SPOOLES_SYMMETRIC, cumopsDV) ;
break ;
case 4 : /* dd map */
msIV = ETree_msByNvtxCutoff(etree4, cutoff) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n multisector IV object") ;
IV_writeForHumanEye(msIV, msgFile) ;
fflush(msgFile) ;
}
ownersIV = ETree_ddMapNew(etree4, SPOOLES_REAL,
SPOOLES_SYMMETRIC, msIV, cumopsDV) ;
IV_free(msIV) ;
break ;
}
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n totalOps = %.0f", DV_sum(cumopsDV)) ;
DVscale(DV_size(cumopsDV), DV_entries(cumopsDV),
nthread/DV_sum(cumopsDV)) ;
fprintf(msgFile, "\n\n cumopsDV") ;
DV_writeForHumanEye(cumopsDV, msgFile) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n ownersIV") ;
IV_writeForHumanEye(ownersIV, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
write out the map IV object
---------------------------
*/
if ( strcmp(outMapIVfileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = IV_writeToFile(ownersIV, outMapIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write owners map to file %s",
t2 - t1, outMapIVfileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from IV_writeToFile(%p,%s)",
rc, ownersIV, outMapIVfileName) ;
}
}
/*
----------------
free the objects
----------------
*/
ETree_free(etree0) ;
ETree_free(etree1) ;
ETree_free(etree2) ;
ETree_free(etree3) ;
ETree_free(etree4) ;
EGraph_free(egraph) ;
Graph_free(graph) ;
IVfree(newToOld) ;
IVfree(oldToNew) ;
IV_free(nzerosIV) ;
IV_free(ownersIV) ;
IVL_free(symbfacIVL) ;
DV_free(cumopsDV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
;
ETree *etree0, *etree1, *etree2, *etree3, *etree4 ;
FILE *msgFile ;
Graph *graph ;
if ( argc != 13 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile n1 n2 n3 maxzeros maxsize "
"\n nthread maptype cutoff etreeFile mapFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n n1 -- number of points in the first direction"
"\n n2 -- number of points in the secETree/drivers/permuteETree.c 0100644 0002055 0007177 00000014211 06536034612 0017331 0 ustar 00cleve compmath 0000040 0000006 /* permuteETree.c */
#include "../ETree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-----------------------------------------------------------
read in an ETree object.
if the ETree is defined on a compressed graph
read in an equivalence map IV object.
expand the ETree to be defined on the unit weight graph.
endif
get the old-to-new vertex permutation.
permute the vtx-to-front map.
created -- 97feb28, cca
-----------------------------------------------------------
*/
{
char *inEqmapIVfileName, *inETreeFileName, *outETreeFileName,
*outIVfileName ;
double t1, t2 ;
int msglvl, rc ;
IV *eqmapIV, *vtxOldToNewIV ;
ETree *etree, *etree2 ;
FILE *msgFile ;
if ( argc != 7 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inETreeFile inEqmapFile "
"\n outETreeFile outIVfile "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inETreeFile -- input file, must be *.etreef or *.etreeb"
"\n inEqmapFile -- input file, must be *.ivf or *.ivb"
"\n outETreeFile -- output file, must be *.etreef or *.etreeb"
"\n outIVfile -- output file for oldToNew vector,"
"\n must be *.ivf or *.ivb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
inEqmapIVfileName = argv[4] ;
outETreeFileName = argv[5] ;
outIVfileName = argv[6] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n inEqmapFile -- %s"
"\n outETreeFile -- %s"
"\n outIVfile -- %s"
"\n",
argv[0], msglvl, argv[2], inETreeFileName, inEqmapIVfileName,
outETreeFileName, outIVfileName) ;
fflush(msgFile) ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
ETree_leftJustify(etree) ;
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
fflush(msgFile) ;
if ( strcmp(inEqmapIVfileName, "none") != 0 ) {
/*
-------------------------------------
read in the equivalence map IV object
-------------------------------------
*/
eqmapIV = IV_new() ;
MARKTIME(t1) ;
rc = IV_readFromFile(eqmapIV, inEqmapIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in eqmapIV from file %s",
t2 - t1, inEqmapIVfileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from IV_readFromFile(%p,%s)",
rc, eqmapIV, inEqmapIVfileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading IV object from file %s",
inEqmapIVfileName) ;
if ( msglvl > 2 ) {
IV_writeForHumanEye(eqmapIV, msgFile) ;
} else {
IV_writeStats(eqmapIV, msgFile) ;
}
fflush(msgFile) ;
/*
---------------------
expand the front tree
---------------------
*/
MARKTIME(t1) ;
etree2 = ETree_expand(etree, eqmapIV) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %9.5f : expand the ETree", t2 - t1) ;
fprintf(msgFile, "\n\n expanded ETree") ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree2, msgFile) ;
} else {
ETree_writeStats(etree2, msgFile) ;
}
/*
------------------------------------------------
free the old ETree object and the eqmapIV object
------------------------------------------------
*/
ETree_free(etree) ;
etree = etree2 ;
etree2 = NULL ;
IV_free(eqmapIV) ;
}
/*
-----------------------------
get the permutation IV object
-----------------------------
*/
MARKTIME(t1) ;
vtxOldToNewIV = ETree_oldToNewVtxPerm(etree) ;
MARKTIME(t2) ;
fprintf(msgFile,
"\n\n CPU %9.5f : get the old-to-new permutation", t2 - t1) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n vertex old-to-new IV object") ;
IV_writeForHumanEye(vtxOldToNewIV, msgFile) ;
} else {
fprintf(msgFile, "\n\n vertex old-to-new IV object") ;
IV_writeStats(vtxOldToNewIV, msgFile) ;
}
fflush(msgFile) ;
/*
------------------------------------------------
overwrite the ETree object with the new ordering
------------------------------------------------
*/
ETree_permuteVertices(etree, vtxOldToNewIV) ;
fprintf(msgFile, "\n\n after permuting the vertices") ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
/*
-------------------------------------
optionally write out the ETree object
-------------------------------------
*/
if ( strcmp(outETreeFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = ETree_writeToFile(etree, outETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write etree to file %s",
t2 - t1, outETreeFileName) ;
}
/*
----------------------------------
optionally write out the IV object
----------------------------------
*/
if ( strcmp(outIVfileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = IV_writeToFile(vtxOldToNewIV, outIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write vtxOldToNewIV to file %s",
t2 - t1, outIVfileName) ;
}
/*
----------------
free the objects
----------------
*/
ETree_free(etree) ;
IV_free(vtxOldToNewIV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ETree/drivers/testExpand.c 0100644 0002055 0007177 00000010430 06574276013 0017046 0 ustar 00cleve compmath 0000040 0000006 /* testExpand.c */
#include "../ETree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------------
read in an ETree object and an equivalence map,
expand the ETree object and optionally write to a file.
created -- 98sep05, cca
-------------------------------------------------------
*/
{
char *inEqmapFileName, *inETreeFileName, *outETreeFileName ;
double t1, t2 ;
ETree *etree, *etree2 ;
FILE *msgFile ;
int msglvl, rc ;
IV *eqmapIV ;
if ( argc != 6 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inETreeFile inEqmapFile outETreeFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inETreeFile -- input file, must be *.etreef or *.etreeb"
"\n inEqmapFile -- input file, must be *.ivf or *.ivb"
"\n outETreeFile -- output file, must be *.etreef or *.etreeb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
inEqmapFileName = argv[4] ;
outETreeFileName = argv[5] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n inEqmapFile -- %s"
"\n outETreeFile -- %s"
"\n",
argv[0], msglvl, argv[2],
inETreeFileName, inEqmapFileName, outETreeFileName) ;
fflush(msgFile) ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
fflush(msgFile) ;
/*
-------------------------------------
read in the equivalence map IV object
-------------------------------------
*/
if ( strcmp(inEqmapFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
eqmapIV = IV_new() ;
MARKTIME(t1) ;
rc = IV_readFromFile(eqmapIV, inEqmapFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in eqmapIV from file %s",
t2 - t1, inEqmapFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from IV_readFromFile(%p,%s)",
rc, eqmapIV, inEqmapFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading IV object from file %s",
inEqmapFileName) ;
if ( msglvl > 2 ) {
IV_writeForHumanEye(eqmapIV, msgFile) ;
} else {
IV_writeStats(eqmapIV, msgFile) ;
}
fflush(msgFile) ;
/*
-----------------------
expand the ETree object
-----------------------
*/
etree2 = ETree_expand(etree, eqmapIV) ;
fprintf(msgFile, "\n\n after expanding the ETree object") ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree2, msgFile) ;
} else {
ETree_writeStats(etree2, msgFile) ;
}
fflush(msgFile) ;
/*
--------------------------
write out the ETree object
--------------------------
*/
if ( strcmp(outETreeFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = ETree_writeToFile(etree2, outETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write etree to file %s",
t2 - t1, outETreeFileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_writeToFile(%p,%s)",
rc, etree2, outETreeFileName) ;
}
/*
---------------------
free the ETree object
---------------------
*/
ETree_free(etree) ;
IV_free(eqmapIV) ;
ETree_free(etree2) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ETree/drivers/testFS.c 0100644 0002055 0007177 00000017435 06652457163 0016157 0 ustar 00cleve compmath 0000040 0000006 /* testFS.c */
#include "../../ETree.h"
#include "../../SymbFac.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------------
read in an ETree object. compute the heights of the nodes
in the tree w.r.t. an out-of-core forward sparse factorization.
draw the tree.
created -- 99jan07, cca
-------------------------------------------------------
*/
{
char *firstEPSfilename, *inETreeFileName, *secondEPSfilename ;
double nfops1, radius, t1, t2 ;
double *x, *y ;
double bbox[4], bounds[4], frame[4] ;
DV *xDV, *yDV ;
IV *dmetricIV, *hmetricIV, *vmetricIV ;
int bndJ, J, K, labelflag, maxdepth, maxnent, msglvl,
nfent1, nfind1, nfront, nleaves1, nnode1, rc ;
int *bndwghts, *depths, *heights, *nzfs, *par ;
ETree *etree ;
FILE *msgFile ;
Tree *tree ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inETreeFile labelflag radius"
"\n firstEPSfileName secondEPSfileName"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inETreeFile -- input file, must be *.etreef or *.etreeb"
"\n labelflag -- flag to draw labels"
"\n radius -- radius of node"
"\n firstEPSfilename -- EPS file for subtree working storage"
"\n secondEPSfilename -- EPS file for node working storage"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
labelflag = atoi(argv[4]) ;
radius = atof(argv[5]) ;
firstEPSfilename = argv[6] ;
secondEPSfilename = argv[7] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n firstEPSfilename -- %s"
"\n labelflag -- %d"
"\n radius -- %f"
"\n",
argv[0], msglvl, argv[2], inETreeFileName, firstEPSfilename,
labelflag, radius) ;
fflush(msgFile) ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
ETree_leftJustify(etree) ;
fprintf(msgFile, "\n\n %d LU entries", ETree_nFactorEntries(etree, 2)) ;
fflush(msgFile) ;
/*
----------------------
compute the statistics
----------------------
*/
tree = etree->tree ;
nfront = etree->nfront ;
nnode1 = etree->tree->n ;
nfind1 = ETree_nFactorIndices(etree) ;
nfent1 = ETree_nFactorEntries(etree, 1) ;
nfops1 = ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
nleaves1 = Tree_nleaves(etree->tree) ;
fprintf(msgFile, "\n root front %d has %d vertices",
etree->tree->root,
etree->nodwghtsIV->vec[etree->tree->root]) ;
fprintf(msgFile, "\n %d fronts, %d indices, %d entries, %.0f ops",
nfront, nfind1, nfent1, nfops1) ;
fprintf(msgFile, "\n max front size = %d",
IV_max(ETree_nodwghtsIV(etree))) ;
fprintf(msgFile, "\n max boundary size = %d",
IV_max(ETree_bndwghtsIV(etree))) ;
/*
------------------------------
get the # of entries per front
------------------------------
*/
vmetricIV = ETree_factorEntriesIV(etree, SPOOLES_SYMMETRIC) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n entries per front") ;
IV_writeForHumanEye(vmetricIV, msgFile) ;
fflush(msgFile) ;
}
maxnent = IV_max(vmetricIV) ;
fprintf(msgFile, "\n\n max entries per front = %d", maxnent) ;
fflush(msgFile) ;
/*
--------------------------------
get the simple (x,y) coordinates
--------------------------------
*/
xDV = DV_new() ;
yDV = DV_new() ;
rc = Tree_getSimpleCoords(tree, 'H', 'C', xDV, yDV) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in %s",
"\n return value %d from Tree_getSimpleCoords()\n",
argv[0], rc) ;
exit(-1) ;
}
x = DV_entries(xDV) ;
y = DV_entries(yDV) ;
/*
----------------------
get the height profile
----------------------
*/
hmetricIV = Tree_setHeightImetric(tree, vmetricIV) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n entries height per front") ;
IV_writeForHumanEye(hmetricIV, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------------------------------
compute y[J] = heights[J] + |bndJ|*(|bndJ|+1)/2
-----------------------------------------------
*/
heights = IV_entries(hmetricIV) ;
bndwghts = ETree_bndwghts(etree) ;
for ( J = 0 ; J < nfront ; J++ ) {
bndJ = bndwghts[J] ;
y[J] = heights[J] + (bndJ*(bndJ+1))/2 ;
}
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n J x y") ;
for ( J = 0 ; J < nfront ; J++ ) {
fprintf(msgFile, "\n %5d %12.3f %12.0f", J, x[J], y[J]) ;
}
}
/*
------------------
compute the bounds
------------------
*/
bounds[0] = 0.0 ;
bounds[1] = 0.0 ;
bounds[2] = DV_max(xDV) ;
bounds[3] = DV_max(yDV) ;
fprintf(stdout, "\n\n bounds = [ %.3g %.3g %.3g %.3g ] ",
bounds[0], bounds[1], bounds[2], bounds[3]) ;
/*
-------------
draw the tree
-------------
*/
bbox[0] = 50.0 ;
bbox[1] = 50.0 ;
bbox[2] = 500.0 ;
bbox[3] = 500.0 ;
frame[0] = bbox[0] + 10 ;
frame[1] = bbox[1] + 10 ;
frame[2] = bbox[2] - 10 ;
frame[3] = bbox[3] - 10 ;
rc = Tree_drawToEPS(tree, firstEPSfilename, xDV, yDV, radius, NULL,
labelflag, radius, NULL, bbox, frame, bounds) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in %s"
"\n return value %d from Tree_drawToEPS()\n",
argv[0], rc) ;
exit(-1) ;
}
/*
---------------------
get the depth profile
---------------------
*/
dmetricIV = Tree_setDepthImetric(tree, vmetricIV) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n entries depth per front") ;
IV_writeForHumanEye(dmetricIV, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------------
compute y[J] = depths[par(J)] + nfent[J]
----------------------------------------
*/
par = Tree_par(tree) ;
depths = IV_entries(dmetricIV) ;
nzfs = IV_entries(vmetricIV) ;
for ( J = 0 ; J < nfront ; J++ ) {
y[J] = nzfs[J] ;
if ( (K = par[J]) != -1 ) {
y[J] += depths[K] ;
}
}
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n J x y") ;
for ( J = 0 ; J < nfront ; J++ ) {
fprintf(msgFile, "\n %5d %12.3f %12.0f", J, x[J], y[J]) ;
}
}
/*
-------------
draw the tree
-------------
*/
bbox[0] = 50.0 ;
bbox[1] = 50.0 ;
bbox[2] = 500.0 ;
bbox[3] = 500.0 ;
frame[0] = bbox[0] + 10 ;
frame[1] = bbox[1] + 10 ;
frame[2] = bbox[2] - 10 ;
frame[3] = bbox[3] - 10 ;
rc = Tree_drawToEPS(tree, secondEPSfilename, xDV, yDV, radius, NULL,
labelflag, radius, NULL, bbox, frame, bounds) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in %s"
"\n return value %d from Tree_drawToEPSfile()\n",
argv[0], rc) ;
exit(-1) ;
}
/*
----------------
free the objects
----------------
*/
ETree_free(etree) ;
IV_free(vmetricIV) ;
IV_free(hmetricIV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
nfent1, nfind1, nfront, nleaves1, nnode1, rc ;
int *bndwghts, *depths, *heights, *nzfs, *par ;
ETree *etree ;
FILE *msgFile ;
Tree *tree ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglETree/drivers/testHeight.c 0100644 0002055 0007177 00000011507 06645206355 0017046 0 ustar 00cleve compmath 0000040 0000006 /* testHeight.c */
#include "../../ETree.h"
#include "../../SymbFac.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------------
read in an ETree object. compute the height of the tree
w.r.t. an out-of-core forward sparse factorization
created -- 99jan07, cca
-------------------------------------------------------
*/
{
char *inETreeFileName ;
double nfops1, t1, t2 ;
IV *dmetricIV, *vmetricIV ;
int maxdepth, maxnent, msglvl, nfent1, nfind1,
nfront, nleaves1, nnode1, rc ;
ETree *etree ;
FILE *msgFile ;
Tree *tree ;
if ( argc != 4 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inETreeFile "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inETreeFile -- input file, must be *.etreef or *.etreeb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n",
argv[0], msglvl, argv[2], inETreeFileName) ;
fflush(msgFile) ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
ETree_leftJustify(etree) ;
fprintf(msgFile, "\n\n %d LU entries", ETree_nFactorEntries(etree, 2)) ;
fflush(msgFile) ;
/*
----------------------
compute the statistics
----------------------
*/
tree = etree->tree ;
nfront = etree->nfront ;
nnode1 = etree->tree->n ;
nfind1 = ETree_nFactorIndices(etree) ;
nfent1 = ETree_nFactorEntries(etree, 1) ;
nfops1 = ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
nleaves1 = Tree_nleaves(etree->tree) ;
fprintf(msgFile, "\n root front %d has %d vertices",
etree->tree->root,
etree->nodwghtsIV->vec[etree->tree->root]) ;
fprintf(msgFile, "\n %d fronts, %d indices, %d entries, %.0f ops",
nfront, nfind1, nfent1, nfops1) ;
fprintf(msgFile, "\n max front size = %d",
IV_max(ETree_nodwghtsIV(etree))) ;
fprintf(msgFile, "\n max boundary size = %d",
IV_max(ETree_bndwghtsIV(etree))) ;
/*
------------------------------
get the # of entries per front
------------------------------
*/
vmetricIV = ETree_factorEntriesIV(etree, SPOOLES_SYMMETRIC) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n entries per front") ;
IV_writeForHumanEye(vmetricIV, msgFile) ;
fflush(msgFile) ;
}
maxnent = IV_max(vmetricIV) ;
fprintf(msgFile, "\n\n max entries per front = %d", maxnent) ;
fflush(msgFile) ;
/*
----------------------
get the height profile
----------------------
*/
dmetricIV = Tree_setDepthImetric(tree, vmetricIV) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n entries depth per front") ;
IV_writeForHumanEye(dmetricIV, msgFile) ;
fflush(msgFile) ;
}
maxdepth = IV_max(dmetricIV) ;
fprintf(msgFile, "\n\n max depth = %d, fraction of total = %8.3f",
maxdepth, ((double) maxdepth)/nfent1) ;
fflush(msgFile) ;
fprintf(msgFile, "\n\n STATS : %12d %12d %12d %8.3f %8.3f",
nfent1, maxnent, maxdepth, ((double) maxdepth)/maxnent,
((double) maxdepth)/nfent1) ;
{
int J ;
int *depth = IV_entries(dmetricIV) ;
int *par = Tree_par(tree) ;
int *fch = Tree_fch(tree) ;
int *sib = Tree_sib(tree) ;
int *nodwghts = ETree_nodwghts(etree) ;
int *bndwghts = ETree_bndwghts(etree) ;
fprintf(msgFile, "\n\n J par fch sib |J| |bndJ| depth/maxdepth") ;
for ( J = 0 ; J < nfront ; J++ ) {
fprintf(msgFile, "\n %7d %7d %7d %7d %7d %7d %8.3f",
J, par[J], fch[J], sib[J], nodwghts[J], bndwghts[J],
((double) depth[J])/maxdepth) ;
}
}
/*
----------------
free the objects
----------------
*/
ETree_free(etree) ;
IV_free(vmetricIV) ;
IV_free(dmetricIV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ETree/drivers/testIO.c 0100644 0002055 0007177 00000006012 06632074507 0016136 0 ustar 00cleve compmath 0000040 0000006 /* testIO.c */
#include "../ETree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------
test ETree_readFromFile and ETree_writeToFile,
useful for translating between formatted *.etreef
and binary *.etreeb files.
created -- 96may02, cca
-------------------------------------------------
*/
{
char *inETreeFileName, *outETreeFileName ;
double t1, t2 ;
int msglvl, rc ;
ETree *etree ;
FILE *msgFile ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.etreef or *.etreeb"
"\n outFile -- output file, must be *.etreef or *.etreeb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
outETreeFileName = argv[4] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], inETreeFileName, outETreeFileName) ;
fflush(msgFile) ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
fflush(msgFile) ;
{
IV *oldToNewIV = ETree_oldToNewVtxPerm(etree) ;
IV_writeForHumanEye(oldToNewIV, msgFile) ;
}
/*
--------------------------
write out the ETree object
--------------------------
*/
if ( strcmp(outETreeFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = ETree_writeToFile(etree, outETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write etree to file %s",
t2 - t1, outETreeFileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_writeToFile(%p,%s)",
rc, etree, outETreeFileName) ;
}
/*
---------------------
free the ETree object
---------------------
*/
ETree_free(etree) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
.c */
#include "../ETree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------
test ETree_readFromFile and ETree_writeToFile,
useful for translating between formatted *.etreef
and binary *.etreeb files.
created -- 96may02, cca
-------------------------------------------------
*/
{
char *inETreeFileName, *outETreeFileName ;
double t1, ETree/drivers/testMS.c 0100644 0002055 0007177 00000014441 06536051661 0016152 0 ustar 00cleve compmath 0000040 0000006 /* testMS.c */
#include "../ETree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-----------------------
generate multisectors
created -- 96oct31, cca
-----------------------
*/
{
char *inETreeFileName, *outIVfileName ;
double cutoff, domops, totops, t1, t2 ;
double *opsreg ;
DV *opsDV ;
int domnzf, domnvtx, flag, depth, ireg, msglvl, nreg, rc,
totnvtx, totnzf ;
int *nvtxreg, *nzfreg ;
IV *msIV, *nvtxIV, *nzfIV ;
ETree *etree ;
FILE *msgFile ;
if ( argc != 7 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inETreeFile outIVfile flag cutoff"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inETreeFile -- input file, must be *.etreef or *.etreeb"
"\n outIVfile -- output file, must be *.ivf or *.ivb"
"\n flag -- type of multisector"
"\n flag = 1 --> multisector via depth of front"
"\n flag = 2 --> multisector via # of vertices in subtree"
"\n flag = 3 --> multisector via # of entries in subtree"
"\n flag = 4 --> multisector via # of operations in subtree"
"\n cutoff -- cutoff point for multisector"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
outIVfileName = argv[4] ;
flag = atoi(argv[5]) ;
if ( flag == 1 ) {
depth = atoi(argv[6]) ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n outIVfile -- %s"
"\n flag -- %d"
"\n depth -- %d"
"\n",
argv[0], msglvl, argv[2], inETreeFileName, outIVfileName,
flag, depth) ;
fflush(msgFile) ;
} else if ( 2 <= flag && flag <= 4 ) {
cutoff = atof(argv[6]) ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n outIVfile -- %s"
"\n flag -- %d"
"\n cutoff -- %f"
"\n",
argv[0], msglvl, argv[2], inETreeFileName, outIVfileName,
flag, cutoff) ;
fflush(msgFile) ;
}
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
fflush(msgFile) ;
/*
--------------------
make the multisector
--------------------
*/
switch ( flag ) {
case 1 :
msIV = ETree_msByDepth(etree, depth) ;
break ;
case 2 :
msIV = ETree_msByNvtxCutoff(etree, cutoff) ;
break ;
case 3 :
msIV = ETree_msByNentCutoff(etree, cutoff, SPOOLES_SYMMETRIC) ;
break ;
case 4 :
msIV = ETree_msByNopsCutoff(etree, cutoff,
SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
break ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n msIV") ;
IV_writeForHumanEye(msIV, msgFile) ;
}
/*
-----------------------
generate the statistics
-----------------------
*/
nvtxIV = IV_new() ;
nzfIV = IV_new() ;
opsDV = DV_new() ;
ETree_msStats(etree, msIV, nvtxIV, nzfIV, opsDV,
SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
nreg = IV_size(nvtxIV) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n msIV") ;
IV_writeForHumanEye(msIV, msgFile) ;
}
nvtxreg = IV_entries(nvtxIV) ;
nzfreg = IV_entries(nzfIV) ;
opsreg = DV_entries(opsDV) ;
domnvtx = IVsum(nreg-1, nvtxreg+1) ;
domnzf = IVsum(nreg-1, nzfreg+1) ;
domops = DVsum(nreg-1, opsreg+1) ;
fprintf(msgFile,
"\n region vertices entries operations metric/(avg domain)") ;
for ( ireg = 0 ; ireg < nreg ; ireg++ ) {
fprintf(msgFile, "\n %5d %10d %10d %12.0f %6.3f %6.3f %6.3f",
ireg, nvtxreg[ireg], nzfreg[ireg], opsreg[ireg],
((double) nvtxreg[ireg]*(nreg-1))/domnvtx,
((double) nzfreg[ireg]*(nreg-1))/domnzf,
opsreg[ireg]*(nreg-1)/domops) ;
}
totnvtx = IV_sum(nvtxIV) ;
totnzf = IV_sum(nzfIV) ;
totops = DV_sum(opsDV) ;
fprintf(msgFile,
"\n\n nvtx %% nzf %% ops %%"
"\n domains %6d %5.2f %9d %5.2f %12.0f %5.3f"
"\n schur complement %6d %5.2f %9d %5.2f %12.0f %5.3f"
"\n total %6d %9d %12.0f ",
domnvtx, (100.*domnvtx)/totnvtx,
domnzf, (100.*domnzf)/totnzf,
domops, (100.*domops)/totops,
totnvtx - domnvtx, (100.*(totnvtx - domnvtx))/totnvtx,
totnzf - domnzf, (100.*(totnzf - domnzf))/totnzf,
totops - domops, (100.*(totops - domops))/totops,
totnvtx, totnzf, totops) ;
fprintf(msgFile, "\n\n FrontETree : %d entries, %.0f ops",
ETree_nFactorEntries(etree, SPOOLES_SYMMETRIC),
ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC)) ;
/*
-----------------------
write out the IV object
-----------------------
*/
if ( strcmp(outIVfileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = IV_writeToFile(msIV, outIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write msIV to file %s",
t2 - t1, outIVfileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from IV_writeToFile(%p,%s)",
rc, msIV, outIVfileName) ;
}
/*
----------------
free the objects
----------------
*/
ETree_free(etree) ;
IV_free(msIV) ;
IV_free(nvtxIV) ;
IV_free(nzfIV) ;
DV_free(opsDV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ETree/drivers/testMaps.c 0100644 0002055 0007177 00000012317 06536053021 0016523 0 ustar 00cleve compmath 0000040 0000006 /* testMaps.c */
#include "../ETree.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-----------------------
test the map routines
created -- 97jan15, cca
-----------------------
*/
{
char *inETreeFileName, *outIVfileName ;
double cutoff, t1, t2 ;
DV *cumopsDV ;
int msglvl, nthread, rc, type ;
IV *ownersIV ;
ETree *etree ;
FILE *msgFile ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inETreeFile outIVfile "
"\n nthread type cutoff"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inETreeFile -- input file, must be *.etreef or *.etreeb"
"\n outIVfile -- output file, must be *.ivf or *.ivb"
"\n nthread -- number of threads"
"\n type -- type of map"
"\n 1 -- wrap map"
"\n 2 -- balanced map via a post-order traversal"
"\n 3 -- subtree-subset map"
"\n 4 -- old domain decomposition map"
"\n 5 -- new domain decomposition map"
"\n cutoff -- cutoff used for the domain decomposition map"
"\n 0 <= cutoff <= 1 used to define the multisector"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
outIVfileName = argv[4] ;
nthread = atoi(argv[5]) ;
type = atoi(argv[6]) ;
cutoff = atof(argv[7]) ;
if ( type < 1 || type > 5 ) {
fprintf(stderr, "\n fatal error in %s"
"\n type = %d, must be 1, 2 or 3",
argv[0], type) ;
exit(-1) ;
}
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n outIVfile -- %s"
"\n nthread -- %d"
"\n type -- %d"
"\n cutoff -- %f"
"\n",
argv[0], msglvl, argv[2], inETreeFileName, outIVfileName,
nthread, type, cutoff) ;
fflush(msgFile) ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
fflush(msgFile) ;
/*
--------------------------------------------------
initialize the cumulative operations metric object
--------------------------------------------------
*/
cumopsDV = DV_new() ;
DV_init(cumopsDV, nthread, NULL) ;
DV_fill(cumopsDV, 0.0) ;
/*
-------------------------------
create the owners map IV object
-------------------------------
*/
switch ( type ) {
case 1 :
ownersIV = ETree_wrapMap(etree, SPOOLES_REAL,
SPOOLES_SYMMETRIC, cumopsDV) ;
break ;
case 2 :
ownersIV = ETree_balancedMap(etree, SPOOLES_REAL,
SPOOLES_SYMMETRIC, cumopsDV) ;
break ;
case 3 :
ownersIV = ETree_subtreeSubsetMap(etree, SPOOLES_REAL,
SPOOLES_SYMMETRIC, cumopsDV) ;
break ;
case 4 :
ownersIV = ETree_ddMap(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC,
cumopsDV, cutoff) ;
break ;
case 5 :
{ IV *msIV ;
/*
msIV = ETree_msByNopsCutoff(etree, cutoff, 1) ;
*/
msIV = ETree_msByNvtxCutoff(etree, cutoff) ;
ownersIV = ETree_ddMapNew(etree, SPOOLES_REAL,
SPOOLES_SYMMETRIC, msIV, cumopsDV) ;
IV_free(msIV) ;
}
break ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n totalOps = %.0f", DV_sum(cumopsDV)) ;
DVscale(DV_size(cumopsDV), DV_entries(cumopsDV),
nthread/DV_sum(cumopsDV)) ;
fprintf(msgFile, "\n\n cumopsDV") ;
DV_writeForHumanEye(cumopsDV, msgFile) ;
fprintf(msgFile, "\n\n ownersIV") ;
IV_writeForHumanEye(ownersIV, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------
write out the IV object
--------------------------
*/
if ( strcmp(outIVfileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = IV_writeToFile(ownersIV, outIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write ownersIV to file %s",
t2 - t1, outIVfileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from IV_writeToFile(%p,%s)",
rc, ownersIV, outIVfileName) ;
}
/*
----------------
free the objects
----------------
*/
ETree_free(etree) ;
DV_free(cumopsDV) ;
IV_free(ownersIV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ETree/drivers/testStats.c 0100644 0002055 0007177 00000023027 06653406437 0016736 0 ustar 00cleve compmath 0000040 0000006 /* testStats.c */
#include "../../SymbFac.h"
#include "../../ETree.h"
#include "../../InpMtx.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------
(1) read in an ETree object.
(2) read in a Graph object.
(3) draw a tree picture of the distribution
of some metric across the fronts
created -- 99jan22, cca
-------------------------------------------
*/
{
char coordflag, heightflag ;
char *inETreeFileName, *inGraphFileName, *outEPSfileName ;
double fontscale, rmax, rscale, t1, t2 ;
double bbox[4], frame[4] ;
double *radius ;
DV *radiusDV, *xDV, *yDV ;
Graph *graph ;
int J, labelflag, metricType, msglvl, nfront, nvtx, rc ;
int *metric, *vwghts ;
IV *metricIV ;
ETree *etree ;
FILE *msgFile ;
Tree *tree ;
if ( argc != 12 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inETreeFile inGraphFile outEPSfile "
"\n metricType heightflag coordflag rscale labelflag fontscale"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inETreeFile -- input file, must be *.etreef or *.etreeb"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n outEPSfile -- output file for tree picture, must be *.eps"
"\n metricType -- metric type"
"\n 0 -- no metric"
"\n 1 -- # of nodes in front"
"\n 2 -- # of original matrix entries in front"
"\n 3 -- # of factor matrix entries in front"
"\n 4 -- # of forward factor ops in front"
"\n 5 -- # of backward factor ops in front"
"\n heightflag -- flag for type of height"
"\n 'D' -- nodes placed by depth in tree"
"\n 'H' -- nodes placed by height in tree"
"\n coordflag -- flag for type of coordinate"
"\n 'C' -- cartesian (x,y) placement"
"\n 'P' -- polar (r,theta) placement"
"\n rmax -- maximum radius in pts"
"\n labelflag -- flag for type of labels"
"\n 1 -- draw labels"
"\n otherwise -- do not draw labels"
"\n fontscale -- scaling parameter for fonts when labels drawed"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
inGraphFileName = argv[4] ;
outEPSfileName = argv[5] ;
metricType = atoi(argv[6]) ;
heightflag = *argv[7] ;
coordflag = *argv[8] ;
rmax = atof(argv[9]) ;
labelflag = atoi(argv[10]) ;
fontscale = atof(argv[11]) ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n inGraphFile -- %s"
"\n outEPSfile -- %s"
"\n metricType -- %d"
"\n heightflag -- %c"
"\n coordflag -- %c"
"\n rmax -- %f"
"\n labelflag -- %d"
"\n fontscale -- %f"
"\n",
argv[0], msglvl, argv[2], inETreeFileName, inGraphFileName,
outEPSfileName, metricType, heightflag, coordflag, rmax,
labelflag, fontscale) ;
fflush(msgFile) ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
ETree_leftJustify(etree) ;
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
fflush(msgFile) ;
nfront = ETree_nfront(etree) ;
tree = ETree_tree(etree) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
nvtx = graph->nvtx ;
vwghts = graph->vwghts ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
----------------------
compute the statistics
----------------------
*/
metricIV = IV_new() ;
IV_init(metricIV, nfront, NULL) ;
metric = IV_entries(metricIV) ;
switch ( metricType ) {
case 0 : {
/*
---------
no metric
---------
*/
IVfill(nfront, metric, 1) ;
} break ;
case 1 : {
/*
-----------
front sizes
-----------
*/
IVcopy(nfront, metric, ETree_nodwghts(etree)) ;
} break ;
case 2 : {
/*
----------------------------------------------
number of original matrix entries in the front
----------------------------------------------
*/
int I, ii, J, v, vsize, w ;
int *vadj, *vtxToFront ;
vtxToFront = ETree_vtxToFront(etree) ;
for ( v = 0 ; v < nvtx ; v++ ) {
I = vtxToFront[v] ;
Graph_adjAndSize(graph, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
J = vtxToFront[w] ;
if ( I <= J ) {
if ( vwghts == NULL ) {
metric[I]++ ;
} else {
metric[I] += vwghts[v]*vwghts[w] ;
}
} else {
if ( vwghts == NULL ) {
metric[J]++ ;
} else {
metric[J] += vwghts[v]*vwghts[w] ;
}
}
}
}
} break ;
case 3 : {
/*
--------------------------------------------
number of factor matrix entries in the front
--------------------------------------------
*/
int *nzf ;
IV *nzfIV ;
nzfIV = ETree_factorEntriesIV(etree, SPOOLES_SYMMETRIC) ;
nzf = IV_entries(nzfIV) ;
for ( J = 0 ; J < nfront ; J++ ) {
metric[J] = nzf[J] ;
}
IV_free(nzfIV) ;
} break ;
case 4 : {
/*
------------------------------------------------
number of forward factor operations in the front
------------------------------------------------
*/
double *ops ;
DV *opsDV ;
opsDV = ETree_forwardOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
ops = DV_entries(opsDV) ;
for ( J = 0 ; J < nfront ; J++ ) {
metric[J] = ops[J] ;
}
DV_free(opsDV) ;
} break ;
case 5 : {
/*
-------------------------------------------------
number of backward factor operations in the front
-------------------------------------------------
*/
double *ops ;
DV *opsDV ;
IVL *symbfacIVL ;
symbfacIVL = SymbFac_initFromGraph(etree, graph) ;
opsDV = ETree_backwardOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC,
graph->vwghts, symbfacIVL) ;
ops = DV_entries(opsDV) ;
for ( J = 0 ; J < nfront ; J++ ) {
metric[J] = ops[J] ;
}
DV_free(opsDV) ;
IVL_free(symbfacIVL) ;
} break ;
default :
fprintf(stderr, "\n error in testStats"
"\n metricType %d not supported", metricType) ;
exit(-1) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n metric vector") ;
IV_writeForHumanEye(metricIV, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------
set the radius vector
---------------------
*/
radiusDV = DV_new() ;
DV_init(radiusDV, nfront, NULL) ;
radius = DV_entries(radiusDV) ;
for ( J = 0 ; J < nfront ; J++ ) {
radius[J] = sqrt(0.318309886*metric[J]) ;
}
rscale = rmax / DVmax(nfront, radius, &J) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n radius vector") ;
DV_writeForHumanEye(radiusDV, msgFile) ;
fflush(msgFile) ;
}
/*
------------------------
get the tree coordinates
------------------------
*/
xDV = DV_new() ;
yDV = DV_new() ;
rc = Tree_getSimpleCoords(tree, heightflag, coordflag, xDV, yDV) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error return %d from Tree_getSimpleCoords()",rc);
exit(-1) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n x-coordinates") ;
DV_writeForHumanEye(xDV, msgFile) ;
fprintf(msgFile, "\n\n y-coordinates") ;
DV_writeForHumanEye(yDV, msgFile) ;
fprintf(msgFile, "\n\n radius") ;
DV_writeForHumanEye(radiusDV, msgFile) ;
fflush(msgFile) ;
}
/*
-------------
draw the tree
-------------
*/
bbox[0] = 50 ;
bbox[1] = 50 ;
bbox[2] = 550 ;
bbox[3] = 550 ;
frame[0] = 60 ;
frame[1] = 60 ;
frame[2] = 540 ;
frame[3] = 540 ;
rc = Tree_drawToEPS(tree, outEPSfileName, xDV, yDV, rscale, radiusDV,
labelflag, fontscale, NULL, bbox, frame, NULL) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error return %d from Tree_drawToEPSfile()", rc) ;
exit(-1) ;
}
/*
----------------
free the objects
----------------
*/
ETree_free(etree) ;
Graph_free(graph) ;
IV_free(metricIV) ;
DV_free(radiusDV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ee = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
ETree_leftJustify(etree) ;
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETrETree/drivers/testStorage.c 0100644 0002055 0007177 00000020444 06643463254 0017243 0 ustar 00cleve compmath 0000040 0000006 /* testStorage.c */
#include "../../ETree.h"
#include "../../SymbFac.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
----------------------------------------------------
read in an ETree object.
read in a Graph object.
get the symbolic factorization IVL object.
compute the storage profiles for the general sparse,
forward sparse and multifrontal methods.
created -- 96oct03, cca
----------------------------------------------------
*/
{
char *inETreeFileName, *inGraphFileName ;
double elapsed, nfops1, t1, t2 ;
double *FSvec, *GSvec, *MFvec, *backwardops, *forwardops, *vmetric ;
DV *vmetricDV ;
Graph *graph ;
int J, msglvl, nfent1, nfind1, nfront, nleaves1, nnode1, rc ;
IVL *symbfacIVL ;
ETree *etree ;
FILE *msgFile ;
Tree *tree ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inETreeFile inGraphFile "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inETreeFile -- input file, must be *.etreef or *.etreeb"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
inGraphFileName = argv[4] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n inGraphFile -- %s"
"\n",
argv[0], msglvl, argv[2],
inETreeFileName, inGraphFileName) ;
fflush(msgFile) ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree, inETreeFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading ETree object from file %s",
inETreeFileName) ;
if ( msglvl > 2 ) {
ETree_writeForHumanEye(etree, msgFile) ;
} else {
ETree_writeStats(etree, msgFile) ;
}
ETree_leftJustify(etree) ;
fprintf(msgFile, "\n\n %d LU entries", ETree_nFactorEntries(etree, 2)) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
----------------------
compute the statistics
----------------------
*/
tree = etree->tree ;
nfront = etree->nfront ;
nnode1 = etree->tree->n ;
nfind1 = ETree_nFactorIndices(etree) ;
nfent1 = ETree_nFactorEntries(etree, 1) ;
nfops1 = ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
nleaves1 = Tree_nleaves(etree->tree) ;
fprintf(msgFile, "\n root front %d has %d vertices",
etree->tree->root,
etree->nodwghtsIV->vec[etree->tree->root]) ;
fprintf(msgFile, "\n %d fronts, %d indices, %d entries, %.0f ops",
nfront, nfind1, nfent1, nfops1) ;
/*
--------------------------------------------
create the symbolic factorization IVL object
--------------------------------------------
*/
symbfacIVL = SymbFac_initFromGraph(etree, graph) ;
fprintf(msgFile,
"\n\n symbolic factorization IVL object in old ordering") ;
if ( msglvl > 2 ) {
IVL_writeForHumanEye(symbfacIVL, msgFile) ;
} else {
IVL_writeStats(symbfacIVL, msgFile) ;
}
fflush(msgFile) ;
/*
--------------------------
get the operations profile
--------------------------
*/
vmetricDV = ETree_backwardOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC,
graph->vwghts, symbfacIVL) ;
vmetric = DV_entries(vmetricDV) ;
backwardops = DVinit(nfront, 0.0) ;
elapsed = 0.0 ;
for ( J = Tree_postOTfirst(etree->tree) ;
J != -1 ;
J = Tree_postOTnext(etree->tree, J) ) {
elapsed += vmetric[J] ;
backwardops[J] = elapsed ;
}
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n sum of backward ops = %.0f",
DV_sum(vmetricDV)) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n backward ops") ;
DVfprintf(msgFile, nfront, backwardops) ;
}
DV_free(vmetricDV) ;
vmetricDV = ETree_forwardOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
vmetric = DV_entries(vmetricDV) ;
forwardops = DVinit(nfront, 0.0) ;
elapsed = 0.0 ;
for ( J = Tree_postOTfirst(etree->tree) ;
J != -1 ;
J = Tree_postOTnext(etree->tree, J) ) {
elapsed += vmetric[J] ;
forwardops[J] = elapsed ;
}
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n sum of forward ops = %.0f",
DV_sum(vmetricDV)) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n forward ops") ;
DVfprintf(msgFile, nfront, forwardops) ;
}
DV_free(vmetricDV) ;
/*
--------------------------------------
get the general sparse storage profile
--------------------------------------
*/
GSvec = DVinit(nfront, 0.0) ;
ETree_GSstorageProfile(etree, SPOOLES_SYMMETRIC,
symbfacIVL, graph->vwghts, GSvec) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n GSvec storage") ;
DVfprintf(msgFile, nfront, GSvec) ;
}
/*
--------------------------------------
get the forward sparse storage profile
--------------------------------------
*/
FSvec = DVinit(nfront, 0.0) ;
ETree_FSstorageProfile(etree, SPOOLES_SYMMETRIC, symbfacIVL, FSvec) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n FSvec storage") ;
DVfprintf(msgFile, nfront, FSvec) ;
}
/*
------------------------------------
get the multifrontal storage profile
------------------------------------
*/
MFvec = DVinit(nfront, 0.0) ;
ETree_MFstackProfile(etree, SPOOLES_SYMMETRIC, MFvec) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n MFvec storage") ;
DVfprintf(msgFile, nfront, MFvec) ;
}
if ( msglvl > 0 ) {
fprintf(msgFile,
"\n %% five columns of data"
"\n %% backward-ops GS-storage forward-ops FS-storage MF-storage") ;
fprintf(msgFile, "\n data = [ ...") ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
/*
fprintf(msgFile, "\n %12.0f %12.0f %12.0f %12.0f %12.0f",
backwardops[J], FSvec[J], forwardops[J], MGSvec[J], Fvec[J]) ;
*/
fprintf(msgFile, "\n %12.0f %12.4e %12.0f, %12.4e %12.4e",
backwardops[J], GSvec[J]/nfent1,
forwardops[J], FSvec[J]/nfent1, MFvec[J]/nfent1) ;
}
fprintf(msgFile,
" ] ;"
"\n bops = data(:,1) ;"
"\n gs = data(:,2) ;"
"\n fops = data(:,3) ;"
"\n fs = data(:,4) ;"
"\n mf = data(:,5) ;"
"\n\n plot( bops, gs, '-o', fops, fs, '-v', fops, mf, '-s') ; "
"\n xmax = max(bops) ;"
"\n ymax = max( [ max(gs) max(fs) max(mf) ] ) ;"
"\n axis([0, xmax, 0, ymax]) ;"
"\n xlabel(' elapsed operations') ;"
"\n ylabel(' fraction of total factor storage') ;"
"\n title(' workspace profile, ""x"" GS, ""o"" FS, ""*"" MF') ;"
"\n text( 0.1*xmax, 0.9*ymax, 'circle -- general sparse') ;"
"\n text( 0.1*xmax, 0.8*ymax, 'triangle -- forward sparse') ;"
"\n text( 0.1*xmax, 0.7*ymax, 'square -- multifrontal') ;" ) ;
}
/*
----------------
free the objects
----------------
*/
ETree_free(etree) ;
Graph_free(graph) ;
IVL_free(symbfacIVL) ;
DVfree(GSvec) ;
DVfree(MFvec) ;
DVfree(forwardops) ;
DVfree(backwardops) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(-1) ; }
/*--------------------------------------------------------------------*/
= 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graphETree/drivers/testTransform.c 0100644 0002055 0007177 00000027524 06633027561 0017614 0 ustar 00cleve compmath 0000040 0000006 /* testTransform.c */
#include "../../ETree.h"
#include "../../SymbFac.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------------
read in an ETree object and testTransform it by
1 -- merge only children if possible
2 -- merge all children if possible
3 -- split large non-leaf fronts
created -- 96jun27, cca
-------------------------------------------------------
*/
{
char *inETreeFileName, *inGraphFileName, *outETreeFileName ;
double cpus[6], ops[6], t1, t2 ;
ETree *etree0, *etree1, *etree2, *etree3, *etree4, *etree5 ;
FILE *msgFile ;
Graph *graph ;
int maxsize, maxzeros, msglvl, rc, seed ;
int nfronts[7], nfind[7], nzf[7] ;
IV *nzerosIV ;
IVL *symbfacIVL ;
if ( argc != 9 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inETreeFile inGraphFile outETreeFile "
"\n maxzeros maxsize seed"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inETreeFile -- input file, must be *.etreef or *.etreeb"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n outETreeFile -- output file, must be *.etreef or *.etreeb"
"\n maxzeros -- maximum number of zeros in a front"
"\n maxsize -- maximum number of vertices in a front"
"\n seed -- random number seed"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inETreeFileName = argv[3] ;
inGraphFileName = argv[4] ;
outETreeFileName = argv[5] ;
maxzeros = atoi(argv[6]) ;
maxsize = atoi(argv[7]) ;
seed = atoi(argv[8]) ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inETreeFile -- %s"
"\n inGraphFile -- %s"
"\n outETreeFile -- %s"
"\n maxzeros -- %d"
"\n maxsize -- %d"
"\n seed -- %d"
"\n",
argv[0], msglvl, argv[2], inETreeFileName, inGraphFileName,
outETreeFileName, maxzeros, maxsize, seed) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(inETreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
etree0 = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(etree0, inETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s",
t2 - t1, inETreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, etree0, inETreeFileName) ;
exit(-1) ;
}
nfronts[0] = ETree_nfront(etree0) ;
nfind[0] = ETree_nFactorIndices(etree0) ;
nzf[0] = ETree_nFactorEntries(etree0, SPOOLES_SYMMETRIC) ;
ops[0] = ETree_nFactorOps(etree0, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n\n original : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[0], nfind[0], nzf[0], ops[0]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n original front tree ") ;
ETree_writeForHumanEye(etree0, msgFile) ;
fflush(msgFile) ;
}
fflush(msgFile) ;
/*
----------------------------------
get the fundamental supernode tree
----------------------------------
*/
nzerosIV = IV_new() ;
IV_init(nzerosIV, nfronts[0], NULL) ;
IV_fill(nzerosIV, 0) ;
MARKTIME(t1) ;
etree1 = ETree_mergeFrontsOne(etree0, 0, nzerosIV) ;
MARKTIME(t2) ;
cpus[1] = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : get fundamental supernode tree",
t2 - t1) ;
nfronts[1] = ETree_nfront(etree1) ;
nfind[1] = ETree_nFactorIndices(etree1) ;
nzf[1] = ETree_nFactorEntries(etree1, SPOOLES_SYMMETRIC) ;
ops[1] = ETree_nFactorOps(etree1, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n merge one : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[1], nfind[1], nzf[1], ops[1]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after first merge") ;
ETree_writeForHumanEye(etree1, msgFile) ;
}
fprintf(msgFile, "\n IV_sum(nzerosIV) = %d, IV_max(nzerosIV) = %d",
IV_sum(nzerosIV), IV_max(nzerosIV)) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n nzerosIV") ;
IV_writeForHumanEye(nzerosIV, msgFile) ;
fflush(msgFile) ;
}
ETree_writeToFile(etree1,
"/local1/cleve/ARPA/matrices/R3D13824/nd1.etreef") ;
/*
---------------------------
try to absorb only children
---------------------------
*/
MARKTIME(t1) ;
etree2 = ETree_mergeFrontsOne(etree1, maxzeros, nzerosIV) ;
MARKTIME(t2) ;
cpus[2] = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : merge only single child", t2 - t1) ;
nfronts[2] = ETree_nfront(etree2) ;
nfind[2] = ETree_nFactorIndices(etree2) ;
nzf[2] = ETree_nFactorEntries(etree2, SPOOLES_SYMMETRIC) ;
ops[2] = ETree_nFactorOps(etree2, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n merge one : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[2], nfind[2], nzf[2], ops[2]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after first merge") ;
ETree_writeForHumanEye(etree2, msgFile) ;
}
fprintf(msgFile, "\n IV_sum(nzerosIV) = %d, IV_max(nzerosIV) = %d",
IV_sum(nzerosIV), IV_max(nzerosIV)) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n nzerosIV") ;
IV_writeForHumanEye(nzerosIV, msgFile) ;
fflush(msgFile) ;
}
ETree_writeToFile(etree2,
"/local1/cleve/ARPA/matrices/R3D13824/nd2.etreef") ;
/*
--------------------------
try to absorb all children
--------------------------
*/
MARKTIME(t1) ;
etree3 = ETree_mergeFrontsAll(etree2, maxzeros, nzerosIV) ;
MARKTIME(t2) ;
cpus[3] = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : merge all children", t2 - t1) ;
nfronts[3] = ETree_nfront(etree3) ;
nfind[3] = ETree_nFactorIndices(etree3) ;
nzf[3] = ETree_nFactorEntries(etree3, SPOOLES_SYMMETRIC) ;
ops[3] = ETree_nFactorOps(etree3, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n merge all : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[3], nfind[3], nzf[3], ops[3]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after second merge") ;
ETree_writeForHumanEye(etree2, msgFile) ;
}
fprintf(msgFile, "\n IV_sum(nzerosIV) = %d, IV_max(nzerosIV) = %d",
IV_sum(nzerosIV), IV_max(nzerosIV)) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n nzerosIV") ;
IV_writeForHumanEye(nzerosIV, msgFile) ;
fflush(msgFile) ;
}
ETree_writeToFile(etree3,
"/local1/cleve/ARPA/matrices/R3D13824/nd3.etreef") ;
/*
--------------------------
try to absorb any children
--------------------------
*/
MARKTIME(t1) ;
etree4 = ETree_mergeFrontsAny(etree3, maxzeros, nzerosIV) ;
MARKTIME(t2) ;
cpus[4] = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : merge any child", t2 - t1) ;
nfronts[4] = ETree_nfront(etree4) ;
nfind[4] = ETree_nFactorIndices(etree4) ;
nzf[4] = ETree_nFactorEntries(etree4, SPOOLES_SYMMETRIC) ;
ops[4] = ETree_nFactorOps(etree4, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n merge any : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[4], nfind[4], nzf[4], ops[4]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after second merge") ;
ETree_writeForHumanEye(etree4, msgFile) ;
}
fprintf(msgFile, "\n IV_sum(nzerosIV) = %d, IV_max(nzerosIV) = %d",
IV_sum(nzerosIV), IV_max(nzerosIV)) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n nzerosIV") ;
IV_writeForHumanEye(nzerosIV, msgFile) ;
fflush(msgFile) ;
}
ETree_writeToFile(etree4,
"/local1/cleve/ARPA/matrices/R3D13824/nd4.etreef") ;
/*
--------------------
split the front tree
--------------------
*/
MARKTIME(t1) ;
etree5 = ETree_splitFronts(etree4, graph->vwghts, maxsize, 0) ;
MARKTIME(t2) ;
cpus[5] = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : split fronts", t2 - t1) ;
nfronts[5] = ETree_nfront(etree5) ;
nfind[5] = ETree_nFactorIndices(etree5) ;
nzf[5] = ETree_nFactorEntries(etree5, SPOOLES_SYMMETRIC) ;
ops[5] = ETree_nFactorOps(etree5, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n split : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[5], nfind[5], nzf[5], ops[5]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree after split") ;
ETree_writeForHumanEye(etree5, msgFile) ;
}
/*
----------------------------------------
create the symbolic factorization object
----------------------------------------
*/
MARKTIME(t1) ;
symbfacIVL = SymbFac_initFromGraph(etree5, graph) ;
MARKTIME(t2) ;
cpus[6] = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : symbolic factorization", t2 - t1) ;
nfronts[6] = ETree_nfront(etree5) ;
nfind[6] = ETree_nFactorIndices(etree5) ;
nzf[6] = ETree_nFactorEntries(etree5, SPOOLES_SYMMETRIC) ;
ops[6] = ETree_nFactorOps(etree5, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
fprintf(msgFile,
"\n final : %8d fronts, %8d indices, %8d |L|, %12.0f ops",
nfronts[6], nfind[6], nzf[6], ops[6]) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n after symbolic factorization") ;
ETree_writeForHumanEye(etree5, msgFile) ;
fprintf(msgFile, "\n\n after symbolic factorization") ;
IVL_writeForHumanEye(symbfacIVL, msgFile) ;
}
fprintf(msgFile, "\n\n"
"\n CPU #fronts #indices #entries #ops"
"\n original : %8d %8d %8d %12.0f "
"\n fs tree : %8.3f %8d %8d %8d %12.0f "
"\n merge one : %8.3f %8d %8d %8d %12.0f "
"\n merge all : %8.3f %8d %8d %8d %12.0f "
"\n merge any : %8.3f %8d %8d %8d %12.0f "
"\n split : %8.3f %8d %8d %8d %12.0f "
"\n final : %8.3f %8d %8d %8d %12.0f ",
nfronts[0], nfind[0], nzf[0], ops[0],
cpus[1], nfronts[1], nfind[1], nzf[1], ops[1],
cpus[2], nfronts[2], nfind[2], nzf[2], ops[2],
cpus[3], nfronts[3], nfind[3], nzf[3], ops[3],
cpus[4], nfronts[4], nfind[4], nzf[4], ops[4],
cpus[5], nfronts[5], nfind[5], nzf[5], ops[5],
cpus[6], nfronts[6], nfind[6], nzf[6], ops[6]) ;
ETree_writeToFile(etree5,
"/local1/cleve/ARPA/matrices/R3D13824/nd5.etreef") ;
/*
--------------------------
write out the ETree object
--------------------------
*/
if ( strcmp(outETreeFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = ETree_writeToFile(etree5, outETreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write etree to file %s",
t2 - t1, outETreeFileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_writeToFile(%p,%s)",
rc, etree5, outETreeFileName) ;
}
/*
----------------------
free the ETree objects
----------------------
*/
/*
ETree_free(etree0) ;
ETree_free(etree1) ;
ETree_free(etree2) ;
ETree_free(etree3) ;
ETree_free(etree4) ;
ETree_free(etree5) ;
*/
Graph_free(graph) ;
IVL_free(symbfacIVL) ;
IV_free(nzerosIV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
RPA/matrices/R3D13824/nd1.etreef") ;
/*
---------------------------
try to absorb only children
---------------------------
*/
MARKTIME(t1) ;
etree2 = ETree_mergeFETree/doc/ 0042755 0002055 0007177 00000000000 06653150725 0013660 5 ustar 00cleve compmath 0000040 0000006 ETree/doc/dataStructure.tex 0100640 0002055 0007177 00000001514 06534106075 0017221 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\par
The {\tt ETree} object has six fields.
\begin{itemize}
\item {\tt int nfront} : number of fronts in the tree
\item {\tt int nvtx} : number of vertices in the tree
\item {\tt Tree *tree} : pointer to a {\tt Tree} structure
\item {\tt IV *nodwghtsIV} : pointer to an {\tt IV} object to hold
front weights, size {\tt nfront}
\item {\tt IV *bndwghtsIV} : pointer to an {\tt IV} object to hold
the weights of the fronts' boundaries, size {\tt nfront}
\item {\tt IV *vtxToFrontIV} : pointer to an {\tt IV} object to hold
the map from vertices to fronts, size {\tt nfront}
\end{itemize}
A correctly initialized and nontrivial {\tt ETree} object
will have positive {\tt nfront} and {\tt nvtx} values,
a valid {\tt tree} field and non-{\tt NULL}
{\tt nodwghtsIV}, {\tt bndwghtsIV} and {\tt vtxToFrontIV} pointers.
ETree/doc/intro.tex 0100640 0002055 0007177 00000002771 06534106075 0015530 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt ETree}: Elimination and Front Trees}
\label{chapter:ETree}
\par
The {\tt ETree} object is used to model an elimination tree or a
front tree for a sparse factorization with symmetric structure.
The tree is defined over a set of vertices in a graph --- the graph
can be unit weight or non-unit weight.
A ``node'' in the tree can be a single vertex (in the context of
an elimination tree) or a group of vertices (as for a front tree).
\par
The tree information is stored as a {\tt Tree} object.
In addition there are three {\tt IV} objects.
One stores the total size of the nodes in the fronts,
one stores the size of the boundaries of the fronts,
and one stores the map from the vertices to the fronts.
\par
There is a great deal of functionality embodied into the {\tt ETree}
object.
Given an elimination tree or a front tree, one can extract the
permutation vectors (for the fronts or the vertices), extract a
multisector based on several criteria, compress the front tree in
several ways, justify the tree (order children of a node in
meaningful ways), evaluate metric vectors on the tree (heights,
depths, subtree accumulators).
\par
The front tree we obtain from a low-fill matrix ordering is usually
not the front tree that drives the factorization.
We provide three methods that transform the former into the latter.
One method merges the fronts together in a
way that adds logical zeros to their structure.
One method splits large fronts into smaller fronts.
One method combines these two functionalities.
ETree/doc/main.aux 0100640 0002055 0007177 00000007321 06653142257 0015316 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\contentsline {chapter}{\numberline {1}{\tt ETree}: Elimination and Front Trees}{1}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chapter:ETree}{{1}{1}}
\@writefile{toc}{\contentsline {section}{\numberline {1.1}Data Structure}{1}}
\@writefile{toc}{\contentsline {section}{\numberline {1.2}Prototypes and descriptions of {\tt ETree} methods}{2}}
\newlabel{section:ETree:proto}{{1.2}{2}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.1}Basic methods}{2}}
\newlabel{subsection:ETree:proto:basics}{{1.2.1}{2}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.2}Instance methods}{2}}
\newlabel{subsection:ETree:proto:instance}{{1.2.2}{2}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.3}Initializer methods}{4}}
\newlabel{subsection:ETree:proto:initializers}{{1.2.3}{4}}
\citation{liu90-etree}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.4}Utility methods}{6}}
\newlabel{subsection:ETree:proto:utilities}{{1.2.4}{6}}
\citation{liu91-generalizedEnvelope}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.5}Metrics methods}{8}}
\newlabel{subsection:ETree:proto:metrics}{{1.2.5}{8}}
\citation{ash89-relaxed}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.6}Compression methods}{9}}
\newlabel{subsection:ETree:proto:compression}{{1.2.6}{9}}
\citation{liu85-mfstorage}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.7}Justification methods}{10}}
\newlabel{subsection:ETree:proto:justify}{{1.2.7}{10}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.8}Permutation methods}{10}}
\newlabel{subsection:ETree:proto:permutation}{{1.2.8}{10}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.9}Multisector methods}{11}}
\newlabel{subsection:ETree:proto:multisector}{{1.2.9}{11}}
\citation{duf83-multifrontal}
\citation{ash89-relaxed}
\citation{ash89-relaxed}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.10}Transformation methods}{13}}
\newlabel{subsection:ETree:proto:transformation}{{1.2.10}{13}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.11}Parallel factorization map methods}{15}}
\newlabel{subsection:ETree:proto:map}{{1.2.11}{15}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.12}Storage profile methods}{16}}
\newlabel{subsection:ETree:proto:storage}{{1.2.12}{16}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.13}IO methods}{17}}
\newlabel{subsection:ETree:proto:IO}{{1.2.13}{17}}
\@writefile{toc}{\contentsline {section}{\numberline {1.3}Driver programs for the {\tt ETree} object}{18}}
\newlabel{section:ETree:drivers}{{1.3}{18}}
\@writefile{lof}{\contentsline {figure}{\numberline {1.1}{\ignorespaces {\sc GRD7x7}: Working storage for the forward sparse factorization of the nested dissection ordering. On the left is the storage required to factor ${\mathaccent "0362\relax J}$ and its update matrix. On the right is the storage required to factor $J$ and all of its ancestors. Both plots have the same scale.}}{23}}
\newlabel{fig-GRD7x7-FStree}{{1.1}{23}}
\citation{ash89-relaxed}
\citation{duf83-multifrontal}
\@writefile{lof}{\contentsline {figure}{\numberline {1.2}{\ignorespaces {\sc GRD7x7x7}: Four tree plots for a $7 \times 7 \times 7$ grid matrix ordered using nested dissection. The top left tree measure number of original matrix entries in a front. The top right tree measure number of factor matrix entries in a front. The bottom left tree measure number of factor operations in a front for a forward looking factorization, e.g., forward sparse. The bottom right tree measure number of factor operations in a front for a backward looking factorization, e.g., general sparse.}}{28}}
\newlabel{fig-GRD7x7x7-metrics}{{1.2}{28}}
ETree/doc/main.log 0100640 0002055 0007177 00000026277 06653142257 0015315 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.14159 (C version 6.1) (format=latex 97.4.4) 25 JAN 1999 11:23
**main
(main.tex
LaTeX2e <1996/12/01> patch level 1
Babel and hyphenation patterns for english, german, loaded.
(/home/tex/teTeX/texmf/tex/latex/base/report.cls
Document Class: report 1996/10/31 v1.3u Standard LaTeX document class
(/home/tex/teTeX/texmf/tex/latex/base/leqno.clo
File: leqno.clo 1996/07/26 v1.1b Standard LaTeX option (left equation numbers)
)
(/home/tex/teTeX/texmf/tex/latex/base/size11.clo
File: size11.clo 1996/10/31 v1.3u Standard LaTeX file (size option)
)
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
\abovecaptionskip=\skip41
\belowcaptionskip=\skip42
\bibindent=\dimen102
)
\@indexfile=\write3
Writing index file main.idx
(/home/tex/teTeX/texmf/tex/generic/local/psfig/psfig.tex
\@unused=\write4
\ps@stream=\read1
\p@intvaluex=\dimen103
\p@intvaluey=\dimen104
psfig/tex 1.10-dvips
) (main.aux)
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 18.
LaTeX Font Info: ... okay on input line 18.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 18.
LaTeX Font Info: ... okay on input line 18.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 18.
LaTeX Font Info: ... okay on input line 18.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 18.
LaTeX Font Info: ... okay on input line 18.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 18.
LaTeX Font Info: ... okay on input line 18.
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 18.
LaTeX Font Info: ... okay on input line 18.
(intro.tex
Chapter 1.
) (dataStructure.tex
LaTeX Font Info: Try loading font information for OMS+cmr on input line 6.
(/home/tex/teTeX/texmf/tex/latex/base/omscmr.fd
File: omscmr.fd 1997/01/14 v2.5a Standard LaTeX font definitions
)
LaTeX Font Info: Font shape `OMS/cmr/m/n' in size <10.95> not available
(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 6.
[1
])
(proto.tex [2] [3] [4]
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <10.95> on input line 292.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <8> on input line 292.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <6> on input line 292.
LaTeX Warning: Citation `liu90-etree' on page 5 undefined on input line 292.
Overfull \hbox (11.7664pt too wide) in paragraph at lines 320--320
[]\OT1/cmtt/m/n/10.95 void ETree_initFromDenseMatrix ( ETree *etree, int n, in
t option, int param ) ;[]
[]
Overfull \hbox (52.00722pt too wide) in paragraph at lines 354--354
[]\OT1/cmtt/m/n/10.95 int ETree_initFromSubtree ( ETree *subtree, IV *nodeidsI
V, ETree *etree, IV *vtxIV ) ;[]
[]
[5]
Overfull \hbox (0.18552pt too wide) in paragraph at lines 433--439
\OT1/cmr/m/n/10.95 pa-ram-e-ter can be one of \OT1/cmtt/m/n/10.95 SPOOLES[]SYMM
ETRIC\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95 SPOOLES[]HERMITIAN \OT1/cmr/m/n/1
0.95 or \OT1/cmtt/m/n/10.95 SPOOLES[]NONSYMMETRIC\OT1/cmr/m/n/10.95 .
[]
Overfull \hbox (23.26378pt too wide) in paragraph at lines 466--466
[]\OT1/cmtt/m/n/10.95 double ETree_nInternalOpsInFront ( ETree *etree, int typ
e, int symflag, int J ) ;[]
[]
[6]
Overfull \hbox (23.26378pt too wide) in paragraph at lines 486--486
[]\OT1/cmtt/m/n/10.95 double ETree_nExternalOpsInFront ( ETree *etree, int typ
e, int symflag, int J ) ;[]
[]
Overfull \hbox (69.25328pt too wide) in paragraph at lines 565--565
[]\OT1/cmtt/m/n/10.95 ETree * ETree_spliceTwoEtrees ( ETree *etree0, Graph *gr
aph, IV *mapIV, ETree *etree1 ) ;[]
[]
[7]
LaTeX Warning: Citation `liu91-generalizedEnvelope' on page 8 undefined on inpu
t line 661.
[8]
LaTeX Warning: Citation `ash89-relaxed' on page 9 undefined on input line 681.
Overfull \hbox (0.29208pt too wide) in paragraph at lines 691--695
[]\OT1/cmr/m/n/10.95 the struc-tures of $\OML/cmm/m/it/10.95 v[]$ \OT1/cmr/m/n/
10.95 and $\OML/cmm/m/it/10.95 v[]$ \OT1/cmr/m/n/10.95 are nested, i.e., \OT1/c
mtt/m/n/10.95 bndwght[$\OML/cmm/m/it/10.95 v[]$\OT1/cmtt/m/n/10.95 ] = nodwght[
$\OML/cmm/m/it/10.95 v[]$\OT1/cmtt/m/n/10.95 ] + bndwght[$\OML/cmm/m/it/10.95 v
[]$\OT1/cmtt/m/n/10.95 ]
[]
[9]
LaTeX Warning: Citation `liu85-mfstorage' on page 10 undefined on input line 75
9.
[10] [11]
Overfull \hbox (29.01247pt too wide) in paragraph at lines 944--944
[]\OT1/cmtt/m/n/10.95 IV * ETree_msByNopsCutoff ( ETree *etree, double cutoff,
int type, int symflag ) ;[]
[]
Overfull \hbox (23.26378pt too wide) in paragraph at lines 1000--1000
[] \OT1/cmtt/m/n/10.95 double alpha, int *ptotalgain, int
msglvl, FILE *msgFile ) ;[]
[]
[12]
LaTeX Warning: Citation `duf83-multifrontal' on page 13 undefined on input line
1038.
LaTeX Warning: Citation `ash89-relaxed' on page 13 undefined on input line 1039
.
LaTeX Warning: Citation `ash89-relaxed' on page 13 undefined on input line 1064
.
[13] [14] [15] [16] [17]) (drivers.tex
Overfull \hbox (19.63927pt too wide) in paragraph at lines 31--36
\OT1/cmtt/m/n/10.95 *.graphf \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.graphb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 Graph \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 Graph[]readFromFile()
[]
[18]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 81--86
\OT1/cmtt/m/n/10.95 *.etreef \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.etreeb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 ETree \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 ETree[]readFromFile()
[]
[19] [20]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 258--263
\OT1/cmtt/m/n/10.95 *.etreef \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.etreeb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 ETree \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 ETree[]readFromFile()
[]
[21]
Overfull \hbox (0.26903pt too wide) in paragraph at lines 333--333
[]\OT1/cmtt/m/n/10.95 testFS msglvl msgFile inETreeFile labelflag radius first
EPSfile secondEPSfile[]
[]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 358--363
\OT1/cmtt/m/n/10.95 *.etreef \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.etreeb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 ETree \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 ETree[]readFromFile()
[]
psfig: searching ../../ETree/doc/FS1.eps for bounding box
psfig: including ../../ETree/doc/FS1.eps
psfig: searching ../../ETree/doc/FS2.eps for bounding box
psfig: including ../../ETree/doc/FS2.eps
[22]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 411--415
\OT1/cmtt/m/n/10.95 *.etreef \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.etreeb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 ETree \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 ETree[]readFromFile()
[]
[23]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 437--442
\OT1/cmtt/m/n/10.95 *.etreef \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.etreeb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 ETree \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 ETree[]readFromFile()
[]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 472--477
\OT1/cmtt/m/n/10.95 *.etreef \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.etreeb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 ETree \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 ETree[]readFromFile()
[]
[24]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 573--578
\OT1/cmtt/m/n/10.95 *.etreef \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.etreeb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 ETree \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 ETree[]readFromFile()
[]
[25]
Overfull \hbox (17.51509pt too wide) in paragraph at lines 617--617
[]\OT1/cmtt/m/n/10.95 testStats msglvl msgFile inETreeFile labelflag radius fi
rstEPSfile secondEPSfile[]
[]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 653--658
\OT1/cmtt/m/n/10.95 *.etreef \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.etreeb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 ETree \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 ETree[]readFromFile()
[]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 658--663
\OT1/cmtt/m/n/10.95 *.graphf \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.graphb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 Graph \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 Graph[]readFromFile()
[]
[26]
LaTeX Warning: Reference `subsection:Tree:proto:drawing' on page 27 undefined o
n input line 670.
psfig: searching ../../ETree/doc/GRD7x7x7_nzA.eps for bounding box
psfig: including ../../ETree/doc/GRD7x7x7_nzA.eps
psfig: searching ../../ETree/doc/GRD7x7x7_nzF.eps for bounding box
psfig: including ../../ETree/doc/GRD7x7x7_nzF.eps
psfig: searching ../../ETree/doc/GRD7x7x7_forwops.eps for bounding box
psfig: including ../../ETree/doc/GRD7x7x7_forwops.eps
psfig: searching ../../ETree/doc/GRD7x7x7_backops.eps for bounding box
psfig: including ../../ETree/doc/GRD7x7x7_backops.eps
psfig: searching ../../ETree/doc/workingStorage.eps for bounding box
psfig: including ../../ETree/doc/workingStorage.eps
Overfull \hbox (19.63927pt too wide) in paragraph at lines 732--737
\OT1/cmtt/m/n/10.95 *.etreef \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.etreeb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 ETree \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 ETree[]readFromFile()
[]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 737--741
\OT1/cmtt/m/n/10.95 *.graphf \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.graphb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 Graph \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 Graph[]readFromFile()
[]
LaTeX Warning: Citation `ash89-relaxed' on page 27 undefined on input line 752.
LaTeX Warning: Citation `duf83-multifrontal' on page 27 undefined on input line
752.
[27] [28]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 798--803
\OT1/cmtt/m/n/10.95 *.etreef \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.etreeb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 ETree \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 ETree[]readFromFile()
[]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 803--808
\OT1/cmtt/m/n/10.95 *.graphf \OT1/cmr/m/n/10.95 or \OT1/cmtt/m/n/10.95 *.graphb
\OT1/cmr/m/n/10.95 . The \OT1/cmtt/m/n/10.95 Graph \OT1/cmr/m/n/10.95 ob-ject i
s read from the file via the \OT1/cmtt/m/n/10.95 Graph[]readFromFile()
[]
) (main.ind [29] [30
] [31
]) (main.aux)
LaTeX Warning: There were undefined references.
)
Here is how much of TeX's memory you used:
599 strings out of 10908
6400 string characters out of 72189
53984 words of memory out of 262141
3465 multiletter control sequences out of 9500
10951 words of font info for 40 fonts, out of 150000 for 255
14 hyphenation exceptions out of 607
23i,6n,22p,612b,426s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (31 pages, 106436 bytes).
ETree/doc/main.tex 0100644 0002055 0007177 00000001116 06650656221 0015317 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\input psfig
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt ETree} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt ETree} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
ETree/doc/main.idx 0100644 0002055 0007177 00000012071 06653142257 0015307 0 ustar 00cleve compmath 0000040 0000006 \indexentry{ETree_new@{\tt ETree\_new()}}{2}
\indexentry{ETree_setDefaultFields@{\tt ETree\_setDefaultFields()}}{2}
\indexentry{ETree_clearData@{\tt ETree\_clearData()}}{2}
\indexentry{ETree_free@{\tt ETree\_free()}}{2}
\indexentry{ETree_nfront@{\tt ETree\_nfront()}}{2}
\indexentry{ETree_nvtx@{\tt ETree\_nvtx()}}{3}
\indexentry{ETree_tree@{\tt ETree\_tree()}}{3}
\indexentry{ETree_root@{\tt ETree\_root()}}{3}
\indexentry{ETree_par@{\tt ETree\_par()}}{3}
\indexentry{ETree_fch@{\tt ETree\_fch()}}{3}
\indexentry{ETree_sib@{\tt ETree\_sib()}}{3}
\indexentry{ETree_nodwghtsIV@{\tt ETree\_nodwghtsIV()}}{3}
\indexentry{ETree_nodwghts@{\tt ETree\_nodwghts()}}{3}
\indexentry{ETree_bndwghtsIV@{\tt ETree\_bndwghtsIV()}}{3}
\indexentry{ETree_bndwghts@{\tt ETree\_bndwghts()}}{4}
\indexentry{ETree_vtxToFrontIV@{\tt ETree\_vtxToFrontIV()}}{4}
\indexentry{ETree_vtxToFront@{\tt ETree\_vtxToFront()}}{4}
\indexentry{ETree_frontSize@{\tt ETree\_frontSize()}}{4}
\indexentry{ETree_frontBoundarySize@{\tt ETree\_frontBoundarySize()}}{4}
\indexentry{ETree_maxNindAndNent@{\tt ETree\_maxNindAndNent()}}{4}
\indexentry{ETree_init1@{\tt ETree\_init1()}}{4}
\indexentry{ETree_initFromGraph@{\tt ETree\_initFromGraph()}}{5}
\indexentry{ETree_initFromGraphWithPerms@{\tt ETree\_initFromGraphWithPerms()}}{5}
\indexentry{ETree_initFromDenseMatrix@{\tt ETree\_initFromDenseMatrix()}}{5}
\indexentry{ETree_initFromFile@{\tt ETree\_initFromFile()}}{5}
\indexentry{ETree_initFromSubtree@{\tt ETree\_initFromSubtree()}}{5}
\indexentry{ETree_sizeOf@{\tt ETree\_sizeOf()}}{6}
\indexentry{ETree_nFactorIndices@{\tt ETree\_nFactorIndices()}}{6}
\indexentry{ETree_nFactorEntries@{\tt ETree\_nFactorEntries()}}{6}
\indexentry{ETree_nFactorOps@{\tt ETree\_nFactorOps()}}{6}
\indexentry{ETree_nFactorEntriesInFront@{\tt ETree\_nFactorEntriesInFront()}}{6}
\indexentry{ETree_nInternalOpsInFront@{\tt ETree\_nInternalOpsInFront()}}{7}
\indexentry{ETree_nExternalOpsInFront@{\tt ETree\_nExternalOpsInFront()}}{7}
\indexentry{ETree_factorEntriesIV@{\tt ETree\_factorEntriesIV()}}{7}
\indexentry{ETree_backwardOps@{\tt ETree\_backwardOps()}}{7}
\indexentry{ETree_forwardOps@{\tt ETree\_forwardOps()}}{7}
\indexentry{ETree_expand@{\tt ETree\_expand()}}{7}
\indexentry{ETree_spliceTwoEtrees@{\tt ETree\_spliceTwoEtrees()}}{8}
\indexentry{ETree_nvtxMetric@{\tt ETree\_nvtxMetric()}}{8}
\indexentry{ETree_nentMetric@{\tt ETree\_nentMetric()}}{8}
\indexentry{ETree_nopsMetric@{\tt ETree\_nopsMetric()}}{8}
\indexentry{ETree_fundChainMap@{\tt ETree\_fundChainMap()}}{9}
\indexentry{ETree_fundSupernodeMap@{\tt ETree\_fundSupernodeMap()}}{9}
\indexentry{ETree_compress@{\tt ETree\_compress()}}{10}
\indexentry{ETree_leftJustify@{\tt ETree\_leftJustify()}}{10}
\indexentry{ETree_leftJustifyI@{\tt ETree\_leftJustifyI()}}{10}
\indexentry{ETree_leftJustifyD@{\tt ETree\_leftJustifyD()}}{10}
\indexentry{ETree_newToOldFrontPerm@{\tt ETree\_newToOldFrontPerm()}}{10}
\indexentry{ETree_oldToNewFrontPerm@{\tt ETree\_oldToNewFrontPerm()}}{10}
\indexentry{ETree_newToOldVtxPerm@{\tt ETree\_newToOldVtxPerm()}}{11}
\indexentry{ETree_oldToNewVtxPerm@{\tt ETree\_oldToNewVtxPerm()}}{11}
\indexentry{ETree_permuteVertices@{\tt ETree\_permuteVertices()}}{11}
\indexentry{ETree_msByDepth@{\tt ETree\_msByDepth()}}{11}
\indexentry{ETree_msByNvtxCutoff@{\tt ETree\_msByNvtxCutoff()}}{11}
\indexentry{ETree_msByNentCutoff@{\tt ETree\_msByNentCutoff()}}{11}
\indexentry{ETree_msByNopsCutoff@{\tt ETree\_msByNopsCutoff()}}{12}
\indexentry{ETree_msStats@{\tt ETree\_msStats()}}{12}
\indexentry{ETree_optPart@{\tt ETree\_optPart()}}{12}
\indexentry{ETree_mergeFrontsOne@{\tt ETree\_mergeFrontsOne()}}{14}
\indexentry{ETree_mergeFrontsAll@{\tt ETree\_mergeFrontsAll()}}{14}
\indexentry{ETree_mergeFrontsAny@{\tt ETree\_mergeFrontsAny()}}{14}
\indexentry{ETree_splitFronts@{\tt ETree\_splitFronts()}}{14}
\indexentry{ETree_transform@{\tt ETree\_transform()}}{15}
\indexentry{ETree_transform2@{\tt ETree\_transform2()}}{15}
\indexentry{ETree_wrapMap@{\tt ETree\_wrapMap()}}{15}
\indexentry{ETree_balancedMap@{\tt ETree\_balancedMap()}}{15}
\indexentry{ETree_subtreeSubsetMap@{\tt ETree\_subtreeSubsetMap()}}{15}
\indexentry{ETree_ddMap@{\tt ETree\_ddMap()}}{15}
\indexentry{ETree_ddMapNew@{\tt ETree\_ddMapNew()}}{15}
\indexentry{ETree_MFstackProfile@{\tt ETree\_MFstackProfile()}}{16}
\indexentry{ETree_GSstorageProfile@{\tt ETree\_GSstorageProfile()}}{16}
\indexentry{ETree_FSstorageProfile@{\tt ETree\_FSstorageProfile()}}{16}
\indexentry{ETree_forwSolveProfile@{\tt ETree\_forwSolveProfile()}}{16}
\indexentry{ETree_backSolveProfile@{\tt ETree\_backSolveProfile()}}{17}
\indexentry{ETree_readFromFile@{\tt ETree\_readFromFile()}}{17}
\indexentry{ETree_readFromFormattedFile@{\tt ETree\_readFromFormattedFile()}}{17}
\indexentry{ETree_readFromBinaryFile@{\tt ETree\_readFromBinaryFile()}}{17}
\indexentry{ETree_writeToFile@{\tt ETree\_writeToFile()}}{17}
\indexentry{ETree_writeToFormattedFile@{\tt ETree\_writeToFormattedFile()}}{17}
\indexentry{ETree_writeToBinaryFile@{\tt ETree\_writeToBinaryFile()}}{18}
\indexentry{ETree_writeForHumanEye@{\tt ETree\_writeForHumanEye()}}{18}
\indexentry{ETree_writeStats@{\tt ETree\_writeStats()}}{18}
ETree/doc/drivers.tex 0100644 0002055 0007177 00000101746 06653142172 0016061 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt ETree} object}
\label{section:ETree:drivers}
\par
This section contains brief descriptions of the driver programs.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
createETree msglvl msgFile inGraphFile inPermFile outIVfile outETreeFile
\end{verbatim}
This driver program reads in a {\tt Graph} object and a {\tt Perm}
permutation object and creates a front tree {\tt ETree} object.
The map from vertices to fronts is optionally written out to {\tt
outIVfile}.
The {\tt ETree} object is optionally written out to {\tt outETreeFile}.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt inPermFile} parameter is the input file for the {\tt Perm}
object. It must be of the form {\tt *.permf} or {\tt *.permb}.
The {\tt Perm} object is read from the file via the
{\tt Perm\_readFromFile()} method.
\item
The {\tt outIVfile} parameter is the output file for the
vertex-to-front map {\tt IV} object.
If {\tt outIVfile} is {\tt none} then the {\tt IV} object is not
written to a file.
Otherwise, the {\tt IV\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outIVfile} is of the form
{\tt *.ivf}), or
a binary file (if {\tt outIVfile} is of the form {\tt *.ivb}).
\item
The {\tt outETreeFile} parameter is the output file for the
{\tt ETree} object.
If {\tt outETreeFile} is {\tt none} then the {\tt ETree} object is not
written to a file.
Otherwise, the {\tt ETree\_writeToFile()} method is called to write
the object to
a formatted file (if {\tt outETreeFile} is of the form
{\tt *.etreef}),
or
a binary file (if {\tt outETreeFile} is of the form {\tt *.etreeb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
extractTopSep msglvl msgFile inETreeFile outIVfile
\end{verbatim}
This driver program creates an {\tt IV} object that contains a
{\tt compids[]} vector, where {\tt compids[v] = 0} if vertex {\tt v}
is in the top level separator and {\tt -1} otherwise.
The {\tt IV} object is optionally written out to a file.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means that all objects are written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
message data.
\item
The {\tt inETreeFile} parameter is the input file for the {\tt ETree}
object. It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\item
The {\tt outIVfile} parameter is the output file for the
vertex-to-front map {\tt IV} object.
If {\tt outIVfile} is {\tt none} then the {\tt IV} object is not
written to a file.
Otherwise, the {\tt IV\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outIVfile} is of the form
{\tt *.ivf}), or
a binary file (if {\tt outIVfile} is of the form {\tt *.ivb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
mkNDETree msglvl msgFile n1 n2 n3 maxzeros maxsize outFile
\end{verbatim}
\par
This program constructs a front tree for a Laplacian operator on a
regular grid ordered using nested dissection.
When {\tt n3 = 1}, the problem is two dimensional and a 9-point
operator is used.
When {\tt n3 > 1}, the problem is three dimensional and a 27-point
operator is used.
A sequence of five ETree objects are produced:
\begin{itemize}
\item vertex elimination tree
\item fundamental supernode front tree
\item front tree after trying to merge with an only child
\item front tree after trying to merge with all children
\item front tree after splitting large fronts
\end{itemize}
The merging and splitting process are controlled by the
{\tt maxzeros} and {\tt maxsize} parameters.
Here is some typical output for a $15 \times 15 \times 15$ grid
matrix with {\tt maxzeros = 64} and {\tt maxsize = 32}.
\begin{verbatim}
vtx tree : 3375 fronts, 367237 indices, 367237 |L|, 63215265 ops
fs tree : 1023 fronts, 39661 indices, 367237 |L|, 63215265 ops
merge1 : 1023 fronts, 39661 indices, 367237 |L|, 63215265 ops
merge2 : 511 fronts, 29525 indices, 373757 |L|, 63590185 ops
split : 536 fronts, 34484 indices, 373757 |L|, 63590185 ops
\end{verbatim}
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
{\tt n1} is the number of grid points in the first direction.
\item
{\tt n2} is the number of grid points in the second direction.
\item
{\tt n3} is the number of grid points in the third direction.
\item
The {\tt maxzeros} parameter is an upper bound on the number of
logically zero entries that will be allowed in a new front.
\item
The {\tt maxsize} parameter is an upper bound on the number of
vertices in a front --- any original front that contains more than
{\tt maxsize} vertices will be broken up into smaller fronts.
\item
The {\tt outFile} parameter is the output file for the {\tt ETree}
object.
If {\tt outFile} is {\tt none} then the {\tt ETree} object is not
written to a file.
Otherwise, the {\tt ETree\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outFile}
is of the form {\tt *.etreef}), or a binary file
(if {\tt outFile} is of the form {\tt *.etreeb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
mkNDoutput msglvl msgFile n1 n2 n3 maxzeros maxsize
nthread maptype cutoff outETreeFile outMapFile
\end{verbatim}
\par
This program constructs a front tree for a Laplacian operator on a
regular grid ordered using nested dissection.
When {\tt n3 = 1}, the problem is two dimensional and a 9-point
operator is used.
When {\tt n3 > 1}, the problem is three dimensional and a 27-point
operator is used.
The front tree is generated in the same fashion as done by the
{\tt mkNDETree} driver program.
Using this front tree, an {\tt IV} object that maps fronts
to processors is then created using one of four different kinds of
maps.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
{\tt n1} is the number of grid points in the first direction.
\item
{\tt n2} is the number of grid points in the second direction.
\item
{\tt n3} is the number of grid points in the third direction.
\item
The {\tt maxzeros} parameter is an upper bound on the number of
logically zero entries that will be allowed in a new front.
\item
The {\tt maxsize} parameter is an upper bound on the number of
vertices in a front --- any original front that contains more than
{\tt maxsize} vertices will be broken up into smaller fronts.
\item
The {\tt nthread} parameter is the number of threads.
\item
The {\tt maptype} parameter is the type of map.
\begin{itemize}
\item {\tt 1} --- wrap map
\item {\tt 2} --- balanced map
\item {\tt 3} --- subtree-subset map
\item {\tt 4} --- domain decomposition map
\end{itemize}
\item
The {\tt cutoff} parameter is used by the domain decomposition map only.
Try setting {\tt cutoff = 1/nthread} or {\tt cutoff = 1/(2*nthread)}.
\item
The {\tt outETreeFile} parameter is the output file for the {\tt ETree}
object.
If {\tt outETreeFile} is {\tt none} then the {\tt ETree} object is not
written to a file.
Otherwise, the {\tt ETree\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outETreeFile}
is of the form {\tt *.etreef}), or a binary file
(if {\tt outETreeFile} is of the form {\tt *.etreeb}).
\item
The {\tt outMapFile} parameter is the output file for the {\tt IV}
map object.
If {\tt outMapFile} is {\tt none} then the {\tt IV} object is not
written to a file.
Otherwise, the {\tt IV\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outMapFile}
is of the form {\tt *.ivf}), or a binary file
(if {\tt outMapFile} is of the form {\tt *.ivb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
permuteETree msglvl msgFile inETreeFile inEqmapIVfile outETreeFile outIVfile
\end{verbatim}
This driver program is used to get an old-to-new permutation vector
from an {\tt ETree} object and permute the vertices in the
{\tt ETree} object.
The program has the ability to handle an {\tt ETree} object that is
defined on a compressed graph.
If {\tt inEqmapIVfile} is not {\tt none}, the program reads in an
{\tt IV} object that contains the equivalence map, i.e., the map
from the degrees of freedom to the vertices in the compressed graph.
This map is used to expand the {\tt ETree} object.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inETreeFile} parameter is the input file for the {\tt ETree}
object. It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\item
The {\tt inEqmapIVfile} parameter is the input file for the
equivalence map {\tt IV} object.
It must be of the form {\tt *.ivf}, {\tt *.ivb}, or {\tt none}.
If {\tt inEqmapIVfile} is not {\tt none},
the {\tt IV} object is read from the file via the
{\tt IV\_readFromFile()} method.
\item
The {\tt outETreeFile} parameter is the output file for the {\tt ETree}
object.
If {\tt outETreeFile} is {\tt none} then the {\tt ETree} object is not
written to a file.
Otherwise, the {\tt ETree\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outETreeFile}
is of the form {\tt *.etreef}), or a binary file
(if {\tt outETreeFile} is of the form {\tt *.etreeb}).
\item
The {\tt outIVFile} parameter is the output file for the
old-to-new {\tt IV} object.
If {\tt outIVFile} is {\tt none} then the {\tt IV} object is not
written to a file.
Otherwise, the {\tt IV\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outIVFile}
is of the form {\tt *.ivf}), or a binary file
(if {\tt outIVFile} is of the form {\tt *.ivb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testExpand msglvl msgFile inETreeFile inEqmapFile outETreeFile
\end{verbatim}
This driver program is used to translate an {\tt ETree} object for
a compressed graph into an {\tt ETree} object for the unit weight
graph.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inETreeFile} parameter is the input file for the {\tt ETree}
object for the compressed graph.
It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\item
The {\tt inEqmapFile} parameter contains the map from vertices
in the unit weight graph into vertices in the compressed graph.
It must be of the form {\tt *.ivf} or {\tt *.ivb}.
The {\tt IV} object is read from the file via the
{\tt IV\_readFromFile()} method.
\item
The {\tt outETreeFile} parameter is the output file for the {\tt ETree}
object for the unit weight graph.
If {\tt outETreeFile} is {\tt none} then the {\tt ETree} object is not
written to a file.
Otherwise, the {\tt ETree\_writeToFile()} method is called to write
the object to
a formatted file (if {\tt outETreeFile} is of the form {\tt *.etreef}),
or a binary file (if {\tt outETreeFile} is of the form {\tt *.etreeb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testFS msglvl msgFile inETreeFile labelflag radius firstEPSfile secondEPSfile
\end{verbatim}
This driver program investigates the storage requirements for a
limited storage forward sparse factorization.
It first reads in a front tree object and for each front $J$, it
determines two quantities:
(1) the amount of in-core storage necessary to factor
${\widehat J}$ and its boundary,
and
(2) the amount of in-core storage necessary to factor
$J$, $\mbox{par}(J)$, $\mbox{par}^2(J)$, etc.
The program then creates two EPS files, written to {\tt
firstEPSfile} and {\tt secondEPSfile}.
See Figure~\ref{fig-GRD7x7-FStree} for an example.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inETreeFile} parameter is the input file for the {\tt ETree}
object. It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\item
If {\tt labelflag = 1}, the node ids are written on the nodes
in the two plots.
\item
Each node will have a circle with radius {\tt radius}.
\item
The {\tt firstEPSfile}
and {\tt secondEPSfile}
parameters is the output EPS file for the two plots.
\end{itemize}
\begin{figure}[htbp]
\caption{{\sc GRD7x7}: Working storage for the forward sparse
factorization of the nested dissection ordering.
On the left is the storage required to factor
${\widehat J}$ and its update matrix.
On the right is the storage required to factor
$J$ and all of its ancestors.
Both plots have the same scale.}
\label{fig-GRD7x7-FStree}
\begin{center}
\fbox{
\psfig{file=../../ETree/doc/FS1.eps,height=3.00in,width=3.00in}
}
\fbox{
\psfig{file=../../ETree/doc/FS2.eps,height=3.00in,width=3.00in}
}
\end{center}
\end{figure}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testHeight msglvl msgFile inETreeFile
\end{verbatim}
This driver program computes the height of the front tree with
respect to factor storage.
This quantity is the minimum amount of working storage
for a forward sparse factorization.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inETreeFile} parameter is the input file for the {\tt ETree}
object. It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testIO msglvl msgFile inFile outFile
\end{verbatim}
This driver program reads and writes {\tt ETree} files, useful for
converting formatted files to binary files and vice versa.
One can also read in a {\tt ETree} file and print out just the
header information (see the {\tt ETree\_writeStats()} method).
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inFile} parameter is the input file for the {\tt ETree}
object. It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\item
The {\tt outFile} parameter is the output file for the {\tt ETree}
object.
If {\tt outFile} is {\tt none} then the {\tt ETree} object is not
written to a file.
Otherwise, the {\tt ETree\_writeToFile()} method is called to write
the object to
a formatted file (if {\tt outFile} is of the form {\tt *.etreef}),
or
a binary file (if {\tt outFile} is of the form {\tt *.etreeb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testMaps msglvl msgFile inETreeFile outIVfile nthread type cutoff
\end{verbatim}
This program is used to construct an owners {\tt IV} that maps a
front to its owning thread or process.
The owners map {\tt IV} object is optionally written to a file.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inETreeFile} parameter is the input file for the {\tt ETree}
object. It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\item
The {\tt outIVFile} parameter is the output file for the
owners map {\tt IV} object.
If {\tt outIVFile} is {\tt none} then the {\tt IV} object is not
written to a file.
Otherwise, the {\tt IV\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outIVFile}
is of the form {\tt *.ivf}), or a binary file
(if {\tt outIVFile} is of the form {\tt *.ivb}).
\item
The {\tt nthread} parameter specifies the number of threads or
processes to be used.
\item
The {\tt type} parameter specifies the type of multisector.
\begin{itemize}
\item
{\tt type == 1}
--- use {\tt ETree\_wrapMap()} to compute a wrap mapping.
\item
{\tt type == 2}
--- use {\tt ETree\_balancedMap()} to compute a balanced mapping.
\item
{\tt type == 3}
--- use {\tt ETree\_subtreeSubset()}
to compute a subtree-subset mapping.
\item
{\tt type == 4}
--- use {\tt ETree\_ddMap()} to compute a domain decomposition map.
\end{itemize}
\item
{\tt cutoff} is a cutoff value for the multisector used only for
the domain decomposition map.
The cutoff defines the multisector, $0 \le \mbox{\tt cutoff} \le 1$.
If front {\tt J} has a subtree metric based on forward operations
that is greater than or equalt to {\tt cutoff} times the total
number of operations, then front {\tt J} belongs to the
multisector.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testMS msglvl msgFile inETreeFile outIVfile flag cutoff
\end{verbatim}
This program is used to extract a multisector from a front tree
{\tt ETree} object.
It partitions the vertices into domains and a multisector, where
each domain is a subtree of the elimination tree and the
multisector is the rest of the vertices.
The choice of the subtrees depends on the {\tt flag} and {\tt
cutoff} parameters --- it can be based on depth of a subtree or the
number of vertices, factor entries or factor operations associated
with the subtree.
The component ids {\tt IV} object is optionally written to a file.
Here is some sample output for {\tt BCSSTK30} ordered by nested
dissection, where the multisector is defined by subtree vertex
weight ({\tt flag = 2}) with {\tt cutoff = 0.125}.
\begin{verbatim}
region vertices entries operations metric/(avg domain)
0 1671 597058 255691396 0.797 2.201 3.967
1 3104 255341 33205237 1.481 0.941 0.515
2 3222 457255 116441261 1.537 1.685 1.806
3 1514 194916 41940202 0.722 0.718 0.651
4 2057 333186 100212056 0.981 1.228 1.555
5 77 5040 356454 0.037 0.019 0.006
6 1750 266166 62607526 0.835 0.981 0.971
7 1887 325977 101994905 0.900 1.202 1.582
8 3405 492662 125496320 1.624 1.816 1.947
9 3413 501150 141423868 1.628 1.847 2.194
10 3242 320220 51679456 1.546 1.180 0.802
11 2118 238011 44427959 1.010 0.877 0.689
12 1454 136777 18166107 0.694 0.504 0.282
13 10 106 1168 0.005 0.000 0.000
nvtx % nzf % ops %
domains 27253 94.22 3526807 85.52 837952519 76.620
schur complement 1671 5.78 597058 14.48 255691396 23.380
total 28924 4123865 1093643915
\end{verbatim}
Region {\tt 0} is the Schur complement, and there are thirteen
domains, eleven of good size.
A perfectly balanced tree would have eight domains using {\tt cutoff}
equal to 1/8.
It is interesting to see that the Schur complment contains only six
per cent of the vertices but almost one quarter the number of
operations.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inETreeFile} parameter is the input file for the {\tt ETree}
object. It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\item
The {\tt outIVFile} parameter is the output file for the {\tt IV}
object.
If {\tt outIVFile} is {\tt none} then the {\tt IV} object is not
written to a file.
Otherwise, the {\tt IV\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outIVFile}
is of the form {\tt *.ivf}), or a binary file
(if {\tt outIVFile} is of the form {\tt *.ivb}).
\item
The {\tt flag} parameter specifies the type of multisector.
\begin{itemize}
\item
{\tt flag == 1} --- the multisector is based on the depth of the
front, i.e., if the front is more than {\tt depth} steps removed
from the root, it forms the root of a domain.
\item
{\tt flag == 2} --- the multisector is based on the number of
vertices in a subtree, i.e., if the subtree rooted at a front
contains more than {\tt cutoff} times the total number of vertices,
it is a domain.
\item
{\tt flag == 3} --- the multisector is based on the number of
factor entries in a subtree, i.e., if the subtree rooted at a front
contains more than {\tt cutoff} times the total number of factor
entries, it is a domain.
\item
{\tt flag == 4} --- the multisector is based on the number of
factor operations in a subtree, i.e., if the subtree rooted at a front
contains more than {\tt cutoff} times the total number of factor
operations, it is a domain.
\end{itemize}
\item
{\tt cutoff} is a cutoff value for the multisector, see above
description when {\tt flag} equals {\tt 1}, {\tt 2} or {\tt 3}.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testStats msglvl msgFile inETreeFile labelflag radius firstEPSfile secondEPSfile
\end{verbatim}
This driver program computes one of five metrics associated with a
front tree and writes an EPS file that illustrates the metric overlaid
on the tree structure.
It first reads in a front tree object and
a graph file.
There are six possible plots:
\begin{center}
\begin{tabular}{c|l}
{\tt metricType} & type of metric \\ \hline
0 & no metric, just a tree plot \\
1 & \# of nodes in a front \\
2 & \# of original matrix entries in a front \\
3 & \# of factor matrix entries in a front \\
4 & \# of forward factor operations in a front \\
5 & \# of backward factor operations in a front
\end{tabular}
\end{center}
The maximum value of the metric creates a circle with radius
{\tt rmax}, and all other nodes have circles with their area
relative to this largest circle.
See Figure~\ref{fig-GRD7x7x7-metrics} contains four plots,
each used {\tt heightflag = 'D'}, {\tt coordflag = 'P'},
{\tt rmax = 20} and {\tt labelflag = 0}.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inETreeFile} parameter is the input file for the {\tt ETree}
object. It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt outEPSfile} parameter is the name of the EPS file
to hold the tree.
\item
The {\tt metricType} parameter defines the type of metric to be
illustrated. See above for values.
\item
For information about the {\tt heightflag} and {\tt coordflag}
parameters, see Section~\ref{subsection:Tree:proto:drawing}.
\item
If {\tt labelflag = 1}, the node ids are written on the nodes
in the two plots.
\item
The {\tt fontscale} parameter is the font size when labels are
drawn.
\end{itemize}
\begin{figure}[htbp]
\caption{{\sc GRD7x7x7}: Four tree plots for a $7 \times 7 \times 7$
grid matrix ordered using nested dissection.
The top left tree measure number of original matrix entries in a front.
The top right tree measure number of factor matrix entries in a front.
The bottom left tree measure number of factor operations in a front
for a forward looking factorization, e.g., forward sparse.
The bottom right tree measure number of factor operations in a front
for a backward looking factorization, e.g., general sparse.}
\label{fig-GRD7x7x7-metrics}
\begin{center}
\fbox{
\psfig{file=../../ETree/doc/GRD7x7x7_nzA.eps,height=3.00in,width=3.00in}
}
\fbox{
\psfig{file=../../ETree/doc/GRD7x7x7_nzF.eps,height=3.00in,width=3.00in}
}
\par
\fbox{
\psfig{file=../../ETree/doc/GRD7x7x7_forwops.eps,height=3.00in,width=3.00in}
}
\fbox{
\psfig{file=../../ETree/doc/GRD7x7x7_backops.eps,height=3.00in,width=3.00in}
}
\end{center}
\end{figure}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testStorage msglvl msgFile inETreeFile inGraphFile
\end{verbatim}
This driver program is used to evaluate the working storage for the
left-looking general sparse and multifrontal algorithms using the
natural post-order traversal of the front tree.
The output is in matlab format to produce a plot.
An example is found below.
\begin{center}
\makebox{
% \psfig{file=workingStorage.eps,width=3.0in,height=2.40in}
\psfig{file=../../ETree/doc/workingStorage.eps,width=3.0in,height=2.40in}
}
\end{center}
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inETreeFile} parameter is the input file for the {\tt ETree}
object. It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testTransform msglvl msgFile inETreeFile inGraphFile
outETreeFile maxzeros maxsize seed
\end{verbatim}
This driver program is used to transform a front tree {\tt ETree}
object into a (possibly) merged and (possibly) split front tree.
{\it Merging} the front tree means combining fronts together
that do not introduce more than {\tt maxzeros} zero entries in a
front. (See \cite{ash89-relaxed} and \cite{duf83-multifrontal}
for a description of this supernode amalgamation or relaxation.)
{\it Splitting} a front means breaking a front up into a chain of
smaller fronts; this allows more processors to work on the original
front in a straightforward manner.
The new front tree is optionally written to a file.
Here is some output for the {\tt R3D13824} matrix using
{\tt maxzeros = 1000} and {\tt maxsize = 64}.
\begin{verbatim}
CPU #fronts #indices #entries #ops
original : 6001 326858 3459359 1981403337
merge one : 0.209 3477 158834 3497139 2000297117
merge all : 0.136 748 95306 3690546 2021347776
merge any : 0.073 597 85366 3753241 2035158539
split : 0.202 643 115139 3753241 2035158539
final : 3.216 643 115128 3752694 2034396840
\end{verbatim}
Note how the number of fronts, front indices, factor entries and
factor operations change after each step.
Merging chains (the {\tt merge one} line) halves
the number of fronts while increasing operations by 1\%.
Merging all children when possible
(the {\tt merge all} line)
reduces the number of fronts by a factor of 5
while increasing operations by another 1\%.
Merging any other children (the {\tt merge any} line)
has another additional effect.
Splitting the fronts increases the number of fronts slightly,
but appears not to change the factor entries or operation counts.
This is false, as the final step computes the symbolic
factorization for the last front tree and updates the boundary
sizes of the fronts.
We see that the number of indices, entries and factor operations
actually decrease slightly due to the split fronts.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt ETree} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inETreeFile} parameter is the input file for the {\tt ETree}
object. It must be of the form {\tt *.etreef} or {\tt *.etreeb}.
The {\tt ETree} object is read from the file via the
{\tt ETree\_readFromFile()} method.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt outETreeFile} parameter is the output file for the {\tt ETree}
object.
If {\tt outETreeFile} is {\tt none} then the {\tt ETree} object is not
written to a file.
Otherwise, the {\tt ETree\_writeToFile()} method is called to write
the object to a formatted file (if {\tt outETreeFile}
is of the form {\tt *.etreef}), or a binary file
(if {\tt outETreeFile} is of the form {\tt *.etreeb}).
\item
The {\tt maxzeros} parameter is an upper bound on the number of
logically zero entries that will be allowed in a new front.
\item
The {\tt maxsize} parameter is an upper bound on the number of
vertices in a front --- any original front that contains more than
{\tt maxsize} vertices will be broken up into smaller fronts.
\item
{\tt seed} is a seed for a random number generator.
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
ne} then the {\tt IV} objeETree/doc/proto.tex 0100644 0002055 0007177 00000173074 06650174510 0015547 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt ETree} methods}
\label{section:ETree:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt ETree} object.
\par
\subsection{Basic methods}
\label{subsection:ETree:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ETree * ETree_new ( void ) ;
\end{verbatim}
\index{ETree_new@{\tt ETree\_new()}}
This method simply allocates storage for the {\tt ETree} structure
and then sets the default fields by a call to
{\tt ETree\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_setDefaultFields ( ETree *etree ) ;
\end{verbatim}
\index{ETree_setDefaultFields@{\tt ETree\_setDefaultFields()}}
This method sets the structure's fields are set to default values:
{\tt nfront = nvtx = 0}, {\tt tree = nodwghtsIV = bndwghtsIV =
vtxToFrontIV = NULL}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_clearData ( ETree *etree ) ;
\end{verbatim}
\index{ETree_clearData@{\tt ETree\_clearData()}}
This method clears data and releases any storage allocated by the
object.
If {\tt tree} is not {\tt NULL},
then {\tt Tree\_free(tree)} is called to free the {\tt Tree}
object.
It releases any storage held by the
{\tt nodwghtsIV}, {\tt bndwghtsIV}
and {\tt vtxToFrontIV} {\tt IV} objects
via calls to {\tt IV\_free()}.
It then sets the structure's default fields
with a call to {\tt ETree\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_free ( ETree *etree ) ;
\end{verbatim}
\index{ETree_free@{\tt ETree\_free()}}
This method releases any storage by a call to
{\tt ETree\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Instance methods}
\label{subsection:ETree:proto:instance}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_nfront ( ETree *etree ) ;
\end{verbatim}
\index{ETree_nfront@{\tt ETree\_nfront()}}
This method returns the number of fronts.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_nvtx ( ETree *etree ) ;
\end{verbatim}
\index{ETree_nvtx@{\tt ETree\_nvtx()}}
This method returns the number of vertices.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Tree * ETree_tree ( ETree *etree ) ;
\end{verbatim}
\index{ETree_tree@{\tt ETree\_tree()}}
This method returns a pointer to the {\tt Tree} object.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_root ( ETree *etree ) ;
\end{verbatim}
\index{ETree_root@{\tt ETree\_root()}}
This method returns the id of the root node.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt etree->tree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int * ETree_par ( ETree *etree ) ;
\end{verbatim}
\index{ETree_par@{\tt ETree\_par()}}
This method returns the pointer to the parent vector.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt etree->tree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int * ETree_fch ( ETree *etree ) ;
\end{verbatim}
\index{ETree_fch@{\tt ETree\_fch()}}
This method returns the pointer to the first child vector.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt etree->tree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int * ETree_sib ( ETree *etree ) ;
\end{verbatim}
\index{ETree_sib@{\tt ETree\_sib()}}
This method returns the pointer to the sibling vector.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt etree->tree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_nodwghtsIV ( ETree *etree ) ;
\end{verbatim}
\index{ETree_nodwghtsIV@{\tt ETree\_nodwghtsIV()}}
This method returns a pointer to the {\tt nodwghtsIV} object.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int * ETree_nodwghts ( ETree *etree ) ;
\end{verbatim}
\index{ETree_nodwghts@{\tt ETree\_nodwghts()}}
This method returns a pointer to the {\tt nodwghts} vector.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt etree->nodwghtsIV} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_bndwghtsIV ( ETree *etree ) ;
\end{verbatim}
\index{ETree_bndwghtsIV@{\tt ETree\_bndwghtsIV()}}
This method returns a pointer to the {\tt bndwghtsIV} object.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int * ETree_bndwghts ( ETree *etree ) ;
\end{verbatim}
\index{ETree_bndwghts@{\tt ETree\_bndwghts()}}
This method returns a pointer to the {\tt bndwghts} vector.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt etree->bndwghtsIV} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_vtxToFrontIV ( ETree *etree ) ;
\end{verbatim}
\index{ETree_vtxToFrontIV@{\tt ETree\_vtxToFrontIV()}}
This method returns a pointer to the {\tt vtxToFrontIV} object.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int * ETree_vtxToFront ( ETree *etree ) ;
\end{verbatim}
\index{ETree_vtxToFront@{\tt ETree\_vtxToFront()}}
This method returns a pointer to the {\tt vtxToFront} vector.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt etree->vtxToFrontIV} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_frontSize ( ETree *etree, int J ) ;
\end{verbatim}
\index{ETree_frontSize@{\tt ETree\_frontSize()}}
This method returns the number of internal degrees of freedom
in front {\tt J}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if {\tt J} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_frontBoundarySize ( ETree *etree, int J ) ;
\end{verbatim}
\index{ETree_frontBoundarySize@{\tt ETree\_frontBoundarySize()}}
This method returns the number of external or
boundary degrees of freedom in front {\tt J}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if {\tt J} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_maxNindAndNent ( ETree *etree, int symflag,
int *pmaxnind, int *pmaxnent ) ;
\end{verbatim}
\index{ETree_maxNindAndNent@{\tt ETree\_maxNindAndNent()}}
This method fills
{\tt *pmaxnind} with the maximum number of
indices for a front (just column indices if symmetric front,
row and column indices if nonsymmetric front)
and {\tt *pmaxnent} with the maximum number of
entries for a front (just upper entries if symmetric front,
all entries if nonsymmetric front).
The {\tt symflag} parameter must be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
The entries in the (2,2) block of the front are not counted.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initializer methods}
\label{subsection:ETree:proto:initializers}
\par
There are four initializer methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_init1 ( ETree *etree, int nfront, int nvtx ) ;
\end{verbatim}
\index{ETree_init1@{\tt ETree\_init1()}}
This method initializes an {\tt ETree} object given the number of
fronts and number of vertices.
Any previous data is cleared with a call to
{\tt ETree\_clearData()},
The {\tt Tree} object is initialized with a call to {\tt Tree\_init1()}.
The {\tt nodwghtsIV}, {\tt bndwghtsIV} and {\tt vtxToFrontIV} objects
are initialized with calls to {\tt IV\_init()}.
The entries in {\tt nodwghtsIV} and {\tt bndwghtsIV} are set to {\tt 0},
while the entries in {\tt vtxToFrontIV} are set to {\tt -1}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL}, or if {\tt nfront} is negative,
or if {\tt nvtx < nfront},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_initFromGraph ( ETree *etree, Graph *g ) ;
\end{verbatim}
\index{ETree_initFromGraph@{\tt ETree\_initFromGraph()}}
This method generates an elimination tree from a graph.
The {\tt nodwghtsIV} vector object is filled with the weights of the
vertices in the graph.
The {\tt tree->par} vector and {\tt bndwghtsIV} vector object
are filled using the simple $O(|L|)$ algorithm from \cite{liu90-etree}.
The {\tt fch[]}, {\tt sib[]} and {\tt root} fields of the included
{\tt Tree} object are then set.
{\tt vtxToFrontIV}, the {\tt IV} object that holds the map from
vertices to fronts, is set to the identity.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt g} is {\tt NULL} or {\tt g->nvtx} is negative,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_initFromGraphWithPerms ( ETree *etree, Graph *g ) ;
int newToOld[], int oldToNew[] ) ;
\end{verbatim}
\index{ETree_initFromGraphWithPerms@{\tt ETree\_initFromGraphWithPerms()}}
This method generates an elimination tree from a graph using two
permutation vectors.
The behavior of the method is exactly the same as the initializer
{\tt ETree\_initFromGraph()}, with the exception that
{\tt vtxToFrontIV}, the {\tt IV} object that holds the map from
vertices to fronts, is set to the {\tt oldToNew[]} map.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt g} is {\tt NULL} or {\tt g->nvtx} is negative,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_initFromDenseMatrix ( ETree *etree, int n, int option, int param ) ;
\end{verbatim}
\index{ETree_initFromDenseMatrix@{\tt ETree\_initFromDenseMatrix()}}
This method initializes a front tree to factor
a {\tt n x n} dense matrix.
If {\tt option == 1}, then all fronts (save possibly the last) have
the same number of internal vertices, namely {\tt param}.
If {\tt option == 2}, then we try to make all fronts have the same
number of entries in their (1,1), (1,2) and (2,1) blocks, namely
{\tt param} entries.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL} or if ${\tt n} <= 0$,
or if ${\tt option} < 1$,
or if $2 < {\tt option}$ ,
or if ${\tt param} \le 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_initFromFile ( ETree *etree, char *inETreeFileName,
int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{ETree_initFromFile@{\tt ETree\_initFromFile()}}
This method reads in an {\tt ETree} object from a file, gets the
old-to-new vertex permutation, permutes to vertex-to-front map,
and returns an {\tt IV} object that contains the old-to-new
permutation.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL}
or {\tt inETreeFileName} is ``{\tt none}'',
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_initFromSubtree ( ETree *subtree, IV *nodeidsIV, ETree *etree, IV *vtxIV ) ;
\end{verbatim}
\index{ETree_initFromSubtree@{\tt ETree\_initFromSubtree()}}
This method initializes {\tt subtree} from {\tt tree} using the
nodes of {\tt etree} that are found in {\tt nodeidsIV}.
The map from nodes in {\tt subtree} to nodes in {\tt etree}
is returned in {\tt vtxIV}.
\par \noindent {\it Return code: }
1 for a normal return,
-1 if {\tt subtree} is {\tt NULL},
-2 if {\tt nodeidsIV} is {\tt NULL},
-3 if {\tt etree} is {\tt NULL},
-4 if {\tt nodeidsIV} is invalid,
-5 if {\tt vtxIV} is {\tt NULL}.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:ETree:proto:utilities}
\par
The utility methods return the number of bytes taken by the object,
or the number of factor indices, entries or operations required by
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_sizeOf ( ETree *etree ) ;
\end{verbatim}
\index{ETree_sizeOf@{\tt ETree\_sizeOf()}}
This method returns the number of bytes taken by this object
(which includes the bytes taken by the internal {\tt Tree}
structure).
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_nFactorIndices ( ETree *etree ) ;
\end{verbatim}
\index{ETree_nFactorIndices@{\tt ETree\_nFactorIndices()}}
This method returns the number of indices taken by the factor matrix
that the tree represents.
Note, if the {\tt ETree} object is a vertex elimination tree,
the number of indices is equal to the number of entries.
If the number of compressed indices is required, create an {\tt
ETree} object to represent the tree of fundamental supernodes
and then call this method with this compressed tree.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt tree} is {\tt NULL}
or if $\mbox{\tt nfront} < 1$,
or if $\mbox{\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_nFactorEntries ( ETree *etree, int symflag ) ;
\end{verbatim}
\index{ETree_nFactorEntries@{\tt ETree\_nFactorEntries()}}
This method returns the number of entries taken by the factor matrix
that the tree represents.
The {\tt symflag} parameter can be one of
{\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or
{\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt tree} is {\tt NULL},
or if $\mbox{\tt nfront} < 1$,
or if $\mbox{\tt nvtx} < 1$,
or if {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double ETree_nFactorOps ( ETree *etree, int type, int symflag ) ;
\end{verbatim}
\index{ETree_nFactorOps@{\tt ETree\_nFactorOps()}}
This method returns the number of operations taken by the factor matrix
that the tree represents.
The {\tt type} parameter can be one of {\tt SPOOLES\_REAL} or
{\tt SPOOLES\_COMPLEX}.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt tree} is {\tt NULL},
or if $\mbox{\tt nfront} < 1$,
or if $\mbox{\tt nvtx} < 1$,
or if {\tt type} or {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double ETree_nFactorEntriesInFront ( ETree *etree, int symflag, int J ) ;
\end{verbatim}
\index{ETree_nFactorEntriesInFront@{\tt ETree\_nFactorEntriesInFront()}}
This method returns the number of entries in front {\tt J} for an
$LU$ factorization.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt tree} is {\tt NULL},
or if $\mbox{\tt nfront} < 1$,
or if {\tt symflag} is invalid,
or if ${\tt J} < 0$,
or if ${\tt J} \ge {\tt nfront}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double ETree_nInternalOpsInFront ( ETree *etree, int type, int symflag, int J ) ;
\end{verbatim}
\index{ETree_nInternalOpsInFront@{\tt ETree\_nInternalOpsInFront()}}
This method returns the number of internal operations performed
by front {\tt J} on its $(1,1)$, $(2,1)$, and $(1,2)$ blocks
during a factorization.
The {\tt type} parameter can be one of {\tt SPOOLES\_REAL} or
{\tt SPOOLES\_COMPLEX}.
{\tt symflag} must be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt tree} is {\tt NULL},
or if $\mbox{\tt nfront} < 1$,
or if {\tt type} or {\tt symflag} is invalid,
or if ${\tt J} < 0$,
or if ${\tt J} \ge {\tt nfront}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double ETree_nExternalOpsInFront ( ETree *etree, int type, int symflag, int J ) ;
\end{verbatim}
\index{ETree_nExternalOpsInFront@{\tt ETree\_nExternalOpsInFront()}}
This method returns the number of operations performed by front
{\tt J} on its $(2,2)$ block for an $LU$ factorization.
The {\tt type} parameter can be one of {\tt SPOOLES\_REAL} or
{\tt SPOOLES\_COMPLEX}.
{\tt symflag} must be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt tree} is {\tt NULL},
or if $\mbox{\tt nfront} < 1$,
or if {\tt type} or {\tt symflag} is invalid,
or if ${\tt J} < 0$,
or if ${\tt J} \ge {\tt nfront}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_factorEntriesIV ( ETree *etree, int symflag ) ;
\end{verbatim}
\index{ETree_factorEntriesIV@{\tt ETree\_factorEntriesIV()}}
This method creates and returns an {\tt IV} object that is filled
with the number of entries for the fronts.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
DV * ETree_backwardOps ( ETree *etree, int type, int symflag,
int vwghts[], IV *symbfacIVL ) ;
\end{verbatim}
\index{ETree_backwardOps@{\tt ETree\_backwardOps()}}
This method creates and returns a {\tt DV} object that is filled
with the backward operations (left-looking) for the fronts.
The {\tt type} parameter can be one of {\tt SPOOLES\_REAL} or
{\tt SPOOLES\_COMPLEX}.
{\tt symflag} must be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt symbfacIVL} is {\tt NULL},
or if {\tt type} or {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
DV * ETree_forwardOps ( ETree *etree, int type, int symflag ) ;
\end{verbatim}
\index{ETree_forwardOps@{\tt ETree\_forwardOps()}}
This method creates and returns a {\tt DV} object that is filled
with the forward operations (right-looking) for the fronts.
The {\tt type} parameter can be one of {\tt SPOOLES\_REAL} or
{\tt SPOOLES\_COMPLEX}.
{\tt symflag} must be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if {\tt type} or {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ETree * ETree_expand ( ETree *etree, IV *eqmapIV ) ;
\end{verbatim}
\index{ETree_expand@{\tt ETree\_expand()}}
This method creates and returns an {\tt ETree} object
for an uncompressed graph.
The map from compressed vertices to uncompressed vertices
is found in the {\tt eqmapIV} object.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt eqmapIV} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ETree * ETree_spliceTwoEtrees ( ETree *etree0, Graph *graph, IV *mapIV, ETree *etree1 ) ;
\end{verbatim}
\index{ETree_spliceTwoEtrees@{\tt ETree\_spliceTwoEtrees()}}
This method creates and returns an {\tt ETree} object that is
formed by splicing together two front trees,
{\tt etree0} for the vertices the eliminated domains,
{\tt etree1} for the vertices the Schur complement.
The {\tt mapIV} object maps vertices to domains or the Schur
complement --- if the entry is {\tt 0}, the vertex is in the Schur
complement, otherwise it is in a domain.
\par \noindent {\it Error checking:}
If {\tt etree0}, {\tt graph}, {\tt mapIV} or {\tt etree1} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\subsection{Metrics methods}
\label{subsection:ETree:proto:metrics}
\par
Many operations need to know some {\it metric} defined on the nodes
in a etree.
Here are three examples:
\begin{itemize}
\item
the weight of each front in the tree (this is just the {\tt
nodwghtsIV} object);
\item
the number of factor entries in each front
\item
the number of factor operations associated with each front in a
forward looking factorization.
\end{itemize}
Other metrics based on height, depth or subtree accumulation
can be evaluated using the {\tt Tree} metric methods on the
{\tt Tree} object contained in the {\tt ETree} object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_nvtxMetric ( ETree *etree ) ;
\end{verbatim}
\index{ETree_nvtxMetric@{\tt ETree\_nvtxMetric()}}
An {\tt IV} object of size {\tt nvtx} is created,
filled with the entries from {\tt etree->nodwghtsIV},
and returned.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_nentMetric ( ETree *etree, int symflag ) ;
\end{verbatim}
\index{ETree_nentMetric@{\tt ETree\_nentMetric()}}
An {\tt IV} object of size {\tt nfront} is created and returned.
Each entry of the vector is filled with the number of factor
entries associated with the corresponding front.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
DV * ETree_nopsMetric ( ETree *etree, int type, int symflag ) ;
\end{verbatim}
\index{ETree_nopsMetric@{\tt ETree\_nopsMetric()}}
An {\tt DV} object of size {\tt nfront} is created and returned.
Each entry of the vector is filled with the number of factor
operations associated with the corresponding front.
The {\tt type} parameter can be one of {\tt SPOOLES\_REAL} or
{\tt SPOOLES\_COMPLEX}.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
or if {\tt type} or {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Compression methods}
\label{subsection:ETree:proto:compression}
\par
Frequently an {\tt ETree} object will need to be compressed
in some manner.
Elimination trees usually have long chains of vertices at the higher
levels, where each chain of vertices corresponds to a supernode.
Liu's generalized row envelope methods partition the vertices by
longest chains \cite{liu91-generalizedEnvelope}.
In both cases, we can construct a map from each node to a set of
nodes to define a smaller, more compact {\tt ETree} object.
Given such a map, we construct the smaller etree.
\par
A fundamental chain is a set of vertices $v_1, \ldots, v_m$ such that
\begin{enumerate}
\item
$v_1$ is a leaf or has two or more children,
\item
$v_i$ is the only child of $v_{i+1}$ for $1 \le i < m$,
\item
$v_m$ is either a root or has a sibling.
\end{enumerate}
The set of fundamental chains is uniquely defined.
In the context of elimination etrees, a fundamental chain is very
close to a fundamental supernode, and in many cases,
fundamental chains can be used to contruct the fronts with little
added fill and factor operations.
\par
A fundamental supernode \cite{ash89-relaxed} is a set of vertices
$v_1, \ldots, v_m$ such that
\begin{enumerate}
\item
$v_1$ is a leaf or has two or more children,
\item
$v_i$ is the only child of $v_{i+1}$ for $1 \le i < m$,
\item
$v_m$ is either a root or has a sibling, and
\item
the structures of $v_i$ and $v_{i+1}$ are nested,
i.e.,
{\tt bndwght[$v_i$] =
nodwght[$v_{i+1}$] + bndwght[$v_{i+1}$]} for $1 \le i < m$.
\end{enumerate}
The set of fundamental supernodes is uniquely defined.
\par
Once a map from the nodes in a tree to nodes in a compressed tree
is known, the compressed tree can be created using the {\tt
ETree\_compress()} method.
In this way, a vertex elimination tree can be used to generate a
front tree.
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_fundChainMap ( ETree *etree ) ;
\end{verbatim}
\index{ETree_fundChainMap@{\tt ETree\_fundChainMap()}}
An {\tt IV} object of size {\tt nfront} is created,
filled via a call to {\tt Tree\_fundChainMap},
then returned.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt tree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_fundSupernodeMap ( ETree *etree ) ;
\end{verbatim}
\index{ETree_fundSupernodeMap@{\tt ETree\_fundSupernodeMap()}}
An {\tt IV} object of size {\tt nfront} is created,
filled with the map from vertices to fundamental supernodes,
then returned.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt tree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ETree * ETree_compress ( ETree *etree, IV *frontMapIV ) ;
\end{verbatim}
\index{ETree_compress@{\tt ETree\_compress()}}
Using {\tt frontMapIV}, a new {\tt ETree} object is created
and returned.
If {\tt frontMapIV} does not define each inverse map of a new node
to be connected set of nodes in the old {\tt ETree} object,
the new {\tt ETree} object will not be well defined.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt frontMapIV} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Justification methods}
\label{subsection:ETree:proto:justify}
\par
Given an {\tt ETree} object,
how should the children of a node be ordered?
This ``justification'' can have a large impact in the working
storage for the front etree in the multifrontal algorithm
\cite{liu85-mfstorage}.
Justification also is useful when displaying trees.
These methods simply check for errors and then call the appropriate
{\tt Tree} method.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_leftJustify ( ETree *etree ) ;
\end{verbatim}
\index{ETree_leftJustify@{\tt ETree\_leftJustify()}}
If {\tt u} and {\tt v} are siblings, and {\tt u} comes
before {\tt v} in a post-order traversal, then the size of the
subtree rooted at {\tt u} is as large or larger than the size of
the subtree rooted at {\tt v}.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt tree} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_leftJustifyI ( ETree *etree, IV *metricIV ) ;
void ETree_leftJustifyD ( ETree *etree, DV *metricDV ) ;
\end{verbatim}
\index{ETree_leftJustifyI@{\tt ETree\_leftJustifyI()}}
\index{ETree_leftJustifyD@{\tt ETree\_leftJustifyD()}}
Otherwise, if {\tt u} and {\tt v} are siblings, and {\tt u} comes
before {\tt v} in a post-order traversal, then the weight of the
subtree rooted at {\tt u} is as large or larger than the weight of
the subtree rooted at {\tt v}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
or if {\tt metricIV} is {\tt NULL}
or invalid (wrong size or {\tt NULL} vector inside),
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Permutation methods}
\label{subsection:ETree:proto:permutation}
\par
Often we need to extract a permutation from an {\tt ETree} object,
e.g., a post-order traversal of a front tree gives an ordering of the
fronts for a factorization or forward solve, the inverse
gives an ordering for a backward solve.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_newToOldFrontPerm ( ETree *etree ) ;
IV * ETree_oldToNewFrontPerm ( ETree *etree ) ;
\end{verbatim}
\index{ETree_newToOldFrontPerm@{\tt ETree\_newToOldFrontPerm()}}
\index{ETree_oldToNewFrontPerm@{\tt ETree\_oldToNewFrontPerm()}}
An {\tt IV} object is created with size {\tt nfront}.
A post-order traversal of the {\tt Tree} object fills
the new-to-old permutation.
A reversal of the new-to-old permutation gives the
old-to-new permutation.
Both methods are simply wrappers around the respective
{\tt Tree} methods.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_newToOldVtxPerm ( ETree *etree ) ;
IV * ETree_oldToNewVtxPerm ( ETree *etree ) ;
\end{verbatim}
\index{ETree_newToOldVtxPerm@{\tt ETree\_newToOldVtxPerm()}}
\index{ETree_oldToNewVtxPerm@{\tt ETree\_oldToNewVtxPerm()}}
An {\tt IV} object is created with size {\tt nvtx}.
First we find a new-to-old permutation of the fronts.
Then we search over the fronts in their new order to
fill the vertex new-to-old permutation vector.
The old-to-new vertex permutation vector is found by first finding
the new-to-old vertex permutation vector, then inverting it.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_permuteVertices ( ETree *etree, IV *vtxOldToNewIV ) ;
\end{verbatim}
\index{ETree_permuteVertices@{\tt ETree\_permuteVertices()}}
This method permutes the vertices --- the {\tt vtxToFrontIV} map is
updated to reflect the new vertex numbering.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt vtxOldToNewIV} is {\tt NULL},
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Multisector methods}
\label{subsection:ETree:proto:multisector}
One of our goals is to improve a matrix ordering using the
multisection ordering algorithm.
To do this, we need to extract a multisector from the vertices,
i.e., a set of nodes that when removed from the graph, break the
remaining vertices into more than one (typically many) components.
The following two methods create and return an {\tt IV} integer
vector object that contains the nodes in the multisector.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_msByDepth ( ETree *etree, int depth ) ;
\end{verbatim}
\index{ETree_msByDepth@{\tt ETree\_msByDepth()}}
An {\tt IV} object is created to hold the multisector nodes
and returned.
Multisector nodes have their component id zero,
domain nodes have their component id one.
A vertex is in the multisector if the depth of the front to which
it belongs is less than or equal to {\tt depth}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
or if ${\tt depth} \le 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_msByNvtxCutoff ( ETree *etree, double cutoff ) ;
\end{verbatim}
\index{ETree_msByNvtxCutoff@{\tt ETree\_msByNvtxCutoff()}}
An {\tt IV} object is created to hold the multisector nodes
and returned.
Multisector nodes have their component id zero,
domain nodes have their component id one.
Inclusion in the multisector is based on the number of vertices
in the subtree that a vertex belongs, or strictly speaking, the
number of vertices in the subtree of the front to which a vertex
belongs.
If weight of the subtree is more than {\tt cutoff} times the vertex
weight, the vertex is in the multisector.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_msByNentCutoff ( ETree *etree, double cutoff, int symflag ) ;
\end{verbatim}
\index{ETree_msByNentCutoff@{\tt ETree\_msByNentCutoff()}}
An {\tt IV} object is created to hold the multisector nodes
and returned.
Multisector nodes have their component id zero,
domain nodes have their component id one.
Inclusion in the multisector is based on the number of factor
entries in the subtree that a vertex belongs, or strictly speaking,
the number of factor entries in the subtree of the front to which
a vertex belongs.
If weight of the subtree is more than {\tt cutoff} times the number
of factor entries, the vertex is in the multisector.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
or if {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_msByNopsCutoff ( ETree *etree, double cutoff, int type, int symflag ) ;
\end{verbatim}
\index{ETree_msByNopsCutoff@{\tt ETree\_msByNopsCutoff()}}
An {\tt IV} object is created to hold the multisector nodes
and returned.
Multisector nodes have their component id zero,
domain nodes have their component id one.
Inclusion in the multisector is based on the number of right-looking
factor operations in the subtree that a vertex belongs,
or strictly speaking, the number of factor operations
in the subtree of the front to which a vertex belongs.
If weight of the subtree is more than {\tt cutoff} times the number
of factor operations, the vertex is in the multisector.
The {\tt type} parameter can be one of {\tt SPOOLES\_REAL} or
{\tt SPOOLES\_COMPLEX}.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
or if {\tt type} or {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_msStats ( ETree *etree, IV *msIV, IV *nvtxIV, IV *nzfIV,
DV *opsDV, int type, int symflag ) ;
\end{verbatim}
\index{ETree_msStats@{\tt ETree\_msStats()}}
This method is used to generate some statistics about a domain
decomposition.
On input, {\tt msIV} is a flag vector,
i.e., {\tt ms[v] = 0} means that {\tt v} is in the Schur
complement, otherwise {\tt v} is in domain.
On output, {\tt msIV} is a map from nodes to regions,
i.e., {\tt ms[v] = 0} means that {\tt v} is in the Schur
complement, otherwise {\tt v} is in domain {\tt ms[v]}.
On output, {\tt nvtxIV} contains the number of vertices in each of
the regions,
{\tt nzfIV} contains the number of factor entries in each of
the regions, and
{\tt opsIV} contains the number of factor operations in each of
the regions.
The {\tt type} parameter can be one of {\tt SPOOLES\_REAL} or
{\tt SPOOLES\_COMPLEX}.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree}, {\tt msIV}, {\tt nvtxIV}, {\tt nzfIV}
or {\tt opsIV} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_optPart ( ETree *etree, Graph *graph, IVL *symbfacIVL,
double alpha, int *ptotalgain, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{ETree_optPart@{\tt ETree\_optPart()}}
This method is used to find the optimal domain/Schur complement
partition for a semi-implicit factorization.
The gain of a subtree ${\widehat J}$ is equal to
$|L_{\partial{J},{\widehat J}}|
- |A_{\partial{J},{\widehat J}}|
- \alpha |L_{{\widehat J},{\widehat J}}|$.
When $\alpha = 0$, we minimize active storage,
when $\alpha = 1$, we minimize solve operations.
On return, {\tt *ptotalgain} is filled with the total gain.
The return value is a pointer to {\tt compidsIV},
where {\tt compids[J] = 0} means that {\tt J} is in the Schur
complement,
and {\tt compids[J] != 0} means that {\tt J} is in
domain {\tt compids[J]}.
\par \noindent {\it Error checking:}
If {\tt etree}, {\tt graph} or {\tt symbfacIVL}
is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Transformation methods}
\label{subsection:ETree:proto:transformation}
Often the elimination tree or front tree that we obtain from an
ordering of the graph is not as appropriate for a factorization as
we would like.
There are two important cases.
\begin{itemize}
\item
Near the leaves of the tree the fronts are typically small in size.
There is an overhead associated with each front, and though the
overhead varies with regard to the factorization algorithm, it can
be beneficial to group small subtrees together into one front.
The expense is added storage for the logically zero entries and the
factor operations on them.
In this library, the technique we use to merge fronts together is
{\it node amalgamation} \cite{duf83-multifrontal},
or more specifically {\it supernode relaxation} \cite{ash89-relaxed}.
\item
Near the root of the tree the fronts can be very large, large
enough that special techniques are necessary to handle the large
dense frontal matrices that might not be able to exist in-core.
Another consideration is a parallel setting where the design
decision is to have each front be factored by a single thread of
computation.
Large fronts dictate a long critical path in the factorization task
graph.
We try to split a large front into two or more smaller fronts
that form a chain in the front tree.
Breaking the front into smaller fronts will reduce core storage
requirements and have better cache reuse and reduce the critical
path through the task graph.
\end{itemize}
We provide three methods to merge fronts together and one method to
break fronts apart, and one method that is a wrapper around all these.
Let us describe the differences between the methods that merge
fronts together.
Each method performs a post-order traversal of the front tree.
They differ on the decision process when visiting a front.
\begin{itemize}
\item
The method {\tt ETree\_mergeFrontsAny()} is taken from
\cite{ash89-relaxed}.
When visiting a front it tries to merge that front
with one of its children if it will not add too many zero entries
to that front. If successful, it tries to merge the front with
another child.
This approach has served well for over a decade in a serial
environment, but we discovered that it has a negative effect
on nested dissection orderings when we want a parallel
factorization.
Often it merges the top level separator with {\it one} of its
children, and thus reduces parallelism in the front tree.
\item
The method {\tt ETree\_mergeFrontsOne()}
only tries to merge a front when it has only one child.
This method is very useful if one has a vertex elimination tree
(where the number of fronts is equal to the number of vertices),
for the fundamental supernode tree can be created using
{\tt maxzeros = 0}.
This method has some affect for minimum degree or fill orderings,
where chains of nodes can occur in two ways: aggregation (where a
vertex is eliminated that is adjacent to only one subtree) or when
the indistinguishabilty test fails.
In general, this method does not effectively reduce the number
of fronts because it has the ``parent-only child'' restriction.
\item
The method {\tt ETree\_mergeFrontsAll()} tries to merge a front
with {\it all} of its children, if the resulting front does not
contain too many zero entries.
This has the effect of merging small bushy subtrees, but will not
merge a top level separator with one of its children.
\end{itemize}
For a serial application, {\tt ETree\_mergeFrontsAny()} is suitable.
For a parallel application, we recommend first using
{\tt ETree\_mergeFrontsOne()}
followed by
{\tt ETree\_mergeFrontsAll()}.
See the driver programs {\tt testTransform} and {\tt mkNDETree}
for examples of how to call the methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ETree * ETree_mergeFrontsOne ( ETree *etree, int maxzeros, IV *nzerosIV ) ;
\end{verbatim}
\index{ETree_mergeFrontsOne@{\tt ETree\_mergeFrontsOne()}}
This method only tries to merge a front with its only child.
It returns an {\tt ETree} object where one or more
subtrees that contain multiple fronts
have been merged into single fronts.
The parameter that governs the merging process is {\tt maxzeros},
the number of zero entries that can be introduced by merging
a child and parent front together.
On input, {\tt nzerosIV} contains the number of zeros presently in
each front.
It is modified on output to correspond with the new front tree.
This method only tries to merge a front with its only child.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ETree * ETree_mergeFrontsAll ( ETree *etree, int maxzeros ) ;
\end{verbatim}
\index{ETree_mergeFrontsAll@{\tt ETree\_mergeFrontsAll()}}
This method only tries to merge a front with all of its children.
It returns an {\tt ETree} object where a front
has either been merged with none or all of its children.
The parameter that governs the merging process is {\tt maxzeros},
the number of zero entries that can be introduced by merging
the children and parent front together.
On input, {\tt nzerosIV} contains the number of zeros presently in
each front.
It is modified on output to correspond with the new front tree.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ETree * ETree_mergeFrontsAny ( ETree *etree, int maxzeros ) ;
\end{verbatim}
\index{ETree_mergeFrontsAny@{\tt ETree\_mergeFrontsAny()}}
This method only tries to merge a front with any subset of its children.
It returns an {\tt ETree} object where a front has
possibly merged with any of its children.
The parameter that governs the merging process is {\tt maxzeros},
the number of zero entries that can be introduced by merging
the children and parent front together.
On input, {\tt nzerosIV} contains the number of zeros presently in
each front.
It is modified on output to correspond with the new front tree.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ETree * ETree_splitFronts ( ETree *etree, int vwghts[],
int maxfrontsize, int seed ) ;
\end{verbatim}
\index{ETree_splitFronts@{\tt ETree\_splitFronts()}}
This method returns an {\tt ETree} object where one or more large
fronts have been split into smaller fronts.
Only an interior front (a front that is not a leaf in the tree)
can be split.
No front in the returned {\tt ETree} object has more than
{\tt maxfrontsize} rows and columns.
The {\tt vwghts[]} vector stores the number of degrees of freedom
associated with a vertex; if {\tt vwghts} is {\tt NULL}, then the
vertices have unit weight.
The way the vertices in a front to be split are assigned to smaller
fronts is random; the {\tt seed} parameter is a seed to a random
number generator that permutes the vertices in a front.
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
or if ${\tt maxfrontsize} \le 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ETree * ETree_transform ( ETree *etree, int vwghts[], int maxzeros,
int maxfrontsize, int seed ) ;
ETree * ETree_transform2 ( ETree *etree, int vwghts[], int maxzeros,
int maxfrontsize, int seed ) ;
\end{verbatim}
\index{ETree_transform@{\tt ETree\_transform()}}
\index{ETree_transform2@{\tt ETree\_transform2()}}
These methods returns an {\tt ETree} object where one or more subtrees
that contain multiple fronts have been merged into single fronts and
where one or more large fronts have been split into smaller fronts.
The two methods differ slightly.
{\tt ETree\_transform2()} is better suited for parallel computing
because it tends to preserve the tree branching properties.
(A front is merged with either an only child or all children.
{\tt ETree\_transform()} can merge a front with any subset of its
children.)
\par \noindent {\it Error checking:}
If {\tt etree} is {\tt NULL},
or if ${\tt nfront} < 1$,
or if ${\tt nvtx} < 1$,
or if ${\tt maxfrontsize} \le 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Parallel factorization map methods}
\label{subsection:ETree:proto:map}
This family of methods create a map from the fronts to processors
or threads, used in a parallel factorization.
\par
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * ETree_wrapMap ( ETree *etree, int type, int symflag, DV *cumopsDV ) ;
IV * ETree_balancedMap ( ETree *etree, int type,
int symflag, DV *cumopsDV ) ;
IV * ETree_subtreeSubsetMap ( ETree *etree, int type,
int symflag,DV *cumopsDV ) ;
IV * ETree_ddMap ( ETree *etree, int type, int symflag,
DV *cumopsDV, double cutoff ) ;
IV * ETree_ddMapNew ( ETree *etree, int type, int symflag,
IV *msIV, DV *cumopsDV ) ;
\end{verbatim}
\index{ETree_wrapMap@{\tt ETree\_wrapMap()}}
\index{ETree_balancedMap@{\tt ETree\_balancedMap()}}
\index{ETree_subtreeSubsetMap@{\tt ETree\_subtreeSubsetMap()}}
\index{ETree_ddMap@{\tt ETree\_ddMap()}}
\index{ETree_ddMapNew@{\tt ETree\_ddMapNew()}}
These methods construct and return an {\tt IV} object that contains
the map from fronts to threads.
The size of the input {\tt cumopsDV} object is the number of
threads or processors.
On output, {\tt cumopsDV} contains the number of factor operations
performed by the threads or processors for a fan-in factorization.
The {\tt type} parameter can be one of {\tt SPOOLES\_REAL} or
{\tt SPOOLES\_COMPLEX}.
{\tt symflag} must be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par
\begin{itemize}
\item
The simplest map is the {\it wrap map}, where front {\tt J} is
assigned to thread or processor {\tt J \% nthread}.
\item
The {\it balanced map} attempts to balance the computations across the
threads or processes, where the fronts are visited in a post-order
traversal of the tree and a front is assigned to a thread or
processor with the least number of accumulated operations thus far.
\item
The {\it subtree-subset map} is the most complex, where subsets of
threads or processors are assigned to subtrees via a pre-order
traversal of the tree. (Each root of the tree can be assigned to
all processors.)
The tree is then visited in a post-order traversal, and each front
is assigned to an eligible thread or processor with the least
number of accumulated ops so far.
\item
The {\it domain decomposition map} is also complex,
where domains are mapped to threads, then the fronts in the schur
complement are mapped to threads, both using independent balanced maps.
The method {\tt ETree\_ddMapNew()} is more robust than {\tt
ETree\_ddMap()}, and is more general in the sense that it takes
a multisector vector as input.
The {\tt msIV} object is a map from the vertices to $\{0,1\}$.
A vertex mapped to 0 lies in the Schur complement,
a vertex mapped to 1 lies in a domain.
\end{itemize}
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt cumopsDV} is {\tt NULL},
or if {\tt type} or {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Storage profile methods}
\label{subsection:ETree:proto:storage}
\par
These methods fill a vector with the total amount of working
storage necessary during the factor and solves.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_MFstackProfile ( ETree *etree, int type, double dvec[] ) ;
\end{verbatim}
\index{ETree_MFstackProfile@{\tt ETree\_MFstackProfile()}}
\par
On return, {\tt dvec[J]} contains the amount of active storage to
eliminate {\tt J} using the multifrontal method and the natural
post-order traversal.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt dvec} are {\tt NULL},
or if {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_GSstorageProfile ( ETree *etree, int type, IVL *symbfacIVL,
int *vwghts, double dvec[] ) ;
\end{verbatim}
\index{ETree_GSstorageProfile@{\tt ETree\_GSstorageProfile()}}
\par
On return, {\tt dvec[J]} contains the amount of active storage to
eliminate {\tt J} using the left-looking general sparse method
and the natural post-order traversal.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt dvec} are {\tt NULL},
or if {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_FSstorageProfile ( ETree *etree, int type, IVL *symbfacIVL,
double dvec[] ) ;
\end{verbatim}
\index{ETree_FSstorageProfile@{\tt ETree\_FSstorageProfile()}}
\par
On return, {\tt dvec[J]} contains the amount of active storage to
eliminate {\tt J} using the right-looking forward sparse method
and the natural post-order traversal.
The {\tt symflag} parameter can be one of {\tt SPOOLES\_SYMMETRIC},
{\tt SPOOLES\_HERMITIAN} or {\tt SPOOLES\_NONSYMMETRIC}.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt dvec} are {\tt NULL},
or if {\tt symflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_forwSolveProfile ( ETree *etree, double dvec[] ) ;
\end{verbatim}
\index{ETree_forwSolveProfile@{\tt ETree\_forwSolveProfile()}}
\par
On return, {\tt dvec[J]} contains the amount of stack storage to
solve for {\tt J} using the multifrontal-based forward solve.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt dvec} are {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void ETree_backSolveProfile ( ETree *etree, double dvec[] ) ;
\end{verbatim}
\index{ETree_backSolveProfile@{\tt ETree\_backSolveProfile()}}
\par
On return, {\tt dvec[J]} contains the amount of stack storage to
solve for {\tt J} using the multifrontal-based backward solve.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt dvec} are {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:ETree:proto:IO}
\par
There are the usual eight IO routines.
The file structure of a tree object is simple:
{\tt nfront}, {\tt nvtx},
a {\tt Tree} object followed by the
{\tt nodwghtsIV},
{\tt bndwghtsIV} and
{\tt vtxToFrontIV} objects.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_readFromFile ( ETree *etree, char *fn ) ;
\end{verbatim}
\index{ETree_readFromFile@{\tt ETree\_readFromFile()}}
\par
This method reads an {\tt ETree} object from a file
whose name is stored in {\tt *fn}.
It tries to open the file and if it is successful,
it then calls {\tt ETree\_readFromFormattedFile()} or
{\tt ETree\_readFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.etreef} (for a formatted file)
or {\tt *.etreeb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_readFromFormattedFile ( ETree *etree, FILE *fp ) ;
\end{verbatim}
\index{ETree_readFromFormattedFile@{\tt ETree\_readFromFormattedFile()}}
\par
This method reads an {\tt ETree} object from a formatted file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fscanf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_readFromBinaryFile ( ETree *etree, FILE *fp ) ;
\end{verbatim}
\index{ETree_readFromBinaryFile@{\tt ETree\_readFromBinaryFile()}}
\par
This method reads an {\tt ETree} object from a formatted file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fread}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_writeToFile ( ETree *etree, char *fn ) ;
\end{verbatim}
\index{ETree_writeToFile@{\tt ETree\_writeToFile()}}
\par
This method writes an {\tt ETree} object to a file
whose name is stored in {\tt *fn}.
An attempt is made to open the file and if successful,
it then calls {\tt ETree\_writeFromFormattedFile()}
for a formatted file, or
{\tt ETree\_writeFromBinaryFile()} for a binary file.
The method then closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.etreef} (for a formatted file)
or {\tt *.etreeb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_writeToFormattedFile ( ETree *etree, FILE *fp ) ;
\end{verbatim}
\index{ETree_writeToFormattedFile@{\tt ETree\_writeToFormattedFile()}}
\par
This method writes an {\tt ETree} object to a formatted file.
Otherwise, the data is written to the file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fprintf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_writeToBinaryFile ( ETree *etree, FILE *fp ) ;
\end{verbatim}
\index{ETree_writeToBinaryFile@{\tt ETree\_writeToBinaryFile()}}
\par
This method writes an {\tt ETree} object to a binary file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fwrite}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_writeForHumanEye ( ETree *etree, FILE *fp ) ;
\end{verbatim}
\index{ETree_writeForHumanEye@{\tt ETree\_writeForHumanEye()}}
\par
This method writes an {\tt ETree} object to a file in a readable
format.
Otherwise, the method {\tt ETree\_writeStats()}
is called to write out the
header and statistics.
Then the parent, first child, sibling, node weight and boundary
weight values are printed out in five columns.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int ETree_writeStats ( ETree *etree, FILE *fp ) ;
\end{verbatim}
\index{ETree_writeStats@{\tt ETree\_writeStats()}}
\par
This method write a header and some statistics to a file.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt etree} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
r processors are assigned to subtrees via a pre-order
traversal of the tree. (Each root of the tree can be assigned to
all processors.)
The tree is then visited in a post-order traversal, and each front
is assigned to an eligible thread or processor with the least
number of accumulated ops so far.
\item
The {\it domain decomposition map} is also complex,
where domains are mapped to threads, then the fronts in the schur
complement are mapped to thrETree/doc/main.ind 0100644 0002055 0007177 00000006271 06653142247 0015301 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt ETree\_backSolveProfile()}, 17
\item {\tt ETree\_backwardOps()}, 7
\item {\tt ETree\_balancedMap()}, 15
\item {\tt ETree\_bndwghts()}, 4
\item {\tt ETree\_bndwghtsIV()}, 3
\item {\tt ETree\_clearData()}, 2
\item {\tt ETree\_compress()}, 10
\item {\tt ETree\_ddMap()}, 15
\item {\tt ETree\_ddMapNew()}, 15
\item {\tt ETree\_expand()}, 7
\item {\tt ETree\_factorEntriesIV()}, 7
\item {\tt ETree\_fch()}, 3
\item {\tt ETree\_forwardOps()}, 7
\item {\tt ETree\_forwSolveProfile()}, 16
\item {\tt ETree\_free()}, 2
\item {\tt ETree\_frontBoundarySize()}, 4
\item {\tt ETree\_frontSize()}, 4
\item {\tt ETree\_FSstorageProfile()}, 16
\item {\tt ETree\_fundChainMap()}, 9
\item {\tt ETree\_fundSupernodeMap()}, 9
\item {\tt ETree\_GSstorageProfile()}, 16
\item {\tt ETree\_init1()}, 4
\item {\tt ETree\_initFromDenseMatrix()}, 5
\item {\tt ETree\_initFromFile()}, 5
\item {\tt ETree\_initFromGraph()}, 5
\item {\tt ETree\_initFromGraphWithPerms()}, 5
\item {\tt ETree\_initFromSubtree()}, 5
\item {\tt ETree\_leftJustify()}, 10
\item {\tt ETree\_leftJustifyD()}, 10
\item {\tt ETree\_leftJustifyI()}, 10
\item {\tt ETree\_maxNindAndNent()}, 4
\item {\tt ETree\_mergeFrontsAll()}, 14
\item {\tt ETree\_mergeFrontsAny()}, 14
\item {\tt ETree\_mergeFrontsOne()}, 14
\item {\tt ETree\_MFstackProfile()}, 16
\item {\tt ETree\_msByDepth()}, 11
\item {\tt ETree\_msByNentCutoff()}, 11
\item {\tt ETree\_msByNopsCutoff()}, 12
\item {\tt ETree\_msByNvtxCutoff()}, 11
\item {\tt ETree\_msStats()}, 12
\item {\tt ETree\_nentMetric()}, 8
\item {\tt ETree\_new()}, 2
\item {\tt ETree\_newToOldFrontPerm()}, 10
\item {\tt ETree\_newToOldVtxPerm()}, 11
\item {\tt ETree\_nExternalOpsInFront()}, 7
\item {\tt ETree\_nFactorEntries()}, 6
\item {\tt ETree\_nFactorEntriesInFront()}, 6
\item {\tt ETree\_nFactorIndices()}, 6
\item {\tt ETree\_nFactorOps()}, 6
\item {\tt ETree\_nfront()}, 2
\item {\tt ETree\_nInternalOpsInFront()}, 7
\item {\tt ETree\_nodwghts()}, 3
\item {\tt ETree\_nodwghtsIV()}, 3
\item {\tt ETree\_nopsMetric()}, 8
\item {\tt ETree\_nvtx()}, 3
\item {\tt ETree\_nvtxMetric()}, 8
\item {\tt ETree\_oldToNewFrontPerm()}, 10
\item {\tt ETree\_oldToNewVtxPerm()}, 11
\item {\tt ETree\_optPart()}, 12
\item {\tt ETree\_par()}, 3
\item {\tt ETree\_permuteVertices()}, 11
\item {\tt ETree\_readFromBinaryFile()}, 17
\item {\tt ETree\_readFromFile()}, 17
\item {\tt ETree\_readFromFormattedFile()}, 17
\item {\tt ETree\_root()}, 3
\item {\tt ETree\_setDefaultFields()}, 2
\item {\tt ETree\_sib()}, 3
\item {\tt ETree\_sizeOf()}, 6
\item {\tt ETree\_spliceTwoEtrees()}, 8
\item {\tt ETree\_splitFronts()}, 14
\item {\tt ETree\_subtreeSubsetMap()}, 15
\item {\tt ETree\_transform()}, 15
\item {\tt ETree\_transform2()}, 15
\item {\tt ETree\_tree()}, 3
\item {\tt ETree\_vtxToFront()}, 4
\item {\tt ETree\_vtxToFrontIV()}, 4
\item {\tt ETree\_wrapMap()}, 15
\item {\tt ETree\_writeForHumanEye()}, 18
\item {\tt ETree\_writeStats()}, 18
\item {\tt ETree\_writeToBinaryFile()}, 18
\item {\tt ETree\_writeToFile()}, 17
\item {\tt ETree\_writeToFormattedFile()}, 17
\end{theindex}
ETree/doc/main.ilg 0100644 0002055 0007177 00000000457 06653142247 0015302 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (82 entries accepted, 0 rejected).
Sorting entries....done (511 comparisons).
Generating output file main.ind....done (86 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
ETree/doc/workingStorage.eps 0100644 0002055 0007177 00000121576 06534106075 0017402 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%Creator: MATLAB, The Mathworks, Inc.
%%Title: workingStorage.eps
%%CreationDate: 09/05/97 13:55:11
%%DocumentNeededFonts: Helvetica
%%DocumentProcessColors: Cyan Magenta Yellow Black
%%Pages: 1
%%BoundingBox: 56 201 549 600
%%EndComments
%%BeginProlog
% MathWorks dictionary
/MathWorks 150 dict begin
% definition operators
/bdef {bind def} bind def
/ldef {load def} bind def
/xdef {exch def} bdef
/xstore {exch store} bdef
% operator abbreviations
/c /clip ldef
/cc /concat ldef
/cp /closepath ldef
/gr /grestore ldef
/gs /gsave ldef
/mt /moveto ldef
/np /newpath ldef
/cm /currentmatrix ldef
/sm /setmatrix ldef
/rc {rectclip} bdef
/rf {rectfill} bdef
/rm /rmoveto ldef
/rl /rlineto ldef
/s /show ldef
/sc {setcmykcolor} bdef
/sr /setrgbcolor ldef
/sg /setgray ldef
/w /setlinewidth ldef
/j /setlinejoin ldef
/cap /setlinecap ldef
% page state control
/pgsv () def
/bpage {/pgsv save def} bdef
/epage {pgsv restore} bdef
/bplot /gsave ldef
/eplot {stroke grestore} bdef
% orientation switch
/portraitMode 0 def
/landscapeMode 1 def
% coordinate system mappings
/dpi2point 0 def
% font control
/FontSize 0 def
/FMS {
/FontSize xstore %save size off stack
findfont
[FontSize 0 0 FontSize neg 0 0]
makefont
setfont
}bdef
/reencode {
exch dup where
{pop load} {pop StandardEncoding} ifelse
exch
dup 3 1 roll
findfont dup length dict begin
{ 1 index /FID ne {def}{pop pop} ifelse } forall
/Encoding exch def
currentdict
end
definefont pop
} bdef
/isroman {
findfont /CharStrings get
/Agrave known
} bdef
/FMSR {
3 1 roll 1 index
dup isroman
{reencode} {pop pop} ifelse
exch FMS
} bdef
/csm {
1 dpi2point div -1 dpi2point div scale
neg translate
landscapeMode eq {90 rotate} if
} bdef
% line types: solid, dotted, dashed, dotdash
/SO { [] 0 setdash } bdef
/DO { [.5 dpi2point mul 4 dpi2point mul] 0 setdash } bdef
/DA { [6 dpi2point mul] 0 setdash } bdef
/DD { [.5 dpi2point mul 4 dpi2point mul 6 dpi2point mul 4 dpi2point mul] 0 setdash } bdef
% macros for lines and objects
/L {
lineto
stroke
} bdef
/MP {
3 1 roll moveto
1 sub {rlineto} repeat
} bdef
/AP {
{rlineto} repeat
} bdef
/PP {
closepath eofill
} bdef
/DP {
closepath stroke
} bdef
/MR {
4 -2 roll moveto
dup 0 exch rlineto
exch 0 rlineto
neg 0 exch rlineto
closepath
} bdef
/FR {
MR stroke
} bdef
/PR {
MR fill
} bdef
/L1i {
{ currentfile picstr readhexstring pop } image
} bdef
/tMatrix matrix def
/MakeOval {
newpath
tMatrix currentmatrix pop
translate scale
0 0 1 0 360 arc
tMatrix setmatrix
} bdef
/FO {
MakeOval
stroke
} bdef
/PO {
MakeOval
fill
} bdef
/PD {
currentlinecap 1 setlinecap 3 1 roll 2 copy moveto lineto stroke setlinecap
} bdef
/FA {
newpath
tMatrix currentmatrix pop
translate scale
0 0 1 5 -2 roll arc
tMatrix setmatrix
stroke
} bdef
/PA {
newpath
tMatrix currentmatrix pop
translate 0 0 moveto scale
0 0 1 5 -2 roll arc
closepath
tMatrix setmatrix
fill
} bdef
/FAn {
newpath
tMatrix currentmatrix pop
translate scale
0 0 1 5 -2 roll arcn
tMatrix setmatrix
stroke
} bdef
/PAn {
newpath
tMatrix currentmatrix pop
translate 0 0 moveto scale
0 0 1 5 -2 roll arcn
closepath
tMatrix setmatrix
fill
} bdef
currentdict end def
%%EndProlog
%%BeginSetup
MathWorks begin
0 cap
end
%%EndSetup
%%Page: 1 1
%%BeginPageSetup
%%PageBoundingBox: 56 201 549 600
MathWorks begin
bpage
%%EndPageSetup
%%BeginObject: graph1 1
bplot
/dpi2point 12 def
portraitMode 0216 7344 csm
466 133 5913 4797 MR c np
88 dict begin %Colortable dictionary
/c0 { 0 0 0 sr} bdef
/c1 { 1 1 1 sr} bdef
/c2 { 1 0 0 sr} bdef
/c3 { 0 1 0 sr} bdef
/c4 { 0 0 1 sr} bdef
/c5 { 1 1 0 sr} bdef
/c6 { 1 0 1 sr} bdef
/c7 { 0 1 1 sr} bdef
1 j
1 sg
0 0 6916 5185 PR
6 w
0 4225 5358 0 0 -4225 899 4613 4 MP
PP
-5358 0 0 4225 5358 0 0 -4225 899 4613 5 MP stroke
DO
4 w
SO
6 w
0 sg
899 4613 mt 6257 4613 L
899 388 mt 6257 388 L
899 4613 mt 899 388 L
6257 4613 mt 6257 388 L
899 4613 mt 6257 4613 L
899 4613 mt 899 388 L
899 4613 mt 899 4559 L
899 388 mt 899 442 L
%%IncludeResource: font Helvetica
/Helvetica /ISOLatin1Encoding 120 FMSR
866 4759 mt
(0) s
1435 4613 mt 1435 4559 L
1435 388 mt 1435 442 L
1352 4759 mt
(0.1) s
1971 4613 mt 1971 4559 L
1971 388 mt 1971 442 L
1888 4759 mt
(0.2) s
2506 4613 mt 2506 4559 L
2506 388 mt 2506 442 L
2423 4759 mt
(0.3) s
3042 4613 mt 3042 4559 L
3042 388 mt 3042 442 L
2959 4759 mt
(0.4) s
3578 4613 mt 3578 4559 L
3578 388 mt 3578 442 L
3495 4759 mt
(0.5) s
4114 4613 mt 4114 4559 L
4114 388 mt 4114 442 L
4031 4759 mt
(0.6) s
4650 4613 mt 4650 4559 L
4650 388 mt 4650 442 L
4567 4759 mt
(0.7) s
5185 4613 mt 5185 4559 L
5185 388 mt 5185 442 L
5102 4759 mt
(0.8) s
5721 4613 mt 5721 4559 L
5721 388 mt 5721 442 L
5638 4759 mt
(0.9) s
6257 4613 mt 6257 4559 L
6257 388 mt 6257 442 L
6224 4759 mt
(1) s
899 4613 mt 953 4613 L
6257 4613 mt 6203 4613 L
798 4657 mt
(0) s
899 4085 mt 953 4085 L
6257 4085 mt 6203 4085 L
631 4129 mt
(0.05) s
899 3557 mt 953 3557 L
6257 3557 mt 6203 3557 L
698 3601 mt
(0.1) s
899 3029 mt 953 3029 L
6257 3029 mt 6203 3029 L
631 3073 mt
(0.15) s
899 2501 mt 953 2501 L
6257 2501 mt 6203 2501 L
698 2545 mt
(0.2) s
899 1972 mt 953 1972 L
6257 1972 mt 6203 1972 L
631 2016 mt
(0.25) s
899 1444 mt 953 1444 L
6257 1444 mt 6203 1444 L
698 1488 mt
(0.3) s
899 916 mt 953 916 L
6257 916 mt 6203 916 L
631 960 mt
(0.35) s
899 388 mt 953 388 L
6257 388 mt 6203 388 L
698 432 mt
(0.4) s
899 4613 mt 6257 4613 L
899 388 mt 6257 388 L
899 4613 mt 899 388 L
6257 4613 mt 6257 388 L
gs 899 388 5359 4226 MR c np
1866 65 577 -501 103 -189 41 -93 10 103 43 -107 9 2 10 -43
1 -7 1 2 2 -18 0 -5 1 -5 0 -5 0 6 2 -2
2 -4 2 -11 0 -7 0 -4 1 -2 0 -2 1 -9 0 -4
1 -7 0 -2 0 -4 0 -3 0 -1 1 -13 0 0 4 14
12 -54 1 -13 0 18 6 -22 2 -4 2 1 1 -8 1 -5
0 -6 1 -2 1 3 2 -17 0 -3 0 -5 0 -6 1 -2
0 0 0 -2 0 2 1 -6 1 4 2 -16 1 -5 0 -5
0 -2 0 -6 0 21 14 -73 1 -16 0 -10 0 -8 2 -17
0 -13 1 -10 0 9 9 -47 1 -13 0 -9 0 11 5 -37
1 -13 0 -10 1 -6 0 -6 0 -9 0 436 259 -140 138 -35
110 -203 25 -35 20 -35 14 -24 8 -31 2 -6 1 4 2 -18
0 -5 0 -4 1 -4 0 -2 0 -3 0 -2 0 13 3 -3
2 -13 1 -8 0 3 2923 2180 100 MP stroke
2 -4 2 1 2 -2 1 2 3 -18 0 -5 1 -7 0 -5
0 -5 0 -1 1 -8 0 -5 0 -3 0 -3 0 -1 1 -13
0 -9 1 -11 0 -2 0 -9 0 2 1 -16 0 -11 1 14
11 -47 1 -13 0 74 25 -77 1 -5 2 -1 2 -2 2 -8
0 -5 1 -6 0 -2 1 5 2 -16 0 -7 0 -4 1 -5
0 -5 0 5 3 2 7 -36 1 10 4 -21 2 -2 2 0
3 -15 0 -7 1 -6 0 -6 0 0 1 -7 0 -6 0 4
1 -6 0 -5 0 -4 0 -3 0 -3 0 -2 1 -5 2 -17
2 -20 1 -13 0 -9 1 -13 0 121 78 -147 5 -37 1 -13
0 -9 0 0 0 -13 1 -9 0 149 80 -200 6 -42 1 -13
0 -8 1 -16 1 -10 0 50 16 -45 4 -5 4 26 10 -43
1 -7 1 5 3 -16 0 -6 0 -5 0 -1 1 -7 0 15
4 -28 0 -1 2 -6 2606 2929 100 MP stroke
1 6 2 -16 1 -4 0 -4 0 -2 0 -2 1 -5 0 -5
0 -2 0 0 0 -7 0 46 14 -59 1 -10 0 2 1 -7
0 4 1 -7 0 -5 0 -5 0 -3 0 -1 0 -1 0 19
6 -33 0 -3 2 8 4 -10 2 -18 0 -5 1 -6 0 -7
0 -1 1 -3 1 -6 0 -5 0 -6 0 -1 0 -3 0 547
507 -626 3 15 15 -56 7 -47 2 -14 0 -13 1 -9 0 1
1 -16 0 -11 0 -2 0 -1 0 -2 0 -2 0 12 6 -37
0 -13 1 -10 0 -13 1 359 287 -382 10 -45 7 -46 1 -11
0 -2 0 -9 0 1 1 -17 1 -10 0 -13 0 0 1 -13
0 -9 0 432 275 -183 105 -93 50 -75 18 -76 0 -8 2 -6
1 2 2 -17 0 -6 0 -5 0 -3 2 -16 0 -4 1 -5
1 -4 1 -7 1 1 0 -7 0 -5 1 -5 0 -1 0 -3
0 -3 0 33 15 -66 1240 3720 100 MP stroke
1 -14 0 -9 0 23 8 -37 0 -13 1 15 5 -26 0 -2
0 0 1 -6 0 -5 0 -6 0 -1 0 0 0 -1 1 16
3 -18 1 -3 1 -7 0 -5 0 -4 0 -2 0 -3 0 9
3 -18 0 -3 1 -5 0 -5 1 -7 0 11 7 19 21 -67
5 -37 1 -13 0 -9 1 -13 0 38 12 -48 2 -4 2 -1
2 -2 1 -9 1 -6 0 5 2 -17 0 -3 1 -6 0 -7
1 -4 0 -5 0 5 2 -13 0 1 2 -18 0 -2 1 -7
0 -4 1 -4 0 -2 0 -3 0 -2 0 130 80 -158 14 -72
2 -18 0 -9 1 -11 0 -2 0 -9 0 2 1 -15 1 -13
0 61 39 -111 1 -17 1 -13 0 -10 0 -1 0 104 45 -117
1 -15 0 -11 0 65 24 -91 2 -18 0 -9 1 -13 0 -9
0 32 7 -9 5 -12 3 -18 0 -3 1 -8 0 -6 0 -5
0 9 3 -20 0 -4 916 4508 100 MP stroke
1 -9 0 -3 0 -5 0 -3 0 -2 0 18 5 -23 1 -1
0 -2 1 -9 0 -4 1 -7 0 -5 0 11 2 -3 1 2
3 -18 0 -5 1 -6 0 -6 0 -5 0 -1 1 -8 0 -5
0 -3 899 4610 26 MP stroke
434 1188 619 -336 211 -94 74 -375 10 214 58 -62 15 5 15 -75
2 -21 1 26 3 -18 1 -16 1 -7 0 -11 1 8 3 -23
2 44 3 -33 1 -9 1 -18 1 3 1 18 1 -18 1 -6
1 -18 0 0 1 -13 0 0 0 8 4 -26 2 -35 5 118
20 -88 3 -26 2 20 9 -57 2 0 2 23 2 -29 1 0
1 -7 1 -8 1 26 3 -18 1 -14 1 -7 1 -9 0 0
0 -4 0 0 0 5 2 -21 2 26 3 -18 1 -7 0 -11
0 2 1 -7 1 187 35 -135 4 -58 3 -41 2 7 6 -67
3 -26 3 -42 2 124 22 -181 3 -28 2 -13 0 66 14 -88
3 -26 2 -46 2 5 2 -26 1 -12 1 620 266 -99 162 211
162 -157 46 -49 31 15 25 1 12 -94 2 -20 1 26 3 -19
1 -16 1 -1 1 -11 0 0 0 -3 0 0 1 8 3 68
4 -62 1 -9 1 -11 3892 2832 100 MP stroke
3 0 3 -21 1 35 2 12 3 -18 1 -15 2 -8 0 -8
1 -10 0 3 2 -9 0 -20 1 0 0 -3 0 8 3 -26
3 -41 2 -5 1 -21 2 -12 0 19 5 -57 2 -42 2 125
22 -182 3 -26 2 141 32 -132 3 -26 2 0 2 23 3 -29
0 0 1 -8 1 -7 1 26 3 -19 1 -7 1 -9 1 -7
0 -10 0 11 6 98 12 -94 2 20 9 -44 3 23 2 -7
3 -10 2 -8 0 -8 1 -9 1 4 1 -15 1 -13 0 17
1 -8 1 -10 0 -13 0 0 1 -3 0 6 2 -32 8 65
8 -109 4 -26 2 -39 3 -26 3 367 91 -243 14 -88 3 -28
2 -12 0 -25 3 -28 2 -12 1 436 118 -170 17 -132 4 -26
2 5 5 -57 2 -42 2 130 27 -222 4 0 4 99 14 -74
2 -21 2 26 3 -18 1 -8 0 -10 0 1 1 -7 1 54
7 -41 2 -25 3 -21 3362 3640 100 MP stroke
1 26 3 -18 1 -7 0 -11 1 0 0 1 1 -7 0 -8
0 0 1 -1 0 -7 1 138 22 -125 2 -4 1 -19 1 -3
0 2 1 -7 1 -11 0 -13 1 -1 0 1 0 -3 0 94
10 -75 2 -39 4 18 5 0 2 -18 1 -15 2 -8 1 -8
0 -6 2 -3 1 -7 0 -10 1 -13 0 -3 0 0 1 1369
607 -947 7 170 46 -154 22 -160 5 -31 3 -28 2 -12 0 -22
5 32 4 -64 0 -7 0 -35 1 0 0 -5 0 68 14 -88
3 -26 2 -39 4 -26 2 975 359 -723 30 7 21 -172 3 -4
0 -21 2 -13 0 39 6 -84 3 -40 3 -33 0 -25 3 -28
2 -12 0 817 347 -220 134 -75 64 -63 27 -109 4 -26 2 -21
1 26 3 -18 1 -7 1 -9 1 34 4 -57 3 -42 2 0
2 -2 1 -15 1 6 1 -7 0 -10 1 -13 0 -3 0 0
0 -3 1 190 28 -156 1504 3732 100 MP stroke
3 -28 2 -12 0 66 14 -88 3 -26 2 17 8 -57 0 3
1 0 1 -8 1 -10 0 -12 0 1 0 -3 0 -2 1 41
5 -23 1 -3 1 -7 1 -10 0 -13 1 0 0 -3 0 36
3 -18 1 -15 1 -9 1 0 1 -7 1 9 11 165 38 -83
14 -88 3 -26 3 -39 3 -26 2 69 19 -88 4 -26 2 0
2 23 2 -29 1 -7 1 25 3 -18 1 -5 1 -8 1 -7
0 -11 1 -10 0 31 4 -26 2 -11 3 -18 1 -15 1 -9
1 -1 0 -10 1 0 0 -4 0 0 0 438 124 -245 35 -75
6 -94 2 -42 3 -4 1 -21 1 -13 1 -22 4 -31 4 -26
2 228 59 -186 6 -68 4 -28 1 -12 1 -28 2 235 52 -136
5 -57 2 -42 2 135 40 -49 6 -93 2 -40 4 -28 1 -12
1 48 10 -30 5 0 3 -19 1 -4 1 -9 1 -17 1 -11
0 47 4 -29 1 3 928 4502 100 MP stroke
1 -19 1 -13 1 -18 0 0 0 -2 1 52 6 -43 1 4
0 18 2 -18 1 -14 1 -7 0 -13 1 6 1 35 3 12
3 -18 0 -15 2 -9 1 -7 0 -10 0 2 2 -8 1 -20
0 0 899 4607 26 MP stroke
gr
36 36 899 4610 FO
36 36 899 4607 FO
36 36 899 4602 FO
36 36 900 4594 FO
36 36 900 4593 FO
36 36 900 4588 FO
36 36 900 4582 FO
36 36 901 4576 FO
36 36 901 4571 FO
36 36 904 4553 FO
36 36 905 4555 FO
36 36 907 4552 FO
36 36 907 4563 FO
36 36 907 4558 FO
36 36 908 4551 FO
36 36 908 4547 FO
36 36 909 4538 FO
36 36 909 4536 FO
36 36 910 4535 FO
36 36 915 4512 FO
36 36 915 4530 FO
36 36 915 4528 FO
36 36 915 4525 FO
36 36 915 4520 FO
36 36 915 4517 FO
36 36 916 4508 FO
36 36 916 4504 FO
36 36 919 4484 FO
36 36 919 4493 FO
36 36 919 4488 FO
36 36 919 4482 FO
36 36 920 4474 FO
36 36 920 4471 FO
36 36 923 4453 FO
36 36 928 4441 FO
36 36 935 4432 FO
36 36 935 4464 FO
36 36 935 4455 FO
36 36 936 4442 FO
36 36 936 4433 FO
36 36 938 4415 FO
36 36 962 4324 FO
36 36 962 4389 FO
36 36 962 4378 FO
36 36 963 4363 FO
36 36 1008 4246 FO
36 36 1008 4350 FO
36 36 1008 4349 FO
36 36 1008 4339 FO
36 36 1009 4326 FO
36 36 1010 4309 FO
36 36 1049 4198 FO
36 36 1049 4259 FO
36 36 1050 4246 FO
36 36 1051 4231 FO
36 36 1051 4233 FO
36 36 1051 4224 FO
36 36 1051 4222 FO
36 36 1052 4211 FO
36 36 1052 4202 FO
36 36 1054 4184 FO
36 36 1068 4112 FO
36 36 1148 3954 FO
36 36 1148 4084 FO
36 36 1148 4082 FO
36 36 1148 4079 FO
36 36 1148 4077 FO
36 36 1149 4073 FO
36 36 1149 4069 FO
36 36 1150 4062 FO
36 36 1150 4060 FO
36 36 1152 4042 FO
36 36 1152 4043 FO
36 36 1154 4030 FO
36 36 1154 4035 FO
36 36 1154 4030 FO
36 36 1155 4026 FO
36 36 1155 4019 FO
36 36 1156 4013 FO
36 36 1156 4010 FO
36 36 1158 3993 FO
36 36 1158 3998 FO
36 36 1159 3992 FO
36 36 1160 3983 FO
36 36 1162 3981 FO
36 36 1164 3980 FO
36 36 1166 3976 FO
36 36 1178 3928 FO
36 36 1178 3966 FO
36 36 1179 3953 FO
36 36 1179 3944 FO
36 36 1180 3931 FO
36 36 1185 3894 FO
36 36 1206 3827 FO
36 36 1213 3846 FO
36 36 1213 3857 FO
36 36 1214 3850 FO
36 36 1214 3845 FO
36 36 1215 3840 FO
36 36 1215 3837 FO
36 36 1218 3819 FO
36 36 1218 3828 FO
36 36 1218 3825 FO
36 36 1218 3823 FO
36 36 1218 3819 FO
36 36 1218 3814 FO
36 36 1219 3807 FO
36 36 1220 3804 FO
36 36 1223 3786 FO
36 36 1224 3802 FO
36 36 1224 3801 FO
36 36 1224 3801 FO
36 36 1224 3800 FO
36 36 1224 3794 FO
36 36 1224 3789 FO
36 36 1225 3783 FO
36 36 1225 3783 FO
36 36 1225 3781 FO
36 36 1230 3755 FO
36 36 1231 3770 FO
36 36 1231 3757 FO
36 36 1239 3720 FO
36 36 1239 3743 FO
36 36 1239 3734 FO
36 36 1240 3720 FO
36 36 1255 3654 FO
36 36 1255 3687 FO
36 36 1255 3684 FO
36 36 1255 3681 FO
36 36 1255 3680 FO
36 36 1256 3675 FO
36 36 1256 3670 FO
36 36 1256 3663 FO
36 36 1257 3664 FO
36 36 1258 3657 FO
36 36 1259 3653 FO
36 36 1260 3648 FO
36 36 1260 3644 FO
36 36 1262 3628 FO
36 36 1262 3625 FO
36 36 1262 3620 FO
36 36 1262 3614 FO
36 36 1264 3597 FO
36 36 1265 3599 FO
36 36 1267 3593 FO
36 36 1267 3585 FO
36 36 1285 3509 FO
36 36 1335 3434 FO
36 36 1440 3341 FO
36 36 1715 3158 FO
36 36 1715 3590 FO
36 36 1715 3581 FO
36 36 1716 3568 FO
36 36 1716 3568 FO
36 36 1716 3555 FO
36 36 1717 3545 FO
36 36 1718 3528 FO
36 36 1718 3529 FO
36 36 1718 3520 FO
36 36 1718 3518 FO
36 36 1719 3507 FO
36 36 1726 3461 FO
36 36 1736 3416 FO
36 36 2023 3034 FO
36 36 2024 3393 FO
36 36 2024 3380 FO
36 36 2025 3370 FO
36 36 2025 3357 FO
36 36 2031 3320 FO
36 36 2031 3332 FO
36 36 2031 3330 FO
36 36 2031 3328 FO
36 36 2031 3327 FO
36 36 2031 3325 FO
36 36 2031 3314 FO
36 36 2032 3298 FO
36 36 2032 3299 FO
36 36 2033 3290 FO
36 36 2033 3277 FO
36 36 2035 3263 FO
36 36 2042 3216 FO
36 36 2057 3160 FO
36 36 2060 3175 FO
36 36 2567 2549 FO
36 36 2567 3096 FO
36 36 2567 3093 FO
36 36 2567 3092 FO
36 36 2567 3086 FO
36 36 2567 3081 FO
36 36 2568 3075 FO
36 36 2569 3072 FO
36 36 2569 3071 FO
36 36 2569 3064 FO
36 36 2570 3058 FO
36 36 2570 3053 FO
36 36 2572 3035 FO
36 36 2576 3025 FO
36 36 2578 3033 FO
36 36 2578 3030 FO
36 36 2584 2997 FO
36 36 2584 3016 FO
36 36 2584 3015 FO
36 36 2584 3014 FO
36 36 2584 3011 FO
36 36 2584 3006 FO
36 36 2584 3001 FO
36 36 2585 2994 FO
36 36 2585 2998 FO
36 36 2586 2991 FO
36 36 2586 2993 FO
36 36 2587 2983 FO
36 36 2601 2924 FO
36 36 2601 2970 FO
36 36 2601 2963 FO
36 36 2601 2963 FO
36 36 2601 2961 FO
36 36 2601 2956 FO
36 36 2602 2951 FO
36 36 2602 2949 FO
36 36 2602 2947 FO
36 36 2602 2943 FO
36 36 2603 2939 FO
36 36 2605 2923 FO
36 36 2606 2929 FO
36 36 2608 2923 FO
36 36 2608 2922 FO
36 36 2612 2894 FO
36 36 2612 2909 FO
36 36 2613 2902 FO
36 36 2613 2901 FO
36 36 2613 2896 FO
36 36 2613 2890 FO
36 36 2616 2874 FO
36 36 2617 2879 FO
36 36 2618 2872 FO
36 36 2628 2829 FO
36 36 2632 2855 FO
36 36 2636 2850 FO
36 36 2652 2805 FO
36 36 2652 2855 FO
36 36 2653 2845 FO
36 36 2654 2829 FO
36 36 2654 2821 FO
36 36 2655 2808 FO
36 36 2661 2766 FO
36 36 2741 2566 FO
36 36 2741 2715 FO
36 36 2742 2706 FO
36 36 2742 2693 FO
36 36 2742 2693 FO
36 36 2742 2684 FO
36 36 2743 2671 FO
36 36 2748 2634 FO
36 36 2826 2487 FO
36 36 2826 2608 FO
36 36 2827 2595 FO
36 36 2827 2586 FO
36 36 2828 2573 FO
36 36 2830 2553 FO
36 36 2832 2536 FO
36 36 2833 2531 FO
36 36 2833 2529 FO
36 36 2833 2526 FO
36 36 2833 2523 FO
36 36 2833 2519 FO
36 36 2833 2514 FO
36 36 2834 2508 FO
36 36 2834 2512 FO
36 36 2834 2506 FO
36 36 2835 2499 FO
36 36 2835 2499 FO
36 36 2835 2493 FO
36 36 2836 2487 FO
36 36 2836 2480 FO
36 36 2839 2465 FO
36 36 2841 2465 FO
36 36 2843 2463 FO
36 36 2847 2442 FO
36 36 2848 2452 FO
36 36 2855 2416 FO
36 36 2858 2418 FO
36 36 2858 2423 FO
36 36 2858 2418 FO
36 36 2859 2413 FO
36 36 2859 2409 FO
36 36 2859 2402 FO
36 36 2861 2386 FO
36 36 2862 2391 FO
36 36 2862 2389 FO
36 36 2863 2383 FO
36 36 2863 2378 FO
36 36 2865 2370 FO
36 36 2867 2368 FO
36 36 2869 2367 FO
36 36 2870 2362 FO
36 36 2895 2285 FO
36 36 2895 2359 FO
36 36 2896 2346 FO
36 36 2907 2299 FO
36 36 2908 2313 FO
36 36 2908 2302 FO
36 36 2909 2286 FO
36 36 2909 2288 FO
36 36 2909 2279 FO
36 36 2909 2277 FO
36 36 2910 2266 FO
36 36 2910 2257 FO
36 36 2911 2244 FO
36 36 2911 2243 FO
36 36 2911 2240 FO
36 36 2911 2237 FO
36 36 2911 2232 FO
36 36 2912 2224 FO
36 36 2912 2223 FO
36 36 2912 2218 FO
36 36 2912 2213 FO
36 36 2913 2206 FO
36 36 2913 2201 FO
36 36 2916 2183 FO
36 36 2917 2185 FO
36 36 2919 2183 FO
36 36 2921 2184 FO
36 36 2923 2180 FO
36 36 2923 2183 FO
36 36 2924 2175 FO
36 36 2926 2162 FO
36 36 2929 2159 FO
36 36 2929 2172 FO
36 36 2929 2170 FO
36 36 2929 2167 FO
36 36 2929 2165 FO
36 36 2930 2161 FO
36 36 2930 2157 FO
36 36 2930 2152 FO
36 36 2932 2134 FO
36 36 2933 2138 FO
36 36 2935 2132 FO
36 36 2943 2101 FO
36 36 2957 2077 FO
36 36 2977 2042 FO
36 36 3002 2007 FO
36 36 3112 1804 FO
36 36 3250 1769 FO
36 36 3509 1629 FO
36 36 3509 2065 FO
36 36 3509 2056 FO
36 36 3509 2050 FO
36 36 3510 2044 FO
36 36 3510 2034 FO
36 36 3511 2021 FO
36 36 3516 1984 FO
36 36 3516 1995 FO
36 36 3516 1986 FO
36 36 3517 1973 FO
36 36 3526 1926 FO
36 36 3526 1935 FO
36 36 3527 1925 FO
36 36 3527 1912 FO
36 36 3529 1895 FO
36 36 3529 1887 FO
36 36 3529 1877 FO
36 36 3530 1861 FO
36 36 3544 1788 FO
36 36 3544 1809 FO
36 36 3544 1803 FO
36 36 3544 1801 FO
36 36 3544 1796 FO
36 36 3545 1791 FO
36 36 3547 1775 FO
36 36 3548 1779 FO
36 36 3549 1773 FO
36 36 3549 1775 FO
36 36 3549 1773 FO
36 36 3549 1773 FO
36 36 3550 1771 FO
36 36 3550 1765 FO
36 36 3550 1760 FO
36 36 3550 1757 FO
36 36 3552 1740 FO
36 36 3553 1743 FO
36 36 3554 1741 FO
36 36 3554 1735 FO
36 36 3555 1730 FO
36 36 3556 1722 FO
36 36 3558 1723 FO
36 36 3560 1719 FO
36 36 3566 1697 FO
36 36 3566 1715 FO
36 36 3567 1702 FO
36 36 3579 1648 FO
36 36 3583 1662 FO
36 36 3583 1662 FO
36 36 3584 1649 FO
36 36 3584 1648 FO
36 36 3584 1645 FO
36 36 3584 1641 FO
36 36 3584 1639 FO
36 36 3585 1632 FO
36 36 3585 1628 FO
36 36 3586 1619 FO
36 36 3586 1617 FO
36 36 3587 1615 FO
36 36 3587 1611 FO
36 36 3587 1604 FO
36 36 3589 1593 FO
36 36 3591 1589 FO
36 36 3593 1587 FO
36 36 3593 1593 FO
36 36 3593 1588 FO
36 36 3594 1583 FO
36 36 3594 1578 FO
36 36 3596 1560 FO
36 36 3597 1562 FO
36 36 3598 1555 FO
36 36 3608 1512 FO
36 36 3617 1514 FO
36 36 3660 1407 FO
36 36 3670 1510 FO
36 36 3711 1417 FO
36 36 3814 1228 FO
36 36 4391 727 FO
36 36 6257 792 FO
gs 899 388 5359 4226 MR c np
gr
874 4582 mt 924 4632 L
924 4582 mt 874 4632 L
874 4582 mt 924 4632 L
924 4582 mt 874 4632 L
875 4562 mt 925 4612 L
925 4562 mt 875 4612 L
877 4554 mt 927 4604 L
927 4554 mt 877 4604 L
877 4556 mt 927 4606 L
927 4556 mt 877 4606 L
877 4546 mt 927 4596 L
927 4546 mt 877 4596 L
878 4539 mt 928 4589 L
928 4539 mt 878 4589 L
880 4530 mt 930 4580 L
930 4530 mt 880 4580 L
880 4515 mt 930 4565 L
930 4515 mt 880 4565 L
883 4497 mt 933 4547 L
933 4497 mt 883 4547 L
886 4509 mt 936 4559 L
936 4509 mt 886 4559 L
887 4544 mt 937 4594 L
937 4544 mt 887 4594 L
888 4550 mt 938 4600 L
938 4550 mt 888 4600 L
888 4537 mt 938 4587 L
938 4537 mt 888 4587 L
889 4530 mt 939 4580 L
939 4530 mt 889 4580 L
890 4516 mt 940 4566 L
940 4516 mt 890 4566 L
892 4498 mt 942 4548 L
942 4498 mt 892 4548 L
892 4516 mt 942 4566 L
942 4516 mt 892 4566 L
893 4520 mt 943 4570 L
943 4520 mt 893 4570 L
899 4477 mt 949 4527 L
949 4477 mt 899 4527 L
900 4529 mt 950 4579 L
950 4529 mt 900 4579 L
900 4527 mt 950 4577 L
950 4527 mt 900 4577 L
900 4527 mt 950 4577 L
950 4527 mt 900 4577 L
901 4509 mt 951 4559 L
951 4509 mt 901 4559 L
902 4496 mt 952 4546 L
952 4496 mt 902 4546 L
903 4477 mt 953 4527 L
953 4477 mt 903 4527 L
904 4480 mt 954 4530 L
954 4480 mt 904 4530 L
908 4451 mt 958 4501 L
958 4451 mt 908 4501 L
908 4498 mt 958 4548 L
958 4498 mt 908 4548 L
909 4487 mt 959 4537 L
959 4487 mt 909 4537 L
910 4470 mt 960 4520 L
960 4470 mt 910 4520 L
911 4461 mt 961 4511 L
961 4461 mt 911 4511 L
912 4457 mt 962 4507 L
962 4457 mt 912 4507 L
915 4438 mt 965 4488 L
965 4438 mt 915 4488 L
920 4438 mt 970 4488 L
970 4438 mt 920 4488 L
930 4408 mt 980 4458 L
980 4408 mt 930 4458 L
931 4456 mt 981 4506 L
981 4456 mt 931 4506 L
932 4444 mt 982 4494 L
982 4444 mt 932 4494 L
936 4416 mt 986 4466 L
986 4416 mt 936 4466 L
938 4376 mt 988 4426 L
988 4376 mt 938 4426 L
944 4283 mt 994 4333 L
994 4283 mt 944 4333 L
984 4234 mt 1034 4284 L
1034 4234 mt 984 4284 L
986 4369 mt 1036 4419 L
1036 4369 mt 986 4419 L
988 4327 mt 1038 4377 L
1038 4327 mt 988 4377 L
993 4270 mt 1043 4320 L
1043 4270 mt 993 4320 L
1045 4134 mt 1095 4184 L
1095 4134 mt 1045 4184 L
1047 4369 mt 1097 4419 L
1097 4369 mt 1047 4419 L
1048 4341 mt 1098 4391 L
1098 4341 mt 1048 4391 L
1049 4329 mt 1099 4379 L
1099 4329 mt 1049 4379 L
1053 4301 mt 1103 4351 L
1103 4301 mt 1053 4351 L
1059 4233 mt 1109 4283 L
1109 4233 mt 1059 4283 L
1118 4047 mt 1168 4097 L
1168 4047 mt 1118 4097 L
1120 4275 mt 1170 4325 L
1170 4275 mt 1120 4325 L
1124 4249 mt 1174 4299 L
1174 4249 mt 1124 4299 L
1128 4218 mt 1178 4268 L
1178 4218 mt 1128 4268 L
1129 4196 mt 1179 4246 L
1179 4196 mt 1129 4246 L
1130 4183 mt 1180 4233 L
1180 4183 mt 1130 4233 L
1131 4162 mt 1181 4212 L
1181 4162 mt 1131 4212 L
1134 4158 mt 1184 4208 L
1184 4158 mt 1134 4208 L
1136 4116 mt 1186 4166 L
1186 4116 mt 1136 4166 L
1142 4022 mt 1192 4072 L
1192 4022 mt 1142 4072 L
1177 3947 mt 1227 3997 L
1227 3947 mt 1177 3997 L
1301 3702 mt 1351 3752 L
1351 3702 mt 1301 3752 L
1301 4140 mt 1351 4190 L
1351 4140 mt 1301 4190 L
1301 4140 mt 1351 4190 L
1351 4140 mt 1301 4190 L
1301 4136 mt 1351 4186 L
1351 4136 mt 1301 4186 L
1302 4136 mt 1352 4186 L
1352 4136 mt 1302 4186 L
1302 4126 mt 1352 4176 L
1352 4126 mt 1302 4176 L
1303 4125 mt 1353 4175 L
1353 4125 mt 1303 4175 L
1304 4116 mt 1354 4166 L
1354 4116 mt 1304 4166 L
1305 4101 mt 1355 4151 L
1355 4101 mt 1305 4151 L
1308 4083 mt 1358 4133 L
1358 4083 mt 1308 4133 L
1310 4072 mt 1360 4122 L
1360 4072 mt 1310 4122 L
1314 4046 mt 1364 4096 L
1364 4046 mt 1314 4096 L
1314 4077 mt 1364 4127 L
1364 4077 mt 1314 4127 L
1315 4067 mt 1365 4117 L
1365 4067 mt 1315 4117 L
1315 4056 mt 1365 4106 L
1365 4056 mt 1315 4106 L
1316 4049 mt 1366 4099 L
1366 4049 mt 1316 4099 L
1317 4041 mt 1367 4091 L
1367 4041 mt 1317 4091 L
1318 4036 mt 1368 4086 L
1368 4036 mt 1318 4086 L
1321 4018 mt 1371 4068 L
1371 4018 mt 1321 4068 L
1322 4043 mt 1372 4093 L
1372 4043 mt 1322 4093 L
1323 4036 mt 1373 4086 L
1373 4036 mt 1323 4086 L
1325 4007 mt 1375 4057 L
1375 4007 mt 1325 4057 L
1327 4030 mt 1377 4080 L
1377 4030 mt 1327 4080 L
1329 4030 mt 1379 4080 L
1379 4030 mt 1329 4080 L
1333 4004 mt 1383 4054 L
1383 4004 mt 1333 4054 L
1352 3916 mt 1402 3966 L
1402 3916 mt 1352 3966 L
1354 3985 mt 1404 4035 L
1404 3985 mt 1354 4035 L
1357 3959 mt 1407 4009 L
1407 3959 mt 1357 4009 L
1360 3920 mt 1410 3970 L
1410 3920 mt 1360 3970 L
1363 3894 mt 1413 3944 L
1413 3894 mt 1363 3944 L
1377 3806 mt 1427 3856 L
1427 3806 mt 1377 3856 L
1415 3723 mt 1465 3773 L
1465 3723 mt 1415 3773 L
1426 3888 mt 1476 3938 L
1476 3888 mt 1426 3938 L
1427 3897 mt 1477 3947 L
1477 3897 mt 1427 3947 L
1428 3890 mt 1478 3940 L
1478 3890 mt 1428 3940 L
1429 3890 mt 1479 3940 L
1479 3890 mt 1429 3940 L
1430 3881 mt 1480 3931 L
1480 3881 mt 1430 3931 L
1431 3866 mt 1481 3916 L
1481 3866 mt 1431 3916 L
1434 3848 mt 1484 3898 L
1484 3848 mt 1434 3898 L
1434 3884 mt 1484 3934 L
1484 3884 mt 1434 3934 L
1434 3881 mt 1484 3931 L
1484 3881 mt 1434 3931 L
1435 3881 mt 1485 3931 L
1485 3881 mt 1435 3931 L
1435 3868 mt 1485 3918 L
1485 3868 mt 1435 3918 L
1436 3858 mt 1486 3908 L
1486 3858 mt 1436 3908 L
1437 3851 mt 1487 3901 L
1487 3851 mt 1437 3901 L
1438 3848 mt 1488 3898 L
1488 3848 mt 1438 3898 L
1443 3825 mt 1493 3875 L
1493 3825 mt 1443 3875 L
1444 3866 mt 1494 3916 L
1494 3866 mt 1444 3916 L
1444 3864 mt 1494 3914 L
1494 3864 mt 1444 3914 L
1444 3861 mt 1494 3911 L
1494 3861 mt 1444 3911 L
1444 3862 mt 1494 3912 L
1494 3862 mt 1444 3912 L
1444 3850 mt 1494 3900 L
1494 3850 mt 1444 3900 L
1445 3840 mt 1495 3890 L
1495 3840 mt 1445 3890 L
1446 3832 mt 1496 3882 L
1496 3832 mt 1446 3882 L
1447 3832 mt 1497 3882 L
1497 3832 mt 1447 3882 L
1447 3835 mt 1497 3885 L
1497 3835 mt 1447 3885 L
1455 3778 mt 1505 3828 L
1505 3778 mt 1455 3828 L
1457 3795 mt 1507 3845 L
1507 3795 mt 1457 3845 L
1460 3769 mt 1510 3819 L
1510 3769 mt 1460 3819 L
1474 3681 mt 1524 3731 L
1524 3681 mt 1474 3731 L
1474 3747 mt 1524 3797 L
1524 3747 mt 1474 3797 L
1476 3735 mt 1526 3785 L
1526 3735 mt 1476 3785 L
1479 3707 mt 1529 3757 L
1529 3707 mt 1479 3757 L
1507 3551 mt 1557 3601 L
1557 3551 mt 1507 3601 L
1508 3741 mt 1558 3791 L
1558 3741 mt 1508 3791 L
1508 3738 mt 1558 3788 L
1558 3738 mt 1508 3788 L
1508 3738 mt 1558 3788 L
1558 3738 mt 1508 3788 L
1508 3735 mt 1558 3785 L
1558 3735 mt 1508 3785 L
1509 3722 mt 1559 3772 L
1559 3722 mt 1509 3772 L
1509 3712 mt 1559 3762 L
1559 3712 mt 1509 3762 L
1510 3705 mt 1560 3755 L
1560 3705 mt 1510 3755 L
1511 3711 mt 1561 3761 L
1561 3711 mt 1511 3761 L
1512 3696 mt 1562 3746 L
1562 3696 mt 1512 3746 L
1514 3694 mt 1564 3744 L
1564 3694 mt 1514 3744 L
1516 3694 mt 1566 3744 L
1566 3694 mt 1516 3744 L
1519 3652 mt 1569 3702 L
1569 3652 mt 1519 3702 L
1523 3595 mt 1573 3645 L
1573 3595 mt 1523 3645 L
1524 3629 mt 1574 3679 L
1574 3629 mt 1524 3679 L
1525 3620 mt 1575 3670 L
1575 3620 mt 1525 3670 L
1526 3613 mt 1576 3663 L
1576 3613 mt 1526 3663 L
1529 3595 mt 1579 3645 L
1579 3595 mt 1529 3645 L
1530 3621 mt 1580 3671 L
1580 3621 mt 1530 3671 L
1532 3600 mt 1582 3650 L
1582 3600 mt 1532 3650 L
1536 3574 mt 1586 3624 L
1586 3574 mt 1536 3624 L
1563 3465 mt 1613 3515 L
1613 3465 mt 1563 3515 L
1627 3402 mt 1677 3452 L
1677 3402 mt 1627 3452 L
1761 3327 mt 1811 3377 L
1811 3327 mt 1761 3377 L
2108 3107 mt 2158 3157 L
2158 3107 mt 2108 3157 L
2108 3924 mt 2158 3974 L
2158 3924 mt 2108 3974 L
2110 3912 mt 2160 3962 L
2160 3912 mt 2110 3962 L
2113 3884 mt 2163 3934 L
2163 3884 mt 2113 3934 L
2113 3859 mt 2163 3909 L
2163 3859 mt 2113 3909 L
2116 3826 mt 2166 3876 L
2166 3826 mt 2116 3876 L
2119 3786 mt 2169 3836 L
2169 3786 mt 2119 3836 L
2125 3702 mt 2175 3752 L
2175 3702 mt 2125 3752 L
2125 3741 mt 2175 3791 L
2175 3741 mt 2125 3791 L
2127 3728 mt 2177 3778 L
2177 3728 mt 2127 3778 L
2127 3707 mt 2177 3757 L
2177 3707 mt 2127 3757 L
2130 3703 mt 2180 3753 L
2180 3703 mt 2130 3753 L
2151 3531 mt 2201 3581 L
2201 3531 mt 2151 3581 L
2181 3538 mt 2231 3588 L
2231 3538 mt 2181 3588 L
2540 2815 mt 2590 2865 L
2590 2815 mt 2540 2865 L
2542 3790 mt 2592 3840 L
2592 3790 mt 2542 3840 L
2546 3764 mt 2596 3814 L
2596 3764 mt 2546 3814 L
2548 3725 mt 2598 3775 L
2598 3725 mt 2548 3775 L
2551 3699 mt 2601 3749 L
2601 3699 mt 2551 3749 L
2565 3611 mt 2615 3661 L
2615 3611 mt 2565 3661 L
2565 3679 mt 2615 3729 L
2615 3679 mt 2565 3729 L
2565 3674 mt 2615 3724 L
2615 3674 mt 2565 3724 L
2566 3674 mt 2616 3724 L
2616 3674 mt 2566 3724 L
2566 3639 mt 2616 3689 L
2616 3639 mt 2566 3689 L
2566 3632 mt 2616 3682 L
2616 3632 mt 2566 3682 L
2570 3568 mt 2620 3618 L
2620 3568 mt 2570 3618 L
2575 3600 mt 2625 3650 L
2625 3600 mt 2575 3650 L
2575 3578 mt 2625 3628 L
2625 3578 mt 2575 3628 L
2577 3566 mt 2627 3616 L
2627 3566 mt 2577 3616 L
2580 3538 mt 2630 3588 L
2630 3538 mt 2580 3588 L
2585 3507 mt 2635 3557 L
2635 3507 mt 2585 3557 L
2607 3347 mt 2657 3397 L
2657 3347 mt 2607 3397 L
2653 3193 mt 2703 3243 L
2703 3193 mt 2653 3243 L
2660 3363 mt 2710 3413 L
2710 3363 mt 2660 3413 L
3267 2416 mt 3317 2466 L
3317 2416 mt 3267 2466 L
3268 3785 mt 3318 3835 L
3318 3785 mt 3268 3835 L
3268 3785 mt 3318 3835 L
3318 3785 mt 3268 3835 L
3268 3782 mt 3318 3832 L
3318 3782 mt 3268 3832 L
3269 3769 mt 3319 3819 L
3319 3769 mt 3269 3819 L
3269 3759 mt 3319 3809 L
3319 3759 mt 3269 3809 L
3270 3752 mt 3320 3802 L
3320 3752 mt 3270 3802 L
3272 3749 mt 3322 3799 L
3322 3749 mt 3272 3799 L
3272 3743 mt 3322 3793 L
3322 3743 mt 3272 3793 L
3273 3735 mt 3323 3785 L
3323 3735 mt 3273 3785 L
3275 3727 mt 3325 3777 L
3325 3727 mt 3275 3777 L
3276 3712 mt 3326 3762 L
3326 3712 mt 3276 3762 L
3278 3694 mt 3328 3744 L
3328 3694 mt 3278 3744 L
3283 3694 mt 3333 3744 L
3333 3694 mt 3283 3744 L
3287 3712 mt 3337 3762 L
3337 3712 mt 3287 3762 L
3289 3673 mt 3339 3723 L
3339 3673 mt 3289 3723 L
3299 3598 mt 3349 3648 L
3349 3598 mt 3299 3648 L
3299 3692 mt 3349 3742 L
3349 3692 mt 3299 3742 L
3299 3689 mt 3349 3739 L
3349 3689 mt 3299 3739 L
3299 3690 mt 3349 3740 L
3349 3690 mt 3299 3740 L
3300 3689 mt 3350 3739 L
3350 3689 mt 3300 3739 L
3300 3676 mt 3350 3726 L
3350 3676 mt 3300 3726 L
3301 3665 mt 3351 3715 L
3351 3665 mt 3301 3715 L
3302 3658 mt 3352 3708 L
3352 3658 mt 3302 3708 L
3302 3660 mt 3352 3710 L
3352 3660 mt 3302 3710 L
3303 3657 mt 3353 3707 L
3353 3657 mt 3303 3707 L
3304 3638 mt 3354 3688 L
3354 3638 mt 3304 3688 L
3306 3634 mt 3356 3684 L
3356 3634 mt 3306 3684 L
3328 3509 mt 3378 3559 L
3378 3509 mt 3328 3559 L
3329 3647 mt 3379 3697 L
3379 3647 mt 3329 3697 L
3329 3640 mt 3379 3690 L
3379 3640 mt 3329 3690 L
3330 3639 mt 3380 3689 L
3380 3639 mt 3330 3689 L
3330 3639 mt 3380 3689 L
3380 3639 mt 3330 3689 L
3330 3631 mt 3380 3681 L
3380 3631 mt 3330 3681 L
3331 3624 mt 3381 3674 L
3381 3624 mt 3331 3674 L
3331 3625 mt 3381 3675 L
3381 3625 mt 3331 3675 L
3332 3625 mt 3382 3675 L
3382 3625 mt 3332 3675 L
3332 3614 mt 3382 3664 L
3382 3614 mt 3332 3664 L
3333 3607 mt 3383 3657 L
3383 3607 mt 3333 3657 L
3336 3589 mt 3386 3639 L
3386 3589 mt 3336 3639 L
3337 3615 mt 3387 3665 L
3387 3615 mt 3337 3665 L
3340 3594 mt 3390 3644 L
3390 3594 mt 3340 3644 L
3342 3569 mt 3392 3619 L
3392 3569 mt 3342 3619 L
3349 3528 mt 3399 3578 L
3399 3528 mt 3349 3578 L
3350 3582 mt 3400 3632 L
3400 3582 mt 3350 3632 L
3351 3575 mt 3401 3625 L
3401 3575 mt 3351 3625 L
3351 3576 mt 3401 3626 L
3401 3576 mt 3351 3626 L
3351 3566 mt 3401 3616 L
3401 3566 mt 3351 3616 L
3352 3558 mt 3402 3608 L
3402 3558 mt 3352 3608 L
3355 3540 mt 3405 3590 L
3405 3540 mt 3355 3590 L
3357 3566 mt 3407 3616 L
3407 3566 mt 3357 3616 L
3359 3545 mt 3409 3595 L
3409 3545 mt 3359 3595 L
3373 3471 mt 3423 3521 L
3423 3471 mt 3373 3521 L
3377 3570 mt 3427 3620 L
3427 3570 mt 3377 3620 L
3381 3570 mt 3431 3620 L
3431 3570 mt 3381 3620 L
3408 3348 mt 3458 3398 L
3458 3348 mt 3408 3398 L
3410 3478 mt 3460 3528 L
3460 3478 mt 3410 3528 L
3412 3436 mt 3462 3486 L
3462 3436 mt 3412 3486 L
3417 3379 mt 3467 3429 L
3467 3379 mt 3417 3429 L
3419 3384 mt 3469 3434 L
3469 3384 mt 3419 3434 L
3423 3358 mt 3473 3408 L
3473 3358 mt 3423 3408 L
3440 3226 mt 3490 3276 L
3490 3226 mt 3440 3276 L
3558 3056 mt 3608 3106 L
3608 3056 mt 3558 3106 L
3559 3492 mt 3609 3542 L
3609 3492 mt 3559 3542 L
3561 3480 mt 3611 3530 L
3611 3480 mt 3561 3530 L
3564 3452 mt 3614 3502 L
3614 3452 mt 3564 3502 L
3564 3427 mt 3614 3477 L
3614 3427 mt 3564 3477 L
3566 3415 mt 3616 3465 L
3616 3415 mt 3566 3465 L
3569 3387 mt 3619 3437 L
3619 3387 mt 3569 3437 L
3583 3299 mt 3633 3349 L
3633 3299 mt 3583 3349 L
3674 3056 mt 3724 3106 L
3724 3056 mt 3674 3106 L
3677 3423 mt 3727 3473 L
3727 3423 mt 3677 3473 L
3680 3397 mt 3730 3447 L
3730 3397 mt 3680 3447 L
3682 3358 mt 3732 3408 L
3732 3358 mt 3682 3408 L
3686 3332 mt 3736 3382 L
3736 3332 mt 3686 3382 L
3694 3223 mt 3744 3273 L
3744 3223 mt 3694 3273 L
3702 3288 mt 3752 3338 L
3752 3288 mt 3702 3338 L
3704 3256 mt 3754 3306 L
3754 3256 mt 3704 3306 L
3704 3262 mt 3754 3312 L
3754 3262 mt 3704 3312 L
3705 3259 mt 3755 3309 L
3755 3259 mt 3705 3309 L
3705 3259 mt 3755 3309 L
3755 3259 mt 3705 3309 L
3705 3246 mt 3755 3296 L
3755 3246 mt 3705 3296 L
3706 3236 mt 3756 3286 L
3756 3236 mt 3706 3286 L
3707 3228 mt 3757 3278 L
3757 3228 mt 3707 3278 L
3707 3245 mt 3757 3295 L
3757 3245 mt 3707 3295 L
3708 3232 mt 3758 3282 L
3758 3232 mt 3708 3282 L
3709 3217 mt 3759 3267 L
3759 3217 mt 3709 3267 L
3710 3221 mt 3760 3271 L
3760 3221 mt 3710 3271 L
3711 3212 mt 3761 3262 L
3761 3212 mt 3711 3262 L
3711 3204 mt 3761 3254 L
3761 3204 mt 3711 3254 L
3713 3196 mt 3763 3246 L
3763 3196 mt 3713 3246 L
3716 3186 mt 3766 3236 L
3766 3186 mt 3716 3236 L
3718 3179 mt 3768 3229 L
3768 3179 mt 3718 3229 L
3721 3202 mt 3771 3252 L
3771 3202 mt 3721 3252 L
3730 3158 mt 3780 3208 L
3780 3158 mt 3730 3208 L
3732 3178 mt 3782 3228 L
3782 3178 mt 3732 3228 L
3744 3084 mt 3794 3134 L
3794 3084 mt 3744 3134 L
3750 3182 mt 3800 3232 L
3800 3182 mt 3750 3232 L
3750 3193 mt 3800 3243 L
3800 3193 mt 3750 3243 L
3750 3183 mt 3800 3233 L
3800 3183 mt 3750 3233 L
3751 3176 mt 3801 3226 L
3801 3176 mt 3751 3226 L
3752 3167 mt 3802 3217 L
3802 3167 mt 3752 3217 L
3753 3160 mt 3803 3210 L
3803 3160 mt 3753 3210 L
3756 3141 mt 3806 3191 L
3806 3141 mt 3756 3191 L
3757 3167 mt 3807 3217 L
3807 3167 mt 3757 3217 L
3758 3160 mt 3808 3210 L
3808 3160 mt 3758 3210 L
3759 3152 mt 3809 3202 L
3809 3152 mt 3759 3202 L
3759 3152 mt 3809 3202 L
3809 3152 mt 3759 3202 L
3762 3123 mt 3812 3173 L
3812 3123 mt 3762 3173 L
3764 3146 mt 3814 3196 L
3814 3146 mt 3764 3196 L
3766 3146 mt 3816 3196 L
3816 3146 mt 3766 3196 L
3769 3120 mt 3819 3170 L
3819 3120 mt 3769 3170 L
3801 2988 mt 3851 3038 L
3851 2988 mt 3801 3038 L
3803 3129 mt 3853 3179 L
3853 3129 mt 3803 3179 L
3806 3103 mt 3856 3153 L
3856 3103 mt 3806 3153 L
3828 2921 mt 3878 2971 L
3878 2921 mt 3828 2971 L
3830 3046 mt 3880 3096 L
3880 3046 mt 3830 3096 L
3832 3004 mt 3882 3054 L
3882 3004 mt 3832 3054 L
3837 2947 mt 3887 2997 L
3887 2947 mt 3837 2997 L
3837 2966 mt 3887 3016 L
3887 2966 mt 3837 3016 L
3839 2954 mt 3889 3004 L
3889 2954 mt 3839 3004 L
3840 2933 mt 3890 2983 L
3890 2933 mt 3840 2983 L
3842 2928 mt 3892 2978 L
3892 2928 mt 3842 2978 L
3845 2887 mt 3895 2937 L
3895 2887 mt 3845 2937 L
3848 2861 mt 3898 2911 L
3898 2861 mt 3848 2911 L
3848 2869 mt 3898 2919 L
3898 2869 mt 3848 2919 L
3848 2866 mt 3898 2916 L
3898 2866 mt 3848 2916 L
3849 2866 mt 3899 2916 L
3899 2866 mt 3849 2916 L
3849 2846 mt 3899 2896 L
3899 2846 mt 3849 2896 L
3851 2837 mt 3901 2887 L
3901 2837 mt 3851 2887 L
3851 2840 mt 3901 2890 L
3901 2840 mt 3851 2890 L
3852 2830 mt 3902 2880 L
3902 2830 mt 3852 2880 L
3852 2822 mt 3902 2872 L
3902 2822 mt 3852 2872 L
3854 2814 mt 3904 2864 L
3904 2814 mt 3854 2864 L
3855 2799 mt 3905 2849 L
3905 2799 mt 3855 2849 L
3858 2781 mt 3908 2831 L
3908 2781 mt 3858 2831 L
3860 2793 mt 3910 2843 L
3910 2793 mt 3860 2843 L
3861 2828 mt 3911 2878 L
3911 2828 mt 3861 2878 L
3864 2807 mt 3914 2857 L
3914 2807 mt 3864 2857 L
3867 2807 mt 3917 2857 L
3917 2807 mt 3867 2857 L
3868 2796 mt 3918 2846 L
3918 2796 mt 3868 2846 L
3869 2787 mt 3919 2837 L
3919 2787 mt 3869 2837 L
3873 2725 mt 3923 2775 L
3923 2725 mt 3873 2775 L
3876 2793 mt 3926 2843 L
3926 2793 mt 3876 2843 L
3877 2801 mt 3927 2851 L
3927 2801 mt 3877 2851 L
3877 2801 mt 3927 2851 L
3927 2801 mt 3877 2851 L
3877 2798 mt 3927 2848 L
3927 2798 mt 3877 2848 L
3877 2798 mt 3927 2848 L
3927 2798 mt 3877 2848 L
3878 2787 mt 3928 2837 L
3928 2787 mt 3878 2837 L
3879 2786 mt 3929 2836 L
3929 2786 mt 3879 2836 L
3880 2770 mt 3930 2820 L
3930 2770 mt 3880 2820 L
3883 2751 mt 3933 2801 L
3933 2751 mt 3883 2801 L
3884 2777 mt 3934 2827 L
3934 2777 mt 3884 2827 L
3886 2757 mt 3936 2807 L
3936 2757 mt 3886 2807 L
3898 2663 mt 3948 2713 L
3948 2663 mt 3898 2713 L
3923 2664 mt 3973 2714 L
3973 2664 mt 3923 2714 L
3954 2679 mt 4004 2729 L
4004 2679 mt 3954 2729 L
4000 2630 mt 4050 2680 L
4050 2630 mt 4000 2680 L
4162 2473 mt 4212 2523 L
4212 2473 mt 4162 2523 L
4324 2684 mt 4374 2734 L
4374 2684 mt 4324 2734 L
4590 2585 mt 4640 2635 L
4640 2585 mt 4590 2635 L
4591 3205 mt 4641 3255 L
4641 3205 mt 4591 3255 L
4592 3193 mt 4642 3243 L
4642 3193 mt 4592 3243 L
4594 3167 mt 4644 3217 L
4644 3167 mt 4594 3217 L
4596 3172 mt 4646 3222 L
4646 3172 mt 4596 3222 L
4598 3126 mt 4648 3176 L
4648 3126 mt 4598 3176 L
4601 3100 mt 4651 3150 L
4651 3100 mt 4601 3150 L
4615 3012 mt 4665 3062 L
4665 3012 mt 4615 3062 L
4615 3078 mt 4665 3128 L
4665 3078 mt 4615 3128 L
4617 3065 mt 4667 3115 L
4667 3065 mt 4617 3115 L
4620 3037 mt 4670 3087 L
4670 3037 mt 4620 3087 L
4642 2856 mt 4692 2906 L
4692 2856 mt 4642 2906 L
4644 2980 mt 4694 3030 L
4694 2980 mt 4644 3030 L
4647 2938 mt 4697 2988 L
4697 2938 mt 4647 2988 L
4650 2912 mt 4700 2962 L
4700 2912 mt 4650 2962 L
4656 2845 mt 4706 2895 L
4706 2845 mt 4656 2895 L
4658 2852 mt 4708 2902 L
4708 2852 mt 4658 2902 L
4661 2811 mt 4711 2861 L
4711 2811 mt 4661 2861 L
4665 2753 mt 4715 2803 L
4715 2753 mt 4665 2803 L
4700 2618 mt 4750 2668 L
4750 2618 mt 4700 2668 L
4701 2805 mt 4751 2855 L
4751 2805 mt 4701 2855 L
4702 2798 mt 4752 2848 L
4752 2798 mt 4702 2848 L
4702 2800 mt 4752 2850 L
4752 2800 mt 4702 2850 L
4702 2789 mt 4752 2839 L
4752 2789 mt 4702 2839 L
4703 2782 mt 4753 2832 L
4753 2782 mt 4703 2832 L
4706 2764 mt 4756 2814 L
4756 2764 mt 4706 2814 L
4708 2790 mt 4758 2840 L
4758 2790 mt 4708 2840 L
4710 2769 mt 4760 2819 L
4760 2769 mt 4710 2819 L
4710 2774 mt 4760 2824 L
4760 2774 mt 4710 2824 L
4710 2774 mt 4760 2824 L
4760 2774 mt 4710 2824 L
4710 2770 mt 4760 2820 L
4760 2770 mt 4710 2820 L
4710 2770 mt 4760 2820 L
4760 2770 mt 4710 2820 L
4711 2761 mt 4761 2811 L
4761 2761 mt 4711 2811 L
4712 2754 mt 4762 2804 L
4762 2754 mt 4712 2804 L
4713 2740 mt 4763 2790 L
4763 2740 mt 4713 2790 L
4716 2722 mt 4766 2772 L
4766 2722 mt 4716 2772 L
4717 2748 mt 4767 2798 L
4767 2748 mt 4717 2798 L
4718 2740 mt 4768 2790 L
4768 2740 mt 4718 2790 L
4719 2733 mt 4769 2783 L
4769 2733 mt 4719 2783 L
4720 2733 mt 4770 2783 L
4770 2733 mt 4720 2783 L
4722 2704 mt 4772 2754 L
4772 2704 mt 4722 2754 L
4724 2727 mt 4774 2777 L
4774 2727 mt 4724 2777 L
4726 2727 mt 4776 2777 L
4776 2727 mt 4726 2777 L
4735 2670 mt 4785 2720 L
4785 2670 mt 4735 2720 L
4737 2690 mt 4787 2740 L
4787 2690 mt 4737 2740 L
4740 2664 mt 4790 2714 L
4790 2664 mt 4740 2714 L
4760 2576 mt 4810 2626 L
4810 2576 mt 4760 2626 L
4765 2694 mt 4815 2744 L
4815 2694 mt 4765 2744 L
4767 2659 mt 4817 2709 L
4817 2659 mt 4767 2709 L
4771 2633 mt 4821 2683 L
4821 2633 mt 4771 2683 L
4771 2641 mt 4821 2691 L
4821 2641 mt 4771 2691 L
4771 2641 mt 4821 2691 L
4821 2641 mt 4771 2691 L
4772 2628 mt 4822 2678 L
4822 2628 mt 4772 2678 L
4772 2628 mt 4822 2678 L
4822 2628 mt 4772 2678 L
4773 2610 mt 4823 2660 L
4823 2610 mt 4773 2660 L
4774 2604 mt 4824 2654 L
4824 2604 mt 4774 2654 L
4775 2586 mt 4825 2636 L
4825 2586 mt 4775 2636 L
4776 2604 mt 4826 2654 L
4826 2604 mt 4776 2654 L
4777 2607 mt 4827 2657 L
4827 2607 mt 4777 2657 L
4778 2589 mt 4828 2639 L
4828 2589 mt 4778 2639 L
4779 2580 mt 4829 2630 L
4829 2580 mt 4779 2630 L
4782 2547 mt 4832 2597 L
4832 2547 mt 4782 2597 L
4784 2591 mt 4834 2641 L
4834 2591 mt 4784 2641 L
4787 2568 mt 4837 2618 L
4837 2568 mt 4787 2618 L
4788 2576 mt 4838 2626 L
4838 2576 mt 4788 2626 L
4788 2565 mt 4838 2615 L
4838 2565 mt 4788 2615 L
4789 2558 mt 4839 2608 L
4839 2558 mt 4789 2608 L
4790 2542 mt 4840 2592 L
4840 2542 mt 4790 2592 L
4793 2524 mt 4843 2574 L
4843 2524 mt 4793 2574 L
4794 2550 mt 4844 2600 L
4844 2550 mt 4794 2600 L
4796 2529 mt 4846 2579 L
4846 2529 mt 4796 2579 L
4811 2454 mt 4861 2504 L
4861 2454 mt 4811 2504 L
4826 2459 mt 4876 2509 L
4876 2459 mt 4826 2509 L
4884 2397 mt 4934 2447 L
4934 2397 mt 4884 2447 L
4894 2611 mt 4944 2661 L
4944 2611 mt 4894 2661 L
4968 2236 mt 5018 2286 L
5018 2236 mt 4968 2286 L
5179 2142 mt 5229 2192 L
5229 2142 mt 5179 2192 L
5798 1806 mt 5848 1856 L
5848 1806 mt 5798 1856 L
6232 2994 mt 6282 3044 L
6282 2994 mt 6232 3044 L
gs 899 388 5359 4226 MR c np
gr
2879 4901 mt
( fraction of total operations) s
577 3260 mt -90 rotate
( fraction of entries in L and U) s
90 rotate
2065 292 mt
( BCSSTK24, multisection ordering, working storage study) s
3578 3865 mt
(multifrontal) s
2506 1488 mt
(general sparse) s
end
eplot
%%EndObject graph 1
epage
end
showpage
%%Trailer
%%EOF
4 L
3390 3594 mt 3340 3644 L
3342 3569 mt 3392 3619 L
3392 3569 mt 3342 3619 L
3349 3528 mt 3399 3578 L
3399 3528 mt 3349 3578 L
3ETree/doc/makefile 0100644 0002055 0007177 00000000027 06542767400 0015353 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
ETree/doc/FS1.eps 0100644 0002055 0007177 00000010010 06652457237 0014754 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 50 50 500 500
/CSH {
%
% center show a string
%
% stack
% string str
%
dup stringwidth pop 2 div neg 0 rmoveto
show
} def
/ML {
%
% moveto lineto
%
% stack
% x0 y0 x1 y1
%
moveto lineto
} def
/FC {
%
% draw filled circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc fill
} def
/OC {
%
% draw open circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc stroke
} def
/rscale 10.000 def
/fontscale 10.000 def
% 60 60 430 430 rectclip
newpath
490 103 476 175 ML
461 149 476 175 ML
476 175 447 375 ML
433 149 418 332 ML
404 252 418 332 ML
418 332 447 375 ML
447 375 390 490 ML
375 149 361 175 ML
347 103 361 175 ML
361 175 332 375 ML
318 252 304 332 ML
289 149 304 332 ML
304 332 332 375 ML
332 375 390 490 ML
390 490 275 490 ML
261 149 246 332 ML
232 252 246 332 ML
246 332 218 375 ML
203 103 189 175 ML
175 149 189 175 ML
189 175 218 375 ML
218 375 160 490 ML
146 252 132 332 ML
117 149 132 332 ML
132 332 103 375 ML
88.7 149 74.3 175 ML
60 103 74.3 175 ML
74.3 175 103 375 ML
103 375 160 490 ML
160 490 275 490 ML
stroke
gsave
/Helvetica-Bold findfont fontscale scalefont setfont
1.0 setgray 490 103 10 FC
0.0 setgray 490 103 10 OC
490 97.6 moveto (0) CSH
1.0 setgray 461 149 10 FC
0.0 setgray 461 149 10 OC
461 144 moveto (1) CSH
1.0 setgray 476 175 10 FC
0.0 setgray 476 175 10 OC
476 170 moveto (2) CSH
1.0 setgray 433 149 10 FC
0.0 setgray 433 149 10 OC
433 144 moveto (3) CSH
1.0 setgray 404 252 10 FC
0.0 setgray 404 252 10 OC
404 247 moveto (4) CSH
1.0 setgray 418 332 10 FC
0.0 setgray 418 332 10 OC
418 327 moveto (5) CSH
1.0 setgray 447 375 10 FC
0.0 setgray 447 375 10 OC
447 370 moveto (6) CSH
1.0 setgray 375 149 10 FC
0.0 setgray 375 149 10 OC
375 144 moveto (7) CSH
1.0 setgray 347 103 10 FC
0.0 setgray 347 103 10 OC
347 97.6 moveto (8) CSH
1.0 setgray 361 175 10 FC
0.0 setgray 361 175 10 OC
361 170 moveto (9) CSH
1.0 setgray 318 252 10 FC
0.0 setgray 318 252 10 OC
318 247 moveto (10) CSH
1.0 setgray 289 149 10 FC
0.0 setgray 289 149 10 OC
289 144 moveto (11) CSH
1.0 setgray 304 332 10 FC
0.0 setgray 304 332 10 OC
304 327 moveto (12) CSH
1.0 setgray 332 375 10 FC
0.0 setgray 332 375 10 OC
332 370 moveto (13) CSH
1.0 setgray 390 490 10 FC
0.0 setgray 390 490 10 OC
390 485 moveto (14) CSH
1.0 setgray 261 149 10 FC
0.0 setgray 261 149 10 OC
261 144 moveto (15) CSH
1.0 setgray 232 252 10 FC
0.0 setgray 232 252 10 OC
232 247 moveto (16) CSH
1.0 setgray 246 332 10 FC
0.0 setgray 246 332 10 OC
246 327 moveto (17) CSH
1.0 setgray 203 103 10 FC
0.0 setgray 203 103 10 OC
203 97.6 moveto (18) CSH
1.0 setgray 175 149 10 FC
0.0 setgray 175 149 10 OC
175 144 moveto (19) CSH
1.0 setgray 189 175 10 FC
0.0 setgray 189 175 10 OC
189 170 moveto (20) CSH
1.0 setgray 218 375 10 FC
0.0 setgray 218 375 10 OC
218 370 moveto (21) CSH
1.0 setgray 146 252 10 FC
0.0 setgray 146 252 10 OC
146 247 moveto (22) CSH
1.0 setgray 117 149 10 FC
0.0 setgray 117 149 10 OC
117 144 moveto (23) CSH
1.0 setgray 132 332 10 FC
0.0 setgray 132 332 10 OC
132 327 moveto (24) CSH
1.0 setgray 88.7 149 10 FC
0.0 setgray 88.7 149 10 OC
88.7 144 moveto (25) CSH
1.0 setgray 60 103 10 FC
0.0 setgray 60 103 10 OC
60 97.6 moveto (26) CSH
1.0 setgray 74.3 175 10 FC
0.0 setgray 74.3 175 10 OC
74.3 170 moveto (27) CSH
1.0 setgray 103 375 10 FC
0.0 setgray 103 375 10 OC
103 370 moveto (28) CSH
1.0 setgray 160 490 10 FC
0.0 setgray 160 490 10 OC
160 485 moveto (29) CSH
1.0 setgray 275 490 10 FC
0.0 setgray 275 490 10 OC
275 485 moveto (30) CSH
grestore
% 60 60 430 430 rectstroke
showpage
tgray 476 175 10 OC
476 170 moveto (2) CSH
1.0 setgray 433 149 10 FC
0.0 setgray 433 149 10 OC
433 144 moveto (3) CSH
1.0 setgray 404 252 10 FC
0.0 setgray 404 252 10 OC
404 247 moveto (4) CSH
1.0 setgray 418 332 10 FC
0.0 setgray 418 332 10 OC
418 327 moveto (5) CSH
1.0 setgray 447 375 10 FC
0.0 setgray 447 375 10 OC
447 370 moveto (6) CSH
1.0 setgray 375 149 10 FC
0.0 setgray 375 149 10 OC
375 144 moveto (7) CSH
1.0 setgray 347 10ETree/doc/FS2.eps 0100644 0002055 0007177 00000010004 06652457247 0014761 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 50 50 500 500
/CSH {
%
% center show a string
%
% stack
% string str
%
dup stringwidth pop 2 div neg 0 rmoveto
show
} def
/ML {
%
% moveto lineto
%
% stack
% x0 y0 x1 y1
%
moveto lineto
} def
/FC {
%
% draw filled circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc fill
} def
/OC {
%
% draw open circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc stroke
} def
/rscale 10.000 def
/fontscale 10.000 def
% 60 60 430 430 rectclip
newpath
490 452 476 435 ML
461 460 476 435 ML
476 435 447 409 ML
433 477 418 452 ML
404 490 418 452 ML
418 452 447 409 ML
447 409 390 294 ML
375 460 361 435 ML
347 452 361 435 ML
361 435 332 409 ML
318 490 304 452 ML
289 477 304 452 ML
304 452 332 409 ML
332 409 390 294 ML
390 294 275 179 ML
261 477 246 452 ML
232 490 246 452 ML
246 452 218 409 ML
203 452 189 435 ML
175 460 189 435 ML
189 435 218 409 ML
218 409 160 294 ML
146 490 132 452 ML
117 477 132 452 ML
132 452 103 409 ML
88.7 460 74.3 435 ML
60 452 74.3 435 ML
74.3 435 103 409 ML
103 409 160 294 ML
160 294 275 179 ML
stroke
gsave
/Helvetica-Bold findfont fontscale scalefont setfont
1.0 setgray 490 452 10 FC
0.0 setgray 490 452 10 OC
490 447 moveto (0) CSH
1.0 setgray 461 460 10 FC
0.0 setgray 461 460 10 OC
461 455 moveto (1) CSH
1.0 setgray 476 435 10 FC
0.0 setgray 476 435 10 OC
476 430 moveto (2) CSH
1.0 setgray 433 477 10 FC
0.0 setgray 433 477 10 OC
433 472 moveto (3) CSH
1.0 setgray 404 490 10 FC
0.0 setgray 404 490 10 OC
404 485 moveto (4) CSH
1.0 setgray 418 452 10 FC
0.0 setgray 418 452 10 OC
418 447 moveto (5) CSH
1.0 setgray 447 409 10 FC
0.0 setgray 447 409 10 OC
447 404 moveto (6) CSH
1.0 setgray 375 460 10 FC
0.0 setgray 375 460 10 OC
375 455 moveto (7) CSH
1.0 setgray 347 452 10 FC
0.0 setgray 347 452 10 OC
347 447 moveto (8) CSH
1.0 setgray 361 435 10 FC
0.0 setgray 361 435 10 OC
361 430 moveto (9) CSH
1.0 setgray 318 490 10 FC
0.0 setgray 318 490 10 OC
318 485 moveto (10) CSH
1.0 setgray 289 477 10 FC
0.0 setgray 289 477 10 OC
289 472 moveto (11) CSH
1.0 setgray 304 452 10 FC
0.0 setgray 304 452 10 OC
304 447 moveto (12) CSH
1.0 setgray 332 409 10 FC
0.0 setgray 332 409 10 OC
332 404 moveto (13) CSH
1.0 setgray 390 294 10 FC
0.0 setgray 390 294 10 OC
390 289 moveto (14) CSH
1.0 setgray 261 477 10 FC
0.0 setgray 261 477 10 OC
261 472 moveto (15) CSH
1.0 setgray 232 490 10 FC
0.0 setgray 232 490 10 OC
232 485 moveto (16) CSH
1.0 setgray 246 452 10 FC
0.0 setgray 246 452 10 OC
246 447 moveto (17) CSH
1.0 setgray 203 452 10 FC
0.0 setgray 203 452 10 OC
203 447 moveto (18) CSH
1.0 setgray 175 460 10 FC
0.0 setgray 175 460 10 OC
175 455 moveto (19) CSH
1.0 setgray 189 435 10 FC
0.0 setgray 189 435 10 OC
189 430 moveto (20) CSH
1.0 setgray 218 409 10 FC
0.0 setgray 218 409 10 OC
218 404 moveto (21) CSH
1.0 setgray 146 490 10 FC
0.0 setgray 146 490 10 OC
146 485 moveto (22) CSH
1.0 setgray 117 477 10 FC
0.0 setgray 117 477 10 OC
117 472 moveto (23) CSH
1.0 setgray 132 452 10 FC
0.0 setgray 132 452 10 OC
132 447 moveto (24) CSH
1.0 setgray 88.7 460 10 FC
0.0 setgray 88.7 460 10 OC
88.7 455 moveto (25) CSH
1.0 setgray 60 452 10 FC
0.0 setgray 60 452 10 OC
60 447 moveto (26) CSH
1.0 setgray 74.3 435 10 FC
0.0 setgray 74.3 435 10 OC
74.3 430 moveto (27) CSH
1.0 setgray 103 409 10 FC
0.0 setgray 103 409 10 OC
103 404 moveto (28) CSH
1.0 setgray 160 294 10 FC
0.0 setgray 160 294 10 OC
160 289 moveto (29) CSH
1.0 setgray 275 179 10 FC
0.0 setgray 275 179 10 OC
275 174 moveto (30) CSH
grestore
% 60 60 430 430 rectstroke
showpage
ETree/doc/GRD7x7x7_nzA.eps 0100644 0002055 0007177 00000042702 06652460772 0016447 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 50 50 550 550
/CSH {
%
% center show a string
%
% stack
% string str
%
dup stringwidth pop 2 div neg 0 rmoveto
show
} def
/ML {
%
% moveto lineto
%
% stack
% x0 y0 x1 y1
%
moveto lineto
} def
/FC {
%
% draw filled circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc fill
} def
/OC {
%
% draw open circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc stroke
} def
/rscale 1.868 def
/fontscale 6.000 def
60 60 480 480 rectclip
newpath
535 278 495 272 ML
532 255 495 272 ML
495 272 453 263 ML
526 233 485 235 ML
518 211 485 235 ML
485 235 453 263 ML
453 263 407 251 ML
508 190 469 200 ML
496 171 469 200 ML
469 200 427 208 ML
483 152 446 170 ML
467 135 446 170 ML
446 170 427 208 ML
427 208 407 251 ML
407 251 353 243 ML
450 120 417 144 ML
431 106 417 144 ML
417 144 381 167 ML
412 94.1 384 124 ML
391 84.3 384 124 ML
384 124 381 167 ML
381 167 340 190 ML
369 76.6 348 111 ML
346 71 348 111 ML
348 111 324 146 ML
324 67.6 310 106 ML
301 66.5 310 106 ML
310 106 324 146 ML
324 146 340 190 ML
340 190 353 243 ML
353 243 299 262 ML
277 67.6 272 108 ML
255 71 272 108 ML
272 108 262 149 ML
232 76.6 234 117 ML
210 84.3 234 117 ML
234 117 262 149 ML
262 149 250 195 ML
190 94.1 200 133 ML
170 106 200 133 ML
200 133 207 175 ML
151 120 169 156 ML
134 135 169 156 ML
169 156 207 175 ML
207 175 250 195 ML
250 195 242 248 ML
118 152 143 184 ML
105 171 143 184 ML
143 184 166 220 ML
92.8 190 123 217 ML
82.9 211 123 217 ML
123 217 166 220 ML
166 220 190 261 ML
75.2 233 110 253 ML
69.5 255 110 253 ML
110 253 145 278 ML
66.1 278 105 291 ML
65 301 105 291 ML
105 291 145 278 ML
145 278 190 261 ML
190 261 242 248 ML
242 248 299 262 ML
299 262 301 301 ML
66.1 324 106 329 ML
69.5 346 106 329 ML
106 329 148 339 ML
75.2 369 116 366 ML
82.9 390 116 366 ML
116 366 148 339 ML
148 339 194 351 ML
92.8 411 132 401 ML
105 431 132 401 ML
132 401 174 394 ML
118 449 155 432 ML
134 466 155 432 ML
155 432 174 394 ML
174 394 194 351 ML
194 351 248 359 ML
151 482 184 458 ML
170 496 184 458 ML
184 458 220 435 ML
190 507 217 477 ML
210 517 217 477 ML
217 477 220 435 ML
220 435 261 411 ML
232 525 253 490 ML
255 530 253 490 ML
253 490 277 455 ML
277 534 291 496 ML
301 535 291 496 ML
291 496 277 455 ML
277 455 261 411 ML
261 411 248 359 ML
248 359 302 340 ML
324 534 329 494 ML
346 530 329 494 ML
329 494 339 452 ML
369 525 367 485 ML
391 517 367 485 ML
367 485 339 452 ML
stroke
newpath
339 452 351 407 ML
412 507 401 468 ML
431 496 401 468 ML
401 468 394 426 ML
450 482 432 445 ML
467 466 432 445 ML
432 445 394 426 ML
394 426 351 407 ML
351 407 359 353 ML
483 449 458 417 ML
496 431 458 417 ML
458 417 435 381 ML
508 411 478 384 ML
518 390 478 384 ML
478 384 435 381 ML
435 381 411 340 ML
526 369 491 348 ML
532 346 491 348 ML
491 348 456 324 ML
535 324 497 310 ML
536 301 497 310 ML
497 310 456 324 ML
456 324 411 340 ML
411 340 359 353 ML
359 353 302 340 ML
302 340 301 301 ML
stroke
gsave
1.0 setgray 535 278 2.11 rscale mul FC
0.0 setgray 535 278 2.11 rscale mul OC
535 278 1.5 sub moveto
1.0 setgray 532 255 2.65 rscale mul FC
0.0 setgray 532 255 2.65 rscale mul OC
532 255 1.5 sub moveto
1.0 setgray 495 272 2.39 rscale mul FC
0.0 setgray 495 272 2.39 rscale mul OC
495 272 1.5 sub moveto
1.0 setgray 526 233 2.65 rscale mul FC
0.0 setgray 526 233 2.65 rscale mul OC
526 233 1.5 sub moveto
1.0 setgray 518 211 3.29 rscale mul FC
0.0 setgray 518 211 3.29 rscale mul OC
518 211 1.5 sub moveto
1.0 setgray 485 235 3.09 rscale mul FC
0.0 setgray 485 235 3.09 rscale mul OC
485 235 1.5 sub moveto
1.0 setgray 453 263 4.37 rscale mul FC
0.0 setgray 453 263 4.37 rscale mul OC
453 263 1.5 sub moveto
1.0 setgray 508 190 2.65 rscale mul FC
0.0 setgray 508 190 2.65 rscale mul OC
508 190 1.5 sub moveto
1.0 setgray 496 171 3.29 rscale mul FC
0.0 setgray 496 171 3.29 rscale mul OC
496 171 1.5 sub moveto
1.0 setgray 469 200 3.09 rscale mul FC
0.0 setgray 469 200 3.09 rscale mul OC
469 200 1.5 sub moveto
1.0 setgray 483 152 3.29 rscale mul FC
0.0 setgray 483 152 3.29 rscale mul OC
483 152 1.5 sub moveto
1.0 setgray 467 135 4.07 rscale mul FC
0.0 setgray 467 135 4.07 rscale mul OC
467 135 1.5 sub moveto
1.0 setgray 446 170 3.91 rscale mul FC
0.0 setgray 446 170 3.91 rscale mul OC
446 170 1.5 sub moveto
1.0 setgray 427 208 5.86 rscale mul FC
0.0 setgray 427 208 5.86 rscale mul OC
427 208 1.5 sub moveto
1.0 setgray 407 251 6.63 rscale mul FC
0.0 setgray 407 251 6.63 rscale mul OC
407 251 1.5 sub moveto
1.0 setgray 450 120 2.65 rscale mul FC
0.0 setgray 450 120 2.65 rscale mul OC
450 120 1.5 sub moveto
1.0 setgray 431 106 2.11 rscale mul FC
0.0 setgray 431 106 2.11 rscale mul OC
431 106 1.5 sub moveto
1.0 setgray 417 144 2.39 rscale mul FC
0.0 setgray 417 144 2.39 rscale mul OC
417 144 1.5 sub moveto
1.0 setgray 412 94.1 3.29 rscale mul FC
0.0 setgray 412 94.1 3.29 rscale mul OC
412 94.1 1.5 sub moveto
1.0 setgray 391 84.3 2.65 rscale mul FC
0.0 setgray 391 84.3 2.65 rscale mul OC
391 84.3 1.5 sub moveto
1.0 setgray 384 124 3.09 rscale mul FC
0.0 setgray 384 124 3.09 rscale mul OC
384 124 1.5 sub moveto
1.0 setgray 381 167 4.37 rscale mul FC
0.0 setgray 381 167 4.37 rscale mul OC
381 167 1.5 sub moveto
1.0 setgray 369 76.6 3.29 rscale mul FC
0.0 setgray 369 76.6 3.29 rscale mul OC
369 76.6 1.5 sub moveto
1.0 setgray 346 71 2.65 rscale mul FC
0.0 setgray 346 71 2.65 rscale mul OC
346 71 1.5 sub moveto
1.0 setgray 348 111 3.09 rscale mul FC
0.0 setgray 348 111 3.09 rscale mul OC
348 111 1.5 sub moveto
1.0 setgray 324 67.6 4.07 rscale mul FC
0.0 setgray 324 67.6 4.07 rscale mul OC
324 67.6 1.5 sub moveto
1.0 setgray 301 66.5 3.29 rscale mul FC
0.0 setgray 301 66.5 3.29 rscale mul OC
301 66.5 1.5 sub moveto
1.0 setgray 310 106 3.91 rscale mul FC
0.0 setgray 310 106 3.91 rscale mul OC
310 106 1.5 sub moveto
1.0 setgray 324 146 5.86 rscale mul FC
0.0 setgray 324 146 5.86 rscale mul OC
324 146 1.5 sub moveto
1.0 setgray 340 190 6.63 rscale mul FC
0.0 setgray 340 190 6.63 rscale mul OC
340 190 1.5 sub moveto
1.0 setgray 353 243 6.63 rscale mul FC
0.0 setgray 353 243 6.63 rscale mul OC
353 243 1.5 sub moveto
1.0 setgray 277 67.6 2.65 rscale mul FC
0.0 setgray 277 67.6 2.65 rscale mul OC
277 67.6 1.5 sub moveto
1.0 setgray 255 71 3.29 rscale mul FC
0.0 setgray 255 71 3.29 rscale mul OC
255 71 1.5 sub moveto
1.0 setgray 272 108 3.09 rscale mul FC
0.0 setgray 272 108 3.09 rscale mul OC
272 108 1.5 sub moveto
1.0 setgray 232 76.6 2.11 rscale mul FC
0.0 setgray 232 76.6 2.11 rscale mul OC
232 76.6 1.5 sub moveto
1.0 setgray 210 84.3 2.65 rscale mul FC
0.0 setgray 210 84.3 2.65 rscale mul OC
210 84.3 1.5 sub moveto
1.0 setgray 234 117 2.39 rscale mul FC
0.0 setgray 234 117 2.39 rscale mul OC
234 117 1.5 sub moveto
1.0 setgray 262 149 4.37 rscale mul FC
0.0 setgray 262 149 4.37 rscale mul OC
262 149 1.5 sub moveto
1.0 setgray 190 94.1 3.29 rscale mul FC
0.0 setgray 190 94.1 3.29 rscale mul OC
190 94.1 1.5 sub moveto
1.0 setgray 170 106 4.07 rscale mul FC
0.0 setgray 170 106 4.07 rscale mul OC
170 106 1.5 sub moveto
1.0 setgray 200 133 3.91 rscale mul FC
0.0 setgray 200 133 3.91 rscale mul OC
200 133 1.5 sub moveto
1.0 setgray 151 120 2.65 rscale mul FC
0.0 setgray 151 120 2.65 rscale mul OC
151 120 1.5 sub moveto
1.0 setgray 134 135 3.29 rscale mul FC
0.0 setgray 134 135 3.29 rscale mul OC
134 135 1.5 sub moveto
1.0 setgray 169 156 3.09 rscale mul FC
0.0 setgray 169 156 3.09 rscale mul OC
169 156 1.5 sub moveto
1.0 setgray 207 175 5.86 rscale mul FC
0.0 setgray 207 175 5.86 rscale mul OC
207 175 1.5 sub moveto
1.0 setgray 250 195 6.63 rscale mul FC
0.0 setgray 250 195 6.63 rscale mul OC
250 195 1.5 sub moveto
1.0 setgray 118 152 3.29 rscale mul FC
0.0 setgray 118 152 3.29 rscale mul OC
118 152 1.5 sub moveto
1.0 setgray 105 171 2.65 rscale mul FC
0.0 setgray 105 171 2.65 rscale mul OC
105 171 1.5 sub moveto
1.0 setgray 143 184 3.09 rscale mul FC
0.0 setgray 143 184 3.09 rscale mul OC
143 184 1.5 sub moveto
1.0 setgray 92.8 190 2.65 rscale mul FC
0.0 setgray 92.8 190 2.65 rscale mul OC
92.8 190 1.5 sub moveto
1.0 setgray 82.9 211 2.11 rscale mul FC
0.0 setgray 82.9 211 2.11 rscale mul OC
82.9 211 1.5 sub moveto
1.0 setgray 123 217 2.39 rscale mul FC
0.0 setgray 123 217 2.39 rscale mul OC
123 217 1.5 sub moveto
1.0 setgray 166 220 4.37 rscale mul FC
0.0 setgray 166 220 4.37 rscale mul OC
166 220 1.5 sub moveto
1.0 setgray 75.2 233 4.07 rscale mul FC
0.0 setgray 75.2 233 4.07 rscale mul OC
75.2 233 1.5 sub moveto
1.0 setgray 69.5 255 3.29 rscale mul FC
0.0 setgray 69.5 255 3.29 rscale mul OC
69.5 255 1.5 sub moveto
1.0 setgray 110 253 3.91 rscale mul FC
0.0 setgray 110 253 3.91 rscale mul OC
110 253 1.5 sub moveto
1.0 setgray 66.1 278 3.29 rscale mul FC
0.0 setgray 66.1 278 3.29 rscale mul OC
66.1 278 1.5 sub moveto
1.0 setgray 65 301 2.65 rscale mul FC
0.0 setgray 65 301 2.65 rscale mul OC
65 301 1.5 sub moveto
1.0 setgray 105 291 3.09 rscale mul FC
0.0 setgray 105 291 3.09 rscale mul OC
105 291 1.5 sub moveto
1.0 setgray 145 278 5.86 rscale mul FC
0.0 setgray 145 278 5.86 rscale mul OC
145 278 1.5 sub moveto
1.0 setgray 190 261 6.63 rscale mul FC
0.0 setgray 190 261 6.63 rscale mul OC
190 261 1.5 sub moveto
1.0 setgray 242 248 6.63 rscale mul FC
0.0 setgray 242 248 6.63 rscale mul OC
242 248 1.5 sub moveto
1.0 setgray 299 262 8.85 rscale mul FC
0.0 setgray 299 262 8.85 rscale mul OC
299 262 1.5 sub moveto
1.0 setgray 66.1 324 2.65 rscale mul FC
0.0 setgray 66.1 324 2.65 rscale mul OC
66.1 324 1.5 sub moveto
1.0 setgray 69.5 346 3.29 rscale mul FC
0.0 setgray 69.5 346 3.29 rscale mul OC
69.5 346 1.5 sub moveto
1.0 setgray 106 329 3.09 rscale mul FC
0.0 setgray 106 329 3.09 rscale mul OC
106 329 1.5 sub moveto
1.0 setgray 75.2 369 3.29 rscale mul FC
0.0 setgray 75.2 369 3.29 rscale mul OC
75.2 369 1.5 sub moveto
1.0 setgray 82.9 390 4.07 rscale mul FC
0.0 setgray 82.9 390 4.07 rscale mul OC
82.9 390 1.5 sub moveto
1.0 setgray 116 366 3.91 rscale mul FC
0.0 setgray 116 366 3.91 rscale mul OC
116 366 1.5 sub moveto
1.0 setgray 148 339 5.86 rscale mul FC
0.0 setgray 148 339 5.86 rscale mul OC
148 339 1.5 sub moveto
1.0 setgray 92.8 411 2.11 rscale mul FC
0.0 setgray 92.8 411 2.11 rscale mul OC
92.8 411 1.5 sub moveto
1.0 setgray 105 431 2.65 rscale mul FC
0.0 setgray 105 431 2.65 rscale mul OC
105 431 1.5 sub moveto
1.0 setgray 132 401 2.39 rscale mul FC
0.0 setgray 132 401 2.39 rscale mul OC
132 401 1.5 sub moveto
1.0 setgray 118 449 2.65 rscale mul FC
0.0 setgray 118 449 2.65 rscale mul OC
118 449 1.5 sub moveto
1.0 setgray 134 466 3.29 rscale mul FC
0.0 setgray 134 466 3.29 rscale mul OC
134 466 1.5 sub moveto
1.0 setgray 155 432 3.09 rscale mul FC
0.0 setgray 155 432 3.09 rscale mul OC
155 432 1.5 sub moveto
1.0 setgray 174 394 4.37 rscale mul FC
0.0 setgray 174 394 4.37 rscale mul OC
174 394 1.5 sub moveto
1.0 setgray 194 351 6.63 rscale mul FC
0.0 setgray 194 351 6.63 rscale mul OC
194 351 1.5 sub moveto
1.0 setgray 151 482 3.29 rscale mul FC
0.0 setgray 151 482 3.29 rscale mul OC
151 482 1.5 sub moveto
1.0 setgray 170 496 2.65 rscale mul FC
0.0 setgray 170 496 2.65 rscale mul OC
170 496 1.5 sub moveto
1.0 setgray 184 458 3.09 rscale mul FC
0.0 setgray 184 458 3.09 rscale mul OC
184 458 1.5 sub moveto
1.0 setgray 190 507 4.07 rscale mul FC
0.0 setgray 190 507 4.07 rscale mul OC
190 507 1.5 sub moveto
1.0 setgray 210 517 3.29 rscale mul FC
0.0 setgray 210 517 3.29 rscale mul OC
210 517 1.5 sub moveto
1.0 setgray 217 477 3.91 rscale mul FC
0.0 setgray 217 477 3.91 rscale mul OC
217 477 1.5 sub moveto
1.0 setgray 220 435 5.86 rscale mul FC
0.0 setgray 220 435 5.86 rscale mul OC
220 435 1.5 sub moveto
1.0 setgray 232 525 2.65 rscale mul FC
0.0 setgray 232 525 2.65 rscale mul OC
232 525 1.5 sub moveto
1.0 setgray 255 530 2.11 rscale mul FC
0.0 setgray 255 530 2.11 rscale mul OC
255 530 1.5 sub moveto
1.0 setgray 253 490 2.39 rscale mul FC
0.0 setgray 253 490 2.39 rscale mul OC
253 490 1.5 sub moveto
1.0 setgray 277 534 3.29 rscale mul FC
0.0 setgray 277 534 3.29 rscale mul OC
277 534 1.5 sub moveto
1.0 setgray 301 535 2.65 rscale mul FC
0.0 setgray 301 535 2.65 rscale mul OC
301 535 1.5 sub moveto
1.0 setgray 291 496 3.09 rscale mul FC
0.0 setgray 291 496 3.09 rscale mul OC
291 496 1.5 sub moveto
1.0 setgray 277 455 4.37 rscale mul FC
0.0 setgray 277 455 4.37 rscale mul OC
277 455 1.5 sub moveto
1.0 setgray 261 411 6.63 rscale mul FC
0.0 setgray 261 411 6.63 rscale mul OC
261 411 1.5 sub moveto
1.0 setgray 248 359 6.63 rscale mul FC
0.0 setgray 248 359 6.63 rscale mul OC
248 359 1.5 sub moveto
1.0 setgray 324 534 3.29 rscale mul FC
0.0 setgray 324 534 3.29 rscale mul OC
324 534 1.5 sub moveto
1.0 setgray 346 530 4.07 rscale mul FC
0.0 setgray 346 530 4.07 rscale mul OC
346 530 1.5 sub moveto
1.0 setgray 329 494 3.91 rscale mul FC
0.0 setgray 329 494 3.91 rscale mul OC
329 494 1.5 sub moveto
1.0 setgray 369 525 2.65 rscale mul FC
0.0 setgray 369 525 2.65 rscale mul OC
369 525 1.5 sub moveto
1.0 setgray 391 517 3.29 rscale mul FC
0.0 setgray 391 517 3.29 rscale mul OC
391 517 1.5 sub moveto
1.0 setgray 367 485 3.09 rscale mul FC
0.0 setgray 367 485 3.09 rscale mul OC
367 485 1.5 sub moveto
1.0 setgray 339 452 5.86 rscale mul FC
0.0 setgray 339 452 5.86 rscale mul OC
339 452 1.5 sub moveto
1.0 setgray 412 507 2.65 rscale mul FC
0.0 setgray 412 507 2.65 rscale mul OC
412 507 1.5 sub moveto
1.0 setgray 431 496 3.29 rscale mul FC
0.0 setgray 431 496 3.29 rscale mul OC
431 496 1.5 sub moveto
1.0 setgray 401 468 3.09 rscale mul FC
0.0 setgray 401 468 3.09 rscale mul OC
401 468 1.5 sub moveto
1.0 setgray 450 482 2.11 rscale mul FC
0.0 setgray 450 482 2.11 rscale mul OC
450 482 1.5 sub moveto
1.0 setgray 467 466 2.65 rscale mul FC
0.0 setgray 467 466 2.65 rscale mul OC
467 466 1.5 sub moveto
1.0 setgray 432 445 2.39 rscale mul FC
0.0 setgray 432 445 2.39 rscale mul OC
432 445 1.5 sub moveto
1.0 setgray 394 426 4.37 rscale mul FC
0.0 setgray 394 426 4.37 rscale mul OC
394 426 1.5 sub moveto
1.0 setgray 351 407 6.63 rscale mul FC
0.0 setgray 351 407 6.63 rscale mul OC
351 407 1.5 sub moveto
1.0 setgray 483 449 4.07 rscale mul FC
0.0 setgray 483 449 4.07 rscale mul OC
483 449 1.5 sub moveto
1.0 setgray 496 431 3.29 rscale mul FC
0.0 setgray 496 431 3.29 rscale mul OC
496 431 1.5 sub moveto
1.0 setgray 458 417 3.91 rscale mul FC
0.0 setgray 458 417 3.91 rscale mul OC
458 417 1.5 sub moveto
1.0 setgray 508 411 3.29 rscale mul FC
0.0 setgray 508 411 3.29 rscale mul OC
508 411 1.5 sub moveto
1.0 setgray 518 390 2.65 rscale mul FC
0.0 setgray 518 390 2.65 rscale mul OC
518 390 1.5 sub moveto
1.0 setgray 478 384 3.09 rscale mul FC
0.0 setgray 478 384 3.09 rscale mul OC
478 384 1.5 sub moveto
1.0 setgray 435 381 5.86 rscale mul FC
0.0 setgray 435 381 5.86 rscale mul OC
435 381 1.5 sub moveto
1.0 setgray 526 369 3.29 rscale mul FC
0.0 setgray 526 369 3.29 rscale mul OC
526 369 1.5 sub moveto
1.0 setgray 532 346 2.65 rscale mul FC
0.0 setgray 532 346 2.65 rscale mul OC
532 346 1.5 sub moveto
1.0 setgray 491 348 3.09 rscale mul FC
0.0 setgray 491 348 3.09 rscale mul OC
491 348 1.5 sub moveto
1.0 setgray 535 324 2.65 rscale mul FC
0.0 setgray 535 324 2.65 rscale mul OC
535 324 1.5 sub moveto
1.0 setgray 536 301 2.11 rscale mul FC
0.0 setgray 536 301 2.11 rscale mul OC
536 301 1.5 sub moveto
1.0 setgray 497 310 2.39 rscale mul FC
0.0 setgray 497 310 2.39 rscale mul OC
497 310 1.5 sub moveto
1.0 setgray 456 324 4.37 rscale mul FC
0.0 setgray 456 324 4.37 rscale mul OC
456 324 1.5 sub moveto
1.0 setgray 411 340 6.63 rscale mul FC
0.0 setgray 411 340 6.63 rscale mul OC
411 340 1.5 sub moveto
1.0 setgray 359 353 6.63 rscale mul FC
0.0 setgray 359 353 6.63 rscale mul OC
359 353 1.5 sub moveto
1.0 setgray 302 340 8.85 rscale mul FC
0.0 setgray 302 340 8.85 rscale mul OC
302 340 1.5 sub moveto
1.0 setgray 301 301 10.7 rscale mul FC
0.0 setgray 301 301 10.7 rscale mul OC
301 301 1.5 sub moveto
grestore
60 60 480 480 rectstroke
showpage setgray 262 149 4.37 rscale mul FC
0.0 setgray 262 149 4.ETree/doc/GRD7x7x7_nzF.eps 0100644 0002055 0007177 00000042622 06652461052 0016445 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 50 50 550 550
/CSH {
%
% center show a string
%
% stack
% string str
%
dup stringwidth pop 2 div neg 0 rmoveto
show
} def
/ML {
%
% moveto lineto
%
% stack
% x0 y0 x1 y1
%
moveto lineto
} def
/FC {
%
% draw filled circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc fill
} def
/OC {
%
% draw open circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc stroke
} def
/rscale 0.999 def
/fontscale 6.000 def
60 60 480 480 rectclip
newpath
539 276 498 271 ML
535 253 498 271 ML
498 271 455 261 ML
530 230 488 233 ML
522 208 488 233 ML
488 233 455 261 ML
455 261 408 249 ML
512 187 472 197 ML
500 167 472 197 ML
472 197 429 205 ML
486 148 448 166 ML
470 130 448 166 ML
448 166 429 205 ML
429 205 408 249 ML
408 249 354 241 ML
452 114 419 139 ML
433 100 419 139 ML
419 139 382 163 ML
413 88.3 386 119 ML
392 78.3 386 119 ML
386 119 382 163 ML
382 163 340 187 ML
370 70.3 349 106 ML
347 64.6 349 106 ML
349 106 323 142 ML
324 61.2 310 100 ML
300 60 310 100 ML
310 100 323 142 ML
323 142 340 187 ML
340 187 354 241 ML
354 241 298 260 ML
276 61.2 271 102 ML
253 64.6 271 102 ML
271 102 261 145 ML
230 70.3 233 112 ML
208 78.3 233 112 ML
233 112 261 145 ML
261 145 249 192 ML
187 88.3 197 128 ML
167 100 197 128 ML
197 128 205 171 ML
148 114 166 152 ML
130 130 166 152 ML
166 152 205 171 ML
205 171 249 192 ML
249 192 241 246 ML
114 148 139 181 ML
100 167 139 181 ML
139 181 163 218 ML
88.3 187 119 214 ML
78.3 208 119 214 ML
119 214 163 218 ML
163 218 187 260 ML
70.3 230 106 251 ML
64.6 253 106 251 ML
106 251 142 277 ML
61.2 276 100 290 ML
60 300 100 290 ML
100 290 142 277 ML
142 277 187 260 ML
187 260 241 246 ML
241 246 298 260 ML
298 260 300 300 ML
61.2 324 102 329 ML
64.6 347 102 329 ML
102 329 145 339 ML
70.3 370 112 367 ML
78.3 392 112 367 ML
112 367 145 339 ML
145 339 192 351 ML
88.3 413 128 403 ML
100 433 128 403 ML
128 403 171 395 ML
114 452 152 434 ML
130 470 152 434 ML
152 434 171 395 ML
171 395 192 351 ML
192 351 246 359 ML
148 486 181 461 ML
167 500 181 461 ML
181 461 218 437 ML
187 512 214 481 ML
208 522 214 481 ML
214 481 218 437 ML
218 437 260 413 ML
230 530 251 494 ML
253 535 251 494 ML
251 494 277 458 ML
276 539 290 500 ML
300 540 290 500 ML
290 500 277 458 ML
277 458 260 413 ML
260 413 246 359 ML
246 359 302 340 ML
324 539 329 498 ML
347 535 329 498 ML
329 498 339 455 ML
370 530 367 488 ML
392 522 367 488 ML
367 488 339 455 ML
stroke
newpath
339 455 351 408 ML
413 512 403 472 ML
433 500 403 472 ML
403 472 395 429 ML
452 486 434 448 ML
470 470 434 448 ML
434 448 395 429 ML
395 429 351 408 ML
351 408 359 354 ML
486 452 461 419 ML
500 433 461 419 ML
461 419 437 382 ML
512 413 481 386 ML
522 392 481 386 ML
481 386 437 382 ML
437 382 413 340 ML
530 370 494 349 ML
535 347 494 349 ML
494 349 458 323 ML
539 324 500 310 ML
540 300 500 310 ML
500 310 458 323 ML
458 323 413 340 ML
413 340 359 354 ML
359 354 302 340 ML
302 340 300 300 ML
stroke
gsave
1.0 setgray 539 276 1.6 rscale mul FC
0.0 setgray 539 276 1.6 rscale mul OC
539 276 1.5 sub moveto
1.0 setgray 535 253 1.95 rscale mul FC
0.0 setgray 535 253 1.95 rscale mul OC
535 253 1.5 sub moveto
1.0 setgray 498 271 2.11 rscale mul FC
0.0 setgray 498 271 2.11 rscale mul OC
498 271 1.5 sub moveto
1.0 setgray 530 230 1.95 rscale mul FC
0.0 setgray 530 230 1.95 rscale mul OC
530 230 1.5 sub moveto
1.0 setgray 522 208 2.39 rscale mul FC
0.0 setgray 522 208 2.39 rscale mul OC
522 208 1.5 sub moveto
1.0 setgray 488 233 2.65 rscale mul FC
0.0 setgray 488 233 2.65 rscale mul OC
488 233 1.5 sub moveto
1.0 setgray 455 261 4.89 rscale mul FC
0.0 setgray 455 261 4.89 rscale mul OC
455 261 1.5 sub moveto
1.0 setgray 512 187 1.95 rscale mul FC
0.0 setgray 512 187 1.95 rscale mul OC
512 187 1.5 sub moveto
1.0 setgray 500 167 2.39 rscale mul FC
0.0 setgray 500 167 2.39 rscale mul OC
500 167 1.5 sub moveto
1.0 setgray 472 197 2.65 rscale mul FC
0.0 setgray 472 197 2.65 rscale mul OC
472 197 1.5 sub moveto
1.0 setgray 486 148 2.39 rscale mul FC
0.0 setgray 486 148 2.39 rscale mul OC
486 148 1.5 sub moveto
1.0 setgray 470 130 2.93 rscale mul FC
0.0 setgray 470 130 2.93 rscale mul OC
470 130 1.5 sub moveto
1.0 setgray 448 166 3.29 rscale mul FC
0.0 setgray 448 166 3.29 rscale mul OC
448 166 1.5 sub moveto
1.0 setgray 429 205 6.26 rscale mul FC
0.0 setgray 429 205 6.26 rscale mul OC
429 205 1.5 sub moveto
1.0 setgray 408 249 11 rscale mul FC
0.0 setgray 408 249 11 rscale mul OC
408 249 1.5 sub moveto
1.0 setgray 452 114 1.95 rscale mul FC
0.0 setgray 452 114 1.95 rscale mul OC
452 114 1.5 sub moveto
1.0 setgray 433 100 1.6 rscale mul FC
0.0 setgray 433 100 1.6 rscale mul OC
433 100 1.5 sub moveto
1.0 setgray 419 139 2.11 rscale mul FC
0.0 setgray 419 139 2.11 rscale mul OC
419 139 1.5 sub moveto
1.0 setgray 413 88.3 2.39 rscale mul FC
0.0 setgray 413 88.3 2.39 rscale mul OC
413 88.3 1.5 sub moveto
1.0 setgray 392 78.3 1.95 rscale mul FC
0.0 setgray 392 78.3 1.95 rscale mul OC
392 78.3 1.5 sub moveto
1.0 setgray 386 119 2.65 rscale mul FC
0.0 setgray 386 119 2.65 rscale mul OC
386 119 1.5 sub moveto
1.0 setgray 382 163 4.89 rscale mul FC
0.0 setgray 382 163 4.89 rscale mul OC
382 163 1.5 sub moveto
1.0 setgray 370 70.3 2.39 rscale mul FC
0.0 setgray 370 70.3 2.39 rscale mul OC
370 70.3 1.5 sub moveto
1.0 setgray 347 64.6 1.95 rscale mul FC
0.0 setgray 347 64.6 1.95 rscale mul OC
347 64.6 1.5 sub moveto
1.0 setgray 349 106 2.65 rscale mul FC
0.0 setgray 349 106 2.65 rscale mul OC
349 106 1.5 sub moveto
1.0 setgray 324 61.2 2.93 rscale mul FC
0.0 setgray 324 61.2 2.93 rscale mul OC
324 61.2 1.5 sub moveto
1.0 setgray 300 60 2.39 rscale mul FC
0.0 setgray 300 60 2.39 rscale mul OC
300 60 1.5 sub moveto
1.0 setgray 310 100 3.29 rscale mul FC
0.0 setgray 310 100 3.29 rscale mul OC
310 100 1.5 sub moveto
1.0 setgray 323 142 6.26 rscale mul FC
0.0 setgray 323 142 6.26 rscale mul OC
323 142 1.5 sub moveto
1.0 setgray 340 187 11 rscale mul FC
0.0 setgray 340 187 11 rscale mul OC
340 187 1.5 sub moveto
1.0 setgray 354 241 12.4 rscale mul FC
0.0 setgray 354 241 12.4 rscale mul OC
354 241 1.5 sub moveto
1.0 setgray 276 61.2 1.95 rscale mul FC
0.0 setgray 276 61.2 1.95 rscale mul OC
276 61.2 1.5 sub moveto
1.0 setgray 253 64.6 2.39 rscale mul FC
0.0 setgray 253 64.6 2.39 rscale mul OC
253 64.6 1.5 sub moveto
1.0 setgray 271 102 2.65 rscale mul FC
0.0 setgray 271 102 2.65 rscale mul OC
271 102 1.5 sub moveto
1.0 setgray 230 70.3 1.6 rscale mul FC
0.0 setgray 230 70.3 1.6 rscale mul OC
230 70.3 1.5 sub moveto
1.0 setgray 208 78.3 1.95 rscale mul FC
0.0 setgray 208 78.3 1.95 rscale mul OC
208 78.3 1.5 sub moveto
1.0 setgray 233 112 2.11 rscale mul FC
0.0 setgray 233 112 2.11 rscale mul OC
233 112 1.5 sub moveto
1.0 setgray 261 145 4.89 rscale mul FC
0.0 setgray 261 145 4.89 rscale mul OC
261 145 1.5 sub moveto
1.0 setgray 187 88.3 2.39 rscale mul FC
0.0 setgray 187 88.3 2.39 rscale mul OC
187 88.3 1.5 sub moveto
1.0 setgray 167 100 2.93 rscale mul FC
0.0 setgray 167 100 2.93 rscale mul OC
167 100 1.5 sub moveto
1.0 setgray 197 128 3.29 rscale mul FC
0.0 setgray 197 128 3.29 rscale mul OC
197 128 1.5 sub moveto
1.0 setgray 148 114 1.95 rscale mul FC
0.0 setgray 148 114 1.95 rscale mul OC
148 114 1.5 sub moveto
1.0 setgray 130 130 2.39 rscale mul FC
0.0 setgray 130 130 2.39 rscale mul OC
130 130 1.5 sub moveto
1.0 setgray 166 152 2.65 rscale mul FC
0.0 setgray 166 152 2.65 rscale mul OC
166 152 1.5 sub moveto
1.0 setgray 205 171 6.26 rscale mul FC
0.0 setgray 205 171 6.26 rscale mul OC
205 171 1.5 sub moveto
1.0 setgray 249 192 11 rscale mul FC
0.0 setgray 249 192 11 rscale mul OC
249 192 1.5 sub moveto
1.0 setgray 114 148 2.39 rscale mul FC
0.0 setgray 114 148 2.39 rscale mul OC
114 148 1.5 sub moveto
1.0 setgray 100 167 1.95 rscale mul FC
0.0 setgray 100 167 1.95 rscale mul OC
100 167 1.5 sub moveto
1.0 setgray 139 181 2.65 rscale mul FC
0.0 setgray 139 181 2.65 rscale mul OC
139 181 1.5 sub moveto
1.0 setgray 88.3 187 1.95 rscale mul FC
0.0 setgray 88.3 187 1.95 rscale mul OC
88.3 187 1.5 sub moveto
1.0 setgray 78.3 208 1.6 rscale mul FC
0.0 setgray 78.3 208 1.6 rscale mul OC
78.3 208 1.5 sub moveto
1.0 setgray 119 214 2.11 rscale mul FC
0.0 setgray 119 214 2.11 rscale mul OC
119 214 1.5 sub moveto
1.0 setgray 163 218 4.89 rscale mul FC
0.0 setgray 163 218 4.89 rscale mul OC
163 218 1.5 sub moveto
1.0 setgray 70.3 230 2.93 rscale mul FC
0.0 setgray 70.3 230 2.93 rscale mul OC
70.3 230 1.5 sub moveto
1.0 setgray 64.6 253 2.39 rscale mul FC
0.0 setgray 64.6 253 2.39 rscale mul OC
64.6 253 1.5 sub moveto
1.0 setgray 106 251 3.29 rscale mul FC
0.0 setgray 106 251 3.29 rscale mul OC
106 251 1.5 sub moveto
1.0 setgray 61.2 276 2.39 rscale mul FC
0.0 setgray 61.2 276 2.39 rscale mul OC
61.2 276 1.5 sub moveto
1.0 setgray 60 300 1.95 rscale mul FC
0.0 setgray 60 300 1.95 rscale mul OC
60 300 1.5 sub moveto
1.0 setgray 100 290 2.65 rscale mul FC
0.0 setgray 100 290 2.65 rscale mul OC
100 290 1.5 sub moveto
1.0 setgray 142 277 6.26 rscale mul FC
0.0 setgray 142 277 6.26 rscale mul OC
142 277 1.5 sub moveto
1.0 setgray 187 260 11 rscale mul FC
0.0 setgray 187 260 11 rscale mul OC
187 260 1.5 sub moveto
1.0 setgray 241 246 12.4 rscale mul FC
0.0 setgray 241 246 12.4 rscale mul OC
241 246 1.5 sub moveto
1.0 setgray 298 260 20 rscale mul FC
0.0 setgray 298 260 20 rscale mul OC
298 260 1.5 sub moveto
1.0 setgray 61.2 324 1.95 rscale mul FC
0.0 setgray 61.2 324 1.95 rscale mul OC
61.2 324 1.5 sub moveto
1.0 setgray 64.6 347 2.39 rscale mul FC
0.0 setgray 64.6 347 2.39 rscale mul OC
64.6 347 1.5 sub moveto
1.0 setgray 102 329 2.65 rscale mul FC
0.0 setgray 102 329 2.65 rscale mul OC
102 329 1.5 sub moveto
1.0 setgray 70.3 370 2.39 rscale mul FC
0.0 setgray 70.3 370 2.39 rscale mul OC
70.3 370 1.5 sub moveto
1.0 setgray 78.3 392 2.93 rscale mul FC
0.0 setgray 78.3 392 2.93 rscale mul OC
78.3 392 1.5 sub moveto
1.0 setgray 112 367 3.29 rscale mul FC
0.0 setgray 112 367 3.29 rscale mul OC
112 367 1.5 sub moveto
1.0 setgray 145 339 6.26 rscale mul FC
0.0 setgray 145 339 6.26 rscale mul OC
145 339 1.5 sub moveto
1.0 setgray 88.3 413 1.6 rscale mul FC
0.0 setgray 88.3 413 1.6 rscale mul OC
88.3 413 1.5 sub moveto
1.0 setgray 100 433 1.95 rscale mul FC
0.0 setgray 100 433 1.95 rscale mul OC
100 433 1.5 sub moveto
1.0 setgray 128 403 2.11 rscale mul FC
0.0 setgray 128 403 2.11 rscale mul OC
128 403 1.5 sub moveto
1.0 setgray 114 452 1.95 rscale mul FC
0.0 setgray 114 452 1.95 rscale mul OC
114 452 1.5 sub moveto
1.0 setgray 130 470 2.39 rscale mul FC
0.0 setgray 130 470 2.39 rscale mul OC
130 470 1.5 sub moveto
1.0 setgray 152 434 2.65 rscale mul FC
0.0 setgray 152 434 2.65 rscale mul OC
152 434 1.5 sub moveto
1.0 setgray 171 395 4.89 rscale mul FC
0.0 setgray 171 395 4.89 rscale mul OC
171 395 1.5 sub moveto
1.0 setgray 192 351 11 rscale mul FC
0.0 setgray 192 351 11 rscale mul OC
192 351 1.5 sub moveto
1.0 setgray 148 486 2.39 rscale mul FC
0.0 setgray 148 486 2.39 rscale mul OC
148 486 1.5 sub moveto
1.0 setgray 167 500 1.95 rscale mul FC
0.0 setgray 167 500 1.95 rscale mul OC
167 500 1.5 sub moveto
1.0 setgray 181 461 2.65 rscale mul FC
0.0 setgray 181 461 2.65 rscale mul OC
181 461 1.5 sub moveto
1.0 setgray 187 512 2.93 rscale mul FC
0.0 setgray 187 512 2.93 rscale mul OC
187 512 1.5 sub moveto
1.0 setgray 208 522 2.39 rscale mul FC
0.0 setgray 208 522 2.39 rscale mul OC
208 522 1.5 sub moveto
1.0 setgray 214 481 3.29 rscale mul FC
0.0 setgray 214 481 3.29 rscale mul OC
214 481 1.5 sub moveto
1.0 setgray 218 437 6.26 rscale mul FC
0.0 setgray 218 437 6.26 rscale mul OC
218 437 1.5 sub moveto
1.0 setgray 230 530 1.95 rscale mul FC
0.0 setgray 230 530 1.95 rscale mul OC
230 530 1.5 sub moveto
1.0 setgray 253 535 1.6 rscale mul FC
0.0 setgray 253 535 1.6 rscale mul OC
253 535 1.5 sub moveto
1.0 setgray 251 494 2.11 rscale mul FC
0.0 setgray 251 494 2.11 rscale mul OC
251 494 1.5 sub moveto
1.0 setgray 276 539 2.39 rscale mul FC
0.0 setgray 276 539 2.39 rscale mul OC
276 539 1.5 sub moveto
1.0 setgray 300 540 1.95 rscale mul FC
0.0 setgray 300 540 1.95 rscale mul OC
300 540 1.5 sub moveto
1.0 setgray 290 500 2.65 rscale mul FC
0.0 setgray 290 500 2.65 rscale mul OC
290 500 1.5 sub moveto
1.0 setgray 277 458 4.89 rscale mul FC
0.0 setgray 277 458 4.89 rscale mul OC
277 458 1.5 sub moveto
1.0 setgray 260 413 11 rscale mul FC
0.0 setgray 260 413 11 rscale mul OC
260 413 1.5 sub moveto
1.0 setgray 246 359 12.4 rscale mul FC
0.0 setgray 246 359 12.4 rscale mul OC
246 359 1.5 sub moveto
1.0 setgray 324 539 2.39 rscale mul FC
0.0 setgray 324 539 2.39 rscale mul OC
324 539 1.5 sub moveto
1.0 setgray 347 535 2.93 rscale mul FC
0.0 setgray 347 535 2.93 rscale mul OC
347 535 1.5 sub moveto
1.0 setgray 329 498 3.29 rscale mul FC
0.0 setgray 329 498 3.29 rscale mul OC
329 498 1.5 sub moveto
1.0 setgray 370 530 1.95 rscale mul FC
0.0 setgray 370 530 1.95 rscale mul OC
370 530 1.5 sub moveto
1.0 setgray 392 522 2.39 rscale mul FC
0.0 setgray 392 522 2.39 rscale mul OC
392 522 1.5 sub moveto
1.0 setgray 367 488 2.65 rscale mul FC
0.0 setgray 367 488 2.65 rscale mul OC
367 488 1.5 sub moveto
1.0 setgray 339 455 6.26 rscale mul FC
0.0 setgray 339 455 6.26 rscale mul OC
339 455 1.5 sub moveto
1.0 setgray 413 512 1.95 rscale mul FC
0.0 setgray 413 512 1.95 rscale mul OC
413 512 1.5 sub moveto
1.0 setgray 433 500 2.39 rscale mul FC
0.0 setgray 433 500 2.39 rscale mul OC
433 500 1.5 sub moveto
1.0 setgray 403 472 2.65 rscale mul FC
0.0 setgray 403 472 2.65 rscale mul OC
403 472 1.5 sub moveto
1.0 setgray 452 486 1.6 rscale mul FC
0.0 setgray 452 486 1.6 rscale mul OC
452 486 1.5 sub moveto
1.0 setgray 470 470 1.95 rscale mul FC
0.0 setgray 470 470 1.95 rscale mul OC
470 470 1.5 sub moveto
1.0 setgray 434 448 2.11 rscale mul FC
0.0 setgray 434 448 2.11 rscale mul OC
434 448 1.5 sub moveto
1.0 setgray 395 429 4.89 rscale mul FC
0.0 setgray 395 429 4.89 rscale mul OC
395 429 1.5 sub moveto
1.0 setgray 351 408 11 rscale mul FC
0.0 setgray 351 408 11 rscale mul OC
351 408 1.5 sub moveto
1.0 setgray 486 452 2.93 rscale mul FC
0.0 setgray 486 452 2.93 rscale mul OC
486 452 1.5 sub moveto
1.0 setgray 500 433 2.39 rscale mul FC
0.0 setgray 500 433 2.39 rscale mul OC
500 433 1.5 sub moveto
1.0 setgray 461 419 3.29 rscale mul FC
0.0 setgray 461 419 3.29 rscale mul OC
461 419 1.5 sub moveto
1.0 setgray 512 413 2.39 rscale mul FC
0.0 setgray 512 413 2.39 rscale mul OC
512 413 1.5 sub moveto
1.0 setgray 522 392 1.95 rscale mul FC
0.0 setgray 522 392 1.95 rscale mul OC
522 392 1.5 sub moveto
1.0 setgray 481 386 2.65 rscale mul FC
0.0 setgray 481 386 2.65 rscale mul OC
481 386 1.5 sub moveto
1.0 setgray 437 382 6.26 rscale mul FC
0.0 setgray 437 382 6.26 rscale mul OC
437 382 1.5 sub moveto
1.0 setgray 530 370 2.39 rscale mul FC
0.0 setgray 530 370 2.39 rscale mul OC
530 370 1.5 sub moveto
1.0 setgray 535 347 1.95 rscale mul FC
0.0 setgray 535 347 1.95 rscale mul OC
535 347 1.5 sub moveto
1.0 setgray 494 349 2.65 rscale mul FC
0.0 setgray 494 349 2.65 rscale mul OC
494 349 1.5 sub moveto
1.0 setgray 539 324 1.95 rscale mul FC
0.0 setgray 539 324 1.95 rscale mul OC
539 324 1.5 sub moveto
1.0 setgray 540 300 1.6 rscale mul FC
0.0 setgray 540 300 1.6 rscale mul OC
540 300 1.5 sub moveto
1.0 setgray 500 310 2.11 rscale mul FC
0.0 setgray 500 310 2.11 rscale mul OC
500 310 1.5 sub moveto
1.0 setgray 458 323 4.89 rscale mul FC
0.0 setgray 458 323 4.89 rscale mul OC
458 323 1.5 sub moveto
1.0 setgray 413 340 11 rscale mul FC
0.0 setgray 413 340 11 rscale mul OC
413 340 1.5 sub moveto
1.0 setgray 359 354 12.4 rscale mul FC
0.0 setgray 359 354 12.4 rscale mul OC
359 354 1.5 sub moveto
1.0 setgray 302 340 20 rscale mul FC
0.0 setgray 302 340 20 rscale mul OC
302 340 1.5 sub moveto
1.0 setgray 300 300 19.7 rscale mul FC
0.0 setgray 300 300 19.7 rscale mul OC
300 300 1.5 sub moveto
grestore
60 60 480 480 rectstroke
showpage mul OC
233 112 1.5 sub moveto
1.0 setgray 261 145 4.89 rscale mul FC
0.0 setgray 261 145 4.89 rscETree/doc/GRD7x7x7_forwops.eps 0100644 0002055 0007177 00000042664 06652461101 0017410 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 50 50 550 550
/CSH {
%
% center show a string
%
% stack
% string str
%
dup stringwidth pop 2 div neg 0 rmoveto
show
} def
/ML {
%
% moveto lineto
%
% stack
% x0 y0 x1 y1
%
moveto lineto
} def
/FC {
%
% draw filled circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc fill
} def
/OC {
%
% draw open circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc stroke
} def
/rscale 0.128 def
/fontscale 6.000 def
60 60 480 480 rectclip
newpath
539 276 498 271 ML
535 253 498 271 ML
498 271 455 261 ML
530 230 488 233 ML
522 208 488 233 ML
488 233 455 261 ML
455 261 408 249 ML
512 187 472 197 ML
500 167 472 197 ML
472 197 429 205 ML
486 148 448 166 ML
470 130 448 166 ML
448 166 429 205 ML
429 205 408 249 ML
408 249 354 241 ML
452 114 419 139 ML
433 100 419 139 ML
419 139 382 163 ML
413 88.3 386 119 ML
392 78.3 386 119 ML
386 119 382 163 ML
382 163 340 187 ML
370 70.3 349 106 ML
347 64.6 349 106 ML
349 106 323 142 ML
324 61.2 310 100 ML
300 60 310 100 ML
310 100 323 142 ML
323 142 340 187 ML
340 187 354 241 ML
354 241 298 260 ML
276 61.2 271 102 ML
253 64.6 271 102 ML
271 102 261 145 ML
230 70.3 233 112 ML
208 78.3 233 112 ML
233 112 261 145 ML
261 145 249 192 ML
187 88.3 197 128 ML
167 100 197 128 ML
197 128 205 171 ML
148 114 166 152 ML
130 130 166 152 ML
166 152 205 171 ML
205 171 249 192 ML
249 192 241 246 ML
114 148 139 181 ML
100 167 139 181 ML
139 181 163 218 ML
88.3 187 119 214 ML
78.3 208 119 214 ML
119 214 163 218 ML
163 218 187 260 ML
70.3 230 106 251 ML
64.6 253 106 251 ML
106 251 142 277 ML
61.2 276 100 290 ML
60 300 100 290 ML
100 290 142 277 ML
142 277 187 260 ML
187 260 241 246 ML
241 246 298 260 ML
298 260 300 300 ML
61.2 324 102 329 ML
64.6 347 102 329 ML
102 329 145 339 ML
70.3 370 112 367 ML
78.3 392 112 367 ML
112 367 145 339 ML
145 339 192 351 ML
88.3 413 128 403 ML
100 433 128 403 ML
128 403 171 395 ML
114 452 152 434 ML
130 470 152 434 ML
152 434 171 395 ML
171 395 192 351 ML
192 351 246 359 ML
148 486 181 461 ML
167 500 181 461 ML
181 461 218 437 ML
187 512 214 481 ML
208 522 214 481 ML
214 481 218 437 ML
218 437 260 413 ML
230 530 251 494 ML
253 535 251 494 ML
251 494 277 458 ML
276 539 290 500 ML
300 540 290 500 ML
290 500 277 458 ML
277 458 260 413 ML
260 413 246 359 ML
246 359 302 340 ML
324 539 329 498 ML
347 535 329 498 ML
329 498 339 455 ML
370 530 367 488 ML
392 522 367 488 ML
367 488 339 455 ML
stroke
newpath
339 455 351 408 ML
413 512 403 472 ML
433 500 403 472 ML
403 472 395 429 ML
452 486 434 448 ML
470 470 434 448 ML
434 448 395 429 ML
395 429 351 408 ML
351 408 359 354 ML
486 452 461 419 ML
500 433 461 419 ML
461 419 437 382 ML
512 413 481 386 ML
522 392 481 386 ML
481 386 437 382 ML
437 382 413 340 ML
530 370 494 349 ML
535 347 494 349 ML
494 349 458 323 ML
539 324 500 310 ML
540 300 500 310 ML
500 310 458 323 ML
458 323 413 340 ML
413 340 359 354 ML
359 354 302 340 ML
302 340 300 300 ML
stroke
gsave
1.0 setgray 539 276 4.51 rscale mul FC
0.0 setgray 539 276 4.51 rscale mul OC
539 276 1.5 sub moveto
1.0 setgray 535 253 6.77 rscale mul FC
0.0 setgray 535 253 6.77 rscale mul OC
535 253 1.5 sub moveto
1.0 setgray 498 271 7.9 rscale mul FC
0.0 setgray 498 271 7.9 rscale mul OC
498 271 1.5 sub moveto
1.0 setgray 530 230 6.77 rscale mul FC
0.0 setgray 530 230 6.77 rscale mul OC
530 230 1.5 sub moveto
1.0 setgray 522 208 10.2 rscale mul FC
0.0 setgray 522 208 10.2 rscale mul OC
522 208 1.5 sub moveto
1.0 setgray 488 233 12.4 rscale mul FC
0.0 setgray 488 233 12.4 rscale mul OC
488 233 1.5 sub moveto
1.0 setgray 455 261 24.4 rscale mul FC
0.0 setgray 455 261 24.4 rscale mul OC
455 261 1.5 sub moveto
1.0 setgray 512 187 6.77 rscale mul FC
0.0 setgray 512 187 6.77 rscale mul OC
512 187 1.5 sub moveto
1.0 setgray 500 167 10.2 rscale mul FC
0.0 setgray 500 167 10.2 rscale mul OC
500 167 1.5 sub moveto
1.0 setgray 472 197 12.4 rscale mul FC
0.0 setgray 472 197 12.4 rscale mul OC
472 197 1.5 sub moveto
1.0 setgray 486 148 10.2 rscale mul FC
0.0 setgray 486 148 10.2 rscale mul OC
486 148 1.5 sub moveto
1.0 setgray 470 130 15.2 rscale mul FC
0.0 setgray 470 130 15.2 rscale mul OC
470 130 1.5 sub moveto
1.0 setgray 448 166 19.2 rscale mul FC
0.0 setgray 448 166 19.2 rscale mul OC
448 166 1.5 sub moveto
1.0 setgray 429 205 40.1 rscale mul FC
0.0 setgray 429 205 40.1 rscale mul OC
429 205 1.5 sub moveto
1.0 setgray 408 249 71.2 rscale mul FC
0.0 setgray 408 249 71.2 rscale mul OC
408 249 1.5 sub moveto
1.0 setgray 452 114 6.77 rscale mul FC
0.0 setgray 452 114 6.77 rscale mul OC
452 114 1.5 sub moveto
1.0 setgray 433 100 4.51 rscale mul FC
0.0 setgray 433 100 4.51 rscale mul OC
433 100 1.5 sub moveto
1.0 setgray 419 139 7.9 rscale mul FC
0.0 setgray 419 139 7.9 rscale mul OC
419 139 1.5 sub moveto
1.0 setgray 413 88.3 10.2 rscale mul FC
0.0 setgray 413 88.3 10.2 rscale mul OC
413 88.3 1.5 sub moveto
1.0 setgray 392 78.3 6.77 rscale mul FC
0.0 setgray 392 78.3 6.77 rscale mul OC
392 78.3 1.5 sub moveto
1.0 setgray 386 119 12.4 rscale mul FC
0.0 setgray 386 119 12.4 rscale mul OC
386 119 1.5 sub moveto
1.0 setgray 382 163 24.4 rscale mul FC
0.0 setgray 382 163 24.4 rscale mul OC
382 163 1.5 sub moveto
1.0 setgray 370 70.3 10.2 rscale mul FC
0.0 setgray 370 70.3 10.2 rscale mul OC
370 70.3 1.5 sub moveto
1.0 setgray 347 64.6 6.77 rscale mul FC
0.0 setgray 347 64.6 6.77 rscale mul OC
347 64.6 1.5 sub moveto
1.0 setgray 349 106 12.4 rscale mul FC
0.0 setgray 349 106 12.4 rscale mul OC
349 106 1.5 sub moveto
1.0 setgray 324 61.2 15.2 rscale mul FC
0.0 setgray 324 61.2 15.2 rscale mul OC
324 61.2 1.5 sub moveto
1.0 setgray 300 60 10.2 rscale mul FC
0.0 setgray 300 60 10.2 rscale mul OC
300 60 1.5 sub moveto
1.0 setgray 310 100 19.2 rscale mul FC
0.0 setgray 310 100 19.2 rscale mul OC
310 100 1.5 sub moveto
1.0 setgray 323 142 40.1 rscale mul FC
0.0 setgray 323 142 40.1 rscale mul OC
323 142 1.5 sub moveto
1.0 setgray 340 187 71.2 rscale mul FC
0.0 setgray 340 187 71.2 rscale mul OC
340 187 1.5 sub moveto
1.0 setgray 354 241 91.5 rscale mul FC
0.0 setgray 354 241 91.5 rscale mul OC
354 241 1.5 sub moveto
1.0 setgray 276 61.2 6.77 rscale mul FC
0.0 setgray 276 61.2 6.77 rscale mul OC
276 61.2 1.5 sub moveto
1.0 setgray 253 64.6 10.2 rscale mul FC
0.0 setgray 253 64.6 10.2 rscale mul OC
253 64.6 1.5 sub moveto
1.0 setgray 271 102 12.4 rscale mul FC
0.0 setgray 271 102 12.4 rscale mul OC
271 102 1.5 sub moveto
1.0 setgray 230 70.3 4.51 rscale mul FC
0.0 setgray 230 70.3 4.51 rscale mul OC
230 70.3 1.5 sub moveto
1.0 setgray 208 78.3 6.77 rscale mul FC
0.0 setgray 208 78.3 6.77 rscale mul OC
208 78.3 1.5 sub moveto
1.0 setgray 233 112 7.9 rscale mul FC
0.0 setgray 233 112 7.9 rscale mul OC
233 112 1.5 sub moveto
1.0 setgray 261 145 24.4 rscale mul FC
0.0 setgray 261 145 24.4 rscale mul OC
261 145 1.5 sub moveto
1.0 setgray 187 88.3 10.2 rscale mul FC
0.0 setgray 187 88.3 10.2 rscale mul OC
187 88.3 1.5 sub moveto
1.0 setgray 167 100 15.2 rscale mul FC
0.0 setgray 167 100 15.2 rscale mul OC
167 100 1.5 sub moveto
1.0 setgray 197 128 19.2 rscale mul FC
0.0 setgray 197 128 19.2 rscale mul OC
197 128 1.5 sub moveto
1.0 setgray 148 114 6.77 rscale mul FC
0.0 setgray 148 114 6.77 rscale mul OC
148 114 1.5 sub moveto
1.0 setgray 130 130 10.2 rscale mul FC
0.0 setgray 130 130 10.2 rscale mul OC
130 130 1.5 sub moveto
1.0 setgray 166 152 12.4 rscale mul FC
0.0 setgray 166 152 12.4 rscale mul OC
166 152 1.5 sub moveto
1.0 setgray 205 171 40.1 rscale mul FC
0.0 setgray 205 171 40.1 rscale mul OC
205 171 1.5 sub moveto
1.0 setgray 249 192 71.2 rscale mul FC
0.0 setgray 249 192 71.2 rscale mul OC
249 192 1.5 sub moveto
1.0 setgray 114 148 10.2 rscale mul FC
0.0 setgray 114 148 10.2 rscale mul OC
114 148 1.5 sub moveto
1.0 setgray 100 167 6.77 rscale mul FC
0.0 setgray 100 167 6.77 rscale mul OC
100 167 1.5 sub moveto
1.0 setgray 139 181 12.4 rscale mul FC
0.0 setgray 139 181 12.4 rscale mul OC
139 181 1.5 sub moveto
1.0 setgray 88.3 187 6.77 rscale mul FC
0.0 setgray 88.3 187 6.77 rscale mul OC
88.3 187 1.5 sub moveto
1.0 setgray 78.3 208 4.51 rscale mul FC
0.0 setgray 78.3 208 4.51 rscale mul OC
78.3 208 1.5 sub moveto
1.0 setgray 119 214 7.9 rscale mul FC
0.0 setgray 119 214 7.9 rscale mul OC
119 214 1.5 sub moveto
1.0 setgray 163 218 24.4 rscale mul FC
0.0 setgray 163 218 24.4 rscale mul OC
163 218 1.5 sub moveto
1.0 setgray 70.3 230 15.2 rscale mul FC
0.0 setgray 70.3 230 15.2 rscale mul OC
70.3 230 1.5 sub moveto
1.0 setgray 64.6 253 10.2 rscale mul FC
0.0 setgray 64.6 253 10.2 rscale mul OC
64.6 253 1.5 sub moveto
1.0 setgray 106 251 19.2 rscale mul FC
0.0 setgray 106 251 19.2 rscale mul OC
106 251 1.5 sub moveto
1.0 setgray 61.2 276 10.2 rscale mul FC
0.0 setgray 61.2 276 10.2 rscale mul OC
61.2 276 1.5 sub moveto
1.0 setgray 60 300 6.77 rscale mul FC
0.0 setgray 60 300 6.77 rscale mul OC
60 300 1.5 sub moveto
1.0 setgray 100 290 12.4 rscale mul FC
0.0 setgray 100 290 12.4 rscale mul OC
100 290 1.5 sub moveto
1.0 setgray 142 277 40.1 rscale mul FC
0.0 setgray 142 277 40.1 rscale mul OC
142 277 1.5 sub moveto
1.0 setgray 187 260 71.2 rscale mul FC
0.0 setgray 187 260 71.2 rscale mul OC
187 260 1.5 sub moveto
1.0 setgray 241 246 91.5 rscale mul FC
0.0 setgray 241 246 91.5 rscale mul OC
241 246 1.5 sub moveto
1.0 setgray 298 260 156 rscale mul FC
0.0 setgray 298 260 156 rscale mul OC
298 260 1.5 sub moveto
1.0 setgray 61.2 324 6.77 rscale mul FC
0.0 setgray 61.2 324 6.77 rscale mul OC
61.2 324 1.5 sub moveto
1.0 setgray 64.6 347 10.2 rscale mul FC
0.0 setgray 64.6 347 10.2 rscale mul OC
64.6 347 1.5 sub moveto
1.0 setgray 102 329 12.4 rscale mul FC
0.0 setgray 102 329 12.4 rscale mul OC
102 329 1.5 sub moveto
1.0 setgray 70.3 370 10.2 rscale mul FC
0.0 setgray 70.3 370 10.2 rscale mul OC
70.3 370 1.5 sub moveto
1.0 setgray 78.3 392 15.2 rscale mul FC
0.0 setgray 78.3 392 15.2 rscale mul OC
78.3 392 1.5 sub moveto
1.0 setgray 112 367 19.2 rscale mul FC
0.0 setgray 112 367 19.2 rscale mul OC
112 367 1.5 sub moveto
1.0 setgray 145 339 40.1 rscale mul FC
0.0 setgray 145 339 40.1 rscale mul OC
145 339 1.5 sub moveto
1.0 setgray 88.3 413 4.51 rscale mul FC
0.0 setgray 88.3 413 4.51 rscale mul OC
88.3 413 1.5 sub moveto
1.0 setgray 100 433 6.77 rscale mul FC
0.0 setgray 100 433 6.77 rscale mul OC
100 433 1.5 sub moveto
1.0 setgray 128 403 7.9 rscale mul FC
0.0 setgray 128 403 7.9 rscale mul OC
128 403 1.5 sub moveto
1.0 setgray 114 452 6.77 rscale mul FC
0.0 setgray 114 452 6.77 rscale mul OC
114 452 1.5 sub moveto
1.0 setgray 130 470 10.2 rscale mul FC
0.0 setgray 130 470 10.2 rscale mul OC
130 470 1.5 sub moveto
1.0 setgray 152 434 12.4 rscale mul FC
0.0 setgray 152 434 12.4 rscale mul OC
152 434 1.5 sub moveto
1.0 setgray 171 395 24.4 rscale mul FC
0.0 setgray 171 395 24.4 rscale mul OC
171 395 1.5 sub moveto
1.0 setgray 192 351 71.2 rscale mul FC
0.0 setgray 192 351 71.2 rscale mul OC
192 351 1.5 sub moveto
1.0 setgray 148 486 10.2 rscale mul FC
0.0 setgray 148 486 10.2 rscale mul OC
148 486 1.5 sub moveto
1.0 setgray 167 500 6.77 rscale mul FC
0.0 setgray 167 500 6.77 rscale mul OC
167 500 1.5 sub moveto
1.0 setgray 181 461 12.4 rscale mul FC
0.0 setgray 181 461 12.4 rscale mul OC
181 461 1.5 sub moveto
1.0 setgray 187 512 15.2 rscale mul FC
0.0 setgray 187 512 15.2 rscale mul OC
187 512 1.5 sub moveto
1.0 setgray 208 522 10.2 rscale mul FC
0.0 setgray 208 522 10.2 rscale mul OC
208 522 1.5 sub moveto
1.0 setgray 214 481 19.2 rscale mul FC
0.0 setgray 214 481 19.2 rscale mul OC
214 481 1.5 sub moveto
1.0 setgray 218 437 40.1 rscale mul FC
0.0 setgray 218 437 40.1 rscale mul OC
218 437 1.5 sub moveto
1.0 setgray 230 530 6.77 rscale mul FC
0.0 setgray 230 530 6.77 rscale mul OC
230 530 1.5 sub moveto
1.0 setgray 253 535 4.51 rscale mul FC
0.0 setgray 253 535 4.51 rscale mul OC
253 535 1.5 sub moveto
1.0 setgray 251 494 7.9 rscale mul FC
0.0 setgray 251 494 7.9 rscale mul OC
251 494 1.5 sub moveto
1.0 setgray 276 539 10.2 rscale mul FC
0.0 setgray 276 539 10.2 rscale mul OC
276 539 1.5 sub moveto
1.0 setgray 300 540 6.77 rscale mul FC
0.0 setgray 300 540 6.77 rscale mul OC
300 540 1.5 sub moveto
1.0 setgray 290 500 12.4 rscale mul FC
0.0 setgray 290 500 12.4 rscale mul OC
290 500 1.5 sub moveto
1.0 setgray 277 458 24.4 rscale mul FC
0.0 setgray 277 458 24.4 rscale mul OC
277 458 1.5 sub moveto
1.0 setgray 260 413 71.2 rscale mul FC
0.0 setgray 260 413 71.2 rscale mul OC
260 413 1.5 sub moveto
1.0 setgray 246 359 91.5 rscale mul FC
0.0 setgray 246 359 91.5 rscale mul OC
246 359 1.5 sub moveto
1.0 setgray 324 539 10.2 rscale mul FC
0.0 setgray 324 539 10.2 rscale mul OC
324 539 1.5 sub moveto
1.0 setgray 347 535 15.2 rscale mul FC
0.0 setgray 347 535 15.2 rscale mul OC
347 535 1.5 sub moveto
1.0 setgray 329 498 19.2 rscale mul FC
0.0 setgray 329 498 19.2 rscale mul OC
329 498 1.5 sub moveto
1.0 setgray 370 530 6.77 rscale mul FC
0.0 setgray 370 530 6.77 rscale mul OC
370 530 1.5 sub moveto
1.0 setgray 392 522 10.2 rscale mul FC
0.0 setgray 392 522 10.2 rscale mul OC
392 522 1.5 sub moveto
1.0 setgray 367 488 12.4 rscale mul FC
0.0 setgray 367 488 12.4 rscale mul OC
367 488 1.5 sub moveto
1.0 setgray 339 455 40.1 rscale mul FC
0.0 setgray 339 455 40.1 rscale mul OC
339 455 1.5 sub moveto
1.0 setgray 413 512 6.77 rscale mul FC
0.0 setgray 413 512 6.77 rscale mul OC
413 512 1.5 sub moveto
1.0 setgray 433 500 10.2 rscale mul FC
0.0 setgray 433 500 10.2 rscale mul OC
433 500 1.5 sub moveto
1.0 setgray 403 472 12.4 rscale mul FC
0.0 setgray 403 472 12.4 rscale mul OC
403 472 1.5 sub moveto
1.0 setgray 452 486 4.51 rscale mul FC
0.0 setgray 452 486 4.51 rscale mul OC
452 486 1.5 sub moveto
1.0 setgray 470 470 6.77 rscale mul FC
0.0 setgray 470 470 6.77 rscale mul OC
470 470 1.5 sub moveto
1.0 setgray 434 448 7.9 rscale mul FC
0.0 setgray 434 448 7.9 rscale mul OC
434 448 1.5 sub moveto
1.0 setgray 395 429 24.4 rscale mul FC
0.0 setgray 395 429 24.4 rscale mul OC
395 429 1.5 sub moveto
1.0 setgray 351 408 71.2 rscale mul FC
0.0 setgray 351 408 71.2 rscale mul OC
351 408 1.5 sub moveto
1.0 setgray 486 452 15.2 rscale mul FC
0.0 setgray 486 452 15.2 rscale mul OC
486 452 1.5 sub moveto
1.0 setgray 500 433 10.2 rscale mul FC
0.0 setgray 500 433 10.2 rscale mul OC
500 433 1.5 sub moveto
1.0 setgray 461 419 19.2 rscale mul FC
0.0 setgray 461 419 19.2 rscale mul OC
461 419 1.5 sub moveto
1.0 setgray 512 413 10.2 rscale mul FC
0.0 setgray 512 413 10.2 rscale mul OC
512 413 1.5 sub moveto
1.0 setgray 522 392 6.77 rscale mul FC
0.0 setgray 522 392 6.77 rscale mul OC
522 392 1.5 sub moveto
1.0 setgray 481 386 12.4 rscale mul FC
0.0 setgray 481 386 12.4 rscale mul OC
481 386 1.5 sub moveto
1.0 setgray 437 382 40.1 rscale mul FC
0.0 setgray 437 382 40.1 rscale mul OC
437 382 1.5 sub moveto
1.0 setgray 530 370 10.2 rscale mul FC
0.0 setgray 530 370 10.2 rscale mul OC
530 370 1.5 sub moveto
1.0 setgray 535 347 6.77 rscale mul FC
0.0 setgray 535 347 6.77 rscale mul OC
535 347 1.5 sub moveto
1.0 setgray 494 349 12.4 rscale mul FC
0.0 setgray 494 349 12.4 rscale mul OC
494 349 1.5 sub moveto
1.0 setgray 539 324 6.77 rscale mul FC
0.0 setgray 539 324 6.77 rscale mul OC
539 324 1.5 sub moveto
1.0 setgray 540 300 4.51 rscale mul FC
0.0 setgray 540 300 4.51 rscale mul OC
540 300 1.5 sub moveto
1.0 setgray 500 310 7.9 rscale mul FC
0.0 setgray 500 310 7.9 rscale mul OC
500 310 1.5 sub moveto
1.0 setgray 458 323 24.4 rscale mul FC
0.0 setgray 458 323 24.4 rscale mul OC
458 323 1.5 sub moveto
1.0 setgray 413 340 71.2 rscale mul FC
0.0 setgray 413 340 71.2 rscale mul OC
413 340 1.5 sub moveto
1.0 setgray 359 354 91.5 rscale mul FC
0.0 setgray 359 354 91.5 rscale mul OC
359 354 1.5 sub moveto
1.0 setgray 302 340 156 rscale mul FC
0.0 setgray 302 340 156 rscale mul OC
302 340 1.5 sub moveto
1.0 setgray 300 300 113 rscale mul FC
0.0 setgray 300 300 113 rscale mul OC
300 300 1.5 sub moveto
grestore
60 60 480 480 rectstroke
showpage moveto
1.0 setgray 261 145 24.4 rscale mul FC
0.0 setgray 261 145 ETree/doc/GRD7x7x7_backops.eps 0100644 0002055 0007177 00000042664 06652461133 0017340 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 50 50 550 550
/CSH {
%
% center show a string
%
% stack
% string str
%
dup stringwidth pop 2 div neg 0 rmoveto
show
} def
/ML {
%
% moveto lineto
%
% stack
% x0 y0 x1 y1
%
moveto lineto
} def
/FC {
%
% draw filled circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc fill
} def
/OC {
%
% draw open circle
%
% stack
% x y r
%
newpath 2 index 1 index add 2 index moveto 0 360 arc stroke
} def
/rscale 0.079 def
/fontscale 6.000 def
60 60 480 480 rectclip
newpath
539 276 498 271 ML
535 253 498 271 ML
498 271 455 261 ML
530 230 488 233 ML
522 208 488 233 ML
488 233 455 261 ML
455 261 408 249 ML
512 187 472 197 ML
500 167 472 197 ML
472 197 429 205 ML
486 148 448 166 ML
470 130 448 166 ML
448 166 429 205 ML
429 205 408 249 ML
408 249 354 241 ML
452 114 419 139 ML
433 100 419 139 ML
419 139 382 163 ML
413 88.3 386 119 ML
392 78.3 386 119 ML
386 119 382 163 ML
382 163 340 187 ML
370 70.3 349 106 ML
347 64.6 349 106 ML
349 106 323 142 ML
324 61.2 310 100 ML
300 60 310 100 ML
310 100 323 142 ML
323 142 340 187 ML
340 187 354 241 ML
354 241 298 260 ML
276 61.2 271 102 ML
253 64.6 271 102 ML
271 102 261 145 ML
230 70.3 233 112 ML
208 78.3 233 112 ML
233 112 261 145 ML
261 145 249 192 ML
187 88.3 197 128 ML
167 100 197 128 ML
197 128 205 171 ML
148 114 166 152 ML
130 130 166 152 ML
166 152 205 171 ML
205 171 249 192 ML
249 192 241 246 ML
114 148 139 181 ML
100 167 139 181 ML
139 181 163 218 ML
88.3 187 119 214 ML
78.3 208 119 214 ML
119 214 163 218 ML
163 218 187 260 ML
70.3 230 106 251 ML
64.6 253 106 251 ML
106 251 142 277 ML
61.2 276 100 290 ML
60 300 100 290 ML
100 290 142 277 ML
142 277 187 260 ML
187 260 241 246 ML
241 246 298 260 ML
298 260 300 300 ML
61.2 324 102 329 ML
64.6 347 102 329 ML
102 329 145 339 ML
70.3 370 112 367 ML
78.3 392 112 367 ML
112 367 145 339 ML
145 339 192 351 ML
88.3 413 128 403 ML
100 433 128 403 ML
128 403 171 395 ML
114 452 152 434 ML
130 470 152 434 ML
152 434 171 395 ML
171 395 192 351 ML
192 351 246 359 ML
148 486 181 461 ML
167 500 181 461 ML
181 461 218 437 ML
187 512 214 481 ML
208 522 214 481 ML
214 481 218 437 ML
218 437 260 413 ML
230 530 251 494 ML
253 535 251 494 ML
251 494 277 458 ML
276 539 290 500 ML
300 540 290 500 ML
290 500 277 458 ML
277 458 260 413 ML
260 413 246 359 ML
246 359 302 340 ML
324 539 329 498 ML
347 535 329 498 ML
329 498 339 455 ML
370 530 367 488 ML
392 522 367 488 ML
367 488 339 455 ML
stroke
newpath
339 455 351 408 ML
413 512 403 472 ML
433 500 403 472 ML
403 472 395 429 ML
452 486 434 448 ML
470 470 434 448 ML
434 448 395 429 ML
395 429 351 408 ML
351 408 359 354 ML
486 452 461 419 ML
500 433 461 419 ML
461 419 437 382 ML
512 413 481 386 ML
522 392 481 386 ML
481 386 437 382 ML
437 382 413 340 ML
530 370 494 349 ML
535 347 494 349 ML
494 349 458 323 ML
539 324 500 310 ML
540 300 500 310 ML
500 310 458 323 ML
458 323 413 340 ML
413 340 359 354 ML
359 354 302 340 ML
302 340 300 300 ML
stroke
gsave
1.0 setgray 539 276 1.6 rscale mul FC
0.0 setgray 539 276 1.6 rscale mul OC
539 276 1.5 sub moveto
1.0 setgray 535 253 1.95 rscale mul FC
0.0 setgray 535 253 1.95 rscale mul OC
535 253 1.5 sub moveto
1.0 setgray 498 271 3.99 rscale mul FC
0.0 setgray 498 271 3.99 rscale mul OC
498 271 1.5 sub moveto
1.0 setgray 530 230 1.95 rscale mul FC
0.0 setgray 530 230 1.95 rscale mul OC
530 230 1.5 sub moveto
1.0 setgray 522 208 2.39 rscale mul FC
0.0 setgray 522 208 2.39 rscale mul OC
522 208 1.5 sub moveto
1.0 setgray 488 233 4.98 rscale mul FC
0.0 setgray 488 233 4.98 rscale mul OC
488 233 1.5 sub moveto
1.0 setgray 455 261 13.5 rscale mul FC
0.0 setgray 455 261 13.5 rscale mul OC
455 261 1.5 sub moveto
1.0 setgray 512 187 1.95 rscale mul FC
0.0 setgray 512 187 1.95 rscale mul OC
512 187 1.5 sub moveto
1.0 setgray 500 167 2.39 rscale mul FC
0.0 setgray 500 167 2.39 rscale mul OC
500 167 1.5 sub moveto
1.0 setgray 472 197 4.98 rscale mul FC
0.0 setgray 472 197 4.98 rscale mul OC
472 197 1.5 sub moveto
1.0 setgray 486 148 2.39 rscale mul FC
0.0 setgray 486 148 2.39 rscale mul OC
486 148 1.5 sub moveto
1.0 setgray 470 130 2.93 rscale mul FC
0.0 setgray 470 130 2.93 rscale mul OC
470 130 1.5 sub moveto
1.0 setgray 448 166 6.18 rscale mul FC
0.0 setgray 448 166 6.18 rscale mul OC
448 166 1.5 sub moveto
1.0 setgray 429 205 17.3 rscale mul FC
0.0 setgray 429 205 17.3 rscale mul OC
429 205 1.5 sub moveto
1.0 setgray 408 249 49.3 rscale mul FC
0.0 setgray 408 249 49.3 rscale mul OC
408 249 1.5 sub moveto
1.0 setgray 452 114 1.95 rscale mul FC
0.0 setgray 452 114 1.95 rscale mul OC
452 114 1.5 sub moveto
1.0 setgray 433 100 1.6 rscale mul FC
0.0 setgray 433 100 1.6 rscale mul OC
433 100 1.5 sub moveto
1.0 setgray 419 139 3.99 rscale mul FC
0.0 setgray 419 139 3.99 rscale mul OC
419 139 1.5 sub moveto
1.0 setgray 413 88.3 2.39 rscale mul FC
0.0 setgray 413 88.3 2.39 rscale mul OC
413 88.3 1.5 sub moveto
1.0 setgray 392 78.3 1.95 rscale mul FC
0.0 setgray 392 78.3 1.95 rscale mul OC
392 78.3 1.5 sub moveto
1.0 setgray 386 119 4.98 rscale mul FC
0.0 setgray 386 119 4.98 rscale mul OC
386 119 1.5 sub moveto
1.0 setgray 382 163 13.5 rscale mul FC
0.0 setgray 382 163 13.5 rscale mul OC
382 163 1.5 sub moveto
1.0 setgray 370 70.3 2.39 rscale mul FC
0.0 setgray 370 70.3 2.39 rscale mul OC
370 70.3 1.5 sub moveto
1.0 setgray 347 64.6 1.95 rscale mul FC
0.0 setgray 347 64.6 1.95 rscale mul OC
347 64.6 1.5 sub moveto
1.0 setgray 349 106 4.98 rscale mul FC
0.0 setgray 349 106 4.98 rscale mul OC
349 106 1.5 sub moveto
1.0 setgray 324 61.2 2.93 rscale mul FC
0.0 setgray 324 61.2 2.93 rscale mul OC
324 61.2 1.5 sub moveto
1.0 setgray 300 60 2.39 rscale mul FC
0.0 setgray 300 60 2.39 rscale mul OC
300 60 1.5 sub moveto
1.0 setgray 310 100 6.18 rscale mul FC
0.0 setgray 310 100 6.18 rscale mul OC
310 100 1.5 sub moveto
1.0 setgray 323 142 17.3 rscale mul FC
0.0 setgray 323 142 17.3 rscale mul OC
323 142 1.5 sub moveto
1.0 setgray 340 187 49.3 rscale mul FC
0.0 setgray 340 187 49.3 rscale mul OC
340 187 1.5 sub moveto
1.0 setgray 354 241 77.9 rscale mul FC
0.0 setgray 354 241 77.9 rscale mul OC
354 241 1.5 sub moveto
1.0 setgray 276 61.2 1.95 rscale mul FC
0.0 setgray 276 61.2 1.95 rscale mul OC
276 61.2 1.5 sub moveto
1.0 setgray 253 64.6 2.39 rscale mul FC
0.0 setgray 253 64.6 2.39 rscale mul OC
253 64.6 1.5 sub moveto
1.0 setgray 271 102 4.98 rscale mul FC
0.0 setgray 271 102 4.98 rscale mul OC
271 102 1.5 sub moveto
1.0 setgray 230 70.3 1.6 rscale mul FC
0.0 setgray 230 70.3 1.6 rscale mul OC
230 70.3 1.5 sub moveto
1.0 setgray 208 78.3 1.95 rscale mul FC
0.0 setgray 208 78.3 1.95 rscale mul OC
208 78.3 1.5 sub moveto
1.0 setgray 233 112 3.99 rscale mul FC
0.0 setgray 233 112 3.99 rscale mul OC
233 112 1.5 sub moveto
1.0 setgray 261 145 13.5 rscale mul FC
0.0 setgray 261 145 13.5 rscale mul OC
261 145 1.5 sub moveto
1.0 setgray 187 88.3 2.39 rscale mul FC
0.0 setgray 187 88.3 2.39 rscale mul OC
187 88.3 1.5 sub moveto
1.0 setgray 167 100 2.93 rscale mul FC
0.0 setgray 167 100 2.93 rscale mul OC
167 100 1.5 sub moveto
1.0 setgray 197 128 6.18 rscale mul FC
0.0 setgray 197 128 6.18 rscale mul OC
197 128 1.5 sub moveto
1.0 setgray 148 114 1.95 rscale mul FC
0.0 setgray 148 114 1.95 rscale mul OC
148 114 1.5 sub moveto
1.0 setgray 130 130 2.39 rscale mul FC
0.0 setgray 130 130 2.39 rscale mul OC
130 130 1.5 sub moveto
1.0 setgray 166 152 4.98 rscale mul FC
0.0 setgray 166 152 4.98 rscale mul OC
166 152 1.5 sub moveto
1.0 setgray 205 171 17.3 rscale mul FC
0.0 setgray 205 171 17.3 rscale mul OC
205 171 1.5 sub moveto
1.0 setgray 249 192 49.3 rscale mul FC
0.0 setgray 249 192 49.3 rscale mul OC
249 192 1.5 sub moveto
1.0 setgray 114 148 2.39 rscale mul FC
0.0 setgray 114 148 2.39 rscale mul OC
114 148 1.5 sub moveto
1.0 setgray 100 167 1.95 rscale mul FC
0.0 setgray 100 167 1.95 rscale mul OC
100 167 1.5 sub moveto
1.0 setgray 139 181 4.98 rscale mul FC
0.0 setgray 139 181 4.98 rscale mul OC
139 181 1.5 sub moveto
1.0 setgray 88.3 187 1.95 rscale mul FC
0.0 setgray 88.3 187 1.95 rscale mul OC
88.3 187 1.5 sub moveto
1.0 setgray 78.3 208 1.6 rscale mul FC
0.0 setgray 78.3 208 1.6 rscale mul OC
78.3 208 1.5 sub moveto
1.0 setgray 119 214 3.99 rscale mul FC
0.0 setgray 119 214 3.99 rscale mul OC
119 214 1.5 sub moveto
1.0 setgray 163 218 13.5 rscale mul FC
0.0 setgray 163 218 13.5 rscale mul OC
163 218 1.5 sub moveto
1.0 setgray 70.3 230 2.93 rscale mul FC
0.0 setgray 70.3 230 2.93 rscale mul OC
70.3 230 1.5 sub moveto
1.0 setgray 64.6 253 2.39 rscale mul FC
0.0 setgray 64.6 253 2.39 rscale mul OC
64.6 253 1.5 sub moveto
1.0 setgray 106 251 6.18 rscale mul FC
0.0 setgray 106 251 6.18 rscale mul OC
106 251 1.5 sub moveto
1.0 setgray 61.2 276 2.39 rscale mul FC
0.0 setgray 61.2 276 2.39 rscale mul OC
61.2 276 1.5 sub moveto
1.0 setgray 60 300 1.95 rscale mul FC
0.0 setgray 60 300 1.95 rscale mul OC
60 300 1.5 sub moveto
1.0 setgray 100 290 4.98 rscale mul FC
0.0 setgray 100 290 4.98 rscale mul OC
100 290 1.5 sub moveto
1.0 setgray 142 277 17.3 rscale mul FC
0.0 setgray 142 277 17.3 rscale mul OC
142 277 1.5 sub moveto
1.0 setgray 187 260 49.3 rscale mul FC
0.0 setgray 187 260 49.3 rscale mul OC
187 260 1.5 sub moveto
1.0 setgray 241 246 77.9 rscale mul FC
0.0 setgray 241 246 77.9 rscale mul OC
241 246 1.5 sub moveto
1.0 setgray 298 260 161 rscale mul FC
0.0 setgray 298 260 161 rscale mul OC
298 260 1.5 sub moveto
1.0 setgray 61.2 324 1.95 rscale mul FC
0.0 setgray 61.2 324 1.95 rscale mul OC
61.2 324 1.5 sub moveto
1.0 setgray 64.6 347 2.39 rscale mul FC
0.0 setgray 64.6 347 2.39 rscale mul OC
64.6 347 1.5 sub moveto
1.0 setgray 102 329 4.98 rscale mul FC
0.0 setgray 102 329 4.98 rscale mul OC
102 329 1.5 sub moveto
1.0 setgray 70.3 370 2.39 rscale mul FC
0.0 setgray 70.3 370 2.39 rscale mul OC
70.3 370 1.5 sub moveto
1.0 setgray 78.3 392 2.93 rscale mul FC
0.0 setgray 78.3 392 2.93 rscale mul OC
78.3 392 1.5 sub moveto
1.0 setgray 112 367 6.18 rscale mul FC
0.0 setgray 112 367 6.18 rscale mul OC
112 367 1.5 sub moveto
1.0 setgray 145 339 17.3 rscale mul FC
0.0 setgray 145 339 17.3 rscale mul OC
145 339 1.5 sub moveto
1.0 setgray 88.3 413 1.6 rscale mul FC
0.0 setgray 88.3 413 1.6 rscale mul OC
88.3 413 1.5 sub moveto
1.0 setgray 100 433 1.95 rscale mul FC
0.0 setgray 100 433 1.95 rscale mul OC
100 433 1.5 sub moveto
1.0 setgray 128 403 3.99 rscale mul FC
0.0 setgray 128 403 3.99 rscale mul OC
128 403 1.5 sub moveto
1.0 setgray 114 452 1.95 rscale mul FC
0.0 setgray 114 452 1.95 rscale mul OC
114 452 1.5 sub moveto
1.0 setgray 130 470 2.39 rscale mul FC
0.0 setgray 130 470 2.39 rscale mul OC
130 470 1.5 sub moveto
1.0 setgray 152 434 4.98 rscale mul FC
0.0 setgray 152 434 4.98 rscale mul OC
152 434 1.5 sub moveto
1.0 setgray 171 395 13.5 rscale mul FC
0.0 setgray 171 395 13.5 rscale mul OC
171 395 1.5 sub moveto
1.0 setgray 192 351 49.3 rscale mul FC
0.0 setgray 192 351 49.3 rscale mul OC
192 351 1.5 sub moveto
1.0 setgray 148 486 2.39 rscale mul FC
0.0 setgray 148 486 2.39 rscale mul OC
148 486 1.5 sub moveto
1.0 setgray 167 500 1.95 rscale mul FC
0.0 setgray 167 500 1.95 rscale mul OC
167 500 1.5 sub moveto
1.0 setgray 181 461 4.98 rscale mul FC
0.0 setgray 181 461 4.98 rscale mul OC
181 461 1.5 sub moveto
1.0 setgray 187 512 2.93 rscale mul FC
0.0 setgray 187 512 2.93 rscale mul OC
187 512 1.5 sub moveto
1.0 setgray 208 522 2.39 rscale mul FC
0.0 setgray 208 522 2.39 rscale mul OC
208 522 1.5 sub moveto
1.0 setgray 214 481 6.18 rscale mul FC
0.0 setgray 214 481 6.18 rscale mul OC
214 481 1.5 sub moveto
1.0 setgray 218 437 17.3 rscale mul FC
0.0 setgray 218 437 17.3 rscale mul OC
218 437 1.5 sub moveto
1.0 setgray 230 530 1.95 rscale mul FC
0.0 setgray 230 530 1.95 rscale mul OC
230 530 1.5 sub moveto
1.0 setgray 253 535 1.6 rscale mul FC
0.0 setgray 253 535 1.6 rscale mul OC
253 535 1.5 sub moveto
1.0 setgray 251 494 3.99 rscale mul FC
0.0 setgray 251 494 3.99 rscale mul OC
251 494 1.5 sub moveto
1.0 setgray 276 539 2.39 rscale mul FC
0.0 setgray 276 539 2.39 rscale mul OC
276 539 1.5 sub moveto
1.0 setgray 300 540 1.95 rscale mul FC
0.0 setgray 300 540 1.95 rscale mul OC
300 540 1.5 sub moveto
1.0 setgray 290 500 4.98 rscale mul FC
0.0 setgray 290 500 4.98 rscale mul OC
290 500 1.5 sub moveto
1.0 setgray 277 458 13.5 rscale mul FC
0.0 setgray 277 458 13.5 rscale mul OC
277 458 1.5 sub moveto
1.0 setgray 260 413 49.3 rscale mul FC
0.0 setgray 260 413 49.3 rscale mul OC
260 413 1.5 sub moveto
1.0 setgray 246 359 77.9 rscale mul FC
0.0 setgray 246 359 77.9 rscale mul OC
246 359 1.5 sub moveto
1.0 setgray 324 539 2.39 rscale mul FC
0.0 setgray 324 539 2.39 rscale mul OC
324 539 1.5 sub moveto
1.0 setgray 347 535 2.93 rscale mul FC
0.0 setgray 347 535 2.93 rscale mul OC
347 535 1.5 sub moveto
1.0 setgray 329 498 6.18 rscale mul FC
0.0 setgray 329 498 6.18 rscale mul OC
329 498 1.5 sub moveto
1.0 setgray 370 530 1.95 rscale mul FC
0.0 setgray 370 530 1.95 rscale mul OC
370 530 1.5 sub moveto
1.0 setgray 392 522 2.39 rscale mul FC
0.0 setgray 392 522 2.39 rscale mul OC
392 522 1.5 sub moveto
1.0 setgray 367 488 4.98 rscale mul FC
0.0 setgray 367 488 4.98 rscale mul OC
367 488 1.5 sub moveto
1.0 setgray 339 455 17.3 rscale mul FC
0.0 setgray 339 455 17.3 rscale mul OC
339 455 1.5 sub moveto
1.0 setgray 413 512 1.95 rscale mul FC
0.0 setgray 413 512 1.95 rscale mul OC
413 512 1.5 sub moveto
1.0 setgray 433 500 2.39 rscale mul FC
0.0 setgray 433 500 2.39 rscale mul OC
433 500 1.5 sub moveto
1.0 setgray 403 472 4.98 rscale mul FC
0.0 setgray 403 472 4.98 rscale mul OC
403 472 1.5 sub moveto
1.0 setgray 452 486 1.6 rscale mul FC
0.0 setgray 452 486 1.6 rscale mul OC
452 486 1.5 sub moveto
1.0 setgray 470 470 1.95 rscale mul FC
0.0 setgray 470 470 1.95 rscale mul OC
470 470 1.5 sub moveto
1.0 setgray 434 448 3.99 rscale mul FC
0.0 setgray 434 448 3.99 rscale mul OC
434 448 1.5 sub moveto
1.0 setgray 395 429 13.5 rscale mul FC
0.0 setgray 395 429 13.5 rscale mul OC
395 429 1.5 sub moveto
1.0 setgray 351 408 49.3 rscale mul FC
0.0 setgray 351 408 49.3 rscale mul OC
351 408 1.5 sub moveto
1.0 setgray 486 452 2.93 rscale mul FC
0.0 setgray 486 452 2.93 rscale mul OC
486 452 1.5 sub moveto
1.0 setgray 500 433 2.39 rscale mul FC
0.0 setgray 500 433 2.39 rscale mul OC
500 433 1.5 sub moveto
1.0 setgray 461 419 6.18 rscale mul FC
0.0 setgray 461 419 6.18 rscale mul OC
461 419 1.5 sub moveto
1.0 setgray 512 413 2.39 rscale mul FC
0.0 setgray 512 413 2.39 rscale mul OC
512 413 1.5 sub moveto
1.0 setgray 522 392 1.95 rscale mul FC
0.0 setgray 522 392 1.95 rscale mul OC
522 392 1.5 sub moveto
1.0 setgray 481 386 4.98 rscale mul FC
0.0 setgray 481 386 4.98 rscale mul OC
481 386 1.5 sub moveto
1.0 setgray 437 382 17.3 rscale mul FC
0.0 setgray 437 382 17.3 rscale mul OC
437 382 1.5 sub moveto
1.0 setgray 530 370 2.39 rscale mul FC
0.0 setgray 530 370 2.39 rscale mul OC
530 370 1.5 sub moveto
1.0 setgray 535 347 1.95 rscale mul FC
0.0 setgray 535 347 1.95 rscale mul OC
535 347 1.5 sub moveto
1.0 setgray 494 349 4.98 rscale mul FC
0.0 setgray 494 349 4.98 rscale mul OC
494 349 1.5 sub moveto
1.0 setgray 539 324 1.95 rscale mul FC
0.0 setgray 539 324 1.95 rscale mul OC
539 324 1.5 sub moveto
1.0 setgray 540 300 1.6 rscale mul FC
0.0 setgray 540 300 1.6 rscale mul OC
540 300 1.5 sub moveto
1.0 setgray 500 310 3.99 rscale mul FC
0.0 setgray 500 310 3.99 rscale mul OC
500 310 1.5 sub moveto
1.0 setgray 458 323 13.5 rscale mul FC
0.0 setgray 458 323 13.5 rscale mul OC
458 323 1.5 sub moveto
1.0 setgray 413 340 49.3 rscale mul FC
0.0 setgray 413 340 49.3 rscale mul OC
413 340 1.5 sub moveto
1.0 setgray 359 354 77.9 rscale mul FC
0.0 setgray 359 354 77.9 rscale mul OC
359 354 1.5 sub moveto
1.0 setgray 302 340 161 rscale mul FC
0.0 setgray 302 340 161 rscale mul OC
302 340 1.5 sub moveto
1.0 setgray 300 300 254 rscale mul FC
0.0 setgray 300 300 254 rscale mul OC
300 300 1.5 sub moveto
grestore
60 60 480 480 rectstroke
showpage Eigen/Bridge.h 0100755 0002055 0007177 00000016264 06636254320 0014507 0 ustar 00cleve compmath 0000040 0000006 #include "../InpMtx.h"
#include "../Pencil.h"
#include "../ETree.h"
#include "../FrontMtx.h"
#include "../SymbFac.h"
#include "../misc.h"
/*
----------------------------------------------------------------
this object is the bridge between the lanczos and spooles codes.
NOTE: serial version
neqns -- number of equations
prbtype -- problem type
1 -- vibration, multiply with M or B
2 -- buckling, multiply with K or A
3 -- simple
mxbsz -- maximum block size
seed -- random number seed used in ordering
msglvl -- message level for SPOOLES programs
set msglvl = 0 for no output
set msglvl = 1 for scalar and timing output
set msglvl >= 2 for lots of output
msgFile -- message file for debug and diagnostic output
external objects, not free'd in the cleanup
A -- InpMtx object for the first matrix,
B -- InpMtx object for the second matrix
internal objects, free'd in cleanup
pencil -- Pencil object that contains A + sigma B
frontETree -- object that contains the front tree information
symbfacIVL -- object that contains the symbolic factorization
mtxmanager -- SubMtx manager object that handles storage
for the submatrices of the factors.
frontmtx -- object that contains the factorization
oldToNewIV -- object that contains the old-to-new permutation
newToOldIV -- object that contains the new-to-old permutation
X -- DenseMtx object used in the matrix multiply
and solves
Y -- DenseMtx object used in the matrix multiply
and solves
created -- 98aug10, jcp & cca
----------------------------------------------------------------
*/
typedef struct bridge_ {
int prbtype ;
int neqns ;
int mxbsz ;
InpMtx *A ;
InpMtx *B ;
Pencil *pencil ;
ETree *frontETree ;
IVL *symbfacIVL ;
SubMtxManager *mtxmanager ;
FrontMtx *frontmtx ;
IV *oldToNewIV ;
IV *newToOldIV ;
DenseMtx *X ;
DenseMtx *Y ;
int seed ;
int msglvl ;
FILE *msgFile ;
} Bridge ;
/*--------------------------------------------------------------------*/
#ifndef _TIMINGS_
#define _TIMINGS_
#include
static struct timeval TV ;
static struct timezone TZ ;
#define MARKTIME(t) \
gettimeofday(&TV, &TZ) ; \
t = (TV.tv_sec + 0.000001*TV.tv_usec)
#endif
/*--------------------------------------------------------------------*/
/*
------------------------------
prototypes for bridge routines
------------------------------
*/
/*
----------------------------------------------------------------
purpose --
given InpMtx objects that contain A and B, initialize the bridge
data structure for the serial factor's, solve's and mvm's.
data -- pointer to a Bridge object
pprbtype -- pointer to value containing problem type
*prbtype = 1 --> A X = B X Lambda, vibration problem
*prbtype = 2 --> A X = B X Lambda, buckling problem
*prbtype = 3 --> A X = X Lambda, simple eigenvalue problem
pneqns -- pointer to value containing number of equations
pmxbsz -- pointer to value containing blocksize
A -- pointer to InpMtx object containing A
B -- pointer to InpMtx object containing B
pseed -- pointer to value containing a random number seed
pmsglvl -- pointer to value containing a message level
msgFile -- message file pointer
return value --
1 -- normal return
-1 -- data is NULL
-2 -- pprbtype is NULL
-3 -- *pprbtype is invalid
-4 -- pneqns is NULL
-5 -- *pneqns is invalid
-6 -- pmxbsz is NULL
-7 -- *pmxbsz is invalid
-8 -- A and B are NULL
-9 -- pseed is NULL
-10 -- pmsglvl is NULL
-11 -- *pmsglvl > 0 and msgFile is NULL
created -- 98aug10, cca
----------------------------------------------------------------
*/
int
Setup (
void *data,
int *pprbtype,
int *pneqns,
int *pmxbsz,
InpMtx *A,
InpMtx *B,
int *pseed,
int *pmsglvl,
FILE *msgFile
) ;
/*
---------------------------------------------------------------------
purpose -- to compute the factorization of A - sigma * B
note: all variables in the calling sequence are references
to allow call from fortran.
input parameters
data -- pointer to bridge data object
psigma -- shift for the matrix pencil
ppvttol -- pivot tolerance
*ppvttol = 0.0 --> no pivoting used
*ppvttol != 0.0 --> pivoting used, entries in factor are
bounded above by 1/pvttol in magnitude
output parameters
*pinertia -- on return contains the number of negative eigenvalues
*perror -- on return contains an error code
1 -- error found during factorization
0 -- normal return
-1 -- psigma is NULL
-2 -- ppvttol is NULL
-3 -- data is NULL
-4 -- pinertia is NULL
created -- 98aug10, cca & jcp
---------------------------------------------------------------------
*/
void
Factor (
double *psigma,
double *ppvttol,
void *data,
int *pinertia,
int *perror
) ;
/*
-------------------------------------------------------------
purpose --- to compute a matrix-vector multiply y[] = C * x[]
where C is the identity, A or B (depending on *pprbtype).
*pnrows -- # of rows in x[]
*pncols -- # of columns in x[]
*pprbtype -- problem type
*pprbtype = 1 --> vibration problem, matrix is A
*pprbtype = 2 --> buckling problem, matrix is B
*pprbtype = 3 --> matrix is identity, y[] = x[]
created -- 98aug11, cca & jcp
-------------------------------------------------------------
*/
void
MatMul (
int *pnrows,
int *pncols,
double x[],
double y[],
int *pprbtype,
void *data
) ;
/*
----------------------------------------------
purpose -- to solve a linear system
(A - sigma*B) sol[] = rhs[]
data -- pointer to bridge data object
*pnrows -- # of rows in x[] and y[]
*pncols -- # of columns in x[] and y[]
rhs[] -- vector that holds right hand sides
sol[] -- vector to hold solutions
note: rhs[] and sol[] can be the same array.
on return, *perror holds an error code.
1 -- normal return
-1 -- pnrows is NULL
-2 -- pncols is NULL
-3 -- rhs is NULL
-4 -- sol is NULL
-5 -- data is NULL
created -- 98aug10, cca & jcp
----------------------------------------------
*/
void
Solve (
int *pnrows,
int *pncols,
double rhs[],
double sol[],
void *data,
int *perror
) ;
/*
--------------------------------------------
purpose -- to free the owned data structures
return values --
1 -- normal return
-1 -- data is NULL
created -- 98aug10, cca
--------------------------------------------
*/
int
Cleanup (
void *data
) ;
/*--------------------------------------------------------------------*/
Eigen/BridgeMPI.h 0100755 0002055 0007177 00000017605 06636772510 0015063 0 ustar 00cleve compmath 0000040 0000006 /* BridgeMPI.h */
/*
#include
*/
#include "../MPI.h"
#define LOCAL 1
#define GLOBAL 2
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
this object is the bridge between the lanczos and spooles codes.
NOTE: MPI version
neqns -- number of equations
prbtype -- problem type
1 -- vibration, multiply with M or B
2 -- buckling, multiply with K or A
3 -- simple
mxbsz -- maximum block size
nproc -- number of processes
myid -- id of this process
coordFlag -- coordinate flag
1 -- global coordinates for local matrix used in mvm
2 -- local coordinates for local matrix used in mvm
seed -- random number seed used in ordering
msglvl -- message level for SPOOLES programs
set msglvl = 0 for no output
set msglvl = 1 for scalar and timing output
set msglvl >= 2 for lots of output
msgFile -- message file for debug and diagnostic output
external objects, not free'd in the cleanup
A -- InpMtx object for the first matrix,
B -- InpMtx object for the second matrix
internal objects, free'd in cleanup
pencil -- Pencil object that contains A + sigma B
frontETree -- object that contains the front tree information
symbfacIVL -- object that contains the symbolic factorization
mtxmanager -- SubMtx manager object that handles storage
for the submatrices of the factors.
frontmtx -- object that contains the factorization
oldToNewIV -- object that contains the old-to-new permutation
newToOldIV -- object that contains the new-to-old permutation
vtxmapIV -- object that contains the map
from vertices to processes
myownedIV -- object that contains the vertices
owned by this processor
ownersIV -- object that contains the map
from fronts to processes
solvemap -- object that contains the map
from submatrices to processes
rowmapIV -- if pivoting was performed, this object holds
the map from rows of the factor to processors.
Xloc -- local matrix for X of Y = A*X
Yloc -- local matrix for Y of Y = A*X
info -- object for distributed matrix-matrix multiply
created -- 98aug10, jcp & cca
--------------------------------------------------------------------
*/
typedef struct bridgeMPI_ {
int neqns ;
int nproc ;
int myid ;
int prbtype ;
int mxbsz ;
int coordFlag ;
InpMtx *A ;
InpMtx *B ;
Pencil *pencil ;
ETree *frontETree ;
IVL *symbfacIVL ;
SubMtxManager *mtxmanager ;
FrontMtx *frontmtx ;
IV *oldToNewIV ;
IV *newToOldIV ;
IV *vtxmapIV ;
IV *myownedIV ;
IV *ownersIV ;
IV *rowmapIV ;
SolveMap *solvemap ;
MatMulInfo *info ;
DenseMtx *Xloc ;
DenseMtx *Yloc ;
int seed ;
int msglvl ;
FILE *msgFile ;
MPI_Comm comm ;
} BridgeMPI ;
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose --
given InpMtx objects that contain A and B, initialize the bridge
data structure for the MPI factor's, solve's and mvm's.
NOTE: all the input arguments are pointers
to allow calls from Fortran
data -- pointer to a Bridge object
pprbtype -- pointer to value containing problem type
*prbtype = 1 --> A X = B X Lambda, vibration problem
*prbtype = 2 --> A X = B X Lambda, buckling problem
*prbtype = 3 --> A X = X Lambda, simple eigenvalue problem
pneqns -- pointer to value containing number of equations
pmxbsz -- pointer to value containing blocksize
A -- pointer to InpMtx object containing A
B -- pointer to InpMtx object containing B
pseed -- pointer to value containing a random number seed
pmsglvl -- pointer to value containing a message level
msgFile -- message file pointer
return value --
1 -- normal return
-1 -- data is NULL
-2 -- pprbtype is NULL
-3 -- *pprbtype is invalid
-4 -- pneqns is NULL
-5 -- *pneqns is invalid
-6 -- pmxbsz is NULL
-7 -- *pmxbsz is invalid
-8 -- A and B are NULL
-9 -- pseed is NULL
-10 -- pmsglvl is NULL
-11 -- *pmsglvl > 0 and msgFile is NULL
-12 -- comm is NULL
created -- 98aug10, cca
----------------------------------------------------------------
*/
int
SetupMPI (
void *data,
int *pprbtype,
int *pneqns,
int *pmxbsz,
InpMtx *A,
InpMtx *B,
int *pseed,
int *pmsglvl,
FILE *msgFile,
MPI_Comm comm
) ;
/*
---------------------------------------------------------------------
purpose -- to compute the factorization of A - sigma * B
note: all variables in the calling sequence are references
to allow call from fortran.
input parameters
data -- pointer to bridge data object
psigma -- shift for the matrix pencil
ppvttol -- pivot tolerance
*ppvttol = 0.0 --> no pivoting used
*ppvttol != 0.0 --> pivoting used, entries in factor are
bounded above by 1/pvttol in magnitude
output parameters
*pinertia -- on return contains the number of negative eigenvalues
*perror -- on return contains an error code
1 -- error found during factorization
0 -- normal return
-1 -- psigma is NULL
-2 -- ppvttol is NULL
-3 -- data is NULL
-4 -- pinertia is NULL
created -- 98aug10, cca & jcp
---------------------------------------------------------------------
*/
void
FactorMPI (
double *psigma,
double *ppvttol,
void *data,
int *pinertia,
int *perror
) ;
/*
-------------------------------------------------------------
purpose --- to compute a matrix-vector multiply y[] = C * x[]
where C is the identity, A or B (depending on *pprbtype).
*pnrows -- # of rows in x[]
*pncols -- # of columns in x[]
*pprbtype -- problem type
*pprbtype = 1 --> vibration problem, matrix is A
*pprbtype = 2 --> buckling problem, matrix is B
*pprbtype = 3 --> matrix is identity, y[] = x[]
created -- 98aug11, cca & jcp
-------------------------------------------------------------
*/
void
MatMulMPI (
int *pnrows,
int *pncols,
double x[],
double y[],
int *pprbtype,
void *data
) ;
/*
----------------------------------------------
purpose -- to solve a linear system
(A - sigma*B) sol[] = rhs[]
data -- pointer to bridge data object
*pnrows -- # of rows in x[] and y[]
*pncols -- # of columns in x[] and y[]
rhs[] -- vector that holds right hand sides
sol[] -- vector to hold solutions
note: rhs[] and sol[] can be the same array.
on return, *perror holds an error code.
created -- 98aug10, cca & jcp
----------------------------------------------
*/
void
SolveMPI (
int *pnrows,
int *pncols,
double rhs[],
double sol[],
void *data,
int *perror
) ;
/*
--------------------------------------------
purpose -- to free the owned data structures
return values --
1 -- normal return
-1 -- data is NULL
created -- 98aug10, cca
--------------------------------------------
*/
int
CleanupMPI (
void *data
) ;
/*--------------------------------------------------------------------*/
Eigen/BridgeMT.h 0100755 0002055 0007177 00000016644 06636255347 0014764 0 ustar 00cleve compmath 0000040 0000006 #include "../InpMtx.h"
#include "../Pencil.h"
#include "../ETree.h"
#include "../FrontMtx.h"
#include "../SymbFac.h"
#include "../MT.h"
#include "../misc.h"
/*
--------------------------------------------------------------------
this object is the bridge between the lanczos and spooles codes.
NOTE: POSIX multithreaded version
neqns -- number of equations
prbtype -- problem type
1 -- vibration, multiply with M or B
2 -- buckling, multiply with K or A
3 -- simple
mxbsz -- maximum block size
nthread -- number of threads
seed -- random number seed used in ordering
msglvl -- message level for SPOOLES programs
set msglvl = 0 for no output
set msglvl = 1 for scalar and timing output
set msglvl >= 2 for lots of output
msgFile -- message file for debug and diagnostic output
external objects, not free'd in the cleanup
A -- InpMtx object for the first matrix,
B -- InpMtx object for the second matrix
internal objects, free'd in cleanup
pencil -- Pencil object that contains A + sigma B
frontETree -- object that contains the front tree information
symbfacIVL -- object that contains the symbolic factorization
mtxmanager -- SubMtx manager object that handles storage
for the submatrices of the factors.
frontmtx -- object that contains the factorization
oldToNewIV -- object that contains the old-to-new permutation
newToOldIV -- object that contains the new-to-old permutation
ownersIV -- object that contains the map from fronts to threads
solvemap -- object that contains the map
from submatrices to threads
created -- 98aug10, jcp & cca
--------------------------------------------------------------------
*/
typedef struct bridgeMT_ {
int prbtype ;
int neqns ;
int mxbsz ;
int nthread ;
InpMtx *A ;
InpMtx *B ;
Pencil *pencil ;
ETree *frontETree ;
IVL *symbfacIVL ;
SubMtxManager *mtxmanager ;
FrontMtx *frontmtx ;
IV *oldToNewIV ;
IV *newToOldIV ;
DenseMtx *X ;
DenseMtx *Y ;
IV *ownersIV ;
SolveMap *solvemap ;
int seed ;
int msglvl ;
FILE *msgFile ;
} BridgeMT ;
/*--------------------------------------------------------------------*/
#ifndef _TIMINGS_
#define _TIMINGS_
#include
static struct timeval TV ;
static struct timezone TZ ;
#define MARKTIME(t) \
gettimeofday(&TV, &TZ) ; \
t = (TV.tv_sec + 0.000001*TV.tv_usec)
#endif
/*--------------------------------------------------------------------*/
/*
------------------------------
prototypes for bridge routines
------------------------------
*/
/*
------------------------------------------------------------------
purpose --
given InpMtx objects that contain A and B, initialize the bridge
data structure for the multithreaded factor's, solve's and mvm's.
data -- pointer to a Bridge object
pprbtype -- pointer to value containing problem type
*prbtype = 1 --> A X = B X Lambda, vibration problem
*prbtype = 2 --> A X = B X Lambda, buckling problem
*prbtype = 3 --> A X = X Lambda, simple eigenvalue problem
pneqns -- pointer to value containing number of equations
pmxbsz -- pointer to value containing blocksize
A -- pointer to InpMtx object containing A
B -- pointer to InpMtx object containing B
pseed -- pointer to value containing a random number seed
pmsglvl -- pointer to value containing a message level
msgFile -- message file pointer
pnthread -- pointer to value containing # of threads
return value --
1 -- normal return
-1 -- data is NULL
-2 -- pprbtype is NULL
-3 -- *pprbtype is invalid
-4 -- pneqns is NULL
-5 -- *pneqns is invalid
-6 -- pmxbsz is NULL
-7 -- *pmxbsz is invalid
-8 -- A and B are NULL
-9 -- pseed is NULL
-10 -- pmsglvl is NULL
-11 -- *pmsglvl > 0 and msgFile is NULL
created -- 98aug10, cca
------------------------------------------------------------------
*/
int
SetupMT (
void *data,
int *pprbtype,
int *pneqns,
int *pmxbsz,
InpMtx *A,
InpMtx *B,
int *pseed,
int *pnthread,
int *pmsglvl,
FILE *msgFile
) ;
/*
---------------------------------------------------------------------
purpose -- to compute the factorization of A - sigma * B
note: all variables in the calling sequence are references
to allow call from fortran.
input parameters
data -- pointer to bridge data object
psigma -- shift for the matrix pencil
ppvttol -- pivot tolerance
*ppvttol = 0.0 --> no pivoting used
*ppvttol != 0.0 --> pivoting used, entries in factor are
bounded above by 1/pvttol in magnitude
output parameters
*pinertia -- on return contains the number of negative eigenvalues
*perror -- on return contains an error code
1 -- error found during factorization
0 -- normal return
-1 -- psigma is NULL
-2 -- ppvttol is NULL
-3 -- data is NULL
-4 -- pinertia is NULL
created -- 98aug10, cca & jcp
---------------------------------------------------------------------
*/
void
FactorMT (
double *psigma,
double *ppvttol,
void *data,
int *pinertia,
int *perror
) ;
/*
-------------------------------------------------------------
purpose --- to compute a matrix-vector multiply y[] = C * x[]
where C is the identity, A or B (depending on *pprbtype).
*pprbtype -- problem type
*pprbtype = 1 --> vibration problem, matrix is A
*pprbtype = 2 --> buckling problem, matrix is B
*pprbtype = 3 --> matrix is identity, y[] = x[]
*pnrows -- # of rows in x[]
*pncols -- # of columns in x[]
created -- 98aug11, cca & jcp
-------------------------------------------------------------
*/
void
MatMulMT (
int *pnrows,
int *pncols,
double x[],
double y[],
int *pprbtype,
void *data
) ;
/*
----------------------------------------------
purpose -- to solve a linear system
(A - sigma*B) sol[] = rhs[]
data -- pointer to bridge data object
*pnrows -- # of rows in x[] and y[]
*pncols -- # of columns in x[] and y[]
rhs[] -- vector that holds right hand sides
sol[] -- vector to hold solutions
note: rhs[] and sol[] can be the same array.
on return, *perror holds an error code.
1 -- normal return
-1 -- pnrows is NULL
-2 -- pncols is NULL
-3 -- rhs is NULL
-4 -- sol is NULL
-5 -- data is NULL
created -- 98aug10, cca & jcp
----------------------------------------------
*/
void
SolveMT (
int *pnrows,
int *pncols,
double rhs[],
double sol[],
void *data,
int *perror
) ;
/*
--------------------------------------------
purpose -- to free the owned data structures
return values --
1 -- normal return
-1 -- data is NULL
created -- 98aug10, cca
--------------------------------------------
*/
int
CleanupMT (
void *data
) ;
/*--------------------------------------------------------------------*/
containing number of equations
pmxbsz -- pointer to value containing blocksize
A Eigen/makefile 0100755 0002055 0007177 00000000423 06636776154 0014646 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make all_drivers
lib :
cd srcMPI ; make BridgeMPI.a
cd srcMT ; make BridgeMT.a
cd srcST ; make Bridge.a
clean :
cd srcMPI ; make clean
cd srcMT ; make clean
cd srcST ; make clean
cd drivers ; make clean
cd doc ; make clean
Eigen/srcST/makefile 0100644 0002055 0007177 00000000525 06636254303 0015667 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = Bridge
$(OBJ).a : \
$(OBJ).a(Cleanup.o) \
$(OBJ).a(Factor.o) \
$(OBJ).a(MatMul.o) \
$(OBJ).a(Setup.o) \
$(OBJ).a(Solve.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
Eigen/srcST/Cleanup.c 0100644 0002055 0007177 00000002711 06633561116 0015721 0 ustar 00cleve compmath 0000040 0000006 /* Cleanup.c */
#include "../Bridge.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Cleanup = 0 ;
static double time_Cleanup = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
purpose -- to free the owned data structures
return values --
1 -- normal return
-1 -- data is NULL
created -- 98aug10, cca
--------------------------------------------
*/
int
Cleanup (
void *data
) {
Bridge *bridge = (Bridge *) data ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Cleanup++ ;
fprintf(stdout, "\n (%d) Cleanup()", count_Cleanup) ;
fflush(stdout) ;
#endif
/*
---------------
check the input
---------------
*/
if ( data == NULL ) {
fprintf(stderr, "\n error in Cleanup()"
"\n data is NULL\n") ;
return(-1) ;
}
bridge->pencil->inpmtxA = NULL ;
bridge->pencil->inpmtxB = NULL ;
Pencil_free(bridge->pencil) ;
IVL_free(bridge->symbfacIVL) ;
FrontMtx_free(bridge->frontmtx) ;
ETree_free(bridge->frontETree) ;
SubMtxManager_free(bridge->mtxmanager) ;
IV_free(bridge->oldToNewIV) ;
IV_free(bridge->newToOldIV) ;
DenseMtx_free(bridge->X) ;
DenseMtx_free(bridge->Y) ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Cleanup += t2 - t1 ;
fprintf(stdout, ", %8.3f seconds, %8.3f total seconds, ",
t2 - t1, time_Cleanup) ;
fflush(stdout) ;
#endif
return(1) ; }
/*--------------------------------------------------------------------*/
Eigen/srcST/Factor.c 0100644 0002055 0007177 00000012452 06633557326 0015563 0 ustar 00cleve compmath 0000040 0000006 /* Factor.c */
#include "../Bridge.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Factor = 0 ;
static double time_Factor = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
purpose -- to compute the factorization of A - sigma * B
note: all variables in the calling sequence are references
to allow call from fortran.
input parameters
data -- pointer to bridge data object
psigma -- shift for the matrix pencil
ppvttol -- pivot tolerance
*ppvttol = 0.0 --> no pivoting used
*ppvttol != 0.0 --> pivoting used, entries in factor are
bounded above by 1/pvttol in magnitude
output parameters
*pinertia -- on return contains the number of negative eigenvalues
*perror -- on return contains an error code
1 -- error found during factorization
0 -- normal return
-1 -- psigma is NULL
-2 -- ppvttol is NULL
-3 -- data is NULL
-4 -- pinertia is NULL
created -- 98aug10, cca & jcp
---------------------------------------------------------------------
*/
void
Factor (
double *psigma,
double *ppvttol,
void *data,
int *pinertia,
int *perror
) {
Bridge *bridge = (Bridge *) data ;
Chv *rootchv ;
ChvManager *chvmanager ;
double droptol=0.0, tau ;
double cpus[10] ;
int stats[20] ;
int nnegative, nzero, npositive, pivotingflag ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Factor++ ;
fprintf(stdout, "\n (%d) Factor()", count_Factor) ;
fflush(stdout) ;
#endif
/*
---------------
check the input
---------------
*/
if ( psigma == NULL ) {
fprintf(stderr, "\n error in Factor()"
"\n psigma is NULL\n") ;
*perror = -1 ; return ;
}
if ( ppvttol == NULL ) {
fprintf(stderr, "\n error in Factor()"
"\n ppvttol is NULL\n") ;
*perror = -2 ; return ;
}
if ( data == NULL ) {
fprintf(stderr, "\n error in Factor()"
"\n data is NULL\n") ;
*perror = -3 ; return ;
}
if ( pinertia == NULL ) {
fprintf(stderr, "\n error in Factor()"
"\n pinertia is NULL\n") ;
*perror = -4 ; return ;
}
if ( perror == NULL ) {
fprintf(stderr, "\n error in Factor()"
"\n perror is NULL\n") ;
return ;
}
/*
----------------------------------
set the shift in the pencil object
----------------------------------
*/
bridge->pencil->sigma[0] = -(*psigma) ;
bridge->pencil->sigma[1] = 0.0 ;
/*
-----------------------------------------------------
clear the front matrix and submatrix mananger objects
-----------------------------------------------------
*/
FrontMtx_clearData(bridge->frontmtx);
SubMtxManager_clearData(bridge->mtxmanager);
/*
-----------------------------------------------------------
set the pivot tolerance.
NOTE: spooles's "tau" parameter is a bound on the magnitude
of the factor entries, and is the recipricol of that of the
pivot tolerance of the lanczos code
-----------------------------------------------------------
*/
if ( *ppvttol == 0.0 ) {
tau = 10.0 ;
pivotingflag = SPOOLES_NO_PIVOTING ;
} else {
tau = (1.0)/(*ppvttol) ;
pivotingflag = SPOOLES_PIVOTING ;
}
/*
----------------------------------
initialize the front matrix object
----------------------------------
*/
FrontMtx_init(bridge->frontmtx, bridge->frontETree, bridge->symbfacIVL,
SPOOLES_REAL, SPOOLES_SYMMETRIC, FRONTMTX_DENSE_FRONTS,
pivotingflag, NO_LOCK, 0, NULL, bridge->mtxmanager,
bridge->msglvl, bridge->msgFile) ;
/*
-------------------------
compute the factorization
-------------------------
*/
chvmanager = ChvManager_new() ;
ChvManager_init(chvmanager, NO_LOCK, 1);
IVfill(20, stats, 0) ;
DVfill(10, cpus, 0.0) ;
rootchv = FrontMtx_factorPencil(bridge->frontmtx, bridge->pencil, tau,
droptol, chvmanager, perror, cpus,
stats, bridge->msglvl, bridge->msgFile);
ChvManager_free(chvmanager);
/*
----------------------------
if matrix is singular then
set error flag and return
----------------------------
*/
if ( rootchv != NULL ) {
*perror = 1 ;
return ;
}
/*
------------------------------------------------------------------
post-process the factor matrix, convert from fronts to submatrices
------------------------------------------------------------------
*/
FrontMtx_postProcess(bridge->frontmtx, bridge->msglvl, bridge->msgFile);
/*
-------------------
compute the inertia
-------------------
*/
FrontMtx_inertia(bridge->frontmtx, &nnegative, &nzero, &npositive) ;
*pinertia = nnegative;
/*
------------------------------------------------------------------
set the error. (this is simple since when the spooles codes detect
a fatal error, they print out a message to stderr and exit.)
------------------------------------------------------------------
*/
*perror = 0 ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Factor += t2 - t1 ;
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Factor) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
Eigen/srcST/MatMul.c 0100644 0002055 0007177 00000005621 06636531742 0015541 0 ustar 00cleve compmath 0000040 0000006 /* MatMul.c */
#include "../Bridge.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_MatMul = 0 ;
static double time_MatMul = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
purpose --- to compute a matrix-vector multiply y[] = C * x[]
where C is the identity, A or B (depending on *pprbtype).
*pprbtype -- problem type
*pprbtype = 1 --> vibration problem, matrix is A
*pprbtype = 2 --> buckling problem, matrix is B
*pprbtype = 3 --> matrix is identity, y[] = x[]
*pnrows -- # of rows in x[]
*pncols -- # of columns in x[]
created -- 98aug11, cca & jcp
-------------------------------------------------------------
*/
void
MatMul (
int *pnrows,
int *pncols,
double x[],
double y[],
int *pprbtype,
void *data
) {
int ncols, nent, nrows ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_MatMul++ ;
fprintf(stdout, "\n (%d) MatMul()", count_MatMul) ;
fflush(stdout) ;
#endif
nrows = *pnrows ;
ncols = *pncols ;
nent = nrows*ncols ;
if ( *pprbtype == 3 ) {
/*
--------------------------
... matrix is the identity
--------------------------
*/
DVcopy(nent, y, x) ;
return;
} else {
Bridge *bridge = (Bridge *) data ;
DenseMtx *X, *Y ;
double alpha[2] = {1.0, 0.0} ;
/*
---------------------------------
setup x and y as DenseMtx objects
---------------------------------
*/
X = bridge->X ;
DenseMtx_init(X, SPOOLES_REAL, 0, 0, nrows, ncols, 1, nrows);
DVcopy (nent, DenseMtx_entries(X), x);
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile, "\n inside MatMul, X") ;
DenseMtx_writeForHumanEye(X, bridge->msgFile) ;
fflush(bridge->msgFile) ;
}
Y = bridge->Y ;
DenseMtx_init(Y, SPOOLES_REAL, 0, 0, nrows, ncols, 1, nrows);
DenseMtx_zero(Y);
if ( *pprbtype == 1 ) {
/*
---------------------------------------
... vibration case matrix is 'm' or 'b'
---------------------------------------
*/
InpMtx_sym_mmm(bridge->B, Y, alpha, X);
} else {
/*
--------------------------------------
... buckling case matrix is 'k' or 'a'
--------------------------------------
*/
InpMtx_sym_mmm(bridge->A, Y, alpha, X);
}
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile, "\n inside MatMul, Y") ;
DenseMtx_writeForHumanEye(Y, bridge->msgFile) ;
fflush(bridge->msgFile) ;
}
/*
--------------------------------
copy solution into output vector
--------------------------------
*/
DVcopy (nent, y, DenseMtx_entries(Y) );
}
#if MYDEBUG > 0
MARKTIME(t2) ;
time_MatMul += t2 - t1 ;
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_MatMul) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
Eigen/srcST/Setup.c 0100644 0002055 0007177 00000022207 06633557207 0015442 0 ustar 00cleve compmath 0000040 0000006 /* Setup.c */
#include "../Bridge.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Setup = 0 ;
static double time_Setup = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose --
given InpMtx objects that contain A and B, initialize the bridge
data structure for the serial factor's, solve's and mvm's.
data -- pointer to a Bridge object
pprbtype -- pointer to value containing problem type
*prbtype = 1 --> A X = B X Lambda, vibration problem
*prbtype = 2 --> A X = B X Lambda, buckling problem
*prbtype = 3 --> A X = X Lambda, simple eigenvalue problem
pneqns -- pointer to value containing number of equations
pmxbsz -- pointer to value containing blocksize
A -- pointer to InpMtx object containing A
B -- pointer to InpMtx object containing B
pseed -- pointer to value containing a random number seed
pmsglvl -- pointer to value containing a message level
msgFile -- message file pointer
return value --
1 -- normal return
-1 -- data is NULL
-2 -- pprbtype is NULL
-3 -- *pprbtype is invalid
-4 -- pneqns is NULL
-5 -- *pneqns is invalid
-6 -- pmxbsz is NULL
-7 -- *pmxbsz is invalid
-8 -- A and B are NULL
-9 -- pseed is NULL
-10 -- pmsglvl is NULL
-11 -- *pmsglvl > 0 and msgFile is NULL
created -- 98aug10, cca
----------------------------------------------------------------
*/
int
Setup (
void *data,
int *pprbtype,
int *pneqns,
int *pmxbsz,
InpMtx *A,
InpMtx *B,
int *pseed,
int *pmsglvl,
FILE *msgFile
) {
Bridge *bridge = (Bridge *) data ;
double sigma[2] ;
Graph *graph ;
int maxdomainsize, maxsize, maxzeros, msglvl, mxbsz,
nedges, neqns, prbtype, seed ;
IVL *adjIVL ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Setup++ ;
fprintf(stdout, "\n (%d) Setup()", count_Setup) ;
fflush(stdout) ;
#endif
/*
--------------------
check the input data
--------------------
*/
if ( data == NULL ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n data is NULL\n") ;
return(-1) ;
}
if ( pprbtype == NULL ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n prbtype is NULL\n") ;
return(-2) ;
}
prbtype = *pprbtype ;
if ( prbtype < 1 || prbtype > 3 ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n prbtype = %d, is invalid\n", prbtype) ;
return(-3) ;
}
if ( pneqns == NULL ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n pneqns is NULL\n") ;
return(-4) ;
}
neqns = *pneqns ;
if ( neqns <= 0 ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n neqns = %d, is invalid\n", neqns) ;
return(-5) ;
}
if ( pmxbsz == NULL ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n pmxbsz is NULL\n") ;
return(-6) ;
}
mxbsz = *pmxbsz ;
if ( mxbsz <= 0 ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n *pmxbsz = %d, is invalid\n", mxbsz) ;
return(-7) ;
}
if ( A == NULL && B == NULL ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n A and B are NULL\n") ;
return(-8) ;
}
if ( pseed == NULL ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n pseed is NULL\n") ;
return(-9) ;
}
seed = *pseed ;
if ( pmsglvl == NULL ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n pmsglvl is NULL\n") ;
return(-10) ;
}
msglvl = *pmsglvl ;
if ( msglvl > 0 && msgFile == NULL ) {
fprintf(stderr, "\n fatal error in Setup()"
"\n msglvl = %d, msgFile = NULL\n", msglvl) ;
return(-11) ;
}
bridge->msglvl = msglvl ;
bridge->msgFile = msgFile ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n inside Setup()"
"\n neqns = %d, prbtype = %d, mxbsz = %d, seed = %d",
neqns, prbtype, mxbsz, seed) ;
if ( A != NULL ) {
fprintf(msgFile, "\n\n matrix A") ;
InpMtx_writeForHumanEye(A, msgFile) ;
}
if ( B != NULL ) {
fprintf(msgFile, "\n\n matrix B") ;
InpMtx_writeForHumanEye(B, msgFile) ;
}
fflush(msgFile) ;
}
bridge->prbtype = prbtype ;
bridge->neqns = neqns ;
bridge->mxbsz = mxbsz ;
bridge->A = A ;
bridge->B = B ;
bridge->seed = seed ;
/*
----------------------------
create and initialize pencil
----------------------------
*/
sigma[0] = 1.0; sigma[1] = 0.0;
bridge->pencil = Pencil_new() ;
Pencil_setDefaultFields(bridge->pencil) ;
Pencil_init(bridge->pencil, SPOOLES_REAL, SPOOLES_SYMMETRIC,
A, sigma, B) ;
/*
--------------------------------
convert to row or column vectors
--------------------------------
*/
if ( A != NULL ) {
if ( ! INPMTX_IS_BY_ROWS(A) && ! INPMTX_IS_BY_COLUMNS(A) ) {
InpMtx_changeCoordType(A, INPMTX_BY_ROWS) ;
}
if ( ! INPMTX_IS_BY_VECTORS(A) ) {
InpMtx_changeStorageMode(A, INPMTX_BY_VECTORS) ;
}
}
if ( B != NULL ) {
if ( ! INPMTX_IS_BY_ROWS(B) && ! INPMTX_IS_BY_COLUMNS(B) ) {
InpMtx_changeCoordType(B, INPMTX_BY_ROWS) ;
}
if ( ! INPMTX_IS_BY_VECTORS(B) ) {
InpMtx_changeStorageMode(B, INPMTX_BY_VECTORS) ;
}
}
/*
-------------------------------
create a Graph object for A + B
-------------------------------
*/
graph = Graph_new() ;
adjIVL = Pencil_fullAdjacency(bridge->pencil) ;
nedges = IVL_tsize(adjIVL),
Graph_init2(graph, 0, bridge->neqns, 0, nedges,
bridge->neqns, nedges, adjIVL, NULL, NULL) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n graph of the input matrix") ;
Graph_writeForHumanEye(graph, msgFile) ;
fflush(msgFile) ;
}
/*
---------------
order the graph
---------------
*/
maxdomainsize = neqns / 64 ;
if ( maxdomainsize == 0 ) {
maxdomainsize = 1 ;
}
maxzeros = (int) (0.01*neqns) ;
maxsize = 64 ;
bridge->frontETree = orderViaBestOfNDandMS(graph, maxdomainsize,
maxzeros, maxsize, bridge->seed, msglvl, msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree from ordering") ;
ETree_writeForHumanEye(bridge->frontETree, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------------------
get the old-to-new and new-to-old permutations
----------------------------------------------
*/
bridge->oldToNewIV = ETree_oldToNewVtxPerm(bridge->frontETree) ;
bridge->newToOldIV = ETree_newToOldVtxPerm(bridge->frontETree) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n old-to-new permutation") ;
IV_writeForHumanEye(bridge->oldToNewIV, msgFile) ;
fprintf(msgFile, "\n\n new-to-old permutation") ;
IV_writeForHumanEye(bridge->newToOldIV, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------------------
permute the vertices in the front tree
--------------------------------------
*/
ETree_permuteVertices(bridge->frontETree, bridge->oldToNewIV) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n permuted front etree") ;
ETree_writeForHumanEye(bridge->frontETree, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------------------------
permute the entries in the pencil.
note, after the permutation the
entries are mapped into the upper triangle.
-------------------------------------------
*/
Pencil_permute(bridge->pencil, bridge->oldToNewIV, bridge->oldToNewIV) ;
Pencil_mapToUpperTriangle(bridge->pencil) ;
Pencil_changeCoordType(bridge->pencil, INPMTX_BY_CHEVRONS) ;
Pencil_changeStorageMode(bridge->pencil, INPMTX_BY_VECTORS) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n permuted pencil") ;
Pencil_writeForHumanEye(bridge->pencil, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------
compute the symbolic factorization
----------------------------------
*/
bridge->symbfacIVL = SymbFac_initFromPencil(bridge->frontETree,
bridge->pencil) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n symbolic factorization") ;
IVL_writeForHumanEye(bridge->symbfacIVL, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------------------------------
create a FrontMtx object to hold the factorization
--------------------------------------------------
*/
bridge->frontmtx = FrontMtx_new() ;
/*
------------------------------------------------------------
create a SubMtxManager object to hold the factor submatrices
------------------------------------------------------------
*/
bridge->mtxmanager = SubMtxManager_new() ;
SubMtxManager_init(bridge->mtxmanager, NO_LOCK, 0) ;
/*
------------------------------------------------------------
allocate the working objects X and Y for the matrix multiply
------------------------------------------------------------
*/
bridge->X = DenseMtx_new() ;
DenseMtx_init(bridge->X, SPOOLES_REAL, 0, 0, neqns, mxbsz, 1, neqns) ;
bridge->Y = DenseMtx_new() ;
DenseMtx_init(bridge->Y, SPOOLES_REAL, 0, 0, neqns, mxbsz, 1, neqns) ;
/*
------------------------
free the working storage
------------------------
*/
Graph_free(graph) ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Setup += t2 - t1 ;
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Setup) ;
fflush(stdout) ;
#endif
return(1) ; }
/*--------------------------------------------------------------------*/
Eigen/srcST/Solve.c 0100644 0002055 0007177 00000007055 06633557262 0015437 0 ustar 00cleve compmath 0000040 0000006 /* Solve.c */
#include "../Bridge.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Solve = 0 ;
static double time_Solve = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
purpose -- to solve a linear system
(A - sigma*B) sol[] = rhs[]
data -- pointer to bridge data object
*pnrows -- # of rows in x[] and y[]
*pncols -- # of columns in x[] and y[]
rhs[] -- vector that holds right hand sides
sol[] -- vector to hold solutions
note: rhs[] and sol[] can be the same array.
on return, *perror holds an error code.
1 -- normal return
-1 -- pnrows is NULL
-2 -- pncols is NULL
-3 -- rhs is NULL
-4 -- sol is NULL
-5 -- data is NULL
created -- 98aug10, cca & jcp
----------------------------------------------
*/
void
Solve (
int *pnrows,
int *pncols,
double rhs[],
double sol[],
void *data,
int *perror
) {
Bridge *bridge = (Bridge *) data ;
DenseMtx *rhsmtx, *solmtx ;
double cpus[10] ;
int nent, ncols, nrows ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Solve++ ;
fprintf(stdout, "\n (%d) Solve()", count_Solve) ;
fflush(stdout) ;
#endif
/*
---------------
check the input
---------------
*/
if ( perror == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n perror == NULL\n") ;
return ;
}
if ( pnrows == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n pnrows == NULL\n") ;
*perror = -1 ; return ;
}
if ( pncols == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n pncols == NULL\n") ;
*perror = -2 ; return ;
}
if ( rhs == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n rhs == NULL\n") ;
*perror = -3 ; return ;
}
if ( sol == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n sol == NULL\n") ;
*perror = -4 ; return ;
}
if ( data == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n data == NULL\n") ;
*perror = -5 ; return ;
}
/*
----------------------------------
set the number of rows and columns
----------------------------------
*/
nrows = *pnrows ;
ncols = *pncols ;
nent = nrows*ncols ;
/*
-------------------------------------------
setup rhsmtx and solmtx as DenseMtx objects
------------------------------------------
*/
rhsmtx = bridge->Y ;
DenseMtx_init(rhsmtx, SPOOLES_REAL, 0, 0, nrows, ncols, 1, nrows) ;
DVcopy (nent, DenseMtx_entries(rhsmtx), rhs) ;
solmtx = bridge->X ;
DenseMtx_init(solmtx, SPOOLES_REAL, 0, 0, nrows, ncols, 1, nrows) ;
DenseMtx_zero(solmtx) ;
/*
-----------------------
solve the linear system
-----------------------
*/
DVzero(10, cpus) ;
FrontMtx_solve(bridge->frontmtx, solmtx, rhsmtx, bridge->mtxmanager,
cpus, bridge->msglvl, bridge->msgFile) ;
/*
-----------------------------------
copy solution into output parameter
-----------------------------------
*/
DVcopy(nent, sol, DenseMtx_entries(solmtx)) ;
/*
------------------------------------------------------------------
set the error. (this is simple since when the spooles codes detect
a fatal error, they print out a message to stderr and exit.)
------------------------------------------------------------------
*/
*perror = 0 ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Solve += t2 - t1 ;
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Solve) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
ata ;
DenseMtx *rhsmtx, *solmtx ;
double cpus[10] ;
int nent, ncols, nrows ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Solve++ ;
fprintf(stdout, "\n (%d) Solve()", count_Solve) ;
fflush(stdout) ;
#endif
/*
---------------
check the input
---------------
*/
if ( perror == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n perror == NULL\n") ;
return ;
}
if ( pnrows == NULL ) {
fprintf(stderr, "\n error in SolvEigen/srcMT/makefile 0100644 0002055 0007177 00000000541 06625571075 0015665 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = BridgeMT
$(OBJ).a : \
$(OBJ).a(CleanupMT.o) \
$(OBJ).a(FactorMT.o) \
$(OBJ).a(MatMulMT.o) \
$(OBJ).a(SetupMT.o) \
$(OBJ).a(SolveMT.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
Eigen/srcMT/CleanupMT.c 0100644 0002055 0007177 00000002475 06633561121 0016157 0 ustar 00cleve compmath 0000040 0000006 /* CleanupMT.c */
#include "../BridgeMT.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Cleanup = 0 ;
static double time_Cleanup = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
purpose -- to free the owned data structures
return values --
1 -- normal return
-1 -- data is NULL
created -- 98aug10, cca
--------------------------------------------
*/
int
CleanupMT (
void *data
) {
BridgeMT *bridge = (BridgeMT *) data ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Cleanup++ ;
fprintf(stdout, "\n (%d) CleanupMT()", count_Cleanup) ;
#endif
bridge->pencil->inpmtxA = NULL ;
bridge->pencil->inpmtxB = NULL ;
Pencil_free(bridge->pencil) ;
IVL_free(bridge->symbfacIVL) ;
FrontMtx_free(bridge->frontmtx) ;
ETree_free(bridge->frontETree) ;
SubMtxManager_free(bridge->mtxmanager) ;
IV_free(bridge->oldToNewIV) ;
IV_free(bridge->newToOldIV) ;
IV_free(bridge->ownersIV) ;
DenseMtx_free(bridge->X) ;
DenseMtx_free(bridge->Y) ;
SolveMap_free(bridge->solvemap) ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Cleanup += t2 - t1 ;
fprintf(stdout, ", %8.3f seconds, %8.3f total seconds, ",
t2 - t1, time_Cleanup) ;
#endif
return(1) ; }
/*--------------------------------------------------------------------*/
Eigen/srcMT/FactorMT.c 0100644 0002055 0007177 00000013522 06633561177 0016014 0 ustar 00cleve compmath 0000040 0000006 /* FactorMT.c */
#include "../BridgeMT.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Factor = 0 ;
static double time_Factor = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
purpose -- to compute the factorization of A - sigma * B
note: all variables in the calling sequence are references
to allow call from fortran.
input parameters
data -- pointer to bridge data object
psigma -- shift for the matrix pencil
ppvttol -- pivot tolerance
*ppvttol = 0.0 --> no pivoting used
*ppvttol != 0.0 --> pivoting used, entries in factor are
bounded above by 1/pvttol in magnitude
output parameters
*pinertia -- on return contains the number of negative eigenvalues
*perror -- on return contains an error code
1 -- error found during factorization
0 -- normal return
-1 -- psigma is NULL
-2 -- ppvttol is NULL
-3 -- data is NULL
-4 -- pinertia is NULL
created -- 98aug10, cca & jcp
---------------------------------------------------------------------
*/
void
FactorMT (
double *psigma,
double *ppvttol,
void *data,
int *pinertia,
int *perror
) {
BridgeMT *bridge = (BridgeMT *) data ;
Chv *rootchv ;
ChvManager *chvmanager ;
double droptol=0.0, tau ;
double cpus[10] ;
int stats[20] ;
int nnegative, nzero, npositive, pivotingflag ;
int nproc ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Factor++ ;
fprintf(stdout, "\n (%d) FactorMT()", count_Factor) ;
fflush(stdout) ;
#endif
/*
---------------
check the input
---------------
*/
if ( psigma == NULL ) {
fprintf(stderr, "\n error in FactorMT()"
"\n psigma is NULL\n") ;
*perror = -1 ; return ;
}
if ( ppvttol == NULL ) {
fprintf(stderr, "\n error in FactorMT()"
"\n ppvttol is NULL\n") ;
*perror = -2 ; return ;
}
if ( data == NULL ) {
fprintf(stderr, "\n error in FactorMT()"
"\n data is NULL\n") ;
*perror = -3 ; return ;
}
if ( pinertia == NULL ) {
fprintf(stderr, "\n error in FactorMT()"
"\n pinertia is NULL\n") ;
*perror = -4 ; return ;
}
if ( perror == NULL ) {
fprintf(stderr, "\n error in FactorMT()"
"\n perror is NULL\n") ;
return ;
}
nproc = bridge->nthread ;
/*
----------------------------------
set the shift in the pencil object
----------------------------------
*/
bridge->pencil->sigma[0] = -(*psigma) ;
bridge->pencil->sigma[1] = 0.0 ;
/*
----------------------------------------------------------------
clear the front matrix, submatrix mananger and solve map objects
----------------------------------------------------------------
*/
FrontMtx_clearData(bridge->frontmtx);
SubMtxManager_clearData(bridge->mtxmanager);
SolveMap_clearData(bridge->solvemap) ;
/*
-----------------------------------------------------------
set the pivot tolerance.
NOTE: spooles's "tau" parameter is a bound on the magnitude
of the factor entries, and is the recipricol of that of the
pivot tolerance of the lanczos code
-----------------------------------------------------------
*/
if ( *ppvttol == 0.0 ) {
tau = 10.0 ;
pivotingflag = SPOOLES_NO_PIVOTING ;
} else {
tau = (1.0)/(*ppvttol) ;
pivotingflag = SPOOLES_PIVOTING ;
}
/*
----------------------------------
initialize the front matrix object
----------------------------------
*/
FrontMtx_init(bridge->frontmtx, bridge->frontETree, bridge->symbfacIVL,
SPOOLES_REAL, SPOOLES_SYMMETRIC, FRONTMTX_DENSE_FRONTS,
pivotingflag, LOCK_IN_PROCESS, 0, NULL,
bridge->mtxmanager, bridge->msglvl, bridge->msgFile) ;
/*
-------------------------
compute the factorization
-------------------------
*/
chvmanager = ChvManager_new() ;
ChvManager_init(chvmanager, LOCK_IN_PROCESS, 1);
IVfill(20, stats, 0) ;
DVfill(10, cpus, 0.0) ;
rootchv = FrontMtx_MT_factorPencil(bridge->frontmtx, bridge->pencil,
tau, droptol, chvmanager, bridge->ownersIV, 0,
perror, cpus, stats, bridge->msglvl, bridge->msgFile) ;
ChvManager_free(chvmanager);
/*
----------------------------
if matrix is singular then
set error flag and return
----------------------------
*/
if ( rootchv != NULL ) {
*perror = 1 ;
return ;
}
/*
------------------------------------------------------------------
post-process the factor matrix, convert from fronts to submatrices
------------------------------------------------------------------
*/
FrontMtx_postProcess(bridge->frontmtx, bridge->msglvl, bridge->msgFile);
/*
-------------------
compute the inertia
-------------------
*/
FrontMtx_inertia(bridge->frontmtx, &nnegative, &nzero, &npositive) ;
*pinertia = nnegative;
/*
--------------------------
set up the SolveMap object
--------------------------
*/
SolveMap_ddMap(bridge->solvemap, SPOOLES_SYMMETRIC,
FrontMtx_upperBlockIVL(bridge->frontmtx),
FrontMtx_lowerBlockIVL(bridge->frontmtx), nproc,
bridge->ownersIV, FrontMtx_frontTree(bridge->frontmtx),
bridge->seed, bridge->msglvl, bridge->msgFile ) ;
/*
------------------------------------------------------------------
set the error. (this is simple since when the spooles codes detect
a fatal error, they print out a message to stderr and exit.)
------------------------------------------------------------------
*/
*perror = 0 ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Factor += t2 - t1 ;
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Factor) ;
fflush(stdout) ;
#endif
return; }
/*--------------------------------------------------------------------*/
s the number of negative eigenvalues
*perror -- on return contains an error code
1 -- error found during factorization
0 -- normal return
Eigen/srcMT/MatMulMT.c 0100644 0002055 0007177 00000007221 06633561255 0015771 0 ustar 00cleve compmath 0000040 0000006 /* MatMulMT.c */
#include "../BridgeMT.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_MatMul = 0 ;
static double time_MatMul = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
purpose --- to compute a matrix-vector multiply y[] = C * x[]
where C is the identity, A or B (depending on *pprbtype).
*pprbtype -- problem type
*pprbtype = 1 --> vibration problem, matrix is A
*pprbtype = 2 --> buckling problem, matrix is B
*pprbtype = 3 --> matrix is identity, y[] = x[]
*pnrows -- # of rows in x[]
*pncols -- # of columns in x[]
created -- 98aug11, cca & jcp
-------------------------------------------------------------
*/
void
MatMulMT (
int *pnrows,
int *pncols,
double x[],
double y[],
int *pprbtype,
void *data
) {
int ncols, nent, nrows ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_MatMul++ ;
fprintf(stdout, "\n (%d) MatMulMT()", count_MatMul) ;
fflush(stdout) ;
#endif
nrows = *pnrows ;
ncols = *pncols ;
nent = nrows*ncols ;
if ( *pprbtype == 3 ) {
/*
--------------------------
... matrix is the identity
--------------------------
*/
DVcopy(nent, y, x) ;
return;
} else {
BridgeMT *bridge = (BridgeMT *) data ;
DenseMtx *X, *Y ;
double alpha[2] = {1.0, 0.0} ;
int nthread = bridge->nthread ;
/*
---------------------------------
setup x and y as DenseMtx objects
---------------------------------
*/
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile,
"\n inside MatMulMT, nrows = %d, ncols = %d",
nrows, ncols) ;
fprintf(bridge->msgFile, "\n x[]") ;
DVfprintf(bridge->msgFile, nent, x) ;
fflush(bridge->msgFile) ;
}
X = bridge->X ;
DenseMtx_init(X, SPOOLES_REAL, 0, 0, nrows, ncols, 1, nrows);
DVcopy(nent, DenseMtx_entries(X), x);
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile, "\n inside MatMulMT, X") ;
DenseMtx_writeForHumanEye(X, bridge->msgFile) ;
fflush(bridge->msgFile) ;
}
Y = bridge->Y ;
DenseMtx_init(Y, SPOOLES_REAL, 0, 0, nrows, ncols, 1, nrows);
DenseMtx_zero(Y);
if ( *pprbtype == 1 ) {
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile, "\n\n vibration problem") ;
fflush(bridge->msgFile) ;
}
/*
---------------------------------------
... vibration case matrix is 'm' or 'b'
---------------------------------------
*/
InpMtx_MT_sym_mmm(bridge->B, Y, alpha, X, nthread,
bridge->msglvl, bridge->msgFile);
} else {
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile, "\n\n buckling problem") ;
fflush(bridge->msgFile) ;
}
/*
--------------------------------------
... buckling case matrix is 'k' or 'a'
--------------------------------------
*/
InpMtx_MT_sym_mmm(bridge->A, Y, alpha, X, nthread,
bridge->msglvl, bridge->msgFile);
}
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile, "\n inside MatMulMT, Y") ;
DenseMtx_writeForHumanEye(Y, bridge->msgFile) ;
fflush(bridge->msgFile) ;
}
/*
--------------------------------
copy solution into output vector
--------------------------------
*/
DVcopy (nent, y, DenseMtx_entries(Y) );
}
#if MYDEBUG > 0
MARKTIME(t2) ;
MARKTIME(t2) ;
time_MatMul += t2 - t1 ;
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_MatMul) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
Eigen/srcMT/SetupMT.c 0100644 0002055 0007177 00000025257 06636762112 0015701 0 ustar 00cleve compmath 0000040 0000006 /* SetupMT.c */
#include "../BridgeMT.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Setup = 0 ;
static double time_Setup = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
purpose --
given InpMtx objects that contain A and B, initialize the bridge
data structure for the multithreaded factor's, solve's and mvm's.
data -- pointer to a Bridge object
pprbtype -- pointer to value containing problem type
*prbtype = 1 --> A X = B X Lambda, vibration problem
*prbtype = 2 --> A X = B X Lambda, buckling problem
*prbtype = 3 --> A X = X Lambda, simple eigenvalue problem
pneqns -- pointer to value containing number of equations
pmxbsz -- pointer to value containing blocksize
A -- pointer to InpMtx object containing A
B -- pointer to InpMtx object containing B
pseed -- pointer to value containing a random number seed
pmsglvl -- pointer to value containing a message level
msgFile -- message file pointer
pnthread -- pointer to value containing # of threads
return value --
1 -- normal return
-1 -- data is NULL
-2 -- pprbtype is NULL
-3 -- *pprbtype is invalid
-4 -- pneqns is NULL
-5 -- *pneqns is invalid
-6 -- pmxbsz is NULL
-7 -- *pmxbsz is invalid
-8 -- A and B are NULL
-9 -- pseed is NULL
-10 -- pmsglvl is NULL
-11 -- *pmsglvl > 0 and msgFile is NULL
-12 -- pnthreads is NULL
-13 -- *pnthreads is invalid
created -- 98aug10, cca
------------------------------------------------------------------
*/
int
SetupMT (
void *data,
int *pprbtype,
int *pneqns,
int *pmxbsz,
InpMtx *A,
InpMtx *B,
int *pseed,
int *pnthread,
int *pmsglvl,
FILE *msgFile
) {
BridgeMT *bridge = (BridgeMT *) data ;
double sigma[2] ;
DV *cumopsDV ;
Graph *graph ;
int maxdomainsize, maxsize, maxzeros, msglvl, mxbsz,
nedges, neqns, nthread, prbtype, seed ;
IVL *adjIVL ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Setup++ ;
fprintf(stdout, "\n (%d) SetupMT()", count_Setup) ;
fflush(stdout) ;
#endif
/*
--------------------
check the input data
--------------------
*/
if ( data == NULL ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n data is NULL\n") ;
return(-1) ;
}
if ( pprbtype == NULL ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n pprbtype is NULL\n") ;
return(-2) ;
}
prbtype = *pprbtype ;
if ( prbtype < 1 || prbtype > 3 ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n prbtype = %d, is invalid\n", prbtype) ;
return(-3) ;
}
if ( pneqns == NULL ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n pneqns is NULL\n") ;
return(-4) ;
}
neqns = *pneqns ;
if ( neqns <= 0 ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n neqns = %d, is invalid\n", neqns) ;
return(-5) ;
}
if ( pmxbsz == NULL ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n pmxbsz is NULL\n") ;
return(-6) ;
}
mxbsz = *pmxbsz ;
if ( mxbsz <= 0 ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n *pmxbsz = %d, is invalid\n", mxbsz) ;
return(-7) ;
}
if ( A == NULL && B == NULL ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n A and B are NULL\n") ;
return(-8) ;
}
if ( pseed == NULL ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n pseed is NULL\n") ;
return(-9) ;
}
seed = *pseed ;
if ( pmsglvl == NULL ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n pmsglvl is NULL\n") ;
return(-10) ;
}
msglvl = *pmsglvl ;
if ( msglvl > 0 && msgFile == NULL ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n msglvl = %d, msgFile = NULL\n", msglvl) ;
return(-11) ;
}
if ( pnthread == NULL ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n pnthread is NULL\n") ;
return(-12) ;
}
nthread = *pnthread ;
if ( nthread <= 0 ) {
fprintf(stderr, "\n fatal error in SetupMT()"
"\n nthread = %d, is invalid\n", nthread) ;
return(-13) ;
}
bridge->msglvl = *pmsglvl ;
/*
bridge->msglvl = 2 ;
*/
bridge->msgFile = msgFile ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n inside SetupMT()"
"\n neqns = %d, prbtype = %d, mxbsz = %d, seed = %d, nthread = %d",
neqns, prbtype, mxbsz, seed, nthread) ;
if ( A != NULL ) {
fprintf(msgFile, "\n\n matrix A") ;
InpMtx_writeForHumanEye(A, msgFile) ;
}
if ( B != NULL ) {
fprintf(msgFile, "\n\n matrix B") ;
InpMtx_writeForHumanEye(B, msgFile) ;
}
fflush(msgFile) ;
}
bridge->prbtype = prbtype ;
bridge->neqns = neqns ;
bridge->mxbsz = mxbsz ;
bridge->A = A ;
bridge->B = B ;
bridge->seed = seed ;
bridge->nthread = nthread ;
/*
----------------------------
create and initialize pencil
----------------------------
*/
sigma[0] = 1.0; sigma[1] = 0.0;
bridge->pencil = Pencil_new() ;
Pencil_setDefaultFields(bridge->pencil) ;
Pencil_init(bridge->pencil, SPOOLES_REAL, SPOOLES_SYMMETRIC,
A, sigma, B) ;
/*
--------------------------------
convert to row or column vectors
--------------------------------
*/
if ( A != NULL ) {
if ( ! INPMTX_IS_BY_ROWS(A) && ! INPMTX_IS_BY_COLUMNS(A) ) {
InpMtx_changeCoordType(A, INPMTX_BY_ROWS) ;
}
if ( ! INPMTX_IS_BY_VECTORS(A) ) {
InpMtx_changeStorageMode(A, INPMTX_BY_VECTORS) ;
}
}
if ( B != NULL ) {
if ( ! INPMTX_IS_BY_ROWS(B) && ! INPMTX_IS_BY_COLUMNS(B) ) {
InpMtx_changeCoordType(B, INPMTX_BY_ROWS) ;
}
if ( ! INPMTX_IS_BY_VECTORS(B) ) {
InpMtx_changeStorageMode(B, INPMTX_BY_VECTORS) ;
}
}
/*
-------------------------------
create a Graph object for A + B
-------------------------------
*/
graph = Graph_new() ;
adjIVL = Pencil_fullAdjacency(bridge->pencil);
nedges = IVL_tsize(adjIVL),
Graph_init2(graph, 0, bridge->neqns, 0, nedges,
bridge->neqns, nedges, adjIVL, NULL, NULL) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n graph of the input matrix") ;
Graph_writeForHumanEye(graph, msgFile) ;
fflush(msgFile) ;
}
/*
---------------
order the graph
---------------
*/
maxdomainsize = neqns / 64 ;
if ( maxdomainsize == 0 ) {
maxdomainsize = 1 ;
}
maxzeros = (int) (0.01*neqns) ;
maxsize = 64 ;
bridge->frontETree = orderViaBestOfNDandMS(graph, maxdomainsize,
maxzeros, maxsize, bridge->seed, msglvl, msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree from ordering") ;
ETree_writeForHumanEye(bridge->frontETree, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------------------
get the old-to-new and new-to-old permutations
----------------------------------------------
*/
bridge->oldToNewIV = ETree_oldToNewVtxPerm(bridge->frontETree) ;
bridge->newToOldIV = ETree_newToOldVtxPerm(bridge->frontETree) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n old-to-new permutation") ;
IV_writeForHumanEye(bridge->oldToNewIV, msgFile) ;
fprintf(msgFile, "\n\n new-to-old permutation") ;
IV_writeForHumanEye(bridge->newToOldIV, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------------------
permute the vertices in the front tree
--------------------------------------
*/
ETree_permuteVertices(bridge->frontETree, bridge->oldToNewIV) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n permuted front etree") ;
ETree_writeForHumanEye(bridge->frontETree, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------------------------
permute the entries in the pencil.
note, after the permutation the
entries are mapped into the upper triangle.
-------------------------------------------
*/
Pencil_permute(bridge->pencil, bridge->oldToNewIV, bridge->oldToNewIV) ;
Pencil_mapToUpperTriangle(bridge->pencil) ;
Pencil_changeCoordType(bridge->pencil, INPMTX_BY_CHEVRONS) ;
Pencil_changeStorageMode(bridge->pencil, INPMTX_BY_VECTORS) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n permuted pencil") ;
Pencil_writeForHumanEye(bridge->pencil, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------
compute the symbolic factorization
----------------------------------
*/
bridge->symbfacIVL = SymbFac_initFromPencil(bridge->frontETree,
bridge->pencil) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n symbolic factorization") ;
IVL_writeForHumanEye(bridge->symbfacIVL, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------------------------------
create a FrontMtx object to hold the factorization
--------------------------------------------------
*/
bridge->frontmtx = FrontMtx_new() ;
/*
------------------------------------------------------------
create a SubMtxManager object to hold the factor submatrices
------------------------------------------------------------
*/
bridge->mtxmanager = SubMtxManager_new() ;
SubMtxManager_init(bridge->mtxmanager, LOCK_IN_PROCESS, 0) ;
/*
------------------------------------------------------------
allocate the working objects X and Y for the matrix multiply
------------------------------------------------------------
*/
bridge->X = DenseMtx_new() ;
DenseMtx_init(bridge->X, SPOOLES_REAL, 0, 0, neqns, mxbsz, 1, neqns) ;
bridge->Y = DenseMtx_new() ;
DenseMtx_init(bridge->Y, SPOOLES_REAL, 0, 0, neqns, mxbsz, 1, neqns) ;
/*
--------------------------------------------------------
setup up ownersIV, the map from fronts to owning threads
--------------------------------------------------------
*/
cumopsDV = DV_new() ;
DV_init(cumopsDV, bridge->nthread, NULL );
bridge->ownersIV = ETree_ddMap(bridge->frontETree, SPOOLES_REAL,
SPOOLES_SYMMETRIC, cumopsDV,
1./(2.*bridge->nthread) );
if ( msglvl >= 0 ) {
fprintf(msgFile, "\n\n load balance for the processors") ;
DV_writeForHumanEye(cumopsDV, msgFile) ;
fprintf(msgFile, "\n\n map from fronts to threads") ;
IV_writeForHumanEye(bridge->ownersIV, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------------------------------------------------
create a SolveMap object, the map from submatries to owning threads
-------------------------------------------------------------------
*/
bridge->solvemap = SolveMap_new() ;
/*
------------------------
free the working storage
------------------------
*/
Graph_free(graph) ;
DV_free(cumopsDV);
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Setup += t2 - t1 ;
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Setup) ;
fflush(stdout) ;
#endif
return(1) ; }
/*--------------------------------------------------------------------*/
Eigen/srcMT/SolveMT.c 0100644 0002055 0007177 00000007111 06633561405 0015655 0 ustar 00cleve compmath 0000040 0000006 /* SolveMT.c */
#include "../BridgeMT.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Solve = 0 ;
static double time_Solve = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
purpose -- to solve a linear system
(A - sigma*B) sol[] = rhs[]
data -- pointer to bridge data object
*pnrows -- # of rows in x[] and y[]
*pncols -- # of columns in x[] and y[]
rhs[] -- vector that holds right hand sides
sol[] -- vector to hold solutions
note: rhs[] and sol[] can be the same array.
on return, *perror holds an error code.
1 -- normal return
-1 -- pnrows is NULL
-2 -- pncols is NULL
-3 -- rhs is NULL
-4 -- sol is NULL
-5 -- data is NULL
created -- 98aug10, cca & jcp
----------------------------------------------
*/
void
SolveMT (
int *pnrows,
int *pncols,
double rhs[],
double sol[],
void *data,
int *perror
) {
BridgeMT *bridge = (BridgeMT *) data ;
DenseMtx *rhsmtx, *solmtx ;
double cpus[10] ;
int nent, ncols, nrows ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Solve++ ;
fprintf(stdout, "\n (%d) SolveMT()", count_Solve) ;
fflush(stdout) ;
#endif
/*
---------------
check the input
---------------
*/
if ( perror == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n perror == NULL\n") ;
return ;
}
if ( pnrows == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n pnrows == NULL\n") ;
*perror = -1 ; return ;
}
if ( pncols == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n pncols == NULL\n") ;
*perror = -2 ; return ;
}
if ( rhs == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n rhs == NULL\n") ;
*perror = -3 ; return ;
}
if ( sol == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n sol == NULL\n") ;
*perror = -4 ; return ;
}
if ( data == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n data == NULL\n") ;
*perror = -5 ; return ;
}
/*
----------------------------------
set the number of rows and columns
----------------------------------
*/
nrows = *pnrows ;
ncols = *pncols ;
nent = nrows*ncols ;
/*
-------------------------------------------
setup rhsmtx and solmtx as DenseMtx objects
------------------------------------------
*/
rhsmtx = bridge->Y ;
DenseMtx_init(rhsmtx, SPOOLES_REAL, 0, 0, nrows, ncols, 1, nrows) ;
DVcopy (nent, DenseMtx_entries(rhsmtx), rhs) ;
solmtx = bridge->X ;
DenseMtx_init(solmtx, SPOOLES_REAL, 0, 0, nrows, ncols, 1, nrows) ;
DenseMtx_zero(solmtx) ;
/*
-----------------------
solve the linear system
-----------------------
*/
DVzero(10, cpus) ;
FrontMtx_MT_solve(bridge->frontmtx, solmtx, rhsmtx, bridge->mtxmanager,
bridge->solvemap, cpus, bridge->msglvl, bridge->msgFile) ;
/*
-----------------------------------
copy solution into output parameter
-----------------------------------
*/
DVcopy(nent, sol, DenseMtx_entries(solmtx)) ;
/*
------------------------------------------------------------------
set the error. (this is simple since when the spooles codes detect
a fatal error, they print out a message to stderr and exit.)
------------------------------------------------------------------
*/
*perror = 0 ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Solve += t2 - t1 ;
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Solve) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
smtx, *solmtx ;
double cpus[10] ;
int nent, ncols, nrows ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Solve++ ;
fprintf(stdout, "\n (%d) SolveMT()", count_Solve) ;
fflush(stdout) ;
#endif
/*
---------------
check the input
---------------
*/
if ( perror == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n perror == NULL\n") ;
return ;
}
if ( pnrows == NULL ) {
fprintf(stderr, "\n errEigen/srcMPI/makefile 0100644 0002055 0007177 00000001204 06636772136 0015772 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
#
# set suffix rule *.c --> *.a
#
.c.a :
$(PURIFY) $(CC) -c $(CFLAGS) $(MPI_INCLUDE_DIR) $*.c -o $*.o
$(AR) $(ARFLAGS) $(OBJ).a $*.o
rm $*.o
#-----------------------------------------------------------------------
OBJ = BridgeMPI
$(OBJ).a : \
$(OBJ).a(JimMatMulMPI.o) \
$(OBJ).a(JimSolveMPI.o) \
$(OBJ).a(CleanupMPI.o) \
$(OBJ).a(FactorMPI.o) \
$(OBJ).a(MatMulMPI.o) \
$(OBJ).a(SetupMPI.o) \
$(OBJ).a(SolveMPI.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
Eigen/srcMPI/CleanupMPI.c 0100644 0002055 0007177 00000003600 06636727557 0016404 0 ustar 00cleve compmath 0000040 0000006 /* CleanupMPI.c */
#include "../BridgeMPI.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Cleanup = 0 ;
static double time_Cleanup = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
purpose -- to free the owned data structures
return values --
1 -- normal return
-1 -- data is NULL
created -- 98aug10, cca
--------------------------------------------
*/
int
CleanupMPI (
void *data
) {
BridgeMPI *bridge = (BridgeMPI *) data ;
#if MYDEBUG > 0
double t1, t2 ;
MARKTIME(t1) ;
count_Cleanup++ ;
if ( bridge->myid == 0 ) {
fprintf(stdout, "\n (%d) CleanupMPI()", count_Cleanup) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, "\n (%d) CleanupMPI()", count_Cleanup) ;
fflush(bridge->msgFile) ;
#endif
bridge->pencil->inpmtxA = NULL ;
bridge->pencil->inpmtxB = NULL ;
Pencil_free(bridge->pencil) ;
IVL_free(bridge->symbfacIVL) ;
FrontMtx_free(bridge->frontmtx) ;
ETree_free(bridge->frontETree) ;
SubMtxManager_free(bridge->mtxmanager) ;
IV_free(bridge->oldToNewIV) ;
IV_free(bridge->newToOldIV) ;
IV_free(bridge->vtxmapIV) ;
IV_free(bridge->ownersIV) ;
IV_free(bridge->myownedIV) ;
if ( bridge->rowmapIV != NULL ) {
IV_free(bridge->rowmapIV) ;
}
if ( bridge->info != NULL ) {
MatMul_cleanup(bridge->info) ;
DenseMtx_free(bridge->Xloc) ;
DenseMtx_free(bridge->Yloc) ;
}
SolveMap_free(bridge->solvemap) ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Cleanup += t2 - t1 ;
if ( bridge->myid == 0 ) {
fprintf(stdout, ", %8.3f seconds, %8.3f total seconds, ",
t2 - t1, time_Cleanup) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, ", %8.3f seconds, %8.3f total seconds, ",
t2 - t1, time_Cleanup) ;
fflush(bridge->msgFile) ;
#endif
return(1) ; }
/*--------------------------------------------------------------------*/
Eigen/srcMPI/FactorMPI.c 0100644 0002055 0007177 00000022475 06636771455 0016242 0 ustar 00cleve compmath 0000040 0000006 /* FactorMPI.c */
#include "../BridgeMPI.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Factor = 0 ;
static double time_Factor = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
purpose -- to compute the factorization of A - sigma * B
note: all variables in the calling sequence are references
to allow call from fortran.
input parameters
data -- pointer to bridge data object
psigma -- shift for the matrix pencil
ppvttol -- pivot tolerance
*ppvttol = 0.0 --> no pivoting used
*ppvttol != 0.0 --> pivoting used, entries in factor are
bounded above by 1/pvttol in magnitude
output parameters
*pinertia -- on return contains the number of negative eigenvalues
*perror -- on return contains an error code
1 -- error found during factorization
0 -- normal return
-1 -- psigma is NULL
-2 -- ppvttol is NULL
-3 -- data is NULL
-4 -- pinertia is NULL
created -- 98aug10, cca & jcp
---------------------------------------------------------------------
*/
void
FactorMPI (
double *psigma,
double *ppvttol,
void *data,
int *pinertia,
int *perror
) {
BridgeMPI *bridge = (BridgeMPI *) data ;
Chv *rootchv ;
ChvManager *chvmanager ;
double droptol=0.0, tau ;
double cpus[20] ;
FILE *msgFile ;
int recvtemp[3], sendtemp[3], stats[20] ;
int msglvl, nnegative, nzero, npositive, pivotingflag, tag ;
MPI_Comm comm ;
int nproc ;
#if MYDEBUG > 0
double t1, t2 ;
count_Factor++ ;
MARKTIME(t1) ;
if ( bridge->myid == 0 ) {
fprintf(stdout, "\n (%d) FactorMPI()", count_Factor) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, "\n (%d) FactorMPI()", count_Factor) ;
fflush(bridge->msgFile) ;
#endif
nproc = bridge->nproc ;
/*
---------------
check the input
---------------
*/
if ( psigma == NULL ) {
fprintf(stderr, "\n error in FactorMPI()"
"\n psigma is NULL\n") ;
*perror = -1 ; return ;
}
if ( ppvttol == NULL ) {
fprintf(stderr, "\n error in FactorMPI()"
"\n ppvttol is NULL\n") ;
*perror = -2 ; return ;
}
if ( data == NULL ) {
fprintf(stderr, "\n error in FactorMPI()"
"\n data is NULL\n") ;
*perror = -3 ; return ;
}
if ( pinertia == NULL ) {
fprintf(stderr, "\n error in FactorMPI()"
"\n pinertia is NULL\n") ;
*perror = -4 ; return ;
}
if ( perror == NULL ) {
fprintf(stderr, "\n error in FactorMPI()"
"\n perror is NULL\n") ;
return ;
}
comm = bridge->comm ;
msglvl = bridge->msglvl ;
msgFile = bridge->msgFile ;
/*
----------------------------------
set the shift in the pencil object
----------------------------------
*/
bridge->pencil->sigma[0] = -(*psigma) ;
bridge->pencil->sigma[1] = 0.0 ;
/*
-----------------------------------------
if the matrices are in local coordinates
(i.e., this is the first factorization
following a matrix-vector multiply) then
map the matrix into global coordinates
-----------------------------------------
*/
if ( bridge->coordFlag == LOCAL ) {
if ( bridge->prbtype == 1 ) {
MatMul_setGlobalIndices(bridge->info, bridge->B) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n matrix B in local coordinates") ;
InpMtx_writeForHumanEye(bridge->B, msgFile) ;
fflush(msgFile) ;
}
}
if ( bridge->prbtype == 2 ) {
MatMul_setGlobalIndices(bridge->info, bridge->A) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n matrix A in local coordinates") ;
InpMtx_writeForHumanEye(bridge->A, msgFile) ;
fflush(msgFile) ;
}
}
bridge->coordFlag = GLOBAL ;
}
/*
-----------------------------------------------------
clear the front matrix and submatrix mananger objects
-----------------------------------------------------
*/
FrontMtx_clearData(bridge->frontmtx);
SubMtxManager_clearData(bridge->mtxmanager);
SolveMap_clearData(bridge->solvemap) ;
if ( bridge->rowmapIV != NULL ) {
IV_free(bridge->rowmapIV) ;
bridge->rowmapIV = NULL ;
}
/*
-----------------------------------------------------------
set the pivot tolerance.
NOTE: spooles's "tau" parameter is a bound on the magnitude
of the factor entries, and is the recipricol of that of the
pivot tolerance of the lanczos code
-----------------------------------------------------------
*/
if ( *ppvttol == 0.0 ) {
tau = 10.0 ;
pivotingflag = SPOOLES_NO_PIVOTING ;
} else {
tau = (1.0)/(*ppvttol) ;
pivotingflag = SPOOLES_PIVOTING ;
}
/*
----------------------------------
initialize the front matrix object
----------------------------------
*/
FrontMtx_init(bridge->frontmtx, bridge->frontETree, bridge->symbfacIVL,
SPOOLES_REAL, SPOOLES_SYMMETRIC, FRONTMTX_DENSE_FRONTS,
pivotingflag, NO_LOCK, bridge->myid, bridge->ownersIV,
bridge->mtxmanager, bridge->msglvl, bridge->msgFile) ;
/*
-------------------------
compute the factorization
-------------------------
*/
tag = 0 ;
chvmanager = ChvManager_new() ;
ChvManager_init(chvmanager, NO_LOCK, 0);
IVfill(20, stats, 0) ;
DVfill(20, cpus, 0.0) ;
rootchv = FrontMtx_MPI_factorPencil(bridge->frontmtx, bridge->pencil,
tau, droptol, chvmanager, bridge->ownersIV,
0, perror, cpus, stats, bridge->msglvl,
bridge->msgFile, tag, comm) ;
ChvManager_free(chvmanager);
tag += 3*FrontMtx_nfront(bridge->frontmtx) + 2 ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n numeric factorization") ;
FrontMtx_writeForHumanEye(bridge->frontmtx, bridge->msgFile) ;
fflush(bridge->msgFile) ;
}
/*
----------------------------
if matrix is singular then
set error flag and return
----------------------------
*/
if ( rootchv != NULL ) {
fprintf(msgFile, "\n WHOA NELLY!, matrix is singular") ;
fflush(msgFile) ;
*perror = 1 ;
return ;
}
/*
------------------------------------------------------------------
post-process the factor matrix, convert from fronts to submatrices
------------------------------------------------------------------
*/
FrontMtx_MPI_postProcess(bridge->frontmtx, bridge->ownersIV, stats,
bridge->msglvl, bridge->msgFile, tag, comm);
tag += 5*bridge->nproc ;
/*
-------------------
compute the inertia
-------------------
*/
FrontMtx_inertia(bridge->frontmtx, &nnegative, &nzero, &npositive) ;
sendtemp[0] = nnegative ;
sendtemp[1] = nzero ;
sendtemp[2] = npositive ;
if ( bridge->msglvl > 2 && bridge->msgFile != NULL ) {
fprintf(bridge->msgFile, "\n local inertia = < %d, %d, %d >",
nnegative, nzero, npositive) ;
fflush(bridge->msgFile) ;
}
MPI_Allreduce((void *) sendtemp, (void *) recvtemp, 3, MPI_INT,
MPI_SUM, comm) ;
nnegative = recvtemp[0] ;
nzero = recvtemp[1] ;
npositive = recvtemp[2] ;
if ( bridge->msglvl > 2 && bridge->msgFile != NULL ) {
fprintf(bridge->msgFile, "\n global inertia = < %d, %d, %d >",
nnegative, nzero, npositive) ;
fflush(bridge->msgFile) ;
}
*pinertia = nnegative;
/*
---------------------------
create the solve map object
---------------------------
*/
SolveMap_ddMap(bridge->solvemap, SPOOLES_REAL,
FrontMtx_upperBlockIVL(bridge->frontmtx),
FrontMtx_lowerBlockIVL(bridge->frontmtx), nproc,
bridge->ownersIV, FrontMtx_frontTree(bridge->frontmtx),
bridge->seed, bridge->msglvl, bridge->msgFile) ;
/*
-------------------------------
redistribute the front matrices
-------------------------------
*/
FrontMtx_MPI_split(bridge->frontmtx, bridge->solvemap, stats,
bridge->msglvl, bridge->msgFile, tag, comm) ;
if ( *ppvttol != 0.0 ) {
/*
-------------------------------------------------------------
pivoting for stability may have taken place. create rowmapIV,
the map from rows in the factorization to processes.
-------------------------------------------------------------
*/
bridge->rowmapIV = FrontMtx_MPI_rowmapIV(bridge->frontmtx,
bridge->ownersIV, bridge->msglvl,
bridge->msgFile, bridge->comm) ;
if ( bridge->msglvl > 2 && bridge->msgFile != NULL ) {
fprintf(bridge->msgFile, "\n\n bridge->rowmapIV") ;
IV_writeForHumanEye(bridge->rowmapIV, bridge->msgFile) ;
fflush(bridge->msgFile) ;
}
} else {
bridge->rowmapIV = NULL ;
}
/*
------------------------------------------------------------------
set the error. (this is simple since when the spooles codes detect
a fatal error, they print out a message to stderr and exit.)
------------------------------------------------------------------
*/
*perror = 0 ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Factor += t2 - t1 ;
if ( bridge->myid == 0 ) {
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Factor) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Factor) ;
fflush(bridge->msgFile) ;
#endif
return; }
/*--------------------------------------------------------------------*/
Eigen/srcMPI/JimMatMulMPI.c 0100644 0002055 0007177 00000012507 06636772077 0016657 0 ustar 00cleve compmath 0000040 0000006 /* JimMatMulMPI.c */
#include "../BridgeMPI.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_JimMatMul = 0 ;
static double time_JimMatMul = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
purpose --- to compute a matrix-vector multiply y[] = C * x[]
where C is the identity, A or B (depending on *pprbtype).
*pnrows -- # of rows in x[]
*pncols -- # of columns in x[]
*pprbtype -- problem type
*pprbtype = 1 --> vibration problem, matrix is A
*pprbtype = 2 --> buckling problem, matrix is B
*pprbtype = 3 --> matrix is identity, y[] = x[]
x[] -- vector to be multiplied
NOTE: the x[] vector is global, not a portion
y[] -- product vector
NOTE: the y[] vector is global, not a portion
created -- 98aug28, cca & jcp
-------------------------------------------------------------
*/
void
JimMatMulMPI (
int *pnrows,
int *pncols,
double x[],
double y[],
int *pprbtype,
void *data
) {
BridgeMPI *bridge = (BridgeMPI *) data ;
int ncols, nent, nrows ;
#if MYDEBUG > 0
double t1, t2 ;
count_JimMatMul++ ;
MARKTIME(t1) ;
if ( bridge->myid == 0 ) {
fprintf(stdout, "\n (%d) JimMatMulMPI() start", count_JimMatMul) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile,
"\n (%d) JimMatMulMPI() start", count_JimMatMul) ;
fflush(bridge->msgFile) ;
#endif
nrows = *pnrows ;
ncols = *pncols ;
nent = nrows*ncols ;
if ( *pprbtype == 3 ) {
/*
--------------------------
... matrix is the identity
--------------------------
*/
DVcopy(nent, y, x) ;
} else {
BridgeMPI *bridge = (BridgeMPI *) data ;
DenseMtx *mtx, *newmtx ;
int irow, jcol, jj, kk, myid, neqns, nowned, tag = 0 ;
int *vtxmap ;
int stats[4] ;
IV *mapIV ;
/*
---------------------------------------------
slide the owned rows of x[] down in the array
---------------------------------------------
*/
vtxmap = IV_entries(bridge->vtxmapIV) ;
neqns = bridge->neqns ;
myid = bridge->myid ;
nowned = IV_size(bridge->myownedIV) ;
for ( jcol = jj = kk = 0 ; jcol < ncols ; jcol++ ) {
for ( irow = 0 ; irow < neqns ; irow++, jj++ ) {
if ( vtxmap[irow] == myid ) {
y[kk++] = x[jj] ;
}
}
}
if ( kk != nowned * ncols ) {
fprintf(stderr, "\n proc %d : kk %d, nowned %d, ncols %d",
myid, kk, nowned, ncols) ;
exit(-1) ;
}
/*
----------------------------------------
call the method that assumes local input
----------------------------------------
*/
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile,
"\n inside JimMatMulMPI, calling MatMulMpi"
"\n prbtype %d, nrows %d, ncols %d, nowned %d",
*pprbtype, *pnrows, *pncols, nowned) ;
fflush(bridge->msgFile) ;
}
MatMulMPI(&nowned, pncols, y, y, pprbtype, data) ;
/*
-------------------------------------------------
gather all the entries of y[] onto processor zero
-------------------------------------------------
*/
mtx = DenseMtx_new() ;
DenseMtx_init(mtx, SPOOLES_REAL, 0, 0, nowned, ncols, 1, nowned) ;
DVcopy (nowned*ncols, DenseMtx_entries(mtx), y) ;
IVcopy(nowned, mtx->rowind, IV_entries(bridge->myownedIV)) ;
mapIV = IV_new() ;
IV_init(mapIV, neqns, NULL) ;
IV_fill(mapIV, 0) ;
IVfill(4, stats, 0) ;
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile, "\n mtx: %d rows x %d columns",
mtx->nrow, mtx->ncol) ;
fflush(bridge->msgFile) ;
}
newmtx = DenseMtx_MPI_splitByRows(mtx, mapIV, stats, bridge->msglvl,
bridge->msgFile, tag, bridge->comm) ;
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile, "\n newmtx: %d rows x %d columns",
newmtx->nrow, newmtx->ncol) ;
fflush(bridge->msgFile) ;
}
DenseMtx_free(mtx) ;
mtx = newmtx ;
IV_free(mapIV) ;
if ( myid == 0 ) {
if ( mtx->nrow != neqns || mtx->ncol != ncols ) {
fprintf(bridge->msgFile,
"\n\n WHOA: mtx->nrows %d, mtx->ncols %d"
", neqns %d, ncols %d", mtx->nrow, mtx->ncol,
neqns, ncols) ;
exit(-1) ;
}
DVcopy(neqns*ncols, y, DenseMtx_entries(mtx)) ;
}
DenseMtx_free(mtx) ;
/*
---------------------------------------------
broadcast the entries to the other processors
---------------------------------------------
*/
MPI_Bcast((void *) y, neqns*ncols, MPI_DOUBLE, 0, bridge->comm) ;
if ( bridge->msglvl > 2 ) {
fprintf(bridge->msgFile, "\n after the broadcast") ;
fflush(bridge->msgFile) ;
}
}
MPI_Barrier(bridge->comm) ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_JimMatMul += t2 - t1 ;
if ( bridge->myid == 0 ) {
fprintf(stdout, "\n (%d) JimMatMulMPI() end", count_JimMatMul) ;
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_JimMatMul) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile,
"\n (%d) JimMatMulMPI() end", count_JimMatMul) ;
fprintf(bridge->msgFile, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_JimMatMul) ;
fflush(bridge->msgFile) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
out) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile,
"\n (%d) JimMatMulMPI() start", count_JimMatMul) ;
fflush(bridge->msgFile) ;
#endif
nrows = *pnrows ;
ncols = *pncols Eigen/srcMPI/JimSolveMPI.c 0100644 0002055 0007177 00000011541 06636772712 0016541 0 ustar 00cleve compmath 0000040 0000006 /* JimSolveMPI.c */
#include "../BridgeMPI.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_JimSolve = 0 ;
static double time_JimSolve = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
purpose -- to solve a linear system
(A - sigma*B) sol[] = rhs[]
data -- pointer to bridge data object
*pnrows -- # of rows in x[] and y[]
*pncols -- # of columns in x[] and y[]
rhs[] -- vector that holds right hand sides
NOTE: the rhs[] vector is global, not a portion
sol[] -- vector to hold solutions
NOTE: the sol[] vector is global, not a portion
note: rhs[] and sol[] can be the same array.
on return, *perror holds an error code.
created -- 98aug28, cca & jcp
--------------------------------------------------
*/
void
JimSolveMPI (
int *pnrows,
int *pncols,
double rhs[],
double sol[],
void *data,
int *perror
) {
BridgeMPI *bridge = (BridgeMPI *) data ;
DenseMtx *mtx, *newmtx ;
int irow, jj, jcol, kk, myid, ncols = *pncols,
neqns, nowned, tag = 0 ;
int *vtxmap ;
int stats[4] ;
IV *mapIV ;
#if MYDEBUG > 0
double t1, t2 ;
count_JimSolve++ ;
MARKTIME(t1) ;
if ( bridge->myid == 0 ) {
fprintf(stdout, "\n (%d) JimSolve() start", count_JimSolve) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, "\n (%d) JimSolve() start", count_JimSolve) ;
fflush(bridge->msgFile) ;
#endif
MPI_Barrier(bridge->comm) ;
/*
---------------------------------------------
slide the owned rows of rhs down in the array
---------------------------------------------
*/
vtxmap = IV_entries(bridge->vtxmapIV) ;
neqns = bridge->neqns ;
myid = bridge->myid ;
nowned = IV_size(bridge->myownedIV) ;
for ( jcol = jj = kk = 0 ; jcol < ncols ; jcol++ ) {
for ( irow = 0 ; irow < neqns ; irow++, jj++ ) {
if ( vtxmap[irow] == myid ) {
sol[kk++] = rhs[jj] ;
}
}
}
if ( kk != nowned * ncols ) {
fprintf(stderr, "\n proc %d : kk %d, nowned %d, ncols %d",
myid, kk, nowned, ncols) ;
exit(-1) ;
}
/*
----------------------------------------
call the method that assumes local input
----------------------------------------
*/
if ( bridge->msglvl > 1 ) {
fprintf(bridge->msgFile, "\n calling SolveMPI()") ;
fflush(bridge->msgFile) ;
}
SolveMPI(&nowned, pncols, sol, sol, data, perror) ;
if ( bridge->msglvl > 1 ) {
fprintf(bridge->msgFile, "\n return from SolveMPI()") ;
fflush(bridge->msgFile) ;
}
/*
------------------------------------------
gather all the entries onto processor zero
------------------------------------------
*/
mtx = DenseMtx_new() ;
DenseMtx_init(mtx, SPOOLES_REAL, 0, 0, nowned, ncols, 1, nowned) ;
DVcopy (nowned*ncols, DenseMtx_entries(mtx), sol) ;
IVcopy(nowned, mtx->rowind, IV_entries(bridge->myownedIV)) ;
mapIV = IV_new() ;
IV_init(mapIV, neqns, NULL) ;
IV_fill(mapIV, 0) ;
IVfill(4, stats, 0) ;
if ( bridge->msglvl > 1 ) {
fprintf(bridge->msgFile, "\n calling DenseMtx_split()()") ;
fflush(bridge->msgFile) ;
}
newmtx = DenseMtx_MPI_splitByRows(mtx, mapIV, stats, bridge->msglvl,
bridge->msgFile, tag, bridge->comm) ;
if ( bridge->msglvl > 1 ) {
fprintf(bridge->msgFile, "\n return from DenseMtx_split()()") ;
fflush(bridge->msgFile) ;
}
DenseMtx_free(mtx) ;
mtx = newmtx ;
IV_free(mapIV) ;
if ( myid == 0 ) {
DVcopy(neqns*ncols, sol, DenseMtx_entries(mtx)) ;
}
DenseMtx_free(mtx) ;
/*
---------------------------------------------
broadcast the entries to the other processors
---------------------------------------------
*/
if ( bridge->msglvl > 1 ) {
fprintf(bridge->msgFile, "\n calling MPI_Bcast()()") ;
fflush(bridge->msgFile) ;
}
MPI_Bcast((void *) sol, neqns*ncols, MPI_DOUBLE, 0, bridge->comm) ;
if ( bridge->msglvl > 1 ) {
fprintf(bridge->msgFile, "\n return from MPI_Bcast()()") ;
fflush(bridge->msgFile) ;
}
MPI_Barrier(bridge->comm) ;
/*
------------------------------------------------------------------
set the error. (this is simple since when the spooles codes detect
a fatal error, they print out a message to stderr and exit.)
------------------------------------------------------------------
*/
*perror = 0 ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_JimSolve += t2 - t1 ;
if ( bridge->myid == 0 ) {
fprintf(stdout, "\n (%d) JimSolve() end", count_JimSolve) ;
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_JimSolve) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, "\n (%d) JimSolve() end", count_JimSolve) ;
fprintf(bridge->msgFile, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_JimSolve) ;
fflush(bridge->msgFile) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
Eigen/srcMPI/MatMulMPI.c 0100644 0002055 0007177 00000014016 06636772011 0016200 0 ustar 00cleve compmath 0000040 0000006 /* MatMulMPI.c */
#include "../BridgeMPI.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_MatMul = 0 ;
static double time_MatMul = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
purpose --- to compute a matrix-vector multiply y[] = C * x[]
where C is the identity, A or B (depending on *pprbtype).
*pnrows -- # of rows in x[]
*pncols -- # of columns in x[]
*pprbtype -- problem type
*pprbtype = 1 --> vibration problem, matrix is A
*pprbtype = 2 --> buckling problem, matrix is B
*pprbtype = 3 --> matrix is identity, y[] = x[]
created -- 98aug11, cca & jcp
-------------------------------------------------------------
*/
void
MatMulMPI (
int *pnrows,
int *pncols,
double x[],
double y[],
int *pprbtype,
void *data
) {
BridgeMPI *bridge = (BridgeMPI *) data ;
int ncols, nent, nrows ;
#if MYDEBUG > 0
double t1, t2 ;
count_MatMul++ ;
MARKTIME(t1) ;
if ( bridge->myid == 0 ) {
fprintf(stdout, "\n (%d) MatMulMPI()", count_MatMul) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, "\n (%d) MatMulMPI()", count_MatMul) ;
fflush(bridge->msgFile) ;
#endif
nrows = *pnrows ;
ncols = *pncols ;
nent = nrows*ncols ;
if ( *pprbtype == 3 ) {
/*
--------------------------
... matrix is the identity
--------------------------
*/
if ( x == NULL ) {
fprintf(stderr, "\n\n fatal error in MatMulMPI, y <-- x, x is NULL") ;
exit(-1) ;
}
if ( y == NULL ) {
fprintf(stderr, "\n\n fatal error in MatMulMPI, y <-- x, y is NULL") ;
exit(-1) ;
}
DVcopy(nent, y, x) ;
return;
} else {
DenseMtx *Xloc = bridge->Xloc, *Yloc = bridge->Yloc ;
double alpha[2] = {1.0, 0.0} ;
FILE *msgFile = bridge->msgFile ;
int msglvl = bridge->msglvl, n, nmyowned, tag = 0 ;
int *list, *owned ;
int stats[4] ;
MPI_Comm comm = bridge->comm ;
/*
-----------------------------------------------
if the matrices are in global coordinates
(i.e., this is the first matrix-vector multiply
following a factorization) then
map the matrix into local coordinates
-----------------------------------------------
*/
if ( bridge->msglvl > 1 ) {
fprintf(bridge->msgFile,
"\n\n inside MatMulMPI, nrow = %d, ncol = %d",
nrows, ncols) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n\n bridge->coordFlag = %d", bridge->coordFlag) ;
fflush(msgFile) ;
}
if ( bridge->coordFlag == GLOBAL ) {
if ( bridge->prbtype == 1 ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n ready to permute B") ;
fflush(msgFile) ;
}
MatMul_setLocalIndices(bridge->info, bridge->B) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n matrix B in local coordinates") ;
InpMtx_writeForHumanEye(bridge->B, msgFile) ;
fflush(msgFile) ;
}
} else if ( bridge->prbtype == 2 ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n ready to permute A") ;
fflush(msgFile) ;
}
MatMul_setLocalIndices(bridge->info, bridge->A) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n matrix A in local coordinates") ;
InpMtx_writeForHumanEye(bridge->A, msgFile) ;
fflush(msgFile) ;
}
}
bridge->coordFlag = LOCAL ;
}
/*
--------------------------------------------------
check to see that Xloc and Yloc are the right size
--------------------------------------------------
*/
if ( Xloc->nrow != nrows ) {
fprintf(stderr,
"\n\n fatal error in MatMulMPI, nrows %d, Xloc->nrow %d",
nrows, Xloc->nrow) ;
exit(-1) ;
}
if ( Xloc->ncol != ncols ) {
IV_sizeAndEntries(bridge->myownedIV, &nmyowned, &owned) ;
DenseMtx_clearData(Xloc) ;
DenseMtx_init(Xloc, SPOOLES_REAL, 0, 0,
nmyowned, ncols, 1, nmyowned) ;
DenseMtx_rowIndices(Xloc, &n, &list) ;
IVcopy(n, list, owned) ;
DenseMtx_clearData(Yloc) ;
DenseMtx_init(Yloc, SPOOLES_REAL, 0, 0,
nmyowned, ncols, 1, nmyowned) ;
DenseMtx_rowIndices(Yloc, &n, &list) ;
IVcopy(n, list, owned) ;
}
/*
------------------
copy x[] into Xloc
------------------
*/
DVcopy(nent, DenseMtx_entries(Xloc), x) ;
/*
---------
zero Yloc
---------
*/
DenseMtx_zero(Yloc) ;
/*
----------------------------------------
compute the local matrix-vector multiply
----------------------------------------
*/
if ( *pprbtype == 1 ) {
IVzero(4, stats) ;
MatMul_MPI_mmm(bridge->info, Yloc, alpha, bridge->B,
Xloc, stats, msglvl, msgFile, tag, comm) ;
} else if ( *pprbtype == 2 ) {
IVzero(4, stats) ;
MatMul_MPI_mmm(bridge->info, Yloc, alpha, bridge->A,
Xloc, stats, msglvl, msgFile, tag, comm) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n after mvm, Yloc") ;
DenseMtx_writeForHumanEye(Yloc, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------------
copy entries of Yloc into y[]
-----------------------------
*/
if ( DenseMtx_entries(Yloc) == NULL ) {
fprintf(stderr,
"\n\n fatal error in MatMulMPI, y <-- Yloc, Yloc is NULL") ;
exit(-1) ;
}
if ( y == NULL ) {
fprintf(stderr, "\n\n fatal error in MatMulMPI, y <-- Yloc, y is NULL") ;
exit(-1) ;
}
DVcopy(nent, y, DenseMtx_entries(Yloc)) ;
}
#if MYDEBUG > 0
MARKTIME(t2) ;
time_MatMul += t2 - t1 ;
if ( bridge->myid == 0 ) {
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_MatMul) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_MatMul) ;
fflush(bridge->msgFile) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
Eigen/srcMPI/SetupMPI.c 0100644 0002055 0007177 00000036730 06636730130 0016104 0 ustar 00cleve compmath 0000040 0000006 /* SetupMPI.c */
#include "../BridgeMPI.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Setup = 0 ;
static double time_Setup = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose --
given InpMtx objects that contain A and B, initialize the bridge
data structure for the MPI factor's, solve's and mvm's.
NOTE: all the input arguments are pointers
to allow calls from Fortran
data -- pointer to a Bridge object
pprbtype -- pointer to value containing problem type
*prbtype = 1 --> A X = B X Lambda, vibration problem
*prbtype = 2 --> A X = B X Lambda, buckling problem
*prbtype = 3 --> A X = X Lambda, simple eigenvalue problem
pneqns -- pointer to value containing number of equations
pmxbsz -- pointer to value containing blocksize
A -- pointer to InpMtx object containing A
B -- pointer to InpMtx object containing B
pseed -- pointer to value containing a random number seed
pmsglvl -- pointer to value containing a message level
msgFile -- message file pointer
return value --
1 -- normal return
-1 -- data is NULL
-2 -- pprbtype is NULL
-3 -- *pprbtype is invalid
-4 -- pneqns is NULL
-5 -- *pneqns is invalid
-6 -- pmxbsz is NULL
-7 -- *pmxbsz is invalid
-8 -- A and B are NULL
-9 -- pseed is NULL
-10 -- pmsglvl is NULL
-11 -- *pmsglvl > 0 and msgFile is NULL
-12 -- comm is NULL
created -- 98aug10, cca
----------------------------------------------------------------
*/
int
SetupMPI (
void *data,
int *pprbtype,
int *pneqns,
int *pmxbsz,
InpMtx *A,
InpMtx *B,
int *pseed,
int *pmsglvl,
FILE *msgFile,
MPI_Comm comm
) {
BridgeMPI *bridge = (BridgeMPI *) data ;
double cutoff, minops ;
double *opcounts ;
double sigma[2] ;
DV *cumopsDV ;
Graph *graph ;
int maxdomainsize, maxsize, maxzeros, msglvl, myid, mxbsz,
nedges, neqns, nmyowned, nproc, prbtype, root, seed, tag ;
int stats[4] ;
IVL *adjIVL ;
#if MYDEBUG > 0
double t1, t2 ;
#endif
/*
---------------------------------
get number of processors and rank
---------------------------------
*/
MPI_Comm_rank(comm, &myid) ;
MPI_Comm_size(comm, &nproc) ;
#if MYDEBUG > 0
count_Setup++ ;
MARKTIME(t1) ;
if ( myid == 0 ) {
fprintf(stdout, "\n (%d) SetupMPI()", count_Setup) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, "\n (%d) SetupMPI()", count_Setup) ;
fflush(bridge->msgFile) ;
#endif
/*
--------------------
check the input data
--------------------
*/
if ( data == NULL ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n data is NULL\n") ;
return(-1) ;
}
if ( pprbtype == NULL ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n prbtype is NULL\n") ;
return(-2) ;
}
prbtype = *pprbtype ;
if ( prbtype < 1 || prbtype > 3 ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n prbtype = %d, is invalid\n", prbtype) ;
return(-3) ;
}
if ( pneqns == NULL ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n pneqns is NULL\n") ;
return(-4) ;
}
neqns = *pneqns ;
if ( neqns <= 0 ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n neqns = %d, is invalid\n", neqns) ;
return(-5) ;
}
if ( pmxbsz == NULL ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n pmxbsz is NULL\n") ;
return(-6) ;
}
mxbsz = *pmxbsz ;
if ( mxbsz <= 0 ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n *pmxbsz = %d, is invalid\n", mxbsz) ;
return(-7) ;
}
if ( A == NULL && B == NULL ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n A and B are NULL\n") ;
return(-8) ;
}
if ( pseed == NULL ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n pseed is NULL\n") ;
return(-9) ;
}
seed = *pseed ;
if ( pmsglvl == NULL ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n pmsglvl is NULL\n") ;
return(-10) ;
}
msglvl = *pmsglvl ;
if ( msglvl > 0 && msgFile == NULL ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n msglvl = %d, msgFile = NULL\n", msglvl) ;
return(-11) ;
}
if ( comm == NULL ) {
fprintf(stderr, "\n fatal error in SetupMPI()"
"\n comm = NULL\n") ;
return(-12) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n inside SetupMPI()"
"\n neqns = %d, prbtype = %d, mxbsz = %d, seed = %d",
neqns, prbtype, mxbsz, seed) ;
if ( A != NULL ) {
fprintf(msgFile, "\n\n matrix A") ;
InpMtx_writeForHumanEye(A, msgFile) ;
}
if ( B != NULL ) {
fprintf(msgFile, "\n\n matrix B") ;
InpMtx_writeForHumanEye(B, msgFile) ;
}
fflush(msgFile) ;
}
bridge->myid = myid ;
bridge->nproc = nproc ;
bridge->prbtype = prbtype ;
bridge->neqns = neqns ;
bridge->mxbsz = mxbsz ;
bridge->A = A ;
bridge->B = B ;
bridge->seed = seed ;
bridge->msglvl = msglvl ;
bridge->msgFile = msgFile ;
bridge->comm = comm ;
/*
------------------------------------
STEP 1: create and initialize pencil
------------------------------------
*/
sigma[0] = 1.0;
sigma[1] = 0.0;
bridge->pencil = Pencil_new() ;
Pencil_init(bridge->pencil, SPOOLES_REAL, SPOOLES_SYMMETRIC,
A, sigma, B) ;
/*
----------------------------------------
STEP 2: convert to row or column vectors
----------------------------------------
*/
if ( A != NULL ) {
if ( ! INPMTX_IS_BY_ROWS(A) && ! INPMTX_IS_BY_COLUMNS(A) ) {
InpMtx_changeCoordType(A, INPMTX_BY_ROWS) ;
}
if ( ! INPMTX_IS_BY_VECTORS(A) ) {
InpMtx_changeStorageMode(A, INPMTX_BY_VECTORS) ;
}
}
if ( B != NULL ) {
if ( ! INPMTX_IS_BY_ROWS(B) && ! INPMTX_IS_BY_COLUMNS(B) ) {
InpMtx_changeCoordType(B, INPMTX_BY_ROWS) ;
}
if ( ! INPMTX_IS_BY_VECTORS(B) ) {
InpMtx_changeStorageMode(B, INPMTX_BY_VECTORS) ;
}
}
/*
---------------------------------------
STEP 3: create a Graph object for A + B
---------------------------------------
*/
graph = Graph_new() ;
IVfill(4, stats, 0) ;
adjIVL = Pencil_MPI_fullAdjacency(bridge->pencil,
stats, msglvl, msgFile, comm);
nedges = IVL_tsize(adjIVL),
Graph_init2(graph, 0, bridge->neqns, 0, nedges,
bridge->neqns, nedges, adjIVL, NULL, NULL) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n graph of the input pencil") ;
fflush(msgFile) ;
}
/*
------------------------------------------------------------
STEP 4: order the graph. each processor orders the graph
independently. then the processors determine who
has the best ordering, and that ordering information
(contained in the FrontETree object) is broadcast
to all processors.
------------------------------------------------------------
*/
maxdomainsize = neqns / 64 ;
if ( maxdomainsize == 0 ) {
maxdomainsize = 1 ;
}
maxzeros = (int) (0.01*neqns) ;
maxsize = 64 ;
bridge->frontETree = orderViaBestOfNDandMS(graph, maxdomainsize,
maxzeros, maxsize, bridge->seed + myid,
msglvl, msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front tree from ordering") ;
fflush(msgFile) ;
}
Graph_free(graph) ;
opcounts = DVinit(nproc, 0.0) ;
opcounts[myid] = ETree_nFactorOps(bridge->frontETree,
SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n before gather \n" );
fflush(msgFile) ;
}
MPI_Allgather((void *) &opcounts[myid], 1, MPI_DOUBLE,
(void *) opcounts, 1, MPI_DOUBLE, comm) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n after gather \n" );
fflush(msgFile) ;
}
minops = DVmin(nproc, opcounts, &root) ;
root = 0 ;
DVfree(opcounts) ;
bridge->frontETree = ETree_MPI_Bcast(bridge->frontETree, root,
msglvl, msgFile, comm) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n best front tree") ;
ETree_writeForHumanEye(bridge->frontETree, msgFile) ;
fflush(msgFile) ;
}
/*
ETree_writeToFile(bridge->frontETree, "stk35.etreef") ;
*/
/*
------------------------------------------------------
STEP 5: get the old-to-new and new-to-old permutations
------------------------------------------------------
*/
bridge->oldToNewIV = ETree_oldToNewVtxPerm(bridge->frontETree) ;
bridge->newToOldIV = ETree_newToOldVtxPerm(bridge->frontETree) ;
IV_writeToFile(bridge->oldToNewIV, "oldToNew.ivf") ;
IV_writeToFile(bridge->newToOldIV, "newToOld.ivf") ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n old-to-new permutation") ;
fprintf(msgFile, "\n\n new-to-old permutation") ;
fflush(msgFile) ;
}
/*
----------------------------------------------
STEP 6: permute the vertices in the front tree
----------------------------------------------
*/
ETree_permuteVertices(bridge->frontETree, bridge->oldToNewIV) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n permuted front etree") ;
fflush(msgFile) ;
}
/*
------------------------------------------------------------
STEP 7: generate
(1) ownersIV -- the map from fronts to processors
(2) vtxmapIV -- the map from vertices to processors
(3) myownedIV -- vertices owned by this processor
------------------------------------------------------------
*/
cutoff = 1./(2*nproc) ;
cumopsDV = DV_new() ;
DV_init(cumopsDV, nproc, NULL) ;
bridge->ownersIV = ETree_ddMap(bridge->frontETree, SPOOLES_REAL,
SPOOLES_SYMMETRIC, cumopsDV, cutoff) ;
DV_free(cumopsDV) ;
bridge->vtxmapIV = IV_new() ;
IV_init(bridge->vtxmapIV, bridge->neqns, NULL) ;
IVgather(bridge->neqns, IV_entries(bridge->vtxmapIV),
IV_entries(bridge->ownersIV),
ETree_vtxToFront(bridge->frontETree)) ;
bridge->myownedIV = IV_targetEntries(bridge->vtxmapIV, myid) ;
nmyowned = IV_size(bridge->myownedIV) ;
bridge->rowmapIV = NULL ;
if ( msglvl > 0 ) {
fprintf(msgFile, "\n\n map from fronts to owning processes") ;
IV_writeForHumanEye(bridge->ownersIV, msgFile) ;
fprintf(msgFile, "\n\n map from vertices to owning processes") ;
IV_writeForHumanEye(bridge->vtxmapIV, msgFile) ;
fprintf(msgFile, "\n\n vertices owned by this process") ;
IV_writeForHumanEye(bridge->myownedIV, msgFile) ;
fflush(msgFile) ;
}
/*
IV_writeToFile(bridge->ownersIV, "owners.ivf") ;
Tree_writeToFile(bridge->frontETree->tree, "stk35.treef") ;
*/
/*
---------------------------------------------------
STEP 8: permute the entries in the pencil.
note, after the permutation the
entries are mapped into the upper triangle.
---------------------------------------------------
*/
Pencil_permute(bridge->pencil, bridge->oldToNewIV, bridge->oldToNewIV) ;
Pencil_mapToUpperTriangle(bridge->pencil) ;
Pencil_changeCoordType(bridge->pencil, INPMTX_BY_CHEVRONS) ;
Pencil_changeStorageMode(bridge->pencil, INPMTX_BY_VECTORS) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n permuted pencil") ;
fflush(msgFile) ;
}
tag = 0 ;
Pencil_MPI_split(bridge->pencil, bridge->vtxmapIV,
stats, msglvl, msgFile, tag, comm) ;
Pencil_changeCoordType(bridge->pencil, INPMTX_BY_CHEVRONS) ;
Pencil_changeStorageMode(bridge->pencil, INPMTX_BY_VECTORS) ;
bridge->A = A = bridge->pencil->inpmtxA ;
bridge->B = B = bridge->pencil->inpmtxB ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n permuted and split pencil") ;
fflush(msgFile) ;
}
/*
------------------------------------------
STEP 9: compute the symbolic factorization
------------------------------------------
*/
bridge->symbfacIVL = SymbFac_MPI_initFromPencil(bridge->frontETree,
bridge->ownersIV, bridge->pencil,
stats, msglvl, msgFile, tag, comm) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n symbolic factorization") ;
IVL_writeForHumanEye(bridge->symbfacIVL, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------------------------------------------
STEP 10: create a FrontMtx object to hold the factorization
-----------------------------------------------------------
*/
bridge->frontmtx = FrontMtx_new() ;
/*
---------------------------------------------------------------------
STEP 11: create a SubMtxManager object to hold the factor submatrices
---------------------------------------------------------------------
*/
bridge->mtxmanager = SubMtxManager_new() ;
SubMtxManager_init(bridge->mtxmanager, NO_LOCK, 0) ;
/*
---------------------------------------------
STEP 12: create a SolveMap object to hold the
map from submatrices to processes
---------------------------------------------
*/
bridge->solvemap = SolveMap_new() ;
/*
-----------------------------------
STEP 13: set up the distributed mvm
-----------------------------------
*/
bridge->coordFlag = GLOBAL ;
if ( *pprbtype == 3 ) {
/*
----------------------------------
matrix is the identity, do nothing
----------------------------------
*/
bridge->info = NULL ;
bridge->Xloc = NULL ;
bridge->Yloc = NULL ;
} else {
InpMtx *mtx ;
int n ;
int *list ;
/*
----------------------------------------------
generalized eigenvalue problem, find out which
matrix to use with the matrix-vector multiply
----------------------------------------------
*/
if ( *pprbtype == 1 ) {
mtx = B ;
} else if ( *pprbtype == 2 ) {
mtx = A ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n before MatMul_MPI_setup \n" );
fflush(msgFile) ;
}
bridge->info = MatMul_MPI_setup(mtx, SPOOLES_SYMMETRIC, MMM_WITH_A,
bridge->vtxmapIV, bridge->vtxmapIV,
stats, msglvl, msgFile, tag, comm) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n after MatMul_MPI_setup \n" );
fflush(msgFile) ;
}
/*
---------------------------------
set up the Xloc and Yloc matrices
---------------------------------
*/
if ( msglvl > 2 ) {
fprintf(msgFile, "\n SPOOLES_REAL = %d", SPOOLES_REAL) ;
fprintf(msgFile, "\n bridge->mxbsz = %d", bridge->mxbsz) ;
fprintf(msgFile, "\n initializing Xloc") ;
fflush(msgFile) ;
}
bridge->Xloc = DenseMtx_new() ;
DenseMtx_init(bridge->Xloc, SPOOLES_REAL, 0, 0,
nmyowned, bridge->mxbsz, 1, nmyowned) ;
DenseMtx_rowIndices(bridge->Xloc, &n, &list) ;
IVcopy(n, list, IV_entries(bridge->myownedIV)) ;
bridge->Yloc = DenseMtx_new() ;
DenseMtx_zero(bridge->Xloc) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n initializing Yloc") ;
fflush(msgFile) ;
}
DenseMtx_init(bridge->Yloc, SPOOLES_REAL, 0, 0,
nmyowned, bridge->mxbsz, 1, nmyowned) ;
DenseMtx_rowIndices(bridge->Yloc, &n, &list) ;
IVcopy(n, list, IV_entries(bridge->myownedIV)) ;
DenseMtx_zero(bridge->Yloc) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n initial Xloc matrix") ;
fprintf(msgFile, "\n\n initial Yloc matrix") ;
}
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n leaving SetupMPI()\n") ;
fflush(msgFile) ;
}
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Setup += t2 - t1 ;
if ( bridge->myid == 0 ) {
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Setup) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Setup) ;
fflush(bridge->msgFile) ;
#endif
return(1) ; }
/*--------------------------------------------------------------------*/
Eigen/srcMPI/SolveMPI.c 0100644 0002055 0007177 00000014402 06636772455 0016104 0 ustar 00cleve compmath 0000040 0000006 /* SolveMPI.c */
#include "../BridgeMPI.h"
#define MYDEBUG 1
#if MYDEBUG > 0
static int count_Solve = 0 ;
static double time_Solve = 0.0 ;
#endif
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
purpose -- to solve a linear system
(A - sigma*B) sol[] = rhs[]
data -- pointer to bridge data object
*pnrows -- # of rows in x[] and y[]
*pncols -- # of columns in x[] and y[]
rhs[] -- vector that holds right hand sides
sol[] -- vector to hold solutions
note: rhs[] and sol[] can be the same array.
on return, *perror holds an error code.
1 -- normal return
-1 -- pnrows is NULL
-2 -- pncols is NULL
-3 -- rhs is NULL
-4 -- sol is NULL
-5 -- data is NULL
created -- 98aug10, cca & jcp
----------------------------------------------
*/
void
SolveMPI (
int *pnrows,
int *pncols,
double rhs[],
double sol[],
void *data,
int *perror
) {
BridgeMPI *bridge = (BridgeMPI *) data ;
DenseMtx *rhsmtx ;
double cpus[20] ;
int nent, ncols, nrows, tag = 0 ;
int stats[8] ;
#if MYDEBUG > 0
double t1, t2 ;
count_Solve++ ;
MARKTIME(t1) ;
if ( bridge->myid == 0 ) {
fprintf(stdout, "\n (%d) SolveMPI()", count_Solve) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, "\n (%d) SolveMPI()", count_Solve) ;
fflush(bridge->msgFile) ;
#endif
/*
---------------
check the input
---------------
*/
if ( perror == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n perror == NULL\n") ;
return ;
}
if ( pnrows == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n pnrows == NULL\n") ;
*perror = -1 ; return ;
}
if ( pncols == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n pncols == NULL\n") ;
*perror = -2 ; return ;
}
if ( rhs == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n rhs == NULL\n") ;
*perror = -3 ; return ;
}
if ( sol == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n sol == NULL\n") ;
*perror = -4 ; return ;
}
if ( data == NULL ) {
fprintf(stderr, "\n error in Solve()"
"\n data == NULL\n") ;
*perror = -5 ; return ;
}
/*
----------------------------------
set the number of rows and columns
----------------------------------
*/
nrows = *pnrows ;
ncols = *pncols ;
nent = nrows*ncols ;
/*
---------------------------------
setup rhsmtx as a DenseMtx object
---------------------------------
*/
rhsmtx = DenseMtx_new() ;
DenseMtx_init(rhsmtx, SPOOLES_REAL, 0, 0, nrows, ncols, 1, nrows) ;
if ( rhs == NULL ) {
fprintf(stderr, "\n fatal error in SolveMPI, rhsmtx <-- rhs, rhs is NULL") ;
exit(-1) ;
}
if ( DenseMtx_entries(rhsmtx) == NULL ) {
fprintf(stderr,
"\n fatal error in SolveMPI, rhsmtx <-- rhs, rhsmtx is NULL") ;
exit(-1) ;
}
DVcopy (nent, DenseMtx_entries(rhsmtx), rhs) ;
IVcopy(nrows, rhsmtx->rowind, IV_entries(bridge->myownedIV)) ;
if ( bridge->msglvl > 2 && bridge->msgFile != NULL ) {
fprintf(bridge->msgFile, "\n\n rhsmtx initialized") ;
DenseMtx_writeForHumanEye(rhsmtx, bridge->msgFile) ;
fflush(bridge->msgFile) ;
}
if ( bridge->rowmapIV != NULL ) {
DenseMtx *newmtx ;
/*
--------------------------------
pivoting may have taken place,
redistribute the rows of the rhs
--------------------------------
*/
IVzero(4, stats) ;
newmtx = DenseMtx_MPI_splitByRows(rhsmtx, bridge->rowmapIV, stats,
bridge->msglvl, bridge->msgFile, tag, bridge->comm) ;
DenseMtx_free(rhsmtx) ;
rhsmtx = newmtx ;
if ( bridge->msglvl > 2 && bridge->msgFile != NULL ) {
fprintf(bridge->msgFile, "\n\n rhsmtx after redistribution") ;
DenseMtx_writeForHumanEye(rhsmtx, bridge->msgFile) ;
fflush(bridge->msgFile) ;
}
}
/*
-----------------------
solve the linear system
-----------------------
*/
IVzero(8, stats) ;
DVzero(20, cpus) ;
FrontMtx_MPI_solve(bridge->frontmtx, rhsmtx, rhsmtx, bridge->mtxmanager,
bridge->solvemap, cpus, stats, bridge->msglvl,
bridge->msgFile, tag, bridge->comm) ;
if ( bridge->msglvl > 2 && bridge->msgFile != NULL ) {
fprintf(bridge->msgFile,
"\n\n solution matrix after redistribution") ;
DenseMtx_writeForHumanEye(rhsmtx, bridge->msgFile) ;
fflush(bridge->msgFile) ;
}
if ( bridge->rowmapIV != NULL ) {
DenseMtx *newmtx ;
/*
-------------------------------------
pivoting may have taken place,
redistribute the rows of the solution
-------------------------------------
*/
newmtx = DenseMtx_MPI_splitByRows(rhsmtx, bridge->vtxmapIV, stats,
bridge->msglvl, bridge->msgFile, tag, bridge->comm) ;
DenseMtx_free(rhsmtx) ;
rhsmtx = newmtx ;
if ( bridge->msglvl > 2 && bridge->msgFile != NULL ) {
fprintf(bridge->msgFile,
"\n\n solution matrix after redistribution") ;
DenseMtx_writeForHumanEye(rhsmtx, bridge->msgFile) ;
fflush(bridge->msgFile) ;
}
}
/*
-----------------------------------
copy solution into output parameter
-----------------------------------
*/
if ( DenseMtx_entries(rhsmtx) == NULL ) {
fprintf(stderr,
"\n fatal error in SolveMPI, sol <-- rhsmtx, rhsmtx is NULL") ;
exit(-1) ;
}
if ( sol == NULL ) {
fprintf(stderr, "\n fatal error in SolveMPI, sol <-- rhsmtx, sol is NULL") ;
exit(-1) ;
}
DVcopy(nent, sol, DenseMtx_entries(rhsmtx)) ;
/*
------------------------
free the working storage
------------------------
*/
DenseMtx_free(rhsmtx) ;
/*
------------------------------------------------------------------
set the error. (this is simple since when the spooles codes detect
a fatal error, they print out a message to stderr and exit.)
------------------------------------------------------------------
*/
*perror = 0 ;
#if MYDEBUG > 0
MARKTIME(t2) ;
time_Solve += t2 - t1 ;
if ( bridge->myid == 0 ) {
fprintf(stdout, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Solve) ;
fflush(stdout) ;
}
#endif
#if MYDEBUG > 1
fprintf(bridge->msgFile, ", %8.3f seconds, %8.3f total time",
t2 - t1, time_Solve) ;
fflush(bridge->msgFile) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
Eigen/drivers/do_MPI_fiddle 0100755 0002055 0007177 00000000763 06636727161 0017166 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
set pgFile = spooles.pg
echo matrix3fiddle
uncompress < $MTX_DIR/matrix.fid.3A.Z > fort.37
uncompress < $MTX_DIR/matrix.fid.3B.Z > fort.38
set msglvl = 0
set msgFile = res.fiddle
set parmFile = fiddle.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.fiddle
/usr/local/mpi/bin/mpirun -p4pg $pgFile \
testMPI $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc* res.9*
Eigen/drivers/do_MPI_mtx10 0100755 0002055 0007177 00000000745 06636727166 0016715 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
set pgFile = spooles.pg
echo matrix10
uncompress < $MTX_DIR/matrix.10A.Z > fort.37
uncompress < $MTX_DIR/matrix.10B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx10
set parmFile = mtx10.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx10
/usr/local/mpi/bin/mpirun -p4pg $pgFile \
testMPI $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc* res.9*
Eigen/drivers/do_MPI_mtx3 0100755 0002055 0007177 00000000737 06636727033 0016631 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
set pgFile = spooles.pg
echo matrix3
uncompress < $MTX_DIR/matrix.3A.Z > fort.37
uncompress < $MTX_DIR/matrix.3B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx3
set parmFile = mtx3.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx3
/usr/local/mpi/bin/mpirun -p4pg $pgFile \
testMPI $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc* res.9*
Eigen/drivers/do_MPI_mtx4 0100755 0002055 0007177 00000000737 06636727175 0016641 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
set pgFile = spooles.pg
echo matrix4
uncompress < $MTX_DIR/matrix.4A.Z > fort.37
uncompress < $MTX_DIR/matrix.4B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx4
set parmFile = mtx4.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx4
/usr/local/mpi/bin/mpirun -p4pg $pgFile \
testMPI $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc* res.9*
Eigen/drivers/do_MPI_mtx5 0100755 0002055 0007177 00000000737 06636727202 0016631 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
set pgFile = spooles.pg
echo matrix5
uncompress < $MTX_DIR/matrix.5A.Z > fort.37
uncompress < $MTX_DIR/matrix.5B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx5
set parmFile = mtx5.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx5
/usr/local/mpi/bin/mpirun -p4pg $pgFile \
testMPI $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc* res.9*
Eigen/drivers/do_MPI_mtx6 0100755 0002055 0007177 00000000737 06636727207 0016637 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
set pgFile = spooles.pg
echo matrix6
uncompress < $MTX_DIR/matrix.6A.Z > fort.37
uncompress < $MTX_DIR/matrix.6B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx6
set parmFile = mtx6.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx6
/usr/local/mpi/bin/mpirun -p4pg $pgFile \
testMPI $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc* res.9*
Eigen/drivers/do_MPI_mtx7 0100755 0002055 0007177 00000000737 06636727214 0016636 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
set pgFile = spooles.pg
echo matrix7
uncompress < $MTX_DIR/matrix.7A.Z > fort.37
uncompress < $MTX_DIR/matrix.7B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx7
set parmFile = mtx7.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx7
/usr/local/mpi/bin/mpirun -p4pg $pgFile \
testMPI $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc* res.9*
Eigen/drivers/do_MPI_mtx8 0100755 0002055 0007177 00000000737 06636727220 0016634 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
set pgFile = spooles.pg
echo matrix8
uncompress < $MTX_DIR/matrix.8A.Z > fort.37
uncompress < $MTX_DIR/matrix.8B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx8
set parmFile = mtx8.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx8
/usr/local/mpi/bin/mpirun -p4pg $pgFile \
testMPI $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc* res.9*
Eigen/drivers/do_MPI_mtx9 0100755 0002055 0007177 00000000737 06636727226 0016643 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
set pgFile = spooles.pg
echo matrix9
uncompress < $MTX_DIR/matrix.9A.Z > fort.37
uncompress < $MTX_DIR/matrix.9B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx9
set parmFile = mtx9.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx9
/usr/local/mpi/bin/mpirun -p4pg $pgFile \
testMPI $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc* res.9*
Eigen/drivers/do_MPI_plat362 0100755 0002055 0007177 00000000703 06636727241 0017123 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
set pgFile = spooles.pg
echo plat362.mtx
uncompress < $MTX_DIR/plat362.mtx.Z > fort.37
set msglvl = 0
set msgFile = res.plat362
set parmFile = plat362.inp
set seed = 10
set inFileA = fort.37
set inFileB = none
set resFile = res.mtx.plat362
/usr/local/mpi/bin/mpirun -p4pg $pgFile \
testMPI $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc* res.9*
Eigen/drivers/do_MT_mtx10 0100755 0002055 0007177 00000000665 06636726262 0016605 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix10
uncompress < $MTX_DIR/matrix.10A.Z > fort.37
uncompress < $MTX_DIR/matrix.10B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx10
set parmFile = mtx10.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx10
set nthread = 4
testMT $msglvl $msgFile $parmFile $seed $nthread $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_MT_mtx3 0100755 0002055 0007177 00000000656 06636726271 0016527 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix3
uncompress < $MTX_DIR/matrix.3A.Z > fort.37
uncompress < $MTX_DIR/matrix.3B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx3
set parmFile = mtx3.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx3
set nthread = 4
testMT $msglvl $msgFile $parmFile $seed $nthread $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_MT_mtx4 0100755 0002055 0007177 00000000657 06636726276 0016536 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix4
uncompress < $MTX_DIR/matrix.4A.Z > fort.37
uncompress < $MTX_DIR/matrix.4B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx4
set parmFile = mtx4.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx4
set nthread = 4
testMT $msglvl $msgFile $parmFile $seed $nthread $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_MT_mtx5 0100755 0002055 0007177 00000000657 06636726304 0016527 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix5
uncompress < $MTX_DIR/matrix.5A.Z > fort.37
uncompress < $MTX_DIR/matrix.5B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx5
set parmFile = mtx5.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx5
set nthread = 4
testMT $msglvl $msgFile $parmFile $seed $nthread $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_MT_mtx6 0100755 0002055 0007177 00000000657 06636726311 0016526 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix6
uncompress < $MTX_DIR/matrix.6A.Z > fort.37
uncompress < $MTX_DIR/matrix.6B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx6
set parmFile = mtx6.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx6
set nthread = 4
testMT $msglvl $msgFile $parmFile $seed $nthread $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_MT_mtx7 0100755 0002055 0007177 00000000657 06636726317 0016535 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix7
uncompress < $MTX_DIR/matrix.7A.Z > fort.37
uncompress < $MTX_DIR/matrix.7B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx7
set parmFile = mtx7.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx7
set nthread = 4
testMT $msglvl $msgFile $parmFile $seed $nthread $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_MT_mtx8 0100755 0002055 0007177 00000000657 06636726324 0016534 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix8
uncompress < $MTX_DIR/matrix.8A.Z > fort.37
uncompress < $MTX_DIR/matrix.8B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx8
set parmFile = mtx8.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx8
set nthread = 4
testMT $msglvl $msgFile $parmFile $seed $nthread $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_MT_mtx9 0100755 0002055 0007177 00000000657 06636726332 0016534 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix9
uncompress < $MTX_DIR/matrix.9A.Z > fort.37
uncompress < $MTX_DIR/matrix.9B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx9
set parmFile = mtx9.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx9
set nthread = 4
testMT $msglvl $msgFile $parmFile $seed $nthread $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_MT_plat362 0100755 0002055 0007177 00000000623 06636726342 0017020 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo plat362.mtx
uncompress < $MTX_DIR/plat362.mtx.Z > fort.37
set msglvl = 0
set msgFile = res.plat362
set parmFile = plat362.inp
set seed = 10
set inFileA = fort.37
set inFileB = none
set resFile = res.mtx.plat362
set nthread = 4
testMT $msglvl $msgFile $parmFile $seed $nthread $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_MT_tests 0100755 0002055 0007177 00000004603 06632025671 0016762 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set TEST_DIR = ../../../inp
echo plat362.mtx
rm fort.*
uncompress < $TEST_DIR/plat362.mtx.Z > fort.37
cp $TEST_DIR/jcp.plat362.inp input.dat
testMT 0 junk stdout 10 3 3 fort.37 > res.mtx.plat362
echo matrices.3
rm fort.*
uncompress < $TEST_DIR/matrix.3A.Z > fort.37
uncompress < $TEST_DIR/matrix.3B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.3 input.dat
testMT 0 junk stdout 10 1 3 fort.37 fort.38 > res.mtx.3
echo matrices.4
rm fort.*
uncompress < $TEST_DIR/matrix.4A.Z > fort.37
uncompress < $TEST_DIR/matrix.4B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.4 input.dat
testMT 0 junk stdout 10 1 3 fort.37 fort.38 > res.mtx.4
echo matrices.5
rm fort.*
uncompress < $TEST_DIR/matrix.5A.Z > fort.37
uncompress < $TEST_DIR/matrix.5B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.5 input.dat
testMT 0 junk stdout 10 1 3 fort.37 fort.38 > res.mtx.5
echo matrices.6
rm fort.*
uncompress < $TEST_DIR/matrix.6A.Z > fort.37
uncompress < $TEST_DIR/matrix.6B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.6 input.dat
testMT 0 junk stdout 10 1 3 fort.37 fort.38 > res.mtx.6
echo matrices.7
rm fort.*
uncompress < $TEST_DIR/matrix.7A.Z > fort.37
uncompress < $TEST_DIR/matrix.7B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.7 input.dat
testMT 0 junk stdout 10 1 3 fort.37 fort.38 > res.mtx.7
echo matrices.8
rm fort.*
uncompress < $TEST_DIR/matrix.8A.Z > fort.37
uncompress < $TEST_DIR/matrix.8B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.8 input.dat
testMT 0 junk stdout 10 1 3 fort.37 fort.38 > res.mtx.8
echo matrices.9
rm fort.*
uncompress < $TEST_DIR/matrix.9A.Z > fort.37
uncompress < $TEST_DIR/matrix.9B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.9 input.dat
testMT 0 junk stdout 10 1 3 fort.37 fort.38 > res.mtx.9
echo matrices.10
rm fort.*
uncompress < $TEST_DIR/matrix.10A.Z > fort.37
uncompress < $TEST_DIR/matrix.10B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.10 input.dat
testMT 0 junk stdout 10 1 3 fort.37 fort.38 > res.mtx.10
echo matrices.11
rm fort.*
uncompress < $TEST_DIR/matrix.11A.Z > fort.37
uncompress < $TEST_DIR/matrix.11B.Z > fort.38
cp $TEST_DIR/jcp.inp.buck.11 input.dat
testMT 0 junk stdout 10 2 3 fort.37 fort.38 > res.mtx.11
echo matrices.3_fiddle
#rm fort.*
#uncompress < $TEST_DIR/matrix.fid.3A.Z > fort.37
#uncompress < $TEST_DIR/matrix.fid.3B.Z > fort.38
#cp $TEST_DIR/jcp.inp.buck.3fid input.dat
#testMT 0 junk stdout 10 2 3 fort.37 fort.38 > res.mtx.3_fiddle
quick_diff
rm -f fort.* junk* res* *.dat /tmp/*fil*
Eigen/drivers/do_ST_35 0100750 0002055 0007177 00000000352 06636253731 0016051 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set TEST_DIR = /scratch/pattersn/
echo bcsstk35.mtx
rm fort.*
cp $TEST_DIR/bcsstk35.mtx.rb fort.37
cp $TEST_DIR/bcsstm35.mtx.rb fort.38
cp input.dat.35 input.dat
time testSerial 0 stdout stdout 10 1 fort.37 fort.38
Eigen/drivers/do_ST_fiddle 0100755 0002055 0007177 00000000654 06636722635 0017067 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix3fiddle
uncompress < $MTX_DIR/matrix.fid.3A.Z > fort.37
uncompress < $MTX_DIR/matrix.fid.3B.Z > fort.38
set msglvl = 0
set msgFile = res.fiddle
set parmFile = fiddle.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.fiddle
testSerial $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_mtx10 0100755 0002055 0007177 00000000636 06636722651 0016607 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix10
uncompress < $MTX_DIR/matrix.10A.Z > fort.37
uncompress < $MTX_DIR/matrix.10B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx10
set parmFile = mtx10.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx10
testSerial $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_mtx3 0100755 0002055 0007177 00000000630 06636722657 0016531 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix3
uncompress < $MTX_DIR/matrix.3A.Z > fort.37
uncompress < $MTX_DIR/matrix.3B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx3
set parmFile = mtx3.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx3
testSerial $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_mtx4 0100755 0002055 0007177 00000000630 06636722665 0016531 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix4
uncompress < $MTX_DIR/matrix.4A.Z > fort.37
uncompress < $MTX_DIR/matrix.4B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx4
set parmFile = mtx4.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx4
testSerial $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_mtx5 0100755 0002055 0007177 00000000630 06636722674 0016532 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix5
uncompress < $MTX_DIR/matrix.5A.Z > fort.37
uncompress < $MTX_DIR/matrix.5B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx5
set parmFile = mtx5.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx5
testSerial $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_mtx6 0100755 0002055 0007177 00000000630 06636722702 0016523 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix6
uncompress < $MTX_DIR/matrix.6A.Z > fort.37
uncompress < $MTX_DIR/matrix.6B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx6
set parmFile = mtx6.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx6
testSerial $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_mtx7 0100755 0002055 0007177 00000000630 06636722710 0016523 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix7
uncompress < $MTX_DIR/matrix.7A.Z > fort.37
uncompress < $MTX_DIR/matrix.7B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx7
set parmFile = mtx7.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx7
testSerial $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_mtx8 0100755 0002055 0007177 00000000630 06636722715 0016531 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix8
uncompress < $MTX_DIR/matrix.8A.Z > fort.37
uncompress < $MTX_DIR/matrix.8B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx8
set parmFile = mtx8.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx8
testSerial $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_mtx9 0100755 0002055 0007177 00000000630 06636722723 0016531 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo matrix9
uncompress < $MTX_DIR/matrix.9A.Z > fort.37
uncompress < $MTX_DIR/matrix.9B.Z > fort.38
set msglvl = 0
set msgFile = res.mtx9
set parmFile = mtx9.inp
set seed = 10
set inFileA = fort.37
set inFileB = fort.38
set resFile = res.mtx9
testSerial $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_plat362 0100755 0002055 0007177 00000000574 06636722555 0017035 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /home/pattersn/LANCZOS/test/inp
echo plat362.mtx
uncompress < $MTX_DIR/plat362.mtx.Z > fort.37
set msglvl = 0
set msgFile = res.plat362
set parmFile = plat362.inp
set seed = 10
set inFileA = fort.37
set inFileB = none
set resFile = res.mtx.plat362
testSerial $msglvl $msgFile $parmFile $seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_stk35 0100755 0002055 0007177 00000000566 06636722734 0016613 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set MTX_DIR = /local1/cleve/ARPA/matrices/BCSSTK35
echo bcsstk35
set msglvl = 0
set msgFile = res.stk35
set parmFile = stk35.inp
set seed = 10
set inFileA = $MTX_DIR/bcsstk35.mtx.rb
set inFileB = $MTX_DIR/bcsstm35.mtx.rb
set resFile = res.stk35
testSerial $msglvl $msgFile $parmFile
$seed $inFileA $inFileB
rm fort.* lmq* lq* evc*
Eigen/drivers/do_ST_tests 0100755 0002055 0007177 00000004713 06636253705 0016777 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set TEST_DIR = ../../../inp
echo plat362.mtx
rm fort.*
uncompress < $TEST_DIR/plat362.mtx.Z > fort.37
cp $TEST_DIR/jcp.plat362.inp input.dat
testSerial 0 junk stdout 10 3 fort.37
exit
testSerial 0 junk stdout 10 3 fort.37 > res.mtx.plat362
echo matrices.3
rm fort.*
uncompress < $TEST_DIR/matrix.3A.Z > fort.37
uncompress < $TEST_DIR/matrix.3B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.3 input.dat
testSerial 0 junk stdout 10 1 fort.37 fort.38 > res.mtx.3
echo matrices.4
rm fort.*
uncompress < $TEST_DIR/matrix.4A.Z > fort.37
uncompress < $TEST_DIR/matrix.4B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.4 input.dat
testSerial 0 junk stdout 10 1 fort.37 fort.38 > res.mtx.4
echo matrices.5
rm fort.*
uncompress < $TEST_DIR/matrix.5A.Z > fort.37
uncompress < $TEST_DIR/matrix.5B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.5 input.dat
testSerial 0 junk stdout 10 1 fort.37 fort.38 > res.mtx.5
echo matrices.6
rm fort.*
uncompress < $TEST_DIR/matrix.6A.Z > fort.37
uncompress < $TEST_DIR/matrix.6B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.6 input.dat
testSerial 0 junk stdout 10 1 fort.37 fort.38 > res.mtx.6
echo matrices.7
rm fort.*
uncompress < $TEST_DIR/matrix.7A.Z > fort.37
uncompress < $TEST_DIR/matrix.7B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.7 input.dat
testSerial 0 junk stdout 10 1 fort.37 fort.38 > res.mtx.7
echo matrices.8
rm fort.*
uncompress < $TEST_DIR/matrix.8A.Z > fort.37
uncompress < $TEST_DIR/matrix.8B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.8 input.dat
testSerial 0 junk stdout 10 1 fort.37 fort.38 > res.mtx.8
echo matrices.9
rm fort.*
uncompress < $TEST_DIR/matrix.9A.Z > fort.37
uncompress < $TEST_DIR/matrix.9B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.9 input.dat
testSerial 0 junk stdout 10 1 fort.37 fort.38 > res.mtx.9
echo matrices.10
rm fort.*
uncompress < $TEST_DIR/matrix.10A.Z > fort.37
uncompress < $TEST_DIR/matrix.10B.Z > fort.38
cp $TEST_DIR/jcp.inp.vib.10 input.dat
testSerial 0 junk stdout 10 1 fort.37 fort.38 > res.mtx.10
echo matrices.11
rm fort.*
uncompress < $TEST_DIR/matrix.11A.Z > fort.37
uncompress < $TEST_DIR/matrix.11B.Z > fort.38
cp $TEST_DIR/jcp.inp.buck.11 input.dat
testSerial 0 junk stdout 10 2 fort.37 fort.38 > res.mtx.11
echo matrices.3_fiddle
#rm fort.*
#uncompress < $TEST_DIR/matrix.fid.3A.Z > fort.37
#uncompress < $TEST_DIR/matrix.fid.3B.Z > fort.38
#cp $TEST_DIR/jcp.inp.buck.3fid input.dat
#testSerial 0 junk stdout 10 2 fort.37 fort.38 > res.mtx.3_fiddle
quick_diff
rm -f fort.* junk* stdout /tmp/*fil* res* *.dat
Eigen/drivers/makefile 0100600 0002055 0007177 00000004013 06653142443 0016273 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
#
# set suffix rule *.c --> *.o
#
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $(MPI_INCLUDE_DIR) $<
#
#-----------------------------------------------------------------------
#
# redefine CC for mpi on sgi
#
# CCmpi = /opt/mpi/bin/mpicc
#
#-----------------------------------------------------------------------
F77 = f77
DRIVERS = testSerial testMT testMPI
#-----------------------------------------------------------------------
# environment on sparcstation 20
#
# locations of eigensolver libraries
#
LANCZOS_ST_LIB = /home/pattersn/LANCZOS/lib/Serial_lncz.a
LANCZOS_MT_LIB = /home/pattersn/LANCZOS/lib/MT_lncz.a
LANCZOS_MPI_LIB = /home/pattersn/LANCZOS/lib/MPI_lncz.a
#
# locations of spooles libraries
#
SPOOLES_DIR = ../..
SPOOLES_LIB = $(SPOOLES_DIR)/spooles.a
SPOOLES_MT_LIB = $(SPOOLES_DIR)/MT/src/spoolesMT.a
SPOOLES_MPI_LIB = $(SPOOLES_DIR)/MPI/src/spoolesMPI.a
#
# libraries needed for the eigensolver
#
LIBS_FOR_ST = $(LANCZOS_ST_LIB) ../srcST/Bridge.a $(SPOOLES_LIB) -lm
LIBS_FOR_MT = $(LANCZOS_MT_LIB) ../srcMT/BridgeMT.a \
$(SPOOLES_MT_LIB) $(SPOOLES_LIB) ${THREAD_LIBS} -lm
LIBS_FOR_MPI = $(LANCZOS_MPI_LIB) ../srcMPI/BridgeMPI.a \
$(SPOOLES_MPI_LIB) $(SPOOLES_LIB) ${MPI_LIBS} -lm
#-----------------------------------------------------------------------
#
# dependencies for Bridge objects
#
STlibs :
cd ../srcST ; make Bridge.a
MTlibs :
cd ../srcMT ; make BridgeMT.a
MPIlibs :
cd ../srcMPI ; make BridgeMPI.a
#-----------------------------------------------------------------------
all_drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
testSerial : testSerial.o STlibs ../../spooles.a
${PURIFY} ${F77} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS_FOR_ST}
testMT : testMT.o MTlibs ../../spooles.a
${PURIFY} ${F77} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS_FOR_MT}
testMPI : testMPI.o MPIlibs ../../spooles.a
${PURIFY} ${F77} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS_FOR_MPI}
Eigen/drivers/testMPI.c 0100755 0002055 0007177 00000027077 06636771277 0016334 0 ustar 00cleve compmath 0000040 0000006 /* testMPI.c */
#include "../BridgeMPI.h"
void JimMatMulMPI ( ) ;
void JimSolveMPI ( ) ;
/*--------------------------------------------------------------------*/
void main ( int argc, char *argv[] )
/*
-----------------------------------------------------------------
MPI environment: read in Harwell-Boeing matrices, using factor,
solve, and multiply routines based on spooles, invoke eigensolver
created -- 98mar31, jcp
modified -- 98dec18, cca
-----------------------------------------------------------------
*/
{
BridgeMPI bridge ;
MPI_Comm comm ;
char *inFileName_A, *inFileName_B, *parmFileName, *type ;
char buffer[20], pbtype[4], which[4] ;
int error, fstevl, lfinit, lstevl, msglvl, myid, mxbksz, ncol,
ndiscd, neig, neigvl, nfound, nnonzeros, nproc, nrhs, nrow,
prbtyp, rc, retc, rfinit, seed, warnng ;
int c__5 = 5, output = 6 ;
int *lanczos_wksp ;
InpMtx *inpmtxA, *inpmtxB ;
FILE *msgFile, *parmFile ;
double lftend, rhtend, center, shfscl, t1, t2 ;
double c__1 = 1.0, c__4 = 4.0, tolact = 2.309970868130169e-11 ;
double eigval[1000], sigma[2] ;
double *evec;
/*
---------------------------------------------------------------
find out the identity of this process and the number of process
---------------------------------------------------------------
*/
MPI_Init(&argc, &argv) ;
MPI_Comm_dup(MPI_COMM_WORLD, &comm) ;
MPI_Comm_rank(comm, &myid) ;
MPI_Comm_size(comm, &nproc) ;
fprintf(stdout, "\n myid = %d", myid) ;
fflush(stdout) ;
/*--------------------------------------------------------------------*/
/*
-----------------------------
decode the command line input
-----------------------------
*/
if ( argc != 7 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile parmFile seed inFileA inFileB"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n parmFile -- input parameters file"
"\n seed -- random number seed, used for ordering"
"\n inFileA -- stiffness matrix, in Harwell-Boeing format"
"\n inFileB -- mass matrix, in Harwell-Boeing format"
"\n used for prbtyp = 1 or 2"
"\n", argv[0]) ;
return ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else {
int length = strlen(argv[2]) + 1 + 4 ;
char *buffer = CVinit(length, '\0') ;
sprintf(buffer, "%s.%d", argv[2], myid) ;
if ( (msgFile = fopen(buffer, "w")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], buffer) ;
return ;
}
CVfree(buffer) ;
}
parmFileName = argv[3] ;
seed = atoi(argv[4]) ;
inFileName_A = argv[5] ;
inFileName_B = argv[6] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n message file -- %s"
"\n parameter file -- %s"
"\n stiffness matrix file -- %s"
"\n mass matrix file -- %s"
"\n random number seed -- %d"
"\n",
argv[0], msglvl, argv[2], parmFileName, inFileName_A,
inFileName_B, seed) ;
fflush(msgFile) ;
if ( strcmp(inFileName_A, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
/*--------------------------------------------------------------------*/
if ( myid == 0 ) {
/*
----------------------------------------------
processor zero reads in the matrix header info
----------------------------------------------
*/
MARKTIME(t1) ;
readHB_info(inFileName_A, &nrow, &ncol, &nnonzeros, &type, &nrhs) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in harwell-boeing header info",
t2 - t1) ;
fflush(msgFile) ;
}
MPI_Bcast((void *) &nrow, 1, MPI_INT, 0, MPI_COMM_WORLD) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
read in eigenvalue problem data
neigvl -- # of desired eigenvalues
which -- which eigenvalues to compute
'l' or 'L' lowest (smallest magnitude)
'h' or 'H' highest (largest magnitude)
'n' or 'N' nearest to central value
'c' or 'C' nearest to central value
'a' or 'A' all eigenvalues in interval
pbtype -- type of problem
'v' or 'V' generalized symmetric problem (K,M)
with M positive semidefinite (vibration problem)
'b' or 'B' generalized symmetric problem (K,K_s)
with K positive semidefinite
with K_s posibly indefinite (buckling problem)
'o' or 'O' ordinary symmetric eigenproblem
lfinit -- if true, lftend is restriction on lower bound of
eigenvalues. if false, no restriction on lower bound
lftend -- left endpoint of interval
rfinit -- if true, rhtend is restriction on upper bound of
eigenvalues. if false, no restriction on upper bound
rhtend -- right endpoint of interval
center -- center of interval
mxbksz -- upper bound on block size for Lanczos recurrence
shfscl -- shift scaling parameter, an estimate on the magnitude
of the smallest nonzero eigenvalues
---------------------------------------------------------------
*/
MARKTIME(t1) ;
parmFile = fopen(parmFileName, "r");
fscanf(parmFile, "%d %s %s %d %le %d %le %le %d %le",
&neigvl, which, pbtype, &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &mxbksz, &shfscl) ;
fclose(parmFile);
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in eigenvalue problem data",
t2 - t1) ;
fflush(msgFile) ;
/*
----------------------------------------
check and set the problem type parameter
----------------------------------------
*/
switch ( pbtype[1] ) {
case 'v' : case 'V' : prbtyp = 1 ; break ;
case 'b' : case 'B' : prbtyp = 2 ; break ;
case 'o' : case 'O' : prbtyp = 3 ; break ;
default :
fprintf(stderr, "\n invalid problem type %s", pbtype) ;
exit(-1) ;
}
/*
----------------------------
Initialize Lanczos workspace
----------------------------
*/
MARKTIME(t1) ;
lanczos_init_ ( &lanczos_wksp ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : initialize Lanczos workspace",
t2 - t1) ;
fflush(msgFile) ;
/*
----------------------------------
initialize communication structure
----------------------------------
*/
MARKTIME(t1) ;
lanczos_set_parm( &lanczos_wksp, "order-of-problem", &nrow, &retc );
lanczos_set_parm( &lanczos_wksp, "accuracy-tolerance", &tolact, &retc );
lanczos_set_parm( &lanczos_wksp, "max-block-size", &mxbksz, &retc );
lanczos_set_parm( &lanczos_wksp, "shift-scale", &shfscl, &retc );
lanczos_set_parm( &lanczos_wksp, "message_level", &msglvl, &retc );
lanczos_set_parm( &lanczos_wksp, "mpi-communicator", &comm, &retc );
lanczos_set_parm( &lanczos_wksp, "qfile-pathname", "lqfil", &retc );
lanczos_set_parm( &lanczos_wksp, "mqfil-pathname", "lmqfil", &retc );
lanczos_set_parm( &lanczos_wksp, "evfil-pathname", "evcfil", &retc );
MARKTIME(t2) ;
fprintf(msgFile,
"\n CPU %8.3f : init the lanczos communication structure",
t2 - t1) ;
fflush(msgFile) ;
/*--------------------------------------------------------------------*/
if ( myid == 0 ) {
/*
------------------------------------
processor zero reads in the matrices
------------------------------------
*/
MARKTIME(t1) ;
inpmtxA = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxA, inFileName_A ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in first matrix", t2 - t1) ;
fflush(msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n InpMtx A object after loading") ;
InpMtx_writeForHumanEye(inpmtxA, msgFile) ;
fflush(msgFile) ;
}
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__1, &retc );
if ( prbtyp != 3 ) {
if ( strcmp(inFileName_B, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
inpmtxB = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxB, inFileName_B ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in first matrix", t2 - t1) ;
fflush(msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n InpMtx B object after loading") ;
InpMtx_writeForHumanEye(inpmtxB, msgFile) ;
fflush(msgFile) ;
}
} else {
inpmtxB = NULL ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__4, &retc );
}
} else {
/*
------------------------------------------------
other processors initialize their local matrices
------------------------------------------------
*/
inpmtxA = InpMtx_new() ;
InpMtx_init(inpmtxA, INPMTX_BY_CHEVRONS, SPOOLES_REAL, 0, 0) ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__1, &retc );
if ( prbtyp == 1 || prbtyp == 2 ) {
inpmtxB = InpMtx_new() ;
InpMtx_init(inpmtxB, INPMTX_BY_CHEVRONS, SPOOLES_REAL, 0, 0) ;
} else {
inpmtxB = NULL ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__4, &retc );
}
}
/*
-----------------------------
set up the solver environment
-----------------------------
*/
MARKTIME(t1) ;
rc = SetupMPI((void *) &bridge, &prbtyp, &nrow, &mxbksz, inpmtxA,
inpmtxB, &seed, &msglvl, msgFile, MPI_COMM_WORLD) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set up solver environment", t2 - t1) ;
fflush(msgFile) ;
if ( rc != 1 ) {
fprintf(stderr, "\n fatal error return %d from SetupMPI()", rc) ;
MPI_Finalize() ;
exit(-1) ;
}
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
invoke eigensolver
nfound -- # of eigenvalues found and kept
ndisc -- # of additional eigenvalues discarded
-----------------------------------------------
*/
MARKTIME(t1) ;
lanczos_run ( &neigvl, &which[1] , &pbtype[1], &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &lanczos_wksp, &bridge, &nfound,
&ndiscd, &warnng, &error, FactorMPI, JimMatMulMPI,
JimSolveMPI ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : time for lanczos run", t2 - t1) ;
fflush(msgFile) ;
if ( myid == 0 ) {
/*
----------------------------------------------
processor 0 deals with eigenvalues and vectors
----------------------------------------------
*/
MARKTIME(t1) ;
neig = nfound + ndiscd ;
lstevl = nfound ;
lanczos_eigenvalues (&lanczos_wksp, eigval, &neig, &retc);
fstevl = 1 ;
if ( nfound == 0 ) fstevl = -1 ;
if ( ndiscd > 0 ) lstevl = -ndiscd ;
hdslp5_ ("computed eigenvalues returned by hdserl",
&neig, eigval, &output, 39L ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvalues",
t2 - t1) ;
fflush(msgFile) ;
/*
-------------------------
get eigenvectors and print
-------------------------
*/
/*
MARKTIME(t1) ;
neig = min ( 50, nrow );
Lncz_ALLOCATE(evec, double, nrow, retc);
for (i = 1; i<= nfound; i++) {
lanczos_eigenvector(&lanczos_wksp, &i, &i, newToOld,
evec, &nrow, &retc) ;
hdslp5_("computed eigenvector returned by hdserc",
&neig, evec, &output, 39L ) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvectors",
t2 - t1) ;
fflush(msgFile) ;
*/
}
/*
------------------------
free the working storage
------------------------
*/
MARKTIME(t1) ;
lanczos_free(&lanczos_wksp) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free lanczos workspace", t2 - t1) ;
fflush(msgFile) ;
MARKTIME(t1) ;
CleanupMPI(&bridge) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free solver workspace", t2 - t1) ;
fflush(msgFile) ;
MPI_Finalize() ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return ; }
Eigen/drivers/testMT.c 0100644 0002055 0007177 00000023435 06636726214 0016205 0 ustar 00cleve compmath 0000040 0000006 /* testMT.c */
#include "../BridgeMT.h"
void FactorMT ( ) ;
void MatMulMT ( ) ;
void SolveMT ( ) ;
/*--------------------------------------------------------------------*/
void main ( int argc, char *argv[] )
/*
----------------------------------------------------------------
read in Harwell-Boeing matrices, using multithreaded factor,
solve, and multiply routines based on spooles, invoke eigensolver
created -- 98mar31, jcp
modified -- 98dec18, cca
----------------------------------------------------------------
*/
{
BridgeMT bridge ;
char *inFileName_A, *inFileName_B, *parmFileName, *type ;
char buffer[20], pbtype[4], which[4] ;
double lftend, rhtend, center, shfscl, t1, t2 ;
double c__1 = 1.0, c__4 = 4.0, tolact = 2.309970868130169e-11 ;
double eigval[1000], sigma[2];
double *evec;
int error, fstevl, lfinit, lstevl, msglvl, mxbksz, ncol, ndiscd,
neig, neigvl, nfound, nnonzeros, nrhs, nrow, nthreads,
prbtyp, rc, retc, rfinit, seed, warnng ;
int c__5 = 5, output = 6 ;
int *lanczos_wksp;
InpMtx *inpmtxA, *inpmtxB ;
FILE *msgFile, *parmFile ;
/*--------------------------------------------------------------------*/
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile parmFile seed nthread inFileA inFileB"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n parmFile -- input parameters file"
"\n seed -- random number seed, used for ordering"
"\n nthreads -- number of threads "
"\n inFileA -- stiffness matrix, in Harwell-Boeing format"
"\n inFileB -- mass matrix, in Harwell-Boeing format"
"\n used for prbtype = 1 or 2"
"\n", argv[0]) ;
return ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n able to open file %s\n", argv[0], argv[2]) ;
exit(-1) ;
}
parmFileName = argv[3] ;
seed = atoi(argv[4]) ;
nthreads = atoi(argv[5]) ;
inFileName_A = argv[6] ;
inFileName_B = argv[7] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n message file -- %s"
"\n parameter file -- %s"
"\n stiffness matrix file -- %s"
"\n mass matrix file -- %s"
"\n random number seed -- %d"
"\n number of threads -- %d"
"\n",
argv[0], msglvl, argv[2], parmFileName, inFileName_A,
inFileName_B, seed, nthreads) ;
fflush(msgFile) ;
/*
---------------------------------------------
read in the Harwell-Boeing matrix information
---------------------------------------------
*/
if ( strcmp(inFileName_A, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
readHB_info (inFileName_A, &nrow, &ncol, &nnonzeros, &type, &nrhs) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in harwell-boeing header info",
t2 - t1) ;
fflush(msgFile) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
read in eigenvalue problem data
neigvl -- # of desired eigenvalues
which -- which eigenvalues to compute
'l' or 'L' lowest (smallest magnitude)
'h' or 'H' highest (largest magnitude)
'n' or 'N' nearest to central value
'c' or 'C' nearest to central value
'a' or 'A' all eigenvalues in interval
pbtype -- type of problem
'v' or 'V' generalized symmetric problem (K,M)
with M positive semidefinite (vibration problem)
'b' or 'B' generalized symmetric problem (K,K_s)
with K positive semidefinite
with K_s posibly indefinite (buckling problem)
'o' or 'O' ordinary symmetric eigenproblem
lfinit -- if true, lftend is restriction on lower bound of
eigenvalues. if false, no restriction on lower bound
lftend -- left endpoint of interval
rfinit -- if true, rhtend is restriction on upper bound of
eigenvalues. if false, no restriction on upper bound
rhtend -- right endpoint of interval
center -- center of interval
mxbksz -- upper bound on block size for Lanczos recurrence
shfscl -- shift scaling parameter, an estimate on the magnitude
of the smallest nonzero eigenvalues
---------------------------------------------------------------
*/
MARKTIME(t1) ;
parmFile = fopen(parmFileName, "r");
fscanf(parmFile, "%d %s %s %d %le %d %le %le %d %le",
&neigvl, which, pbtype, &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &mxbksz, &shfscl) ;
fclose(parmFile);
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in eigenvalue problem data",
t2 - t1) ;
fflush(msgFile) ;
/*
----------------------------------------
check and set the problem type parameter
----------------------------------------
*/
switch ( pbtype[1] ) {
case 'v' :
case 'V' :
prbtyp = 1 ;
break ;
case 'b' :
case 'B' :
prbtyp = 2 ;
break ;
case 'o' :
case 'O' :
prbtyp = 3 ;
break ;
default :
fprintf(stderr, "\n invalid problem type %s", pbtype) ;
exit(-1) ;
}
/*
----------------------------
Initialize Lanczos workspace
----------------------------
*/
MARKTIME(t1) ;
lanczos_init_ ( &lanczos_wksp ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : initialize Lanczos workspace",
t2 - t1) ;
fflush(msgFile) ;
/*
----------------------------------
initialize communication structure
----------------------------------
*/
MARKTIME(t1) ;
lanczos_set_parm( &lanczos_wksp, "order-of-problem", &nrow, &retc );
lanczos_set_parm( &lanczos_wksp, "accuracy-tolerance", &tolact, &retc);
lanczos_set_parm( &lanczos_wksp, "max-block-size", &mxbksz, &retc );
lanczos_set_parm( &lanczos_wksp, "shift-scale", &shfscl, &retc );
lanczos_set_parm( &lanczos_wksp, "message_level", &msglvl, &retc );
lanczos_set_parm( &lanczos_wksp, "number-of-threads", &nthreads, &retc);
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : init lanczos communication structure",
t2 - t1) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
create the InpMtx objects for matrix A and B
---------------------------------------------
*/
if ( strcmp(inFileName_A, "none") == 0 ) {
fprintf(msgFile, "\n no file to read A from") ;
exit(-1) ;
}
MARKTIME(t1) ;
inpmtxA = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxA, inFileName_A ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in A", t2 - t1) ;
fflush(msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n InpMtx A object after loading") ;
InpMtx_writeForHumanEye(inpmtxA, msgFile) ;
fflush(msgFile) ;
}
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__1, &retc );
if ( prbtyp != 3 ) {
if ( strcmp(inFileName_B, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
inpmtxB = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxB, inFileName_B ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in B", t2 - t1) ;
fflush(msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n InpMtx B object after loading") ;
InpMtx_writeForHumanEye(inpmtxB, msgFile) ;
fflush(msgFile) ;
}
} else {
inpmtxB = NULL ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__4, &retc );
}
/*
-----------------------------
set up the solver environment
-----------------------------
*/
MARKTIME(t1) ;
rc = SetupMT((void *) &bridge, &prbtyp, &nrow, &mxbksz, inpmtxA,
inpmtxB, &seed, &nthreads, &msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set up the solver environment",
t2 - t1) ;
fflush(msgFile) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error return %d from SetupMT()", rc) ;
exit(-1) ;
}
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
invoke eigensolver
nfound -- # of eigenvalues found and kept
ndisc -- # of additional eigenvalues discarded
-----------------------------------------------
*/
MARKTIME(t1) ;
lanczos_run ( &neigvl, &which[1] , &pbtype[1], &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &lanczos_wksp, &bridge, &nfound,
&ndiscd, &warnng, &error, FactorMT, MatMulMT, SolveMT ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : time for lanczos_run", t2 - t1) ;
fflush(msgFile) ;
/*
-------------------------
get eigenvalues and print
-------------------------
*/
MARKTIME(t1) ;
neig = nfound + ndiscd ;
lstevl = nfound ;
lanczos_eigenvalues (&lanczos_wksp, eigval, &neig, &retc);
fstevl = 1 ;
if ( nfound == 0 ) fstevl = -1 ;
if ( ndiscd > 0 ) lstevl = -ndiscd ;
hdslp5_ ("computed eigenvalues returned by hdserl",
&neig, eigval, &output, 39L ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvalues", t2 - t1) ;
fflush(msgFile) ;
/*
-------------------------
get eigenvectors and print
-------------------------
*/
/*
MARKTIME(t1) ;
neig = min ( 50, nrow );
Lncz_ALLOCATE(evec, double, nrow, retc);
for (i = 1; i<= nfound; i++) {d
lanczos_eigenvector ( &lanczos_wksp, &i, &i, newToOld,
evec, &nrow, &retc ) ;
hdslp5_ ( "computed eigenvector returned by hdserc",
&neig, evec, &output, 39L ) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvectors", t2 - t1) ;
fflush(msgFile) ;
*/
/*
------------------------
free the working storage
------------------------
*/
MARKTIME(t1) ;
lanczos_free( &lanczos_wksp ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free lanczos workspace", t2 - t1) ;
fflush(msgFile) ;
MARKTIME(t1) ;
CleanupMT(&bridge) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free solver workspace", t2 - t1) ;
fflush(msgFile) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return ; }
Eigen/drivers/testSerial.c 0100644 0002055 0007177 00000023205 06636761001 0017070 0 ustar 00cleve compmath 0000040 0000006 /* testSerial.c */
#include "../Bridge.h"
void Factor ( ) ;
void MatMul ( ) ;
void Solve ( ) ;
/*--------------------------------------------------------------------*/
void main ( int argc, char *argv[] )
/*
----------------------------------------------------------
read in Harwell-Boeing matrices, use serial factor, solve,
and multiply routines based on spooles, invoke eigensolver
created -- 98mar31 jcp
modified -- 98dec18, cca
----------------------------------------------------------
*/
{
Bridge bridge ;
char *inFileName_A, *inFileName_B, *outFileName,
*parmFileName, *type ;
char buffer[20], pbtype[4], which[4] ;
double lftend, rhtend, center, shfscl, t1, t2 ;
double c__1 = 1.0, c__4 = 4.0, tolact = 2.309970868130169e-11 ;
double eigval[1000], sigma[2];
double *evec;
int error, fstevl, lfinit, lstevl, mxbksz, msglvl, ncol, ndiscd,
neig, neigvl, nfound, nnonzeros, nrhs, nrow, prbtyp, rc,
retc, rfinit, seed, warnng ;
int c__5 = 5, output = 6 ;
int *lanczos_wksp;
InpMtx *inpmtxA, *inpmtxB ;
FILE *msgFile, *parmFile;
/*--------------------------------------------------------------------*/
if ( argc != 7 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile parmFile seed inFileA inFileB"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n parmFile -- input parameters file"
"\n seed -- random number seed, used for ordering"
"\n inFileA -- stiffness matrix in Harwell-Boeing format"
"\n inFileB -- mass matrix in Harwell-Boeing format"
"\n used for prbtyp = 1 or 2"
"\n", argv[0]) ;
return ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
exit(-1) ;
}
parmFileName = argv[3] ;
seed = atoi(argv[4]) ;
inFileName_A = argv[5] ;
inFileName_B = argv[6] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n parmFile -- %s"
"\n seed -- %d"
"\n stiffness file -- %s"
"\n mass file -- %s"
"\n",
argv[0], msglvl, argv[2], parmFileName, seed,
inFileName_A, inFileName_B) ;
fflush(msgFile) ;
/*
---------------------------------------------
read in the Harwell-Boeing matrix information
---------------------------------------------
*/
if ( strcmp(inFileName_A, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
readHB_info (inFileName_A, &nrow, &ncol, &nnonzeros, &type, &nrhs) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in header information for A",
t2 - t1) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
read in eigenvalue problem data
neigvl -- # of desired eigenvalues
which -- which eigenvalues to compute
'l' or 'L' lowest (smallest magnitude)
'h' or 'H' highest (largest magnitude)
'n' or 'N' nearest to central value
'c' or 'C' nearest to central value
'a' or 'A' all eigenvalues in interval
pbtype -- type of problem
'v' or 'V' generalized symmetric problem (K,M)
with M positive semidefinite (vibration problem)
'b' or 'B' generalized symmetric problem (K,K_s)
with K positive semidefinite
with K_s posibly indefinite (buckling problem)
'o' or 'O' ordinary symmetric eigenproblem
lfinit -- if true, lftend is restriction on lower bound of
eigenvalues. if false, no restriction on lower bound
lftend -- left endpoint of interval
rfinit -- if true, rhtend is restriction on upper bound of
eigenvalues. if false, no restriction on upper bound
rhtend -- right endpoint of interval
center -- center of interval
mxbksz -- upper bound on block size for Lanczos recurrence
shfscl -- shift scaling parameter, an estimate on the magnitude
of the smallest nonzero eigenvalues
---------------------------------------------------------------
*/
MARKTIME(t1) ;
parmFile = fopen(parmFileName, "r");
fscanf(parmFile, "%d %s %s %d %le %d %le %le %d %le",
&neigvl, which, pbtype, &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &mxbksz, &shfscl) ;
fclose(parmFile);
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in eigenvalue problem data",
t2 - t1) ;
/*
----------------------------------------
check and set the problem type parameter
----------------------------------------
*/
switch ( pbtype[1] ) {
case 'v' : case 'V' : prbtyp = 1 ; break ;
case 'b' : case 'B' : prbtyp = 2 ; break ;
case 'o' : case 'O' : prbtyp = 3 ; break ;
default :
fprintf(stderr, "\n invalid problem type %s", pbtype) ;
exit(-1) ;
}
/*
----------------------------
Initialize Lanczos workspace
----------------------------
*/
MARKTIME(t1) ;
lanczos_init_ ( &lanczos_wksp ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : initialize lanczos workspace",
t2 - t1) ;
/*
----------------------------------
initialize communication structure
----------------------------------
*/
MARKTIME(t1) ;
lanczos_set_parm( &lanczos_wksp, "order-of-problem", &nrow, &retc );
lanczos_set_parm( &lanczos_wksp, "accuracy-tolerance", &tolact, &retc );
lanczos_set_parm( &lanczos_wksp, "max-block-size", &mxbksz, &retc );
lanczos_set_parm( &lanczos_wksp, "shift-scale", &shfscl, &retc );
lanczos_set_parm( &lanczos_wksp, "message_level", &msglvl, &retc );
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : init lanczos communication structure",
t2 - t1) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
create the InpMtx objects for matrix A and B
---------------------------------------------
*/
if ( strcmp(inFileName_A, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
inpmtxA = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxA, inFileName_A ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in A", t2 - t1) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n InpMtx A object after loading") ;
InpMtx_writeForHumanEye(inpmtxA, msgFile) ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__1, &retc );
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set A's parameters", t2 - t1) ;
if ( prbtyp != 3 ) {
if ( strcmp(inFileName_B, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
inpmtxB = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxB, inFileName_B ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in B", t2 - t1) ;
} else {
MARKTIME(t1) ;
inpmtxB = NULL ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__4, &retc );
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set B's parameters", t2 - t1) ;
}
if ( msglvl > 2 && prbtyp != 3 ) {
fprintf(msgFile, "\n\n InpMtx B object after loading") ;
InpMtx_writeForHumanEye(inpmtxB, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------------
set up the solver environment
-----------------------------
*/
MARKTIME(t1) ;
rc = Setup((void *) &bridge, &prbtyp, &nrow, &mxbksz, inpmtxA, inpmtxB,
&seed, &msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set up solver environment", t2 - t1) ;
if ( rc != 1 ) {
fprintf(stderr, "\n fatal error %d from Setup()", rc) ;
exit(-1) ;
}
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
invoke eigensolver
nfound -- # of eigenvalues found and kept
ndisc -- # of additional eigenvalues discarded
-----------------------------------------------
*/
MARKTIME(t1) ;
lanczos_run(&neigvl, &which[1] , &pbtype[1], &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &lanczos_wksp, &bridge, &nfound,
&ndiscd, &warnng, &error, Factor, MatMul, Solve ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : time for lanczos run", t2 - t1) ;
/*
-------------------------
get eigenvalues and print
-------------------------
*/
MARKTIME(t1) ;
neig = nfound + ndiscd ;
lstevl = nfound ;
lanczos_eigenvalues (&lanczos_wksp, eigval, &neig, &retc);
fstevl = 1 ;
if ( nfound == 0 ) fstevl = -1 ;
if ( ndiscd > 0 ) lstevl = -ndiscd ;
hdslp5_ ("computed eigenvalues returned by hdserl",
&neig, eigval, &output, 39L ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvalues ", t2 - t1) ;
/*
-------------------------
get eigenvectors and print
-------------------------
*/
/*
MARKTIME(t1) ;
neig = min ( 50, nrow );
Lncz_ALLOCATE(evec, double, nrow, retc);
for ( i = 1 ; i <= nfound ; i++ ) {
lanczos_eigenvector ( &lanczos_wksp, &i, &i, newToOld,
evec, &nrow, &retc ) ;
hdslp5_ ( "computed eigenvector returned by hdserc",
&neig, evec, &output, 39L ) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvectors ", t2 - t1) ;
*/
/*
------------------------
free the working storage
------------------------
*/
MARKTIME(t1) ;
lanczos_free( &lanczos_wksp ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free lanczos workspace ", t2 - t1) ;
MARKTIME(t1) ;
rc = Cleanup(&bridge) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free solver workspace ", t2 - t1) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error return %d from Cleanup()", rc) ;
exit(-1) ;
}
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return ; }
-------------------------------------*/
void main ( int argc, char *argv[] )
/*
----------------------------------------------------------
read in Harwell-Boeing matrices, use serial factor, solve,
and multiply routines based on spooles, invoke eigensolver
created -- 98mar31 jcp
modified -- 98dec18, cca
-----------------------------------------------------Eigen/drivers/fiddle.inp 0100644 0002055 0007177 00000000061 06636521604 0016542 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'b' 0 0.0e0 0 1.e20 0. 5 0.87332995124806
Eigen/drivers/mtx10.inp 0100644 0002055 0007177 00000000060 06636521520 0016260 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'v' 0 0.0e0 0 1.e20 0. 5 9.5636564981352
Eigen/drivers/mtx11.inp 0100644 0002055 0007177 00000000060 06636521543 0016266 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'v' 0 0.0e0 0 1.e20 0. 5 99447.067288973
Eigen/drivers/mtx3.inp 0100644 0002055 0007177 00000000062 06636520070 0016203 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'v' 0 0.0e0 0 1.e20 0. 5 0.87332995124806
Eigen/drivers/mtx4.inp 0100644 0002055 0007177 00000000066 06636520723 0016215 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'v' 0 0.0e0 0 1.e20 0. 5 5.3746168051265e-04
Eigen/drivers/mtx5.inp 0100644 0002055 0007177 00000000061 06636521075 0016212 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'v' 0 0.0e0 0 1.e20 0. 5 387589.03033154
Eigen/drivers/mtx6.inp 0100644 0002055 0007177 00000000060 06636521255 0016212 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'v' 0 0.0e0 0 1.e20 0. 5 79.625527957362
Eigen/drivers/mtx7.inp 0100644 0002055 0007177 00000000060 06636521373 0016214 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'v' 0 0.0e0 0 1.e20 0. 5 46.834305149396
Eigen/drivers/mtx8.inp 0100644 0002055 0007177 00000000060 06636521454 0016215 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'v' 0 0.0e0 0 1.e20 0. 5 4.8004558690386
Eigen/drivers/mtx9.inp 0100644 0002055 0007177 00000000060 06636521501 0016207 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'v' 0 0.0e0 0 1.e20 0. 5 2.7403158577391
Eigen/drivers/plat362.inp 0100644 0002055 0007177 00000000054 06636516414 0016513 0 ustar 00cleve compmath 0000040 0000006 10 'l' 'o' 1 2.5e-5 1 2.4e-2 0. 2 2.0364e-5
Eigen/drivers/stk35.inp 0100644 0002055 0007177 00000000050 06636522323 0016261 0 ustar 00cleve compmath 0000040 0000006 100 'l' 'v' 0 0.0e0 0 1.e20 0. 5 19.349
Eigen/drivers/spooles.pg 0100755 0002055 0007177 00000000374 06636547544 0016644 0 ustar 00cleve compmath 0000040 0000006 chinacat 0 /local1/cleve/ARPA/release2.1/Eigen/drivers/testMPI
chinacat 1 /local1/cleve/ARPA/release2.1/Eigen/drivers/testMPI
chinacat 1 /local1/cleve/ARPA/release2.1/Eigen/drivers/testMPI
chinacat 1 /local1/cleve/ARPA/release2.1/Eigen/drivers/testMPI
Eigen/doc/ 0042755 0002055 0007177 00000000000 06653150726 0013704 5 ustar 00cleve compmath 0000040 0000006 Eigen/doc/MPI.tex 0100644 0002055 0007177 00000047434 06636775375 0015100 0 ustar 00cleve compmath 0000040 0000006 \chapter{The MPI Bridge Object and Driver}
\label{chapter:MPI}
\par
\section{The \texttt{BridgeMPI} Data Structure}
\label{section:BridgeMPI:dataStructure}
\par
The {\tt BridgeMPI} structure has the following fields.
\begin{itemize}
%
\item
{\tt int prbtype} : problem type
\begin{itemize}
\item {\tt 1} --- vibration, a multiply with $B$ is required.
\item {\tt 2} --- buckling, a multiply with $A$ is required.
\item {\tt 3} --- simple, no multiply is required.
\end{itemize}
\item
{\tt int neqns} : number of equations,
i.e., number of vertices in the graph.
\item
{\tt int mxbsz} : block size for the Lanczos process.
\item
{\tt int nproc} : number of processors.
\item
{\tt int myid} : id (rank) of this processor.
\item
{\tt int seed} : random number seed used in the ordering.
\item
{\tt int coordFlag} : coordinate flag for local $A$ and $B$ matrices.
\begin{itemize}
\item 1 ({\tt LOCAL}) for local indices, needed for matrix-multiplies.
\item 2 ({\tt GLOBAL}) for global indices, needed for factorizations.
\end{itemize}
\item
{\tt InpMtx *A} : matrix object for $A$
\item
{\tt InpMtx *B} : matrix object for $B$
\item
{\tt Pencil *pencil} : object to hold linear combination of $A$ and $B$.
\item
{\tt ETree *frontETree} : object that defines the factorizations,
e.g., the number of fronts, the tree they form, the number of
internal and external rows for each front, and the map from
vertices to the front where it is contained.
\item
{\tt IVL *symbfacIVL} : object that contains the symbolic
factorization of the matrix.
\item
{\tt SubMtxManager *mtxmanager} : object that manages the
\texttt{SubMtx} objects that store the factor entries and are used
in the solves.
\item
{\tt FrontMtx *frontmtx} : object that stores the $L$, $D$ and $U$
factor matrices.
\item
{\tt IV *oldToNewIV} : object that stores old-to-new permutation vector.
\item
{\tt IV *newToOldIV} : object that stores new-to-old permutation vector.
\item
{\tt DenseMtx *Xloc} : dense {\it local} matrix object that is used
during the matrix multiples and solves.
\item
{\tt DenseMtx *Yloc} : dense {\it local} matrix object that is used
during the matrix multiples and solves.
\item
{\tt IV *vtxmapIV} : object that maps vertices to owning processors
for the factorization and matrix-multiplies.
\item
{\tt IV *myownedIV} : object that contains a list of all vertices
owned by this processor.
\item
{\tt IV *ownersIV} : object that maps fronts to owning processors
for the factorization and matrix-multiplies.
\item
{\tt IV *rowmapIV} : if pivoting was performed for numerical
stability, this object maps rows of the factor to processors.
\item
{\tt SolveMap *solvemap} : object that maps factor submatrices to
owning threads for the solve.
\item
{\tt MatMulInfo *info} : object that holds all the communication
information for a distributed matrix-multiply.
\item
{\tt int msglvl} : message level for output.
When 0, no output, When 1, just statistics and cpu times.
When greater than 1, more and more output.
\item
{\tt FILE *msgFile} : message file for output.
When \texttt{msglvl} $>$ 0, \texttt{msgFile} must not be \texttt{NULL}.
\item
{\tt MPI\_Comm comm} : MPI communicator.
\end{itemize}
\par
\section{Prototypes and descriptions of \texttt{BridgeMPI} methods}
\label{section:BridgeMPI:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt BridgeMPI} object.
\par
In contrast to the serial and MT bridge objects, there are seven
methods instead of five.
In a distributed environment, data structures should be partitioned
across processors.
On the {\bf SPOOLES} side, the factor entries, and the $X$ and $Y$
matrices that take part in the solves and matrix-multiplies, are
partitioned among the processors according to the ``front structure''
and vertex map of the factor matrices.
The {\bf SPOOLES} solve and matrix-multiply bridge methods expect
the {\it local} $X$ and $Y$ matrices.
On the {\bf LANCZOS} side, the Krylov blocks and eigenvectors are
partitioned across processors in a simple block manner.
(The first of $p$ processors has the first $n/p$ rows, etc.)
\par
At the present time, the {\bf SPOOLES} and {\bf LANCZOS} software
have no agreement on how the data should be partitioned.
(For example, {\bf SPOOLES} could tell {\bf LANCZOS} how it wants
the data to be partitioned,
or {\bf LANCZOS} could tell {\bf SPOOLES} how it wants
the data to be partitioned.)
Therefore, inside the {\bf LANCZOS} software a global Krylov block
is assembled on each processor prior to calling the solve or
matrix-multiply methods.
To ``translate'' between the global blocks to local blocks, and
then back to global blocks, we have written two wrapper methods,
{\tt JimMatMulMPI()} and {\tt JimSolveMPI()}.
Each takes the global input block, compresses it into a local
block, call the bridge matrix-multiply or solve method,
then takes the local output blocks and gathers them on all the
processors into each of their global output blocks.
These operations add a considerable cost to the solve and
matrix-multiplies, but the next release of the {\bf LANCZOS}
software will remove these steps.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int SetupMPI ( void *data, int *pprbtype, int *pneqns,
int *pmxbsz, InpMtx *A, InpMtx *B, int *pseed,
int *pmsglvl, FILE *msgFile, MPI_Comm comm ) ;
\end{verbatim}
\index{SetupMPI@{\tt SetupMPI()}}
\noindent All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt void *data} --- a pointer to the {\tt BridgeMPI} object.
\item {\tt int *pprbtype} --- {\tt *pprbtype} holds the problem type.
\begin{itemize}
\item {\tt 1} --- vibration, a multiply with $B$ is required.
\item {\tt 2} --- buckling, a multiply with $A$ is required.
\item {\tt 3} --- simple, no multiply is required.
\end{itemize}
\item {\tt int *pneqns} --- {\tt *pneqns} is the number of equations.
\item {\tt int *pmxbsz} --- {\tt *pmxbsz} is an upper bound on the
block size.
\item {\tt InpMtx *A} --- {\tt A} is a {\bf SPOOLES} object that
holds the matrix $A$.
\item {\tt InpMtx *B} --- {\tt B} is a {\bf SPOOLES} object that
holds the matrix $B$. For an ordinary eigenproblem, $B$ is the
identity and {\tt B} is {\tt NULL}.
\item {\tt int *pseed} --- {\tt *pseed} is a random number seed.
\item {\tt int *pmsglvl} --- {\tt *pmsglvl} is a message level for
the bridge methods and the {\bf SPOOLES} methods they call.
\item {\tt FILE *pmsglvl} --- {\tt msgFile} is the message file
for the bridge methods and the {\bf SPOOLES} methods they call.
\item {\tt MPI\_Comm comm} --- MPI communicator.
matrix-multiplies.
\end{itemize}
This method must be called in the driver program prior to invoking
the eigensolver via a call to {\tt lanczos\_run()}.
It then follows this sequence of action.
\begin{itemize}
\item
The method begins by checking all the input data,
and setting the appropriate fields of the {\tt BridgeMPI} object.
\item
The {\tt pencil} object is initialized with {\tt A} and {\tt B}.
\item
{\tt A} and {\tt B} are converted to storage by rows and vector mode.
\item
A {\tt Graph} object is created that contains the sparsity pattern of
the union of {\tt A} and {\tt B}.
\item
The graph is ordered by first finding a recursive dissection partition,
and then evaluating the orderings produced by nested dissection and
multisection, and choosing the better of the two.
The {\tt frontETree} object is produced and placed into the {\tt bridge}
object.
\item
Old-to-new and new-to-old permutations are extracted from the front tree
and loaded into the {\tt BridgeMPI} object.
\item
The vertices in the front tree are permuted, as well as the entries in
{\tt A} and {\tt B}.
Entries in the lower triangle of {\tt A} and {\tt B} are mapped into the
upper triangle, and the storage modes of {\tt A} and {\tt B} are changed
to chevrons and vectors, in preparation for the first factorization.
\item
The {\tt ownersIV}, {\tt vtxmapIV} and {\tt myownedIV} objects are
created, that map fronts and vertices to processors.
\item
The entries in {\tt A} and {\tt B} are permuted.
Entries in the permuted lower triangle are mapped into the upper
triangle.
The storage modes of {\tt A} and {\tt B} are changed
to chevrons and vectors,
and the entries of {\tt A} and {\tt B} are redistributed to the
processors that own them.
\item
The symbolic factorization is then computed and loaded in the {\tt
BridgeMPI} object.
\item
A {\tt FrontMtx} object is created to hold the factorization
and loaded into the {\tt BridgeMPI} object.
\item
A {\tt SubMtxManager} object is created to hold the factor's
submatrices and loaded into the {\tt BridgeMPI} object.
\item
The map from factor submatrices to their owning threads
is computed and stored in the {\tt solvemap} object.
\item
The distributed matrix-multiplies are set up.
\end{itemize}
The {\tt A} and {\tt B} matrices are now in their permuted ordering,
i.e., $PAP^T$ and $PBP^T$, and all data structures are with respect to
this ordering. After the Lanczos run completes, any generated
eigenvectors must be permuted back into their original ordering using
the {\tt oldToNewIV} and {\tt newToOldIV} objects.
\par \noindent {\it Return value:}
\begin{center}
\begin{tabular}[t]{rl}
~1 & normal return \\
-1 & \texttt{data} is \texttt{NULL} \\
-2 & \texttt{pprbtype} is \texttt{NULL} \\
-3 & \texttt{*pprbtype} is invalid \\
-4 & \texttt{pneqns} is \texttt{NULL} \\
-5 & \texttt{*pneqns} is invalid \\
-6 & \texttt{pmxbsz} is \texttt{NULL}
\end{tabular}
\begin{tabular}[t]{rl}
-7 & \texttt{*pmxbsz} is invalid \\
-8 & \texttt{A} and \texttt{B} are \texttt{NULL} \\
-9 & \texttt{seed} is \texttt{NULL} \\
-10 & \texttt{msglvl} is \texttt{NULL} \\
-11 & $\texttt{msglvl} > 0$ and \texttt{msgFile} is \texttt{NULL} \\
-12 & \texttt{comm} is \texttt{NULL}
\end{tabular}
\end{center}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FactorMPI ( double *psigma, double *ppvttol, void *data,
int *pinertia, int *perror ) ;
\end{verbatim}
\index{FactorMPI@{\tt FactorMPI()}}
This method computes the factorization of $A - \sigma B$.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt double *psigma} --- the shift parameter $\sigma$ is
found in {\tt *psigma}.
\item {\tt double *ppvttol} --- the pivot tolerance is
found in {\tt *ppvttol}. When ${\tt *ppvttol} = 0.0$,
the factorization is computed without pivoting for stability.
When ${\tt *ppvttol} > 0.0$, the factorization is computed
with pivoting for stability, and all offdiagonal entries
have magnitudes bounded above by $1/({\tt *ppvttol})$.
\item {\tt void *data} --- a pointer to the {\tt BridgeMPI} object.
\item {\tt int *pinertia} --- on return, {\tt *pinertia} holds the
number of negative eigenvalues.
\item {\tt int *perror} --- on return, {\tt *perror} holds an
error code.
\begin{center}
\begin{tabular}[t]{rl}
~1 & error in the factorization \\
~0 & normal return \\
-1 & \texttt{psigma} is \texttt{NULL}
\end{tabular}
\begin{tabular}[t]{rl}
-2 & \texttt{ppvttol} is \texttt{NULL} \\
-3 & \texttt{data} is \texttt{NULL} \\
-4 & \texttt{pinertia} is \texttt{NULL}
\end{tabular}
\end{center}
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void JimMatMulMPI ( int *pnrows, int *pncols, double X[], double Y[],
int *pprbtype, void *data ) ;
\end{verbatim}
\index{JimMatMulMPI@{\tt JimMatMulMPI()}}
This method computes a multiply of the form $Y = I X$, $Y = A X$
or $Y = B X$.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt int *pnrows} --- {\tt *pnrows} contains the number of
{\it global} rows in $X$ and $Y$.
\item {\tt int *pncols} --- {\tt *pncols} contains the number of
{\it global} columns in $X$ and $Y$.
\item {\tt double X[]} --- this is the {\it global} $X$ matrix,
stored column major with leading dimension {\tt *pnrows}.
\item {\tt double Y[]} --- this is the {\it global} $Y$ matrix,
stored column major with leading dimension {\tt *pnrows}.
\item {\tt int *pprbtype} --- {\tt *pprbtype} holds the problem type.
\begin{itemize}
\item {\tt 1} --- vibration, a multiply with $B$ is required.
\item {\tt 2} --- buckling, a multiply with $A$ is required.
\item {\tt 3} --- simple, no multiply is required.
\end{itemize}
\item {\tt void *data} --- a pointer to the {\tt BridgeMPI} object.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void MatMulMPI ( int *pnrows, int *pncols, double X[], double Y[],
int *pprbtype, void *data ) ;
\end{verbatim}
\index{MatMulMPI@{\tt MatMulMPI()}}
This method computes a multiply of the form $Y = I X$, $Y = A X$
or $Y = B X$.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt int *pnrows} --- {\tt *pnrows} contains the number of
{\it local} rows in $X$ and $Y$.
\item {\tt int *pncols} --- {\tt *pncols} contains the number of
{\it local} columns in $X$ and $Y$.
\item {\tt double X[]} --- this is the {\it local} $X$ matrix,
stored column major with leading dimension {\tt *pnrows}.
\item {\tt double Y[]} --- this is the {\it local} $Y$ matrix,
stored column major with leading dimension {\tt *pnrows}.
\item {\tt int *pprbtype} --- {\tt *pprbtype} holds the problem type.
\begin{itemize}
\item {\tt 1} --- vibration, a multiply with $B$ is required.
\item {\tt 2} --- buckling, a multiply with $A$ is required.
\item {\tt 3} --- simple, no multiply is required.
\end{itemize}
\item {\tt void *data} --- a pointer to the {\tt BridgeMPI} object.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void JimSolveMPI ( int *pnrows, int *pncols, double X[], double Y[],
void *data, int *perror ) ;
\end{verbatim}
\index{JimSolveMPI@{\tt JimSolveMPI()}}
This method solves $(A - \sigma B) X = Y$, where
$(A - \sigma B)$ has been factored by a previous call to {\tt Factor()}.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt int *pnrows} --- {\tt *pnrows} contains the number of
{\it global} rows in $X$ and $Y$.
\item {\tt int *pncols} --- {\tt *pncols} contains the number of
{\it global} columns in $X$ and $Y$.
\item {\tt double X[]} --- this is the {\it global} $X$ matrix,
stored column major with leading dimension {\tt *pnrows}.
\item {\tt double Y[]} --- this is the {\it global} $Y$ matrix,
stored column major with leading dimension {\tt *pnrows}.
\item {\tt void *data} --- a pointer to the {\tt BridgeMPI} object.
\item {\tt int *perror} --- on return, {\tt *perror} holds an
error code.
\begin{center}
\begin{tabular}[t]{rl}
~1 & normal return \\
-1 & \texttt{pnrows} is \texttt{NULL} \\
-2 & \texttt{pncols} is \texttt{NULL}
\end{tabular}
\begin{tabular}[t]{rl}
-3 & \texttt{X} is \texttt{NULL} \\
-4 & \texttt{Y} is \texttt{NULL} \\
-5 & \texttt{data} is \texttt{NULL}
\end{tabular}
\end{center}
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void SolveMPI ( int *pnrows, int *pncols, double X[], double Y[],
void *data, int *perror ) ;
\end{verbatim}
\index{SolveMPI@{\tt SolveMPI()}}
This method solves $(A - \sigma B) X = Y$, where
$(A - \sigma B)$ has been factored by a previous call to {\tt Factor()}.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt int *pnrows} --- {\tt *pnrows} contains the number of
{\it local} rows in $X$ and $Y$.
\item {\tt int *pncols} --- {\tt *pncols} contains the number of
{\it local} columns in $X$ and $Y$.
\item {\tt double X[]} --- this is the {\it local} $X$ matrix,
stored column major with leading dimension {\tt *pnrows}.
\item {\tt double Y[]} --- this is the {\it local} $Y$ matrix,
stored column major with leading dimension {\tt *pnrows}.
\item {\tt void *data} --- a pointer to the {\tt BridgeMPI} object.
\item {\tt int *perror} --- on return, {\tt *perror} holds an
error code.
\begin{center}
\begin{tabular}[t]{rl}
~1 & normal return \\
-1 & \texttt{pnrows} is \texttt{NULL} \\
-2 & \texttt{pncols} is \texttt{NULL}
\end{tabular}
\begin{tabular}[t]{rl}
-3 & \texttt{X} is \texttt{NULL} \\
-4 & \texttt{Y} is \texttt{NULL} \\
-5 & \texttt{data} is \texttt{NULL}
\end{tabular}
\end{center}
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int CleanupMPI ( void *data ) ;
\end{verbatim}
\index{CleanupMPI@{\tt CleanupMPI()}}
This method releases all the storage used by the {\bf SPOOLES}
library functions.
\par \noindent {\it Return value:}
1 for a normal return,
-1 if a {\tt data} is {\tt NULL}.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\section{The \texttt{testMPI} Driver Program}
\label{section:BridgeMPI:driver}
\par
A complete listing of the multithreaded driver program is
found in chapter~\ref{chapter:MPI_driver}.
The program is invoked by this command sequence.
\begin{verbatim}
testMPI msglvl msgFile parmFile seed inFileA inFileB
\end{verbatim}
where
\begin{itemize}
\item
{\tt msglvl} is the message level for the {\tt BridgeMPI}
methods and the {\bf SPOOLES} software.
\item
{\tt msgFile} is the message file for the {\tt BridgeMPI}
methods and the {\bf SPOOLES} software.
\item
{\tt parmFile} is the input file for the parameters of the
eigensystem to be solved.
\item
{\tt seed} is a random number seed
used by the {\bf SPOOLES} software.
\item
{\tt inFileA} is the Harwell-Boeing file for the matrix $A$.
\item
{\tt inFileB} is the Harwell-Boeing file for the matrix $B$.
\end{itemize}
This program is executed for some sample matrices by the
{\tt do\_ST\_*} shell scripts in the {\tt drivers} directory.
\par
Here is a short description of the steps in the driver program.
See Chapter~\ref{chapter:serial_driver} for the listing.
\begin{enumerate}
\item
Each processor determines the number of processors and its rank.
\item
Each processor decodes the command line inputs.
\item
Processor {\tt 0} reads the
header of the Harwell-Boeing file for $A$
and broadcasts the number of equations to all processors.
\item
Each processor reads from the {\tt parmFile} file
the parameters that define the eigensystem to be solved.
\item
Each processor initializes its Lanczos eigensolver workspace.
\item
Each processor fills its
Lanczos communication structure with some parameters.
\item
Processor {\tt 0} reads in the $A$ and possibly $B$ matrices from the
Harwell-Boeing files and converts them into {\tt InpMtx} objects
from the {\bf SPOOLES} library.
The other processors initialize their local {\tt InpMtx} objects.
\item
Each processor initializes its linear solver environment
via a call to {\tt SetupMPI()}.
\item
Each processor invokes
the eigensolver via a call to {\tt lanczos\_run()}.
The {\tt FactorMPI()}, {\tt JimSolveMPI()}
and {\tt JimMatMulMPI()} methods are passed to this routine.
\item
Processor zero extracts the eigenvalues via a call to
{\tt lanczos\_eigenvalues()} and prints them out.
\item
Processor zero extracts the eigenvectors via a call to
{\tt lanczos\_eigenvectors()} and prints them out.
\item
Each processor free's
the eigensolver working storage via a call to {\tt lanczos\_free()}.
\item
Each processor free's
the linear solver working storage via a call to {\tt CleanupMPI()}.
\end{enumerate}
d{tabular}
\end{center}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FactorMPI ( double *psigma, double *ppvttol, void *data,
int *pinertia, int *perror ) Eigen/doc/MPI_driver.tex 0100644 0002055 0007177 00000027256 06636771640 0016442 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt testMPI.c} --- A MPI Driver Program}
\label{chapter:MPI_driver}
\begin{verbatim}
/* testMPI.c */
#include "../BridgeMPI.h"
void JimMatMulMPI ( ) ;
void JimSolveMPI ( ) ;
/*--------------------------------------------------------------------*/
void main ( int argc, char *argv[] )
/*
-----------------------------------------------------------------
MPI environment: read in Harwell-Boeing matrices, using factor,
solve, and multiply routines based on spooles, invoke eigensolver
created -- 98mar31, jcp
modified -- 98dec18, cca
-----------------------------------------------------------------
*/
{
BridgeMPI bridge ;
MPI_Comm comm ;
char *inFileName_A, *inFileName_B, *parmFileName, *type ;
char buffer[20], pbtype[4], which[4] ;
int error, fstevl, lfinit, lstevl, msglvl, myid, mxbksz, ncol,
ndiscd, neig, neigvl, nfound, nnonzeros, nproc, nrhs, nrow,
prbtyp, rc, retc, rfinit, seed, warnng ;
int c__5 = 5, output = 6 ;
int *lanczos_wksp ;
InpMtx *inpmtxA, *inpmtxB ;
FILE *msgFile, *parmFile ;
double lftend, rhtend, center, shfscl, t1, t2 ;
double c__1 = 1.0, c__4 = 4.0, tolact = 2.309970868130169e-11 ;
double eigval[1000], sigma[2] ;
double *evec;
/*
---------------------------------------------------------------
find out the identity of this process and the number of process
---------------------------------------------------------------
*/
MPI_Init(&argc, &argv) ;
MPI_Comm_dup(MPI_COMM_WORLD, &comm) ;
MPI_Comm_rank(comm, &myid) ;
MPI_Comm_size(comm, &nproc) ;
fprintf(stdout, "\n myid = %d", myid) ;
fflush(stdout) ;
/*--------------------------------------------------------------------*/
/*
-----------------------------
decode the command line input
-----------------------------
*/
if ( argc != 7 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile parmFile seed inFileA inFileB"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n parmFile -- input parameters file"
"\n seed -- random number seed, used for ordering"
"\n inFileA -- stiffness matrix, in Harwell-Boeing format"
"\n inFileB -- mass matrix, in Harwell-Boeing format"
"\n used for prbtyp = 1 or 2"
"\n", argv[0]) ;
return ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else {
int length = strlen(argv[2]) + 1 + 4 ;
char *buffer = CVinit(length, '\0') ;
sprintf(buffer, "%s.%d", argv[2], myid) ;
if ( (msgFile = fopen(buffer, "w")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], buffer) ;
return ;
}
CVfree(buffer) ;
}
parmFileName = argv[3] ;
seed = atoi(argv[4]) ;
inFileName_A = argv[5] ;
inFileName_B = argv[6] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n message file -- %s"
"\n parameter file -- %s"
"\n stiffness matrix file -- %s"
"\n mass matrix file -- %s"
"\n random number seed -- %d"
"\n",
argv[0], msglvl, argv[2], parmFileName, inFileName_A,
inFileName_B, seed) ;
fflush(msgFile) ;
if ( strcmp(inFileName_A, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
/*--------------------------------------------------------------------*/
if ( myid == 0 ) {
/*
----------------------------------------------
processor zero reads in the matrix header info
----------------------------------------------
*/
MARKTIME(t1) ;
readHB_info(inFileName_A, &nrow, &ncol, &nnonzeros, &type, &nrhs) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in harwell-boeing header info",
t2 - t1) ;
fflush(msgFile) ;
}
MPI_Bcast((void *) &nrow, 1, MPI_INT, 0, MPI_COMM_WORLD) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
read in eigenvalue problem data
neigvl -- # of desired eigenvalues
which -- which eigenvalues to compute
'l' or 'L' lowest (smallest magnitude)
'h' or 'H' highest (largest magnitude)
'n' or 'N' nearest to central value
'c' or 'C' nearest to central value
'a' or 'A' all eigenvalues in interval
pbtype -- type of problem
'v' or 'V' generalized symmetric problem (K,M)
with M positive semidefinite (vibration problem)
'b' or 'B' generalized symmetric problem (K,K_s)
with K positive semidefinite
with K_s posibly indefinite (buckling problem)
'o' or 'O' ordinary symmetric eigenproblem
lfinit -- if true, lftend is restriction on lower bound of
eigenvalues. if false, no restriction on lower bound
lftend -- left endpoint of interval
rfinit -- if true, rhtend is restriction on upper bound of
eigenvalues. if false, no restriction on upper bound
rhtend -- right endpoint of interval
center -- center of interval
mxbksz -- upper bound on block size for Lanczos recurrence
shfscl -- shift scaling parameter, an estimate on the magnitude
of the smallest nonzero eigenvalues
---------------------------------------------------------------
*/
MARKTIME(t1) ;
parmFile = fopen(parmFileName, "r");
fscanf(parmFile, "%d %s %s %d %le %d %le %le %d %le",
&neigvl, which, pbtype, &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &mxbksz, &shfscl) ;
fclose(parmFile);
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in eigenvalue problem data",
t2 - t1) ;
fflush(msgFile) ;
/*
----------------------------------------
check and set the problem type parameter
----------------------------------------
*/
switch ( pbtype[1] ) {
case 'v' : case 'V' : prbtyp = 1 ; break ;
case 'b' : case 'B' : prbtyp = 2 ; break ;
case 'o' : case 'O' : prbtyp = 3 ; break ;
default :
fprintf(stderr, "\n invalid problem type %s", pbtype) ;
exit(-1) ;
}
/*
----------------------------
Initialize Lanczos workspace
----------------------------
*/
MARKTIME(t1) ;
lanczos_init_ ( &lanczos_wksp ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : initialize Lanczos workspace",
t2 - t1) ;
fflush(msgFile) ;
/*
----------------------------------
initialize communication structure
----------------------------------
*/
MARKTIME(t1) ;
lanczos_set_parm( &lanczos_wksp, "order-of-problem", &nrow, &retc );
lanczos_set_parm( &lanczos_wksp, "accuracy-tolerance", &tolact, &retc );
lanczos_set_parm( &lanczos_wksp, "max-block-size", &mxbksz, &retc );
lanczos_set_parm( &lanczos_wksp, "shift-scale", &shfscl, &retc );
lanczos_set_parm( &lanczos_wksp, "message_level", &msglvl, &retc );
lanczos_set_parm( &lanczos_wksp, "mpi-communicator", &comm, &retc );
lanczos_set_parm( &lanczos_wksp, "qfile-pathname", "lqfil", &retc );
lanczos_set_parm( &lanczos_wksp, "mqfil-pathname", "lmqfil", &retc );
lanczos_set_parm( &lanczos_wksp, "evfil-pathname", "evcfil", &retc );
MARKTIME(t2) ;
fprintf(msgFile,
"\n CPU %8.3f : init the lanczos communication structure",
t2 - t1) ;
fflush(msgFile) ;
/*--------------------------------------------------------------------*/
if ( myid == 0 ) {
/*
------------------------------------
processor zero reads in the matrices
------------------------------------
*/
MARKTIME(t1) ;
inpmtxA = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxA, inFileName_A ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in first matrix", t2 - t1) ;
fflush(msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n InpMtx A object after loading") ;
InpMtx_writeForHumanEye(inpmtxA, msgFile) ;
fflush(msgFile) ;
}
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__1, &retc );
if ( prbtyp != 3 ) {
if ( strcmp(inFileName_B, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
inpmtxB = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxB, inFileName_B ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in first matrix", t2 - t1) ;
fflush(msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n InpMtx B object after loading") ;
InpMtx_writeForHumanEye(inpmtxB, msgFile) ;
fflush(msgFile) ;
}
} else {
inpmtxB = NULL ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__4, &retc );
}
} else {
/*
------------------------------------------------
other processors initialize their local matrices
------------------------------------------------
*/
inpmtxA = InpMtx_new() ;
InpMtx_init(inpmtxA, INPMTX_BY_CHEVRONS, SPOOLES_REAL, 0, 0) ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__1, &retc );
if ( prbtyp == 1 || prbtyp == 2 ) {
inpmtxB = InpMtx_new() ;
InpMtx_init(inpmtxB, INPMTX_BY_CHEVRONS, SPOOLES_REAL, 0, 0) ;
} else {
inpmtxB = NULL ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__4, &retc );
}
}
/*
-----------------------------
set up the solver environment
-----------------------------
*/
MARKTIME(t1) ;
rc = SetupMPI((void *) &bridge, &prbtyp, &nrow, &mxbksz, inpmtxA,
inpmtxB, &seed, &msglvl, msgFile, MPI_COMM_WORLD) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set up solver environment", t2 - t1) ;
fflush(msgFile) ;
if ( rc != 1 ) {
fprintf(stderr, "\n fatal error return %d from SetupMPI()", rc) ;
MPI_Finalize() ;
exit(-1) ;
}
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
invoke eigensolver
nfound -- # of eigenvalues found and kept
ndisc -- # of additional eigenvalues discarded
-----------------------------------------------
*/
MARKTIME(t1) ;
lanczos_run ( &neigvl, &which[1] , &pbtype[1], &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &lanczos_wksp, &bridge, &nfound,
&ndiscd, &warnng, &error, FactorMPI, JimMatMulMPI,
JimSolveMPI ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : time for lanczos run", t2 - t1) ;
fflush(msgFile) ;
if ( myid == 0 ) {
/*
----------------------------------------------
processor 0 deals with eigenvalues and vectors
----------------------------------------------
*/
MARKTIME(t1) ;
neig = nfound + ndiscd ;
lstevl = nfound ;
lanczos_eigenvalues (&lanczos_wksp, eigval, &neig, &retc);
fstevl = 1 ;
if ( nfound == 0 ) fstevl = -1 ;
if ( ndiscd > 0 ) lstevl = -ndiscd ;
hdslp5_ ("computed eigenvalues returned by hdserl",
&neig, eigval, &output, 39L ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvalues",
t2 - t1) ;
fflush(msgFile) ;
/*
-------------------------
get eigenvectors and print
-------------------------
*/
/*
MARKTIME(t1) ;
neig = min ( 50, nrow );
Lncz_ALLOCATE(evec, double, nrow, retc);
for (i = 1; i<= nfound; i++) {
lanczos_eigenvector(&lanczos_wksp, &i, &i, newToOld,
evec, &nrow, &retc) ;
hdslp5_("computed eigenvector returned by hdserc",
&neig, evec, &output, 39L ) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvectors",
t2 - t1) ;
fflush(msgFile) ;
*/
}
/*
------------------------
free the working storage
------------------------
*/
MARKTIME(t1) ;
lanczos_free(&lanczos_wksp) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free lanczos workspace", t2 - t1) ;
fflush(msgFile) ;
MARKTIME(t1) ;
CleanupMPI(&bridge) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free solver workspace", t2 - t1) ;
fflush(msgFile) ;
MPI_Finalize() ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return ; }
\end{verbatim}
Eigen/doc/MT.tex 0100644 0002055 0007177 00000034014 06636767365 0014761 0 ustar 00cleve compmath 0000040 0000006 \chapter{The Multithreaded Bridge Object and Driver}
\label{chapter:MT}
\par
\section{The \texttt{BridgeMT} Data Structure}
\label{section:BridgeMT:dataStructure}
\par
The {\tt BridgeMT} structure has the following fields.
\begin{itemize}
%
\item
{\tt int prbtype} : problem type
\begin{itemize}
\item {\tt 1} --- vibration, a multiply with $B$ is required.
\item {\tt 2} --- buckling, a multiply with $A$ is required.
\item {\tt 3} --- simple, no multiply is required.
\end{itemize}
\item
{\tt int neqns} : number of equations,
i.e., number of vertices in the graph.
\item
{\tt int mxbsz} : block size for the Lanczos process.
\item
{\tt int nthread} : number of threads to use.
\item
{\tt int seed} : random number seed used in the ordering.
\item
{\tt InpMtx *A} : matrix object for $A$
\item
{\tt InpMtx *B} : matrix object for $B$
\item
{\tt Pencil *pencil} : object to hold linear combination of $A$ and $B$.
\item
{\tt ETree *frontETree} : object that defines the factorizations,
e.g., the number of fronts, the tree they form, the number of
internal and external rows for each front, and the map from
vertices to the front where it is contained.
\item
{\tt IVL *symbfacIVL} : object that contains the symbolic
factorization of the matrix.
\item
{\tt SubMtxManager *mtxmanager} : object that manages the
\texttt{SubMtx} objects that store the factor entries and are used
in the solves.
\item
{\tt FrontMtx *frontmtx} : object that stores the $L$, $D$ and $U$
factor matrices.
\item
{\tt IV *oldToNewIV} : object that stores old-to-new permutation vector.
\item
{\tt IV *newToOldIV} : object that stores new-to-old permutation vector.
\item
{\tt DenseMtx *X} : dense matrix object that is used during the matrix
multiples and solves.
\item
{\tt DenseMtx *Y} : dense matrix object that is used during the matrix
multiples and solves.
\item
{\tt IV *ownersIV} : object that maps fronts to owning threads
for the factorization and matrix-multiplies.
\item
{\tt SolveMap *solvemap} : object that maps factor submatrices to
owning threads for the solve.
\item
{\tt int msglvl} : message level for output.
When 0, no output, When 1, just statistics and cpu times.
When greater than 1, more and more output.
\item
{\tt FILE *msgFile} : message file for output.
When \texttt{msglvl} $>$ 0, \texttt{msgFile} must not be \texttt{NULL}.
\end{itemize}
\par
\section{Prototypes and descriptions of \texttt{BridgeMT} methods}
\label{section:BridgeMT:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt BridgeMT} object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int SetupMT ( void *data, int *pprbtype, int *pneqns,
int *pmxbsz, InpMtx *A, InpMtx *B, int *pseed,
int *pnthread, int *pmsglvl, FILE *msgFile ) ;
\end{verbatim}
\index{SetupMT@{\tt SetupMT()}}
\noindent All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt void *data} --- a pointer to the {\tt BridgeMT} object.
\item {\tt int *pprbtype} --- {\tt *pprbtype} holds the problem type.
\begin{itemize}
\item {\tt 1} --- vibration, a multiply with $B$ is required.
\item {\tt 2} --- buckling, a multiply with $A$ is required.
\item {\tt 3} --- simple, no multiply is required.
\end{itemize}
\item {\tt int *pneqns} --- {\tt *pneqns} is the number of equations.
\item {\tt int *pmxbsz} --- {\tt *pmxbsz} is an upper bound on the
block size.
\item {\tt InpMtx *A} --- {\tt A} is a {\bf SPOOLES} object that
holds the matrix $A$.
\item {\tt InpMtx *B} --- {\tt B} is a {\bf SPOOLES} object that
holds the matrix $B$. For an ordinary eigenproblem, $B$ is the
identity and {\tt B} is {\tt NULL}.
\item {\tt int *pseed} --- {\tt *pseed} is a random number seed.
\item {\tt int *pnthread} --- {\tt *pnthread} is the number of
threads to use during the factorizations, solves and
matrix-multiplies.
\item {\tt int *pmsglvl} --- {\tt *pmsglvl} is a message level for
the bridge methods and the {\bf SPOOLES} methods they call.
\item {\tt FILE *pmsglvl} --- {\tt msgFile} is the message file
for the bridge methods and the {\bf SPOOLES} methods they call.
\end{itemize}
This method must be called in the driver program prior to invoking
the eigensolver via a call to {\tt lanczos\_run()}.
It then follows this sequence of action.
\begin{itemize}
\item
The method begins by checking all the input data,
and setting the appropriate fields of the {\tt BridgeMT} object.
\item
The {\tt pencil} object is initialized with {\tt A} and {\tt B}.
\item
{\tt A} and {\tt B} are converted to storage by rows and vector mode.
\item
A {\tt Graph} object is created that contains the sparsity pattern of
the union of {\tt A} and {\tt B}.
\item
The graph is ordered by first finding a recursive dissection partition,
and then evaluating the orderings produced by nested dissection and
multisection, and choosing the better of the two.
The {\tt frontETree} object is produced and placed into the {\tt bridge}
object.
\item
Old-to-new and new-to-old permutations are extracted from the front tree
and loaded into the {\tt BridgeMT} object.
\item
The vertices in the front tree are permuted, as well as the entries in
{\tt A} and {\tt B}.
Entries in the lower triangle of {\tt A} and {\tt B} are mapped into the
upper triangle, and the storage modes of {\tt A} and {\tt B} are changed
to chevrons and vectors, in preparation for the first factorization.
\item
The symbolic factorization is then computed and loaded in the {\tt
BridgeMT} object.
\item
A {\tt FrontMtx} object is created to hold the factorization
and loaded into the {\tt BridgeMT} object.
\item
A {\tt SubMtxManager} object is created to hold the factor's
submatrices and loaded into the {\tt BridgeMT} object.
\item
Two {\tt DenseMtx} objects are created to be used during the matrix
multiplies and solves.
\item
The map from fronts to their owning threads is computed and stored
in the {\tt ownersIV} object.
\item
The map from factor submatrices to their owning threads
is computed and stored in the {\tt solvemap} object.
\end{itemize}
The {\tt A} and {\tt B} matrices are now in their permuted ordering,
i.e., $PAP^T$ and $PBP^T$, and all data structures are with respect to
this ordering. After the Lanczos run completes, any generated
eigenvectors must be permuted back into their original ordering using
the {\tt oldToNewIV} and {\tt newToOldIV} objects.
\par \noindent {\it Return value:}
\begin{center}
\begin{tabular}[t]{rl}
~1 & normal return \\
-1 & \texttt{data} is \texttt{NULL} \\
-2 & \texttt{pprbtype} is \texttt{NULL} \\
-3 & \texttt{*pprbtype} is invalid \\
-4 & \texttt{pneqns} is \texttt{NULL} \\
-5 & \texttt{*pneqns} is invalid \\
-6 & \texttt{pmxbsz} is \texttt{NULL}
\end{tabular}
\begin{tabular}[t]{rl}
-7 & \texttt{*pmxbsz} is invalid \\
-8 & \texttt{A} and \texttt{B} are \texttt{NULL} \\
-9 & \texttt{seed} is \texttt{NULL} \\
-10 & \texttt{msglvl} is \texttt{NULL} \\
-11 & $\texttt{msglvl} > 0$ and \texttt{msgFile} is \texttt{NULL} \\
-12 & \texttt{pnthread} is \texttt{NULL} \\
-13 & \texttt{*pnthread} is invalid
\end{tabular}
\end{center}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FactorMT ( double *psigma, double *ppvttol, void *data,
int *pinertia, int *perror ) ;
\end{verbatim}
\index{FactorMT@{\tt FactorMT()}}
This method computes the factorization of $A - \sigma B$.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt double *psigma} --- the shift parameter $\sigma$ is
found in {\tt *psigma}.
\item {\tt double *ppvttol} --- the pivot tolerance is
found in {\tt *ppvttol}. When ${\tt *ppvttol} = 0.0$,
the factorization is computed without pivoting for stability.
When ${\tt *ppvttol} > 0.0$, the factorization is computed
with pivoting for stability, and all offdiagonal entries
have magnitudes bounded above by $1/({\tt *ppvttol})$.
\item {\tt void *data} --- a pointer to the {\tt BridgeMT} object.
\item {\tt int *pinertia} --- on return, {\tt *pinertia} holds the
number of negative eigenvalues.
\item {\tt int *perror} --- on return, {\tt *perror} holds an
error code.
\begin{center}
\begin{tabular}[t]{rl}
~1 & error in the factorization \\
~0 & normal return \\
-1 & \texttt{psigma} is \texttt{NULL}
\end{tabular}
\begin{tabular}[t]{rl}
-2 & \texttt{ppvttol} is \texttt{NULL} \\
-3 & \texttt{data} is \texttt{NULL} \\
-4 & \texttt{pinertia} is \texttt{NULL}
\end{tabular}
\end{center}
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void MatMulMT ( int *pnrows, int *pncols, double X[], double Y[],
int *pprbtype, void *data ) ;
\end{verbatim}
\index{MatMulMT@{\tt MatMulMT()}}
This method computes a multiply of the form $Y = I X$, $Y = A X$
or $Y = B X$.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt int *pnrows} --- {\tt *pnrows} contains the number of
rows in $X$ and $Y$.
\item {\tt int *pncols} --- {\tt *pncols} contains the number of
columns in $X$ and $Y$.
\item {\tt double X[]} --- this is the $X$ matrix, stored column
major with leading dimension {\tt *pnrows}.
\item {\tt double Y[]} --- this is the $Y$ matrix, stored column
major with leading dimension {\tt *pnrows}.
\item {\tt int *pprbtype} --- {\tt *pprbtype} holds the problem type.
\begin{itemize}
\item {\tt 1} --- vibration, a multiply with $B$ is required.
\item {\tt 2} --- buckling, a multiply with $A$ is required.
\item {\tt 3} --- simple, no multiply is required.
\end{itemize}
\item {\tt void *data} --- a pointer to the {\tt BridgeMT} object.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void SolveMT ( int *pnrows, int *pncols, double X[], double Y[],
void *data, int *perror ) ;
\end{verbatim}
\index{SolveMT@{\tt SolveMT()}}
This method solves $(A - \sigma B) X = Y$, where
$(A - \sigma B)$ has been factored by a previous call to {\tt Factor()}.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt int *pnrows} --- {\tt *pnrows} contains the number of
rows in $X$ and $Y$.
\item {\tt int *pncols} --- {\tt *pncols} contains the number of
columns in $X$ and $Y$.
\item {\tt double X[]} --- this is the $X$ matrix, stored column
major with leading dimension {\tt *pnrows}.
\item {\tt double Y[]} --- this is the $Y$ matrix, stored column
major with leading dimension {\tt *pnrows}.
\item {\tt void *data} --- a pointer to the {\tt BridgeMT} object.
\item {\tt int *perror} --- on return, {\tt *perror} holds an
error code.
\begin{center}
\begin{tabular}[t]{rl}
~1 & normal return \\
-1 & \texttt{pnrows} is \texttt{NULL} \\
-2 & \texttt{pncols} is \texttt{NULL}
\end{tabular}
\begin{tabular}[t]{rl}
-3 & \texttt{X} is \texttt{NULL} \\
-4 & \texttt{Y} is \texttt{NULL} \\
-5 & \texttt{data} is \texttt{NULL}
\end{tabular}
\end{center}
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int CleanupMT ( void *data ) ;
\end{verbatim}
\index{CleanupMT@{\tt CleanupMT()}}
This method releases all the storage used by the {\bf SPOOLES}
library functions.
\par \noindent {\it Return value:}
1 for a normal return,
-1 if a {\tt data} is {\tt NULL}.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\section{The \texttt{testMT} Driver Program}
\label{section:BridgeMT:driver}
\par
A complete listing of the multithreaded driver program is
found in chapter~\ref{chapter:MT_driver}.
The program is invoked by this command sequence.
\begin{verbatim}
testMT msglvl msgFile parmFile seed nthread inFileA inFileB
\end{verbatim}
where
\begin{itemize}
\item
{\tt msglvl} is the message level for the {\tt BridgeMT}
methods and the {\bf SPOOLES} software.
\item
{\tt msgFile} is the message file for the {\tt BridgeMT}
methods and the {\bf SPOOLES} software.
\item
{\tt parmFile} is the input file for the parameters of the
eigensystem to be solved.
\item
{\tt seed} is a random number seed
used by the {\bf SPOOLES} software.
\item
{\tt nthread} is the number of threads to use in the factors,
solves and matrix-multiplies.
\item
{\tt inFileA} is the Harwell-Boeing file for the matrix $A$.
\item
{\tt inFileB} is the Harwell-Boeing file for the matrix $B$.
\end{itemize}
This program is executed for some sample matrices by the
{\tt do\_ST\_*} shell scripts in the {\tt drivers} directory.
\par
Here is a short description of the steps in the driver program.
See Chapter~\ref{chapter:serial_driver} for the listing.
\begin{enumerate}
\item
The command line inputs are decoded.
\item
The header of the Harwell-Boeing file for $A$ is read.
This yields the number of equations.
\item
The parameters that define the eigensystem to be solved
are read in from the {\tt parmFile} file.
\item
The Lanczos eigensolver workspace is initialized.
\item
The Lanczos communication structure is filled with some parameters.
\item
The $A$ and possibly $B$ matrices are read in from the
Harwell-Boeing files and converted into {\tt InpMtx} objects
from the {\bf SPOOLES} library.
\item
The linear solver environment is then initialized via a call to
{\tt SetupMT()}.
\item
The eigensolver is invoked via a call to {\tt lanczos\_run()}.
The {\tt FactorMT()}, {\tt SolveMT()} and {\tt MatMulMT()} methods
are passed to this routine.
\item
The eigenvalues are extracted and printed via a call to
{\tt lanczos\_eigenvalues()}.
\item
The eigenvectors are extracted and printed via calls to
{\tt lanczos\_eigenvector()}.
\item
The eigensolver working storage is free'd via a call to
{\tt lanczos\_free()}.
\item
The linear solver working storage is free'd via a call to
{\tt CleanupMT()}.
\end{enumerate}
} is a message level for
the bridge methods and the {\bf SPOOLES} methods they call.
\item {\tt FILE *pmsglvl} --- {\tt msgFile} is the message file
for the bridge methods and the {\bf SPOOLES} methods they call.
\end{itemize}
This method must be called in the driver program prior to invoking
the eigensolver via a call to {\tt lanczos\_run()}.
It then follows this sequence of action.
\begin{itemize}
\item
The method begins by checking all the input data,
and setting the appropriate fields of theEigen/doc/MT_driver.tex 0100644 0002055 0007177 00000023624 06636762273 0016332 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt testMT.c} --- A Multithreaded Driver Program}
\label{chapter:MT_driver}
\begin{verbatim}
/* testMT.c */
#include "../BridgeMT.h"
void FactorMT ( ) ;
void MatMulMT ( ) ;
void SolveMT ( ) ;
/*--------------------------------------------------------------------*/
void main ( int argc, char *argv[] )
/*
----------------------------------------------------------------
read in Harwell-Boeing matrices, using multithreaded factor,
solve, and multiply routines based on spooles, invoke eigensolver
created -- 98mar31, jcp
modified -- 98dec18, cca
----------------------------------------------------------------
*/
{
BridgeMT bridge ;
char *inFileName_A, *inFileName_B, *parmFileName, *type ;
char buffer[20], pbtype[4], which[4] ;
double lftend, rhtend, center, shfscl, t1, t2 ;
double c__1 = 1.0, c__4 = 4.0, tolact = 2.309970868130169e-11 ;
double eigval[1000], sigma[2];
double *evec;
int error, fstevl, lfinit, lstevl, msglvl, mxbksz, ncol, ndiscd,
neig, neigvl, nfound, nnonzeros, nrhs, nrow, nthreads,
prbtyp, rc, retc, rfinit, seed, warnng ;
int c__5 = 5, output = 6 ;
int *lanczos_wksp;
InpMtx *inpmtxA, *inpmtxB ;
FILE *msgFile, *parmFile ;
/*--------------------------------------------------------------------*/
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile parmFile seed nthread inFileA inFileB"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n parmFile -- input parameters file"
"\n seed -- random number seed, used for ordering"
"\n nthreads -- number of threads "
"\n inFileA -- stiffness matrix, in Harwell-Boeing format"
"\n inFileB -- mass matrix, in Harwell-Boeing format"
"\n used for prbtype = 1 or 2"
"\n", argv[0]) ;
return ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n able to open file %s\n", argv[0], argv[2]) ;
exit(-1) ;
}
parmFileName = argv[3] ;
seed = atoi(argv[4]) ;
nthreads = atoi(argv[5]) ;
inFileName_A = argv[6] ;
inFileName_B = argv[7] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n message file -- %s"
"\n parameter file -- %s"
"\n stiffness matrix file -- %s"
"\n mass matrix file -- %s"
"\n random number seed -- %d"
"\n number of threads -- %d"
"\n",
argv[0], msglvl, argv[2], parmFileName, inFileName_A,
inFileName_B, seed, nthreads) ;
fflush(msgFile) ;
/*
---------------------------------------------
read in the Harwell-Boeing matrix information
---------------------------------------------
*/
if ( strcmp(inFileName_A, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
readHB_info (inFileName_A, &nrow, &ncol, &nnonzeros, &type, &nrhs) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in harwell-boeing header info",
t2 - t1) ;
fflush(msgFile) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
read in eigenvalue problem data
neigvl -- # of desired eigenvalues
which -- which eigenvalues to compute
'l' or 'L' lowest (smallest magnitude)
'h' or 'H' highest (largest magnitude)
'n' or 'N' nearest to central value
'c' or 'C' nearest to central value
'a' or 'A' all eigenvalues in interval
pbtype -- type of problem
'v' or 'V' generalized symmetric problem (K,M)
with M positive semidefinite (vibration problem)
'b' or 'B' generalized symmetric problem (K,K_s)
with K positive semidefinite
with K_s posibly indefinite (buckling problem)
'o' or 'O' ordinary symmetric eigenproblem
lfinit -- if true, lftend is restriction on lower bound of
eigenvalues. if false, no restriction on lower bound
lftend -- left endpoint of interval
rfinit -- if true, rhtend is restriction on upper bound of
eigenvalues. if false, no restriction on upper bound
rhtend -- right endpoint of interval
center -- center of interval
mxbksz -- upper bound on block size for Lanczos recurrence
shfscl -- shift scaling parameter, an estimate on the magnitude
of the smallest nonzero eigenvalues
---------------------------------------------------------------
*/
MARKTIME(t1) ;
parmFile = fopen(parmFileName, "r");
fscanf(parmFile, "%d %s %s %d %le %d %le %le %d %le",
&neigvl, which, pbtype, &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &mxbksz, &shfscl) ;
fclose(parmFile);
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in eigenvalue problem data",
t2 - t1) ;
fflush(msgFile) ;
/*
----------------------------------------
check and set the problem type parameter
----------------------------------------
*/
switch ( pbtype[1] ) {
case 'v' :
case 'V' :
prbtyp = 1 ;
break ;
case 'b' :
case 'B' :
prbtyp = 2 ;
break ;
case 'o' :
case 'O' :
prbtyp = 3 ;
break ;
default :
fprintf(stderr, "\n invalid problem type %s", pbtype) ;
exit(-1) ;
}
/*
----------------------------
Initialize Lanczos workspace
----------------------------
*/
MARKTIME(t1) ;
lanczos_init_ ( &lanczos_wksp ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : initialize Lanczos workspace",
t2 - t1) ;
fflush(msgFile) ;
/*
----------------------------------
initialize communication structure
----------------------------------
*/
MARKTIME(t1) ;
lanczos_set_parm( &lanczos_wksp, "order-of-problem", &nrow, &retc );
lanczos_set_parm( &lanczos_wksp, "accuracy-tolerance", &tolact, &retc);
lanczos_set_parm( &lanczos_wksp, "max-block-size", &mxbksz, &retc );
lanczos_set_parm( &lanczos_wksp, "shift-scale", &shfscl, &retc );
lanczos_set_parm( &lanczos_wksp, "message_level", &msglvl, &retc );
lanczos_set_parm( &lanczos_wksp, "number-of-threads", &nthreads, &retc);
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : init lanczos communication structure",
t2 - t1) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
create the InpMtx objects for matrix A and B
---------------------------------------------
*/
if ( strcmp(inFileName_A, "none") == 0 ) {
fprintf(msgFile, "\n no file to read A from") ;
exit(-1) ;
}
MARKTIME(t1) ;
inpmtxA = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxA, inFileName_A ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in A", t2 - t1) ;
fflush(msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n InpMtx A object after loading") ;
InpMtx_writeForHumanEye(inpmtxA, msgFile) ;
fflush(msgFile) ;
}
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__1, &retc );
if ( prbtyp != 3 ) {
if ( strcmp(inFileName_B, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
inpmtxB = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxB, inFileName_B ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in B", t2 - t1) ;
fflush(msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n InpMtx B object after loading") ;
InpMtx_writeForHumanEye(inpmtxB, msgFile) ;
fflush(msgFile) ;
}
} else {
inpmtxB = NULL ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__4, &retc );
}
/*
-----------------------------
set up the solver environment
-----------------------------
*/
MARKTIME(t1) ;
rc = SetupMT((void *) &bridge, &prbtyp, &nrow, &mxbksz, inpmtxA,
inpmtxB, &seed, &nthreads, &msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set up the solver environment",
t2 - t1) ;
fflush(msgFile) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error return %d from SetupMT()", rc) ;
exit(-1) ;
}
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
invoke eigensolver
nfound -- # of eigenvalues found and kept
ndisc -- # of additional eigenvalues discarded
-----------------------------------------------
*/
MARKTIME(t1) ;
lanczos_run ( &neigvl, &which[1] , &pbtype[1], &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &lanczos_wksp, &bridge, &nfound,
&ndiscd, &warnng, &error, FactorMT, MatMulMT, SolveMT ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : time for lanczos_run", t2 - t1) ;
fflush(msgFile) ;
/*
-------------------------
get eigenvalues and print
-------------------------
*/
MARKTIME(t1) ;
neig = nfound + ndiscd ;
lstevl = nfound ;
lanczos_eigenvalues (&lanczos_wksp, eigval, &neig, &retc);
fstevl = 1 ;
if ( nfound == 0 ) fstevl = -1 ;
if ( ndiscd > 0 ) lstevl = -ndiscd ;
hdslp5_ ("computed eigenvalues returned by hdserl",
&neig, eigval, &output, 39L ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvalues", t2 - t1) ;
fflush(msgFile) ;
/*
-------------------------
get eigenvectors and print
-------------------------
*/
/*
MARKTIME(t1) ;
neig = min ( 50, nrow );
Lncz_ALLOCATE(evec, double, nrow, retc);
for (i = 1; i<= nfound; i++) {d
lanczos_eigenvector ( &lanczos_wksp, &i, &i, newToOld,
evec, &nrow, &retc ) ;
hdslp5_ ( "computed eigenvector returned by hdserc",
&neig, evec, &output, 39L ) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvectors", t2 - t1) ;
fflush(msgFile) ;
*/
/*
------------------------
free the working storage
------------------------
*/
MARKTIME(t1) ;
lanczos_free( &lanczos_wksp ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free lanczos workspace", t2 - t1) ;
fflush(msgFile) ;
MARKTIME(t1) ;
CleanupMT(&bridge) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free solver workspace", t2 - t1) ;
fflush(msgFile) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return ; }
\end{verbatim}
"\n mass matrix file -- %s"
"\n random number seed -- %d"
"\n number of threads Eigen/doc/abstract.tex 0100644 0002055 0007177 00000002277 06625050065 0016226 0 ustar 00cleve compmath 0000040 0000006 \begin{abstract}
The {\bf SPOOLES} library stands for
{\bf SP}arse {\bf O}bject {\bf O}riented {\bf L}inear
{\bf E}quation {\bf S}olver.
It is written in the C language using object oriented design
and can solve real or complex linear systems in serial,
multithreaded and MPI environments.
It contains three options to order the matrices: minimum degree,
generalized nested dissection and multisection.
The matrices may be symmetric, Hermitian or nonsymmetric.
Pivoting for numerical stability is supported.
\par
While the functionality of the library is broad,
the learning curve can be steep for the initial user.
We present in this paper some ``wrapper'' objects in the serial,
multithreaded and MPI environments that ease the transition.
They were originally written to integrate the {\bf SPOOLES} library
into CSAR's Nastran library.
\par
The wrapper objects are presented as a learning device; anything
that reduces the interface between the user and the library also
restricts the ability to tune the library to a particular need.
This drawback is ameliorated by a number of wrapper methods that
allow the user to change default parameters that govern the
ordering, factorization and solve.
\end{abstract}
Eigen/doc/intro.tex 0100644 0002055 0007177 00000007250 06636756074 0015571 0 ustar 00cleve compmath 0000040 0000006 \chapter{Introduction}
\label{chapter:introduction}
\par
The Lanczos eigensolver
finds selected eigenvalues and eigenvectors of
% three types of eigenproblems,
$AX = B X \Lambda$, where $X$ are eigenvectors
and $\Lambda$ is a diagonal matrix whose elements are eigenvalues.
Three types of eigenproblems are supported.
\begin{itemize}
\item
An ``ordinary'' eigenvalue problem
where $A$ is symmetric and $B = I$.
\item
An ``vibration'' eigenvalue problem
where $A$ is symmetric and
$B$ is symmetric positive semidefinite.
\item
A ``buckling'' eigenvalue problem
$A$ is symmetric positive semidefinite and
$B$ is symmetric.
\end{itemize}
For the vibration and buckling problems, there must exist a
$\sigma$ that is not an eigenvalue such that
$A - \sigma B$ is nonsingular,
i.e., $A$ and $B$ cannot share the same null space.
\par
During the computations, the eigensolver requires the following
sparse linear algebra computations.
\begin{itemize}
\item
Sparse factorizations of the form $A - \sigma B$.
\item
Solves of the form $(A - \sigma B) Z = Y$.
\item
Multiplies of the form $Z = B Y$ (for the vibration problem)
or $Z = A Y$ (for the buckling problem).
\end{itemize}
The Lanczos eigensolver has defined a specific interface with an
external linear algebra package to perform these three operations.
The eigensolver currently interfaces with the {\bf BCSLIB-EXT} linear
solver in a serial environment and the {\bf SPOOLES} linear solver
in serial, multithreaded and MPI environments.
\par
This paper documents the {\bf SPOOLES} objects and functions
that interface with the eigensolver.
The three following chapters describe the serial, multithreaded and
MPI objects, their data structures, and their methods.
The appendix contains listings of three driver programs to exercise
the eigensolver using the {\bf SPOOLES} library.
\par
Symmetric permutations of the eigensystem do not change the
eigenvalues, and the eigenvectors can be easily constructed
using the permutation matrix.
$$
A X = B X \Lambda
\longrightarrow
{\widehat A} {\widehat X}
= {\widehat B} {\widehat X} \Lambda
\quad \mbox{where} \quad
{\widehat A} = PAP^T, \quad
{\widehat B} = PBP^T, \quad
\mbox{and} \quad
{\widehat X} = PX
$$
The linear algebra package is free to use any permutation matrix
$P$ to most efficiently perform the factorizations and solves
involving ${\widehat A}$ and ${\widehat B}$.
This permutation matrix $P$ is typically found by ordering the
graph of $A + B$ using a variant of minimum degree or nested
dissection.
The ordering is performed prior to any action by the eigensolver.
This ``setup phase'' includes more than just finding the
permutation matrix, e.g., various data structures must be
initialized.
In a parallel environment, there is even more setup work to do,
analyzing the factorization and solves and specifying which threads
or processors perform what computations and store what data.
In a distributed environment, the entries of $A$ and $B$ must
also be distributed among the processors in preparation for
the factors and multiplies.
\par
For each of the three environments --- serial, multithreaded and
MPI --- the {\bf SPOOLES} solver has constructed a ``bridge''
object to span the interface between the linear system solver
and the eigensolver.
Each of the {\tt Bridge}, {\tt BridgeMT} and {\tt BridgeMPI}
objects have five methods: set-up, factor, solve, matrix-multiply
and cleanup.
The factor, solve and matrix-multiply methods follow the calling
sequence convention imposed by the eigensolver, and are passed
to the eigensolver at the beginning of the Lanczos run.
The set-up method is called prior to the eigensolver, and the
cleanup method is called after the eigenvalues and eigenvectors
have been determined.
Eigen/doc/main.aux 0100644 0002055 0007177 00000005542 06643472144 0015350 0 ustar 00cleve compmath 0000040 0000006 \relax
\bibstyle{plain}
\@writefile{toc}{\contentsline {chapter}{\numberline {1}Introduction}{2}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chapter:introduction}{{1}{2}}
\@writefile{toc}{\contentsline {chapter}{\numberline {2}The Serial Bridge Object and Driver}{4}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chapter:serial}{{2}{4}}
\@writefile{toc}{\contentsline {section}{\numberline {2.1}The \texttt {Bridge} Data Structure}{4}}
\newlabel{section:Bridge:dataStructure}{{2.1}{4}}
\@writefile{toc}{\contentsline {section}{\numberline {2.2}Prototypes and descriptions of \texttt {Bridge} methods}{5}}
\newlabel{section:Bridge:proto}{{2.2}{5}}
\@writefile{toc}{\contentsline {section}{\numberline {2.3}The \texttt {testSerial} Driver Program}{7}}
\newlabel{section:Bridge:driver}{{2.3}{7}}
\@writefile{toc}{\contentsline {chapter}{\numberline {3}The Multithreaded Bridge Object and Driver}{9}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chapter:MT}{{3}{9}}
\@writefile{toc}{\contentsline {section}{\numberline {3.1}The \texttt {BridgeMT} Data Structure}{9}}
\newlabel{section:BridgeMT:dataStructure}{{3.1}{9}}
\@writefile{toc}{\contentsline {section}{\numberline {3.2}Prototypes and descriptions of \texttt {BridgeMT} methods}{10}}
\newlabel{section:BridgeMT:proto}{{3.2}{10}}
\@writefile{toc}{\contentsline {section}{\numberline {3.3}The \texttt {testMT} Driver Program}{12}}
\newlabel{section:BridgeMT:driver}{{3.3}{12}}
\@writefile{toc}{\contentsline {chapter}{\numberline {4}The MPI Bridge Object and Driver}{14}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chapter:MPI}{{4}{14}}
\@writefile{toc}{\contentsline {section}{\numberline {4.1}The \texttt {BridgeMPI} Data Structure}{14}}
\newlabel{section:BridgeMPI:dataStructure}{{4.1}{14}}
\@writefile{toc}{\contentsline {section}{\numberline {4.2}Prototypes and descriptions of \texttt {BridgeMPI} methods}{15}}
\newlabel{section:BridgeMPI:proto}{{4.2}{15}}
\@writefile{toc}{\contentsline {section}{\numberline {4.3}The \texttt {testMPI} Driver Program}{19}}
\newlabel{section:BridgeMPI:driver}{{4.3}{19}}
\@writefile{toc}{\contentsline {chapter}{\numberline {A}{\tt testSerial.c} --- A Serial Driver Program}{20}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chapter:serial_driver}{{A}{20}}
\@writefile{toc}{\contentsline {chapter}{\numberline {B}{\tt testMT.c} --- A Multithreaded Driver Program}{27}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chapter:MT_driver}{{B}{27}}
\@writefile{toc}{\contentsline {chapter}{\numberline {C}{\tt testMPI.c} --- A MPI Driver Program}{34}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chapter:MPI_driver}{{C}{34}}
Eigen/doc/main.idx 0100644 0002055 0007177 00000001324 06643472144 0015331 0 ustar 00cleve compmath 0000040 0000006 \indexentry{Setup@{\tt Setup()}}{5}
\indexentry{Factor@{\tt Factor()}}{6}
\indexentry{MatMul@{\tt MatMul()}}{6}
\indexentry{Solve@{\tt Solve()}}{7}
\indexentry{Cleanup@{\tt Cleanup()}}{7}
\indexentry{SetupMT@{\tt SetupMT()}}{10}
\indexentry{FactorMT@{\tt FactorMT()}}{11}
\indexentry{MatMulMT@{\tt MatMulMT()}}{12}
\indexentry{SolveMT@{\tt SolveMT()}}{12}
\indexentry{CleanupMT@{\tt CleanupMT()}}{12}
\indexentry{SetupMPI@{\tt SetupMPI()}}{16}
\indexentry{FactorMPI@{\tt FactorMPI()}}{17}
\indexentry{JimMatMulMPI@{\tt JimMatMulMPI()}}{17}
\indexentry{MatMulMPI@{\tt MatMulMPI()}}{18}
\indexentry{JimSolveMPI@{\tt JimSolveMPI()}}{18}
\indexentry{SolveMPI@{\tt SolveMPI()}}{18}
\indexentry{CleanupMPI@{\tt CleanupMPI()}}{19}
Eigen/doc/main.ilg 0100644 0002055 0007177 00000000456 06636774313 0015332 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (17 entries accepted, 0 rejected).
Sorting entries....done (68 comparisons).
Generating output file main.ind....done (33 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
Eigen/doc/main.ind 0100644 0002055 0007177 00000001111 06636774313 0015316 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt Cleanup()}, 7
\item {\tt CleanupMPI()}, 19
\item {\tt CleanupMT()}, 12
\indexspace
\item {\tt Factor()}, 6
\item {\tt FactorMPI()}, 17
\item {\tt FactorMT()}, 11
\indexspace
\item {\tt JimMatMulMPI()}, 17
\item {\tt JimSolveMPI()}, 18
\indexspace
\item {\tt MatMul()}, 6
\item {\tt MatMulMPI()}, 18
\item {\tt MatMulMT()}, 12
\indexspace
\item {\tt Setup()}, 5
\item {\tt SetupMPI()}, 16
\item {\tt SetupMT()}, 10
\item {\tt Solve()}, 7
\item {\tt SolveMPI()}, 18
\item {\tt SolveMT()}, 12
\end{theindex}
Eigen/doc/main.log 0100644 0002055 0007177 00000007674 06643472144 0015344 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.14159 (C version 6.1) (format=latex 97.4.4) 2 JAN 1999 11:32
**main
(main.tex
LaTeX2e <1996/12/01> patch level 1
Babel and hyphenation patterns for english, german, loaded.
(/home/tex/teTeX/texmf/tex/latex/base/report.cls
Document Class: report 1996/10/31 v1.3u Standard LaTeX document class
(/home/tex/teTeX/texmf/tex/latex/base/size10.clo
File: size10.clo 1996/10/31 v1.3u Standard LaTeX file (size option)
)
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
\abovecaptionskip=\skip41
\belowcaptionskip=\skip42
\bibindent=\dimen102
)
\@indexfile=\write3
Writing index file main.idx
(/home/tex/teTeX/texmf/tex/generic/local/psfig/psfig.tex
\@unused=\write4
\ps@stream=\read1
\p@intvaluex=\dimen103
\p@intvaluey=\dimen104
psfig/tex 1.10-dvips
) (main.aux)
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 21.
LaTeX Font Info: ... okay on input line 21.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 21.
LaTeX Font Info: ... okay on input line 21.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 21.
LaTeX Font Info: ... okay on input line 21.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 21.
LaTeX Font Info: ... okay on input line 21.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 21.
LaTeX Font Info: ... okay on input line 21.
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 21.
LaTeX Font Info: ... okay on input line 21.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <12> on input line 52.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <8> on input line 52.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <6> on input line 52.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <9> on input line 52.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <5> on input line 52.
[1
] (main.toc
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <7> on input line 3.
)
\tf@toc=\write5
(intro.tex [1
]
Chapter 1.
LaTeX Font Info: Try loading font information for OMS+cmr on input line 12.
(/home/tex/teTeX/texmf/tex/latex/base/omscmr.fd
File: omscmr.fd 1997/01/14 v2.5a Standard LaTeX font definitions
)
LaTeX Font Info: Font shape `OMS/cmr/m/n' in size <10> not available
(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 12.
) (serial.tex [2
] [3]
Chapter 2.
LaTeX Font Info: Font shape `OT1/cmtt/bx/n' in size <14.4> not available
(Font) Font shape `OT1/cmtt/m/n' tried instead on input line 4.
[4
] [5]
Overfull \hbox (22.49097pt too wide) in paragraph at lines 173--173
[]\OT1/cmtt/m/n/10 void Factor ( double *psigma, double *ppvttol, void *data,
int *pinertia, int *perror ) ;[]
[]
[6] [7]) (MT.tex [8]
Chapter 3.
[9
] [10] [11] [12]) (MPI.tex [13]
Chapter 4.
[14
]
Overfull \hbox (1.79965pt too wide) in paragraph at lines 72--75
[]\OT1/cmtt/m/n/10 IV *ownersIV \OT1/cmr/m/n/10 : ob-ject that maps fronts to o
wn-ing pro-ces-sors for the fac-tor-iza-tion and matrix-multiplies.
[]
[15] [16] [17] [18]) (serial_driver.tex [19]
Appendix A.
[20
] [21] [22] [23] [24] [25]) (MT_driver.tex [26]
Appendix B.
[27
] [28] [29] [30] [31] [32]) (MPI_driver.tex [33]
Appendix C.
[34
] [35] [36] [37] [38] [39] [40]) (main.ind [41] [42
]) (main.aux) )
Here is how much of TeX's memory you used:
570 strings out of 10908
5786 string characters out of 72189
58833 words of memory out of 262141
3463 multiletter control sequences out of 9500
11727 words of font info for 43 fonts, out of 150000 for 255
14 hyphenation exceptions out of 607
25i,11n,21p,152b,396s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (43 pages, 103452 bytes).
ng defaults for OML/cmm/m/it on input line 21.
LaTeX Font Info: .Eigen/doc/main.tex 0100644 0002055 0007177 00000003034 06636770127 0015351 0 ustar 00cleve compmath 0000040 0000006 \documentclass[10pt]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\input psfig
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\bf SPOOLES 2.2 Wrapper Objects} : \today \quad
\hrulefill}
{\quad \hrulefill \quad {\bf SPOOLES 2.2 Wrapper Objects} : \quad \today
\hrulefill}
\begin{document}
\bibliographystyle{plain}
\title{Integrating the {\bf SPOOLES} 2.2 Sparse Linear Algebra Library
\break
into the {\bf LANCZOS} Block-shifted Lanczos Eigensolver }
\author{
Cleve Ashcraft\\
Boeing Phantom Works\thanks{
P. O. Box 24346,
Mail Stop 7L-22,
Seattle, Washington 98124,
{\tt cleve.ashcraft@boeing.com}.
This research was supported in part by the DARPA
Contract DABT63-95-C-0122 and the DoD High Performance Computing
Modernization Program Common HPC Software Support Initiative.}
\and
Jim Patterson\\
Boeing Phantom Works\thanks{
P. O. Box 24346,
Mail Stop 7L-22,
Seattle, Washington 98124,
{\tt pattersn@redwood.rt.cs.boeing.com}.
This research was supported in part by the DARPA
Contract DABT63-95-C-0122 and the DoD High Performance Computing
Modernization Program Common HPC Software Support Initiative.}
}
\date{\today}
\maketitle
\tableofcontents
\input intro.tex
\input serial.tex
\input MT.tex
\input MPI.tex
\appendix
\input serial_driver.tex
\input MT_driver.tex
\input MPI_driver.tex
\input main.ind
\end{document}
Eigen/doc/main.toc 0100644 0002055 0007177 00000002541 06643472144 0015334 0 ustar 00cleve compmath 0000040 0000006 \contentsline {chapter}{\numberline {1}Introduction}{2}
\contentsline {chapter}{\numberline {2}The Serial Bridge Object and Driver}{4}
\contentsline {section}{\numberline {2.1}The \texttt {Bridge} Data Structure}{4}
\contentsline {section}{\numberline {2.2}Prototypes and descriptions of \texttt {Bridge} methods}{5}
\contentsline {section}{\numberline {2.3}The \texttt {testSerial} Driver Program}{7}
\contentsline {chapter}{\numberline {3}The Multithreaded Bridge Object and Driver}{9}
\contentsline {section}{\numberline {3.1}The \texttt {BridgeMT} Data Structure}{9}
\contentsline {section}{\numberline {3.2}Prototypes and descriptions of \texttt {BridgeMT} methods}{10}
\contentsline {section}{\numberline {3.3}The \texttt {testMT} Driver Program}{12}
\contentsline {chapter}{\numberline {4}The MPI Bridge Object and Driver}{14}
\contentsline {section}{\numberline {4.1}The \texttt {BridgeMPI} Data Structure}{14}
\contentsline {section}{\numberline {4.2}Prototypes and descriptions of \texttt {BridgeMPI} methods}{15}
\contentsline {section}{\numberline {4.3}The \texttt {testMPI} Driver Program}{19}
\contentsline {chapter}{\numberline {A}{\tt testSerial.c} --- A Serial Driver Program}{20}
\contentsline {chapter}{\numberline {B}{\tt testMT.c} --- A Multithreaded Driver Program}{27}
\contentsline {chapter}{\numberline {C}{\tt testMPI.c} --- A MPI Driver Program}{34}
Eigen/doc/makefile 0100644 0002055 0007177 00000000027 06625644105 0015374 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
Eigen/doc/serial.tex 0100644 0002055 0007177 00000032146 06636767363 0015722 0 ustar 00cleve compmath 0000040 0000006 \chapter{The Serial Bridge Object and Driver}
\label{chapter:serial}
\par
\section{The \texttt{Bridge} Data Structure}
\label{section:Bridge:dataStructure}
\par
The {\tt Bridge} structure has the following fields.
\begin{itemize}
%
\item
{\tt int prbtype} : problem type
\begin{itemize}
\item {\tt 1} --- vibration, a multiply with $B$ is required.
\item {\tt 2} --- buckling, a multiply with $A$ is required.
\item {\tt 3} --- simple, no multiply is required.
\end{itemize}
\item
{\tt int neqns} : number of equations,
i.e., number of vertices in the graph.
\item
{\tt int mxbsz} : block size for the Lanczos process.
\item
{\tt int seed} : random number seed used in the ordering.
\item
{\tt InpMtx *A} : matrix object for $A$
\item
{\tt InpMtx *B} : matrix object for $B$
\item
{\tt Pencil *pencil} : object to hold linear combination of $A$ and $B$.
\item
{\tt ETree *frontETree} : object that defines the factorizations,
e.g., the number of fronts, the tree they form, the number of
internal and external rows for each front, and the map from
vertices to the front where it is contained.
\item
{\tt IVL *symbfacIVL} : object that contains the symbolic
factorization of the matrix.
\item
{\tt SubMtxManager *mtxmanager} : object that manages the
\texttt{SubMtx} objects that store the factor entries and are used
in the solves.
\item
{\tt FrontMtx *frontmtx} : object that stores the $L$, $D$ and $U$
factor matrices.
\item
{\tt IV *oldToNewIV} : object that stores old-to-new permutation vector.
\item
{\tt IV *newToOldIV} : object that stores new-to-old permutation vector.
\item
{\tt DenseMtx *X} : dense matrix object that is used during the matrix
multiples and solves.
\item
{\tt DenseMtx *Y} : dense matrix object that is used during the matrix
multiples and solves.
\item
{\tt int msglvl} : message level for output.
When 0, no output, When 1, just statistics and cpu times.
When greater than 1, more and more output.
\item
{\tt FILE *msgFile} : message file for output.
When \texttt{msglvl} $>$ 0, \texttt{msgFile} must not be \texttt{NULL}.
\end{itemize}
\par
\section{Prototypes and descriptions of \texttt{Bridge} methods}
\label{section:Bridge:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt Bridge} object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Setup ( void *data, int *pprbtype, int *pneqns, int *pmxbsz,
InpMtx *A, InpMtx *B, int *pseed, int *pmsglvl, FILE *msgFile ) ;
\end{verbatim}
\index{Setup@{\tt Setup()}}
\noindent All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt void *data} --- a pointer to the {\tt Bridge} object.
\item {\tt int *pprbtype} --- {\tt *pprbtype} holds the problem type.
\begin{itemize}
\item {\tt 1} --- vibration, a multiply with $B$ is required.
\item {\tt 2} --- buckling, a multiply with $A$ is required.
\item {\tt 3} --- simple, no multiply is required.
\end{itemize}
\item {\tt int *pneqns} --- {\tt *pneqns} is the number of equations.
\item {\tt int *pmxbsz} --- {\tt *pmxbsz} is an upper bound on the
block size.
\item {\tt InpMtx *A} --- {\tt A} is a {\bf SPOOLES} object that
holds the matrix $A$.
\item {\tt InpMtx *B} --- {\tt B} is a {\bf SPOOLES} object that
holds the matrix $B$. For an ordinary eigenproblem, $B$ is the
identity and {\tt B} is {\tt NULL}.
\item {\tt int *pseed} --- {\tt *pseed} is a random number seed.
\item {\tt int *pmsglvl} --- {\tt *pmsglvl} is a message level for
the bridge methods and the {\bf SPOOLES} methods they call.
\item {\tt FILE *pmsglvl} --- {\tt msgFile} is the message file
for the bridge methods and the {\bf SPOOLES} methods they call.
\end{itemize}
This method must be called in the driver program prior to invoking
the eigensolver via a call to {\tt lanczos\_run()}.
It then follows this sequence of action.
\begin{itemize}
\item
The method begins by checking all the input data,
and setting the appropriate fields of the {\tt Bridge} object.
\item
The {\tt pencil} object is initialized with {\tt A} and {\tt B}.
\item
{\tt A} and {\tt B} are converted to storage by rows and vector mode.
\item
A {\tt Graph} object is created that contains the sparsity pattern of
the union of {\tt A} and {\tt B}.
\item
The graph is ordered by first finding a recursive dissection partition,
and then evaluating the orderings produced by nested dissection and
multisection, and choosing the better of the two.
The {\tt frontETree} object is produced and placed into the {\tt bridge}
object.
\item
Old-to-new and new-to-old permutations are extracted from the front tree
and loaded into the {\tt Bridge} object.
\item
The vertices in the front tree are permuted, as well as the entries in
{\tt A} and {\tt B}.
Entries in the lower triangle of {\tt A} and {\tt B} are mapped into the
upper triangle, and the storage modes of {\tt A} and {\tt B} are changed
to chevrons and vectors, in preparation for the first factorization.
\item
The symbolic factorization is then computed and loaded in the {\tt
Bridge} object.
\item
A {\tt FrontMtx} object is created to hold the factorization
and loaded into the {\tt Bridge} object.
\item
A {\tt SubMtxManager} object is created to hold the factor's
submatrices and loaded into the {\tt Bridge} object.
\item
Two {\tt DenseMtx} objects are created to be used during the matrix
multiplies and solves.
\end{itemize}
The {\tt A} and {\tt B} matrices are now in their permuted ordering,
i.e., $PAP^T$ and $PBP^T$, and all data structures are with respect to
this ordering. After the Lanczos run completes, any generated
eigenvectors must be permuted back into their original ordering using
the {\tt oldToNewIV} and {\tt newToOldIV} objects.
\par \noindent {\it Return value:}
\begin{center}
\begin{tabular}[t]{rl}
~1 & normal return \\
-1 & \texttt{data} is \texttt{NULL} \\
-2 & \texttt{pprbtype} is \texttt{NULL} \\
-3 & \texttt{*pprbtype} is invalid \\
-4 & \texttt{pneqns} is \texttt{NULL} \\
-5 & \texttt{*pneqns} is invalid
\end{tabular}
\begin{tabular}[t]{rl}
-6 & \texttt{pmxbsz} is \texttt{NULL} \\
-7 & \texttt{*pmxbsz} is invalid \\
-8 & \texttt{A} and \texttt{B} are \texttt{NULL} \\
-9 & \texttt{seed} is \texttt{NULL} \\
-10 & \texttt{msglvl} is \texttt{NULL} \\
-11 & $\texttt{msglvl} > 0$ and \texttt{msgFile} is \texttt{NULL}
\end{tabular}
\end{center}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Factor ( double *psigma, double *ppvttol, void *data, int *pinertia, int *perror ) ;
\end{verbatim}
\index{Factor@{\tt Factor()}}
This method computes the factorization of $A - \sigma B$.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt double *psigma} --- the shift parameter $\sigma$ is
found in {\tt *psigma}.
\item {\tt double *ppvttol} --- the pivot tolerance is
found in {\tt *ppvttol}. When ${\tt *ppvttol} = 0.0$,
the factorization is computed without pivoting for stability.
When ${\tt *ppvttol} > 0.0$, the factorization is computed
with pivoting for stability, and all offdiagonal entries
have magnitudes bounded above by $1/({\tt *ppvttol})$.
\item {\tt void *data} --- a pointer to the {\tt Bridge} object.
\item {\tt int *pinertia} --- on return, {\tt *pinertia} holds the
number of negative eigenvalues.
\item {\tt int *perror} --- on return, {\tt *perror} holds an
error code.
\begin{center}
\begin{tabular}[t]{rl}
~1 & error in the factorization \\
~0 & normal return \\
-1 & \texttt{psigma} is \texttt{NULL}
\end{tabular}
\begin{tabular}[t]{rl}
-2 & \texttt{ppvttol} is \texttt{NULL} \\
-3 & \texttt{data} is \texttt{NULL} \\
-4 & \texttt{pinertia} is \texttt{NULL}
\end{tabular}
\end{center}
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void MatMul ( int *pnrows, int *pncols, double X[], double Y[],
int *pprbtype, void *data ) ;
\end{verbatim}
\index{MatMul@{\tt MatMul()}}
This method computes a multiply of the form $Y = I X$, $Y = A X$
or $Y = B X$.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt int *pnrows} --- {\tt *pnrows} contains the number of
rows in $X$ and $Y$.
\item {\tt int *pncols} --- {\tt *pncols} contains the number of
columns in $X$ and $Y$.
\item {\tt double X[]} --- this is the $X$ matrix, stored column
major with leading dimension {\tt *pnrows}.
\item {\tt double Y[]} --- this is the $Y$ matrix, stored column
major with leading dimension {\tt *pnrows}.
\item {\tt int *pprbtype} --- {\tt *pprbtype} holds the problem type.
\begin{itemize}
\item {\tt 1} --- vibration, a multiply with $B$ is required.
\item {\tt 2} --- buckling, a multiply with $A$ is required.
\item {\tt 3} --- simple, no multiply is required.
\end{itemize}
\item {\tt void *data} --- a pointer to the {\tt Bridge} object.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Solve ( int *pnrows, int *pncols, double X[], double Y[],
void *data, int *perror ) ;
\end{verbatim}
\index{Solve@{\tt Solve()}}
This method solves $(A - \sigma B) X = Y$, where
$(A - \sigma B)$ has been factored by a previous call to {\tt Factor()}.
All calling sequence parameters are pointers to more
easily allow an interface with Fortran.
\begin{itemize}
\item {\tt int *pnrows} --- {\tt *pnrows} contains the number of
rows in $X$ and $Y$.
\item {\tt int *pncols} --- {\tt *pncols} contains the number of
columns in $X$ and $Y$.
\item {\tt double X[]} --- this is the $X$ matrix, stored column
major with leading dimension {\tt *pnrows}.
\item {\tt double Y[]} --- this is the $Y$ matrix, stored column
major with leading dimension {\tt *pnrows}.
\item {\tt void *data} --- a pointer to the {\tt Bridge} object.
\item {\tt int *perror} --- on return, {\tt *perror} holds an
error code.
\begin{center}
\begin{tabular}[t]{rl}
~1 & normal return \\
-1 & \texttt{pnrows} is \texttt{NULL} \\
-2 & \texttt{pncols} is \texttt{NULL}
\end{tabular}
\begin{tabular}[t]{rl}
-3 & \texttt{X} is \texttt{NULL} \\
-4 & \texttt{Y} is \texttt{NULL} \\
-5 & \texttt{data} is \texttt{NULL}
\end{tabular}
\end{center}
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Cleanup ( void *data ) ;
\end{verbatim}
\index{Cleanup@{\tt Cleanup()}}
This method releases all the storage used by the {\bf SPOOLES}
library functions.
\par \noindent {\it Return value:}
1 for a normal return,
-1 if a {\tt data} is {\tt NULL}.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\section{The \texttt{testSerial} Driver Program}
\label{section:Bridge:driver}
\par
A complete listing of the serial driver program is
found in chapter~\ref{chapter:serial_driver}.
The program is invoked by this command sequence.
\begin{verbatim}
testSerial msglvl msgFile parmFile seed inFileA inFileB
\end{verbatim}
where
\begin{itemize}
\item
{\tt msglvl} is the message level for the {\tt Bridge}
methods and the {\bf SPOOLES} software.
\item
{\tt msgFile} is the message file for the {\tt Bridge}
methods and the {\bf SPOOLES} software.
\item
{\tt parmFile} is the input file for the parameters of the
eigensystem to be solved.
\item
{\tt seed} is a random number seed
used by the {\bf SPOOLES} software.
\item
{\tt inFileA} is the Harwell-Boeing file for the matrix $A$.
\item
{\tt inFileB} is the Harwell-Boeing file for the matrix $B$.
\end{itemize}
This program is executed for some sample matrices by the
{\tt do\_ST\_*} shell scripts in the {\tt drivers} directory.
\par
Here is a short description of the steps in the driver program.
See Chapter~\ref{chapter:serial_driver} for the listing.
\begin{enumerate}
\item
The command line inputs are decoded.
\item
The header of the Harwell-Boeing file for $A$ is read.
This yields the number of equations.
\item
The parameters that define the eigensystem to be solved
are read in from the {\tt parmFile} file.
\item
The Lanczos eigensolver workspace is initialized.
\item
The Lanczos communication structure is filled with some parameters.
\item
The $A$ and possibly $B$ matrices are read in from the
Harwell-Boeing files and converted into {\tt InpMtx} objects
from the {\bf SPOOLES} library.
\item
The linear solver environment is then initialized via a call to
{\tt Setup()}.
\item
The eigensolver is invoked via a call to {\tt lanczos\_run()}.
The {\tt FactorMT()}, {\tt SolveMT()} and {\tt MatMulMT()}
methods are passed to this routine.
\item
The eigenvalues are extracted and printed via a call to
{\tt lanczos\_eigenvalues()}.
\item
The eigenvectors are extracted and printed via calls to
{\tt lanczos\_eigenvector()}.
\item
The eigensolver working storage is free'd via a call to
{\tt lanczos\_free()}.
\item
The linear solver working storage is free'd via a call to
{\tt Cleanup()}.
\end{enumerate}
*pneqns} is the number of equations.
\item {\tt int *pmxbsz} --- {\tt *pmxbsz} is an upper bound on the
block size.
\item {\tt InpMtx *A} --- {\tt A} is a {\bf SPOOLES} object that
holds the matrix $A$.
\item {\tt InpMtx *B} --- {\tt B} is a {\bf SPOOLES} object that
holds the matrix $B$. For an ordinary eigenproblem, $B$ is the
identity and {\tt B} is {\tt NULL}.
\item {\tt int *pseed} --- {\tt *pseed} isEigen/doc/serial_driver.tex 0100644 0002055 0007177 00000023374 06636753754 0017277 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt testSerial.c} --- A Serial Driver Program}
\label{chapter:serial_driver}
\begin{verbatim}
/* testSerial.c */
#include "../Bridge.h"
void Factor ( ) ;
void MatMul ( ) ;
void Solve ( ) ;
/*--------------------------------------------------------------------*/
void main ( int argc, char *argv[] )
/*
----------------------------------------------------------
read in Harwell-Boeing matrices, use serial factor, solve,
and multiply routines based on spooles, invoke eigensolver
created -- 98mar31 jcp
modified -- 98dec18, cca
----------------------------------------------------------
*/
{
Bridge bridge ;
char *inFileName_A, *inFileName_B, *outFileName,
*parmFileName, *type ;
char buffer[20], pbtype[4], which[4] ;
double lftend, rhtend, center, shfscl, t1, t2 ;
double c__1 = 1.0, c__4 = 4.0, tolact = 2.309970868130169e-11 ;
double eigval[1000], sigma[2];
double *evec;
int error, fstevl, lfinit, lstevl, mxbksz, msglvl, ncol, ndiscd,
neig, neigvl, nfound, nnonzeros, nrhs, nrow, prbtyp, rc,
retc, rfinit, seed, warnng ;
int c__5 = 5, output = 6 ;
int *lanczos_wksp;
InpMtx *inpmtxA, *inpmtxB ;
FILE *msgFile, *parmFile;
/*--------------------------------------------------------------------*/
if ( argc != 7 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile parmFile seed inFileA inFileB"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n parmFile -- input parameters file"
"\n seed -- random number seed, used for ordering"
"\n inFileA -- stiffness matrix in Harwell-Boeing format"
"\n inFileB -- mass matrix in Harwell-Boeing format"
"\n used for prbtyp = 1 or 2"
"\n", argv[0]) ;
return ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
exit(-1) ;
}
parmFileName = argv[3] ;
seed = atoi(argv[4]) ;
inFileName_A = argv[5] ;
inFileName_B = argv[6] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n parmFile -- %s"
"\n seed -- %d"
"\n stiffness file -- %s"
"\n mass file -- %s"
"\n",
argv[0], msglvl, argv[2], parmFileName, seed,
inFileName_A, inFileName_B) ;
fflush(msgFile) ;
/*
---------------------------------------------
read in the Harwell-Boeing matrix information
---------------------------------------------
*/
if ( strcmp(inFileName_A, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
readHB_info (inFileName_A, &nrow, &ncol, &nnonzeros, &type, &nrhs) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in header information for A",
t2 - t1) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
read in eigenvalue problem data
neigvl -- # of desired eigenvalues
which -- which eigenvalues to compute
'l' or 'L' lowest (smallest magnitude)
'h' or 'H' highest (largest magnitude)
'n' or 'N' nearest to central value
'c' or 'C' nearest to central value
'a' or 'A' all eigenvalues in interval
pbtype -- type of problem
'v' or 'V' generalized symmetric problem (K,M)
with M positive semidefinite (vibration problem)
'b' or 'B' generalized symmetric problem (K,K_s)
with K positive semidefinite
with K_s posibly indefinite (buckling problem)
'o' or 'O' ordinary symmetric eigenproblem
lfinit -- if true, lftend is restriction on lower bound of
eigenvalues. if false, no restriction on lower bound
lftend -- left endpoint of interval
rfinit -- if true, rhtend is restriction on upper bound of
eigenvalues. if false, no restriction on upper bound
rhtend -- right endpoint of interval
center -- center of interval
mxbksz -- upper bound on block size for Lanczos recurrence
shfscl -- shift scaling parameter, an estimate on the magnitude
of the smallest nonzero eigenvalues
---------------------------------------------------------------
*/
MARKTIME(t1) ;
parmFile = fopen(parmFileName, "r");
fscanf(parmFile, "%d %s %s %d %le %d %le %le %d %le",
&neigvl, which, pbtype, &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &mxbksz, &shfscl) ;
fclose(parmFile);
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in eigenvalue problem data",
t2 - t1) ;
/*
----------------------------------------
check and set the problem type parameter
----------------------------------------
*/
switch ( pbtype[1] ) {
case 'v' : case 'V' : prbtyp = 1 ; break ;
case 'b' : case 'B' : prbtyp = 2 ; break ;
case 'o' : case 'O' : prbtyp = 3 ; break ;
default :
fprintf(stderr, "\n invalid problem type %s", pbtype) ;
exit(-1) ;
}
/*
----------------------------
Initialize Lanczos workspace
----------------------------
*/
MARKTIME(t1) ;
lanczos_init_ ( &lanczos_wksp ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : initialize lanczos workspace",
t2 - t1) ;
/*
----------------------------------
initialize communication structure
----------------------------------
*/
MARKTIME(t1) ;
lanczos_set_parm( &lanczos_wksp, "order-of-problem", &nrow, &retc );
lanczos_set_parm( &lanczos_wksp, "accuracy-tolerance", &tolact, &retc );
lanczos_set_parm( &lanczos_wksp, "max-block-size", &mxbksz, &retc );
lanczos_set_parm( &lanczos_wksp, "shift-scale", &shfscl, &retc );
lanczos_set_parm( &lanczos_wksp, "message_level", &msglvl, &retc );
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : init lanczos communication structure",
t2 - t1) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
create the InpMtx objects for matrix A and B
---------------------------------------------
*/
if ( strcmp(inFileName_A, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
inpmtxA = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxA, inFileName_A ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in A", t2 - t1) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n InpMtx A object after loading") ;
InpMtx_writeForHumanEye(inpmtxA, msgFile) ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__1, &retc );
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set A's parameters", t2 - t1) ;
if ( prbtyp != 3 ) {
if ( strcmp(inFileName_B, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
inpmtxB = InpMtx_new() ;
InpMtx_readFromHBfile ( inpmtxB, inFileName_B ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in B", t2 - t1) ;
} else {
MARKTIME(t1) ;
inpmtxB = NULL ;
lanczos_set_parm( &lanczos_wksp, "matrix-type", &c__4, &retc );
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set B's parameters", t2 - t1) ;
}
if ( msglvl > 2 && prbtyp != 3 ) {
fprintf(msgFile, "\n\n InpMtx B object after loading") ;
InpMtx_writeForHumanEye(inpmtxB, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------------
set up the solver environment
-----------------------------
*/
MARKTIME(t1) ;
rc = Setup((void *) &bridge, &prbtyp, &nrow, &mxbksz, inpmtxA, inpmtxB,
&seed, &msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set up solver environment", t2 - t1) ;
if ( rc != 1 ) {
fprintf(stderr, "\n fatal error %d from Setup()", rc) ;
exit(-1) ;
}
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
invoke eigensolver
nfound -- # of eigenvalues found and kept
ndisc -- # of additional eigenvalues discarded
-----------------------------------------------
*/
MARKTIME(t1) ;
lanczos_run(&neigvl, &which[1] , &pbtype[1], &lfinit, &lftend,
&rfinit, &rhtend, ¢er, &lanczos_wksp, &bridge, &nfound,
&ndiscd, &warnng, &error, Factor, MatMul, Solve ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : time for lanczos run", t2 - t1) ;
/*
-------------------------
get eigenvalues and print
-------------------------
*/
MARKTIME(t1) ;
neig = nfound + ndiscd ;
lstevl = nfound ;
lanczos_eigenvalues (&lanczos_wksp, eigval, &neig, &retc);
fstevl = 1 ;
if ( nfound == 0 ) fstevl = -1 ;
if ( ndiscd > 0 ) lstevl = -ndiscd ;
hdslp5_ ("computed eigenvalues returned by hdserl",
&neig, eigval, &output, 39L ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvalues ", t2 - t1) ;
/*
-------------------------
get eigenvectors and print
-------------------------
*/
/*
MARKTIME(t1) ;
neig = min ( 50, nrow );
Lncz_ALLOCATE(evec, double, nrow, retc);
for ( i = 1 ; i <= nfound ; i++ ) {
lanczos_eigenvector ( &lanczos_wksp, &i, &i, newToOld,
evec, &nrow, &retc ) ;
hdslp5_ ( "computed eigenvector returned by hdserc",
&neig, evec, &output, 39L ) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get and print eigenvectors ", t2 - t1) ;
*/
/*
------------------------
free the working storage
------------------------
*/
MARKTIME(t1) ;
lanczos_free( &lanczos_wksp ) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free lanczos workspace ", t2 - t1) ;
MARKTIME(t1) ;
rc = Cleanup(&bridge) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : free solver workspace ", t2 - t1) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error return %d from Cleanup()", rc) ;
exit(-1) ;
}
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return ; }
\end{verbatim}
4], which[4] ;
double lftend, rhtend, center, shfscl, t1, t2 ;
double c__1 = 1.0, c__4 = 4.0, tolact = 2.309970868130169e-11 ;
double eigval[1000], sigma[2];
double *evec;
int error, fstevl, lfinit, lstevl, mxbksz, msglvl, ncol, ndiscd,
FrontMtx.h 0100644 0002055 0007177 00000000114 06573537544 0014041 0 ustar 00cleve compmath 0000040 0000006 #ifndef _FrontMtx_
#define _FrontMtx_
#include "FrontMtx/FrontMtx.h"
#endif
FrontMtx/FrontMtx.h 0100644 0002055 0007177 00000151114 06605202032 0015602 0 ustar 00cleve compmath 0000040 0000006 /* FrontMtx.h */
#include "../Pencil.h"
#include "../ETree.h"
#include "../IVL.h"
#include "../PatchAndGoInfo.h"
#include "../Chv.h"
#include "../ChvManager.h"
#include "../ChvList.h"
#include "../SubMtx.h"
#include "../SubMtxList.h"
#include "../SubMtxManager.h"
#include "../DenseMtx.h"
#include "../Ideq.h"
#include "../SolveMap.h"
#include "../Lock.h"
#include "../I2Ohash.h"
#include "../SPOOLES.h"
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
the FrontMtx object is used to compute and store a matrix
factorization in serial, multithreaded and MPI modes.
there are two data modes:
1 --> data is stored by fronts, a 1-D data decomposition.
we use five pointer vectors (p_mtxDJJ[], p_mtxUJJ[],
p_mtxUJN[], p_mtxLJJ[] and p_mtxLNJ[]) to store pointers
to the factor submatrices
2 --> data is stored by submatrices, a 2-D data decomposition.
we use two hash objects (lowerhash and upperhash), a
pointer vector p_mtxDJJ[] and two IVL objects (lowerblockIVL
and upperblockIVL) to store the structure of the matrix.
nfront -- number of fronts in the matrix
neqns -- number of rows and columns in the matrix
type -- type of entries
1 -- real
2 -- complex
symmetryflag -- flag to specify symmetry of the matrix
0 --> symmetric structure, symmetric entries
1 --> symmetric structure, nonsymmetric entries
2 --> nonsymmetric structure, nonsymmetric entries
sparsityflag -- flag to specify dense or sparse fronts
0 --> dense fronts
1 --> sparse fronts
pivotingflag -- flag to specify pivoting enabled
0 --> pivoting not used
1 --> pivoting used
dataMode -- flag to specify storage mode
1 --> 1-dimensional data decomposition, used for factorization
2 --> 2-dimensional data decomposition, used for solves
nentD -- number of entries in the diagonal matrix
nentL -- number of entries in the lower triangular matrix
nentU -- number of entries in the upper triangular matrix
tree -- pointer to an Tree object that holds the tree of fronts
frontETree -- pointer to an ETree object that holds the front tree
symbfacIVL -- pointer to an IVL object that holds
the symbolic factorization
frontsizesIV -- pointer to an IV object that holds the number of
internal rows and columns in each front
rowadjIVL -- pointer to an IVL object that holds the row ids
of the fronts, used only for nonsymmetric matrices with pivoting
coladjIVL -- pointer to an IVL object that holds the column ids
of the fronts, used only with pivoting
p_mtxDJJ -- vector of pointers to the diagonal D_{J,J} objects
p_mtxUJJ -- vector of pointers to the upper U_{J,J} objects
p_mtxUJN -- vector of pointers to the upper U_{J,N} objects
p_mtxLJJ -- vector of pointers to the lower L_{J,J} objects
p_mtxLNJ -- vector of pointers to the lower L_{N,J} objects
lowerblockIVL -- pointer to an IVL object that holds the sparsity
structure of the block L matrix, i.e., front-front edges,
used only for nonsymmetric matrices with pivoting
upperblockIVL -- pointer to an IVL object that holds the sparsity
structure of the block U matrix, i.e., front-front edges
lowerhash -- pointer to a hash table object that holds the
submatrices in L, used only for nonsymmetric factorizations
upperhash -- pointer to a hash table object that holds the
submatrices in U
manager -- object to manage instances of Mtx objects
lock -- mutex object that controls access to allocating
storage in IVL and DVL objects, can be NULL
nlocks -- number of times the lock was locked
patchinfo -- information object needed for special factorizations
created -- 98feb27, cca
-------------------------------------------------------------------
*/
typedef struct _FrontMtx FrontMtx ;
struct _FrontMtx {
int nfront ;
int neqns ;
int type ;
int symmetryflag ;
int sparsityflag ;
int pivotingflag ;
int dataMode ;
int nentD ;
int nentL ;
int nentU ;
Tree *tree ;
ETree *frontETree ;
IV *frontsizesIV ;
IVL *symbfacIVL ;
IVL *rowadjIVL ;
IVL *coladjIVL ;
IVL *lowerblockIVL ;
IVL *upperblockIVL ;
SubMtx **p_mtxDJJ ;
SubMtx **p_mtxUJJ ;
SubMtx **p_mtxUJN ;
SubMtx **p_mtxLJJ ;
SubMtx **p_mtxLNJ ;
I2Ohash *lowerhash ;
I2Ohash *upperhash ;
SubMtxManager *manager ;
Lock *lock ;
PatchAndGoInfo *patchinfo ;
int nlocks ;
} ;
#define FRONTMTX_IS_REAL(mtx) ((mtx)->type == SPOOLES_REAL)
#define FRONTMTX_IS_COMPLEX(mtx) ((mtx)->type == SPOOLES_COMPLEX)
#define FRONTMTX_IS_SYMMETRIC(mtx) \
((mtx)->symmetryflag == SPOOLES_SYMMETRIC)
#define FRONTMTX_IS_HERMITIAN(mtx) \
((mtx)->symmetryflag == SPOOLES_HERMITIAN)
#define FRONTMTX_IS_NONSYMMETRIC(mtx) \
((mtx)->symmetryflag == SPOOLES_NONSYMMETRIC)
#define FRONTMTX_DENSE_FRONTS 0
#define FRONTMTX_SPARSE_FRONTS 1
#define FRONTMTX_IS_DENSE_FRONTS(mtx) \
((mtx)->sparsityflag == FRONTMTX_DENSE_FRONTS)
#define FRONTMTX_IS_SPARSE_FRONTS(mtx) \
((mtx)->sparsityflag == FRONTMTX_SPARSE_FRONTS)
#define FRONTMTX_IS_PIVOTING(mtx) \
((mtx)->pivotingflag == SPOOLES_PIVOTING)
#define FRONTMTX_1D_MODE 1
#define FRONTMTX_2D_MODE 2
#define FRONTMTX_IS_1D_MODE(mtx) \
((mtx)->dataMode == FRONTMTX_1D_MODE)
#define FRONTMTX_IS_2D_MODE(mtx) \
((mtx)->dataMode == FRONTMTX_2D_MODE)
#define NO_LOCK 0
#define LOCK_IN_PROCESS 1
#define LOCK_IN_ALL_PROCESSES 2
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------
simplest constructor
created -- 98may04, cca
-----------------------
*/
FrontMtx *
FrontMtx_new (
void
) ;
/*
-----------------------
set the default fields
created -- 98may04, cca
-----------------------
*/
void
FrontMtx_setDefaultFields (
FrontMtx *frontmtx
) ;
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98may04, cca
--------------------------------------------------
*/
void
FrontMtx_clearData (
FrontMtx *frontmtx
) ;
/*
------------------------------------------
destructor, free's the object and its data
created -- 98may04, cca
------------------------------------------
*/
void
FrontMtx_free (
FrontMtx *frontmtx
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in instance.c --------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------
purpose -- return the number of fronts
created -- 98may04, cca
--------------------------------------
*/
int
FrontMtx_nfront (
FrontMtx *frontmtx
) ;
/*
-----------------------------------------
purpose -- return the number of equations
created -- 98may04, cca
-----------------------------------------
*/
int
FrontMtx_neqns (
FrontMtx *frontmtx
) ;
/*
----------------------------------------------------
purpose -- return a pointer to the front Tree object
created -- 98may04, cca
----------------------------------------------------
*/
Tree *
FrontMtx_frontTree (
FrontMtx *frontmtx
) ;
/*
----------------------------------------------------------------
simple method to return the dimensions of front J and the number
of bytes necessary for the Chv object to hold the front.
created -- 98may04, cca
----------------------------------------------------------------
*/
void
FrontMtx_initialFrontDimensions (
FrontMtx *frontmtx,
int J,
int *pnD,
int *pnL,
int *pnU,
int *pnbytes
) ;
/*
---------------------------------------------------------
return the number of internal rows and columns in front J
created -- 98may04, cca
---------------------------------------------------------
*/
int
FrontMtx_frontSize (
FrontMtx *frontmtx,
int J
) ;
/*
------------------------------------------------------
set the number of internal rows and columns in front J
created -- 98may04, cca
------------------------------------------------------
*/
void
FrontMtx_setFrontSize (
FrontMtx *frontmtx,
int J,
int size
) ;
/*
---------------------------------------------
fill *pncol with the number of columns and
*pcolind with a pointer to the column indices
created -- 98may04, cca
---------------------------------------------
*/
void
FrontMtx_columnIndices (
FrontMtx *frontmtx,
int J,
int *pncol,
int **pcolind
) ;
/*
-------------------------------------------
fill *pnrow with the number of rows and
*prowind with a pointer to the rows indices
created -- 98may04, cca
-------------------------------------------
*/
void
FrontMtx_rowIndices (
FrontMtx *frontmtx,
int J,
int *pnrow,
int **prowind
) ;
/*
-----------------------------------------------------------
purpose -- return a pointer to the (J,J) diagonal submatrix
created -- 98may04, cca
-----------------------------------------------------------
*/
SubMtx *
FrontMtx_diagMtx (
FrontMtx *frontmtx,
int J
) ;
/*
--------------------------------------------------------
purpose -- return a pointer to the (J,K) upper submatrix
created -- 98may04, cca
--------------------------------------------------------
*/
SubMtx *
FrontMtx_upperMtx (
FrontMtx *frontmtx,
int J,
int K
) ;
/*
--------------------------------------------------------
purpose -- return a pointer to the (K,J) lower submatrix
created -- 98may04, cca
--------------------------------------------------------
*/
SubMtx *
FrontMtx_lowerMtx (
FrontMtx *frontmtx,
int K,
int J
) ;
/*
--------------------------------------------------
purpose -- fill *pnadj with the number of fronts K
such that L_{K,J} != 0 and *padj with a
pointer to a list of those fronts
created -- 98may04, cca
--------------------------------------------------
*/
void
FrontMtx_lowerAdjFronts (
FrontMtx *frontmtx,
int J,
int *pnadj,
int **padj
) ;
/*
--------------------------------------------------
purpose -- fill *pnadj with the number of fronts K
such that U_{J,K} != 0 and *padj with a
pointer to a list of those fronts
created -- 98may04, cca
--------------------------------------------------
*/
void
FrontMtx_upperAdjFronts (
FrontMtx *frontmtx,
int J,
int *pnadj,
int **padj
) ;
/*
------------------------------------------------------
purpose -- return the number of nonzero L_{K,J} blocks
created -- 98may04, cca
------------------------------------------------------
*/
int
FrontMtx_nLowerBlocks (
FrontMtx *frontmtx
) ;
/*
------------------------------------------------------
purpose -- return the number of nonzero U_{K,J} blocks
created -- 98may04, cca
------------------------------------------------------
*/
int
FrontMtx_nUpperBlocks (
FrontMtx *frontmtx
) ;
/*
---------------------------------------------------------
purpose -- return a pointer to the upper block IVL object
created -- 98jun13, cca
---------------------------------------------------------
*/
IVL *
FrontMtx_upperBlockIVL (
FrontMtx *frontmtx
) ;
/*
---------------------------------------------------------
purpose -- return a pointer to the lower block IVL object
created -- 98jun13, cca
---------------------------------------------------------
*/
IVL *
FrontMtx_lowerBlockIVL (
FrontMtx *frontmtx
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------------
purpose -- basic initializer
frontETree -- ETree object that stores the front tree
symbfacIVL -- IVL object that stores the symbolic factorization
manager -- SubMtxManager object to manage SubMtx objects
type -- type of entries
SPOOLES_REAL --> real
SPOOLES_COMPLEX --> complex
symmetryflag -- symmetry flag,
SPOOLES_SYMMETRIC --> symmetric structure and entries
SPOOLES_HERMITIAN --> hermitian (complex only)
SPOOLES_NONSYMMETRIC --> nonsymmetric entries
sparsityflag -- flag to specify dense or sparse fronts
FRONTMTX_DENSE_FRONTS --> dense fronts
FRONTMTX_SPARSE_FRONTS --> sparse fronts
pivotingflag -- flag to specify pivoting enabled
SPOOLES_NO_PIVOTING --> pivoting not used
SPOOLES_PIVOTING --> pivoting used
in a multithreaded environment, we need to protect the critical
section where data is allocated. we use a lockflag to do this.
in a serial or distributed environment, use lockflag = 0.
lockflag -- flag to specify lock status
NO_LOCK --> mutex lock is not allocated or initialized
LOCK_IN_PROCESS --> mutex lock is allocated and
it can synchronize only threads in this process.
LOCK_OVER_ALL_PROCESSES --> mutex lock is allocated and
it can synchronize only threads in this and other processes.
in a distributed environment we need to specify which process
owns each front. when we can preallocate data structures
(when there is no pivoting and dense fronts are stored) we
need each process to determine what parts of the data it
can allocate and set up. in a serial or multithreaded
environment, use ownersIV = NULL.
ownersIV -- map from fronts to owning processes
myid -- id of this process.
submatrices (be they lower, diagonal, block diagonal, upper)
are stored in SubMtx objects. the management of these objects,
(allocation and deallocation) is managed by the SubMtxManager
manager object.
manager -- SubMtxManager object to handle the submatrices
created -- 98may04, cca
------------------------------------------------------------------
*/
void
FrontMtx_init (
FrontMtx *frontmtx,
ETree *frontETree,
IVL *symbfacIVL,
int type,
int symmetryflag,
int sparsityflag,
int pivotingflag,
int lockflag,
int myid,
IV *ownersIV,
SubMtxManager *manager,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in factor.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------------------------
compute an (U^T + I)D(I + U) or (L + I)D(I + L) factorization of A.
this is a wrapper method around FrontMtx_factorPencil().
input --
frontmtx -- pointer to the FrontMtx object that will hold
the factorization
pencil -- pointer to the Pencil object that holds A + sigma*B
tau -- upper bound on entries in L and U,
used only when pivoting enabled
droptol -- lower bound on entries in L and U,
used only when sparsity enabled
perror -- error flag, on return
*perror >= 0 --> factorization failed at front *perror
*perror < 0 --> factorization succeeded
cpus[] -- timing array
cpus[0] -- initialize fronts
cpus[1] -- load original entries
cpus[2] -- get updates from descendents
cpus[3] -- assembled postponed data
cpus[4] -- factor the front
cpus[5] -- extract postponed data
cpus[6] -- store factor entries
cpus[7] -- miscellaneous time
cpus[8] -- total time
stats[] -- statistics array
stats[0] -- # of pivots
stats[1] -- # of pivot tests
stats[2] -- # of delayed rows and columns
stats[3] -- # of entries in D
stats[4] -- # of entries in L
stats[5] -- # of entries in U
msglvl -- message level
msgFile -- message file
created -- 98mar27, cca
modified -- 98mar27, cca
perror added to argument list
-------------------------------------------------------------------
*/
Chv *
FrontMtx_factorInpMtx (
FrontMtx *frontmtx,
InpMtx *inpmtx,
double tau,
double droptol,
ChvManager *chvmanager,
int *perror,
double cpus[],
int stats[],
int msglvl,
FILE *msgFile
) ;
/*
-------------------------------------------------------------------
compute an (U^T + I)D(I + U) or (L + I)D(I + L)
factorization of A + sigma*B.
input --
frontmtx -- pointer to the FrontMtx object that will hold
the factorization
pencil -- pointer to the Pencil object that holds A + sigma*B
tau -- upper bound on entries in L and U,
used only when pivoting enabled
droptol -- lower bound on entries in L and U,
used only when sparsity enabled
perror -- error flag, on return
*perror >= 0 --> factorization failed at front *perror
*perror < 0 --> factorization succeeded
cpus[] -- timing array
cpus[0] -- initialize fronts
cpus[1] -- load original entries
cpus[2] -- get updates from descendents
cpus[3] -- assembled postponed data
cpus[4] -- factor the front
cpus[5] -- extract postponed data
cpus[6] -- store factor entries
cpus[7] -- miscellaneous time
cpus[8] -- total time
stats[] -- statistics array
stats[0] -- # of pivots
stats[1] -- # of pivot tests
stats[2] -- # of delayed rows and columns
stats[3] -- # of entries in D
stats[4] -- # of entries in L
stats[5] -- # of entries in U
msglvl -- message level
msgFile -- message file
created -- 98mar27, cca
modified -- 98mar27, cca
perror added to argument list
-------------------------------------------------------------------
*/
Chv *
FrontMtx_factorPencil (
FrontMtx *frontmtx,
Pencil *pencil,
double tau,
double droptol,
ChvManager *chvmanager,
int *perror,
double cpus[],
int stats[],
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in factorUtil.c ------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------
purpose -- initialize a front
created -- 98may04, cca
-----------------------------
*/
void
FrontMtx_initializeFront (
FrontMtx *frontmtx,
Chv *frontJ,
int J
) ;
/*
------------------------------------------------------------------
purpose -- to visit a front during a factorization.
note: this method is called by the serial,
multithreaded and MPI factorization codes.
frontmtx -- front matrix object
pencil -- matrix pencil for A + sigma*B
J -- id of front we are working on
myid -- id of thread or process
owners[] -- map from fronts to owning threads,
in a serial environment, owners = NULL
fronts[] -- vector of pointers to fronts
lookahead -- parameter controls the partial upward visiting
of ancestors before returning
tau -- used when pivoting enabled,
|L_{j,i}| and |U_{i,j}| <= tau
droptol -- used for an approximate factorization
stored |L_{j,i}| and |U_{i,j}| > droptol
status[] -- status vector for the fronts,
'W' -- needs to be woke up
'A' -- active front
'F' -- front is finished
heads[] -- vector of pointers to IP objects that store the
front-to-front update lists
pivotsizesIV -- IV object used during the factorization of a front
when pivoting is enabled
workDV -- DV object used for working storage
parent -- front parent vector
aggList -- list object used in parallel environment, used
to store aggregate fronts
postList -- list object used in pivoting and/or parallel
environments, used to stored delayed data and/or
to synchronize the factorization
chvmanager -- used to manage working storage for Chv objects
stats[] -- statistics vector
cpus[] -- vector to hold breakdown of cpu times
msglvl -- message level
msgFil -- message file
created -- 98may04, cca
------------------------------------------------------------------
*/
char
FrontMtx_factorVisit (
FrontMtx *frontmtx,
Pencil *pencil,
int J,
int myid,
int owners[],
Chv *fronts[],
int lookahead,
double tau,
double droptol,
char status[],
IP *heads[],
IV *pivotsizesIV,
DV *workDV,
int parent[],
ChvList *aggList,
ChvList *postList,
ChvManager *chvmanager,
int stats[],
double cpus[],
int msglvl,
FILE *msgFile
) ;
/*
--------------------------------------------
purpose -- set up the front's data structure
created -- 98mar27, cca
--------------------------------------------
*/
Chv *
FrontMtx_setupFront (
FrontMtx *frontmtx,
Pencil *pencil,
int J,
int myid,
int owners[],
ChvManager *chvmanager,
double cpus[],
int msglvl,
FILE *msgFile
) ;
/*
--------------------------------------------------------------------
purpose -- to set up the link data structures
for a parallel factorization for process myid
return value -- pointer to IP *heads[nfront+2], which contains
the beginning of a list of IP objects that store the remaining
updates to the fronts.
note, heads[nfront] is the first IP object in the free list.
heads[nfront+1] is the base address of the allocated IP objects.
created -- 98mar07, cca
--------------------------------------------------------------------
*/
IP **
FrontMtx_factorSetup (
FrontMtx *frontmtx,
IV *frontOwnersIV,
int myid,
int msglvl,
FILE *msgFile
) ;
/*
-----------------------------------------------
create and return the nactiveChild vector.
nactiveChild[J] contains the number of children
of J that belong to an active path
created -- 97jul03, cca
-----------------------------------------------
*/
int *
FrontMtx_nactiveChild (
FrontMtx *frontmtx,
char *status,
int myid
) ;
/*
---------------------------------------------------------
create, initialize and return a Ideq object
that will be used for a parallel factorization,
forward solve, or backward solve.
the status[] vector will be set as follows:
status[J] = activeflag if J is on an active path
status[J] = inactiveflag if J is not on an active path
created -- 98mar27, cca
---------------------------------------------------------
*/
Ideq *
FrontMtx_setUpDequeue (
FrontMtx *frontmtx,
int owners[],
int myid,
char status[],
IP *heads[],
char activeFlag,
char inactiveFlag,
int msglvl,
FILE *msgFile
) ;
/*
-----------------------------------------------------------------
purpose -- load the dequeue with the leaves of the active subtree
used for a factorization and forward solve
created -- 98mar27, cca
-----------------------------------------------------------------
*/
void
FrontMtx_loadActiveLeaves (
FrontMtx *frontmtx,
char status[],
char activeFlag,
Ideq *dequeue
) ;
/*
-----------------------------------------------
create, initialize and return a ChvList object
to deal with postponed chevrons
created -- 97jul03, cca
-----------------------------------------------
*/
ChvList *
FrontMtx_postList (
FrontMtx *frontmtx,
IV *frontOwnersIV,
int lockflag
) ;
/*
-----------------------------------------------
create, initialize and return a ChvList object
to deal with aggregate chevrons
created -- 97jul03, cca
-----------------------------------------------
*/
ChvList *
FrontMtx_aggregateList (
FrontMtx *frontmtx,
IV *frontOwnersIV,
int lockflag
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in loadEntries.c -----------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------
load entries from sigma*A
chv -- pointer to the Chv object that holds the front
pencil -- pointer to a Pencil that holds the matrix entries
msglvl -- message level
msgFile -- message file
created -- 97jul18, cca
------------------------------------------------------------
*/
void
FrontMtx_loadEntries (
Chv *chv,
Pencil *pencil,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in update.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------
accumulate updates to front J, store them in the Chv object
created -- 98may04, cca
------------------------------------------------------------
*/
void
FrontMtx_update (
FrontMtx *frontmtx,
Chv *frontJ,
IP *heads[],
char status[],
DV *tempDV,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in postponed.c -------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------------
purpose -- to assemble any postponed data into frontJ
frontJ -- pointer to Chv objec that contains current front
chvlist -- pointer to a ChvList object that handles the
lists of postponed Chv objects
chvmanager -- pointer to a ChvManager object for the list
of free Chv objects
pndelay -- pointer to address to contain the # of delayed rows
and columns that were assembled into the front
return value -- pointer to Chv object that contains the new front
created -- 98may04, cca
------------------------------------------------------------------
*/
Chv *
FrontMtx_assemblePostponedData (
FrontMtx *frontmtx,
Chv *frontJ,
ChvList *chvlist,
ChvManager *chvmanager,
int *pndelay
) ;
/*
---------------------------------------------------------
purpose -- extract and store the postponed data
frontJ -- pointer to present front object
npost -- # of postponed rows and columns in frontJ
K -- parent of J
chvlist -- pointer to a ChvList object that handles the
lists of postponed Chv objects
a singly linked list to assemble
chvmanager -- pointer to a ChvManager object for the list
of free Chv objects
created -- 98may04, cca
---------------------------------------------------------
*/
void
FrontMtx_storePostponedData (
FrontMtx *frontmtx,
Chv *frontJ,
int npost,
int K,
ChvList *chvlist,
ChvManager *chvmanager
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in storeFront.c ------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------------------------
purpose -- to store the factor indicies and entries from front J
pivotsizesIV -- used for symmetric or hermitian and pivoting
droptol -- used for drop tolerance factorization,
an entry is stored if its magnitude > droptol
created -- 98may04, cca
----------------------------------------------------------------
*/
void
FrontMtx_storeFront (
FrontMtx *frontmtx,
Chv *frontJ,
IV *pivotsizesIV,
double droptol,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in postProcess.c -----------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------------
purpose -- post-process the factorization
(1) permute row and column adjacency objects if necessary
(2) permute lower and upper matrices if necessary
(3) update the block adjacency objects if necessary
(4) split the chevron submatrices into submatrices
and make the submatrix indices local w.r.t their fronts
created -- 98mar05, cca
--------------------------------------------------------------
*/
void
FrontMtx_postProcess (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in permute.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------------
purpose -- permute the upper adjacency structure so that the
indices in bnd{J} are in ascending order w.r.t. their ancestors
created -- 98mar05, cca
------------------------------------------------------------------
*/
void
FrontMtx_permuteUpperAdj (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) ;
/*
------------------------------------------------------------------
purpose -- permute the lower adjacency structure so that the
indices in bnd{J} are in ascending order w.r.t. their ancestors
created -- 98mar05, cca
------------------------------------------------------------------
*/
void
FrontMtx_permuteLowerAdj (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) ;
/*
------------------------------------------------------------
purpose -- if the columns indices of the front matrix are in
different order than the column indices of U_{J,bnd{J}},
sort the columns of U_{J,bnd{J}} into ascending order
w.r.t the column indices of the front matrix.
created -- 98mar05, cca
------------------------------------------------------------
*/
void
FrontMtx_permuteUpperMatrices (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) ;
/*
--------------------------------------------------------
purpose -- if the row indices of the front matrix are in
different order than the row indices of L_{bnd{J},J},
sort the rows of L_{bnd{J},J} into ascending order
w.r.t the row indices of the front matrix.
created -- 98mar05, cca
--------------------------------------------------------
*/
void
FrontMtx_permuteLowerMatrices (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in split.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------------------------
purpose -- for each U_{J,bnd{J}} matrix, remove from hash table,
split into their U_{J,K} submatrices and insert
into the hash table.
created -- 98may04, cca
----------------------------------------------------------------
*/
void
FrontMtx_splitUpperMatrices (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) ;
/*
----------------------------------------------------------------
purpose -- for each L_{bnd{J},J} matrix, remove from hash table,
split into their L_{K,J} submatrices and insert
into the hash table.
created -- 98may04, cca
----------------------------------------------------------------
*/
void
FrontMtx_splitLowerMatrices (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in solve.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------------
purpose -- to solve a linear system
frontmtx -- FrontMtx object that holds the factor matrices
solmtx -- DenseMtx that holds the solution
rhsmtx -- DenseMtx that holds the right hand side matrix
note: right hand side entries are copied from rhsmtx,
and solution entries are copied into solmtx.
when the row indices of rhsmtx and solmtx are
identical, rhsmtx and solmtx can be the same object.
cpus -- vector to hold cpu breakdown time
cpus[0] -- set up solves
cpus[1] -- fetch rhs and store solution
cpus[2] -- forward solve
cpus[3] -- diagonal solve
cpus[4] -- backward solve
cpus[5] -- total time
mtxmanager -- object that manages working storage
msglvl -- message level
msgFile -- message file
created -- 98may04, cca
------------------------------------------------------------
*/
void
FrontMtx_solve (
FrontMtx *frontmtx,
DenseMtx *solmtx,
DenseMtx *rhsmtx,
SubMtxManager *mtxmanager,
double cpus[],
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in solveUtil.c -------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------
load the right hand side for the owned fronts
created -- 98mar19, cca
---------------------------------------------
*/
SubMtx **
FrontMtx_loadRightHandSide (
FrontMtx *frontmtx,
DenseMtx *rhsmtx,
int owners[],
int myid,
SubMtxManager *mtxmanager,
int msglvl,
FILE *msgFile
) ;
/*
--------------------------------------
visit front J during the forward solve
created -- 98mar27, cca
--------------------------------------
*/
void
FrontMtx_forwardVisit (
FrontMtx *frontmtx,
int J,
int nrhs,
int *owners,
int myid,
SubMtxManager *mtxmanager,
SubMtxList *aggList,
SubMtx *p_mtx[],
char frontIsDone[],
IP *heads[],
SubMtx *p_agg[],
char status[],
int msglvl,
FILE *msgFile
) ;
/*
--------------------------------------------------
purpose -- visit front J during the diagonal solve
created -- 98feb20, cca
--------------------------------------------------
*/
void
FrontMtx_diagonalVisit (
FrontMtx *frontmtx,
int J,
int owners[],
int myid,
SubMtx *p_mtx[],
char frontIsDone[],
SubMtx *p_agg[],
int msglvl,
FILE *msgFile
) ;
/*
---------------------------------------
visit front J during the backward solve
created -- 98mar27, cca
---------------------------------------
*/
void
FrontMtx_backwardVisit (
FrontMtx *frontmtx,
int J,
int nrhs,
int *owners,
int myid,
SubMtxManager *mtxmanager,
SubMtxList *aggList,
SubMtx *p_mtx[],
char frontIsDone[],
IP *heads[],
SubMtx *p_agg[],
char status[],
int msglvl,
FILE *msgFile
) ;
/*
---------------------------------------------------
purpose -- move the solution from the individual
SubMtx objects into the global solution SubMtx object
created -- 98feb20
---------------------------------------------------
*/
void
FrontMtx_storeSolution (
FrontMtx *frontmtx,
int owners[],
int myid,
SubMtxManager *manager,
SubMtx *p_mtx[],
DenseMtx *solmtx,
int msglvl,
FILE *msgFile
) ;
/*
---------------------------------------------------
purpose -- load the dequeue with the roots of the
active subtree used for a backward solve
created -- 98mar27, cca
---------------------------------------------------
*/
void
FrontMtx_loadActiveRoots (
FrontMtx *frontmtx,
char status[],
char activeFlag,
Ideq *dequeue
) ;
/*
--------------------------------------------------------------------
purpose -- to set up the link data structures for a forward solve
return value -- pointer to IP *heads[nfront+2], which contains
the beginning of a list of IP objects that store the remaining
updates to the fronts.
note, heads[nfront] is the first IP object in the free list.
heads[nfront+1] is the base address of the allocated IP objects.
created -- 98feb20, cca
--------------------------------------------------------------------
*/
IP **
FrontMtx_forwardSetup (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) ;
/*
---------------------------------------------------------
purpose -- set up the linked lists for the backward solve
created -- 98feb20, cca
---------------------------------------------------------
*/
IP **
FrontMtx_backwardSetup (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in QRfactor.c --------------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------
purpose -- to compute the (U+I)D(I+U) factorization of A^TA,
where A = QR, R = (D^{1/2} + D^{1/2}U)
cpus[0] -- setup time
cpus[1] -- initialize and load staircase matrix
cpus[2] -- permute the rows into staircase form
cpus[3] -- factor the matrix
cpus[4] -- scale and store factor entries
cpus[5] -- store update entries
cpus[6] -- miscellaneous time
created -- 98may28, cca
------------------------------------------------------------
*/
void
FrontMtx_QR_factor (
FrontMtx *frontmtx,
InpMtx *mtxA,
ChvManager *chvmanager,
double cpus[],
double *pfacops,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in QRsolve.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------
minimize ||b - Ax||_2 by
solving (U^T + I) * D * (I + U) X = A^T * B
where A = QR = QD(I + U)
by calling FrontMtx_solve()
mtxmanager -- object that manages working storage
cpus -- vector of cpu time breakdowns
cpus[0] -- set up solves
cpus[1] -- fetch rhs and store solution
cpus[2] -- forward solve
cpus[3] -- diagonal solve
cpus[4] -- backward solve
cpus[5] -- total solve time
cpus[6] -- time to compute A^T * B
cpus[7] -- total time
created -- 97may27, dkw
modified -- 98may28, cca
-------------------------------------------------
*/
void
FrontMtx_QR_solve (
FrontMtx *frontmtx,
InpMtx *mtxA,
DenseMtx *mtxX,
DenseMtx *mtxB,
SubMtxManager *manager,
double cpus[],
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in QRutil.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------------------
purpose -- to setup two data structures for a QR serial
or multithreaded factorization
rowsIVL[J] -- list of rows of A to be assembled into front J
firstnz[irow] -- column with location of leading nonzero of row in A
created -- 98may29, cca
--------------------------------------------------------------------
*/
void
FrontMtx_QR_setup (
FrontMtx *frontmtx,
InpMtx *mtxA,
IVL **prowsIVL,
int **pfirstnz,
int msglvl,
FILE *msgFile
) ;
/*
-----------------------------------------------
purpose -- visit front J during a serial
or multithreaded QR factorization
cpus[1] -- initialize and load staircase matrix
cpus[2] -- factor the matrix
cpus[3] -- scale and store factor entries
cpus[4] -- store update entries
created -- 98may28, cca
-----------------------------------------------
*/
void
FrontMtx_QR_factorVisit (
FrontMtx *frontmtx,
int J,
InpMtx *mtxA,
IVL *rowsIVL,
int firstnz[],
ChvList *updlist,
ChvManager *chvmanager,
char status[],
int colmap[],
DV *workDV,
double cpus[],
double *pfacops,
int msglvl,
FILE *msgFile
) ;
/*
--------------------------------------------------------------
purpose -- create and return an A2 object that contains rows
of A and rows from update matrices of the children.
the matrix may not be in staircase form
created -- 98may25, cca
--------------------------------------------------------------
*/
A2 *
FrontMtx_QR_assembleFront (
FrontMtx *frontmtx,
int J,
InpMtx *mtxA,
IVL *rowsIVL,
int firstnz[],
int colmap[],
Chv *firstchild,
DV *workDV,
int msglvl,
FILE *msgFile
) ;
/*
----------------------------------------------------
store the factor entries of the reduced front matrix
created -- 98may25, cca
----------------------------------------------------
*/
void
FrontMtx_QR_storeFront (
FrontMtx *frontmtx,
int J,
A2 *frontJ,
int msglvl,
FILE *msgFile
) ;
/*
-------------------------------------------------
purpose -- to create and return a Chv object that
holds the update matrix for front J
created -- 98may25, cca
-------------------------------------------------
*/
Chv *
FrontMtx_QR_storeUpdate (
FrontMtx *frontmtx,
int J,
A2 *frontJ,
ChvManager *chvmanager,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in util.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------
purpose -- produce a map from each column
to the front that contains it
created -- 98may04, cca
-----------------------------------------
*/
IV *
FrontMtx_colmapIV (
FrontMtx *frontmtx
) ;
/*
--------------------------------------------------------------------
purpose -- produce a map from each row to the front that contains it
created -- 98may04, cca
--------------------------------------------------------------------
*/
IV *
FrontMtx_rowmapIV (
FrontMtx *frontmtx
) ;
/*
-------------------------------------------------------------
compute the inertia of a symmetric matrix
fill *pnnegative with the number of negative eigenvalues of A
fill *pnzero with the number of zero eigenvalues of A
fill *pnpositive with the number of positive eigenvalues of A
created -- 98may04, cca
-------------------------------------------------------------
*/
void
FrontMtx_inertia (
FrontMtx *frontmtx,
int *pnnegative,
int *pnzero,
int *pnpositive
) ;
/*
-------------------------------------------------------
purpose -- create and return an IV object that contains
all the row ids owned by process myid.
created -- 98jun13, cca
-------------------------------------------------------
*/
IV *
FrontMtx_ownedRowsIV (
FrontMtx *frontmtx,
int myid,
IV *ownersIV,
int msglvl,
FILE *msgFile
) ;
/*
-------------------------------------------------------
purpose -- create and return an IV object that contains
all the column ids owned by process myid.
created -- 98jun13, cca
-------------------------------------------------------
*/
IV *
FrontMtx_ownedColumnsIV (
FrontMtx *frontmtx,
int myid,
IV *ownersIV,
int msglvl,
FILE *msgFile
) ;
/*
----------------------------------------------------------------
purpose -- to create and return an IVL object that holds the
submatrix nonzero pattern for the upper triangular factor.
NOTE: this method supercedes calling IVL_mapEntries() on
the column adjacency structure. that gave problems when
pivoting forced some fronts to have no eliminated columns.
in some cases, solve aggregates were expected when none
were forthcoming.
created -- 98aug20, cca
----------------------------------------------------------------
*/
IVL *
FrontMtx_makeUpperBlockIVL (
FrontMtx *frontmtx,
IV *colmapIV
) ;
/*
----------------------------------------------------------------
purpose -- to create and return an IVL object that holds the
submatrix nonzero pattern for the lower triangular factor.
NOTE: this method supercedes calling IVL_mapEntries() on
the row adjacency structure. that gave problems when
pivoting forced some fronts to have no eliminated columns.
in some cases, solve aggregates were expected when none
were forthcoming.
created -- 98aug20, cca
----------------------------------------------------------------
*/
IVL *
FrontMtx_makeLowerBlockIVL (
FrontMtx *frontmtx,
IV *rowmapIV
) ;
/*
---------------------------------------------------------------
purpose -- to compute and return the number of floating point
operations to perform a solve with a single right hand side.
created -- 98sep26, cca
---------------------------------------------------------------
*/
int
FrontMtx_nSolveOps (
FrontMtx *frontmtx
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in IO.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------
purpose -- to read in an FrontMtx object from a file
input --
fn -- filename, must be *.frontmtxb or *.frontmtxf
return value -- 1 if success, 0 if failure
created -- 98may04, cca
-----------------------------------------------------
*/
int
FrontMtx_readFromFile (
FrontMtx *frontmtx,
char *fn
) ;
/*
------------------------------------------------------------
purpose -- to read an FrontMtx object from a formatted file
return value -- 1 if success, 0 if failure
created -- 98may04, cca
------------------------------------------------------------
*/
int
FrontMtx_readFromFormattedFile (
FrontMtx *frontmtx,
FILE *fp
) ;
/*
--------------------------------------------------------
purpose -- to read an FrontMtx object from a binary file
return value -- 1 if success, 0 if failure
created -- 98may04, cca
--------------------------------------------------------
*/
int
FrontMtx_readFromBinaryFile (
FrontMtx *frontmtx,
FILE *fp
) ;
/*
-------------------------------------------------
purpose -- to write an FrontMtx object to a file
input --
fn -- filename
*.frontmtxb -- binary
*.frontmtxf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 98may04, cca
-------------------------------------------------
*/
int
FrontMtx_writeToFile (
FrontMtx *frontmtx,
char *fn
) ;
/*
-----------------------------------------------------------
purpose -- to write an FrontMtx object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 98may04, cca
-----------------------------------------------------------
*/
int
FrontMtx_writeToFormattedFile (
FrontMtx *frontmtx,
FILE *fp
) ;
/*
-------------------------------------------------------
purpose -- to write an FrontMtx object to a binary file
return value -- 1 if success, 0 otherwise
created -- 98may04, cca
-------------------------------------------------------
*/
int
FrontMtx_writeToBinaryFile (
FrontMtx *frontmtx,
FILE *fp
) ;
/*
---------------------------------------------------------------
purpose -- to write out the statistics for the FrontMtx object
return value -- 1 if success, 0 otherwise
created -- 98may04, cca
---------------------------------------------------------------
*/
int
FrontMtx_writeStats (
FrontMtx *frontmtx,
FILE *fp
) ;
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
created -- 98may04, cca
----------------------------------------
*/
int
FrontMtx_writeForHumanEye (
FrontMtx *frontmtx,
FILE *fp
) ;
/*
-------------------------------------------------------------
purpose -- to write the factor matrices out for a matlab file
Lname -- name for lower triangular matrix
Dname -- name for diagonal matrix
Uname -- name for upper triangular matrix
presently works only with 1-d data decomposition
created -- 98sep23, cca
-------------------------------------------------------------
*/
int
FrontMtx_writeForMatlab (
FrontMtx *frontmtx,
char *Lname,
char *Dname,
char *Uname,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
ing nonzero of row in A
created -- 98may29, cca
--------------------------------------------------------------------
*/
void
FrontMtx_QR_setup (
FrontMtx *frontmtx,
InpMtx *mtxA,
IVL **prowsIVL,
int **pfirstnz,
int msglvl,
FILE *msgFile
) ;
/*
-----------------------------------------------
purpose -- visit front J during a serial
or multithreaded QR fFrontMtx/makefile 0100644 0002055 0007177 00000000223 06636223577 0015367 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd drivers ; make clean
cd doc ; make clean
FrontMtx/src/makefile 0100644 0002055 0007177 00000001556 06636023065 0016156 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = FrontMtx
$(OBJ).a : \
$(OBJ).a(basics.o) \
$(OBJ).a(factor.o) \
$(OBJ).a(factorUtil.o) \
$(OBJ).a(init.o) \
$(OBJ).a(instance.o) \
$(OBJ).a(IO.o) \
$(OBJ).a(loadEntries.o) \
$(OBJ).a(permute.o) \
$(OBJ).a(postponed.o) \
$(OBJ).a(postProcess.o) \
$(OBJ).a(QRfactor.o) \
$(OBJ).a(QRsolve.o) \
$(OBJ).a(QRutil.o) \
$(OBJ).a(solve.o) \
$(OBJ).a(solveUtil.o) \
$(OBJ).a(split.o) \
$(OBJ).a(storeFront.o) \
$(OBJ).a(update.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
FrontMtx/src/makeGlobalLib 0100644 0002055 0007177 00000001231 06600261022 0017040 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = FrontMtx
SRC = basics.c \
factor.c \
factorUtil.c \
init.c \
instance.c \
IO.c \
loadEntries.c \
permute.c \
postponed.c \
postProcess.c \
QRfactor.c \
QRsolve.c \
QRutil.c \
solve.c \
solveUtil.c \
split.c \
storeFront.c \
update.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
FrontMtx/src/IO.c 0100644 0002055 0007177 00000173221 06612223352 0015123 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../FrontMtx.h"
static const char *suffixb = ".frontmtxb" ;
static const char *suffixf = ".frontmtxf" ;
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------
purpose -- to read in an FrontMtx object from a file
input --
fn -- filename, must be *.frontmtxb or *.frontmtxf
return value -- 1 if success, 0 if failure
created -- 98may04, cca
-----------------------------------------------------
*/
int
FrontMtx_readFromFile (
FrontMtx *frontmtx,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || fn == NULL ) {
fprintf(stderr, "\n error in FrontMtx_readFromFile(%p,%s)"
"\n bad input\n", frontmtx, fn) ;
return(0) ;
}
/*
-------------
read the file
-------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "rb")) == NULL ) {
fprintf(stderr, "\n error in FrontMtx_readFromFile(%p,%s)"
"\n unable to open file %s", frontmtx, fn, fn) ;
rc = 0 ;
} else {
rc = FrontMtx_readFromBinaryFile(frontmtx, fp) ;
#if MYDEBUG > 0
fprintf(stdout,
"\n rc = %d from FrontMtx_readFromBinaryFile()", rc) ;
fflush(stdout) ;
#endif
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "r")) == NULL ) {
fprintf(stderr, "\n error in FrontMtx_readFromFile(%p,%s)"
"\n unable to open file %s", frontmtx, fn, fn) ;
rc = 0 ;
} else {
rc = FrontMtx_readFromFormattedFile(frontmtx, fp) ;
fclose(fp) ;
}
} else {
fprintf(stderr, "\n error in FrontMtx_readFromFile(%p,%s)"
"\n bad FrontMtx file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
frontmtx, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
} else {
fprintf(stderr, "\n error in FrontMtx_readFromFile(%p,%s)"
"\n bad FrontMtx file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
frontmtx, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
#if MYDEBUG > 0
fprintf(stdout,
"\n returning rc = %d from FrontMtx_readFromFile()", rc) ;
fflush(stdout) ;
#endif
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
purpose -- to read an FrontMtx object from a formatted file
return value -- 1 if success, 0 if failure
created -- 98may04, cca
------------------------------------------------------------
*/
int
FrontMtx_readFromFormattedFile (
FrontMtx *frontmtx,
FILE *fp
) {
SubMtx *mtx ;
int imtx, J, JK, KJ, nfront, nmtx, rc ;
int itemp[10] ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || fp == NULL ) {
fprintf(stderr, "\n error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n bad input\n", frontmtx, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
FrontMtx_clearData(frontmtx) ;
/*
-----------------------------
read in the ten scalar fields
-----------------------------
*/
if ( (rc = IVfscanf(fp, 10, itemp)) != 10 ) {
fprintf(stderr, "\n error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", frontmtx, fp, rc, 10) ;
return(0) ;
}
frontmtx->nfront = nfront = itemp[0] ;
frontmtx->neqns = itemp[1] ;
frontmtx->type = itemp[2] ;
frontmtx->symmetryflag = itemp[3] ;
frontmtx->pivotingflag = itemp[4] ;
frontmtx->sparsityflag = itemp[5] ;
frontmtx->dataMode = itemp[6] ;
frontmtx->nentD = itemp[7] ;
frontmtx->nentL = itemp[8] ;
frontmtx->nentU = itemp[9] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n nfront = %d"
"\n neqns = %d"
"\n type = %d"
"\n symmetryflag = %d"
"\n pivotingflag = %d"
"\n sparsityflag = %d"
"\n dataMode = %d"
"\n nentD = %d"
"\n nentL = %d"
"\n nentU = %d",
frontmtx->nfront, frontmtx->neqns, frontmtx->type,
frontmtx->symmetryflag, frontmtx->pivotingflag,
frontmtx->sparsityflag, frontmtx->dataMode,
frontmtx->nentD, frontmtx->nentL, frontmtx->nentU) ;
fflush(stdout) ;
#endif
/*
------------------------
read in the ETree object
------------------------
*/
frontmtx->frontETree = ETree_new() ;
rc = ETree_readFromFormattedFile(frontmtx->frontETree, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in frontETree object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->tree = frontmtx->frontETree->tree ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n ETree object") ;
ETree_writeForHumanEye(frontmtx->frontETree, stdout) ;
fflush(stdout) ;
#endif
/*
-----------------------------------------
read in the symbolic factorization object
-----------------------------------------
*/
frontmtx->symbfacIVL = IVL_new() ;
frontmtx->symbfacIVL->type = IVL_CHUNKED ;
rc = IVL_readFromFormattedFile(frontmtx->symbfacIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in symbfacIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->frontsizesIV = IV_new() ;
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
/*
---------------------------------
read in the front sizes IV object
---------------------------------
*/
rc = IV_readFromFormattedFile(frontmtx->frontsizesIV, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in frontsizesIV object\n",
frontmtx, fp, rc) ;
return(0) ;
}
} else {
/*
----------------------------
create from the ETree object
----------------------------
*/
IV_init(frontmtx->frontsizesIV, frontmtx->nfront, NULL) ;
IVcopy(nfront, IV_entries(frontmtx->frontsizesIV),
ETree_nodwghts(frontmtx->frontETree)) ;
}
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
/*
-----------------------------------------
read in the rowids and colids IVL objects
-----------------------------------------
*/
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
frontmtx->rowadjIVL = IVL_new() ;
frontmtx->rowadjIVL->type = IVL_CHUNKED ;
rc = IVL_readFromFormattedFile(frontmtx->rowadjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in rowadjIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
}
frontmtx->coladjIVL = IVL_new() ;
frontmtx->coladjIVL->type = IVL_CHUNKED ;
rc = IVL_readFromFormattedFile(frontmtx->coladjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in coladjIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
fprintf(stdout, "\n coladjIVL read in") ;
fflush(stdout) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
/*
-------------------------------
set up the five pointer vectors
-------------------------------
*/
ALLOCATE(frontmtx->p_mtxDJJ, struct _SubMtx *, nfront) ;
ALLOCATE(frontmtx->p_mtxUJJ, struct _SubMtx *, nfront) ;
ALLOCATE(frontmtx->p_mtxUJN, struct _SubMtx *, nfront) ;
for ( J = 0 ; J < nfront ; J++ ) {
frontmtx->p_mtxDJJ[J] = NULL ;
frontmtx->p_mtxUJJ[J] = NULL ;
frontmtx->p_mtxUJN[J] = NULL ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
ALLOCATE(frontmtx->p_mtxLJJ, struct _SubMtx *, nfront) ;
ALLOCATE(frontmtx->p_mtxLNJ, struct _SubMtx *, nfront) ;
for ( J = 0 ; J < nfront ; J++ ) {
frontmtx->p_mtxLJJ[J] = NULL ;
frontmtx->p_mtxLNJ[J] = NULL ;
}
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
-----------------------------
read in the lower matrices
-----------------------------
*/
fscanf(fp, " %d", &nmtx) ;
for ( imtx = 0 ; imtx < nmtx ; imtx++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromFormattedFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxLJJ[mtx->colid] = mtx ;
}
fscanf(fp, " %d", &nmtx) ;
for ( imtx = 0 ; imtx < nmtx ; imtx++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromFormattedFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxLNJ[mtx->colid] = mtx ;
}
}
/*
-----------------------------
read in the diagonal matrices
-----------------------------
*/
fscanf(fp, " %d", &nmtx) ;
for ( imtx = 0 ; imtx < nmtx ; imtx++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromFormattedFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxDJJ[mtx->rowid] = mtx ;
}
/*
--------------------------
read in the upper matrices
--------------------------
*/
fscanf(fp, " %d", &nmtx) ;
for ( imtx = 0 ; imtx < nmtx ; imtx++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromFormattedFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxUJJ[mtx->rowid] = mtx ;
}
fscanf(fp, " %d", &nmtx) ;
for ( imtx = 0 ; imtx < nmtx ; imtx++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromFormattedFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxUJN[mtx->rowid] = mtx ;
}
} else {
/*
-------------------------------------------------------
read in the lower and upper block adjacency IVL objects
-------------------------------------------------------
*/
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
frontmtx->lowerblockIVL = IVL_new() ;
frontmtx->lowerblockIVL->type = IVL_CHUNKED ;
rc = IVL_readFromFormattedFile(frontmtx->lowerblockIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in lowerblockIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
}
frontmtx->upperblockIVL = IVL_new() ;
frontmtx->upperblockIVL->type = IVL_CHUNKED ;
rc = IVL_readFromFormattedFile(frontmtx->upperblockIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in upperblockIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
--------------------------------------------------------------
read in the lower submatrices and store them into a hash table
--------------------------------------------------------------
*/
frontmtx->lowerhash = I2Ohash_new() ;
fscanf(fp, " %d", &nmtx) ;
I2Ohash_init(frontmtx->lowerhash, nfront - 1, nmtx, 0) ;
for ( KJ = 0 ; KJ < nmtx ; KJ++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromFormattedFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in lower SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
I2Ohash_insert(frontmtx->lowerhash,
mtx->rowid, mtx->colid, (void *) mtx) ;
}
}
/*
-----------------------------------------------------------------
read in the diagonal submatrices and store them into a hash table
-----------------------------------------------------------------
*/
ALLOCATE(frontmtx->p_mtxDJJ, struct _SubMtx *, nfront) ;
for ( J = 0 ; J < nfront ; J++ ) {
frontmtx->p_mtxDJJ[J] = NULL ;
}
fscanf(fp, " %d", &nmtx) ;
for ( J = 0 ; J < nmtx ; J++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromFormattedFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxDJJ[mtx->rowid] = mtx ;
}
/*
--------------------------------------------------------------
read in the upper submatrices and store them into a hash table
--------------------------------------------------------------
*/
frontmtx->upperhash = I2Ohash_new() ;
fscanf(fp, " %d", &nmtx) ;
I2Ohash_init(frontmtx->upperhash, nfront-1, nmtx, 0) ;
for ( JK = 0 ; JK < nmtx ; JK++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromFormattedFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromFormattedFile(%p,%p)"
"\n error %d reading in upper SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
I2Ohash_insert(frontmtx->upperhash,
mtx->rowid, mtx->colid, (void *) mtx) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- to read an FrontMtx object from a binary file
return value -- 1 if success, 0 if failure
created -- 98may04, cca
--------------------------------------------------------
*/
int
FrontMtx_readFromBinaryFile (
FrontMtx *frontmtx,
FILE *fp
) {
SubMtx *mtx ;
int imtx, J, JK, KJ, nfront, nmtx, rc ;
int itemp[10] ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || fp == NULL ) {
fprintf(stderr, "\n error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n bad input\n", frontmtx, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
FrontMtx_clearData(frontmtx) ;
/*
-----------------------------
read in the ten scalar fields
-----------------------------
*/
if ( (rc = fread((void *) itemp, sizeof(int), 10, fp)) != 10 ) {
fprintf(stderr, "\n error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", frontmtx, fp, rc, 10) ;
return(0) ;
}
frontmtx->nfront = nfront = itemp[0] ;
frontmtx->neqns = itemp[1] ;
frontmtx->type = itemp[2] ;
frontmtx->symmetryflag = itemp[3] ;
frontmtx->pivotingflag = itemp[4] ;
frontmtx->sparsityflag = itemp[5] ;
frontmtx->dataMode = itemp[6] ;
frontmtx->nentD = itemp[7] ;
frontmtx->nentL = itemp[8] ;
frontmtx->nentU = itemp[9] ;
#if MYDEBUG > 0
fprintf(stdout,
"\n\n nfront = %d"
"\n neqns = %d"
"\n type = %d"
"\n symmetryflag = %d"
"\n pivotingflag = %d"
"\n sparsityflag = %d"
"\n dataMode = %d"
"\n nentD = %d"
"\n nentL = %d"
"\n nentU = %d",
frontmtx->nfront, frontmtx->neqns, frontmtx->type,
frontmtx->symmetryflag, frontmtx->pivotingflag,
frontmtx->sparsityflag, frontmtx->dataMode,
frontmtx->nentD, frontmtx->nentL, frontmtx->nentU) ;
fflush(stdout) ;
#endif
/*
------------------------
read in the ETree object
------------------------
*/
frontmtx->frontETree = ETree_new() ;
rc = ETree_readFromBinaryFile(frontmtx->frontETree, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in frontETree object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->tree = frontmtx->frontETree->tree ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n ETree object") ;
ETree_writeForHumanEye(frontmtx->frontETree, stdout) ;
fflush(stdout) ;
#endif
/*
-----------------------------------------
read in the symbolic factorization object
-----------------------------------------
*/
frontmtx->symbfacIVL = IVL_new() ;
frontmtx->symbfacIVL->type = IVL_CHUNKED ;
rc = IVL_readFromBinaryFile(frontmtx->symbfacIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in symbfacIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n symbfacIVL object") ;
IVL_writeForHumanEye(frontmtx->symbfacIVL, stdout) ;
fflush(stdout) ;
#endif
frontmtx->frontsizesIV = IV_new() ;
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
/*
---------------------------------
read in the front sizes IV object
---------------------------------
*/
rc = IV_readFromBinaryFile(frontmtx->frontsizesIV, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in frontsizesIV object\n",
frontmtx, fp, rc) ;
return(0) ;
}
} else {
/*
----------------------------
create from the ETree object
----------------------------
*/
IV_init(frontmtx->frontsizesIV, frontmtx->nfront, NULL) ;
IVcopy(nfront, IV_entries(frontmtx->frontsizesIV),
ETree_nodwghts(frontmtx->frontETree)) ;
}
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
/*
-----------------------------------------
read in the rowids and colids IVL objects
-----------------------------------------
*/
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
frontmtx->rowadjIVL = IVL_new() ;
frontmtx->rowadjIVL->type = IVL_CHUNKED ;
rc = IVL_readFromBinaryFile(frontmtx->rowadjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in rowadjIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n rowadjIVL object") ;
IVL_writeForHumanEye(frontmtx->rowadjIVL, stdout) ;
fflush(stdout) ;
#endif
}
frontmtx->coladjIVL = IVL_new() ;
frontmtx->coladjIVL->type = IVL_CHUNKED ;
rc = IVL_readFromBinaryFile(frontmtx->coladjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in coladjIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n coladjIVL object") ;
IVL_writeForHumanEye(frontmtx->coladjIVL, stdout) ;
fflush(stdout) ;
#endif
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
/*
-------------------------------
set up the five pointer vectors
-------------------------------
*/
ALLOCATE(frontmtx->p_mtxDJJ, struct _SubMtx *, nfront) ;
ALLOCATE(frontmtx->p_mtxUJJ, struct _SubMtx *, nfront) ;
ALLOCATE(frontmtx->p_mtxUJN, struct _SubMtx *, nfront) ;
for ( J = 0 ; J < nfront ; J++ ) {
frontmtx->p_mtxDJJ[J] = NULL ;
frontmtx->p_mtxUJJ[J] = NULL ;
frontmtx->p_mtxUJN[J] = NULL ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
ALLOCATE(frontmtx->p_mtxLJJ, struct _SubMtx *, nfront) ;
ALLOCATE(frontmtx->p_mtxLNJ, struct _SubMtx *, nfront) ;
for ( J = 0 ; J < nfront ; J++ ) {
frontmtx->p_mtxLJJ[J] = NULL ;
frontmtx->p_mtxLNJ[J] = NULL ;
}
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
-----------------------------
read in the lower matrices
-----------------------------
*/
if ( (rc = fread((void *) &nmtx, sizeof(int), 1, fp)) != 1 ) {
fprintf(stderr,
"\n error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", frontmtx, fp, rc, 1) ;
return(0) ;
}
for ( imtx = 0 ; imtx < nmtx ; imtx++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromBinaryFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxLJJ[mtx->colid] = mtx ;
}
if ( (rc = fread((void *) &nmtx, sizeof(int), 1, fp)) != 1 ) {
fprintf(stderr,
"\n error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", frontmtx, fp, rc, 1) ;
return(0) ;
}
for ( imtx = 0 ; imtx < nmtx ; imtx++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromBinaryFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxLNJ[mtx->colid] = mtx ;
}
}
/*
-----------------------------
read in the diagonal matrices
-----------------------------
*/
if ( (rc = fread((void *) &nmtx, sizeof(int), 1, fp)) != 1 ) {
fprintf(stderr, "\n error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", frontmtx, fp, rc, 1) ;
return(0) ;
}
for ( imtx = 0 ; imtx < nmtx ; imtx++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromBinaryFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxDJJ[mtx->rowid] = mtx ;
}
/*
--------------------------
read in the upper matrices
--------------------------
*/
if ( (rc = fread((void *) &nmtx, sizeof(int), 1, fp)) != 1 ) {
fprintf(stderr, "\n error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", frontmtx, fp, rc, 1) ;
return(0) ;
}
for ( imtx = 0 ; imtx < nmtx ; imtx++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromBinaryFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxUJJ[mtx->rowid] = mtx ;
}
if ( (rc = fread((void *) &nmtx, sizeof(int), 1, fp)) != 1 ) {
fprintf(stderr, "\n error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", frontmtx, fp, rc, 1) ;
return(0) ;
}
for ( imtx = 0 ; imtx < nmtx ; imtx++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromBinaryFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxUJN[mtx->rowid] = mtx ;
}
} else {
/*
-------------------------------------------------------
read in the lower and upper block adjacency IVL objects
-------------------------------------------------------
*/
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
frontmtx->lowerblockIVL = IVL_new() ;
frontmtx->lowerblockIVL->type = IVL_CHUNKED ;
rc = IVL_readFromBinaryFile(frontmtx->lowerblockIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in lowerblockIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n lowerblockIVL object") ;
IVL_writeForHumanEye(frontmtx->lowerblockIVL, stdout) ;
fflush(stdout) ;
#endif
}
frontmtx->upperblockIVL = IVL_new() ;
frontmtx->upperblockIVL->type = IVL_CHUNKED ;
rc = IVL_readFromBinaryFile(frontmtx->upperblockIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in upperblockIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n upperblockIVL object") ;
IVL_writeForHumanEye(frontmtx->upperblockIVL, stdout) ;
fflush(stdout) ;
#endif
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
--------------------------------------------------------------
read in the lower submatrices and store them into a hash table
--------------------------------------------------------------
*/
frontmtx->lowerhash = I2Ohash_new() ;
if ( (rc = fread((void *) &nmtx, sizeof(int), 1, fp)) != 1 ) {
fprintf(stderr,
"\n error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", frontmtx, fp, rc, 1) ;
return(0) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n nmtx = %d", nmtx) ;
fflush(stdout) ;
#endif
I2Ohash_init(frontmtx->lowerhash, frontmtx->nfront-1, nmtx, 0) ;
for ( KJ = 0 ; KJ < nmtx ; KJ++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromBinaryFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in lower SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
I2Ohash_insert(frontmtx->lowerhash,
mtx->rowid, mtx->colid, (void *) mtx) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n --- lower SubMtx object") ;
SubMtx_writeForHumanEye(mtx, stdout) ;
fflush(stdout) ;
#endif
}
}
/*
-----------------------------------------------------------------
read in the diagonal submatrices and store them into a hash table
-----------------------------------------------------------------
*/
ALLOCATE(frontmtx->p_mtxDJJ, struct _SubMtx *, nfront) ;
for ( J = 0 ; J < nfront ; J++ ) {
frontmtx->p_mtxDJJ[J] = NULL ;
}
if ( (rc = fread((void *) &nmtx, sizeof(int), 1, fp)) != 1 ) {
fprintf(stderr, "\n error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", frontmtx, fp, rc, 1) ;
return(0) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n nmtx = %d", nmtx) ;
fflush(stdout) ;
#endif
for ( J = 0 ; J < nmtx ; J++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromBinaryFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in diag SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
frontmtx->p_mtxDJJ[mtx->rowid] = mtx ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n --- diagonal SubMtx object") ;
SubMtx_writeForHumanEye(mtx, stdout) ;
fflush(stdout) ;
#endif
}
/*
--------------------------------------------------------------
read in the upper submatrices and store them into a hash table
--------------------------------------------------------------
*/
frontmtx->upperhash = I2Ohash_new() ;
if ( (rc = fread((void *) &nmtx, sizeof(int), 1, fp)) != 1 ) {
fprintf(stderr, "\n error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", frontmtx, fp, rc, 1) ;
return(0) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n nmtx = %d", nmtx) ;
fflush(stdout) ;
#endif
I2Ohash_init(frontmtx->upperhash, nfront-1, nmtx, 0) ;
for ( JK = 0 ; JK < nmtx ; JK++ ) {
mtx = SubMtx_new() ;
rc = SubMtx_readFromBinaryFile(mtx, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_readFromBinaryFile(%p,%p)"
"\n error %d reading in upper SubMtx object\n",
frontmtx, fp, rc) ;
return(0) ;
}
I2Ohash_insert(frontmtx->upperhash,
mtx->rowid, mtx->colid, (void *) mtx) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n --- upper SubMtx object") ;
SubMtx_writeForHumanEye(mtx, stdout) ;
fflush(stdout) ;
#endif
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n\n LEAVING READ_FROM_BINARY_FILE") ;
fflush(stdout) ;
#endif
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to write an FrontMtx object to a file
input --
fn -- filename
*.frontmtxb -- binary
*.frontmtxf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 98may04, cca
-------------------------------------------------
*/
int
FrontMtx_writeToFile (
FrontMtx *frontmtx,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || fn == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_writeToFile(%p,%s)"
"\n bad input\n", frontmtx, fn) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in FrontMtx_writeToFile(%p,%s)"
"\n unable to open file %s", frontmtx, fn, fn) ;
rc = 0 ;
} else {
rc = FrontMtx_writeToBinaryFile(frontmtx, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "w")) == NULL ) {
fprintf(stderr, "\n error in FrontMtx_writeToFile(%p,%s)"
"\n unable to open file %s", frontmtx, fn, fn) ;
rc = 0 ;
} else {
rc = FrontMtx_writeToFormattedFile(frontmtx, fp) ;
fclose(fp) ;
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in FrontMtx_writeToFile(%p,%s)"
"\n unable to open file %s", frontmtx, fn, fn) ;
rc = 0 ;
} else {
rc = FrontMtx_writeForHumanEye(frontmtx, fp) ;
fclose(fp) ;
}
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in FrontMtx_writeToFile(%p,%s)"
"\n unable to open file %s", frontmtx, fn, fn) ;
rc = 0 ;
} else {
rc = FrontMtx_writeForHumanEye(frontmtx, fp) ;
fclose(fp) ;
}
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- to write an FrontMtx object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 98may04, cca
-----------------------------------------------------------
*/
int
FrontMtx_writeToFormattedFile (
FrontMtx *frontmtx,
FILE *fp
) {
SubMtx *mtx ;
int ii, J, K, nadj, nfront, nmtx, rc ;
int *adj ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || fp == NULL ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToFormattedFile(%p,%p)"
"\n bad input\n", frontmtx, fp) ;
exit(-1) ;
}
nfront = frontmtx->nfront ;
/*
---------------------------
write the ten scalar fields
---------------------------
*/
rc = fprintf(fp, "\n %d %d %d %d %d %d %d %d %d %d",
frontmtx->nfront, frontmtx->neqns, frontmtx->type,
frontmtx->symmetryflag, frontmtx->pivotingflag,
frontmtx->sparsityflag, frontmtx->dataMode,
frontmtx->nentD, frontmtx->nentL, frontmtx->nentU) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from first fprintf\n",
frontmtx, fp, rc) ;
return(0) ;
}
/*
--------------------------
write out the ETree object
--------------------------
*/
rc = ETree_writeToFormattedFile(frontmtx->frontETree, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToFormattedFile(%p,%p)"
"\n error %d writing frontETree object\n",
frontmtx, fp, rc) ;
return(0) ;
}
/*
-------------------------------------------
write out the symbolic factorization object
-------------------------------------------
*/
rc = IVL_writeToFormattedFile(frontmtx->symbfacIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToFormattedFile(%p,%p)"
"\n error %d writing symbfacIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
/*
--------------------------------
write out the front sizes object
--------------------------------
*/
rc = IV_writeToFormattedFile(frontmtx->frontsizesIV, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToFormattedFile(%p,%p)"
"\n error %d writing frontsizesIV object\n",
frontmtx, fp, rc) ;
return(0) ;
}
}
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
/*
-------------------------------------------
write out the rowids and colids IVL objects
-------------------------------------------
*/
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
rc = IVL_writeToFormattedFile(frontmtx->rowadjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToFormattedFile(%p,%p)"
"\n error %d writing rowadjIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
}
rc = IVL_writeToFormattedFile(frontmtx->coladjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToFormattedFile(%p,%p)"
"\n error %d writing coladjIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
------------------------------------------------
count the number of L_{J,J} matrices
write out the count, then write out the matrices
------------------------------------------------
*/
for ( J = nmtx = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_lowerMtx(frontmtx, J, J)) != NULL ) {
nmtx++ ;
}
}
fprintf(fp, "\n %d", nmtx) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_lowerMtx(frontmtx, J, J)) != NULL ) {
SubMtx_writeToFormattedFile(mtx, fp) ;
}
}
/*
------------------------------------------------
count the number of L_{*,J} matrices
write out the count, then write out the matrices
------------------------------------------------
*/
for ( J = nmtx = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_lowerMtx(frontmtx, nfront, J)) != NULL ){
nmtx++ ;
}
}
fprintf(fp, "\n %d", nmtx) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_lowerMtx(frontmtx, nfront, J)) != NULL ){
SubMtx_writeToFormattedFile(mtx, fp) ;
}
}
}
/*
------------------------------------------------
count the number of diagonal matrices
write out the count, then write out the matrices
------------------------------------------------
*/
for ( J = nmtx = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_diagMtx(frontmtx, J)) != NULL ) {
nmtx++ ;
}
}
fprintf(fp, "\n %d", nmtx) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_diagMtx(frontmtx, J)) != NULL ) {
SubMtx_writeToFormattedFile(mtx, fp) ;
}
}
/*
------------------------------------------------
count the number of U_{J,J} matrices
write out the count, then write out the matrices
------------------------------------------------
*/
for ( J = nmtx = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, J)) != NULL ) {
nmtx++ ;
}
}
fprintf(fp, "\n %d", nmtx) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, J)) != NULL ) {
SubMtx_writeToFormattedFile(mtx, fp) ;
}
}
/*
------------------------------------------------
count the number of U_{J,*} matrices
write out the count, then write out the matrices
------------------------------------------------
*/
for ( J = nmtx = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, nfront)) != NULL ) {
nmtx++ ;
}
}
fprintf(fp, "\n %d", nmtx) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, nfront)) != NULL ) {
SubMtx_writeToFormattedFile(mtx, fp) ;
}
}
} else {
/*
---------------------------------------------------------
write out the lower and upper block adjacency IVL objects
---------------------------------------------------------
*/
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
rc = IVL_writeToFormattedFile(frontmtx->lowerblockIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToFormattedFile(%p,%p)"
"\n error %d writing lowerblockIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
}
rc = IVL_writeToFormattedFile(frontmtx->upperblockIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToFormattedFile(%p,%p)"
"\n error %d writing upperblockIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
-------------------------------
write out the lower submatrices
-------------------------------
*/
for ( J = nmtx = 0 ; J < frontmtx->nfront ; J++ ) {
IVL_listAndSize(frontmtx->lowerblockIVL, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = adj[ii] ;
if ( (mtx = FrontMtx_lowerMtx(frontmtx, K, J)) != NULL ) {
nmtx++ ;
}
}
}
fprintf(fp, "\n %d", nmtx) ;
for ( J = 0 ; J < frontmtx->nfront ; J++ ) {
IVL_listAndSize(frontmtx->lowerblockIVL, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = adj[ii] ;
if ( (mtx = FrontMtx_lowerMtx(frontmtx, K, J)) != NULL ) {
SubMtx_writeToFormattedFile(mtx, fp) ;
}
}
}
}
/*
----------------------------------
write out the diagonal submatrices
----------------------------------
*/
for ( J = nmtx = 0 ; J < frontmtx->nfront ; J++ ) {
if ( (mtx = FrontMtx_diagMtx(frontmtx, J)) != NULL ) {
nmtx++ ;
}
}
fprintf(fp, "\n %d", nmtx) ;
for ( J = 0 ; J < frontmtx->nfront ; J++ ) {
if ( (mtx = FrontMtx_diagMtx(frontmtx, J)) != NULL ) {
SubMtx_writeToFormattedFile(mtx, fp) ;
}
}
/*
-------------------------------
write out the upper submatrices
-------------------------------
*/
for ( J = nmtx = 0 ; J < frontmtx->nfront ; J++ ) {
IVL_listAndSize(frontmtx->upperblockIVL, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = adj[ii] ;
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, K)) != NULL ) {
nmtx++ ;
}
}
}
fprintf(fp, "\n %d", nmtx) ;
for ( J = 0 ; J < frontmtx->nfront ; J++ ) {
IVL_listAndSize(frontmtx->upperblockIVL, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = adj[ii] ;
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, K)) != NULL ) {
SubMtx_writeToFormattedFile(mtx, fp) ;
}
}
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
purpose -- to write an FrontMtx object to a binary file
return value -- 1 if success, 0 otherwise
created -- 98may04, cca
-------------------------------------------------------
*/
int
FrontMtx_writeToBinaryFile (
FrontMtx *frontmtx,
FILE *fp
) {
SubMtx *mtx ;
int ii, J, K, nadj, nfront, nmtx, rc ;
int *adj ;
int itemp[10] ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || fp == NULL ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToBinaryFile(%p,%p)"
"\n bad input\n", frontmtx, fp) ;
exit(-1) ;
}
/*
---------------------------
write the ten scalar fields
---------------------------
*/
itemp[0] = nfront = frontmtx->nfront ;
itemp[1] = frontmtx->neqns ;
itemp[2] = frontmtx->type ;
itemp[3] = frontmtx->symmetryflag ;
itemp[4] = frontmtx->pivotingflag ;
itemp[5] = frontmtx->sparsityflag ;
itemp[6] = frontmtx->dataMode ;
itemp[7] = frontmtx->nentD ;
itemp[8] = frontmtx->nentL ;
itemp[9] = frontmtx->nentU ;
rc = fwrite((void *) itemp, sizeof(int), 10, fp) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from first fprintf\n",
frontmtx, fp, rc) ;
return(0) ;
}
/*
--------------------------
write out the ETree object
--------------------------
*/
rc = ETree_writeToBinaryFile(frontmtx->frontETree, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToBinaryFile(%p,%p)"
"\n error %d writing frontETree object\n",
frontmtx, fp, rc) ;
return(0) ;
}
/*
-------------------------------------------
write out the symbolic factorization object
-------------------------------------------
*/
rc = IVL_writeToBinaryFile(frontmtx->symbfacIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToBinaryFile(%p,%p)"
"\n error %d writing symbfacIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
/*
--------------------------------
write out the front sizes object
--------------------------------
*/
rc = IV_writeToBinaryFile(frontmtx->frontsizesIV, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToBinaryFile(%p,%p)"
"\n error %d writing frontsizesIV object\n",
frontmtx, fp, rc) ;
return(0) ;
}
}
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
/*
-------------------------------------------
write out the rowids and colids IVL objects
-------------------------------------------
*/
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
rc = IVL_writeToBinaryFile(frontmtx->rowadjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToBinaryFile(%p,%p)"
"\n error %d writing rowadjIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
}
rc = IVL_writeToBinaryFile(frontmtx->coladjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToBinaryFile(%p,%p)"
"\n error %d writing coladjIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
------------------------------------------------
count the number of L_{J,J} matrices
write out the count, then write out the matrices
------------------------------------------------
*/
for ( J = nmtx = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_lowerMtx(frontmtx, J, J)) != NULL ) {
nmtx++ ;
}
}
rc = fwrite((void *) &nmtx, sizeof(int), 1, fp) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_lowerMtx(frontmtx, J, J)) != NULL ) {
SubMtx_writeToBinaryFile(mtx, fp) ;
}
}
/*
------------------------------------------------
count the number of L_{*,J} matrices
write out the count, then write out the matrices
------------------------------------------------
*/
for ( J = nmtx = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_lowerMtx(frontmtx, nfront, J)) != NULL ){
nmtx++ ;
}
}
rc = fwrite((void *) &nmtx, sizeof(int), 1, fp) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_lowerMtx(frontmtx, nfront, J)) != NULL ){
SubMtx_writeToBinaryFile(mtx, fp) ;
}
}
}
/*
------------------------------------------------
count the number of diagonal matrices
write out the count, then write out the matrices
------------------------------------------------
*/
for ( J = nmtx = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_diagMtx(frontmtx, J)) != NULL ) {
nmtx++ ;
}
}
rc = fwrite((void *) &nmtx, sizeof(int), 1, fp) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_diagMtx(frontmtx, J)) != NULL ) {
SubMtx_writeToBinaryFile(mtx, fp) ;
}
}
/*
------------------------------------------------
count the number of U_{J,J} matrices
write out the count, then write out the matrices
------------------------------------------------
*/
for ( J = nmtx = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, J)) != NULL ) {
nmtx++ ;
}
}
rc = fwrite((void *) &nmtx, sizeof(int), 1, fp) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, J)) != NULL ) {
SubMtx_writeToBinaryFile(mtx, fp) ;
}
}
/*
------------------------------------------------
count the number of U_{J,*} matrices
write out the count, then write out the matrices
------------------------------------------------
*/
for ( J = nmtx = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, nfront)) != NULL ) {
nmtx++ ;
}
}
rc = fwrite((void *) &nmtx, sizeof(int), 1, fp) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, nfront)) != NULL ) {
SubMtx_writeToBinaryFile(mtx, fp) ;
}
}
} else {
/*
---------------------------------------------------------
write out the lower and upper block adjacency IVL objects
---------------------------------------------------------
*/
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
rc = IVL_writeToBinaryFile(frontmtx->lowerblockIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToBinaryFile(%p,%p)"
"\n error %d writing lowerblockIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
}
rc = IVL_writeToBinaryFile(frontmtx->upperblockIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_writeToBinaryFile(%p,%p)"
"\n error %d writing upperblockIVL object\n",
frontmtx, fp, rc) ;
return(0) ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
-------------------------------
write out the lower submatrices
-------------------------------
*/
for ( J = nmtx = 0 ; J < frontmtx->nfront ; J++ ) {
IVL_listAndSize(frontmtx->lowerblockIVL, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = adj[ii] ;
if ( (mtx = FrontMtx_lowerMtx(frontmtx, K, J)) != NULL ) {
nmtx++ ;
}
}
}
rc = fwrite((void *) &nmtx, sizeof(int), 1, fp) ;
for ( J = 0 ; J < frontmtx->nfront ; J++ ) {
IVL_listAndSize(frontmtx->lowerblockIVL, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = adj[ii] ;
if ( (mtx = FrontMtx_lowerMtx(frontmtx, K, J)) != NULL ) {
SubMtx_writeToBinaryFile(mtx, fp) ;
}
}
}
}
/*
----------------------------------
write out the diagonal submatrices
----------------------------------
*/
for ( J = nmtx = 0 ; J < frontmtx->nfront ; J++ ) {
if ( (mtx = FrontMtx_diagMtx(frontmtx, J)) != NULL ) {
nmtx++ ;
}
}
rc = fwrite((void *) &nmtx, sizeof(int), 1, fp) ;
for ( J = 0 ; J < frontmtx->nfront ; J++ ) {
if ( (mtx = FrontMtx_diagMtx(frontmtx, J)) != NULL ) {
SubMtx_writeToBinaryFile(mtx, fp) ;
}
}
/*
-------------------------------
write out the upper submatrices
-------------------------------
*/
for ( J = nmtx = 0 ; J < frontmtx->nfront ; J++ ) {
IVL_listAndSize(frontmtx->upperblockIVL, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = adj[ii] ;
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, K)) != NULL ) {
nmtx++ ;
}
}
}
rc = fwrite((void *) &nmtx, sizeof(int), 1, fp) ;
for ( J = 0 ; J < frontmtx->nfront ; J++ ) {
IVL_listAndSize(frontmtx->upperblockIVL, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = adj[ii] ;
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, K)) != NULL ) {
SubMtx_writeToBinaryFile(mtx, fp) ;
}
}
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
purpose -- to write out the statistics for the FrontMtx object
return value -- 1 if success, 0 otherwise
created -- 98may04, cca
---------------------------------------------------------------
*/
int
FrontMtx_writeStats (
FrontMtx *frontmtx,
FILE *fp
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || fp == NULL ) {
fprintf(stderr, "\n error in FrontMtx_writeStats(%p,%p)"
"\n bad input\n", frontmtx, fp) ;
exit(-1) ;
}
fprintf(fp, "\n\n FrontMtx object at address %p"
"\n nfront = %d", frontmtx, frontmtx->nfront) ;
switch ( frontmtx->symmetryflag ) {
case SPOOLES_SYMMETRIC :
fprintf(fp, "\n symmetric entries") ;
break ;
case SPOOLES_HERMITIAN :
fprintf(fp, "\n Hermitian") ;
break ;
case SPOOLES_NONSYMMETRIC :
fprintf(fp, "\n nonsymmetric structure, nonsymmetric entries") ;
break ;
default :
break ;
}
switch ( frontmtx->pivotingflag ) {
case SPOOLES_NO_PIVOTING :
fprintf(fp, "\n pivoting disabled") ;
break ;
case SPOOLES_PIVOTING :
fprintf(fp, "\n pivoting enabled") ;
break ;
default :
break ;
}
switch ( frontmtx->sparsityflag ) {
case FRONTMTX_DENSE_FRONTS :
fprintf(fp, "\n dense fronts") ;
break ;
case FRONTMTX_SPARSE_FRONTS :
fprintf(fp, "\n sparse fronts ") ;
break ;
default :
break ;
}
switch ( frontmtx->dataMode ) {
case FRONTMTX_1D_MODE :
fprintf(fp, "\n one-dimensional data decomposition") ;
break ;
case FRONTMTX_2D_MODE :
fprintf(fp, "\n two-dimensional data decomposition") ;
break ;
default :
break ;
}
fprintf(fp, "\n %d entries in D, %d entries in L, %d entries in U",
frontmtx->nentD, frontmtx->nentL, frontmtx->nentU) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------
purpose -- to write the object to a file
in human readable form
created -- 98may04, cca
----------------------------------------
*/
int
FrontMtx_writeForHumanEye (
FrontMtx *frontmtx,
FILE *fp
) {
SubMtx *mtx ;
int ii, J, K, nadj, nfront ;
int *adj ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_writeForHumanEye(%p,%p)"
"\n bad input\n", frontmtx, fp) ;
exit(-1) ;
}
nfront = frontmtx->nfront ;
FrontMtx_writeStats(frontmtx, fp) ;
if ( frontmtx->frontETree != NULL ) {
fprintf(fp, "\n\n front tree FrontMtx object") ;
ETree_writeForHumanEye(frontmtx->frontETree, fp) ;
fflush(fp) ;
}
if ( frontmtx->symbfacIVL != NULL ) {
fprintf(fp, "\n\n symbfacIVL IVL object") ;
IVL_writeForHumanEye(frontmtx->symbfacIVL, fp) ;
fflush(fp) ;
}
if ( frontmtx->frontsizesIV != NULL ) {
fprintf(fp, "\n\n frontsizesIV IV object") ;
IV_writeForHumanEye(frontmtx->frontsizesIV, fp) ;
fflush(fp) ;
}
if ( frontmtx->rowadjIVL != NULL ) {
fprintf(fp, "\n\n rowids IVL object") ;
IVL_writeForHumanEye(frontmtx->rowadjIVL, fp) ;
fflush(fp) ;
}
if ( frontmtx->coladjIVL != NULL ) {
fprintf(fp, "\n\n colids IVL object") ;
IVL_writeForHumanEye(frontmtx->coladjIVL, fp) ;
fflush(fp) ;
}
if ( frontmtx->lowerblockIVL != NULL ) {
fprintf(fp, "\n\n lower block adjacency IVL object") ;
IVL_writeForHumanEye(frontmtx->lowerblockIVL, fp) ;
fflush(fp) ;
}
if ( frontmtx->upperblockIVL != NULL ) {
fprintf(fp, "\n\n upper block adjacency IVL object") ;
IVL_writeForHumanEye(frontmtx->upperblockIVL, fp) ;
fflush(fp) ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
fprintf(fp, "\n\n lower submatrices") ;
for ( J = 0 ; J < nfront ; J++ ) {
mtx = FrontMtx_lowerMtx(frontmtx, J, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n --- lower submatrix -- diagonal") ;
SubMtx_writeForHumanEye(mtx, fp) ;
fflush(fp) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
mtx = FrontMtx_lowerMtx(frontmtx, nfront, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n --- lower submatrix") ;
SubMtx_writeForHumanEye(mtx, fp) ;
fflush(fp) ;
}
} else {
FrontMtx_lowerAdjFronts(frontmtx, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
if ( (K = adj[ii]) > J
&& (mtx = FrontMtx_lowerMtx(frontmtx, K, J)) != NULL ) {
fprintf(fp, "\n\n --- lower submatrix") ;
SubMtx_writeForHumanEye(mtx, fp) ;
fflush(fp) ;
}
}
}
}
}
fprintf(fp, "\n\n diagonal submatrices") ;
for ( J = 0 ; J < nfront ; J++ ) {
mtx = FrontMtx_diagMtx(frontmtx, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n --- diagonal submatrix") ;
SubMtx_writeForHumanEye(mtx, fp) ;
}
fflush(fp) ;
}
fprintf(fp, "\n\n upper submatrices") ;
for ( J = 0 ; J < nfront ; J++ ) {
mtx = FrontMtx_upperMtx(frontmtx, J, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n --- upper submatrix --- diagonal") ;
SubMtx_writeForHumanEye(mtx, fp) ;
fflush(fp) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
mtx = FrontMtx_upperMtx(frontmtx, J, nfront) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n --- upper submatrix") ;
SubMtx_writeForHumanEye(mtx, fp) ;
fflush(fp) ;
}
} else {
FrontMtx_upperAdjFronts(frontmtx, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
if ( (K = adj[ii]) > J
&& (mtx = FrontMtx_upperMtx(frontmtx, J, K)) != NULL ) {
fprintf(fp, "\n\n --- upper submatrix") ;
SubMtx_writeForHumanEye(mtx, fp) ;
fflush(fp) ;
}
}
}
}
fprintf(fp, "\n\n ### leaving FrontMtx_writeForHumanEye") ;
fflush(fp) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
purpose -- to write the factor matrices out for a matlab file
Lname -- name for lower triangular matrix
Dname -- name for diagonal matrix
Uname -- name for upper triangular matrix
presently works only with 1-d data decomposition
created -- 98sep23, cca
-------------------------------------------------------------
*/
int
FrontMtx_writeForMatlab (
FrontMtx *frontmtx,
char *Lname,
char *Dname,
char *Uname,
FILE *fp
) {
int J, nfront ;
SubMtx *mtx ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || Lname == NULL || Dname == NULL
|| Uname == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_writeForMatlab()"
"\n bad input\n") ;
exit(-1) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
nfront = FrontMtx_nfront(frontmtx) ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
fprintf(fp, "\n\n %% lower submatrices") ;
for ( J = 0 ; J < nfront ; J++ ) {
mtx = FrontMtx_lowerMtx(frontmtx, J, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n %% --- lower submatrix -- diagonal") ;
SubMtx_writeForMatlab(mtx, Lname, fp) ;
fflush(fp) ;
}
mtx = FrontMtx_lowerMtx(frontmtx, nfront, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n %% --- lower submatrix") ;
SubMtx_writeForMatlab(mtx, Lname, fp) ;
fflush(fp) ;
}
}
}
fprintf(fp, "\n\n %% diagonal submatrices") ;
for ( J = 0 ; J < nfront ; J++ ) {
mtx = FrontMtx_diagMtx(frontmtx, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n %% --- diagonal submatrix") ;
SubMtx_writeForMatlab(mtx, Dname, fp) ;
}
fflush(fp) ;
}
fprintf(fp, "\n\n %% upper submatrices") ;
for ( J = 0 ; J < nfront ; J++ ) {
mtx = FrontMtx_upperMtx(frontmtx, J, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n %% --- upper submatrix --- diagonal") ;
SubMtx_writeForMatlab(mtx, Uname, fp) ;
fflush(fp) ;
}
mtx = FrontMtx_upperMtx(frontmtx, J, nfront) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n %% --- upper submatrix") ;
SubMtx_writeForMatlab(mtx, Uname, fp) ;
fflush(fp) ;
}
}
} else if ( FRONTMTX_IS_2D_MODE(frontmtx) ) {
nfront = FrontMtx_nfront(frontmtx) ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
int ii, jj, kk, K, nadj, ncolJ, ncolKJ, nrowK, nrowKJ ;
int *adj, *colindJ, *colKJ, *rowindK, *rowKJ ;
fprintf(fp, "\n\n %% lower submatrices") ;
for ( J = 0 ; J < nfront ; J++ ) {
mtx = FrontMtx_lowerMtx(frontmtx, J, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n %% --- lower submatrix -- diagonal") ;
SubMtx_writeForMatlab(mtx, Lname, fp) ;
fflush(fp) ;
}
FrontMtx_lowerAdjFronts(frontmtx, J, &nadj, &adj) ;
for ( kk = 0 ; kk < nadj ; kk++ ) {
if ( (K = adj[kk]) > J
&& (mtx = FrontMtx_lowerMtx(frontmtx, K, J)) != NULL ) {
fprintf(fp, "\n\n %% --- lower submatrix") ;
SubMtx_columnIndices(mtx, &ncolKJ, &colKJ) ;
FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
for ( ii = 0 ; ii < ncolKJ ; ii++ ) {
colKJ[ii] = colindJ[colKJ[ii]] ;
}
SubMtx_rowIndices(mtx, &nrowKJ, &rowKJ) ;
FrontMtx_rowIndices(frontmtx, K, &nrowK, &rowindK) ;
for ( ii = 0 ; ii < nrowKJ ; ii++ ) {
rowKJ[ii] = rowindK[rowKJ[ii]] ;
}
SubMtx_writeForMatlab(mtx, Lname, fp) ;
for ( ii = jj = 0 ; ii < ncolKJ ; ii++ ) {
while ( colKJ[ii] != colindJ[jj] ) {
jj++ ;
}
colKJ[ii] = jj++ ;
}
for ( ii = jj = 0 ; ii < nrowKJ ; ii++ ) {
while ( rowKJ[ii] != rowindK[jj] ) {
jj++ ;
}
rowKJ[ii] = jj++ ;
}
fflush(fp) ;
}
}
}
}
fprintf(fp, "\n\n %% diagonal submatrices") ;
for ( J = 0 ; J < nfront ; J++ ) {
mtx = FrontMtx_diagMtx(frontmtx, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n %% --- diagonal submatrix") ;
SubMtx_writeForMatlab(mtx, Dname, fp) ;
}
fflush(fp) ;
}
fprintf(fp, "\n\n %% upper submatrices") ;
for ( J = 0 ; J < nfront ; J++ ) {
int ii, jj, kk, K, nadj, ncolK, ncolJK, nrowJ, nrowJK ;
int *adj, *colindK, *colJK, *rowindJ, *rowJK ;
mtx = FrontMtx_upperMtx(frontmtx, J, J) ;
if ( mtx != NULL ) {
fprintf(fp, "\n\n %% --- upper submatrix --- diagonal") ;
SubMtx_writeForMatlab(mtx, Uname, fp) ;
fflush(fp) ;
}
FrontMtx_upperAdjFronts(frontmtx, J, &nadj, &adj) ;
for ( kk = 0 ; kk < nadj ; kk++ ) {
if ( (K = adj[kk]) > J
&& (mtx = FrontMtx_upperMtx(frontmtx, J, K)) != NULL ) {
fprintf(fp, "\n\n %% --- upper submatrix") ;
SubMtx_columnIndices(mtx, &ncolJK, &colJK) ;
FrontMtx_columnIndices(frontmtx, K, &ncolK, &colindK) ;
for ( ii = 0 ; ii < ncolJK ; ii++ ) {
colJK[ii] = colindK[colJK[ii]] ;
}
SubMtx_rowIndices(mtx, &nrowJK, &rowJK) ;
FrontMtx_rowIndices(frontmtx, J, &nrowJ, &rowindJ) ;
for ( ii = 0 ; ii < nrowJK ; ii++ ) {
rowJK[ii] = rowindJ[rowJK[ii]] ;
}
SubMtx_writeForMatlab(mtx, Uname, fp) ;
for ( ii = jj = 0 ; ii < ncolJK ; ii++ ) {
while ( colJK[ii] != colindK[jj] ) {
jj++ ;
}
colJK[ii] = jj++ ;
}
for ( ii = jj = 0 ; ii < nrowJK ; ii++ ) {
while ( rowJK[ii] != rowindJ[jj] ) {
jj++ ;
}
rowJK[ii] = jj++ ;
}
fflush(fp) ;
}
}
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
------------------------------------
*/
int
FrontMtx_writeForHumanEye (
FrontMtx *frontmtx,
FILE *fp
) {
SubMtx *mtx ;
int ii, J, K, nadj, nfront ;
int *adj ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_writeForHumanEye(%p,%p)"
FrontMtx/src/QRfactor.c 0100644 0002055 0007177 00000005777 06571267173 0016364 0 ustar 00cleve compmath 0000040 0000006 /* QRfactor.c */
#include "../FrontMtx.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
purpose -- to compute the (U+I)D(I+U) factorization of A^TA,
where A = QR, R = (D^{1/2} + D^{1/2}U)
cpus[0] -- setup time
cpus[1] -- initialize and load staircase matrix
cpus[2] -- factor the matrix
cpus[3] -- scale and store factor entries
cpus[4] -- store update entries
cpus[5] -- miscellaneous time
cpus[6] -- total time
created -- 98may28, cca
------------------------------------------------------------
*/
void
FrontMtx_QR_factor (
FrontMtx *frontmtx,
InpMtx *mtxA,
ChvManager *chvmanager,
double cpus[],
double *pfacops,
int msglvl,
FILE *msgFile
) {
char *status ;
ChvList *updlist ;
double t0, t1, t2, t3 ;
DV workDV ;
int J, neqns, nfront ;
int *colmap, *firstnz ;
IVL *rowsIVL ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
MARKTIME(t0) ;
if ( frontmtx == NULL || mtxA == NULL || chvmanager == NULL
|| cpus == NULL || pfacops == NULL
|| (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr, "\n fatal error in FrontMtx_QR_factor()"
"\n bad input\n") ;
exit(-1) ;
}
neqns = frontmtx->neqns ;
nfront = frontmtx->nfront ;
tree = frontmtx->tree ;
/*
----------------------------------------------------------------
create the update list object
create the rowsIVL object, where
list(J) = list of rows that are assembled in front J
firstnz[irowA] = first column with nonzero element in A(irowA,*)
colmap[neqns] = work vector for mapping
status[neqns] = status vector for fronts
----------------------------------------------------------------
*/
MARKTIME(t1) ;
updlist = ChvList_new() ;
ChvList_init(updlist, nfront+1, NULL, NO_LOCK, NULL) ;
FrontMtx_QR_setup(frontmtx, mtxA, &rowsIVL, &firstnz, msglvl, msgFile) ;
colmap = IVinit(neqns, -1) ;
status = CVinit(nfront, 'W') ;
DV_setDefaultFields(&workDV) ;
MARKTIME(t2) ;
cpus[0] += t2 - t1 ;
/*
--------------------------------------------
loop over the tree in a post-order traversal
--------------------------------------------
*/
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
FrontMtx_QR_factorVisit(frontmtx, J, mtxA, rowsIVL, firstnz, updlist,
chvmanager, status, colmap, &workDV, cpus,
pfacops, msglvl, msgFile) ;
}
/*
------------------------
free the working storage
------------------------
*/
CVfree(status) ;
DV_clearData(&workDV) ;
ChvList_free(updlist) ;
IVL_free(rowsIVL) ;
IVfree(colmap) ;
IVfree(firstnz) ;
MARKTIME(t3) ;
cpus[6] = t3 - t0 ;
cpus[5] = t3 - t0 - cpus[0] - cpus[1]
- cpus[2] - cpus[3] - cpus[4] - cpus[5] ;
return ; }
/*--------------------------------------------------------------------*/
FrontMtx/src/QRsolve.c 0100644 0002055 0007177 00000005204 06571267173 0016217 0 ustar 00cleve compmath 0000040 0000006 /* QRsolve.c */
#include "../FrontMtx.h"
#include "../../timings.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
minimize ||b - Ax||_2 by
solving (U^T + I) * D * (I + U) X = A^T * B
where A = QR = QD(I + U)
by calling FrontMtx_solve()
note: if A is square, mtxX and mtxB must not be the same
mtxmanager -- object that manages working storage
cpus -- vector of cpu time breakdowns
cpus[0] -- set up solves
cpus[1] -- fetch rhs and store solution
cpus[2] -- forward solve
cpus[3] -- diagonal solve
cpus[4] -- backward solve
cpus[5] -- total solve time
cpus[6] -- time to compute A^T * B
cpus[7] -- total time
created -- 97may27, dkw
modified -- 98may28, cca
--------------------------------------------------------
*/
void
FrontMtx_QR_solve (
FrontMtx *frontmtx,
InpMtx *mtxA,
DenseMtx *mtxX,
DenseMtx *mtxB,
SubMtxManager *mtxmanager,
double cpus[],
int msglvl,
FILE *msgFile
) {
double t0, t1, t2 ;
double alpha[2] ;
/*
---------------
check the input
---------------
*/
MARKTIME(t0) ;
if ( frontmtx == NULL || mtxA == NULL || mtxX == NULL || mtxB == NULL
|| cpus == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_QR_solve(%p,%p,%p,%p,%p,%d,%p)"
"\n bad input\n",
frontmtx, mtxA, mtxX, mtxB, cpus, msglvl, msgFile) ;
exit(-1) ;
}
/*
--------------------
compute X := A^T * B
--------------------
*/
MARKTIME(t1) ;
DenseMtx_zero(mtxX) ;
alpha[0] = 1.0 ; alpha[1] = 0.0 ;
if ( FRONTMTX_IS_REAL(frontmtx) ) {
InpMtx_nonsym_mmm_T(mtxA, mtxX, alpha, mtxB) ;
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
InpMtx_nonsym_mmm_H(mtxA, mtxX, alpha, mtxB) ;
}
MARKTIME(t2) ;
cpus[6] = t2 - t1 ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n B") ;
DenseMtx_writeForHumanEye(mtxB, msgFile) ;
fprintf(msgFile, "\n A^T * B") ;
DenseMtx_writeForHumanEye(mtxX, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------------------
solve (U^T + I) * D * (I + U) Z = X
where Z overwrites X
-----------------------------------
*/
MARKTIME(t1) ;
FrontMtx_solve(frontmtx, mtxX, mtxX, mtxmanager,
cpus, msglvl, msgFile) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n computed mtxX") ;
DenseMtx_writeForHumanEye(mtxX, msgFile) ;
fflush(msgFile) ;
}
MARKTIME(t2) ;
cpus[7] = t2 - t0 ;
return ; }
/*--------------------------------------------------------------------*/
FrontMtx/src/QRutil.c 0100644 0002055 0007177 00000046364 06571267173 0016060 0 ustar 00cleve compmath 0000040 0000006 /* QRutil.c */
#include "../FrontMtx.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
purpose -- to setup two data structures for a QR serial
or multithreaded factorization
rowsIVL[J] -- list of rows of A to be assembled into front J
firstnz[irow] -- column with location of leading nonzero of row in A
created -- 98may29, cca
--------------------------------------------------------------------
*/
void
FrontMtx_QR_setup (
FrontMtx *frontmtx,
InpMtx *mtxA,
IVL **prowsIVL,
int **pfirstnz,
int msglvl,
FILE *msgFile
) {
int count, irow, jcol, J, loc, neqns, nfront, nrowA, rowsize ;
int *firstnz, *head, *link, *list, *rowind, *vtxToFront ;
IVL *rowsIVL ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || mtxA == NULL || prowsIVL == NULL
|| pfirstnz == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr, "\n fatal error in FrontMtx_QR_setup()"
"\n bad input\n") ;
exit(-1) ;
}
neqns = FrontMtx_neqns(frontmtx) ;
nfront = FrontMtx_nfront(frontmtx) ;
vtxToFront = ETree_vtxToFront(frontmtx->frontETree) ;
/*
----------------------------------------------------------------
create the rowsIVL object,
list(J) = list of rows that are assembled in front J
firstnz[irowA] = first column with nonzero element in A(irowA,*)
----------------------------------------------------------------
*/
InpMtx_changeCoordType(mtxA, INPMTX_BY_ROWS) ;
InpMtx_changeStorageMode(mtxA, INPMTX_BY_VECTORS) ;
nrowA = 1 + IVmax(InpMtx_nent(mtxA), InpMtx_ivec1(mtxA), &loc) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n nrowA = %d ", nrowA) ;
fflush(msgFile) ;
}
firstnz = IVinit(nrowA, -1) ;
head = IVinit(nfront, -1) ;
link = IVinit(nrowA, -1) ;
for ( irow = nrowA - 1 ; irow >= 0 ; irow-- ) {
InpMtx_vector(mtxA, irow, &rowsize, &rowind) ;
if ( rowsize > 0 ) {
firstnz[irow] = jcol = rowind[0] ;
J = vtxToFront[jcol] ;
link[irow] = head[J] ;
head[J] = irow ;
}
}
rowsIVL = IVL_new() ;
IVL_init2(rowsIVL, IVL_CHUNKED, nfront, nrowA) ;
list = IVinit(neqns, -1) ;
for ( J = 0 ; J < nfront ; J++ ) {
count = 0 ;
for ( irow = head[J] ; irow != -1 ; irow = link[irow] ) {
list[count++] = irow ;
}
if ( count > 0 ) {
IVL_setList(rowsIVL, J, count, list) ;
}
}
IVfree(head) ;
IVfree(link) ;
IVfree(list) ;
/*
---------------------------
set the pointers for return
---------------------------
*/
*prowsIVL = rowsIVL ;
*pfirstnz = firstnz ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
purpose -- visit front J during a serial
or multithreaded QR factorization
cpus[1] -- initialize and load staircase matrix
cpus[2] -- factor the matrix
cpus[3] -- scale and store factor entries
cpus[4] -- store update entries
created -- 98may28, cca
-----------------------------------------------
*/
void
FrontMtx_QR_factorVisit (
FrontMtx *frontmtx,
int J,
InpMtx *mtxA,
IVL *rowsIVL,
int firstnz[],
ChvList *updlist,
ChvManager *chvmanager,
char status[],
int colmap[],
DV *workDV,
double cpus[],
double *pfacops,
int msglvl,
FILE *msgFile
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || mtxA == NULL || rowsIVL == NULL
|| firstnz == NULL || updlist == NULL || chvmanager == NULL
|| status == NULL || colmap == NULL || workDV == NULL
|| cpus == NULL || pfacops == NULL
|| (msglvl > 0 && msgFile == NULL) ) {
fprintf(msgFile, "\n fatal error in FrontMtx_QR_factorVisit(%d)"
"\n bad input\n", J) ;
exit(-1) ;
}
/*
------------------------------------------------------------
check to see if all incoming updates are present in the list
------------------------------------------------------------
*/
if ( ChvList_isCountZero(updlist, J) == 1 ) {
A2 *frontJ ;
Chv *firstchild, *updchv ;
double ops, t1, t2 ;
int K ;
/*
----------------------------------------
everything is ready to factor this front
----------------------------------------
*/
firstchild = ChvList_getList(updlist, J) ;
/*
----------------------------------------
initialize and load the staircase matrix
----------------------------------------
*/
MARKTIME(t1) ;
frontJ = FrontMtx_QR_assembleFront(frontmtx, J, mtxA, rowsIVL,
firstnz, colmap, firstchild,
workDV, msglvl, msgFile) ;
if ( firstchild != NULL ) {
ChvManager_releaseListOfObjects(chvmanager, firstchild) ;
}
MARKTIME(t2) ;
cpus[1] += t2 - t1 ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n after assembling front") ;
A2_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
factor the staircase matrix
---------------------------
*/
MARKTIME(t1) ;
ops = A2_QRreduce(frontJ, workDV, msglvl, msgFile) ;
*pfacops += ops ;
MARKTIME(t2) ;
cpus[2] += t2 - t1 ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n after factoring") ;
A2_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------
scale and store the factor entries
----------------------------------
*/
MARKTIME(t1) ;
FrontMtx_QR_storeFront(frontmtx, J, frontJ, msglvl, msgFile) ;
MARKTIME(t2) ;
cpus[3] += t2 - t1 ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n after storing factor entries") ;
A2_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------
store the update matrix
-----------------------
*/
if ( (K = frontmtx->tree->par[J]) != -1 ) {
MARKTIME(t1) ;
updchv = FrontMtx_QR_storeUpdate(frontmtx, J, frontJ, chvmanager,
msglvl, msgFile) ;
ChvList_addObjectToList(updlist, updchv, K) ;
MARKTIME(t2) ;
cpus[4] += t2 - t1 ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n after storing update entries") ;
A2_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
}
/*
-------------------------
free the staircase matrix
-------------------------
*/
A2_free(frontJ) ;
/*
-------------------------------------
set the status as finished and return
-------------------------------------
*/
status[J] = 'F' ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
purpose -- create and return an A2 object that contains rows
of A and rows from update matrices of the children.
the matrix may not be in staircase form
created -- 98may25, cca
--------------------------------------------------------------
*/
A2 *
FrontMtx_QR_assembleFront (
FrontMtx *frontmtx,
int J,
InpMtx *mtxA,
IVL *rowsIVL,
int firstnz[],
int colmap[],
Chv *firstchild,
DV *workDV,
int msglvl,
FILE *msgFile
) {
A2 *frontJ ;
Chv *chvI ;
double *rowI, *rowJ, *rowentA ;
int ii, irow, irowA, irowI, jcol, jj, jrow, ncolI, ncolJ,
nentA, nrowI, nrowJ, nrowFromA ;
int *colindA, *colindI, *colindJ, *map, *rowids, *rowsFromA ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || mtxA == NULL || rowsIVL == NULL
|| (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr, "\n fatal error in FrontMtx_QR_assembleFront()"
"\n bad input\n") ;
exit(-1) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n inside FrontMtx_QR_assembleFront(%d)", J) ;
fflush(msgFile) ;
}
/*
--------------------------------------------------
set up the map from global to local column indices
--------------------------------------------------
*/
FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
for ( jcol = 0 ; jcol < ncolJ ; jcol++ ) {
colmap[colindJ[jcol]] = jcol ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n front %d's column indices", J) ;
IVfprintf(msgFile, ncolJ, colindJ) ;
fflush(msgFile) ;
}
/*
-------------------------------------------------
compute the size of the front and map the global
indices of the update matrices into local indices
-------------------------------------------------
*/
IVL_listAndSize(rowsIVL, J, &nrowFromA, &rowsFromA) ;
nrowJ = nrowFromA ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %d rows from A", nrowFromA) ;
fflush(msgFile) ;
}
for ( chvI = firstchild ; chvI != NULL ; chvI = chvI->next ) {
nrowJ += chvI->nD ;
Chv_columnIndices(chvI, &ncolI, &colindI) ;
for ( jcol = 0 ; jcol < ncolI ; jcol++ ) {
colindI[jcol] = colmap[colindI[jcol]] ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n %d rows from child %d", chvI->nD, chvI->id) ;
fflush(msgFile) ;
}
}
/*
----------------------------------------------------------
get workspace for the rowids[nrowJ] and map[nrowJ] vectors
----------------------------------------------------------
*/
if ( sizeof(int) == sizeof(double) ) {
DV_setSize(workDV, 2*nrowJ) ;
} else if ( 2*sizeof(int) == sizeof(double) ) {
DV_setSize(workDV, nrowJ) ;
}
rowids = (int *) DV_entries(workDV) ;
map = rowids + nrowJ ;
IVramp(nrowJ, rowids, 0, 1) ;
IVfill(nrowJ, map, -1) ;
/*
-----------------------------------------------------------------
get the map from incoming rows to their place in the front matrix
-----------------------------------------------------------------
*/
for ( irow = jrow = 0 ; irow < nrowFromA ; irow++, jrow++ ) {
irowA = rowsFromA[irow] ;
map[jrow] = colmap[firstnz[irowA]] ;
}
for ( chvI = firstchild ; chvI != NULL ; chvI = chvI->next ) {
nrowI = chvI->nD ;
Chv_columnIndices(chvI, &ncolI, &colindI) ;
for ( irow = 0 ; irow < nrowI ; irow++, jrow++ ) {
map[jrow] = colindI[irow] ;
}
}
IV2qsortUp(nrowJ, map, rowids) ;
for ( irow = 0 ; irow < nrowJ ; irow++ ) {
map[rowids[irow]] = irow ;
}
/*
----------------------------
allocate the A2 front object
----------------------------
*/
frontJ = A2_new() ;
A2_init(frontJ, frontmtx->type, nrowJ, ncolJ, ncolJ, 1, NULL) ;
A2_zero(frontJ) ;
/*
------------------------------------
load the original rows of the matrix
------------------------------------
*/
for ( jrow = 0 ; jrow < nrowFromA ; jrow++ ) {
irowA = rowsFromA[jrow] ;
rowJ = A2_row(frontJ, map[jrow]) ;
if ( A2_IS_REAL(frontJ) ) {
InpMtx_realVector(mtxA, irowA, &nentA, &colindA, &rowentA) ;
} else if ( A2_IS_COMPLEX(frontJ) ) {
InpMtx_complexVector(mtxA, irowA, &nentA, &colindA, &rowentA) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n loading row %d", irowA) ;
fprintf(msgFile, "\n global indices") ;
IVfprintf(msgFile, nentA, colindA) ;
fflush(msgFile) ;
}
if ( A2_IS_REAL(frontJ) ) {
for ( ii = 0 ; ii < nentA ; ii++ ) {
jj = colmap[colindA[ii]] ;
rowJ[jj] = rowentA[ii] ;
}
} else if ( A2_IS_COMPLEX(frontJ) ) {
for ( ii = 0 ; ii < nentA ; ii++ ) {
jj = colmap[colindA[ii]] ;
rowJ[2*jj] = rowentA[2*ii] ;
rowJ[2*jj+1] = rowentA[2*ii+1] ;
}
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n after assembling rows of A") ;
A2_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------
load the updates from the children
----------------------------------
*/
for ( chvI = firstchild ; chvI != NULL ; chvI = chvI->next ) {
nrowI = chvI->nD ;
Chv_columnIndices(chvI, &ncolI, &colindI) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n loading child %d", chvI->id) ;
fprintf(msgFile, "\n child's column indices") ;
IVfprintf(msgFile, ncolI, colindI) ;
Chv_writeForHumanEye(chvI, msgFile) ;
fflush(msgFile) ;
}
rowI = Chv_entries(chvI) ;
for ( irowI = 0 ; irowI < nrowI ; irowI++, jrow++ ) {
rowJ = A2_row(frontJ, map[jrow]) ;
if ( A2_IS_REAL(frontJ) ) {
for ( ii = irowI ; ii < ncolI ; ii++ ) {
jj = colindI[ii] ;
rowJ[jj] = rowI[ii] ;
}
rowI += ncolI - irowI - 1 ;
} else if ( A2_IS_COMPLEX(frontJ) ) {
for ( ii = irowI ; ii < ncolI ; ii++ ) {
jj = colindI[ii] ;
rowJ[2*jj] = rowI[2*ii] ;
rowJ[2*jj+1] = rowI[2*ii+1] ;
}
rowI += 2*(ncolI - irowI - 1) ;
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n after assembling child %d", chvI->id) ;
A2_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
}
return(frontJ) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
store the factor entries of the reduced front matrix
created -- 98may25, cca
----------------------------------------------------
*/
void
FrontMtx_QR_storeFront (
FrontMtx *frontmtx,
int J,
A2 *frontJ,
int msglvl,
FILE *msgFile
) {
A2 tempA2 ;
double fac, ifac, imag, real, rfac ;
double *entDJJ, *entUJJ, *entUJN, *row ;
int inc1, inc2, irow, jcol, ncol, ncolJ, nD, nentD, nentUJJ,
nfront, nrow, nU ;
int *colind, *colindJ, *firstlocs, *sizes ;
SubMtx *mtx ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || frontJ == NULL
|| (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr, "\n fatal error in FrontMtx_QR_storeFront()"
"\n bad input\n") ;
exit(-1) ;
}
nfront = FrontMtx_nfront(frontmtx) ;
FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
nrow = A2_nrow(frontJ) ;
ncol = A2_ncol(frontJ) ;
A2_setDefaultFields(&tempA2) ;
nD = FrontMtx_frontSize(frontmtx, J) ;
nU = ncol - nD ;
/*
--------------------------------------
scale the rows and square the diagonal
--------------------------------------
*/
row = A2_entries(frontJ) ;
if ( A2_IS_REAL(frontJ) ) {
for ( irow = 0 ; irow < nD ; irow++ ) {
if ( row[irow] != 0.0 ) {
fac = 1./row[irow] ;
for ( jcol = irow + 1 ; jcol < ncol ; jcol++ ) {
row[jcol] *= fac ;
}
row[irow] = row[irow] * row[irow] ;
}
row += ncol ;
}
} else if ( A2_IS_COMPLEX(frontJ) ) {
for ( irow = 0 ; irow < nD ; irow++ ) {
real = row[2*irow] ; imag = row[2*irow+1] ;
if ( real != 0.0 || imag != 0.0 ) {
Zrecip(real, imag, &rfac, &ifac) ;
ZVscale(ncol - irow - 1, & row[2*irow+2], rfac, ifac) ;
row[2*irow] = real*real + imag*imag ;
row[2*irow+1] = 0.0 ;
}
row += 2*ncol ;
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n after scaling rows of A") ;
A2_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------
copy the diagonal entries
-------------------------
*/
mtx = FrontMtx_diagMtx(frontmtx, J) ;
SubMtx_diagonalInfo(mtx, &nentD, &entDJJ) ;
A2_subA2(&tempA2, frontJ, 0, nD-1, 0, nD-1) ;
A2_copyEntriesToVector(&tempA2, nentD, entDJJ,
A2_DIAGONAL, A2_BY_ROWS) ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(nD, colind, colindJ) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n diagonal factor matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, J)) != NULL ) {
/*
------------------------
copy the U_{J,J} entries
------------------------
*/
SubMtx_denseSubcolumnsInfo(mtx, &nD, &nentUJJ,
&firstlocs, &sizes, &entUJJ) ;
A2_copyEntriesToVector(&tempA2, nentUJJ, entUJJ,
A2_STRICT_UPPER, A2_BY_COLUMNS) ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(nD, colind, colindJ) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n UJJ factor matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
if ( ncolJ > nD ) {
/*
-----------------------------
copy the U_{J,bnd{J}} entries
-----------------------------
*/
mtx = FrontMtx_upperMtx(frontmtx, J, nfront) ;
SubMtx_denseInfo(mtx, &nD, &nU, &inc1, &inc2, &entUJN) ;
A2_subA2(&tempA2, frontJ, 0, nD-1, nD, ncolJ-1) ;
A2_copyEntriesToVector(&tempA2, nD*nU, entUJN,
A2_ALL_ENTRIES, A2_BY_COLUMNS) ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(nU, colind, colindJ + nD) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n UJN factor matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to create and return a Chv object that
holds the update matrix for front J
created -- 98may25, cca
-------------------------------------------------
*/
Chv *
FrontMtx_QR_storeUpdate (
FrontMtx *frontmtx,
int J,
A2 *frontJ,
ChvManager *chvmanager,
int msglvl,
FILE *msgFile
) {
A2 tempJ ;
Chv *chvJ ;
double *updent ;
int nbytes, ncolJ, ncolupd, nD, nent, nrowJ, nrowupd ;
int *colindJ, *updind ;
/*
-----------------------------------------------
compute the number of rows in the update matrix
-----------------------------------------------
*/
nD = FrontMtx_frontSize(frontmtx, J) ;
FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
nrowJ = A2_nrow(frontJ) ;
nrowupd = ((nrowJ >= ncolJ) ? ncolJ : nrowJ) - nD ;
ncolupd = ncolJ - nD ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n inside FrontMtx_QR_storeUpdate(%d)", J) ;
fprintf(msgFile, "\n nD %d, nrowJ %d, nrowupd %d, ncolupd %d",
nD, nrowJ, nrowupd, ncolupd) ;
fflush(msgFile) ;
}
if ( nrowupd > 0 && ncolupd > 0 ) {
if ( FRONTMTX_IS_REAL(frontmtx) ) {
nbytes = Chv_nbytesNeeded(nrowupd, 0, ncolupd - nrowupd,
SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
nbytes = Chv_nbytesNeeded(nrowupd, 0, ncolupd - nrowupd,
SPOOLES_COMPLEX, SPOOLES_HERMITIAN) ;
}
chvJ = ChvManager_newObjectOfSizeNbytes(chvmanager, nbytes) ;
if ( FRONTMTX_IS_REAL(frontmtx) ) {
Chv_init(chvJ, J, nrowupd, 0, ncolupd - nrowupd,
SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
Chv_init(chvJ, J, nrowupd, 0, ncolupd - nrowupd,
SPOOLES_COMPLEX, SPOOLES_HERMITIAN) ;
}
Chv_columnIndices(chvJ, &ncolupd, &updind) ;
IVcopy(ncolupd, updind, colindJ + nD) ;
nent = Chv_nent(chvJ) ;
updent = Chv_entries(chvJ) ;
A2_setDefaultFields(&tempJ) ;
A2_subA2(&tempJ, frontJ, nD, nrowJ - 1, nD, ncolJ - 1) ;
A2_copyEntriesToVector(&tempJ, nent, updent, A2_UPPER, A2_BY_ROWS) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n update matrix %d", J) ;
Chv_writeForHumanEye(chvJ, msgFile) ;
fflush(msgFile) ;
}
} else {
chvJ = NULL ;
}
return(chvJ) ; }
/*--------------------------------------------------------------------*/
e for the rowids[nrowJ] and map[nrowJ] vectors
----------------------------------------------------------
*/
if ( sizeof(int) == sizeof(double) ) {
DV_setSize(workDV, 2*nrowJ) ;
} else if ( 2*sizeof(int) == sizeof(double) ) {
DV_setSize(workDV, nrowJ) ;
}
rowFrontMtx/src/basics.c 0100644 0002055 0007177 00000013600 06571267172 0016066 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../FrontMtx.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------
simplest constructor
created -- 98may04, cca
-----------------------
*/
FrontMtx *
FrontMtx_new (
void
) {
FrontMtx *frontmtx ;
ALLOCATE(frontmtx, struct _FrontMtx, 1) ;
FrontMtx_setDefaultFields(frontmtx) ;
return(frontmtx) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the default fields
created -- 98may04, cca
-----------------------
*/
void
FrontMtx_setDefaultFields (
FrontMtx *frontmtx
) {
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_setDefaultFields(%p)"
"\n bad input", frontmtx) ;
exit(-1) ;
}
frontmtx->nfront = 0 ;
frontmtx->neqns = 0 ;
frontmtx->type = SPOOLES_REAL ;
frontmtx->symmetryflag = SPOOLES_SYMMETRIC ;
frontmtx->sparsityflag = FRONTMTX_DENSE_FRONTS ;
frontmtx->pivotingflag = SPOOLES_NO_PIVOTING ;
frontmtx->dataMode = FRONTMTX_1D_MODE ;
frontmtx->nentD = 0 ;
frontmtx->nentL = 0 ;
frontmtx->nentU = 0 ;
frontmtx->tree = NULL ;
frontmtx->frontETree = NULL ;
frontmtx->frontsizesIV = NULL ;
frontmtx->symbfacIVL = NULL ;
frontmtx->rowadjIVL = NULL ;
frontmtx->coladjIVL = NULL ;
frontmtx->lowerblockIVL = NULL ;
frontmtx->upperblockIVL = NULL ;
frontmtx->p_mtxDJJ = NULL ;
frontmtx->p_mtxUJJ = NULL ;
frontmtx->p_mtxUJN = NULL ;
frontmtx->p_mtxLJJ = NULL ;
frontmtx->p_mtxLNJ = NULL ;
frontmtx->lowerhash = NULL ;
frontmtx->upperhash = NULL ;
frontmtx->lock = NULL ;
frontmtx->nlocks = 0 ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
clear the data fields, releasing allocated storage
created -- 98may04, cca
--------------------------------------------------
*/
void
FrontMtx_clearData (
FrontMtx *frontmtx
) {
SubMtx *mtx ;
int ii, J, K, nadj, nfront ;
int *adj ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_clearData(%p)"
"\n bad input\n", frontmtx) ;
exit(-1) ;
}
nfront = frontmtx->nfront ;
/*
----------------------
free the owned storage
----------------------
*/
if ( frontmtx->frontsizesIV != NULL ) {
IV_free(frontmtx->frontsizesIV) ;
}
if ( frontmtx->rowadjIVL != NULL ) {
IVL_free(frontmtx->rowadjIVL) ;
}
if ( frontmtx->coladjIVL != NULL ) {
IVL_free(frontmtx->coladjIVL) ;
}
if ( frontmtx->p_mtxDJJ != NULL ) {
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = frontmtx->p_mtxDJJ[J]) != NULL ) {
SubMtx_free(mtx) ;
}
}
FREE(frontmtx->p_mtxDJJ) ;
}
if ( frontmtx->tree != NULL ) {
if ( frontmtx->frontETree == NULL
|| frontmtx->frontETree->tree != frontmtx->tree ) {
Tree_free(frontmtx->tree) ;
}
frontmtx->tree = NULL ;
}
if ( frontmtx->dataMode == FRONTMTX_1D_MODE ) {
if ( frontmtx->p_mtxUJJ != NULL ) {
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = frontmtx->p_mtxUJJ[J]) != NULL ) {
SubMtx_free(mtx) ;
}
}
FREE(frontmtx->p_mtxUJJ) ;
}
if ( frontmtx->p_mtxUJN != NULL ) {
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = frontmtx->p_mtxUJN[J]) != NULL ) {
SubMtx_free(mtx) ;
}
}
FREE(frontmtx->p_mtxUJN) ;
}
if ( frontmtx->p_mtxLJJ != NULL ) {
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = frontmtx->p_mtxLJJ[J]) != NULL ) {
SubMtx_free(mtx) ;
}
}
FREE(frontmtx->p_mtxLJJ) ;
}
if ( frontmtx->p_mtxLNJ != NULL ) {
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtx = frontmtx->p_mtxLNJ[J]) != NULL ) {
SubMtx_free(mtx) ;
}
}
FREE(frontmtx->p_mtxLNJ) ;
}
} else if ( frontmtx->dataMode == FRONTMTX_2D_MODE ) {
for ( J = 0 ; J < nfront ; J++ ) {
FrontMtx_upperAdjFronts(frontmtx, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = adj[ii] ;
if ( (mtx = FrontMtx_upperMtx(frontmtx, J, K)) != NULL ) {
SubMtx_free(mtx) ;
}
}
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
for ( J = 0 ; J < nfront ; J++ ) {
FrontMtx_lowerAdjFronts(frontmtx, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = adj[ii] ;
if ( (mtx = FrontMtx_lowerMtx(frontmtx, K, J)) != NULL ) {
SubMtx_free(mtx) ;
}
}
}
}
if ( frontmtx->lowerblockIVL != NULL ) {
IVL_free(frontmtx->lowerblockIVL) ;
}
if ( frontmtx->upperblockIVL != NULL ) {
IVL_free(frontmtx->upperblockIVL) ;
}
if ( frontmtx->lowerhash != NULL ) {
I2Ohash_free(frontmtx->lowerhash) ;
}
if ( frontmtx->upperhash != NULL ) {
I2Ohash_free(frontmtx->upperhash) ;
}
}
if ( frontmtx->lock != NULL ) {
/*
-------------------------
destroy and free the lock
-------------------------
*/
Lock_free(frontmtx->lock) ;
}
/*
----------------------
set the default fields
----------------------
*/
FrontMtx_setDefaultFields(frontmtx) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
destructor, free's the object and its data
created -- 98may04, cca
------------------------------------------
*/
void
FrontMtx_free (
FrontMtx *frontmtx
) {
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_free(%p)"
"\n bad input\n", frontmtx) ;
exit(-1) ;
}
FrontMtx_clearData(frontmtx) ;
FREE(frontmtx) ;
return ; }
/*--------------------------------------------------------------------*/
FrontMtx/src/factor.c 0100644 0002055 0007177 00000020300 06650217232 0016061 0 ustar 00cleve compmath 0000040 0000006 /* factor.c */
#include "../FrontMtx.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
compute an (U^T + I)D(I + U) or (L + I)D(I + L) factorization of A.
this is a wrapper method around FrontMtx_factorPencil().
input --
frontmtx -- pointer to the FrontMtx object that will hold
the factorization
pencil -- pointer to the Pencil object that holds A + sigma*B
tau -- upper bound on entries in L and U,
used only when pivoting enabled
droptol -- lower bound on entries in L and U,
used only when sparsity enabled
perror -- error flag, on return
*perror >= 0 --> factorization failed at front *perror
*perror < 0 --> factorization succeeded
cpus[] -- timing array
cpus[0] -- initialize fronts
cpus[1] -- load original entries
cpus[2] -- get updates from descendents
cpus[3] -- assembled postponed data
cpus[4] -- factor the front
cpus[5] -- extract postponed data
cpus[6] -- store factor entries
cpus[7] -- miscellaneous time
cpus[8] -- total time
stats[] -- statistics array
stats[0] -- # of pivots
stats[1] -- # of pivot tests
stats[2] -- # of delayed rows and columns
stats[3] -- # of entries in D
stats[4] -- # of entries in L
stats[5] -- # of entries in U
msglvl -- message level
msgFile -- message file
created -- 98mar27, cca
modified -- 98mar27, cca
perror added to argument list
-------------------------------------------------------------------
*/
Chv *
FrontMtx_factorInpMtx (
FrontMtx *frontmtx,
InpMtx *inpmtx,
double tau,
double droptol,
ChvManager *chvmanager,
int *perror,
double cpus[],
int stats[],
int msglvl,
FILE *msgFile
) {
double zero[2] = {0.0, 0.0} ;
Chv *rootchv ;
Pencil pencil ;
Pencil_setDefaultFields(&pencil) ;
Pencil_init(&pencil, frontmtx->type, frontmtx->symmetryflag,
inpmtx, zero, NULL) ;
rootchv = FrontMtx_factorPencil(frontmtx, &pencil, tau, droptol,
chvmanager, perror, cpus, stats, msglvl, msgFile) ;
return(rootchv) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
compute an (U^T + I)D(I + U) or (L + I)D(I + L)
factorization of A + sigma*B.
input --
frontmtx -- pointer to the FrontMtx object that will hold
the factorization
pencil -- pointer to the Pencil object that holds A + sigma*B
tau -- upper bound on entries in L and U,
used only when pivoting enabled
droptol -- lower bound on entries in L and U,
used only when sparsity enabled
perror -- error flag, on return
*perror >= 0 --> factorization failed at front *perror
*perror < 0 --> factorization succeeded
cpus[] -- timing array
cpus[0] -- initialize fronts
cpus[1] -- load original entries
cpus[2] -- get updates from descendents
cpus[3] -- assembled postponed data
cpus[4] -- factor the front
cpus[5] -- extract postponed data
cpus[6] -- store factor entries
cpus[7] -- miscellaneous time
cpus[8] -- total time
stats[] -- statistics array
stats[0] -- # of pivots
stats[1] -- # of pivot tests
stats[2] -- # of delayed rows and columns
stats[3] -- # of entries in D
stats[4] -- # of entries in L
stats[5] -- # of entries in U
msglvl -- message level
msgFile -- message file
created -- 98mar27, cca
modified -- 98mar27, cca
perror added to argument list
-------------------------------------------------------------------
*/
Chv *
FrontMtx_factorPencil (
FrontMtx *frontmtx,
Pencil *pencil,
double tau,
double droptol,
ChvManager *chvmanager,
int *perror,
double cpus[],
int stats[],
int msglvl,
FILE *msgFile
) {
char *status ;
ChvList *postList ;
Chv *rootchv ;
Chv **fronts ;
double t0, t3 ;
DV tmpDV ;
ETree *frontETree ;
int J, K, ndelayed, nfront, npivots, ntests ;
int *par ;
IP **heads ;
IV pivotsizesIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
MARKTIME(t0) ;
if ( frontmtx == NULL || pencil == NULL || cpus == NULL || stats == NULL
|| (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr, "\n fatal error in FrontMtx_factorPencil()"
"\n frontmtx = %p, pencil = %p"
"\n tau = %e, droptol = %e, cpus = %p"
"\n msglvl = %d, msgFile = %p"
"\n bad input\n",
frontmtx, pencil, tau, droptol, cpus, msglvl, msgFile) ;
exit(-1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n INSIDE FrontMtx_factorPencil()") ;
fflush(msgFile) ;
}
/*
-------------------------------
extract pointers and dimensions
-------------------------------
*/
frontETree = frontmtx->frontETree ;
nfront = ETree_nfront(frontETree) ;
tree = ETree_tree(frontETree) ;
par = ETree_par(frontETree) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n got pointers and dimensions") ;
fflush(msgFile) ;
}
/*
---------------------------------------
allocate and initialize working storage
---------------------------------------
*/
heads = FrontMtx_factorSetup(frontmtx, NULL, 0, msglvl, msgFile) ;
status = CVinit(nfront, 'W') ;
ALLOCATE(fronts, Chv *, nfront) ;
for ( J = 0 ; J < nfront ; J++ ) {
fronts[J] = NULL ;
}
DV_setDefaultFields(&tmpDV) ;
IV_setDefaultFields(&pivotsizesIV) ;
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
postList = ChvList_new() ;
ChvList_init(postList, nfront+1, NULL, 0, NULL) ;
} else {
postList = NULL ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n allocated working storage") ;
fflush(msgFile) ;
}
/*
--------------------------------------------
loop over the tree in a post-order traversal
--------------------------------------------
*/
*perror = -1 ;
npivots = ndelayed = ntests = 0 ;
rootchv = NULL ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
K = par[J] ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n ##### working on front %d, parent %d",
J, K) ;
fflush(msgFile) ;
}
FrontMtx_factorVisit(frontmtx, pencil, J, 0, NULL, fronts, 0,
tau, droptol, status, heads, &pivotsizesIV,
&tmpDV, par, NULL, postList,
chvmanager, stats, cpus, msglvl, msgFile) ;
if ( status[J] == 'E' ) {
/*
-------------------------------
error found, unable to continue
-------------------------------
*/
*perror = J ;
break ;
} else if ( status[J] != 'F' ) {
fprintf(stderr, "\n fatal error, return %c from front %d",
status[J], J) ;
exit(-1) ;
}
}
/*
---------------------------------
get a pointer to the root chevron
---------------------------------
*/
if ( postList == NULL ) {
rootchv = NULL ;
} else {
rootchv = ChvList_getList(postList, nfront) ;
}
/*
------------------
set the statistics
------------------
*/
stats[3] = frontmtx->nentD ;
stats[4] = frontmtx->nentL ;
stats[5] = frontmtx->nentU ;
/*
------------------------
free the working storage
------------------------
*/
IP_free(heads[nfront+1]) ;
FREE(heads) ;
DV_clearData(&tmpDV) ;
IV_clearData(&pivotsizesIV) ;
CVfree(status) ;
FREE(fronts) ;
if ( postList != NULL ) {
ChvList_free(postList) ;
}
/*
--------------------------------
set final and miscellaneous time
--------------------------------
*/
MARKTIME(t3) ;
cpus[8] = t3 - t0 ;
cpus[7] = cpus[8] - cpus[0] - cpus[1] - cpus[2]
- cpus[3] - cpus[4] - cpus[5] - cpus[6] ;
return(rootchv) ; }
/*--------------------------------------------------------------------*/
FrontMtx/src/factorUtil.c 0100644 0002055 0007177 00000105340 06576274510 0016740 0 ustar 00cleve compmath 0000040 0000006 /* factorUtil.c */
#include "../FrontMtx.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------
purpose -- initialize a front
created -- 98may04, cca
-----------------------------
*/
void
FrontMtx_initializeFront (
FrontMtx *frontmtx,
Chv *frontJ,
int J
) {
int ncolJ, nD, nrowJ ;
int *colindJ, *ivec ;
/*
-----------------------------------
get the number of internal vertices
-----------------------------------
*/
nD = ETree_frontSize(frontmtx->frontETree, J) ;
/*
--------------------------------------
get the internal and boundary vertices
--------------------------------------
*/
IVL_listAndSize(frontmtx->symbfacIVL, J, &ncolJ, &colindJ) ;
#if MYDEBUG > 0
fprintf(stdout, "\n front %d, column indices", J) ;
IVfprintf(stdout, ncolJ, colindJ) ;
fflush(stdout) ;
#endif
/*
------------------------------------------------------
initialize the front's dimensions, indices and entries
------------------------------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n front %d, nD %d, nU %d", J, nD, ncolJ - nD) ;
fflush(stdout) ;
#endif
Chv_init(frontJ, J, nD, ncolJ - nD, ncolJ - nD,
frontmtx->type, frontmtx->symmetryflag) ;
/*
-----------------------
fill the column indices
-----------------------
*/
Chv_columnIndices(frontJ, &ncolJ, &ivec) ;
IVcopy(ncolJ, ivec, colindJ) ;
#if MYDEBUG > 0
fprintf(stdout, "\n front %d, colind = %p", J, ivec) ;
IVfprintf(stdout, ncolJ, ivec) ;
fflush(stdout) ;
#endif
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
--------------------
fill the row indices
--------------------
*/
Chv_rowIndices(frontJ, &nrowJ, &ivec) ;
IVcopy(nrowJ, ivec, colindJ) ;
}
/*
------------------------
zero the front's entries
------------------------
*/
Chv_zero(frontJ) ;
#if MYDEBUG > 0
fprintf(stdout, "\n leaving Front_initializeFront()") ;
Chv_writeForHumanEye(frontJ, stdout) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
----------------
static functions
----------------
*/
static void assembleAggregates ( Chv *frontJ, ChvList *aggList,
ChvManager *chvmanager, double cpus[], int msglvl, FILE *msgFile ) ;
static char assemblePostponedData ( FrontMtx *frontmtx, Chv *frontJ,
int *pndelay, Chv *fronts[], ChvList *postList,
ChvManager *chvmanager, double cpus[], int msglvl, FILE *msgFile ) ;
static int factorFront ( FrontMtx *frontmtx, Chv *frontJ,
int ndelay, double tau, IV *pivotsizesIV, DV *workDV, int stats[],
double cpus[], int msglvl, FILE *msgFile ) ;
static void storeEntries ( FrontMtx *frontmtx, Chv *frontJ, int nelim,
double droptol, IV *pivotsizesIV, ChvList *postList,
ChvManager *chvmanager, int parent[], int stats[], double cpus[],
int msglvl, FILE *msgFile ) ;
/*
------------------------------------------------------------------
purpose -- to visit a front during a factorization.
note: this method is called by the serial,
multithreaded and MPI factorization codes.
frontmtx -- front matrix object
pencil -- matrix pencil for A + sigma*B
J -- id of front we are working on
myid -- id of thread or process
owners[] -- map from fronts to owning threads,
in a serial environment, owners = NULL
fronts[] -- vector of pointers to fronts
lookahead -- parameter controls the partial upward visiting
of ancestors before returning
tau -- used when pivoting enabled,
|L_{j,i}| and |U_{i,j}| <= tau
droptol -- used for an approximate factorization
stored |L_{j,i}| and |U_{i,j}| > droptol
status[] -- status vector for the fronts,
'W' -- needs to be woke up
'A' -- active front
'F' -- front is finished
heads[] -- vector of pointers to IP objects that store the
front-to-front update lists
pivotsizesIV -- IV object used during the factorization of a front
when pivoting is enabled
workDV -- DV object used for working storage
parent -- front parent vector
aggList -- list object used in parallel environment, used
to store aggregate fronts
postList -- list object used in pivoting and/or parallel
environments, used to stored delayed data and/or
to synchronize the factorization
chvmanager -- used to manage working storage for Chv objects
stats[] -- statistics vector
cpus[] -- vector to hold breakdown of cpu times
msglvl -- message level
msgFil -- message file
created -- 98may04, cca
------------------------------------------------------------------
*/
char
FrontMtx_factorVisit (
FrontMtx *frontmtx,
Pencil *pencil,
int J,
int myid,
int owners[],
Chv *fronts[],
int lookahead,
double tau,
double droptol,
char status[],
IP *heads[],
IV *pivotsizesIV,
DV *workDV,
int parent[],
ChvList *aggList,
ChvList *postList,
ChvManager *chvmanager,
int stats[],
double cpus[],
int msglvl,
FILE *msgFile
) {
/*
---------------
local variables
---------------
*/
char allAggregatesHere, allPostponedAssmb, allUpdatesDone ;
Chv *frontJ ;
double t1, t2 ;
int K, ndelay, nelim ;
if ( status[J] == 'F' ) {
return('F') ;
}
allUpdatesDone = 'N' ;
allAggregatesHere = 'N' ;
allPostponedAssmb = 'N' ;
frontJ = NULL ;
if ( heads[J] != NULL ) {
/*
--------------------------------
internal updates to be performed
--------------------------------
*/
if ( (frontJ = fronts[J]) == NULL ) {
/*
--------------------
initialize the front
--------------------
*/
fronts[J] = FrontMtx_setupFront(frontmtx, pencil, J, myid,
owners, chvmanager, cpus, msglvl, msgFile) ;
frontJ = fronts[J] ;
status[J] = 'A' ;
}
/*
---------------------------------
compute updates from owned fronts
---------------------------------
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n performing updates") ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
FrontMtx_update(frontmtx, frontJ, heads,
status, workDV, msglvl, msgFile) ;
MARKTIME(t2) ;
cpus[2] += t2 - t1 ;
}
if ( heads[J] == NULL ) {
allUpdatesDone = 'Y' ;
}
if ( owners == NULL || owners[J] == myid ) {
/*
--------------
front is owned
--------------
*/
if ( (frontJ = fronts[J]) == NULL ) {
/*
--------------------
initialize the front
--------------------
*/
fronts[J] = FrontMtx_setupFront(frontmtx, pencil, J, myid,
owners, chvmanager, cpus, msglvl, msgFile) ;
frontJ = fronts[J] ;
status[J] = 'A' ;
}
if ( aggList != NULL ) {
/*
------------------------------------------
we are operating in a parallel environment
------------------------------------------
*/
if ( ChvList_isListNonempty(aggList, J) == 1 ) {
/*
-------------------------------------------------
assemble any aggregate updates from other threads
-------------------------------------------------
*/
assembleAggregates(frontJ, aggList, chvmanager,
cpus, msglvl, msgFile) ;
}
if ( ChvList_isCountZero(aggList, J) == 1 ) {
/*
-------------------------------------------------------
all aggregates are assembled or in the list to assemble
-------------------------------------------------------
*/
if ( ChvList_isListNonempty(aggList, J) == 1 ) {
/*
-------------------------------------------------
assemble any aggregate updates from other threads
-------------------------------------------------
*/
assembleAggregates(frontJ, aggList, chvmanager,
cpus, msglvl, msgFile) ;
}
allAggregatesHere = 'Y' ;
}
} else {
allAggregatesHere = 'Y' ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n allUpdatesDone %c, allAggregatesHere %c",
allUpdatesDone, allAggregatesHere) ;
fflush(msgFile) ;
}
if ( allUpdatesDone == 'Y' && allAggregatesHere == 'Y' ) {
/*
-------------------------------------
all internal updates and all external
aggregates have been incorporated
-------------------------------------
*/
if ( postList != NULL ) {
/*
---------------------------------------------
front is ready to assemble any postponed data
---------------------------------------------
*/
allPostponedAssmb = assemblePostponedData(frontmtx, frontJ,
&ndelay, fronts, postList,
chvmanager, cpus, msglvl, msgFile) ;
frontJ = fronts[J] ;
} else {
allPostponedAssmb = 'Y' ;
ndelay = 0 ;
}
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n\n allPostponedAssmb %c", allPostponedAssmb) ;
fflush(msgFile) ;
}
if ( allPostponedAssmb == 'Y' ) {
/*
-----------------------------
front is ready to be factored
-----------------------------
*/
nelim = factorFront(frontmtx, frontJ, ndelay, tau,
pivotsizesIV, workDV, stats,
cpus, msglvl, msgFile) ;
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n\n J = %d, nelim = %d", frontJ->id, nelim) ;
fflush(msgFile) ;
}
if ( (! FRONTMTX_IS_PIVOTING(frontmtx)) && nelim < frontJ->nD){
/*
------------------------------------------------
a singular front matrix has been found.
release the front and set the status to error
------------------------------------------------
*/
ChvManager_releaseObject(chvmanager, frontJ) ;
fronts[J] = NULL ;
status[J] = 'E' ;
} else {
/*
-------------------------------------------
store any factor entries and postponed data
-------------------------------------------
*/
storeEntries(frontmtx, frontJ, nelim, droptol, pivotsizesIV,
postList, chvmanager, parent, stats,
cpus, msglvl, msgFile) ;
/*
------------------------------------------------
release the front and set the status to finished
------------------------------------------------
*/
ChvManager_releaseObject(chvmanager, frontJ) ;
fronts[J] = NULL ;
status[J] = 'F' ;
}
}
}
} else if ( allUpdatesDone == 'Y' ) {
if ( frontJ != NULL ) {
/*
--------------------------------------------------------
front is not owned and all internal updates are complete
put aggregate update front on the aggregate list
--------------------------------------------------------
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n done with unowned front %3d", J) ;
fflush(msgFile) ;
}
if ( msglvl > 3 ) {
Chv_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
ChvList_addObjectToList(aggList, frontJ, J) ;
MARKTIME(t2) ;
#if MYDEBUG > 0
fprintf(stdout, "\n thread %2d, done with unowned front %3d",
myid, J) ;
fflush(stdout) ;
#endif
cpus[7] += t2 - t1 ;
}
status[J] = 'F' ;
}
if ( --lookahead >= 0 && (K = parent[J]) != -1 ) {
/*
-----------------------------
visit parent before returning
-----------------------------
*/
FrontMtx_factorVisit(frontmtx, pencil, J, myid, owners, fronts,
lookahead, tau, droptol, status, heads, pivotsizesIV,
workDV, parent, aggList, postList, chvmanager,
stats, cpus, msglvl, msgFile) ;
}
return(status[J]) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
purpose -- set up the front's data structure
created -- 98mar27, cca
--------------------------------------------
*/
Chv *
FrontMtx_setupFront (
FrontMtx *frontmtx,
Pencil *pencil,
int J,
int myid,
int owners[],
ChvManager *chvmanager,
double cpus[],
int msglvl,
FILE *msgFile
) {
Chv *frontJ ;
double t1, t2 ;
int nbytes, nD, nL, nU ;
if ( msglvl > 4 ) {
fprintf(msgFile,
"\n\n inside FrontMtx_setupFront()"
"\n frontmtx %p, pencil %p, J %d, myid %d"
"\n owners %p, chvmanager %p, cpus %p"
"\n msglvl %d, msgFile %p",
frontmtx, pencil, J, myid, owners, chvmanager,
cpus, msglvl, msgFile) ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
FrontMtx_initialFrontDimensions(frontmtx, J,
&nD, &nL, &nU, &nbytes) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n nD %d, nL %d, nU %d, nbytes %d",
nD, nL, nU, nbytes) ;
fflush(msgFile) ;
}
frontJ = ChvManager_newObjectOfSizeNbytes(chvmanager, nbytes) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n frontJ = %p", frontJ) ;
fflush(msgFile) ;
}
Chv_init(frontJ, J, nD, nL, nU, frontmtx->type, frontmtx->symmetryflag);
FrontMtx_initializeFront(frontmtx, frontJ, J) ;
MARKTIME(t2) ;
cpus[0] += t2 - t1 ;
if ( pencil != NULL && (owners == NULL || owners[J] == myid) ) {
/*
-------------------------------------------------
thread owns this front, load the original entries
-------------------------------------------------
*/
MARKTIME(t1) ;
FrontMtx_loadEntries(frontJ, pencil, msglvl, msgFile) ;
MARKTIME(t2) ;
cpus[1] += t2 - t1 ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n original entries loaded") ;
fflush(msgFile) ;
}
/*
if ( FRONTMTX_IS_HERMITIAN(frontmtx) && J == frontmtx->nfront - 1 ) {
fprintf(msgFile, "\n last front after entries loaded") ;
Chv_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
*/
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n front initialized") ;
fflush(msgFile) ;
}
if ( msglvl > 3 ) {
Chv_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
return(frontJ) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
purpose -- assemble any aggregate updates from other threads
------------------------------------------------------------
*/
static void
assembleAggregates (
Chv *frontJ,
ChvList *aggList,
ChvManager *chvmanager,
double cpus[],
int msglvl,
FILE *msgFile
) {
Chv *chv, *headchv ;
double t1, t2 ;
MARKTIME(t1) ;
headchv = ChvList_getList(aggList, frontJ->id) ;
for ( chv = headchv ; chv != NULL ; chv = chv->next ) {
Chv_assembleChv(frontJ, chv) ;
}
MARKTIME(t2) ;
cpus[8] += t2 - t1 ;
ChvManager_releaseListOfObjects(chvmanager, headchv) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n after assembly") ;
Chv_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
purpose -- assemble any postponed data
created -- 98mar27, cca
--------------------------------------
*/
static char
assemblePostponedData (
FrontMtx *frontmtx,
Chv *frontJ,
int *pndelay,
Chv *fronts[],
ChvList *postList,
ChvManager *chvmanager,
double cpus[],
int msglvl,
FILE *msgFile
) {
char rc ;
double t1, t2 ;
int J ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n\n frontmtx %p, frontJ %p, pndelay %p"
"\n fronts %p, postList %p, chvmanager %p, cpus %p",
frontmtx, frontJ, pndelay,
fronts, postList, chvmanager, cpus) ;
fflush(msgFile) ;
}
J = frontJ->id ;
if ( msglvl > 1 ) {
if ( ChvList_isCountZero(postList, J) == 1) {
fprintf(msgFile, "\n all postponed data is here") ;
fflush(msgFile) ;
} else {
fprintf(msgFile, "\n still waiting on postponed data") ;
fflush(msgFile) ;
}
}
if ( ChvList_isCountZero(postList, J) == 1 ) {
if ( msglvl > 1 ) {
fprintf(msgFile, "\n assembling postponed data") ;
fflush(msgFile) ;
}
/*
---------------------------
assemble any postponed data
---------------------------
*/
MARKTIME(t1) ;
fronts[J] = FrontMtx_assemblePostponedData(frontmtx, frontJ,
postList, chvmanager, pndelay) ;
if ( frontJ != fronts[J] ) {
if ( msglvl > 1 ) {
fprintf(msgFile, "\n releasing old front") ;
fflush(msgFile) ;
}
ChvManager_releaseObject(chvmanager, frontJ) ;
}
MARKTIME(t2) ;
cpus[3] += t2 - t1 ;
rc = 'Y' ;
} else {
rc = 'N' ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------
purpose -- factor the front
created -- 98mar27, cca
---------------------------
*/
static int
factorFront (
FrontMtx *frontmtx,
Chv *frontJ,
int ndelay,
double tau,
IV *pivotsizesIV,
DV *workDV,
int stats[],
double cpus[],
int msglvl,
FILE *msgFile
) {
double t1, t2 ;
int nelim, npost ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n frontJ = %p, ndelay = %d",
frontJ, ndelay) ;
fprintf(msgFile, "\n tau = %12.4e", tau) ;
fprintf(msgFile, "\n stats %p, cpus %p", stats, cpus) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
Chv_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
nelim = Chv_factorWithPivoting(frontJ, ndelay,
frontmtx->pivotingflag, pivotsizesIV,
workDV, tau, &stats[1]) ;
} else {
nelim = Chv_factorWithNoPivoting(frontJ, frontmtx->patchinfo) ;
}
npost = frontJ->nD - nelim ;
stats[2] += npost ;
if ( !(FRONTMTX_IS_PIVOTING(frontmtx))
|| FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
stats[0] += nelim ;
} else {
stats[0] += IV_size(pivotsizesIV) ;
}
MARKTIME(t2) ;
cpus[4] += t2 - t1 ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n front %d, nelim = %d, npost = %d",
frontJ->id, nelim, npost) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
Chv_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
return(nelim) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
purpose -- store the factor entries in the front matrix object,
and extract any postponed data and put it in the
list object
created -- 98mar27, cca
---------------------------------------------------------------
*/
static void
storeEntries (
FrontMtx *frontmtx,
Chv *frontJ,
int nelim,
double droptol,
IV *pivotsizesIV,
ChvList *postList,
ChvManager *chvmanager,
int parent[],
int stats[],
double cpus[],
int msglvl,
FILE *msgFile
) {
double t1, t2 ;
int npost ;
npost = frontJ->nD - nelim ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n storing factor data, nelim = %d", nelim) ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
frontJ->nD -= npost ;
frontJ->nL += npost ;
frontJ->nU += npost ;
FrontMtx_storeFront(frontmtx, frontJ, pivotsizesIV, droptol,
msglvl, msgFile) ;
frontJ->nD += npost ;
frontJ->nL -= npost ;
frontJ->nU -= npost ;
MARKTIME(t2) ;
cpus[6] += t2 - t1 ;
if ( postList != NULL ) {
Chv *postponedchv ;
if ( npost > 0 ) {
/*
---------------------------------
there is postponed data,
extract and put on postponed list
---------------------------------
*/
postponedchv = frontJ ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n postponed data for front %d",
frontJ->id) ;
Chv_writeForHumanEye(postponedchv, msgFile) ;
fflush(msgFile) ;
}
} else {
postponedchv = NULL ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n storing postponed data %p", postponedchv);
fflush(msgFile) ;
}
MARKTIME(t1) ;
FrontMtx_storePostponedData(frontmtx, postponedchv, npost,
parent[frontJ->id], postList, chvmanager) ;
MARKTIME(t2) ;
cpus[5] += t2 - t1 ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
purpose -- to set up the link data structures
for a parallel factorization for process myid
return value -- pointer to IP *heads[nfront+2], which contains
the beginning of a list of IP objects that store the remaining
updates to the fronts.
note, heads[nfront] is the first IP object in the free list.
heads[nfront+1] is the base address of the allocated IP objects.
created -- 98mar07, cca
--------------------------------------------------------------------
*/
IP **
FrontMtx_factorSetup (
FrontMtx *frontmtx,
IV *frontOwnersIV,
int myid,
int msglvl,
FILE *msgFile
) {
int count, ii, J, K, nadj, nfront ;
int *adj, *mark, *owners, *vtxToFront ;
IP *ip ;
IP **heads ;
IVL *symbfacIVL ;
/*
---------------------------------------------------
count the number of updates this front will perform
---------------------------------------------------
*/
nfront = FrontMtx_nfront(frontmtx) ;
if ( frontOwnersIV != NULL ) {
owners = IV_entries(frontOwnersIV) ;
} else {
owners = NULL ;
}
symbfacIVL = frontmtx->symbfacIVL ;
vtxToFront = ETree_vtxToFront(frontmtx->frontETree) ;
mark = IVinit(nfront, -1) ;
for ( J = count = 0 ; J < nfront ; J++ ) {
if ( owners == NULL || owners[J] == myid ) {
IVL_listAndSize(symbfacIVL, J, &nadj, &adj) ;
mark[J] = J ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = vtxToFront[adj[ii]] ;
if ( mark[K] != J ) {
mark[K] = J ;
count++ ;
}
}
}
}
/*
--------------------------------------------------
set up the update head/links for the factorization
--------------------------------------------------
*/
ALLOCATE(heads, struct _IP *, nfront + 2) ;
for ( J = 0 ; J <= nfront + 1 ; J++ ) {
heads[J] = NULL ;
}
heads[nfront] = heads[nfront+1] = IP_init(count, 1) ;
IVfill(nfront, mark, -1) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( owners == NULL || owners[J] == myid ) {
IVL_listAndSize(symbfacIVL, J, &nadj, &adj) ;
mark[J] = J ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = vtxToFront[adj[ii]] ;
if ( mark[K] != J ) {
mark[K] = J ;
ip = heads[nfront] ; heads[nfront] = ip->next ;
ip->val = J ; ip->next = heads[K] ; heads[K] = ip ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n linking L(%d,%d) to L(%d,%d)",
K, J, K, (ip->next == NULL) ? -1 : ip->next->val) ;
fflush(msgFile) ;
}
}
}
}
}
IVfree(mark) ;
return(heads) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
create and return the nactiveChild vector.
nactiveChild[J] contains the number of children
of J that belong to an active path
created -- 97jul03, cca
-----------------------------------------------
*/
int *
FrontMtx_nactiveChild (
FrontMtx *frontmtx,
char *status,
int myid
) {
int J, K, nfront ;
int *nactiveChild, *par ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || status == NULL || myid < 0 ) {
fprintf(stderr, "\n fatal error in FrontMtx_nativeChild(%p,%p,%d)"
"\n bad input\n", frontmtx, status, myid) ;
exit(-1) ;
}
nfront = frontmtx->nfront ;
par = ETree_par(frontmtx->frontETree) ;
/*
---------------------------------------
create and fill the nactiveChild vector
---------------------------------------
*/
nactiveChild = IVinit(nfront, 0) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( status[J] == 'W' && (K = par[J]) != -1 ) {
nactiveChild[K]++ ;
}
}
return(nactiveChild) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
create, initialize and return a Ideq object
that will be used for a parallel factorization,
forward solve, or backward solve.
the status[] vector will be set as follows:
status[J] = activeflag if J is on an active path
status[J] = inactiveflag if J is not on an active path
created -- 98mar27, cca
---------------------------------------------------------
*/
Ideq *
FrontMtx_setUpDequeue (
FrontMtx *frontmtx,
int owners[],
int myid,
char status[],
IP *heads[],
char activeFlag,
char inactiveFlag,
int msglvl,
FILE *msgFile
) {
Ideq *dequeue ;
int J, K, nfront, npath ;
int *par ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || owners == NULL
|| status == NULL || myid < 0 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_setUpDequeue()"
"\n frontmtx %p, owners %p, myid %d, status %p"
"\n heads %p, activeFlag %c, inactiveFlag %c"
"\n bad input\n",
frontmtx, owners, myid, status, heads,
activeFlag, inactiveFlag) ;
exit(-1) ;
}
nfront = frontmtx->nfront ;
tree = frontmtx->tree ;
par = tree->par ;
/*
------------------------------------
count the number of active paths in
the tree and set the status[] vector
------------------------------------
*/
CVfill(nfront, status, inactiveFlag) ;
for ( J = npath = 0 ; J < nfront ; J++ ) {
if ( status[J] == inactiveFlag ) {
if ( owners[J] == myid || (heads != NULL && heads[J] != NULL) ) {
npath++ ;
for ( K = J ;
K != -1 && status[K] != activeFlag ;
K = par[K] ) {
status[K] = activeFlag ;
}
}
}
}
dequeue = Ideq_new() ;
Ideq_resize(dequeue, npath) ;
return(dequeue) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------------
purpose -- load the dequeue with the leaves of the active subtree
used for a factorization and forward solve
created -- 98mar27, cca
-----------------------------------------------------------------
*/
void
FrontMtx_loadActiveLeaves (
FrontMtx *frontmtx,
char status[],
char activeFlag,
Ideq *dequeue
) {
int I, J, nactivechild, nfront ;
int *fch, *sib ;
nfront = frontmtx->nfront ;
fch = frontmtx->tree->fch ;
sib = frontmtx->tree->sib ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( status[J] == activeFlag ) {
if ( fch[J] == -1 ) {
Ideq_insertAtTail(dequeue, J) ;
} else {
nactivechild = 0 ;
for ( I = fch[J] ; I != -1 ; I = sib[I] ) {
if ( status[I] == activeFlag ) {
nactivechild++ ;
break ;
}
}
if ( nactivechild == 0 ) {
Ideq_insertAtTail(dequeue, J) ;
}
}
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
create, initialize and return a ChvList object
to deal with postponed chevrons
created -- 97jul03, cca
-----------------------------------------------
*/
ChvList *
FrontMtx_postList (
FrontMtx *frontmtx,
IV *frontOwnersIV,
int lockflag
) {
char *flags ;
ChvList *postList ;
int count, I, J, jthread, nchild, nfront, nthread ;
int *counts, *fch, *frontOwners, *mark, *sib ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || frontOwnersIV == NULL
|| lockflag < 0 || lockflag > 2 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_postList(%p,%p,%d)"
"\n bad input\n", frontmtx, frontOwnersIV, lockflag) ;
exit(-1) ;
}
fch = ETree_fch(frontmtx->frontETree) ;
sib = ETree_sib(frontmtx->frontETree) ;
IV_sizeAndEntries(frontOwnersIV, &nfront, &frontOwners) ;
counts = IVinit(nfront+1, 0) ;
if ( lockflag > 0 ) {
flags = CVinit(nfront+1, 'N') ;
} else {
flags = NULL ;
}
nthread = 1 + IV_max(frontOwnersIV) ;
mark = IVinit(nthread, -1) ;
/*
--------------------
loop over the fronts
--------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
count = nchild = 0 ;
for ( I = fch[J] ; I != -1 ; I = sib[I] ) {
nchild++ ;
jthread = frontOwners[I] ;
if ( mark[jthread] != J ) {
mark[jthread] = J ;
count++ ;
}
}
counts[J] = nchild ;
if ( flags != NULL ) {
if ( count > 1 ) {
flags[J] = 'Y' ;
} else {
flags[J] = 'N' ;
}
}
}
count = nchild = 0 ;
for ( J = ETree_root(frontmtx->frontETree) ; J != -1 ; J = sib[J] ) {
nchild++ ;
jthread = frontOwners[J] ;
if ( mark[jthread] != J ) {
mark[jthread] = J ;
count++ ;
}
}
counts[nfront] = nchild ;
if ( flags != NULL ) {
if ( count > 1 ) {
flags[nfront] = 'Y' ;
} else {
flags[nfront] = 'N' ;
}
}
/*
-----------------------------------------
create and initialize the ChvList object
-----------------------------------------
*/
postList = ChvList_new() ;
ChvList_init(postList, nfront+1, counts, lockflag, flags) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(mark) ;
IVfree(counts) ;
if ( flags != NULL ) {
CVfree(flags) ;
}
return(postList) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
create, initialize and return a ChvList object
to deal with aggregate chevrons
created -- 97jul03, cca
-----------------------------------------------
*/
ChvList *
FrontMtx_aggregateList (
FrontMtx *frontmtx,
IV *frontOwnersIV,
int lockflag
) {
char *flags ;
ChvList *aggList ;
int count, ii, I, J, jthread, K, myid, nfront, nthread, size ;
int *counts, *frontOwners, *head, *indices, *link,
*mark, *offsets, *vtxToFront ;
IVL *symbfacIVL ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || frontOwnersIV == NULL
|| lockflag < 0 || lockflag > 2 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_aggregateList(%p,%p,%d)"
"\n bad input\n", frontmtx, frontOwnersIV, lockflag) ;
exit(-1) ;
}
symbfacIVL = frontmtx->symbfacIVL ;
vtxToFront = ETree_vtxToFront(frontmtx->frontETree) ;
IV_sizeAndEntries(frontOwnersIV, &nfront, &frontOwners) ;
nthread = 1 + IV_max(frontOwnersIV) ;
mark = IVinit(nthread, -1) ;
head = IVinit(nfront, -1) ;
link = IVinit(nfront, -1) ;
offsets = IVinit(nfront, 0) ;
counts = IVinit(nfront, 0) ;
if ( lockflag > 0 ) {
flags = CVinit(nfront, 'N') ;
} else {
flags = NULL ;
}
/*
--------------------
loop over the fronts
--------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
myid = frontOwners[J] ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n front %d, owner %d", J, myid) ;
fflush(stdout) ;
#endif
mark[myid] = J ;
count = 0 ;
/*
---------------------------------------------------
loop over all descendent fronts that might update J
---------------------------------------------------
*/
while ( (I = head[J]) != -1 ) {
head[J] = link[I] ;
jthread = frontOwners[I] ;
#if MYDEBUG > 0
fprintf(stdout, "\n descendent front %d, owner %d", I,
jthread) ;
fflush(stdout) ;
#endif
if ( mark[jthread] != J ) {
/*
--------------------------------
expect an aggregate from jthread
--------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, ", incoming aggregate") ;
fflush(stdout) ;
#endif
mark[jthread] = J ;
count++ ;
}
/*
--------------------------------------------------
link front I to next ancestor that it does not own
--------------------------------------------------
*/
IVL_listAndSize(symbfacIVL, I, &size, &indices) ;
for ( ii = offsets[I] ; ii < size ; ii++ ) {
if ( (K = vtxToFront[indices[ii]]) > J
&& frontOwners[K] != jthread ) {
#if MYDEBUG > 0
fprintf(stdout, ", link to %d", K) ;
fflush(stdout) ;
#endif
offsets[I] = ii ;
link[I] = head[K] ;
head[K] = I ;
break ;
}
}
}
/*
-------------------------------------
set the number of incoming aggregates
-------------------------------------
*/
counts[J] = count ;
#if MYDEBUG > 0
fprintf(stdout, "\n counts[%d] = %d", J, counts[J]) ;
fflush(stdout) ;
#endif
/*
---------------------------------------------------
set the flags to see if the list needs to be locked
---------------------------------------------------
*/
if ( flags != NULL ) {
if ( count > 1 ) {
flags[J] = 'Y' ;
} else {
flags[J] = 'N' ;
}
#if MYDEBUG > 0
fprintf(stdout, ", flags[%d] = %c", J, flags[J]) ;
fflush(stdout) ;
#endif
}
/*
--------------------------------------------------
link front J to next ancestor that it does not own
--------------------------------------------------
*/
IVL_listAndSize(symbfacIVL, J, &size, &indices) ;
for ( ii = 0 ; ii < size ; ii++ ) {
if ( (K = vtxToFront[indices[ii]]) > J && frontOwners[K] != myid
) {
#if MYDEBUG > 0
fprintf(stdout, ", linking to %d", K) ;
fflush(stdout) ;
#endif
offsets[J] = ii ;
link[J] = head[K] ;
head[K] = J ;
break ;
}
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n counts") ;
IVfprintf(stdout, nfront, counts) ;
fflush(stdout) ;
#endif
/*
-----------------------------------------
create and initialize the ChvList object
-----------------------------------------
*/
aggList = ChvList_new() ;
ChvList_init(aggList, nfront, counts, lockflag, flags) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(counts) ;
IVfree(head) ;
IVfree(link) ;
IVfree(offsets) ;
IVfree(mark) ;
if ( flags != NULL ) {
CVfree(flags) ;
}
return(aggList) ; }
/*--------------------------------------------------------------------*/
n,
forward solve, or backward solve.
the status[] vector will be set as follows:
status[J] = activeflag if J is on an active path
status[J] = inactiveflag if J is not on an active path
created -- 98mar27, cca
---------------------------------------------------FrontMtx/src/init.c 0100644 0002055 0007177 00000032243 06571323362 0015563 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../FrontMtx.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
purpose -- basic initializer
frontETree -- ETree object that stores the front tree
symbfacIVL -- IVL object that stores the symbolic factorization
manager -- SubMtxManager object to manage SubMtx objects
type -- type of entries
SPOOLES_REAL --> real
SPOOLES_COMPLEX --> complex
symmetryflag -- symmetry flag,
SPOOLES_SYMMETRIC --> symmetric structure and entries
SPOOLES_HERMITIAN --> hermitian (complex only)
SPOOLES_NONSYMMETRIC --> nonsymmetric entries
sparsityflag -- flag to specify dense or sparse fronts
FRONTMTX_DENSE_FRONTS --> dense fronts
FRONTMTX_SPARSE_FRONTS --> sparse fronts
pivotingflag -- flag to specify pivoting enabled
SPOOLES_NO_PIVOTING --> pivoting not used
SPOOLES_PIVOTING --> pivoting used
in a multithreaded environment, we need to protect the critical
section where data is allocated. we use a lockflag to do this.
in a serial or distributed environment, use lockflag = 0.
lockflag -- flag to specify lock status
NO_LOCK --> mutex lock is not allocated or initialized
LOCK_IN_PROCESS --> mutex lock is allocated and
it can synchronize only threads in this process.
LOCK_OVER_ALL_PROCESSES --> mutex lock is allocated and
it can synchronize only threads in this and other processes.
in a distributed environment we need to specify which process
owns each front. when we can preallocate data structures
(when there is no pivoting and dense fronts are stored) we
need each process to determine what parts of the data it
can allocate and set up. in a serial or multithreaded
environment, use ownersIV = NULL.
ownersIV -- map from fronts to owning processes
myid -- id of this process.
submatrices (be they lower, diagonal, block diagonal, upper)
are stored in SubMtx objects. the management of these objects,
(allocation and deallocation) is managed by the SubMtxManager
manager object.
manager -- SubMtxManager object to handle the submatrices
created -- 98may04, cca
------------------------------------------------------------------
*/
void
FrontMtx_init (
FrontMtx *frontmtx,
ETree *frontETree,
IVL *symbfacIVL,
int type,
int symmetryflag,
int sparsityflag,
int pivotingflag,
int lockflag,
int myid,
IV *ownersIV,
SubMtxManager *manager,
int msglvl,
FILE *msgFile
) {
SubMtx *mtx ;
int J, nbytes, nentD, nentL, nentU, neqns, nD, nent, nfront, nU ;
int *bndwghts, *nodwghts, *owners, *vtxToFront ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || frontETree == NULL || symbfacIVL == NULL
|| (ownersIV != NULL && myid < 0)
|| manager == NULL ) {
fprintf(stderr,
"\n fatal error in FrontMtx_init()"
"\n frontmtx %p, frontETree %p, symbfacIVL %p"
"\n myid %d, ownersIV %p, manager %p"
"\n bad input\n",
frontmtx, frontETree, symbfacIVL, myid, ownersIV, manager) ;
exit(-1) ;
}
if ( type != SPOOLES_REAL && type != SPOOLES_COMPLEX ) {
fprintf(stderr, "\n fatal error in FrontMtx_init()"
"\n type %d must be SPOOLES_REAL or SPOOLES_COMPLEX\n",
type) ;
exit(-1) ;
}
if ( type == SPOOLES_REAL &&
! (symmetryflag == SPOOLES_SYMMETRIC
|| symmetryflag == SPOOLES_NONSYMMETRIC) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_init()"
"\n type is real"
"\n symmetryflag is not SPOOLES_SYMMETRIC or SPOOLES_NONSYMMETRIC") ;
exit(-1) ;
}
if ( type == SPOOLES_COMPLEX &&
! (symmetryflag == SPOOLES_SYMMETRIC
|| symmetryflag == SPOOLES_HERMITIAN
|| symmetryflag == SPOOLES_NONSYMMETRIC) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_init()"
"\n type is real, symmetryflag is not SPOOLES_SYMMETRIC,"
"\n SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC") ;
exit(-1) ;
}
if ( ! ( pivotingflag == SPOOLES_PIVOTING
|| pivotingflag == SPOOLES_NO_PIVOTING) ) {
fprintf(stderr, "\n fatal error in FrontMtx_init()"
"\n pivotingflag must be SPOOLES_PIVOTING or SPOOLES_NO_PIVOTING\n") ;
exit(-1) ;
}
if ( ! (lockflag == NO_LOCK
|| lockflag == LOCK_IN_PROCESS
|| lockflag == LOCK_OVER_ALL_PROCESSES) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_init()"
"\n invalid lockflag, must be NO_LOCK"
"\n LOCK_IN_PROCESS or LOCK_OVER_ALL_PROCESSES") ;
exit(-1) ;
}
nfront = frontETree->nfront ;
neqns = frontETree->nvtx ;
nodwghts = ETree_nodwghts(frontETree) ;
bndwghts = ETree_bndwghts(frontETree) ;
vtxToFront = ETree_vtxToFront(frontETree) ;
if ( ownersIV != NULL ) {
owners = IV_entries(ownersIV) ;
} else {
owners = NULL ;
}
/*
----------------------
set the default fields
----------------------
*/
FrontMtx_setDefaultFields(frontmtx) ;
/*
---------------------
set the scalar fields
---------------------
*/
frontmtx->nfront = nfront ;
frontmtx->neqns = neqns ;
frontmtx->type = type ;
frontmtx->symmetryflag = symmetryflag ;
frontmtx->sparsityflag = sparsityflag ;
frontmtx->pivotingflag = pivotingflag ;
frontmtx->dataMode = FRONTMTX_1D_MODE ;
/*
---------------------------------------------------------------
set the front tree ETree and symbolic factorization IVL objects
---------------------------------------------------------------
*/
frontmtx->tree = frontETree->tree ;
frontmtx->frontETree = frontETree ;
frontmtx->symbfacIVL = symbfacIVL ;
/*
----------------------------
set the frontsizes IV object
----------------------------
*/
frontmtx->frontsizesIV = IV_new() ;
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
IV_init(frontmtx->frontsizesIV, nfront, NULL) ;
IV_fill(frontmtx->frontsizesIV, 0) ;
} else {
IV_init(frontmtx->frontsizesIV, nfront, nodwghts) ;
}
/*
------------------------------------------------------
set the row and column adjacency objects, if necessary
------------------------------------------------------
*/
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
frontmtx->coladjIVL = IVL_new() ;
IVL_init1(frontmtx->coladjIVL, IVL_CHUNKED, nfront) ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
frontmtx->rowadjIVL = IVL_new() ;
IVL_init1(frontmtx->rowadjIVL, IVL_CHUNKED, nfront) ;
}
}
/*
---------------------------------
allocate the five pointer vectors
---------------------------------
*/
ALLOCATE(frontmtx->p_mtxDJJ, struct _SubMtx *, nfront) ;
ALLOCATE(frontmtx->p_mtxUJJ, struct _SubMtx *, nfront) ;
ALLOCATE(frontmtx->p_mtxUJN, struct _SubMtx *, nfront) ;
for ( J = 0 ; J < nfront ; J++ ) {
frontmtx->p_mtxDJJ[J] = NULL ;
frontmtx->p_mtxUJJ[J] = NULL ;
frontmtx->p_mtxUJN[J] = NULL ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
ALLOCATE(frontmtx->p_mtxLJJ, struct _SubMtx *, nfront) ;
ALLOCATE(frontmtx->p_mtxLNJ, struct _SubMtx *, nfront) ;
for ( J = 0 ; J < nfront ; J++ ) {
frontmtx->p_mtxLJJ[J] = NULL ;
frontmtx->p_mtxLNJ[J] = NULL ;
}
}
/*
-------------------------------
set the submatrix manager field
-------------------------------
*/
frontmtx->manager = manager ;
/*
-------------------------------------
initialize submatrices where possible
-------------------------------------
*/
if ( ! FRONTMTX_IS_PIVOTING(frontmtx)
&& FRONTMTX_IS_DENSE_FRONTS(frontmtx) ) {
double *entries ;
int ii, jj, ncol, nrow ;
int *firstlocs, *sizes ;
nentD = nentL = nentU = 0 ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( owners == NULL || owners[J] == myid ) {
nD = nodwghts[J] ;
nU = bndwghts[J] ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n J %d, nD %d, nU %d", J, nD, nU) ;
fflush(msgFile) ;
}
/*
---------------
diagonal matrix
---------------
*/
nbytes = SubMtx_nbytesNeeded(type, SUBMTX_DIAGONAL,
nD, nD, nD) ;
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, type, SUBMTX_DIAGONAL, J, J, nD, nD, nD);
SubMtx_diagonalInfo(mtx, &ncol, &entries) ;
SubMtx_zero(mtx) ;
nentD += nD ;
frontmtx->p_mtxDJJ[J] = mtx ;
if ( msglvl > 3 ) {
fprintf(msgFile,
"\n diagonal (%d,%d) matrix %p, %d entries, %d bytes",
J, J, mtx, nD, nbytes) ;
fflush(msgFile) ;
}
if ( (nent = (nD*(nD-1))/2) > 0 ) {
/*
-------------------------------------------
U_{J,J} and possibly lower L_{J,J} matrices
-------------------------------------------
*/
nbytes = SubMtx_nbytesNeeded(type, SUBMTX_DENSE_SUBCOLUMNS,
nD, nD, nent) ;
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, type, SUBMTX_DENSE_SUBCOLUMNS,
J, J, nD, nD, nent);
SubMtx_denseSubcolumnsInfo(mtx, &ncol, &nent, &firstlocs,
&sizes, &entries) ;
for ( jj = 0 ; jj < ncol ; jj++ ) {
firstlocs[jj] = 0 ;
sizes[jj] = jj ;
}
SubMtx_zero(mtx) ;
nentU += nent ;
frontmtx->p_mtxUJJ[J] = mtx ;
if ( msglvl > 3 ) {
fprintf(msgFile,
"\n upper (%d,%d) matrix %p, %d entries, %d bytes",
J, J, mtx, nent, nbytes) ;
fflush(msgFile) ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
nbytes = SubMtx_nbytesNeeded(type, SUBMTX_DENSE_SUBROWS,
nD, nD, nent) ;
mtx = SubMtxManager_newObjectOfSizeNbytes(manager,
nbytes);
SubMtx_init(mtx, type, SUBMTX_DENSE_SUBROWS,
J, J, nD, nD, nent);
SubMtx_denseSubrowsInfo(mtx, &nrow, &nent, &firstlocs,
&sizes, &entries) ;
for ( ii = 0 ; ii < nrow ; ii++ ) {
firstlocs[ii] = 0 ;
sizes[ii] = ii ;
}
SubMtx_zero(mtx) ;
nentL += nent ;
frontmtx->p_mtxLJJ[J] = mtx ;
if ( msglvl > 3 ) {
fprintf(msgFile,
"\n lower (%d,%d) matrix %p, %d entries, %d bytes",
J, J, mtx, nent, nbytes) ;
fflush(msgFile) ;
}
}
}
if ( (nent = nD*nU) > 0 ) {
/*
-----------------------------------------------
U_{J,bnd{J}} and possibly L_{bnd{J},J} matrices
-----------------------------------------------
*/
nbytes = SubMtx_nbytesNeeded(type, SUBMTX_DENSE_COLUMNS,
nD, nU, nent) ;
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, type, SUBMTX_DENSE_COLUMNS,
J, nfront, nD, nU, nent);
SubMtx_zero(mtx) ;
nentU += nent ;
frontmtx->p_mtxUJN[J] = mtx ;
if ( msglvl > 3 ) {
fprintf(msgFile,
"\n upper (%d,%d) matrix %p, %d entries, %d bytes",
J, nfront, mtx, nent, nbytes) ;
fflush(msgFile) ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
nbytes = SubMtx_nbytesNeeded(type, SUBMTX_DENSE_ROWS,
nU, nD, nent);
mtx = SubMtxManager_newObjectOfSizeNbytes(manager,
nbytes);
SubMtx_init(mtx, type, SUBMTX_DENSE_ROWS,
nfront, J, nU, nD, nent);
SubMtx_zero(mtx) ;
nentL += nent ;
frontmtx->p_mtxLNJ[J] = mtx ;
if ( msglvl > 3 ) {
fprintf(msgFile,
"\n lower (%d,%d) matrix %p, %d entries, %d bytes",
nfront, J, mtx, nent, nbytes) ;
fflush(msgFile) ;
}
}
}
}
}
frontmtx->nentD = nentD ;
frontmtx->nentL = nentL ;
frontmtx->nentU = nentU ;
}
if ( lockflag == LOCK_OVER_ALL_PROCESSES
|| lockflag == LOCK_IN_PROCESS ) {
/*
-----------------
allocate the lock
-----------------
*/
frontmtx->lock = Lock_new() ;
Lock_init(frontmtx->lock, lockflag) ;
}
/*
--------------------------------------
set the patch-and-go information field
--------------------------------------
*/
frontmtx->patchinfo = NULL ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n frontmtx->lock = %p", frontmtx->lock) ;
fflush(msgFile) ;
}
return ; }
/*--------------------------------------------------------------------*/
) {
fprintf(stderr,
"\n fatal error in FrontMtx_init()"
"\n type is real"
"\n symmetryflag is not SPOOLES_SYMMETRIC or SPOOLES_NONSYMMETRIC") ;
exit(-1) ;
}
if ( type == SPOOLES_COMPLEX &&
! (symmetryflag == SPOOLES_SYMMETRIC
|| symmetryflag == SPOOLES_HERMITIAN
|| symmetryflag == SPOOLES_NONSYMMETRIC) ) {
fprintf(FrontMtx/src/instance.c 0100644 0002055 0007177 00000036710 06571267172 0016435 0 ustar 00cleve compmath 0000040 0000006 /* instance.c */
#include "../FrontMtx.h"
/*--------------------------------------------------------------------*/
/*
--------------------------------------
purpose -- return the number of fronts
created -- 98may04, cca
--------------------------------------
*/
int
FrontMtx_nfront (
FrontMtx *frontmtx
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_nfront(%p)"
"\n bad input\n", frontmtx) ;
exit(-1) ;
}
return(frontmtx->nfront) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------
purpose -- return the number of equations
created -- 98may04, cca
-----------------------------------------
*/
int
FrontMtx_neqns (
FrontMtx *frontmtx
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_neqns(%p)"
"\n bad input\n", frontmtx) ;
exit(-1) ;
}
return(frontmtx->neqns) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
purpose -- return a pointer to the front Tree object
created -- 98may04, cca
----------------------------------------------------
*/
Tree *
FrontMtx_frontTree (
FrontMtx *frontmtx
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_frontTree(%p)"
"\n bad input\n", frontmtx) ;
exit(-1) ;
}
return(frontmtx->tree) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
simple method to return the dimensions of front J and the number
of bytes necessary for the Chv object to hold the front.
created -- 98may04, cca
----------------------------------------------------------------
*/
void
FrontMtx_initialFrontDimensions (
FrontMtx *frontmtx,
int J,
int *pnD,
int *pnL,
int *pnU,
int *pnbytes
) {
int nbytes, nD, nL, nU ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || J < 0 || J >= frontmtx->nfront
|| pnD == NULL || pnL == NULL || pnU == NULL || pnbytes == NULL ) {
fprintf(stderr,
"\n fatal error in FrontMtx_initialFrontDimensions()"
"\n frontmtx = %p, J = %d, pnD = %p, "
"pnL = %p, pnU = %p, pnbytes = %p",
frontmtx, J, pnD, pnL, pnU, pnbytes) ;
exit(-1) ;
}
switch ( frontmtx->type ) {
case SPOOLES_REAL :
switch ( frontmtx->symmetryflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_NONSYMMETRIC :
break ;
default :
fprintf(stderr,
"\n fatal error in FrontMtx_initialFrontDimensions()"
"\n real type, must be symmetric or nonsymmetric\n") ;
exit(-1) ;
break ;
}
break ;
case SPOOLES_COMPLEX :
switch ( frontmtx->symmetryflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
case SPOOLES_NONSYMMETRIC :
break ;
fprintf(stderr,
"\n fatal error in FrontMtx_initialFrontDimensions()"
"\n complex type, must be symmetric,"
"\n hermitian or nonsymmetric\n") ;
exit(-1) ;
break ;
}
break ;
default :
fprintf(stderr,
"\n fatal error in FrontMtx_initialFrontDimensions()"
"\n bad type, must be real or complex") ;
exit(-1) ;
break ;
}
nD = frontmtx->frontETree->nodwghtsIV->vec[J] ;
nL = nU = frontmtx->frontETree->bndwghtsIV->vec[J] ;
nbytes = Chv_nbytesNeeded(nD, nL, nU,
frontmtx->type, frontmtx->symmetryflag) ;
*pnD = nD ;
*pnL = nL ;
*pnU = nU ;
*pnbytes = nbytes ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
return the number of internal rows and columns in front J
created -- 98may04, cca
---------------------------------------------------------
*/
int
FrontMtx_frontSize (
FrontMtx *frontmtx,
int J
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || frontmtx->frontsizesIV == NULL
|| J < 0 || J >= frontmtx->nfront ) {
fprintf(stderr, "\n fatal error in FrontMtx_frontSize(%p,%d)"
"\n bad input\n", frontmtx, J) ;
exit(-1) ;
}
return(IV_entry(frontmtx->frontsizesIV, J)) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
set the number of internal rows and columns in front J
created -- 98may04, cca
------------------------------------------------------
*/
void
FrontMtx_setFrontSize (
FrontMtx *frontmtx,
int J,
int size
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || frontmtx->frontsizesIV == NULL
|| J < 0 || J >= frontmtx->nfront || size < 0 ) {
fprintf(stderr, "\n fatal error in FrontMtx_setFrontSize(%p,%d,%d)"
"\n bad input\n", frontmtx, J, size) ;
exit(-1) ;
}
IV_setEntry(frontmtx->frontsizesIV, J, size) ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
fill *pncol with the number of columns and
*pcolind with a pointer to the column indices
created -- 98may04, cca
---------------------------------------------
*/
void
FrontMtx_columnIndices (
FrontMtx *frontmtx,
int J,
int *pncol,
int **pcolind
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || J < 0 || J >= frontmtx->nfront
|| pncol == NULL || pcolind == NULL ) {
fprintf(stderr,
"\n fatal error in FrontMtx_columnIndices(%p,%d,%p,%p)"
"\n bad input\n", frontmtx, J, pncol, pcolind) ;
exit(-1) ;
}
if ( ! FRONTMTX_IS_PIVOTING(frontmtx) ) {
IVL_listAndSize(frontmtx->symbfacIVL, J, pncol, pcolind) ;
} else {
IVL_listAndSize(frontmtx->coladjIVL, J, pncol, pcolind) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------
fill *pnrow with the number of rows and
*prowind with a pointer to the rows indices
created -- 98may04, cca
-------------------------------------------
*/
void
FrontMtx_rowIndices (
FrontMtx *frontmtx,
int J,
int *pnrow,
int **prowind
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || J < 0 || J >= frontmtx->nfront
|| pnrow == NULL || prowind == NULL ) {
fprintf(stderr,
"\n fatal error in FrontMtx_rowIndices(%p,%d,%p,%p)"
"\n bad input\n", frontmtx, J, pnrow, prowind) ;
exit(-1) ;
}
if ( ! FRONTMTX_IS_PIVOTING(frontmtx) ) {
IVL_listAndSize(frontmtx->symbfacIVL, J, pnrow, prowind) ;
} else if ( FRONTMTX_IS_SYMMETRIC(frontmtx)
|| FRONTMTX_IS_HERMITIAN(frontmtx) ) {
IVL_listAndSize(frontmtx->coladjIVL, J, pnrow, prowind) ;
} else if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
IVL_listAndSize(frontmtx->rowadjIVL, J, pnrow, prowind) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- return a pointer to the (J,J) diagonal submatrix
created -- 98may04, cca
-----------------------------------------------------------
*/
SubMtx *
FrontMtx_diagMtx (
FrontMtx *frontmtx,
int J
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || J < 0 || J >= frontmtx->nfront ) {
fprintf(stderr, "\n fatal error in FrontMtx_diagMtx(%p,%d)"
"\n bad input\n", frontmtx, J) ;
exit(-1) ;
}
return(frontmtx->p_mtxDJJ[J]) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- return a pointer to the (J,K) upper submatrix
created -- 98may04, cca
--------------------------------------------------------
*/
SubMtx *
FrontMtx_upperMtx (
FrontMtx *frontmtx,
int J,
int K
) {
int rc ;
SubMtx *mtx ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL
|| J < 0 || J >= frontmtx->nfront
|| K < J || K > frontmtx->nfront ) {
fprintf(stderr, "\n fatal error in FrontMtx_upperMtx(%p,%d,%d)"
"\n bad input\n", frontmtx, J, K) ;
exit(-1) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
if ( K == frontmtx->nfront ) {
mtx = frontmtx->p_mtxUJN[J] ;
} else if ( K == J ) {
mtx = frontmtx->p_mtxUJJ[J] ;
}
} else if ( frontmtx->upperhash == NULL ) {
mtx = NULL ;
} else {
rc = I2Ohash_locate(frontmtx->upperhash, J, K, (void *) &mtx) ;
if ( rc == 0 ) {
mtx = NULL ;
}
}
return(mtx) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- return a pointer to the (K,J) lower submatrix
created -- 98may04, cca
--------------------------------------------------------
*/
SubMtx *
FrontMtx_lowerMtx (
FrontMtx *frontmtx,
int K,
int J
) {
int rc ;
SubMtx *mtx ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL
|| J < 0 || J >= frontmtx->nfront
|| K < J || K > frontmtx->nfront ) {
fprintf(stderr, "\n fatal error in FrontMtx_lowerMtx(%p,%d,%d)"
"\n bad input\n", frontmtx, K, J) ;
exit(-1) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
if ( K == frontmtx->nfront ) {
mtx = frontmtx->p_mtxLNJ[J] ;
} else if ( K == J ) {
mtx = frontmtx->p_mtxLJJ[J] ;
}
} else if ( frontmtx->lowerhash == NULL ) {
mtx = NULL ;
} else {
rc = I2Ohash_locate(frontmtx->lowerhash, K, J, (void *) &mtx) ;
if ( rc == 0 ) {
mtx = NULL ;
}
}
return(mtx) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
purpose -- fill *pnadj with the number of fronts K
such that L_{K,J} != 0 and *padj with a
pointer to a list of those fronts
created -- 98may04, cca
--------------------------------------------------
*/
void
FrontMtx_lowerAdjFronts (
FrontMtx *frontmtx,
int J,
int *pnadj,
int **padj
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL
|| J < 0 || J >= frontmtx->nfront
|| pnadj == NULL || padj == NULL ) {
fprintf(stderr,
"\n fatal error in FrontMtx_lowerAdjFronts(%p,%d,%p,%p)"
"\n bad input\n", frontmtx, J, pnadj, padj) ;
exit(-1) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
fprintf(stderr, "\n fatal error in FrontMtx_lowerAdjFronts()"
"\n data mode is 1-D, not 2-D\n") ;
exit(-1) ;
} else if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
IVL_listAndSize(frontmtx->lowerblockIVL, J, pnadj, padj) ;
} else {
IVL_listAndSize(frontmtx->upperblockIVL, J, pnadj, padj) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
purpose -- fill *pnadj with the number of fronts K
such that U_{J,K} != 0 and *padj with a
pointer to a list of those fronts
created -- 98may04, cca
--------------------------------------------------
*/
void
FrontMtx_upperAdjFronts (
FrontMtx *frontmtx,
int J,
int *pnadj,
int **padj
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL
|| J < 0 || J >= frontmtx->nfront
|| pnadj == NULL || padj == NULL ) {
fprintf(stderr,
"\n fatal error in FrontMtx_upperAdjFronts(%p,%d,%p,%p)"
"\n bad input\n", frontmtx, J, pnadj, padj) ;
exit(-1) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
fprintf(stderr, "\n fatal error in FrontMtx_upperAdjFronts()"
"\n data mode is 1, not 2\n") ;
exit(-1) ;
}
IVL_listAndSize(frontmtx->upperblockIVL, J, pnadj, padj) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- return the number of nonzero L_{K,J} blocks
created -- 98may04, cca
------------------------------------------------------
*/
int
FrontMtx_nLowerBlocks (
FrontMtx *frontmtx
) {
int nblocks ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_nLowerBlocks(%p)"
"\n bad input\n", frontmtx) ;
exit(-1) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
fprintf(stderr, "\n fatal error in FrontMtx_nLowerBlocks()"
"\n data mode is 1, not 2\n") ;
exit(-1) ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
nblocks = frontmtx->lowerblockIVL->tsize ;
} else {
nblocks = frontmtx->upperblockIVL->tsize ;
}
return(nblocks) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- return the number of nonzero U_{K,J} blocks
created -- 98may04, cca
------------------------------------------------------
*/
int
FrontMtx_nUpperBlocks (
FrontMtx *frontmtx
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_nUpperBlocks(%p)"
"\n bad input\n", frontmtx) ;
exit(-1) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
fprintf(stderr, "\n fatal error in FrontMtx_nUpperBlocks()"
"\n data mode is 1, not 2\n") ;
exit(-1) ;
}
return(frontmtx->upperblockIVL->tsize) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
purpose -- return a pointer to the upper block IVL object
created -- 98jun13, cca
---------------------------------------------------------
*/
IVL *
FrontMtx_upperBlockIVL (
FrontMtx *frontmtx
) {
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_upperBlockIVL(%p)"
"\n bad input\n", frontmtx) ;
exit(-1) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
fprintf(stderr, "\n fatal error in FrontMtx_upperBlockIVL()"
"\n data mode is 1, not 2\n") ;
exit(-1) ;
}
return(frontmtx->upperblockIVL) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
purpose -- return a pointer to the lower block IVL object
created -- 98jun13, cca
---------------------------------------------------------
*/
IVL *
FrontMtx_lowerBlockIVL (
FrontMtx *frontmtx
) {
IVL *ivl ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_lowerBlockIVL(%p)"
"\n bad input\n", frontmtx) ;
exit(-1) ;
}
if ( FRONTMTX_IS_1D_MODE(frontmtx) ) {
fprintf(stderr, "\n fatal error in FrontMtx_lowerBlockIVL()"
"\n data mode is 1, not 2\n") ;
exit(-1) ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
ivl = frontmtx->lowerblockIVL ;
} else {
ivl = frontmtx->upperblockIVL ;
}
return(ivl) ; }
/*--------------------------------------------------------------------*/
FrontMtx/src/loadEntries.c 0100644 0002055 0007177 00000015657 06571267172 0017111 0 ustar 00cleve compmath 0000040 0000006 /* loadEntries.c */
#include "../FrontMtx.h"
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
load entries from sigma*A
chv -- pointer to the Chv object that holds the front
pencil -- pointer to a Pencil that holds the matrix entries
msglvl -- message level
msgFile -- message file
created -- 97jul18, cca
------------------------------------------------------------
*/
void
FrontMtx_loadEntries (
Chv *chv,
Pencil *pencil,
int msglvl,
FILE *msgFile
) {
InpMtx *inpmtxA, *inpmtxB ;
double one[2] = {1.0,0.0} ;
double *sigma ;
double *chvent ;
int chvsize, ichv, ncol, nD, nL, nU ;
int *chvind, *colind ;
/*
---------------
check the input
---------------
*/
if ( chv == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_loadEntries(%p,%p,%d,%p)"
"\n bad input\n", chv, pencil, msglvl, msgFile) ;
exit(-1) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile,
"\n\n # inside loadEntries for chv %d"
", sigma = %12.4e + i*%12.4e",
chv->id, pencil->sigma[0], pencil->sigma[1]) ;
fflush(msgFile) ;
}
Chv_dimensions(chv, &nD, &nL, &nU) ;
Chv_columnIndices(chv, &ncol, &colind) ;
/*
----------------------------------------
load the original entries, A + sigma * B
----------------------------------------
*/
inpmtxA = pencil->inpmtxA ;
sigma = pencil->sigma ;
inpmtxB = pencil->inpmtxB ;
if ( inpmtxA != NULL ) {
int ii ;
/*
-------------------
load entries from A
-------------------
*/
for ( ii = 0 ; ii < nD ; ii++ ) {
ichv = colind[ii] ;
if ( INPMTX_IS_REAL_ENTRIES(inpmtxA) ) {
InpMtx_realVector(inpmtxA, ichv, &chvsize, &chvind, &chvent) ;
} else if ( INPMTX_IS_COMPLEX_ENTRIES(inpmtxA) ) {
InpMtx_complexVector(inpmtxA,
ichv, &chvsize, &chvind, &chvent) ;
}
if ( chvsize > 0 ) {
if ( msglvl > 3 ) {
int ierr ;
fprintf(msgFile, "\n inpmtxA chevron %d : chvsize = %d",
ichv, chvsize) ;
fprintf(msgFile, "\n chvind") ;
IVfp80(msgFile, chvsize, chvind, 80, &ierr) ;
fprintf(msgFile, "\n chvent") ;
if ( INPMTX_IS_REAL_ENTRIES(inpmtxA) ) {
DVfprintf(msgFile, chvsize, chvent) ;
} else if ( INPMTX_IS_COMPLEX_ENTRIES(inpmtxA) ) {
DVfprintf(msgFile, 2*chvsize, chvent) ;
}
fflush(msgFile) ;
}
Chv_addChevron(chv, one, ichv, chvsize, chvind, chvent) ;
}
}
} else {
double *entries ;
int ii, off, stride ;
/*
-----------------
load the identity
-----------------
*/
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
stride = nD + chv->nU ;
off = 0 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
entries[off] += 1.0 ;
off += stride ;
stride-- ;
}
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
stride = 2*nD + chv->nL + chv->nU - 2 ;
off = nD + chv->nL - 1 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
entries[off] += 1.0 ;
off += stride ;
stride -= 2 ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
stride = nD + chv->nU ;
off = 0 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
entries[2*off] += 1.0 ;
off += stride ;
stride-- ;
}
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
stride = 2*nD + chv->nL + chv->nU - 2 ;
off = nD + chv->nL - 1 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
entries[2*off] += 1.0 ;
off += stride ;
stride -= 2 ;
}
}
}
}
if ( inpmtxB != NULL ) {
int ii ;
/*
-------------------------
load entries from sigma*B
-------------------------
*/
for ( ii = 0 ; ii < nD ; ii++ ) {
ichv = colind[ii] ;
if ( INPMTX_IS_REAL_ENTRIES(inpmtxB) ) {
InpMtx_realVector(inpmtxB, ichv, &chvsize, &chvind, &chvent) ;
} else if ( INPMTX_IS_COMPLEX_ENTRIES(inpmtxA) ) {
InpMtx_complexVector(inpmtxB,
ichv, &chvsize, &chvind, &chvent) ;
}
if ( chvsize > 0 ) {
if ( msglvl > 3 ) {
int ierr ;
fprintf(msgFile, "\n inpmtxB chevron %d : chvsize = %d",
ichv, chvsize) ;
fprintf(msgFile, "\n chvind") ;
IVfp80(msgFile, chvsize, chvind, 80, &ierr) ;
fprintf(msgFile, "\n chvent") ;
if ( INPMTX_IS_REAL_ENTRIES(inpmtxA) ) {
DVfprintf(msgFile, chvsize, chvent) ;
} else if ( INPMTX_IS_COMPLEX_ENTRIES(inpmtxA) ) {
DVfprintf(msgFile, 2*chvsize, chvent) ;
}
}
Chv_addChevron(chv, sigma, ichv, chvsize, chvind, chvent) ;
}
}
} else {
double *entries ;
int ii, off, stride ;
/*
--------------------------------------
load a scalar multiple of the identity
--------------------------------------
*/
entries = Chv_entries(chv) ;
if ( CHV_IS_REAL(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) ) {
stride = nD + chv->nU ;
off = 0 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
entries[off] += sigma[0] ;
off += stride ;
stride-- ;
}
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
stride = 2*nD + chv->nL + chv->nU - 2 ;
off = nD + chv->nL - 1 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
entries[off] += sigma[0] ;
off += stride ;
stride -= 2 ;
}
}
} else if ( CHV_IS_COMPLEX(chv) ) {
if ( CHV_IS_SYMMETRIC(chv) || CHV_IS_HERMITIAN(chv) ) {
if ( CHV_IS_HERMITIAN(chv) && sigma[1] != 0.0 ) {
fprintf(stderr,
"\n fatal error in FrontMtx_loadEntries()"
"\n chevron is hermitian"
"\n sigma = %12.4e + %12.4e*i\n",
sigma[0], sigma[1]) ;
exit(-1) ;
}
stride = nD + chv->nU ;
off = 0 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
entries[2*off] += sigma[0] ;
entries[2*off+1] += sigma[1] ;
off += stride ;
stride-- ;
}
} else if ( CHV_IS_NONSYMMETRIC(chv) ) {
stride = 2*nD + chv->nL + chv->nU - 2 ;
off = nD + chv->nL - 1 ;
for ( ii = 0 ; ii < nD ; ii++ ) {
entries[2*off] += sigma[0] ;
entries[2*off+1] += sigma[1] ;
off += stride ;
stride -= 2 ;
}
}
}
}
return ; }
/*--------------------------------------------------------------------*/
FrontMtx/src/permute.c 0100644 0002055 0007177 00000024637 06571267172 0016317 0 ustar 00cleve compmath 0000040 0000006 /* permute.c */
#include "../FrontMtx.h"
/*--------------------------------------------------------------------*/
static void FrontMtx_reorderRowIndices ( FrontMtx *frontmtx, int J,
int K, int map[], int msglvl, FILE *msgFile ) ;
static void FrontMtx_reorderColumnIndices ( FrontMtx *frontmtx, int J,
int K, int map[], int msglvl, FILE *msgFile ) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
purpose -- permute the upper adjacency structure so that the
indices in bnd{J} are in ascending order w.r.t. their ancestors
created -- 98mar05, cca
------------------------------------------------------------------
*/
void
FrontMtx_permuteUpperAdj (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) {
int J, K, neqns ;
int *map, *par ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_permuteUpperAdj(%p,%d,%p)"
"\n badn input\n", frontmtx, msglvl, msgFile) ;
exit(-1) ;
}
neqns = FrontMtx_neqns(frontmtx) ;
map = IVinit(neqns, -1) ;
tree = FrontMtx_frontTree(frontmtx) ;
par = tree->par ;
for ( J = Tree_preOTfirst(tree) ;
J != -1 ;
J = Tree_preOTnext(tree, J) ) {
if ( (K = par[J]) != -1 ) {
FrontMtx_reorderColumnIndices(frontmtx, J, K, map,
msglvl, msgFile) ;
}
}
IVfree(map) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
purpose -- permute the lower adjacency structure so that the
indices in bnd{J} are in ascending order w.r.t. their ancestors
created -- 98mar05, cca
------------------------------------------------------------------
*/
void
FrontMtx_permuteLowerAdj (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) {
int J, K, neqns ;
int *map, *par ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_permuteLowerAdj(%p,%d,%p)"
"\n badn input\n", frontmtx, msglvl, msgFile) ;
exit(-1) ;
}
neqns = FrontMtx_neqns(frontmtx) ;
map = IVinit(neqns, -1) ;
tree = FrontMtx_frontTree(frontmtx) ;
par = tree->par ;
for ( J = Tree_preOTfirst(tree) ;
J != -1 ;
J = Tree_preOTnext(tree, J) ) {
if ( (K = par[J]) != -1 ) {
FrontMtx_reorderRowIndices(frontmtx, J, K, map,
msglvl, msgFile) ;
}
}
IVfree(map) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
purpose -- if the columns indices of the front matrix are in
different order than the column indices of U_{J,bnd{J}},
sort the columns of U_{J,bnd{J}} into ascending order
w.r.t the column indices of the front matrix.
created -- 98mar05, cca
------------------------------------------------------------
*/
void
FrontMtx_permuteUpperMatrices (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) {
SubMtx *mtxUJ ;
int ii, jj, J, mustdo, neqns, nfront, ncolJ, ncolUJ, nJ ;
int *map, *colindJ, *colindUJ ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_permuteUpperMatrices(%p,%d,%p)"
"\n badn input\n", frontmtx, msglvl, msgFile) ;
exit(-1) ;
}
nfront = FrontMtx_nfront(frontmtx) ;
neqns = FrontMtx_neqns(frontmtx) ;
map = IVinit(neqns, -1) ;
for ( J = 0 ; J < nfront ; J++ ) {
mtxUJ = FrontMtx_upperMtx(frontmtx, J, nfront) ;
if ( mtxUJ != NULL ) {
nJ = FrontMtx_frontSize(frontmtx, J) ;
FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
SubMtx_columnIndices(mtxUJ, &ncolUJ, &colindUJ) ;
for ( ii = nJ, jj = mustdo = 0 ; ii < ncolJ ; ii++, jj++ ) {
if ( colindJ[ii] != colindUJ[jj] ) {
mustdo = 1 ; break ;
}
}
if ( mustdo == 1 ) {
for ( ii = 0 ; ii < ncolJ ; ii++ ) {
map[colindJ[ii]] = ii ;
}
for ( ii = 0 ; ii < ncolUJ ; ii++ ) {
colindUJ[ii] = map[colindUJ[ii]] ;
}
SubMtx_sortColumnsUp(mtxUJ) ;
for ( ii = 0 ; ii < ncolUJ ; ii++ ) {
colindUJ[ii] = colindJ[colindUJ[ii]] ;
}
}
}
}
IVfree(map) ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- if the row indices of the front matrix are in
different order than the row indices of L_{bnd{J},J},
sort the rows of L_{bnd{J},J} into ascending order
w.r.t the row indices of the front matrix.
created -- 98mar05, cca
--------------------------------------------------------
*/
void
FrontMtx_permuteLowerMatrices (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) {
SubMtx *mtxLJ ;
int ii, jj, J, mustdo, neqns, nfront, nJ, nrowJ, nrowUJ ;
int *map, *rowindJ, *rowindUJ ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_permuteLowerMatrices(%p,%d,%p)"
"\n badn input\n", frontmtx, msglvl, msgFile) ;
exit(-1) ;
}
nfront = FrontMtx_nfront(frontmtx) ;
neqns = FrontMtx_neqns(frontmtx) ;
map = IVinit(neqns, -1) ;
for ( J = 0 ; J < nfront ; J++ ) {
mtxLJ = FrontMtx_lowerMtx(frontmtx, nfront, J) ;
if ( mtxLJ != NULL ) {
nJ = FrontMtx_frontSize(frontmtx, J) ;
FrontMtx_rowIndices(frontmtx, J, &nrowJ, &rowindJ) ;
SubMtx_rowIndices(mtxLJ, &nrowUJ, &rowindUJ) ;
for ( ii = nJ, jj = mustdo = 0 ; ii < nrowJ ; ii++, jj++ ) {
if ( rowindJ[ii] != rowindUJ[jj] ) {
mustdo = 1 ; break ;
}
}
if ( mustdo == 1 ) {
for ( ii = 0 ; ii < nrowJ ; ii++ ) {
map[rowindJ[ii]] = ii ;
}
for ( ii = 0 ; ii < nrowUJ ; ii++ ) {
rowindUJ[ii] = map[rowindUJ[ii]] ;
}
SubMtx_sortRowsUp(mtxLJ) ;
for ( ii = 0 ; ii < nrowUJ ; ii++ ) {
rowindUJ[ii] = rowindJ[rowindUJ[ii]] ;
}
}
}
}
IVfree(map) ;
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
purpose -- to reorder the column indices in bnd{J}
to be ascending order w.r.t. K cup bnd{K}
created -- 98mar07, cca
--------------------------------------------------
*/
static void
FrontMtx_reorderColumnIndices (
FrontMtx *frontmtx,
int J,
int K,
int map[],
int msglvl,
FILE *msgFile
) {
int ii, ncolJ, ncolK, nJ ;
int *colindJ, *colindK ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n inside reorderColumnIndices(%d,%d)", J, K) ;
fflush(msgFile) ;
}
nJ = FrontMtx_frontSize(frontmtx, J) ;
FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n nJ = %d, ncolJ = %d", nJ, ncolJ) ;
fflush(msgFile) ;
}
if ( ncolJ == 0 ) {
return ;
}
FrontMtx_columnIndices(frontmtx, K, &ncolK, &colindK) ;
if ( msglvl > 2 ) {
fprintf(msgFile, ", ncolK = %d", ncolK) ;
fflush(msgFile) ;
}
if ( ncolK == 0 ) {
fprintf(stderr, "\n fatal error FrontMtx_reorderColumnIndices()"
"\n J = %d, K = %d, nJ = %d, ncolJ = %d, ncolK = %d\n",
J, K, nJ, ncolJ, ncolK) ;
exit(-1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n colindJ") ;
IVfprintf(msgFile, ncolJ, colindJ) ;
fprintf(msgFile, "\n colindK") ;
IVfprintf(msgFile, ncolK, colindK) ;
fflush(msgFile) ;
}
for ( ii = 0 ; ii < ncolK ; ii++ ) {
map[colindK[ii]] = ii ;
}
for ( ii = nJ ; ii < ncolJ ; ii++ ) {
colindJ[ii] = map[colindJ[ii]] ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n local colindJ") ;
IVfprintf(msgFile, ncolJ, colindJ) ;
fflush(msgFile) ;
}
IVqsortUp(ncolJ - nJ, colindJ + nJ) ;
for ( ii = nJ ; ii < ncolJ ; ii++ ) {
colindJ[ii] = colindK[colindJ[ii]] ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n global colindJ") ;
IVfprintf(msgFile, ncolJ, colindJ) ;
fflush(msgFile) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
purpose -- to reorder the row indices in bnd{J}
to be ascending order w.r.t. K cup bnd{K}
created -- 98mar07, cca
-----------------------------------------------
*/
static void
FrontMtx_reorderRowIndices (
FrontMtx *frontmtx,
int J,
int K,
int map[],
int msglvl,
FILE *msgFile
) {
int ii, nrowJ, nrowK, nJ ;
int *rowindJ, *rowindK ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n inside reorderRowIndices(%d,%d)", J, K) ;
fflush(msgFile) ;
}
nJ = FrontMtx_frontSize(frontmtx, J) ;
FrontMtx_rowIndices(frontmtx, J, &nrowJ, &rowindJ) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n nJ = %d, nrowJ = %d", nJ, nrowJ) ;
fflush(msgFile) ;
}
if ( nrowJ == 0 ) {
return ;
}
FrontMtx_rowIndices(frontmtx, K, &nrowK, &rowindK) ;
if ( msglvl > 2 ) {
fprintf(msgFile, ", nrowK = %d", nrowK) ;
fflush(msgFile) ;
}
if ( nrowK == 0 ) {
fprintf(stderr, "\n fatal error FrontMtx_reorderRowIndices()"
"\n J = %d, K = %d, nJ = %d, nrowJ = %d, nrowK = %d\n",
J, K, nJ, nrowJ, nrowK) ;
exit(-1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n rowindJ") ;
IVfprintf(msgFile, nrowJ, rowindJ) ;
fprintf(msgFile, "\n rowindK") ;
IVfprintf(msgFile, nrowK, rowindK) ;
fflush(msgFile) ;
}
for ( ii = 0 ; ii < nrowK ; ii++ ) {
map[rowindK[ii]] = ii ;
}
for ( ii = nJ ; ii < nrowJ ; ii++ ) {
rowindJ[ii] = map[rowindJ[ii]] ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n local rowindJ") ;
IVfprintf(msgFile, nrowJ, rowindJ) ;
fflush(msgFile) ;
}
IVqsortUp(nrowJ - nJ, rowindJ + nJ) ;
for ( ii = nJ ; ii < nrowJ ; ii++ ) {
rowindJ[ii] = rowindK[rowindJ[ii]] ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n global rowindJ") ;
IVfprintf(msgFile, nrowJ, rowindJ) ;
fflush(msgFile) ;
}
return ; }
/*--------------------------------------------------------------------*/
FrontMtx/src/postProcess.c 0100644 0002055 0007177 00000012245 06612130370 0017133 0 ustar 00cleve compmath 0000040 0000006 /* postProcess.c */
#include "../FrontMtx.h"
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
purpose -- post-process the factorization
(1) permute row and column adjacency objects if necessary
(2) permute lower and upper matrices if necessary
(3) update the block adjacency objects if necessary
(4) split the chevron submatrices into submatrices
and make the submatrix indices local w.r.t their fronts
created -- 98mar05, cca
--------------------------------------------------------------
*/
void
FrontMtx_postProcess (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) {
int nfront ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_postProcess(%p,%d,%p)"
"\n bad input\n", frontmtx, msglvl, msgFile) ;
exit(-1) ;
}
nfront = frontmtx->nfront ;
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
IV *colmapIV, *rowmapIV ;
/*
-------------------------------
permute the adjacency object(s)
-------------------------------
*/
FrontMtx_permuteUpperAdj(frontmtx, msglvl, msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n new column adjacency object") ;
IVL_writeForHumanEye(frontmtx->coladjIVL, msgFile) ;
fflush(msgFile) ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
FrontMtx_permuteLowerAdj(frontmtx, msglvl, msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n new row adjacency object") ;
IVL_writeForHumanEye(frontmtx->rowadjIVL, msgFile) ;
fflush(msgFile) ;
}
}
/*
-------------------------------------------------------------
permute the U_{J,bnd{J}} and L_{bnd{J},J} triangular matrices
-------------------------------------------------------------
*/
FrontMtx_permuteUpperMatrices(frontmtx, msglvl, msgFile) ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
FrontMtx_permuteLowerMatrices(frontmtx, msglvl, msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front factor matrix after pivoting") ;
FrontMtx_writeForHumanEye(frontmtx, msgFile) ;
}
/*
-----------------------------------------------
get the map from columns to owning fronts
and create the new upper block adjacency object
-----------------------------------------------
*/
colmapIV = FrontMtx_colmapIV(frontmtx) ;
frontmtx->upperblockIVL = FrontMtx_makeUpperBlockIVL(frontmtx,
colmapIV) ;
IV_free(colmapIV) ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
-------------------------------------------
get the map from rows to owning fronts and
create the new lower block adjacency object
-------------------------------------------
*/
rowmapIV = FrontMtx_rowmapIV(frontmtx) ;
frontmtx->lowerblockIVL
= FrontMtx_makeLowerBlockIVL(frontmtx, rowmapIV) ;
IV_free(rowmapIV) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n new upper block adjacency object") ;
IVL_writeForHumanEye(frontmtx->upperblockIVL, msgFile) ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
fprintf(msgFile, "\n\n new lower block adjacency object") ;
IVL_writeForHumanEye(frontmtx->lowerblockIVL, msgFile) ;
}
fflush(msgFile) ;
}
} else {
/*
---------------------------------------
get the upper block adjacency structure
---------------------------------------
*/
IV *vtxToFrontIV = ETree_vtxToFrontIV(frontmtx->frontETree) ;
frontmtx->upperblockIVL
= FrontMtx_makeUpperBlockIVL(frontmtx, vtxToFrontIV) ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
---------------------------------------
get the lower block adjacency structure
---------------------------------------
*/
frontmtx->lowerblockIVL
= FrontMtx_makeLowerBlockIVL(frontmtx, vtxToFrontIV) ;
}
}
/*
------------------------
allocate the hash tables
------------------------
*/
frontmtx->upperhash = I2Ohash_new() ;
I2Ohash_init(frontmtx->upperhash, nfront, nfront, nfront) ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
frontmtx->lowerhash = I2Ohash_new() ;
I2Ohash_init(frontmtx->lowerhash, nfront, nfront, nfront) ;
} else {
frontmtx->lowerhash = NULL ;
}
/*
--------------------------------------------------------
split the U_{J,bnd{J}} and L_{bnd{J},J} into submatrices
put the U_{J,K} and L_{K,J} matrices into hash tables,
free the p_mtx*[] vectors.
--------------------------------------------------------
*/
FrontMtx_splitUpperMatrices(frontmtx, msglvl, msgFile) ;
FREE(frontmtx->p_mtxUJJ) ; frontmtx->p_mtxUJJ = NULL ;
FREE(frontmtx->p_mtxUJN) ; frontmtx->p_mtxUJN = NULL ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
FrontMtx_splitLowerMatrices(frontmtx, msglvl, msgFile) ;
FREE(frontmtx->p_mtxLJJ) ; frontmtx->p_mtxLJJ = NULL ;
FREE(frontmtx->p_mtxLNJ) ; frontmtx->p_mtxLNJ = NULL ;
}
frontmtx->dataMode = FRONTMTX_2D_MODE ;
return ; }
/*--------------------------------------------------------------------*/
FrontMtx/src/postponed.c 0100644 0002055 0007177 00000014542 06571267172 0016643 0 ustar 00cleve compmath 0000040 0000006 /* postponed.c */
#include "../FrontMtx.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
purpose -- to assemble any postponed data into frontJ
frontJ -- pointer to Chv objec that contains current front
chvlist -- pointer to a ChvList object that handles the
lists of postponed Chv objects
chvmanager -- pointer to a ChvManager object for the list
of free Chv objects
pndelay -- pointer to address to contain the # of delayed rows
and columns that were assembled into the front
return value -- pointer to Chv object that contains the new front
created -- 98may04, cca
------------------------------------------------------------------
*/
Chv *
FrontMtx_assemblePostponedData (
FrontMtx *frontmtx,
Chv *frontJ,
ChvList *chvlist,
ChvManager *chvmanager,
int *pndelay
) {
Chv *child, *child2, *firstchild, *newfrontJ, *nextchild, *prev ;
int nbytes, nDnew ;
if ( (firstchild = ChvList_getList(chvlist, frontJ->id)) == NULL ) {
/*
-------------------------------------
quick return, no children to assemble
-------------------------------------
*/
*pndelay = 0 ;
return(frontJ) ;
}
/*
-------------------------------------------------------
order the children in ascending order of their front id
this is done to ensure that the serial, multithreaded
and MPI codes all assemble the same frontal matrix.
-------------------------------------------------------
*/
#if MYDEBUG > 0
fprintf(stdout, "\n postponed children of %d :", frontJ->id) ;
for ( child = firstchild ; child != NULL ; child = child->next ) {
fprintf(stdout, " %d", child->id) ;
}
fflush(stdout) ;
#endif
for ( child = firstchild, firstchild = NULL ;
child != NULL ;
child = nextchild ) {
nextchild = child->next ;
for ( child2 = firstchild, prev = NULL ;
child2 != NULL ;
child2 = child2->next ) {
if ( child2->id > child->id ) {
break ;
}
prev = child2 ;
}
if ( prev == NULL ) {
firstchild = child ;
} else {
prev->next = child ;
}
child->next = child2 ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n front %d, postponed children reordered :",
frontJ->id) ;
for ( child = firstchild ; child != NULL ; child = child->next ) {
fprintf(stdout, " %d", child->id) ;
}
fflush(stdout) ;
#endif
/*
--------------------------
compute the new dimensions
--------------------------
*/
nDnew = frontJ->nD ;
for ( child = firstchild ; child != NULL ; child = child->next ) {
nDnew += child->nD ;
}
/*
------------------------
get a new chevron object
------------------------
*/
nbytes = Chv_nbytesNeeded(nDnew, frontJ->nL, frontJ->nU,
frontJ->type, frontJ->symflag) ;
newfrontJ = ChvManager_newObjectOfSizeNbytes(chvmanager, nbytes) ;
Chv_init(newfrontJ, frontJ->id, nDnew, frontJ->nL, frontJ->nU,
frontJ->type, frontJ->symflag) ;
/*
----------------------------------------------------------
pivoting has been enabled, assemble any postponed chevrons
----------------------------------------------------------
*/
*pndelay = Chv_assemblePostponedData(newfrontJ, frontJ, firstchild) ;
/*
--------------------------------------------------
now put the postponed chevrons onto the free list.
--------------------------------------------------
*/
ChvManager_releaseListOfObjects(chvmanager, firstchild) ;
/*
-------------------------------------
set the delay to zero if a root front
-------------------------------------
*/
if ( frontJ->nU == 0 ) {
*pndelay = 0 ;
}
return(newfrontJ) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
purpose -- extract and store the postponed data
frontJ -- pointer to present front object
npost -- # of postponed rows and columns in frontJ
K -- parent of J
chvlist -- pointer to a ChvList object that handles the
lists of postponed Chv objects
a singly linked list to assemble
chvmanager -- pointer to a ChvManager object for the list
of free Chv objects
created -- 98may04, cca
---------------------------------------------------------
*/
void
FrontMtx_storePostponedData (
FrontMtx *frontmtx,
Chv *frontJ,
int npost,
int K,
ChvList *chvlist,
ChvManager *chvmanager
) {
Chv *chv ;
int nbytes, nD, nent, nind, nL, nU ;
if ( npost <= 0 && chvlist != NULL ) {
if ( K == -1 ) {
ChvList_addObjectToList(chvlist, NULL, frontmtx->nfront) ;
} else {
ChvList_addObjectToList(chvlist, NULL, K) ;
}
return ;
}
/*
--------------------------------------
find the number of indices and entries
necessary to store the delayed data
--------------------------------------
*/
Chv_dimensions(frontJ, &nD, &nL, &nU) ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n front %d: npost = %d, nD = %d, nL = %d, nU = %d",
frontJ->id, npost, nD, nL, nU) ;
fflush(stdout) ;
#endif
if ( CHV_IS_SYMMETRIC(frontJ) || CHV_IS_HERMITIAN(frontJ) ) {
nind = npost + nU ;
nent = (npost*(npost+1))/2 + npost*nU ;
} else if ( CHV_IS_NONSYMMETRIC(frontJ) ) {
nind = 2*(npost + nU) ;
nent = npost*(npost + 2*nU) ;
}
/*
------------------------------------
get a Chv object from the free list
------------------------------------
*/
nbytes = Chv_nbytesNeeded(npost, nL, nU, frontJ->type, frontJ->symflag);
chv = ChvManager_newObjectOfSizeNbytes(chvmanager, nbytes) ;
Chv_init(chv, frontJ->id, npost, nL, nU, frontJ->type, frontJ->symflag);
/*
----------------------
store the delayed data
----------------------
*/
Chv_copyTrailingPortion(chv, frontJ, nD - npost) ;
frontJ->nD -= npost ;
frontJ->nL += npost ;
frontJ->nU += npost ;
#if MYDEBUG > 0
fprintf(stdout, "\n\n postponed chevron %p", chv) ;
Chv_writeForHumanEye(chv, stdout) ;
fflush(stdout) ;
#endif
/*
------------------------------
link the postponed Chv object
------------------------------
*/
if ( K == -1 ) {
ChvList_addObjectToList(chvlist, chv, frontmtx->nfront) ;
} else {
ChvList_addObjectToList(chvlist, chv, K) ;
}
return ; }
/*--------------------------------------------------------------------*/
----------------------
order the children in ascending order of their front id
this is done to ensure that the serial, multithreaded
and MPI codes alFrontMtx/src/solve.c 0100644 0002055 0007177 00000013406 06571267171 0015755 0 ustar 00cleve compmath 0000040 0000006 /* solve.c */
#include "../FrontMtx.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
purpose -- to solve a linear system
frontmtx -- FrontMtx object that holds the factor matrices
solmtx -- DenseMtx that holds the solution
rhsmtx -- DenseMtx that holds the right hand side matrix
note: right hand side entries are copied from rhsmtx,
and solution entries are copied into solmtx.
when the row indices of rhsmtx and solmtx are
identical, rhsmtx and solmtx can be the same object.
cpus -- vector to hold cpu breakdown time
cpus[0] -- set up solves
cpus[1] -- fetch rhs and store solution
cpus[2] -- forward solve
cpus[3] -- diagonal solve
cpus[4] -- backward solve
cpus[5] -- total time
mtxmanager -- object that manages working storage
msglvl -- message level
msgFile -- message file
created -- 98may04, cca
------------------------------------------------------------
*/
void
FrontMtx_solve (
FrontMtx *frontmtx,
DenseMtx *solmtx,
DenseMtx *rhsmtx,
SubMtxManager *mtxmanager,
double cpus[],
int msglvl,
FILE *msgFile
) {
char *frontIsDone, *status ;
SubMtx **p_mtx ;
double t0, t1, t2 ;
int J, nfront, nrhs ;
IP **heads ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
MARKTIME(t0) ;
if ( frontmtx == NULL || solmtx == NULL || rhsmtx == NULL
|| mtxmanager == NULL
|| cpus == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr, "\n fatal error in FrontMtx_solve()"
"\n bad input :"
"\n frontmtx = %p, solmtx = %p, rhsmtx = %p"
"\n mtxmanager = %p, cpus = %p"
"\n msglvl = %d, msgFile = %p\n",
frontmtx, solmtx, rhsmtx, mtxmanager,
cpus, msglvl, msgFile) ;
exit(-1) ;
}
nfront = FrontMtx_nfront(frontmtx) ;
tree = FrontMtx_frontTree(frontmtx) ;
nrhs = rhsmtx->ncol ;
/*
--------------------------------------------------
set up the update head/links for the forward solve
--------------------------------------------------
*/
MARKTIME(t1) ;
heads = FrontMtx_forwardSetup(frontmtx, msglvl, msgFile ) ;
frontIsDone = CVinit(nfront, 'N') ;
status = CVinit(nfront, 'W') ;
MARKTIME(t2) ;
cpus[0] = t2 - t1 ;
/*
----------------------------------------------------
load the right hand side into temporary SubMtx objects
----------------------------------------------------
*/
MARKTIME(t1) ;
p_mtx = FrontMtx_loadRightHandSide(frontmtx, rhsmtx, NULL, 0,
mtxmanager, msglvl, msgFile) ;
MARKTIME(t2) ;
cpus[1] = t2 - t1 ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n CPU : load rhs = %8.3f", t2 - t1) ;
}
/*
----------------------------
forward solve: (L + I) y = b
----------------------------
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n ####### starting forward solve") ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n forward visiting front %d", J) ;
fflush(msgFile) ;
}
FrontMtx_forwardVisit(frontmtx, J, nrhs, NULL, 0, mtxmanager, NULL,
p_mtx, frontIsDone, heads, p_mtx, status,
msglvl, msgFile) ;
}
IP_free(heads[nfront+1]) ;
FREE(heads) ;
MARKTIME(t2) ;
cpus[2] = t2 - t1 ;
/*
-----------------
solve D z_J = y_J
-----------------
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n ####### starting diagonal solve") ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
CVfill(nfront, frontIsDone, 'N') ;
for ( J = Tree_postOTfirst(tree) ;
J != -1 ;
J = Tree_postOTnext(tree, J) ) {
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n diagonal visiting front %d", J) ;
fflush(msgFile) ;
}
FrontMtx_diagonalVisit(frontmtx, J, NULL, 0,
p_mtx, frontIsDone, p_mtx, msglvl, msgFile) ;
frontIsDone[J] = 'D' ;
}
MARKTIME(t2) ;
cpus[3] = t2 - t1 ;
/*
---------------------------------------------------
set up the update head/links for the backward solve
---------------------------------------------------
*/
MARKTIME(t1) ;
heads = FrontMtx_backwardSetup(frontmtx, msglvl, msgFile) ;
CVfill(nfront, status, 'W') ;
CVfill(nfront, frontIsDone, 'N') ;
MARKTIME(t2) ;
cpus[0] += t2 - t1 ;
/*
-----------------------------
backward solve: (I + U) x = z
-----------------------------
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n ####### starting backward solve") ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
for ( J = Tree_preOTfirst(tree) ;
J != -1 ;
J = Tree_preOTnext(tree, J) ) {
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n backward visiting front %d", J) ;
fflush(msgFile) ;
}
FrontMtx_backwardVisit(frontmtx, J, nrhs, NULL, 0, mtxmanager, NULL,
p_mtx, frontIsDone, heads, p_mtx, status,
msglvl, msgFile) ;
}
MARKTIME(t2) ;
cpus[4] = t2 - t1 ;
/*
----------------------------
store the solution in rhsmtx
----------------------------
*/
MARKTIME(t1) ;
FrontMtx_storeSolution(frontmtx, NULL, 0, mtxmanager,
p_mtx, solmtx, msglvl, msgFile) ;
MARKTIME(t2) ;
cpus[1] += t2 - t1 ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n CPU : store solution = %8.3f", t2 - t1) ;
}
/*
------------------------
free the working storage
------------------------
*/
IP_free(heads[nfront+1]) ;
FREE(heads) ;
FREE(p_mtx) ;
CVfree(frontIsDone) ;
CVfree(status) ;
MARKTIME(t2) ;
cpus[5] = t2 - t0 ;
return ; }
/*--------------------------------------------------------------------*/
FrontMtx/src/solveUtil.c 0100644 0002055 0007177 00000077444 06612215447 0016622 0 ustar 00cleve compmath 0000040 0000006 /* solveUtil.c */
#include "../FrontMtx.h"
#include "../../SubMtxList.h"
/*--------------------------------------------------------------------*/
static SubMtx * initBJ ( int type, int J, int nJ, int nrhs,
SubMtxManager *mtxmanager, int msglvl, FILE *msgFile ) ;
static void computeForwardUpdates ( FrontMtx *frontmtx, SubMtx *BJ,
int J, IP *heads[], char frontIsDone[], SubMtx *p_mtx[],
int msglvl, FILE *msgFile ) ;
static void assembleAggregates ( int J, SubMtx *BJ, SubMtxList *aggList,
SubMtxManager *mtxmanager, int msglvl, FILE *msgFile ) ;
static void computeBackwardUpdates ( FrontMtx *frontmtx, SubMtx *ZJ,
int J, IP *heads[], char frontIsDone[], SubMtx *p_mtx[],
int msglvl, FILE *msgFile ) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
load the right hand side for the owned fronts
created -- 98mar19, cca
---------------------------------------------
*/
SubMtx **
FrontMtx_loadRightHandSide (
FrontMtx *frontmtx,
DenseMtx *rhsmtx,
int owners[],
int myid,
SubMtxManager *mtxmanager,
int msglvl,
FILE *msgFile
) {
char localrhs ;
SubMtx *BJ ;
SubMtx **p_agg ;
double *bJ, *rhs ;
int inc1, inc2, irow, jrhs, J, kk, nbytes, ncolJ,
neqns, nfront, nJ, nrhs, nrowInRhs, nrowJ ;
int *rowind, *rowindJ, *rowmap ;
nrowInRhs = rhsmtx->nrow ;
neqns = frontmtx->neqns ;
if ( nrowInRhs != neqns ) {
/*
----------------------------------------------------
the rhs matrix is only part of the total rhs matrix.
(this happens in an MPI environment where the rhs
is partitioned among the processors.)
create a map from the global row indices to the
indices local to this rhs matrix.
----------------------------------------------------
*/
rowmap = IVinit(neqns, -1) ;
rowind = rhsmtx->rowind ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n rhsmtx->rowind") ;
IVfprintf(msgFile, rhsmtx->nrow, rowind) ;
fflush(msgFile) ;
}
for ( irow = 0 ; irow < nrowInRhs ; irow++ ) {
rowmap[rowind[irow]] = irow ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n rowmap") ;
IVfprintf(msgFile, neqns, rowmap) ;
fflush(msgFile) ;
}
localrhs = 'T' ;
} else {
localrhs = 'F' ;
}
/*
--------------------------------------
allocate the vector of SubMtx pointers
--------------------------------------
*/
nfront = FrontMtx_nfront(frontmtx) ;
ALLOCATE(p_agg, struct _SubMtx *, nfront) ;
for ( J = 0 ; J < nfront ; J++ ) {
p_agg[J] = NULL ;
}
DenseMtx_dimensions(rhsmtx, &neqns, &nrhs) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (owners == NULL || owners[J] == myid)
&& (nJ = FrontMtx_frontSize(frontmtx, J)) > 0 ) {
FrontMtx_rowIndices(frontmtx, J, &nrowJ, &rowindJ) ;
if ( localrhs == 'T' ) {
/*
------------------------------------------------------
map the global row indices into the local row indices
------------------------------------------------------
*/
for ( irow = 0 ; irow < nJ ; irow++ ) {
rowindJ[irow] = rowmap[rowindJ[irow]] ;
}
}
/*
------------------------------------------------
initialize bmtx, a SubMtx object to hold b_{J,*}
------------------------------------------------
*/
nbytes = SubMtx_nbytesNeeded(frontmtx->type, SUBMTX_DENSE_COLUMNS,
nJ, nrhs, nJ*nrhs);
BJ = SubMtxManager_newObjectOfSizeNbytes(mtxmanager, nbytes) ;
SubMtx_init(BJ, frontmtx->type, SUBMTX_DENSE_COLUMNS,
J, 0, nJ, nrhs, nJ*nrhs) ;
p_agg[J] = BJ ;
if ( BJ == NULL ) {
fprintf(stderr,
"\n fatal error in load rhs(%d), BJ = NULL", J) ;
exit(-1) ;
}
/*
-----------------------
load BJ with b_{J,*}
-----------------------
*/
rhs = DenseMtx_entries(rhsmtx) ;
SubMtx_denseInfo(BJ, &nrowJ, &ncolJ, &inc1, &inc2, &bJ) ;
if ( FRONTMTX_IS_REAL(frontmtx) ) {
for ( jrhs = 0 ; jrhs < nrhs ; jrhs++ ) {
for ( irow = 0 ; irow < nJ ; irow++ ) {
kk = rowindJ[irow] ;
bJ[irow] = rhs[kk] ;
}
bJ += nJ ;
rhs += nrowInRhs ;
}
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
for ( jrhs = 0 ; jrhs < nrhs ; jrhs++ ) {
for ( irow = 0 ; irow < nJ ; irow++ ) {
kk = rowindJ[irow] ;
bJ[2*irow] = rhs[2*kk] ;
bJ[2*irow+1] = rhs[2*kk+1] ;
}
bJ += 2*nJ ;
rhs += 2*nrowInRhs ;
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n rhs for J = %d, BJ = %p", J, BJ) ;
fflush(msgFile) ;
SubMtx_writeForHumanEye(BJ, msgFile) ;
fflush(msgFile) ;
}
if ( localrhs == 'T' ) {
/*
-----------------------------------------------------------
map the local row indices back into the global row indices
-----------------------------------------------------------
*/
for ( irow = 0 ; irow < nJ ; irow++ ) {
rowindJ[irow] = rowind[rowindJ[irow]] ;
}
}
}
}
if ( localrhs == 'T' ) {
IVfree(rowmap) ;
}
return(p_agg) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
visit front J during the forward solve
created -- 98mar27, cca
--------------------------------------
*/
void
FrontMtx_forwardVisit (
FrontMtx *frontmtx,
int J,
int nrhs,
int *owners,
int myid,
SubMtxManager *mtxmanager,
SubMtxList *aggList,
SubMtx *p_mtx[],
char frontIsDone[],
IP *heads[],
SubMtx *p_agg[],
char status[],
int msglvl,
FILE *msgFile
) {
char aggDone, updDone ;
SubMtx *BJ, *LJJ, *UJJ ;
int nJ ;
if ( (nJ = FrontMtx_frontSize(frontmtx, J)) == 0 ) {
/*
-----------------------------------------------------
front has no eliminated rows or columns, quick return
-----------------------------------------------------
*/
if ( owners == NULL || owners[J] == myid ) {
frontIsDone[J] = 'Y' ;
}
status[J] = 'F' ;
return ;
}
if ( heads[J] != NULL ) {
/*
-------------------------------------
there are internal updates to perform
-------------------------------------
*/
if ( (BJ = p_agg[J]) == NULL ) {
/*
---------------------------
create the aggregate object
---------------------------
*/
BJ = p_agg[J] = initBJ(frontmtx->type, J, nJ, nrhs,
mtxmanager, msglvl, msgFile) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n BJ = %p", BJ) ;
fflush(msgFile) ;
SubMtx_writeForHumanEye(BJ, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
compute any waiting updates
---------------------------
*/
computeForwardUpdates(frontmtx, BJ, J, heads, frontIsDone, p_mtx,
msglvl, msgFile) ;
}
if ( heads[J] == NULL ) {
updDone = 'Y' ;
} else {
updDone = 'N' ;
}
if ( aggList != NULL && owners[J] == myid ) {
/*
-----------------------
assemble any aggregates
-----------------------
*/
aggDone = 'N' ;
if ( (BJ = p_agg[J]) == NULL ) {
fprintf(stderr,
"\n 2. fatal error in forwardVisit(%d), BJ = NULL", J) ;
exit(-1) ;
}
assembleAggregates(J, BJ, aggList, mtxmanager,
msglvl, msgFile) ;
if ( SubMtxList_isCountZero(aggList, J) == 1 ) {
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n aggregate count is zero") ;
fflush(msgFile) ;
}
assembleAggregates(J, BJ, aggList, mtxmanager,
msglvl, msgFile) ;
aggDone = 'Y' ;
}
} else {
aggDone = 'Y' ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n updDone = %c, aggDone = %c",
updDone, aggDone) ;
fflush(msgFile) ;
}
if ( updDone == 'Y' && aggDone == 'Y' ) {
BJ = p_agg[J] ;
if ( owners == NULL || owners[J] == myid ) {
/*
-------------------------------------
owned front, ready for interior solve
-------------------------------------
*/
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
LJJ = FrontMtx_lowerMtx(frontmtx, J, J) ;
if ( LJJ != NULL ) {
SubMtx_solve(LJJ, BJ) ;
}
} else {
UJJ = FrontMtx_upperMtx(frontmtx, J, J) ;
if ( UJJ != NULL ) {
if ( FRONTMTX_IS_SYMMETRIC(frontmtx) ) {
SubMtx_solveT(UJJ, BJ) ;
} else if ( FRONTMTX_IS_HERMITIAN(frontmtx) ) {
SubMtx_solveH(UJJ, BJ) ;
}
}
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n after forward solve") ;
SubMtx_writeForHumanEye(BJ, msgFile) ;
fflush(msgFile) ;
}
/*
------------------------------------------------
move YJ (stored in BJ) into p_mtx[],
signal front as done, and set status to finished
------------------------------------------------
*/
p_agg[J] = NULL ;
p_mtx[J] = BJ ;
frontIsDone[J] = 'Y' ;
} else if ( BJ != NULL ) {
/*
--------------------------------------
unowned front, put into aggregate list
--------------------------------------
*/
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n putting BJ into aggregate list") ;
fflush(msgFile) ;
}
SubMtxList_addObjectToList(aggList, BJ, J) ;
p_agg[J] = NULL ;
}
status[J] = 'F' ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------
purpose -- visit front J during the diagonal solve
created -- 98feb20, cca
--------------------------------------------------
*/
void
FrontMtx_diagonalVisit (
FrontMtx *frontmtx,
int J,
int owners[],
int myid,
SubMtx *p_mtx[],
char frontIsDone[],
SubMtx *p_agg[],
int msglvl,
FILE *msgFile
) {
if ( owners == NULL || owners[J] == myid ) {
SubMtx *BJ, *DJJ ;
if ( (BJ = p_mtx[J]) != NULL ) {
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n BJ = %p", BJ) ;
SubMtx_writeForHumanEye(BJ, msgFile) ;
fflush(msgFile) ;
}
DJJ = FrontMtx_diagMtx(frontmtx, J) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n DJJ = %p", DJJ) ;
SubMtx_writeForHumanEye(DJJ, msgFile) ;
fflush(msgFile) ;
}
SubMtx_solve(DJJ, BJ) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n b_{%d,*} after diagonal solve", J) ;
SubMtx_writeForHumanEye(BJ, msgFile) ;
fflush(msgFile) ;
}
p_mtx[J] = NULL ;
p_agg[J] = BJ ;
}
frontIsDone[J] = 'Y' ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------
visit front J during the backward solve
created -- 98mar27, cca
---------------------------------------
*/
void
FrontMtx_backwardVisit (
FrontMtx *frontmtx,
int J,
int nrhs,
int *owners,
int myid,
SubMtxManager *mtxmanager,
SubMtxList *aggList,
SubMtx *p_mtx[],
char frontIsDone[],
IP *heads[],
SubMtx *p_agg[],
char status[],
int msglvl,
FILE *msgFile
) {
char aggDone, updDone ;
SubMtx *UJJ, *ZJ ;
int nJ ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n inside FrontMtx_backwardVisit(%d), nJ = %d",
J, FrontMtx_frontSize(frontmtx, J)) ;
fflush(msgFile) ;
}
if ( (nJ = FrontMtx_frontSize(frontmtx, J)) == 0 ) {
/*
-----------------------------------------------------
front has no eliminated rows or columns, quick return
-----------------------------------------------------
*/
if ( owners == NULL || owners[J] == myid ) {
frontIsDone[J] = 'Y' ;
}
status[J] = 'F' ;
return ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n heads[%d] = %p", J, heads[J]) ;
fflush(msgFile) ;
}
if ( heads[J] != NULL ) {
/*
-------------------------------------
there are internal updates to perform
-------------------------------------
*/
if ( (ZJ = p_agg[J]) == NULL ) {
/*
---------------------------
create the aggregate object
---------------------------
*/
ZJ = p_agg[J] = initBJ(frontmtx->type, J, nJ, nrhs,
mtxmanager, msglvl, msgFile) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n ZJ = %p", ZJ) ;
SubMtx_writeForHumanEye(ZJ, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
compute any waiting updates
---------------------------
*/
computeBackwardUpdates(frontmtx, ZJ, J, heads, frontIsDone, p_mtx,
msglvl, msgFile) ;
}
if ( heads[J] == NULL ) {
updDone = 'Y' ;
} else {
updDone = 'N' ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n updDone = %c", updDone) ;
fflush(msgFile) ;
}
if ( aggList != NULL && owners[J] == myid ) {
/*
-----------------------
assemble any aggregates
-----------------------
*/
aggDone = 'N' ;
if ( (ZJ = p_agg[J]) == NULL ) {
fprintf(stderr,
"\n 2. fatal error in backwardVisit(%d), ZJ = NULL", J) ;
exit(-1) ;
}
assembleAggregates(J, ZJ, aggList, mtxmanager,
msglvl, msgFile) ;
if ( SubMtxList_isCountZero(aggList, J) == 1 ) {
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n aggregate count is zero") ;
fflush(msgFile) ;
}
assembleAggregates(J, ZJ, aggList, mtxmanager,
msglvl, msgFile) ;
aggDone = 'Y' ;
}
} else {
aggDone = 'Y' ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n aggDone = %c", aggDone) ;
fflush(msgFile) ;
}
if ( updDone == 'Y' && aggDone == 'Y' ) {
ZJ = p_agg[J] ;
if ( owners == NULL || owners[J] == myid ) {
/*
-------------------------------------
owned front, ready for interior solve
-------------------------------------
*/
UJJ = FrontMtx_upperMtx(frontmtx, J, J) ;
if ( UJJ != NULL ) {
SubMtx_solve(UJJ, ZJ) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n after backward solve") ;
SubMtx_writeForHumanEye(ZJ, msgFile) ;
fflush(msgFile) ;
}
/*
------------------------------------------------
move YJ (stored in BJ) into p_mtx[],
signal front as done, and set status to finished
------------------------------------------------
*/
p_agg[J] = NULL ;
p_mtx[J] = ZJ ;
frontIsDone[J] = 'Y' ;
} else if ( ZJ != NULL ) {
/*
--------------------------------------
unowned front, put into aggregate list
--------------------------------------
*/
SubMtxList_addObjectToList(aggList, ZJ, J) ;
p_agg[J] = NULL ;
}
status[J] = 'F' ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n status[%d] = %c", J, status[J]) ;
fflush(msgFile) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
purpose -- move the solution from the individual
SubMtx objects into the global solution SubMtx object
created -- 98feb20
---------------------------------------------------
*/
void
FrontMtx_storeSolution (
FrontMtx *frontmtx,
int owners[],
int myid,
SubMtxManager *manager,
SubMtx *p_mtx[],
DenseMtx *solmtx,
int msglvl,
FILE *msgFile
) {
char localsol ;
SubMtx *xmtxJ ;
double *sol, *xJ ;
int inc1, inc2, irow, jrhs, J, kk,
ncolJ, neqns, nfront, nJ, nrhs, nrowInSol, nrowJ ;
int *colindJ, *colmap, *rowind ;
if ( (nrowInSol = solmtx->nrow) != (neqns = frontmtx->neqns) ) {
/*
--------------------------------------------------------------
the solution matrix is only part of the total solution matrix.
(this happens in an MPI environment where the rhs
is partitioned among the processors.)
create a map from the global row indices to the
indices local to this solution matrix.
--------------------------------------------------------------
*/
colmap = IVinit(neqns, -1) ;
rowind = solmtx->rowind ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n solmtx->rowind") ;
IVfprintf(msgFile, solmtx->nrow, rowind) ;
fflush(msgFile) ;
}
for ( irow = 0 ; irow < nrowInSol ; irow++ ) {
colmap[rowind[irow]] = irow ;
}
localsol = 'T' ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n colmap") ;
IVfprintf(msgFile, neqns, colmap) ;
fflush(msgFile) ;
}
} else {
localsol = 'F' ;
}
DenseMtx_dimensions(solmtx, &neqns, &nrhs) ;
nfront = FrontMtx_nfront(frontmtx) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (owners == NULL || owners[J] == myid)
&& (nJ = FrontMtx_frontSize(frontmtx, J)) > 0 ) {
FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
xmtxJ = p_mtx[J] ;
if ( xmtxJ == NULL ) {
fprintf(stderr,
"\n fatal error in storeSolution(%d)"
"\n thread %d, xmtxJ = NULL", J, myid) ;
exit(-1) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n storing solution for front %d", J) ;
SubMtx_writeForHumanEye(xmtxJ, msgFile) ;
fflush(msgFile) ;
}
if ( localsol == 'T' ) {
/*
------------------------------------------------------
map the global row indices into the local row indices
------------------------------------------------------
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n global row indices") ;
IVfprintf(msgFile, nJ, colindJ) ;
fflush(msgFile) ;
}
for ( irow = 0 ; irow < nJ ; irow++ ) {
colindJ[irow] = colmap[colindJ[irow]] ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n local row indices") ;
IVfprintf(msgFile, nJ, colindJ) ;
fflush(msgFile) ;
}
}
/*
----------------------------------
store x_{J,*} into solution matrix
----------------------------------
*/
sol = DenseMtx_entries(solmtx) ;
SubMtx_denseInfo(xmtxJ, &nrowJ, &ncolJ, &inc1, &inc2, &xJ) ;
if ( FRONTMTX_IS_REAL(frontmtx) ) {
for ( jrhs = 0 ; jrhs < nrhs ; jrhs++ ) {
for ( irow = 0 ; irow < nJ ; irow++ ) {
kk = colindJ[irow] ;
sol[kk] = xJ[irow] ;
}
sol += neqns ;
xJ += nJ ;
}
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
for ( jrhs = 0 ; jrhs < nrhs ; jrhs++ ) {
for ( irow = 0 ; irow < nJ ; irow++ ) {
kk = colindJ[irow] ;
sol[2*kk] = xJ[2*irow] ;
sol[2*kk+1] = xJ[2*irow+1] ;
}
sol += 2*neqns ;
xJ += 2*nJ ;
}
}
/*
fprintf(msgFile, "\n solution for front %d stored", J) ;
*/
SubMtxManager_releaseObject(manager, xmtxJ) ;
if ( localsol == 'T' ) {
/*
-----------------------------------------------------------
map the local row indices back into the global row indices
-----------------------------------------------------------
*/
for ( irow = 0 ; irow < nJ ; irow++ ) {
colindJ[irow] = rowind[colindJ[irow]] ;
}
}
}
}
if ( localsol == 'T' ) {
IVfree(colmap) ;
}
/*
fprintf(msgFile, "\n\n SOLUTION") ;
DenseMtx_writeForHumanEye(solmtx, msgFile) ;
*/
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
purpose -- initialize an aggregate SubMtx object
created -- 98mar27, cca
----------------------------------------------
*/
static SubMtx *
initBJ (
int type,
int J,
int nJ,
int nrhs,
SubMtxManager *mtxmanager,
int msglvl,
FILE *msgFile
) {
SubMtx *BJ ;
double *entries ;
int inc1, inc2, nbytes ;
/*
------------------------------------------
B_J not yet allocated (must not be owned),
create and zero the entries
------------------------------------------
*/
nbytes = SubMtx_nbytesNeeded(type, SUBMTX_DENSE_COLUMNS,
nJ, nrhs, nJ*nrhs);
BJ = SubMtxManager_newObjectOfSizeNbytes(mtxmanager, nbytes) ;
if ( BJ == NULL ) {
fprintf(stderr,
"\n 1. fatal error in forwardVisit(%d), BJ = NULL", J) ;
exit(-1) ;
}
SubMtx_init(BJ, type, SUBMTX_DENSE_COLUMNS, J, 0, nJ, nrhs, nJ*nrhs) ;
SubMtx_denseInfo(BJ, &nJ, &nrhs, &inc1, &inc2, &entries) ;
if ( type == SPOOLES_REAL ) {
DVzero(nJ*nrhs, entries) ;
} else if ( type == SPOOLES_COMPLEX ) {
DVzero(2*nJ*nrhs, entries) ;
}
return(BJ) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
purpose -- compute any updates to BJ
created -- 98mar26, cca
------------------------------------
*/
static void
computeForwardUpdates (
FrontMtx *frontmtx,
SubMtx *BJ,
int J,
IP *heads[],
char frontIsDone[],
SubMtx *p_mtx[],
int msglvl,
FILE *msgFile
) {
SubMtx *LJI, *UIJ, *YI ;
int I ;
IP *ip, *nextip ;
/*
-------------------------------
loop over the remaining updates
-------------------------------
*/
for ( ip = heads[J], heads[J] = NULL ;
ip != NULL ;
ip = nextip ) {
I = ip->val ; nextip = ip->next ;
if ( msglvl > 3 ) {
fprintf(msgFile,
"\n\n frontIsDone[%d] = %c, p_mtx[%d] = %p",
I, frontIsDone[I], I, p_mtx[I]) ;
fflush(msgFile) ;
}
if ( frontIsDone[I] == 'Y' ) {
if ( (YI = p_mtx[I]) != NULL ) {
/*
--------------------------------
Y_I exists and has been computed
--------------------------------
*/
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n before solve: YI = %p", YI) ;
SubMtx_writeForHumanEye(YI, msgFile) ;
fflush(msgFile) ;
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
if ( (LJI = FrontMtx_lowerMtx(frontmtx, J, I)) != NULL ) {
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n LJI = %p", LJI) ;
SubMtx_writeForHumanEye(LJI, msgFile) ;
fflush(msgFile) ;
}
SubMtx_solveupd(BJ, LJI, YI) ;
}
} else {
if ( (UIJ = FrontMtx_upperMtx(frontmtx, I, J)) != NULL ) {
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n UIJ = %p", UIJ) ;
SubMtx_writeForHumanEye(UIJ, msgFile) ;
fflush(msgFile) ;
}
if ( FRONTMTX_IS_SYMMETRIC(frontmtx) ) {
SubMtx_solveupdT(BJ, UIJ, YI) ;
} else if ( FRONTMTX_IS_HERMITIAN(frontmtx) ) {
SubMtx_solveupdH(BJ, UIJ, YI) ;
}
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n after update: BJ = %p", BJ) ;
SubMtx_writeForHumanEye(BJ, msgFile) ;
fflush(msgFile) ;
}
}
} else {
/*
------------------------
Y_I is not yet available
------------------------
*/
ip->next = heads[J] ;
heads[J] = ip ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- assemble any aggregates in the aggregate list
created -- 98mar26, cca
--------------------------------------------------------
*/
static void
assembleAggregates (
int J,
SubMtx *BJ,
SubMtxList *aggList,
SubMtxManager *mtxmanager,
int msglvl,
FILE *msgFile
) {
SubMtx *BJhat, *BJhead ;
double *entBJ, *entBJhat ;
int inc1, inc1hat, inc2, inc2hat, ncol, ncolhat, nrow, nrowhat ;
if ( BJ == NULL || aggList == NULL ) {
fprintf(stderr,
"\n fatal error in assembleAggregates()"
"\n BJ = %p, aggList = %p", BJ, aggList) ;
exit(-1) ;
}
if ( SubMtxList_isListNonempty(aggList, BJ->rowid) ) {
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n aggregate list is not-empty") ;
fflush(msgFile) ;
}
SubMtx_denseInfo(BJ, &nrow, &ncol, &inc1, &inc2, &entBJ) ;
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n\n BJ(%d,%d) : nrow %d, ncol %d, inc1 %d, inc2 %d, ent %p",
BJ->rowid, BJ->colid, nrow, ncol, inc1, inc2, entBJ) ;
fflush(msgFile) ;
}
BJhead = SubMtxList_getList(aggList, J) ;
for ( BJhat = BJhead ; BJhat != NULL ; BJhat = BJhat->next ) {
if ( BJhat == NULL ) {
fprintf(stderr,
"\n 3. fatal error in forwardVisit(%d)"
"\n BJhat = NULL", J) ;
exit(-1) ;
}
SubMtx_denseInfo(BJhat, &nrowhat, &ncolhat, &inc1hat, &inc2hat,
&entBJhat) ;
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n BJhat(%d,%d) : nrow %d, ncol %d, inc1 %d, inc2 %d, ent %p",
BJhat->rowid, BJhat->colid,
nrowhat, ncolhat, inc1hat, inc2hat, entBJhat) ;
fflush(msgFile) ;
}
if ( nrow != nrowhat || ncol != ncolhat
|| inc1 != inc1hat || inc2 != inc2hat || entBJhat == NULL ) {
fprintf(stderr, "\n fatal error") ;
exit(-1) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n BJ") ;
SubMtx_writeForHumanEye(BJ, msgFile) ;
fprintf(msgFile, "\n\n BJhat") ;
SubMtx_writeForHumanEye(BJhat, msgFile) ;
fflush(msgFile) ;
}
if ( SUBMTX_IS_REAL(BJhat) ) {
DVadd(nrow*ncol, entBJ, entBJhat) ;
} else if ( SUBMTX_IS_COMPLEX(BJhat) ) {
DVadd(2*nrow*ncol, entBJ, entBJhat) ;
}
}
SubMtxManager_releaseListOfObjects(mtxmanager, BJhead) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n BJ after assembly") ;
SubMtx_writeForHumanEye(BJ, msgFile) ;
fflush(msgFile) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
purpose -- compute any updates to ZJ
created -- 98mar26, cca
------------------------------------
*/
static void
computeBackwardUpdates (
FrontMtx *frontmtx,
SubMtx *ZJ,
int J,
IP *heads[],
char frontIsDone[],
SubMtx *p_mtx[],
int msglvl,
FILE *msgFile
) {
SubMtx *UJK, *XK ;
int K ;
IP *ip, *nextip ;
/*
-------------------------------
loop over the remaining updates
-------------------------------
*/
for ( ip = heads[J], heads[J] = NULL ;
ip != NULL ;
ip = nextip ) {
K = ip->val ; nextip = ip->next ;
if ( msglvl > 3 ) {
fprintf(msgFile,
"\n\n frontIsDone[%d] = %c", K, frontIsDone[K]) ;
fflush(msgFile) ;
}
if ( frontIsDone[K] == 'Y' ) {
if ( (XK = p_mtx[K]) != NULL ) {
/*
--------------------------------
X_K exists and has been computed
--------------------------------
*/
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n before solve: XK = %p", XK) ;
SubMtx_writeForHumanEye(XK, msgFile) ;
fflush(msgFile) ;
}
if ( (UJK = FrontMtx_upperMtx(frontmtx, J, K)) != NULL ) {
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n UJK = %p", UJK) ;
SubMtx_writeForHumanEye(UJK, msgFile) ;
fflush(msgFile) ;
}
SubMtx_solveupd(ZJ, UJK, XK) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n after update: ZJ = %p", ZJ) ;
SubMtx_writeForHumanEye(ZJ, msgFile) ;
fflush(msgFile) ;
}
}
} else {
/*
------------------------
X_K is not yet available
------------------------
*/
ip->next = heads[J] ;
heads[J] = ip ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
purpose -- load the dequeue with the roots of the
active subtree used for a backward solve
created -- 98mar27, cca
---------------------------------------------------
*/
void
FrontMtx_loadActiveRoots (
FrontMtx *frontmtx,
char status[],
char activeFlag,
Ideq *dequeue
) {
int J ;
int *sib ;
sib = frontmtx->tree->sib ;
for ( J = frontmtx->tree->root ; J != -1 ; J = sib[J] ) {
if ( status[J] == activeFlag ) {
Ideq_insertAtTail(dequeue, J) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
purpose -- to set up the link data structures for a forward solve
return value -- pointer to IP *heads[nfront+2], which contains
the beginning of a list of IP objects that store the remaining
updates to the fronts.
note, heads[nfront] is the first IP object in the free list.
heads[nfront+1] is the base address of the allocated IP objects.
created -- 98feb20, cca
--------------------------------------------------------------------
*/
IP **
FrontMtx_forwardSetup (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) {
int ii, J, K, nadj, nblock, nfront ;
int *adj ;
IP *ip ;
IP **heads ;
/*
--------------------------------------------------
set up the update head/links for the forward solve
--------------------------------------------------
*/
nblock = FrontMtx_nLowerBlocks(frontmtx) ;
nfront = FrontMtx_nfront(frontmtx) ;
ALLOCATE(heads, struct _IP *, nfront + 2) ;
for ( J = 0 ; J <= nfront + 1 ; J++ ) {
heads[J] = NULL ;
}
heads[nfront] = heads[nfront+1] = IP_init(nblock, 1) ;
for ( J = 0 ; J < nfront ; J++ ) {
FrontMtx_lowerAdjFronts(frontmtx, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
if ( (K = adj[ii]) > J ) {
ip = heads[nfront] ; heads[nfront] = ip->next ;
ip->val = J ; ip->next = heads[K] ; heads[K] = ip ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n linking L(%d,%d) to L(%d,%d)",
K, J, K, (ip->next == NULL) ? -1 : ip->next->val) ;
fflush(msgFile) ;
}
}
}
}
return(heads) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
purpose -- set up the linked lists for the backward solve
created -- 98feb20, cca
---------------------------------------------------------
*/
IP **
FrontMtx_backwardSetup (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) {
IP *ip ;
IP **heads ;
int ii, J, K, nadj, nblock, nfront ;
int *adj ;
nfront = FrontMtx_nfront(frontmtx) ;
nblock = FrontMtx_nLowerBlocks(frontmtx) ;
ALLOCATE(heads, struct _IP *, nfront + 2) ;
for ( J = 0 ; J <= nfront + 1 ; J++ ) {
heads[J] = NULL ;
}
heads[nfront] = heads[nfront+1] = IP_init(nblock, 1) ;
for ( J = 0 ; J < nfront ; J++ ) {
FrontMtx_upperAdjFronts(frontmtx, J, &nadj, &adj) ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
if ( (K = adj[ii]) > J ) {
if ( heads[nfront] == NULL ) {
fprintf(stderr,
"\n WHOA, heads[nfront] = %p", heads[nfront]) ;
exit(-1) ;
}
ip = heads[nfront] ; heads[nfront] = ip->next ;
ip->val = K ; ip->next = heads[J] ; heads[J] = ip ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n linking U(%d,%d) to U(%d,%d)",
J, K, J, (ip->next == NULL) ? -1 : ip->next->val) ;
fflush(msgFile) ;
}
}
}
}
return(heads) ; }
/*--------------------------------------------------------------------*/
= p_mtx[I]) != NULL ) {
/*
--------------------------------
Y_I exists and has been computed
--------------------------------
*/
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n FrontMtx/src/split.c 0100644 0002055 0007177 00000046312 06647173547 0015771 0 ustar 00cleve compmath 0000040 0000006 /* split.c */
#include "../FrontMtx.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose -- for each U_{J,bnd{J}} matrix, remove from hash table,
split into their U_{J,K} submatrices and insert
into the hash table.
created -- 98may04, cca
----------------------------------------------------------------
*/
void
FrontMtx_splitUpperMatrices (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) {
SubMtx *mtxUJ, *mtxUJJ, *mtxUJK ;
SubMtxManager *manager ;
double *entUJ, *entUJK ;
int count, first, ii, inc1, inc2, jcol, jj, J, K, nbytes,
ncolJ, ncolUJ, ncolUJK, nentUJ, nentUJK, neqns, nfront,
nJ, nrowUJ, nrowUJK, offset, v ;
int *colindJ, *colindUJ, *colindUJK, *colmap, *indicesUJ,
*indicesUJK, *locmap, *rowindUJ, *rowindUJK, *sizesUJ,
*sizesUJK ;
I2Ohash *upperhash ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_splitUpperMatrices(%p,%d,%p)"
"\n bad input\n", frontmtx, msglvl, msgFile) ;
exit(-1) ;
}
nfront = FrontMtx_nfront(frontmtx) ;
neqns = FrontMtx_neqns(frontmtx) ;
upperhash = frontmtx->upperhash ;
manager = frontmtx->manager ;
/*
-----------------------------------
construct the column and local maps
-----------------------------------
*/
colmap = IVinit(neqns, -1) ;
locmap = IVinit(neqns, -1) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (nJ = FrontMtx_frontSize(frontmtx, J)) > 0 ) {
FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
if ( ncolJ > 0 && colindJ != NULL ) {
for ( ii = 0 ; ii < nJ ; ii++ ) {
v = colindJ[ii] ;
colmap[v] = J ;
locmap[v] = ii ;
}
}
}
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n colmap[]") ;
IVfprintf(msgFile, neqns, colmap) ;
fprintf(msgFile, "\n\n locmap[]") ;
IVfprintf(msgFile, neqns, locmap) ;
fflush(msgFile) ;
}
/*
---------------------------------------------
move the U_{J,J} matrices into the hash table
---------------------------------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtxUJJ = FrontMtx_upperMtx(frontmtx, J, J)) != NULL ) {
I2Ohash_insert(frontmtx->upperhash, J, J, mtxUJJ) ;
}
}
/*
------------------------------------------------------------
now split the U_{J,bnd{J}} matrices into U_{J,K} matrices.
note: columns of U_{J,bnd{J}} are assumed to be in ascending
order with respect to the column ordering of the matrix.
------------------------------------------------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
mtxUJ = FrontMtx_upperMtx(frontmtx, J, nfront) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n ### J = %d, mtxUJ = %p", J, mtxUJ) ;
fflush(msgFile) ;
}
if ( mtxUJ != NULL ) {
if ( msglvl > 2 ) {
SubMtx_writeForHumanEye(mtxUJ, msgFile) ;
fflush(msgFile) ;
}
SubMtx_columnIndices(mtxUJ, &ncolUJ, &colindUJ) ;
SubMtx_rowIndices(mtxUJ, &nrowUJ, &rowindUJ) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n column indices for J") ;
IVfprintf(msgFile, ncolUJ, colindUJ) ;
fprintf(msgFile, "\n row indices for UJ") ;
IVfprintf(msgFile, nrowUJ, rowindUJ) ;
fflush(msgFile) ;
}
if ( (K = colmap[colindUJ[0]]) == colmap[colindUJ[ncolUJ-1]] ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n front %d supports only %d", J, K) ;
fflush(msgFile) ;
}
/*
-------------------------------------------------
U_{J,bnd{J}} is one submatrix, bnd{J} \subseteq K
set row and column indices and change column id
-------------------------------------------------
*/
IVramp(nrowUJ, rowindUJ, 0, 1) ;
for ( ii = 0 ; ii < ncolUJ ; ii++ ) {
colindUJ[ii] = locmap[colindUJ[ii]] ;
}
SubMtx_setFields(mtxUJ, mtxUJ->type, mtxUJ->mode, J, K,
mtxUJ->nrow, mtxUJ->ncol, mtxUJ->nent) ;
/*
mtxUJ->colid = K ;
*/
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n ## inserting U(%d,%d) ", J, K) ;
SubMtx_writeForHumanEye(mtxUJ, msgFile) ;
fflush(msgFile) ;
}
I2Ohash_insert(upperhash, J, K, (void *) mtxUJ) ;
} else {
/*
-----------------------------------
split U_{J,bnd{J}} into submatrices
-----------------------------------
*/
nJ = FrontMtx_frontSize(frontmtx, J) ;
if ( SUBMTX_IS_DENSE_COLUMNS(mtxUJ) ) {
SubMtx_denseInfo(mtxUJ,
&nrowUJ, &ncolUJ, &inc1, &inc2, &entUJ) ;
} else if ( SUBMTX_IS_SPARSE_COLUMNS(mtxUJ) ) {
SubMtx_sparseColumnsInfo(mtxUJ, &ncolUJ, &nentUJ,
&sizesUJ, &indicesUJ, &entUJ) ;
offset = 0 ;
count = sizesUJ[0] ;
}
first = 0 ;
K = colmap[colindUJ[0]] ;
for ( jcol = 1 ; jcol <= ncolUJ ; jcol++ ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n jcol = %d", jcol) ;
if ( jcol < ncolUJ ) {
fprintf(msgFile, ", colmap[%d] = %d",
colindUJ[jcol], colmap[colindUJ[jcol]]);
}
fflush(msgFile) ;
}
if ( jcol == ncolUJ || K != colmap[colindUJ[jcol]] ) {
ncolUJK = jcol - first ;
if ( SUBMTX_IS_DENSE_COLUMNS(mtxUJ) ) {
nentUJK = nJ*ncolUJK ;
} else if ( SUBMTX_IS_SPARSE_COLUMNS(mtxUJ) ) {
if ( count == 0 ) {
goto no_entries ;
}
nentUJK = count ;
}
nbytes = SubMtx_nbytesNeeded(mtxUJ->type, mtxUJ->mode,
nJ, ncolUJK, nentUJK) ;
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n ncolUJK %d, nentUJK %d, nbytes %d",
ncolUJK, nentUJK, nbytes) ;
fflush(msgFile) ;
}
mtxUJK = SubMtxManager_newObjectOfSizeNbytes(manager,
nbytes) ;
SubMtx_init(mtxUJK, mtxUJ->type, mtxUJ->mode, J, K,
nJ, ncolUJK, nentUJK) ;
if ( SUBMTX_IS_DENSE_COLUMNS(mtxUJ) ) {
SubMtx_denseInfo(mtxUJK,
&nrowUJK, &ncolUJK, &inc1, &inc2, &entUJK) ;
if ( FRONTMTX_IS_REAL(frontmtx) ) {
DVcopy(nentUJK, entUJK, entUJ + first*nJ) ;
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
DVcopy(2*nentUJK, entUJK, entUJ + 2*first*nJ) ;
}
} else if ( SUBMTX_IS_SPARSE_COLUMNS(mtxUJ) ) {
SubMtx_sparseColumnsInfo(mtxUJK, &ncolUJK, &nentUJK,
&sizesUJK, &indicesUJK, &entUJK) ;
IVcopy(ncolUJK, sizesUJK, sizesUJ + first) ;
IVcopy(nentUJK, indicesUJK, indicesUJ + offset) ;
if ( FRONTMTX_IS_REAL(frontmtx) ) {
DVcopy(nentUJK, entUJK, entUJ + offset) ;
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
DVcopy(2*nentUJK, entUJK, entUJ + 2*offset) ;
}
count = 0 ;
offset += nentUJK ;
}
/*
-------------------------------------
initialize the row and column indices
-------------------------------------
*/
if ( msglvl > 2 ) {
fprintf(msgFile, "\n setting row and column indices");
fflush(msgFile) ;
}
SubMtx_rowIndices(mtxUJK, &nrowUJK, &rowindUJK) ;
IVramp(nJ, rowindUJK, 0, 1) ;
SubMtx_columnIndices(mtxUJK, &ncolUJK, &colindUJK) ;
for ( ii = 0, jj = first ; ii < ncolUJK ; ii++, jj++ ) {
colindUJK[ii] = locmap[colindUJ[jj]] ;
}
/*
----------------------------------
insert U_{J,K} into the hash table
----------------------------------
*/
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n\n ## inserting U(%d,%d) ", J, K) ;
SubMtx_writeForHumanEye(mtxUJK, msgFile) ;
fflush(msgFile) ;
}
I2Ohash_insert(upperhash, J, K, (void *) mtxUJK) ;
/*
-----------------------------------
we jump to here if there were no
entries to be stored in the matrix.
-----------------------------------
*/
no_entries :
/*
----------------------------------------------------
reset first and K to new first location and front id
----------------------------------------------------
*/
first = jcol ;
if ( jcol < ncolUJ ) {
K = colmap[colindUJ[jcol]] ;
}
}
if ( jcol < ncolUJ && SUBMTX_IS_SPARSE_COLUMNS(mtxUJ) ) {
count += sizesUJ[jcol] ;
}
}
/*
--------------------------------------------
give U_{J,bnd{J}} back to the matrix manager
--------------------------------------------
*/
SubMtxManager_releaseObject(manager, mtxUJ) ;
}
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(colmap) ;
IVfree(locmap) ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose -- for each L_{bnd{J},J} matrix, remove from hash table,
split into their L_{K,J} submatrices and insert
into the hash table.
created -- 98may04, cca
----------------------------------------------------------------
*/
void
FrontMtx_splitLowerMatrices (
FrontMtx *frontmtx,
int msglvl,
FILE *msgFile
) {
SubMtx *mtxLJ, *mtxLJJ, *mtxLKJ ;
SubMtxManager *manager ;
double *entLJ, *entLKJ ;
int count, first, ii, inc1, inc2, irow, jj, J, K, nbytes,
ncolLJ, ncolLKJ, nentLJ, nentLKJ, neqns, nfront, nJ,
nrowJ, nrowLJ, nrowLKJ, offset, v ;
int *colindLJ, *colindLKJ, *rowmap, *indicesLJ, *indicesLKJ,
*locmap, *rowindJ, *rowindLJ, *rowindLKJ, *sizesLJ,
*sizesLKJ ;
I2Ohash *lowerhash ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr,
"\n fatal error in FrontMtx_splitLowerMatrices(%p,%d,%p)"
"\n bad input\n", frontmtx, msglvl, msgFile) ;
exit(-1) ;
}
nfront = FrontMtx_nfront(frontmtx) ;
neqns = FrontMtx_neqns(frontmtx) ;
lowerhash = frontmtx->lowerhash ;
manager = frontmtx->manager ;
/*
--------------------------------
construct the row and local maps
--------------------------------
*/
rowmap = IVinit(neqns, -1) ;
locmap = IVinit(neqns, -1) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (nJ = FrontMtx_frontSize(frontmtx, J)) > 0 ) {
FrontMtx_rowIndices(frontmtx, J, &nrowJ, &rowindJ) ;
if ( nrowJ > 0 && rowindJ != NULL ) {
for ( ii = 0 ; ii < nJ ; ii++ ) {
v = rowindJ[ii] ;
rowmap[v] = J ;
locmap[v] = ii ;
}
}
}
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n rowmap[]") ;
IVfprintf(msgFile, neqns, rowmap) ;
fprintf(msgFile, "\n\n locmap[]") ;
IVfprintf(msgFile, neqns, locmap) ;
fflush(msgFile) ;
}
/*
---------------------------------------------
move the L_{J,J} matrices into the hash table
---------------------------------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
if ( (mtxLJJ = FrontMtx_lowerMtx(frontmtx, J, J)) != NULL ) {
I2Ohash_insert(frontmtx->lowerhash, J, J, mtxLJJ) ;
}
}
/*
------------------------------------------------------------
now split the L_{bnd{J},J} matrices into L_{K,J} matrices.
note: columns of L_{bnd{J},J} are assumed to be in ascending
order with respect to the column ordering of the matrix.
------------------------------------------------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
mtxLJ = FrontMtx_lowerMtx(frontmtx, nfront, J) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n ### J = %d, mtxLJ = %p", J, mtxLJ) ;
fflush(msgFile) ;
}
if ( mtxLJ != NULL ) {
if ( msglvl > 2 ) {
SubMtx_writeForHumanEye(mtxLJ, msgFile) ;
fflush(msgFile) ;
}
SubMtx_columnIndices(mtxLJ, &ncolLJ, &colindLJ) ;
SubMtx_rowIndices(mtxLJ, &nrowLJ, &rowindLJ) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n column indices for J") ;
IVfprintf(msgFile, ncolLJ, colindLJ) ;
fprintf(msgFile, "\n row indices for LJ") ;
IVfprintf(msgFile, nrowLJ, rowindLJ) ;
fflush(msgFile) ;
}
if ( (K = rowmap[rowindLJ[0]]) == rowmap[rowindLJ[nrowLJ-1]] ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n front %d supports only %d", J, K) ;
fflush(msgFile) ;
}
/*
-------------------------------------------------
L_{bnd{J},J} is one submatrix, bnd{J} \subseteq K
set row and column indices and change column id
-------------------------------------------------
*/
IVramp(ncolLJ, colindLJ, 0, 1) ;
for ( ii = 0 ; ii < nrowLJ ; ii++ ) {
rowindLJ[ii] = locmap[rowindLJ[ii]] ;
}
/*
mtxLJ->rowid = K ;
*/
SubMtx_setFields(mtxLJ, mtxLJ->type, mtxLJ->mode, K, J,
mtxLJ->nrow, mtxLJ->ncol, mtxLJ->nent) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n ## inserting L(%d,%d) ", K, J) ;
SubMtx_writeForHumanEye(mtxLJ, msgFile) ;
fflush(msgFile) ;
}
I2Ohash_insert(lowerhash, K, J, (void *) mtxLJ) ;
} else {
/*
-----------------------------------
split L_{bnd{J},J} into submatrices
-----------------------------------
*/
nJ = FrontMtx_frontSize(frontmtx, J) ;
if ( SUBMTX_IS_DENSE_ROWS(mtxLJ) ) {
SubMtx_denseInfo(mtxLJ,
&nrowLJ, &ncolLJ, &inc1, &inc2, &entLJ) ;
} else if ( SUBMTX_IS_SPARSE_ROWS(mtxLJ) ) {
SubMtx_sparseRowsInfo(mtxLJ, &nrowLJ, &nentLJ,
&sizesLJ, &indicesLJ, &entLJ) ;
offset = 0 ;
count = sizesLJ[0] ;
}
first = 0 ;
K = rowmap[rowindLJ[0]] ;
for ( irow = 1 ; irow <= nrowLJ ; irow++ ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n irow = %d", irow) ;
if ( irow < nrowLJ ) {
fprintf(msgFile, ", rowmap[%d] = %d",
rowindLJ[irow], rowmap[rowindLJ[irow]]);
}
fflush(msgFile) ;
}
if ( irow == nrowLJ || K != rowmap[rowindLJ[irow]] ) {
nrowLKJ = irow - first ;
if ( SUBMTX_IS_DENSE_ROWS(mtxLJ) ) {
nentLKJ = nJ*nrowLKJ ;
} else if ( SUBMTX_IS_SPARSE_ROWS(mtxLJ) ) {
if ( count == 0 ) {
goto no_entries ;
}
nentLKJ = count ;
}
nbytes = SubMtx_nbytesNeeded(mtxLJ->type, mtxLJ->mode,
nrowLKJ, nJ, nentLKJ) ;
mtxLKJ = SubMtxManager_newObjectOfSizeNbytes(manager,
nbytes) ;
SubMtx_init(mtxLKJ, mtxLJ->type, mtxLJ->mode, K, J,
nrowLKJ, nJ, nentLKJ) ;
if ( SUBMTX_IS_DENSE_ROWS(mtxLJ) ) {
SubMtx_denseInfo(mtxLKJ,
&nrowLKJ, &ncolLKJ, &inc1, &inc2, &entLKJ) ;
if ( FRONTMTX_IS_REAL(frontmtx) ) {
DVcopy(nentLKJ, entLKJ, entLJ + first*nJ) ;
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
DVcopy(2*nentLKJ, entLKJ, entLJ + 2*first*nJ) ;
}
} else if ( SUBMTX_IS_SPARSE_ROWS(mtxLJ) ) {
SubMtx_sparseRowsInfo(mtxLKJ, &nrowLKJ, &nentLKJ,
&sizesLKJ, &indicesLKJ, &entLKJ) ;
IVcopy(nrowLKJ, sizesLKJ, sizesLJ + first) ;
IVcopy(nentLKJ, indicesLKJ, indicesLJ + offset) ;
if ( FRONTMTX_IS_REAL(frontmtx) ) {
DVcopy(nentLKJ, entLKJ, entLJ + offset) ;
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
DVcopy(2*nentLKJ, entLKJ, entLJ + 2*offset) ;
}
count = 0 ;
offset += nentLKJ ;
}
/*
-------------------------------------
initialize the row and column indices
-------------------------------------
*/
SubMtx_rowIndices(mtxLKJ, &nrowLKJ, &rowindLKJ) ;
for ( ii = 0, jj = first ; ii < nrowLKJ ; ii++, jj++ ) {
rowindLKJ[ii] = locmap[rowindLJ[jj]] ;
}
SubMtx_columnIndices(mtxLKJ, &ncolLKJ, &colindLKJ) ;
IVramp(ncolLKJ, colindLKJ, 0, 1) ;
/*
----------------------------------
insert L_{K,J} into the hash table
----------------------------------
*/
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n\n ## inserting L(%d,%d) ", K, J) ;
SubMtx_writeForHumanEye(mtxLKJ, msgFile) ;
fflush(msgFile) ;
}
I2Ohash_insert(lowerhash, K, J, (void *) mtxLKJ) ;
/*
-----------------------------------
we jump to here if there were no
entries to be stored in the matrix.
-----------------------------------
*/
no_entries :
/*
----------------------------------------------------
reset first and K to new first location and front id
----------------------------------------------------
*/
first = irow ;
if ( irow < nrowLJ ) {
K = rowmap[rowindLJ[irow]] ;
}
}
if ( irow < nrowLJ && SUBMTX_IS_SPARSE_ROWS(mtxLJ) ) {
count += sizesLJ[irow] ;
}
}
/*
--------------------------------------------
give L_{bnd{J},J} back to the matrix manager
--------------------------------------------
*/
SubMtxManager_releaseObject(manager, mtxLJ) ;
}
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(rowmap) ;
IVfree(locmap) ;
return ; }
/*--------------------------------------------------------------------*/
if ( jcol < ncolUJ ) {
K = colmap[colindUJ[jcol]] ;
}
}
if ( jcol < ncolUJ && SUBMTX_IS_SPARSE_COLUMNS(mtxUJ) ) {
count += sizesUJ[jcol] ;
}
}
/*
--------------------------------------------
FrontMtx/src/storeFront.c 0100644 0002055 0007177 00000042532 06620617464 0016773 0 ustar 00cleve compmath 0000040 0000006 /* storeFront.c */
#include "../FrontMtx.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose -- to store the factor indicies and entries from front J
pivotsizesIV -- used for symmetric or hermitian and pivoting
droptol -- used for drop tolerance factorization,
an entry is stored if its magnitude > droptol
created -- 98may04, cca
----------------------------------------------------------------
*/
void
FrontMtx_storeFront (
FrontMtx *frontmtx,
Chv *frontJ,
IV *pivotsizesIV,
double droptol,
int msglvl,
FILE *msgFile
) {
SubMtx *mtx ;
double *entries ;
int inc1, inc2, ipivot, irow, jcol, J, m, nbytes,
ncol, nD, nent, nfront, nL, npivot, nrow, nU ;
int *colind, *colindJ, *firstlocs, *indices, *pivots,
*pivotsizes, *rowind, *rowindJ, *sizes ;
SubMtxManager *manager ;
/*
-------------------------------------
extract information from front matrix
-------------------------------------
*/
nfront = frontmtx->nfront ;
manager = frontmtx->manager ;
if ( ( FRONTMTX_IS_SYMMETRIC(frontmtx)
|| FRONTMTX_IS_HERMITIAN(frontmtx) )
&& FRONTMTX_IS_PIVOTING(frontmtx) ) {
IV_sizeAndEntries(pivotsizesIV, &npivot, &pivotsizes) ;
} else {
npivot = 0, pivotsizes = NULL ;
}
/*
--------------------------------
extract information from chevron
--------------------------------
*/
J = frontJ->id ;
Chv_dimensions(frontJ, &nD, &nL, &nU) ;
Chv_columnIndices(frontJ, &ncol, &colindJ) ;
Chv_rowIndices(frontJ, &nrow, &rowindJ) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n inside FrontMtx_storeFront, J = %d", J) ;
fflush(msgFile) ;
}
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
if ( frontmtx->lock != NULL ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n locking lock") ;
fflush(msgFile) ;
}
Lock_lock(frontmtx->lock) ;
frontmtx->nlocks++ ;
}
/*
--------------------
store the front size
--------------------
*/
FrontMtx_setFrontSize(frontmtx, J, nD) ;
/*
------------------------
store the column indices
------------------------
*/
if ( msglvl > 2 ) {
fprintf(msgFile, "\n setting column indices, J = %d", J) ;
fflush(msgFile) ;
}
IVL_setList(frontmtx->coladjIVL, J, ncol, colindJ) ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
---------------------
store the row indices
---------------------
*/
if ( msglvl > 2 ) {
fprintf(msgFile, "\n setting row indices, J = %d", J) ;
fflush(msgFile) ;
}
IVL_setList(frontmtx->rowadjIVL, J, nrow, rowindJ) ;
}
if ( frontmtx->lock != NULL ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n unlocking lock") ;
fflush(msgFile) ;
}
Lock_unlock(frontmtx->lock) ;
}
}
if ( nD == 0 ) {
return ;
}
/*
------------------------
store the D_{J,J} matrix
------------------------
*/
if ( pivotsizes != NULL ) {
/*
---------------------------------------------------
symmetric and pivoting, store block diagonal matrix
---------------------------------------------------
*/
nent = Chv_countEntries(frontJ, npivot, pivotsizes, CHV_DIAGONAL) ;
nbytes = SubMtx_nbytesNeeded(frontJ->type, SUBMTX_BLOCK_DIAGONAL_SYM,
nD, nD, nent) ;
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
if ( FRONTMTX_IS_SYMMETRIC(frontmtx) ) {
SubMtx_init(mtx, frontJ->type, SUBMTX_BLOCK_DIAGONAL_SYM,
J, J, nD, nD, nent) ;
} else if ( FRONTMTX_IS_HERMITIAN(frontmtx) ) {
SubMtx_init(mtx, frontJ->type, SUBMTX_BLOCK_DIAGONAL_HERM,
J, J, nD, nD, nent) ;
}
SubMtx_blockDiagonalInfo(mtx, &nrow, &nent, &pivots, &entries) ;
IVzero(nD, pivots) ;
IVcopy(npivot, pivots, pivotsizes) ;
Chv_copyEntriesToVector(frontJ, npivot, pivotsizes, nent, entries,
CHV_DIAGONAL, CHV_BY_ROWS) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n block diagonal matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
frontmtx->nentD += nent ;
} else {
/*
---------------
diagonal matrix
---------------
*/
mtx = frontmtx->p_mtxDJJ[J] ;
if ( mtx == NULL ) {
nbytes = SubMtx_nbytesNeeded(frontJ->type, SUBMTX_DIAGONAL,
nD, nD, nD) ;
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, frontJ->type, SUBMTX_DIAGONAL, J, J, nD, nD, nD);
}
SubMtx_diagonalInfo(mtx, &nent, &entries) ;
Chv_copyEntriesToVector(frontJ, npivot, pivotsizes, nent, entries,
CHV_DIAGONAL, CHV_BY_ROWS) ;
frontmtx->nentD += nD ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n entries in SubMtx") ;
DVfprintf(msgFile, nent, entries) ;
fprintf(msgFile, "\n\n block diagonal matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
frontmtx->p_mtxDJJ[J] = mtx ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(ncol, colind, colindJ) ;
SubMtx_rowIndices(mtx, &nrow, &rowind) ;
IVcopy(nrow, rowind, rowindJ) ;
/*
------------------------------
store the upper U_{J,J} matrix
------------------------------
*/
if ( FRONTMTX_IS_DENSE_FRONTS(frontmtx) ) {
/*
-----------
dense front
-----------
*/
nent = Chv_countEntries(frontJ, npivot, pivotsizes,
CHV_STRICT_UPPER_11) ;
if ( nent > 0 ) {
mtx = frontmtx->p_mtxUJJ[J] ;
if ( mtx == NULL ) {
nbytes = SubMtx_nbytesNeeded(frontJ->type,
SUBMTX_DENSE_SUBCOLUMNS, nD, nD,nent);
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, frontJ->type, SUBMTX_DENSE_SUBCOLUMNS,
J, J, nD, nD, nent) ;
}
SubMtx_denseSubcolumnsInfo(mtx, &ncol, &nent,
&firstlocs, &sizes, &entries) ;
if ( pivotsizes != NULL ) {
for ( jcol = ipivot = 0 ; jcol < nD ; ipivot++ ) {
m = pivotsizes[ipivot] ;
if ( m == 1 ) {
firstlocs[jcol] = 0 ;
sizes[jcol] = jcol ;
jcol++ ;
} else if ( m == 2 ) {
firstlocs[jcol] = firstlocs[jcol+1] = 0 ;
sizes[jcol] = sizes[jcol+1] = jcol ;
jcol += 2 ;
}
}
} else {
for ( jcol = 0 ; jcol < nD ; jcol++ ) {
firstlocs[jcol] = 0 ;
sizes[jcol] = jcol ;
}
}
Chv_copyEntriesToVector(frontJ, npivot, pivotsizes, nent, entries,
CHV_STRICT_UPPER_11, CHV_BY_COLUMNS) ;
frontmtx->p_mtxUJJ[J] = mtx ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(ncol, colind, colindJ) ;
SubMtx_rowIndices(mtx, &nrow, &rowind) ;
IVcopy(nrow, rowind, rowindJ) ;
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
frontmtx->nentU += nent ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n UJJ matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
} else {
/*
------------
sparse front
------------
*/
nent = Chv_countBigEntries(frontJ, npivot, pivotsizes,
CHV_STRICT_UPPER_11, droptol) ;
if ( nent > 0 ) {
nbytes = SubMtx_nbytesNeeded(frontJ->type, SUBMTX_SPARSE_COLUMNS,
nD, nD, nent) ;
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n U_{%d,%d}, nD %d, nent %d, nbytes %d",
J, J, nD, nent, nbytes) ;
fflush(msgFile) ;
}
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, frontJ->type, SUBMTX_SPARSE_COLUMNS,
J, J, nD, nD, nent) ;
SubMtx_sparseColumnsInfo(mtx, &ncol, &nent,
&sizes, &indices, &entries) ;
Chv_copyBigEntriesToVector(frontJ, npivot, pivotsizes, sizes,
indices, entries, CHV_STRICT_UPPER_11,
CHV_BY_COLUMNS, droptol) ;
frontmtx->p_mtxUJJ[J] = mtx ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(ncol, colind, colindJ) ;
SubMtx_rowIndices(mtx, &nrow, &rowind) ;
IVcopy(nrow, rowind, rowindJ) ;
frontmtx->nentU += nent ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n UJJ matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
}
/*
-----------------------------------
store the upper U_{J,bnd{J}} matrix
-----------------------------------
*/
if ( FRONTMTX_IS_DENSE_FRONTS(frontmtx) ) {
/*
-----------
dense front
-----------
*/
nent = Chv_countEntries(frontJ, npivot, pivotsizes, CHV_UPPER_12) ;
if ( nent > 0 ) {
mtx = frontmtx->p_mtxUJN[J] ;
if ( mtx == NULL ) {
nbytes = SubMtx_nbytesNeeded(frontJ->type,
SUBMTX_DENSE_COLUMNS, nD, nU, nent) ;
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, frontJ->type, SUBMTX_DENSE_COLUMNS,
J, nfront, nD, nU, nent) ;
}
SubMtx_denseInfo(mtx, &nrow, &ncol, &inc1, &inc2, &entries) ;
Chv_copyEntriesToVector(frontJ, npivot, pivotsizes, nent, entries,
CHV_UPPER_12, CHV_BY_COLUMNS) ;
frontmtx->p_mtxUJN[J] = mtx ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(ncol, colind, colindJ + nD) ;
SubMtx_rowIndices(mtx, &nrow, &rowind) ;
IVcopy(nrow, rowind, rowindJ) ;
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
frontmtx->nentU += nent ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n UJJN matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
} else {
/*
------------
sparse front
------------
*/
nent = Chv_countBigEntries(frontJ, npivot, pivotsizes,
CHV_UPPER_12, droptol) ;
if ( nent > 0 ) {
nbytes = SubMtx_nbytesNeeded(frontJ->type, SUBMTX_SPARSE_COLUMNS,
nD, nU, nent) ;
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n U_{%d,%d}, nD %d, nU %d, nent %d, nbytes %d",
J, nfront, nD, nU, nent, nbytes) ;
fflush(msgFile) ;
}
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, frontJ->type, SUBMTX_SPARSE_COLUMNS,
J, nfront, nD, nU, nent) ;
SubMtx_sparseColumnsInfo(mtx,
&nrow, &nent, &sizes, &indices, &entries) ;
Chv_copyBigEntriesToVector(frontJ, npivot, pivotsizes, sizes,
indices, entries, CHV_UPPER_12,
CHV_BY_COLUMNS, droptol) ;
frontmtx->p_mtxUJN[J] = mtx ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(ncol, colind, colindJ + nD) ;
SubMtx_rowIndices(mtx, &nrow, &rowind) ;
IVcopy(nrow, rowind, rowindJ) ;
frontmtx->nentU += nent ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n UJJN matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
}
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
/*
------------------------------
store the lower L_{J,J} matrix
------------------------------
*/
if ( FRONTMTX_IS_DENSE_FRONTS(frontmtx) ) {
/*
-----------
dense front
-----------
*/
nent = Chv_countEntries(frontJ, npivot, pivotsizes,
CHV_STRICT_LOWER_11) ;
if ( nent > 0 ) {
mtx = frontmtx->p_mtxLJJ[J] ;
if ( mtx == NULL ) {
nbytes = SubMtx_nbytesNeeded(frontJ->type,
SUBMTX_DENSE_SUBROWS, nD, nD,nent);
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, frontJ->type, SUBMTX_DENSE_SUBROWS,
J, J, nD, nD, nent) ;
}
SubMtx_denseSubrowsInfo(mtx, &nrow, &nent,
&firstlocs, &sizes, &entries) ;
for ( irow = 0 ; irow < nD ; irow++ ) {
firstlocs[irow] = 0 ;
sizes[irow] = irow ;
}
Chv_copyEntriesToVector(frontJ, npivot, pivotsizes, nent,
entries, CHV_STRICT_LOWER_11, CHV_BY_ROWS) ;
frontmtx->p_mtxLJJ[J] = mtx ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(ncol, colind, colindJ) ;
SubMtx_rowIndices(mtx, &nrow, &rowind) ;
IVcopy(nrow, rowind, rowindJ) ;
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
frontmtx->nentL += nent ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n LJJ matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
} else {
/*
------------
sparse front
------------
*/
nent = Chv_countBigEntries(frontJ, npivot, pivotsizes,
CHV_STRICT_LOWER_11, droptol);
if ( nent > 0 ) {
nbytes = SubMtx_nbytesNeeded(frontJ->type, SUBMTX_SPARSE_ROWS,
nD, nD, nent) ;
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n L_{%d,%d}, nD %d, nent %d, nbytes %d",
J, J, nD, nent, nbytes) ;
fflush(msgFile) ;
}
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, frontJ->type, SUBMTX_SPARSE_ROWS,
J, J, nD, nD, nent) ;
SubMtx_sparseRowsInfo(mtx,
&nrow, &nent, &sizes, &indices, &entries);
Chv_copyBigEntriesToVector(frontJ, npivot, pivotsizes, sizes,
indices, entries, CHV_STRICT_LOWER_11,
CHV_BY_ROWS, droptol) ;
frontmtx->p_mtxLJJ[J] = mtx ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(ncol, colind, colindJ) ;
SubMtx_rowIndices(mtx, &nrow, &rowind) ;
IVcopy(nrow, rowind, rowindJ) ;
frontmtx->nentL += nent ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n LJJ matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
}
/*
-----------------------------------
store the lower L_{bnd{J},J} matrix
-----------------------------------
*/
if ( FRONTMTX_IS_DENSE_FRONTS(frontmtx) ) {
/*
-----------
dense front
-----------
*/
nent = Chv_countEntries(frontJ, npivot, pivotsizes, CHV_LOWER_21);
if ( nent > 0 ) {
mtx = frontmtx->p_mtxLNJ[J] ;
if ( mtx == NULL ) {
nbytes = SubMtx_nbytesNeeded(frontJ->type,
SUBMTX_DENSE_ROWS, nL, nD, nent) ;
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, frontJ->type, SUBMTX_DENSE_ROWS,
nfront, J, nL, nD, nent) ;
}
SubMtx_denseInfo(mtx, &nrow, &ncol, &inc1, &inc2, &entries) ;
Chv_copyEntriesToVector(frontJ, npivot, pivotsizes, nent,
entries, CHV_LOWER_21, CHV_BY_ROWS) ;
frontmtx->p_mtxLNJ[J] = mtx ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(ncol, colind, colindJ) ;
SubMtx_rowIndices(mtx, &nrow, &rowind) ;
IVcopy(nrow, rowind, rowindJ + nD) ;
if ( FRONTMTX_IS_PIVOTING(frontmtx) ) {
frontmtx->nentL += nent ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n LNJ matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
} else {
/*
------------
sparse front
------------
*/
nent = Chv_countBigEntries(frontJ, npivot, pivotsizes,
CHV_LOWER_21, droptol) ;
if ( nent > 0 ) {
nbytes = SubMtx_nbytesNeeded(frontJ->type, SUBMTX_SPARSE_ROWS,
nL, nD, nent) ;
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n L_{%d,%d}, nL %d, nD %d, nent %d, nbytes %d",
nfront, J, nL, nD, nent, nbytes) ;
fflush(msgFile) ;
}
mtx = SubMtxManager_newObjectOfSizeNbytes(manager, nbytes) ;
SubMtx_init(mtx, frontJ->type, SUBMTX_SPARSE_ROWS,
nfront, J, nL, nD, nent) ;
SubMtx_sparseRowsInfo(mtx,
&nrow, &nent, &sizes, &indices, &entries) ;
Chv_copyBigEntriesToVector(frontJ, npivot, pivotsizes, sizes,
indices, entries, CHV_LOWER_21,
CHV_BY_ROWS, droptol) ;
frontmtx->p_mtxLNJ[J] = mtx ;
SubMtx_columnIndices(mtx, &ncol, &colind) ;
IVcopy(ncol, colind, colindJ) ;
SubMtx_rowIndices(mtx, &nrow, &rowind) ;
IVcopy(nrow, rowind, rowindJ + nD) ;
frontmtx->nentL += nent ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n LNJ matrix") ;
SubMtx_writeForHumanEye(mtx, msgFile) ;
fflush(msgFile) ;
}
}
}
}
return ; }
/*--------------------------------------------------------------------*/
wind) ;
IVcopy(nrow, rowind, rowindJ) ;
frontmtx->nentU += nent ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n UJJ matrix") ;
SubMtxFrontMtx/src/update.c 0100644 0002055 0007177 00000007067 06571267172 0016116 0 ustar 00cleve compmath 0000040 0000006 /* update.c */
#include "../FrontMtx.h"
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
accumulate updates to front J, store them in the Chv object
created -- 98may04, cca
------------------------------------------------------------
*/
void
FrontMtx_update (
FrontMtx *frontmtx,
Chv *frontJ,
IP *heads[],
char status[],
DV *tempDV,
int msglvl,
FILE *msgFile
) {
SubMtx *mtxD, *mtxL, *mtxU ;
int I, J, nfront ;
IP *first, *ip, *last, *nextip ;
/*
--------------------------------------
loop over the fronts that may update J
--------------------------------------
*/
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n inside FrontMtx_update(%d)", frontJ->id) ;
fflush(stdout) ;
}
J = frontJ->id ;
nfront = frontmtx->nfront ;
for ( ip = heads[J], heads[J] = first = last = NULL ;
ip != NULL ;
ip = nextip ) {
nextip = ip->next ;
I = ip->val ;
if ( status == NULL || status[I] == 'F' ) {
mtxD = FrontMtx_diagMtx(frontmtx, I) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n update from I %d, mtxD = %p", I, mtxD) ;
fflush(stdout) ;
}
if ( mtxD != NULL ) {
/*
-------------------------------------------------
front I did have some rows and columns eliminated
-------------------------------------------------
*/
mtxU = FrontMtx_upperMtx(frontmtx, I, nfront) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n mtxU = %p", mtxU) ;
fflush(stdout) ;
}
if ( mtxU != NULL ) {
/*
------------------------------
the U_{I,bnd{I}} matrix exists
------------------------------
*/
if ( FRONTMTX_IS_SYMMETRIC(frontmtx) ) {
Chv_updateS(frontJ, mtxD, mtxU, tempDV) ;
} else if ( FRONTMTX_IS_HERMITIAN(frontmtx) ) {
Chv_updateH(frontJ, mtxD, mtxU, tempDV) ;
/*
fprintf(msgFile, "\n after update from front %d", mtxD->rowid) ;
Chv_writeForHumanEye(frontJ, msgFile) ;
*/
} else if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
mtxL = FrontMtx_lowerMtx(frontmtx, nfront, I) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n mtxL = %p", mtxL) ;
fflush(stdout) ;
}
if ( mtxL != NULL ) {
/*
------------------------------
the L_{bnd{I},I} matrix exists
------------------------------
*/
Chv_updateN(frontJ, mtxL, mtxD, mtxU, tempDV) ;
}
}
}
}
if ( last == NULL ) {
last = ip ;
}
ip->next = first ;
first = ip ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n update from I %d is finished", I) ;
fflush(stdout) ;
}
} else {
ip->next = heads[J] ;
heads[J] = ip ;
}
}
/*
if ( frontJ->id == frontmtx->nfront - 1 ) {
fprintf(msgFile, "\n\n last front after updates made") ;
Chv_writeForHumanEye(frontJ, msgFile) ;
fflush(msgFile) ;
}
*/
if ( last != NULL ) {
/*
------------------------------------
link the IP objects to the free list
------------------------------------
*/
last->next = heads[nfront] ;
heads[nfront] = first ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n leaving FrontMtx_update(%d)", frontJ->id) ;
fflush(stdout) ;
}
return ; }
/*--------------------------------------------------------------------*/
FrontMtx/src/util.c 0100644 0002055 0007177 00000042777 06612130407 0015602 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../FrontMtx.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------
purpose -- produce a map from each column
to the front that contains it
created -- 98may04, cca
-----------------------------------------
*/
IV *
FrontMtx_colmapIV (
FrontMtx *frontmtx
) {
int ii, J, ncolJ, neqns, nfront, nJ ;
int *colindJ, *colmap ;
IV *colmapIV ;
/*
-----------------------------------------
get the map from columns to owning fronts
-----------------------------------------
*/
neqns = FrontMtx_neqns(frontmtx) ;
nfront = FrontMtx_nfront(frontmtx) ;
colmapIV = IV_new() ;
IV_init(colmapIV, neqns, NULL) ;
colmap = IV_entries(colmapIV) ;
IVfill(neqns, colmap, -1) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (nJ = FrontMtx_frontSize(frontmtx, J)) > 0 ) {
FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
if ( ncolJ > 0 && colindJ != NULL ) {
for ( ii = 0 ; ii < nJ ; ii++ ) {
colmap[colindJ[ii]] = J ;
}
}
}
}
return(colmapIV) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
purpose -- produce a map from each row to the front that contains it
created -- 98may04, cca
--------------------------------------------------------------------
*/
IV *
FrontMtx_rowmapIV (
FrontMtx *frontmtx
) {
int ii, J, nrowJ, neqns, nfront, nJ ;
int *rowindJ, *rowmap ;
IV *rowmapIV ;
/*
--------------------------------------
get the map from rows to owning fronts
--------------------------------------
*/
neqns = FrontMtx_neqns(frontmtx) ;
nfront = FrontMtx_nfront(frontmtx) ;
rowmapIV = IV_new() ;
IV_init(rowmapIV, neqns, NULL) ;
rowmap = IV_entries(rowmapIV) ;
IVfill(neqns, rowmap, -1) ;
for ( J = 0 ; J < nfront ; J++ ) {
if ( (nJ = FrontMtx_frontSize(frontmtx, J)) > 0 ) {
FrontMtx_rowIndices(frontmtx, J, &nrowJ, &rowindJ) ;
if ( nrowJ > 0 && rowindJ != NULL ) {
for ( ii = 0 ; ii < nJ ; ii++ ) {
rowmap[rowindJ[ii]] = J ;
}
}
}
}
return(rowmapIV) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------
compute the inertia of a symmetric matrix
fill *pnnegative with the number of negative eigenvalues of A
fill *pnzero with the number of zero eigenvalues of A
fill *pnpositive with the number of positive eigenvalues of A
created -- 98may04, cca
-------------------------------------------------------------
*/
void
FrontMtx_inertia (
FrontMtx *frontmtx,
int *pnnegative,
int *pnzero,
int *pnpositive
) {
SubMtx *mtx ;
double arm, areal, bimag, breal, creal, mid, val ;
double *entries ;
int ii, ipivot, irow, J, nent, nfront, nJ,
nnegative, npositive, nzero ;
int *pivotsizes ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL
|| pnnegative == NULL || pnzero == NULL || pnpositive == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_inertia(%p,%p,%p,%p)"
"\n bad input\n",
frontmtx, pnnegative, pnzero, pnpositive) ;
fflush(stdout) ;
}
if ( FRONTMTX_IS_REAL(frontmtx) && ! FRONTMTX_IS_SYMMETRIC(frontmtx) ) {
fprintf(stderr, "\n fatal error in FrontMtx_inertia(%p,%p,%p,%p)"
"\n matrix is real and not symmetric \n",
frontmtx, pnnegative, pnzero, pnpositive) ;
fflush(stdout) ;
} else if ( FRONTMTX_IS_COMPLEX(frontmtx)
&& ! FRONTMTX_IS_HERMITIAN(frontmtx) ) {
fprintf(stderr, "\n fatal error in FrontMtx_inertia(%p,%p,%p,%p)"
"\n matrix is complex and not hermitian \n",
frontmtx, pnnegative, pnzero, pnpositive) ;
fflush(stdout) ;
}
nfront = frontmtx->nfront ;
nnegative = nzero = npositive = 0 ;
for ( J = 0 ; J < nfront ; J++ ) {
mtx = FrontMtx_diagMtx(frontmtx, J) ;
if ( mtx != NULL ) {
if ( ! FRONTMTX_IS_PIVOTING(frontmtx) ) {
/*
-----------
no pivoting
-----------
*/
SubMtx_diagonalInfo(mtx, &nJ, &entries) ;
if ( FRONTMTX_IS_REAL(frontmtx) ) {
for ( ii = 0 ; ii < nJ ; ii++ ) {
if ( entries[ii] < 0.0 ) {
nnegative++ ;
} else if ( entries[ii] > 0.0 ) {
npositive++ ;
} else {
nzero++ ;
}
}
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
for ( ii = 0 ; ii < nJ ; ii++ ) {
if ( entries[2*ii] < 0.0 ) {
nnegative++ ;
} else if ( entries[2*ii] > 0.0 ) {
npositive++ ;
} else {
nzero++ ;
}
}
}
} else {
/*
--------
pivoting
--------
*/
SubMtx_blockDiagonalInfo(mtx, &nJ, &nent,
&pivotsizes, &entries) ;
if ( FRONTMTX_IS_REAL(frontmtx) ) {
for ( irow = ipivot = ii = 0 ; irow < nJ ; ipivot++ ) {
if ( pivotsizes[ipivot] == 1 ) {
val = entries[ii] ;
if ( val < 0.0 ) {
nnegative++ ;
} else if ( val > 0.0 ) {
npositive++ ;
} else {
nzero++ ;
}
irow++ ; ii++ ;
} else {
areal = entries[ii] ;
breal = entries[ii+1] ;
creal = entries[ii+2] ;
mid = 0.5*(areal + creal) ;
arm = sqrt(0.25*(areal - creal)*(areal - creal)
+ breal*breal) ;
val = mid + arm ;
if ( val < 0.0 ) {
nnegative++ ;
} else if ( val > 0.0 ) {
npositive++ ;
} else {
nzero++ ;
}
val = mid - arm ;
if ( val < 0.0 ) {
nnegative++ ;
} else if ( val > 0.0 ) {
npositive++ ;
} else {
nzero++ ;
}
irow += 2 ; ii += 3 ;
}
}
} else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
for ( irow = ipivot = ii = 0 ; irow < nJ ; ipivot++ ) {
if ( pivotsizes[ipivot] == 1 ) {
val = entries[2*ii] ;
if ( val < 0.0 ) {
nnegative++ ;
} else if ( val > 0.0 ) {
npositive++ ;
} else {
nzero++ ;
}
irow++ ; ii++ ;
} else {
areal = entries[2*ii] ;
breal = entries[2*ii+2] ;
bimag = entries[2*ii+3] ;
creal = entries[2*ii+4] ;
mid = 0.5*(areal + creal) ;
arm = sqrt(0.25*(areal - creal)*(areal - creal)
+ breal*breal + bimag*bimag) ;
val = mid + arm ;
if ( val < 0.0 ) {
nnegative++ ;
} else if ( val > 0.0 ) {
npositive++ ;
} else {
nzero++ ;
}
val = mid - arm ;
if ( val < 0.0 ) {
nnegative++ ;
} else if ( val > 0.0 ) {
npositive++ ;
} else {
nzero++ ;
}
irow += 2 ; ii += 3 ;
}
}
}
}
}
}
*pnnegative = nnegative ;
*pnzero = nzero ;
*pnpositive = npositive ;
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
purpose -- create and return an IV object that contains
all the row ids owned by process myid.
created -- 98jun13, cca
-------------------------------------------------------
*/
IV *
FrontMtx_ownedRowsIV (
FrontMtx *frontmtx,
int myid,
IV *ownersIV,
int msglvl,
FILE *msgFile
) {
int J, neqns, nfront, nJ, nowned, nrowJ, offset ;
int *ownedRows, *owners, *rowindJ ;
IV *ownedRowsIV ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_ownedRowsIV(%p,%d,%p)"
"\n bad input\n", frontmtx, myid, ownersIV) ;
exit(-1) ;
}
nfront = frontmtx->nfront ;
neqns = frontmtx->neqns ;
ownedRowsIV = IV_new() ;
if ( ownersIV == NULL ) {
IV_init(ownedRowsIV, neqns, NULL) ;
IV_ramp(ownedRowsIV, 0, 1) ;
} else {
owners = IV_entries(ownersIV) ;
for ( J = 0, nowned = 0 ; J < nfront ; J++ ) {
if ( owners[J] == myid ) {
nJ = FrontMtx_frontSize(frontmtx, J) ;
nowned += nJ ;
}
}
if ( nowned > 0 ) {
IV_init(ownedRowsIV, nowned, NULL) ;
ownedRows = IV_entries(ownedRowsIV) ;
for ( J = 0, offset = 0 ; J < nfront ; J++ ) {
if ( owners[J] == myid ) {
nJ = FrontMtx_frontSize(frontmtx, J) ;
if ( nJ > 0 ) {
FrontMtx_rowIndices(frontmtx, J, &nrowJ, &rowindJ) ;
IVcopy(nJ, ownedRows + offset, rowindJ) ;
offset += nJ ;
}
}
}
}
}
return(ownedRowsIV) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
purpose -- create and return an IV object that contains
all the column ids owned by process myid.
created -- 98jun13, cca
-------------------------------------------------------
*/
IV *
FrontMtx_ownedColumnsIV (
FrontMtx *frontmtx,
int myid,
IV *ownersIV,
int msglvl,
FILE *msgFile
) {
int J, neqns, nfront, nJ, nowned, ncolJ, offset ;
int *ownedColumns, *owners, *colindJ ;
IV *ownedColumnsIV ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_ownedColumnsIV(%p,%d,%p)"
"\n bad input\n", frontmtx, myid, ownersIV) ;
exit(-1) ;
}
nfront = frontmtx->nfront ;
neqns = frontmtx->neqns ;
ownedColumnsIV = IV_new() ;
if ( ownersIV == NULL ) {
IV_init(ownedColumnsIV, neqns, NULL) ;
IV_ramp(ownedColumnsIV, 0, 1) ;
} else {
owners = IV_entries(ownersIV) ;
for ( J = 0, nowned = 0 ; J < nfront ; J++ ) {
if ( owners[J] == myid ) {
nJ = FrontMtx_frontSize(frontmtx, J) ;
nowned += nJ ;
}
}
if ( nowned > 0 ) {
IV_init(ownedColumnsIV, nowned, NULL) ;
ownedColumns = IV_entries(ownedColumnsIV) ;
for ( J = 0, offset = 0 ; J < nfront ; J++ ) {
if ( owners[J] == myid ) {
nJ = FrontMtx_frontSize(frontmtx, J) ;
if ( nJ > 0 ) {
FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
IVcopy(nJ, ownedColumns + offset, colindJ) ;
offset += nJ ;
}
}
}
}
}
return(ownedColumnsIV) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose -- to create and return an IVL object that holds the
submatrix nonzero pattern for the upper triangular factor.
NOTE: this method supercedes calling IVL_mapEntries() on
the column adjacency structure. that gave problems when
pivoting forced some fronts to have no eliminated columns.
in some cases, solve aggregates were expected when none
were forthcoming.
created -- 98aug20, cca
----------------------------------------------------------------
*/
IVL *
FrontMtx_makeUpperBlockIVL (
FrontMtx *frontmtx,
IV *colmapIV
) {
int count, ii, J, K, ncol, nfront, nJ ;
int *colmap, *colind, *list, *mark ;
IVL *upperblockIVL ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || colmapIV == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_makeUpperBlockIVL()"
"\n bad input\n") ;
exit(-1) ;
}
nfront = FrontMtx_nfront(frontmtx) ;
colmap = IV_entries(colmapIV) ;
/*
-----------------------------
set up the working storage
and initialize the IVL object
-----------------------------
*/
mark = IVinit(nfront, -1) ;
list = IVinit(nfront, -1) ;
upperblockIVL = IVL_new() ;
IVL_init1(upperblockIVL, IVL_CHUNKED, nfront) ;
/*
-------------------
fill the IVL object
-------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
if ( (nJ = FrontMtx_frontSize(frontmtx, J)) > 0 ) {
FrontMtx_columnIndices(frontmtx, J, &ncol, &colind) ;
if ( ncol > 0 ) {
mark[J] = J ;
count = 0 ;
list[count++] = J ;
for ( ii = nJ ; ii < ncol ; ii++ ) {
K = colmap[colind[ii]] ;
if ( mark[K] != J ) {
mark[K] = J ;
list[count++] = K ;
}
}
IVL_setList(upperblockIVL, J, count, list) ;
}
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(mark) ;
IVfree(list) ;
return(upperblockIVL) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
purpose -- to create and return an IVL object that holds the
submatrix nonzero pattern for the lower triangular factor.
NOTE: this method supercedes calling IVL_mapEntries() on
the row adjacency structure. that gave problems when
pivoting forced some fronts to have no eliminated columns.
in some cases, solve aggregates were expected when none
were forthcoming.
created -- 98aug20, cca
----------------------------------------------------------------
*/
IVL *
FrontMtx_makeLowerBlockIVL (
FrontMtx *frontmtx,
IV *rowmapIV
) {
int count, ii, J, K, nrow, nfront, nJ ;
int *rowmap, *rowind, *list, *mark ;
IVL *lowerblockIVL ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL || rowmapIV == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_makeLowerBlockIVL()"
"\n bad input\n") ;
exit(-1) ;
}
nfront = FrontMtx_nfront(frontmtx) ;
rowmap = IV_entries(rowmapIV) ;
/*
-----------------------------
set up the working storage
and initialize the IVL object
-----------------------------
*/
mark = IVinit(nfront, -1) ;
list = IVinit(nfront, -1) ;
lowerblockIVL = IVL_new() ;
IVL_init1(lowerblockIVL, IVL_CHUNKED, nfront) ;
/*
-------------------
fill the IVL object
-------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
if ( (nJ = FrontMtx_frontSize(frontmtx, J)) > 0 ) {
FrontMtx_rowIndices(frontmtx, J, &nrow, &rowind) ;
if ( nrow > 0 ) {
mark[J] = J ;
count = 0 ;
list[count++] = J ;
for ( ii = nJ ; ii < nrow ; ii++ ) {
K = rowmap[rowind[ii]] ;
if ( mark[K] != J ) {
mark[K] = J ;
list[count++] = K ;
}
}
IVL_setList(lowerblockIVL, J, count, list) ;
}
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(mark) ;
IVfree(list) ;
return(lowerblockIVL) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
purpose -- to compute and return the number of floating point
operations to perform a solve with a single right hand side.
created -- 98sep26, cca
---------------------------------------------------------------
*/
int
FrontMtx_nSolveOps (
FrontMtx *frontmtx
) {
int nsolveops ;
/*
---------------
check the input
---------------
*/
if ( frontmtx == NULL ) {
fprintf(stderr, "\n fatal error in FrontMtx_nSolveOps()"
"\n frontmtx is NULL\n") ;
exit(-1) ;
}
switch ( frontmtx->type ) {
case SPOOLES_REAL :
switch ( frontmtx->symmetryflag ) {
case SPOOLES_SYMMETRIC :
nsolveops = 4*frontmtx->nentU + frontmtx->nentD ;
break ;
case SPOOLES_NONSYMMETRIC :
nsolveops = 2*frontmtx->nentL + frontmtx->nentD
+ 2*frontmtx->nentU ;
break ;
default :
fprintf(stderr, "\n fatal error in FrontMtx_nSolveOps()"
"\n real type, invalid symmetryflag %d\n",
frontmtx->symmetryflag) ;
exit(-1) ;
break ;
}
break ;
case SPOOLES_COMPLEX :
switch ( frontmtx->symmetryflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
nsolveops = 16*frontmtx->nentU + 8*frontmtx->nentD ;
break ;
case SPOOLES_NONSYMMETRIC :
nsolveops = 8*frontmtx->nentL + 8*frontmtx->nentD
+ 8*frontmtx->nentU ;
break ;
default :
fprintf(stderr, "\n fatal error in FrontMtx_nSolveOps()"
"\n complex type, invalid symmetryflag %d\n",
frontmtx->symmetryflag) ;
exit(-1) ;
break ;
}
break ;
default :
fprintf(stderr, "\n fatal error in FrontMtx_nSolveOps()"
"\n invalid type %d\n", frontmtx->type) ;
exit(-1) ;
break ;
}
return(nsolveops) ; }
/*--------------------------------------------------------------------*/
FrontMtx/drivers/do_QRgrid 0100755 0002055 0007177 00000000517 06573541264 0017147 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set msglvl = 1
set msgFile = res
set msgFile = stdout
set n1 = 7
set n2 = 7
set n3 = 7
set seed = 10101
set nrhs = 4
set type = 1
foreach n ( 7 )
set n1 = $n
set n2 = $n
set n3 = 1
set n3 = $n
echo $n1 x $n2 x $n3 grid
testQRgrid \
$msglvl $msgFile $n1 $n2 $n3 $seed $nrhs $type
end
FrontMtx/drivers/do_factor 0100755 0002055 0007177 00000002164 06633034612 0017224 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set msglvl = 1
set msgFile = res3D.64
set msgFile = /local1/ARPA/junk/res.grid
set msgFile = res.grid
set msgFile = res
set msgFile = stdout
set mtxFile = ../../../matrices/R2D100/orig.inpmtxb
set etreeFile = ../../../matrices/R2D100/nd.etreef
set mtxFile = ../../../matrices/R3D13824/orig.inpmtxb
set etreeFile = ../../../matrices/R3D13824/nd.0.100000.etreef
# set mtxFile = ../../../matrices/R10KV/orig.inpmtxb
# set etreeFile = ../../../matrices/R10KV/best0.etreef
# set mtxFile = ../../../matrices/R2D100/orig.inpmtxb
# set etreeFile = ../../../matrices/R2D100/nd.etreef
# set mtxFile = /local1/ARPA/matrices/SFTC$n/SFTC1.inpmtxb
# set etreeFile = /local1/ARPA/matrices/SFTC$n/best0.etreef
set seed = 10101
set symmetryflag = 0
set sparsityflag = 0
set pivotingflag = 0
set tau = 100
set droptol = 1.e-50
set lookahead = 0
set nrhs = 4
testFactor $msglvl $msgFile $mtxFile $etreeFile \
$seed $symmetryflag $sparsityflag $pivotingflag\
$tau $droptol $lookahead $nrhs
FrontMtx/drivers/do_grid 0100755 0002055 0007177 00000002551 06620603667 0016703 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set msglvl = 1
set msgFile = res3D.64
set msgFile = res
set msgFile = /local1/ARPA/junk/res.grid
set msgFile = res.grid
set msgFile = stdout
set n1 = 7
set n2 = 7
set n3 = 1
set maxzeros = 1000
set maxzeros = 500
set maxzeros = 250
set maxzeros = 750
set maxzeros = 0
set maxsize = 1000
set maxsize = 64
set seed = 10101
set type = 1
set symmetryflag = 0
set sparsityflag = 0
set pivotingflag = 0
set tau = 5
set droptol = 1.e-50
set lookahead = 0
set nrhs = 4
foreach nrhs ( 1 )
# foreach nrhs ( 1 2 3 4 5 6 8 16 )
echo ' nrhs ' $nrhs
# foreach n1 ( 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 )
# foreach maxzeros ( 400 800 1600 )
# foreach maxsize ( 16 32 48 64 80 )
# set msgFile = res3D.$maxsize.$maxzeros
echo $maxzeros $maxsize
# foreach n1 ( 5 7 9 11 13 15 17 19 21 23 25 27 29 31 )
# set n2 = $n1
# set n3 = $n1
# foreach sparsityflag ( 0 1 )
# foreach pivotingflag ( 0 1 )
# foreach symmetryflag ( 0 2 )
echo $n1 $n2 $n3
testGrid $msglvl $msgFile $n1 $n2 $n3 $maxzeros $maxsize \
$seed $type $symmetryflag $sparsityflag $pivotingflag\
$tau $droptol $lookahead $nrhs
# end
# end
# end
# end
# end
# end
end
FrontMtx/drivers/makefile 0100644 0002055 0007177 00000001221 06653142451 0017032 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = testGrid testQRgrid testFactor
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
testQRgrid : testQRgrid.o ../../spooles.a
${PURIFY} ${CC} $(PURIFY_GCC_VERSION) $@.o \
-o $@ ${LIBS} ${THREAD_LIBS}
testGrid : testGrid.o ../../spooles.a
${PURIFY} ${CC} $(PURIFY_GCC_VERSION) $@.o \
-o $@ ${LIBS} ${THREAD_LIBS}
testFactor : testFactor.o ../../spooles.a
${PURIFY} ${CC} $(PURIFY_GCC_VERSION) $@.o \
-o $@ ${LIBS} ${THREAD_LIBS}
FrontMtx/drivers/testFactor.c 0100644 0002055 0007177 00000044326 06632345026 0017631 0 ustar 00cleve compmath 0000040 0000006 /* testFactor.c */
#include "../FrontMtx.h"
#include "../../Drand.h"
#include "../../SymbFac.h"
#include "../../timings.h"
#include "../../misc.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-----------------------------------------------------
test the factor method for a grid matrix
(1) read in an InpMtx object
(2) read in an ETree object
(3) create a solution matrix object
(4) multiply the solution with the matrix
to get a right hand side matrix object
(5) factor the matrix
(6) solve the system
created -- 98sep05, cca
-----------------------------------------------------
*/
{
char *etreeFileName, *mtxFileName ;
Chv *chv, *rootchv ;
ChvManager *chvmanager ;
DenseMtx *mtxB, *mtxX, *mtxZ ;
double one[2] = { 1.0, 0.0 } ;
FrontMtx *frontmtx ;
InpMtx *mtxA ;
SubMtxManager *mtxmanager ;
double cputotal, droptol, factorops ;
double cpus[9] ;
Drand drand ;
double nops, tau, t1, t2 ;
ETree *frontETree ;
FILE *msgFile ;
int error, loc, lockflag, msglvl, neqns, nrhs, nzf,
pivotingflag, rc, seed, sparsityflag, symmetryflag,
type ;
int stats[6] ;
IV *newToOldIV, *oldToNewIV ;
IVL *symbfacIVL ;
if ( argc != 13 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile mtxFile etreeFile"
"\n seed symmetryflag sparsityflag "
"\n pivotingflag tau droptol lockflag nrhs"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n mtxFile -- file to read in InpMtx matrix object"
"\n etreeFile -- file to read in ETree front tree object"
"\n seed -- random number seed"
"\n symmetryflag -- symmetry flag"
"\n 0 --> symmetric "
"\n 1 --> hermitian"
"\n 2 --> nonsymmetric"
"\n sparsityflag -- sparsity flag"
"\n 0 --> store dense fronts"
"\n 1 --> store sparse fronts, use droptol to drop entries"
"\n pivotingflag -- pivoting flag"
"\n 0 --> do not pivot"
"\n 1 --> enable pivoting"
"\n tau -- upper bound on factor entries"
"\n used only with pivoting"
"\n droptol -- lower bound on factor entries"
"\n used only with sparse fronts"
"\n lockflag -- flag to specify lock status"
"\n 0 --> mutex lock is not allocated or initialized"
"\n 1 --> mutex lock is allocated and it can synchronize"
"\n only threads in this process."
"\n 2 --> mutex lock is allocated and it can synchronize"
"\n only threads in this and other processes."
"\n nrhs -- # of right hand sides"
"\n", argv[0]) ;
return(-1) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
mtxFileName = argv[3] ;
etreeFileName = argv[4] ;
seed = atoi(argv[5]) ;
symmetryflag = atoi(argv[6]) ;
sparsityflag = atoi(argv[7]) ;
pivotingflag = atoi(argv[8]) ;
tau = atof(argv[9]) ;
droptol = atof(argv[10]) ;
lockflag = atoi(argv[11]) ;
nrhs = atoi(argv[12]) ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n mtxFileName -- %s"
"\n etreeFileName -- %s"
"\n seed -- %d"
"\n symmetryflag -- %d"
"\n sparsityflag -- %d"
"\n pivotingflag -- %d"
"\n tau -- %e"
"\n droptol -- %e"
"\n lockflag -- %d"
"\n nrhs -- %d"
"\n",
argv[0], msglvl, argv[2], mtxFileName, etreeFileName,
seed, symmetryflag, sparsityflag, pivotingflag,
tau, droptol, lockflag, nrhs) ;
fflush(msgFile) ;
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
Drand_setDefaultFields(&drand) ;
Drand_init(&drand) ;
Drand_setSeed(&drand, seed) ;
/*
Drand_setUniform(&drand, 0.0, 1.0) ;
*/
Drand_setNormal(&drand, 0.0, 1.0) ;
/*
-------------------------
read in the InpMtx object
-------------------------
*/
if ( strcmp(mtxFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
mtxA = InpMtx_new() ;
MARKTIME(t1) ;
rc = InpMtx_readFromFile(mtxA, mtxFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in mtxA from file %s",
t2 - t1, mtxFileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from InpMtx_readFromFile(%p,%s)",
rc, mtxA, mtxFileName) ;
exit(-1) ;
}
type = mtxA->inputMode ;
neqns = 1 + IVmax(mtxA->nent, InpMtx_ivec1(mtxA), &loc) ;
if ( INPMTX_IS_BY_ROWS(mtxA) ) {
fprintf(msgFile, "\n matrix coordinate type is rows") ;
} else if ( INPMTX_IS_BY_COLUMNS(mtxA) ) {
fprintf(msgFile, "\n matrix coordinate type is columns") ;
} else if ( INPMTX_IS_BY_CHEVRONS(mtxA) ) {
fprintf(msgFile, "\n matrix coordinate type is chevrons") ;
} else {
fprintf(msgFile, "\n\n, error, bad coordinate type") ;
exit(-1) ;
}
if ( INPMTX_IS_RAW_DATA(mtxA) ) {
fprintf(msgFile, "\n matrix storage mode is raw data\n") ;
} else if ( INPMTX_IS_SORTED(mtxA) ) {
fprintf(msgFile, "\n matrix storage mode is sorted\n") ;
} else if ( INPMTX_IS_BY_VECTORS(mtxA) ) {
fprintf(msgFile, "\n matrix storage mode is by vectors\n") ;
} else {
fprintf(msgFile, "\n\n, error, bad storage mode") ;
exit(-1) ;
}
{
int maxcol, maxrow, mincol, minrow ;
InpMtx_range(mtxA, &mincol, &maxcol, &minrow, &maxrow) ;
fprintf(msgFile, "\n range of entries = [%d, %d] x [%d,%d]",
minrow, maxrow, mincol, maxcol) ;
}
/*
{
int nent = InpMtx_nent(mtxA) ;
double *dvec = InpMtx_dvec(mtxA) ;
Drand *drand ;
drand = Drand_new() ;
Drand_setUniform(drand, 0., 1.) ;
Drand_fillDvector(drand, nent, dvec) ;
}
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n after reading InpMtx object from file %s",
mtxFileName) ;
if ( msglvl == 2 ) {
InpMtx_writeStats(mtxA, msgFile) ;
} else {
InpMtx_writeForHumanEye(mtxA, msgFile) ;
}
fflush(msgFile) ;
}
/*
--------------------------------------------------------
generate the linear system
1. generate solution matrix and fill with random numbers
2. generate rhs matrix and fill with zeros
3. compute matrix-matrix multiply
--------------------------------------------------------
*/
MARKTIME(t1) ;
mtxX = DenseMtx_new() ;
DenseMtx_init(mtxX, type, 0, -1, neqns, nrhs, 1, neqns) ;
DenseMtx_fillRandomEntries(mtxX, &drand) ;
mtxB = DenseMtx_new() ;
DenseMtx_init(mtxB, type, 1, -1, neqns, nrhs, 1, neqns) ;
DenseMtx_zero(mtxB) ;
fprintf(msgFile, "\n B and X initialized") ;
fflush(msgFile) ;
switch ( symmetryflag ) {
case SPOOLES_SYMMETRIC :
InpMtx_sym_mmm(mtxA, mtxB, one, mtxX) ;
break ;
case SPOOLES_HERMITIAN :
InpMtx_herm_mmm(mtxA, mtxB, one, mtxX) ;
break ;
case SPOOLES_NONSYMMETRIC :
InpMtx_nonsym_mmm(mtxA, mtxB, one, mtxX) ;
break ;
default :
break ;
}
fprintf(msgFile, "\n mvm done") ;
fflush(msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : set up the solution and rhs ",
t2 - t1) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n original mtxX") ;
DenseMtx_writeForHumanEye(mtxX, msgFile) ;
fprintf(msgFile, "\n\n original mtxB") ;
DenseMtx_writeForHumanEye(mtxB, msgFile) ;
fflush(msgFile) ;
}
DenseMtx_writeToFile(mtxB, "rhs.densemtxb") ;
/*
InpMtx_writeForMatlab(mtxA, "A", msgFile) ;
DenseMtx_writeForMatlab(mtxX, "X", msgFile) ;
DenseMtx_writeForMatlab(mtxB, "B", msgFile) ;
*/
/*
------------------------
read in the ETree object
------------------------
*/
if ( strcmp(etreeFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
frontETree = ETree_new() ;
MARKTIME(t1) ;
rc = ETree_readFromFile(frontETree, etreeFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : read in frontETree from file %s",
t2 - t1, etreeFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)",
rc, frontETree, etreeFileName) ;
exit(-1) ;
}
ETree_leftJustify(frontETree) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n after reading ETree object from file %s",
etreeFileName) ;
if ( msglvl == 2 ) {
ETree_writeStats(frontETree, msgFile) ;
} else {
ETree_writeForHumanEye(frontETree, msgFile) ;
}
}
fflush(msgFile) ;
/*
--------------------------------------------------
get the permutations, permute the matrix and the
front tree, and compute the symbolic factorization
--------------------------------------------------
*/
MARKTIME(t1) ;
oldToNewIV = ETree_oldToNewVtxPerm(frontETree) ;
newToOldIV = ETree_newToOldVtxPerm(frontETree) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : get permutations", t2 - t1) ;
MARKTIME(t1) ;
ETree_permuteVertices(frontETree, oldToNewIV) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : permute front tree", t2 - t1) ;
MARKTIME(t1) ;
InpMtx_permute(mtxA, IV_entries(oldToNewIV), IV_entries(oldToNewIV)) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : permute mtxA", t2 - t1) ;
if ( symmetryflag == SPOOLES_SYMMETRIC
|| symmetryflag == SPOOLES_HERMITIAN ) {
MARKTIME(t1) ;
InpMtx_mapToUpperTriangle(mtxA) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : map to upper triangle", t2 - t1) ;
}
if ( ! INPMTX_IS_BY_CHEVRONS(mtxA) ) {
MARKTIME(t1) ;
InpMtx_changeCoordType(mtxA, INPMTX_BY_CHEVRONS) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : change coordinate type", t2 - t1) ;
}
if ( INPMTX_IS_RAW_DATA(mtxA) ) {
MARKTIME(t1) ;
InpMtx_changeStorageMode(mtxA, INPMTX_SORTED) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : sort entries ", t2 - t1) ;
}
if ( INPMTX_IS_SORTED(mtxA) ) {
MARKTIME(t1) ;
InpMtx_changeStorageMode(mtxA, INPMTX_BY_VECTORS) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : convert to vectors ", t2 - t1) ;
}
MARKTIME(t1) ;
symbfacIVL = SymbFac_initFromInpMtx(frontETree, mtxA) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : symbolic factorization", t2 - t1) ;
MARKTIME(t1) ;
DenseMtx_permuteRows(mtxB, oldToNewIV) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : permute rhs", t2 - t1) ;
/*
DenseMtx_writeForMatlab(mtxB, "Bhat", msgFile) ;
*/
/*
------------------------------
initialize the FrontMtx object
------------------------------
*/
MARKTIME(t1) ;
frontmtx = FrontMtx_new() ;
mtxmanager = SubMtxManager_new() ;
SubMtxManager_init(mtxmanager, lockflag, 0) ;
FrontMtx_init(frontmtx, frontETree, symbfacIVL,
type, symmetryflag, sparsityflag, pivotingflag,
lockflag, 0, NULL, mtxmanager, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %8.3f : initialize the front matrix",
t2 - t1) ;
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n nendD = %d, nentL = %d, nentU = %d",
frontmtx->nentD, frontmtx->nentL, frontmtx->nentU) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n front matrix initialized") ;
FrontMtx_writeForHumanEye(frontmtx, msgFile) ;
fflush(msgFile) ;
}
SubMtxManager_writeForHumanEye(mtxmanager, msgFile) ;
/*
-----------------
factor the matrix
-----------------
*/
nzf = ETree_nFactorEntries(frontETree, symmetryflag) ;
factorops = ETree_nFactorOps(frontETree, type, symmetryflag) ;
fprintf(msgFile,
"\n %d factor entries, %.0f factor ops, %8.3f ratio",
nzf, factorops, factorops/nzf) ;
IVzero(6, stats) ;
DVzero(9, cpus) ;
chvmanager = ChvManager_new() ;
ChvManager_init(chvmanager, lockflag, 1) ;
MARKTIME(t1) ;
rootchv = FrontMtx_factorInpMtx(frontmtx, mtxA, tau, droptol,
chvmanager, &error, cpus,
stats, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %8.3f : factor matrix, %8.3f mflops",
t2 - t1, 1.e-6*factorops/(t2-t1)) ;
if ( rootchv != NULL ) {
fprintf(msgFile, "\n\n factorization did not complete") ;
for ( chv = rootchv ; chv != NULL ; chv = chv->next ) {
fprintf(stdout, "\n chv %d, nD = %d, nL = %d, nU = %d",
chv->id, chv->nD, chv->nL, chv->nU) ;
}
}
if ( error >= 0 ) {
fprintf(msgFile, "\n\n error encountered at front %d\n", error) ;
exit(-1) ;
}
fprintf(msgFile,
"\n %8d pivots, %8d pivot tests, %8d delayed rows and columns",
stats[0], stats[1], stats[2]) ;
if ( frontmtx->rowadjIVL != NULL ) {
fprintf(msgFile,
"\n %d entries in rowadjIVL", frontmtx->rowadjIVL->tsize) ;
}
if ( frontmtx->coladjIVL != NULL ) {
fprintf(msgFile,
", %d entries in coladjIVL", frontmtx->coladjIVL->tsize) ;
}
if ( frontmtx->upperblockIVL != NULL ) {
fprintf(msgFile,
"\n %d fronts, %d entries in upperblockIVL",
frontmtx->nfront, frontmtx->upperblockIVL->tsize) ;
}
if ( frontmtx->lowerblockIVL != NULL ) {
fprintf(msgFile,
", %d entries in lowerblockIVL",
frontmtx->lowerblockIVL->tsize) ;
}
fprintf(msgFile,
"\n %d entries in D, %d entries in L, %d entries in U",
stats[3], stats[4], stats[5]) ;
fprintf(msgFile, "\n %d locks", frontmtx->nlocks) ;
if ( FRONTMTX_IS_SYMMETRIC(frontmtx)
|| FRONTMTX_IS_HERMITIAN(frontmtx) ) {
int nneg, npos, nzero ;
FrontMtx_inertia(frontmtx, &nneg, &nzero, &npos) ;
fprintf(msgFile,
"\n %d negative, %d zero and %d positive eigenvalues",
nneg, nzero, npos) ;
fflush(msgFile) ;
}
cputotal = cpus[8] ;
if ( cputotal > 0.0 ) {
fprintf(msgFile,
"\n initialize fronts %8.3f %6.2f"
"\n load original entries %8.3f %6.2f"
"\n update fronts %8.3f %6.2f"
"\n assemble postponed data %8.3f %6.2f"
"\n factor fronts %8.3f %6.2f"
"\n extract postponed data %8.3f %6.2f"
"\n store factor entries %8.3f %6.2f"
"\n miscellaneous %8.3f %6.2f"
"\n total time %8.3f",
cpus[0], 100.*cpus[0]/cputotal,
cpus[1], 100.*cpus[1]/cputotal,
cpus[2], 100.*cpus[2]/cputotal,
cpus[3], 100.*cpus[3]/cputotal,
cpus[4], 100.*cpus[4]/cputotal,
cpus[5], 100.*cpus[5]/cputotal,
cpus[6], 100.*cpus[6]/cputotal,
cpus[7], 100.*cpus[7]/cputotal, cputotal) ;
}
SubMtxManager_writeForHumanEye(mtxmanager, msgFile) ;
ChvManager_writeForHumanEye(chvmanager, msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front factor matrix") ;
FrontMtx_writeForHumanEye(frontmtx, msgFile) ;
}
/*
fprintf(msgFile, "\n L = eye(%d,%d) ;", neqns, neqns) ;
fprintf(msgFile, "\n U = eye(%d,%d) ;", neqns, neqns) ;
fprintf(msgFile, "\n D = zeros(%d,%d) ;", neqns, neqns) ;
FrontMtx_writeForMatlab(frontmtx, "L", "D", "U", msgFile) ;
*/
/*
------------------------------
post-process the factor matrix
------------------------------
*/
MARKTIME(t1) ;
FrontMtx_postProcess(frontmtx, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %8.3f : post-process the matrix", t2 - t1) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front factor matrix after post-processing") ;
FrontMtx_writeForHumanEye(frontmtx, msgFile) ;
}
fprintf(msgFile, "\n\n after post-processing") ;
SubMtxManager_writeForHumanEye(frontmtx->manager, msgFile) ;
/*
----------------
solve the system
----------------
*/
neqns = mtxB->nrow ;
nrhs = mtxB->ncol ;
mtxZ = DenseMtx_new() ;
DenseMtx_init(mtxZ, type, 0, 0, neqns, nrhs, 1, neqns) ;
DenseMtx_zero(mtxZ) ;
if ( type == SPOOLES_REAL ) {
nops = frontmtx->nentD + 2*frontmtx->nentU ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
nops += 2*frontmtx->nentL ;
} else {
nops += 2*frontmtx->nentU ;
}
} else if ( type == SPOOLES_COMPLEX ) {
nops = 8*frontmtx->nentD + 8*frontmtx->nentU ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
nops += 8*frontmtx->nentL ;
} else {
nops += 8*frontmtx->nentU ;
}
}
nops *= nrhs ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n rhs") ;
DenseMtx_writeForHumanEye(mtxB, msgFile) ;
fflush(stdout) ;
}
DVzero(6, cpus) ;
MARKTIME(t1) ;
FrontMtx_solve(frontmtx, mtxZ, mtxB, mtxmanager,
cpus, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %8.3f : solve the system, %.3f mflops",
t2 - t1, 1.e-6*nops/(t2 - t1)) ;
cputotal = t2 - t1 ;
if ( cputotal > 0.0 ) {
fprintf(msgFile,
"\n set up solves %8.3f %6.2f"
"\n load rhs and store solution %8.3f %6.2f"
"\n forward solve %8.3f %6.2f"
"\n diagonal solve %8.3f %6.2f"
"\n backward solve %8.3f %6.2f"
"\n total time %8.3f",
cpus[0], 100.*cpus[0]/cputotal,
cpus[1], 100.*cpus[1]/cputotal,
cpus[2], 100.*cpus[2]/cputotal,
cpus[3], 100.*cpus[3]/cputotal,
cpus[4], 100.*cpus[4]/cputotal, cputotal) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n computed solution") ;
DenseMtx_writeForHumanEye(mtxZ, msgFile) ;
fflush(stdout) ;
}
/*
DenseMtx_writeForMatlab(mtxZ, "Xhat", msgFile) ;
*/
/*
-------------------------------------------------------------
permute the computed solution back into the original ordering
-------------------------------------------------------------
*/
MARKTIME(t1) ;
DenseMtx_permuteRows(mtxZ, newToOldIV) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : permute solution", t2 - t1) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n permuted solution") ;
DenseMtx_writeForHumanEye(mtxZ, msgFile) ;
fflush(stdout) ;
}
/*
-----------------
compute the error
-----------------
*/
DenseMtx_sub(mtxZ, mtxX) ;
fprintf(msgFile, "\n\n maxabs error = %12.4e", DenseMtx_maxabs(mtxZ)) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n error") ;
DenseMtx_writeForHumanEye(mtxZ, msgFile) ;
fflush(stdout) ;
}
fprintf(msgFile, "\n\n after solve") ;
SubMtxManager_writeForHumanEye(frontmtx->manager, msgFile) ;
/*
------------------------
free the working storage
------------------------
*/
IV_free(oldToNewIV) ;
IV_free(newToOldIV) ;
InpMtx_free(mtxA) ;
DenseMtx_free(mtxX) ;
DenseMtx_free(mtxB) ;
DenseMtx_free(mtxZ) ;
FrontMtx_free(frontmtx) ;
ETree_free(frontETree) ;
IVL_free(symbfacIVL) ;
ChvManager_free(chvmanager) ;
SubMtxManager_free(mtxmanager) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ETree_leftJustify(frontETree) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n after reading ETree object from file %s",
etreeFileName) ;
if ( msglvl == 2 ) {
ETree_writeStats(frontETree, msgFile) ;
} else {
ETree_writeForHumanEye(frontETree, msgFile) ;
}
}
fflush(msFrontMtx/drivers/testGrid.c 0100644 0002055 0007177 00000034456 06650147225 0017304 0 ustar 00cleve compmath 0000040 0000006 /* testGrid.c */
#include "../FrontMtx.h"
#include "../../Drand.h"
#include "../../SymbFac.h"
#include "../../timings.h"
#include "../../misc.h"
/*--------------------------------------------------------------------*/
void mkNDlinsys ( int n1, int n2, int n3, int maxzeros, int maxsize,
int type, int symmetryflag, int nrhs, int seed, int msglvl,
FILE *msgFile, ETree **pfrontETree, IVL **psymbfacIVL,
InpMtx **pmtxA, DenseMtx **pmtxX, DenseMtx **pmtxB ) ;
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-----------------------------------------------------
test the factor method for a grid matrix
(1) construct a linear system for a nested dissection
ordering on a regular grid
(2) create a solution matrix object
(3) multiply the solution with the matrix
to get a right hand side matrix object
(4) factor the matrix
(5) solve the system
created -- 98may16, cca
-----------------------------------------------------
*/
{
Chv *chv, *rootchv ;
ChvManager *chvmanager ;
DenseMtx *mtxB, *mtxX, *mtxZ ;
FrontMtx *frontmtx ;
InpMtx *mtxA ;
SubMtxManager *mtxmanager ;
double cputotal, droptol, factorops ;
double cpus[9] ;
Drand drand ;
double nops, tau, t1, t2 ;
ETree *frontETree ;
FILE *msgFile ;
int error, lockflag, maxsize, maxzeros, msglvl, neqns,
n1, n2, n3, nrhs, nzf, pivotingflag,
seed, sparsityflag, symmetryflag, type ;
int stats[6] ;
IVL *symbfacIVL ;
if ( argc != 17 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile n1 n2 n3 maxzeros maxsize"
"\n seed type symmetryflag sparsityflag "
"\n pivotingflag tau droptol lockflag nrhs"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n n1 -- number of grid points in the first direction"
"\n n2 -- number of grid points in the second direction"
"\n n3 -- number of grid points in the third direction"
"\n maxzeros -- max number of zeroes in a front"
"\n maxsize -- max number of internal nodes in a front"
"\n seed -- random number seed"
"\n type -- type of entries"
"\n 1 --> real"
"\n 2 --> complex"
"\n symmetryflag -- symmetry flag"
"\n 0 --> symmetric "
"\n 1 --> hermitian"
"\n 2 --> nonsymmetric"
"\n sparsityflag -- sparsity flag"
"\n 0 --> store dense fronts"
"\n 1 --> store sparse fronts, use droptol to drop entries"
"\n pivotingflag -- pivoting flag"
"\n 0 --> do not pivot"
"\n 1 --> enable pivoting"
"\n tau -- upper bound on factor entries"
"\n used only with pivoting"
"\n droptol -- lower bound on factor entries"
"\n used only with sparse fronts"
"\n lockflag -- flag to specify lock status"
"\n 0 --> mutex lock is not allocated or initialized"
"\n 1 --> mutex lock is allocated and it can synchronize"
"\n only threads in this process."
"\n 2 --> mutex lock is allocated and it can synchronize"
"\n only threads in this and other processes."
"\n nrhs -- # of right hand sides"
"\n", argv[0]) ;
return(-1) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
n1 = atoi(argv[3]) ;
n2 = atoi(argv[4]) ;
n3 = atoi(argv[5]) ;
maxzeros = atoi(argv[6]) ;
maxsize = atoi(argv[7]) ;
seed = atoi(argv[8]) ;
type = atoi(argv[9]) ;
symmetryflag = atoi(argv[10]) ;
sparsityflag = atoi(argv[11]) ;
pivotingflag = atoi(argv[12]) ;
tau = atof(argv[13]) ;
droptol = atof(argv[14]) ;
lockflag = atoi(argv[15]) ;
nrhs = atoi(argv[16]) ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n n1 -- %d"
"\n n2 -- %d"
"\n n3 -- %d"
"\n maxzeros -- %d"
"\n maxsize -- %d"
"\n seed -- %d"
"\n type -- %d"
"\n symmetryflag -- %d"
"\n sparsityflag -- %d"
"\n pivotingflag -- %d"
"\n tau -- %e"
"\n droptol -- %e"
"\n lockflag -- %d"
"\n nrhs -- %d"
"\n",
argv[0], msglvl, argv[2], n1, n2, n3, maxzeros, maxsize,
seed, type, symmetryflag, sparsityflag, pivotingflag,
tau, droptol, lockflag, nrhs) ;
fflush(msgFile) ;
neqns = n1 * n2 * n3 ;
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
Drand_setDefaultFields(&drand) ;
Drand_init(&drand) ;
Drand_setSeed(&drand, seed) ;
/*
Drand_setUniform(&drand, 0.0, 1.0) ;
*/
Drand_setNormal(&drand, 0.0, 1.0) ;
/*
--------------------------
generate the linear system
--------------------------
*/
mkNDlinsys(n1, n2, n3, maxzeros, maxsize, type,
symmetryflag, nrhs, seed, msglvl, msgFile,
&frontETree, &symbfacIVL, &mtxA, &mtxX, &mtxB) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n mtxA") ;
InpMtx_writeForHumanEye(mtxA, msgFile) ;
fprintf(msgFile, "\n mtxX") ;
DenseMtx_writeForHumanEye(mtxX, msgFile) ;
fprintf(msgFile, "\n mtxB") ;
DenseMtx_writeForHumanEye(mtxB, msgFile) ;
fflush(msgFile) ;
}
/*
fprintf(msgFile, "\n neqns = %d ;", n1*n2*n3) ;
fprintf(msgFile, "\n nrhs = %d ;", nrhs) ;
fprintf(msgFile, "\n A = zeros(neqns, neqns) ;") ;
fprintf(msgFile, "\n X = zeros(neqns, nrhs) ;") ;
fprintf(msgFile, "\n B = zeros(neqns, nrhs) ;") ;
InpMtx_writeForMatlab(mtxA, "A", msgFile) ;
DenseMtx_writeForMatlab(mtxX, "X", msgFile) ;
DenseMtx_writeForMatlab(mtxB, "B", msgFile) ;
{
int *ivec1 = InpMtx_ivec1(mtxA) ;
int *ivec2 = InpMtx_ivec2(mtxA) ;
double *dvec = InpMtx_dvec(mtxA) ;
int ichv, ii, col, offset, row, nent = InpMtx_nent(mtxA) ;
fprintf(msgFile, "\n coordType = %d", mtxA->coordType) ;
fprintf(msgFile, "\n start of matrix output file") ;
fprintf(msgFile, "\n %d %d %d", n1*n2*n3, n1*n2*n3, nent) ;
for ( ii = 0 ; ii < nent ; ii++ ) {
ichv = ivec1[ii] ;
if ( (offset = ivec2[ii]) >= 0 ) {
row = ichv, col = row + offset ;
} else {
col = ichv, row = col - offset ;
}
fprintf(msgFile, "\n %d %d %24.16e %24.16e",
row, col, dvec[2*ii], dvec[2*ii+1]) ;
}
}
{
int ii, jj ;
double imag, real ;
fprintf(msgFile, "\n start of rhs output file") ;
fprintf(msgFile, "\n %d %d", n1*n2*n3, nrhs) ;
for ( ii = 0 ; ii < n1*n2*n3 ; ii++ ) {
fprintf(msgFile, "\n %d ", ii) ;
for ( jj = 0 ; jj < nrhs ; jj++ ) {
DenseMtx_complexEntry(mtxB, ii, jj, &real, &imag) ;
fprintf(msgFile, " %24.16e %24.16e", real, imag) ;
}
}
}
*/
/*
------------------------------
initialize the FrontMtx object
------------------------------
*/
MARKTIME(t1) ;
frontmtx = FrontMtx_new() ;
mtxmanager = SubMtxManager_new() ;
SubMtxManager_init(mtxmanager, lockflag, 0) ;
FrontMtx_init(frontmtx, frontETree, symbfacIVL,
type, symmetryflag, sparsityflag, pivotingflag,
lockflag, 0, NULL, mtxmanager, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %8.3f : initialize the front matrix",
t2 - t1) ;
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n nendD = %d, nentL = %d, nentU = %d",
frontmtx->nentD, frontmtx->nentL, frontmtx->nentU) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n front matrix initialized") ;
FrontMtx_writeForHumanEye(frontmtx, msgFile) ;
fflush(msgFile) ;
}
SubMtxManager_writeForHumanEye(mtxmanager, msgFile) ;
/*
-----------------
factor the matrix
-----------------
*/
nzf = ETree_nFactorEntries(frontETree, symmetryflag) ;
factorops = ETree_nFactorOps(frontETree, type, symmetryflag) ;
fprintf(msgFile,
"\n %d factor entries, %.0f factor ops, %8.3f ratio",
nzf, factorops, factorops/nzf) ;
IVzero(6, stats) ;
DVzero(9, cpus) ;
chvmanager = ChvManager_new() ;
ChvManager_init(chvmanager, lockflag, 1) ;
MARKTIME(t1) ;
rootchv = FrontMtx_factorInpMtx(frontmtx, mtxA, tau, droptol,
chvmanager, &error, cpus,
stats, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %8.3f : factor matrix, %8.3f mflops",
t2 - t1, 1.e-6*factorops/(t2-t1)) ;
if ( rootchv != NULL ) {
fprintf(msgFile, "\n\n factorization did not complete") ;
for ( chv = rootchv ; chv != NULL ; chv = chv->next ) {
fprintf(stdout, "\n chv %d, nD = %d, nL = %d, nU = %d",
chv->id, chv->nD, chv->nL, chv->nU) ;
}
}
if ( error >= 0 ) {
fprintf(msgFile, "\n\n error encountered at front %d\n", error) ;
exit(-1) ;
}
fprintf(msgFile,
"\n %8d pivots, %8d pivot tests, %8d delayed rows and columns",
stats[0], stats[1], stats[2]) ;
if ( frontmtx->rowadjIVL != NULL ) {
fprintf(msgFile,
"\n %d entries in rowadjIVL", frontmtx->rowadjIVL->tsize) ;
}
if ( frontmtx->coladjIVL != NULL ) {
fprintf(msgFile,
", %d entries in coladjIVL", frontmtx->coladjIVL->tsize) ;
}
if ( frontmtx->upperblockIVL != NULL ) {
fprintf(msgFile,
"\n %d fronts, %d entries in upperblockIVL",
frontmtx->nfront, frontmtx->upperblockIVL->tsize) ;
}
if ( frontmtx->lowerblockIVL != NULL ) {
fprintf(msgFile,
", %d entries in lowerblockIVL",
frontmtx->lowerblockIVL->tsize) ;
}
fprintf(msgFile,
"\n %d entries in D, %d entries in L, %d entries in U",
stats[3], stats[4], stats[5]) ;
fprintf(msgFile, "\n %d locks", frontmtx->nlocks) ;
cputotal = cpus[8] ;
if ( cputotal > 0.0 ) {
fprintf(msgFile,
"\n initialize fronts %8.3f %6.2f"
"\n load original entries %8.3f %6.2f"
"\n update fronts %8.3f %6.2f"
"\n assemble postponed data %8.3f %6.2f"
"\n factor fronts %8.3f %6.2f"
"\n extract postponed data %8.3f %6.2f"
"\n store factor entries %8.3f %6.2f"
"\n miscellaneous %8.3f %6.2f"
"\n total time %8.3f",
cpus[0], 100.*cpus[0]/cputotal,
cpus[1], 100.*cpus[1]/cputotal,
cpus[2], 100.*cpus[2]/cputotal,
cpus[3], 100.*cpus[3]/cputotal,
cpus[4], 100.*cpus[4]/cputotal,
cpus[5], 100.*cpus[5]/cputotal,
cpus[6], 100.*cpus[6]/cputotal,
cpus[7], 100.*cpus[7]/cputotal, cputotal) ;
}
SubMtxManager_writeForHumanEye(mtxmanager, msgFile) ;
ChvManager_writeForHumanEye(chvmanager, msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front factor matrix") ;
FrontMtx_writeForHumanEye(frontmtx, msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n %% MATLAB file: front factor matrix") ;
FrontMtx_writeForMatlab(frontmtx, "L", "D", "U", msgFile) ;
}
/*
------------------------------
post-process the factor matrix
------------------------------
*/
MARKTIME(t1) ;
FrontMtx_postProcess(frontmtx, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %8.3f : post-process the matrix", t2 - t1) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front factor matrix after post-processing") ;
FrontMtx_writeForHumanEye(frontmtx, msgFile) ;
}
fprintf(msgFile, "\n\n after post-processing") ;
SubMtxManager_writeForHumanEye(frontmtx->manager, msgFile) ;
/*
code to test out the IO methods.
write the matrix to a file, free it,
then read it back in.
note: formatted files do not have much accuracy.
*/
/*
FrontMtx_writeToFile(frontmtx, "temp.frontmtxb") ;
FrontMtx_free(frontmtx) ;
frontmtx = FrontMtx_new() ;
FrontMtx_readFromFile(frontmtx, "temp.frontmtxb") ;
frontmtx->manager = mtxmanager ;
FrontMtx_writeForHumanEye(frontmtx, msgFile) ;
*/
/*
----------------
solve the system
----------------
*/
neqns = mtxB->nrow ;
nrhs = mtxB->ncol ;
mtxZ = DenseMtx_new() ;
DenseMtx_init(mtxZ, type, 0, 0, neqns, nrhs, 1, neqns) ;
DenseMtx_zero(mtxZ) ;
if ( type == SPOOLES_REAL ) {
nops = frontmtx->nentD + 2*frontmtx->nentU ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
nops += 2*frontmtx->nentL ;
} else {
nops += 2*frontmtx->nentU ;
}
} else if ( type == SPOOLES_COMPLEX ) {
nops = 8*frontmtx->nentD + 8*frontmtx->nentU ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
nops += 8*frontmtx->nentL ;
} else {
nops += 8*frontmtx->nentU ;
}
}
nops *= nrhs ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n rhs") ;
DenseMtx_writeForHumanEye(mtxB, msgFile) ;
fflush(stdout) ;
}
DVzero(6, cpus) ;
MARKTIME(t1) ;
FrontMtx_solve(frontmtx, mtxZ, mtxB, mtxmanager,
cpus, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %8.3f : solve the system, %.3f mflops",
t2 - t1, 1.e-6*nops/(t2 - t1)) ;
cputotal = t2 - t1 ;
if ( cputotal > 0.0 ) {
fprintf(msgFile,
"\n set up solves %8.3f %6.2f"
"\n load rhs and store solution %8.3f %6.2f"
"\n forward solve %8.3f %6.2f"
"\n diagonal solve %8.3f %6.2f"
"\n backward solve %8.3f %6.2f"
"\n total time %8.3f",
cpus[0], 100.*cpus[0]/cputotal,
cpus[1], 100.*cpus[1]/cputotal,
cpus[2], 100.*cpus[2]/cputotal,
cpus[3], 100.*cpus[3]/cputotal,
cpus[4], 100.*cpus[4]/cputotal, cputotal) ;
}
/*
fprintf(msgFile, "\n Z = zeros(neqns, nrhs) ;") ;
DenseMtx_writeForMatlab(mtxZ, "Z", msgFile) ;
*/
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n computed solution") ;
DenseMtx_writeForHumanEye(mtxZ, msgFile) ;
fflush(stdout) ;
}
DenseMtx_sub(mtxZ, mtxX) ;
fprintf(msgFile, "\n\n maxabs error = %12.4e", DenseMtx_maxabs(mtxZ)) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n error") ;
DenseMtx_writeForHumanEye(mtxZ, msgFile) ;
fflush(stdout) ;
}
fprintf(msgFile, "\n\n after solve") ;
SubMtxManager_writeForHumanEye(frontmtx->manager, msgFile) ;
/*
------------------------
free the working storage
------------------------
*/
InpMtx_free(mtxA) ;
DenseMtx_free(mtxX) ;
DenseMtx_free(mtxB) ;
DenseMtx_free(mtxZ) ;
FrontMtx_free(frontmtx) ;
ETree_free(frontETree) ;
IVL_free(symbfacIVL) ;
ChvManager_free(chvmanager) ;
SubMtxManager_free(mtxmanager) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
d"
"\n symmetryflag -- %d"
"\n sparsityflag -- %d"
"\n pivotingflag -- %d"
"\n tau -- %e"
"\n droptol -- %e"
"\n lockflag -- %d"
FrontMtx/drivers/testQRgrid.c 0100644 0002055 0007177 00000020042 06571267174 0017601 0 ustar 00cleve compmath 0000040 0000006 /* testQRgrid.c */
#include "../FrontMtx.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
void mkNDlinsysQR ( int n1, int n2, int n3, int type, int nrhs,
int seed, int msglvl, FILE *msgFile, ETree **pfrontETree,
IVL **psymbfacIVL, InpMtx **pmtxA, DenseMtx **pmtxX,
DenseMtx **pmtxB) ;
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------------
test the QR factor method for a FrontMtx object
on an n1 x n2 x n3 grid
(1) generate an overdetermined system AX = B
(2) factor the matrix
(3) solve the systems
created -- 97apr11, dkw
modified -- 98may28, cca
---------------------------------------------------
*/
{
ChvManager *chvmanager ;
DenseMtx *mtxB, *mtxX, *mtxZ ;
double cputotal, factorops ;
double cpus[9] ;
double nops, t1, t2 ;
ETree *frontETree ;
FILE *msgFile ;
FrontMtx *frontmtx ;
InpMtx *mtxA ;
int msglvl, neqns, nrhs, n1, n2, n3, seed, type ;
IVL *symbfacIVL ;
SubMtxManager *mtxmanager ;
if ( argc != 9 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile n1 n2 n3 seed nrhs "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n n1 -- # of points in the first direction"
"\n n2 -- # of points in the second direction"
"\n n3 -- # of points in the third direction"
"\n seed -- random number seed"
"\n nrhs -- # of right hand sides"
"\n type -- type of linear system"
"\n 1 -- real"
"\n 2 -- complex"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
n1 = atoi(argv[3]) ;
n2 = atoi(argv[4]) ;
n3 = atoi(argv[5]) ;
seed = atoi(argv[6]) ;
nrhs = atoi(argv[7]) ;
type = atoi(argv[8]) ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n n1 -- %d"
"\n n2 -- %d"
"\n n3 -- %d"
"\n seed -- %d"
"\n nrhs -- %d"
"\n type -- %d"
"\n",
argv[0], msglvl, argv[2], n1, n2, n3, seed, nrhs, type) ;
fflush(msgFile) ;
neqns = n1*n2*n3 ;
if ( type != SPOOLES_REAL && type != SPOOLES_COMPLEX ) {
fprintf(stderr, "\n fatal error, type must be real or complex") ;
exit(-1) ;
}
/*
------------------------------------------
generate the A X = B overdetermined system
------------------------------------------
*/
mkNDlinsysQR(n1, n2, n3, type, nrhs, seed, msglvl, msgFile,
&frontETree, &symbfacIVL, &mtxA, &mtxX, &mtxB) ;
/*
------------------------------
initialize the FrontMtx object
------------------------------
*/
MARKTIME(t1) ;
mtxmanager = SubMtxManager_new() ;
SubMtxManager_init(mtxmanager, NO_LOCK, 0) ;
frontmtx = FrontMtx_new() ;
if ( type == SPOOLES_REAL ) {
FrontMtx_init(frontmtx, frontETree, symbfacIVL, type,
SPOOLES_SYMMETRIC, FRONTMTX_DENSE_FRONTS,
SPOOLES_NO_PIVOTING, NO_LOCK,
0, NULL, mtxmanager, msglvl, msgFile) ;
} else if ( type == SPOOLES_COMPLEX ) {
FrontMtx_init(frontmtx, frontETree, symbfacIVL, type,
SPOOLES_HERMITIAN, FRONTMTX_DENSE_FRONTS,
SPOOLES_NO_PIVOTING, NO_LOCK,
0, NULL, mtxmanager, msglvl, msgFile) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : FrontMtx initialized", t2 - t1) ;
fflush(msgFile) ;
/*
-----------------
factor the matrix
-----------------
*/
DVzero(6, cpus) ;
chvmanager = ChvManager_new() ;
ChvManager_init(chvmanager, NO_LOCK, 0) ;
factorops = 0.0 ;
MARKTIME(t1) ;
FrontMtx_QR_factor(frontmtx, mtxA, chvmanager,
cpus, &factorops, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n after QR_factor() call, facops = %8.2f",factorops) ;
fprintf(msgFile, "\n CPU %8.3f : FrontMtx_QR_factor, %8.3f mflops",
t2 - t1, 1.e-6*factorops/(t2-t1)) ;
cputotal = t2 - t1 ;
if ( cputotal > 0.0 ) {
fprintf(msgFile, "\n"
"\n setup factorization %8.3f %6.2f"
"\n setup fronts %8.3f %6.2f"
"\n factor fronts %8.3f %6.2f"
"\n store factor %8.3f %6.2f"
"\n store update %8.3f %6.2f"
"\n miscellaneous %8.3f %6.2f"
"\n total time %8.3f",
cpus[0], 100.*cpus[0]/cputotal,
cpus[1], 100.*cpus[1]/cputotal,
cpus[2], 100.*cpus[2]/cputotal,
cpus[3], 100.*cpus[3]/cputotal,
cpus[4], 100.*cpus[4]/cputotal,
cpus[5], 100.*cpus[5]/cputotal, cputotal) ;
}
/*
------------------------------
post-process the factor matrix
------------------------------
*/
MARKTIME(t1) ;
FrontMtx_postProcess(frontmtx, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : post-process the matrix", t2 - t1)
;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n front factor matrix after post-processing") ;
FrontMtx_writeForHumanEye(frontmtx, msgFile) ;
}
fprintf(msgFile, "\n\n after post-processing") ;
SubMtxManager_writeForHumanEye(frontmtx->manager, msgFile) ;
/*
----------------
solve the system
----------------
*/
mtxZ = DenseMtx_new() ;
DenseMtx_init(mtxZ, type, 0, 0, neqns, nrhs, 1, neqns) ;
DenseMtx_zero(mtxZ) ;
if ( type == SPOOLES_REAL ) {
nops = frontmtx->nentD + 2*frontmtx->nentU ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
nops += 2*frontmtx->nentL ;
} else {
nops += 2*frontmtx->nentU ;
}
} else if ( type == SPOOLES_COMPLEX ) {
nops = 8*frontmtx->nentD + 8*frontmtx->nentU ;
if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) {
nops += 8*frontmtx->nentL ;
} else {
nops += 8*frontmtx->nentU ;
}
}
nops *= nrhs ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n rhs") ;
DenseMtx_writeForHumanEye(mtxB, msgFile) ;
fflush(stdout) ;
}
DVzero(6, cpus) ;
MARKTIME(t1) ;
FrontMtx_QR_solve(frontmtx, mtxA, mtxZ, mtxB, mtxmanager,
cpus, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %8.3f : solve the system, %.3f mflops",
t2 - t1, 1.e-6*nops/(t2 - t1)) ;
cputotal = t2 - t1 ;
if ( cputotal > 0.0 ) {
fprintf(msgFile,
"\n CPU %%"
"\n A^TB matrix-matrix multiply %8.3f %6.2f"
"\n set up solves %8.3f %6.2f"
"\n load rhs and store solution %8.3f %6.2f"
"\n forward solve %8.3f %6.2f"
"\n diagonal solve %8.3f %6.2f"
"\n backward solve %8.3f %6.2f"
"\n total solve time %8.3f %6.2f"
"\n total QR solve time %8.3f",
cpus[6], 100.*cpus[6]/cputotal,
cpus[0], 100.*cpus[0]/cputotal,
cpus[1], 100.*cpus[1]/cputotal,
cpus[2], 100.*cpus[2]/cputotal,
cpus[3], 100.*cpus[3]/cputotal,
cpus[4], 100.*cpus[4]/cputotal,
cpus[5], 100.*cpus[5]/cputotal, cputotal) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n computed solution") ;
DenseMtx_writeForHumanEye(mtxZ, msgFile) ;
fflush(stdout) ;
}
/*
-----------------
compute the error
-----------------
*/
DenseMtx_sub(mtxZ, mtxX) ;
fprintf(msgFile, "\n\n maxabs error = %12.4e",
DenseMtx_maxabs(mtxZ)) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n error") ;
DenseMtx_writeForHumanEye(mtxZ, msgFile) ;
fflush(stdout) ;
}
fprintf(msgFile, "\n\n after solve") ;
SubMtxManager_writeForHumanEye(frontmtx->manager, msgFile) ;
/*
------------------------
free the working storage
------------------------
*/
InpMtx_free(mtxA) ;
DenseMtx_free(mtxX) ;
DenseMtx_free(mtxZ) ;
DenseMtx_free(mtxB) ;
FrontMtx_free(frontmtx) ;
IVL_free(symbfacIVL) ;
ETree_free(frontETree) ;
SubMtxManager_free(mtxmanager) ;
ChvManager_free(chvmanager) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/FrontMtx.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
void mkNDlinsysQR ( int n1, int n2, int n3, int type, int nrhs,
int seed, int msglvl, FILE *msgFile, ETree **pfrontETree,
IVL **psymbfacIVL, InpMtx **pmtxA, DenseMtx **pmtxX,
DenseMtx **pmtxB) ;
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
--------------------FrontMtx/doc/ 0042755 0002055 0007177 00000000000 06650232157 0014432 5 ustar 00cleve compmath 0000040 0000006 FrontMtx/doc/dataStructure.tex 0100644 0002055 0007177 00000013140 06572065745 0020012 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structures}
\label{section:FrontMtx:dataStructure}
\par
The {\tt FrontMtx} structure has the following fields.
\begin{itemize}
\item
{\tt int nfront} : number of fronts.
\item
{\tt int neqns} : number of rows and columns in the factor matrix.
\item
{\tt int symmetryflag} : flag to denote the type of symmetry
of $A + \sigma B$.
\begin{itemize}
\item
{\tt SPOOLES\_SYMMETRIC} --- $A$ and/or $B$ are symmetric.
\item
{\tt SPOOLES\_HERMITIAN} --- $A$ and/or $B$ are hermitian.
\item
{\tt SPOOLES\_NONSYMMETRIC} --- $A$ and/or $B$ are nonsymmetric.
\end{itemize}
\item
{\tt int pivotingflag} : flag to specify pivoting for stability,
\begin{itemize}
\item
{\tt SPOOLES\_NO\_PIVOTING} --- pivoting not used
\item
{\tt SPOOLES\_PIVOTING} --- pivoting used
\end{itemize}
\item
{\tt int sparsityflag} : flag to specify storage of factors.
\begin{itemize}
\item
{\tt 0} --- each front is dense
\item
{\tt 1} --- a front may be sparse due to entries dropped
because they are below a drop tolerance.
\end{itemize}
\item
{\tt int dataMode} : flag to specify data storage.
\begin{itemize}
\item
{\tt 1} --- one-dimensional, used during the factorization.
\item
{\tt 2} --- two-dimensional, used during the solves.
\end{itemize}
\item
{\tt int nentD} : number of entries in $D$
\item
{\tt int nentL} : number of entries in $L$
\item
{\tt int nentU} : number of entries in $U$
\item
{\tt Tree *tree} : Tree object that holds the tree of fronts.
Note, normally this is {\tt frontETree->tree}, but we leave this
here for later enhancements where we change the tree after the
factorization, e.g., merge/drop fronts.
\item
{\tt ETree *frontETree} : elimination tree object that holds the
front tree.
\item
{\tt IVL *symbfacIVL} : {\tt IVL} object that holds the
symbolic factorization.
\item
{\tt IV *frontsizesIV} : {\tt IV} object that holds the
vector of front sizes, i.e., the number of internal rows
and columns in a front.
\item
{\tt IVL *rowadjIVL} : {\tt IVL} object that holds the
row list for the fronts, used only for a nonsymmetric factorization
with pivoting enabled.
\item
{\tt IVL *coladjIVL} : {\tt IVL} object that holds the
column list for the fronts, used only for a symmetric or
nonsymmetric factorization with pivoting enabled.
\item
{\tt IVL *lowerblockIVL} : {\tt IVL} object that holds the
front-to-front coupling in $L$, used only for a
nonsymmetric factorization.
\item
{\tt IVL *upperblockIVL} : {\tt IVL} object that holds the
front-to-front coupling in $U$.
\item
{\tt SubMtx **p\_mtxDJJ} : a vector of pointers to diagonal submatrices.
\item
{\tt SubMtx **p\_mtxUJJ} : a vector of pointers to submatrices in U
that are on the block diagonal, used only during the factorization.
\item
{\tt SubMtx **p\_mtxUJN} : a vector of pointers to submatrices in U
that are off the block diagonal, used only during the factorization.
\item
{\tt SubMtx **p\_mtxLJJ} : a vector of pointers to submatrices in L
that are on the block diagonal, used only during a nonsymmetric
factorization.
\item
{\tt SubMtx **p\_mtxLNJ} : a vector of pointers to submatrices in L
that are off the block diagonal, used only during a nonsymmetric
factorization.
\item
{\tt I2Ohash *lowerhash} : pointer to a {\tt I2Ohash} hash table
for submatrices in $L$, used during the solves.
\item
{\tt I2Ohash *upperhash} : pointer to a {\tt I2Ohash} hash table
for submatrices in $U$, used during the solves.
\item
{\tt SubMtxManager *manager} : pointer to an object that manages
the instances of submatrices during the factors and solves.
\item
{\tt Lock *lock} : pointer to a {\tt Lock} lock used
in a multithreaded environment to ensure exlusive access while
allocating storage in the {\tt IV} and {\tt IVL} objects.
This is not used in a serial or MPI environment.
\item
{\tt int nlocks} : number of times the lock has been locked.
\item
{\tt PatchAndGo *info} : this is a pointer to an object that is
used by the {\tt Chv} object during the factorization of a front.
\end{itemize}
\par
One can query the properties of the front matrix object
using these simple macros.
\begin{itemize}
\item
{\tt FRONTMTX\_IS\_REAL(frontmtx)} is {\tt 1} if {\tt frontmtx}
has real entries and {\tt 0} otherwise.
\item
{\tt FRONTMTX\_IS\_COMPLEX(frontmtx)} is {\tt 1} if {\tt frontmtx}
has complex entries and {\tt 0} otherwise.
\item
{\tt FRONTMTX\_IS\_SYMMETRIC(frontmtx)} is {\tt 1} if {\tt frontmtx}
comes from a symmetric matrix or linear combination of symmetric
matrices, and {\tt 0} otherwise.
\item
{\tt FRONTMTX\_IS\_HERMITIAN(frontmtx)} is {\tt 1} if {\tt frontmtx}
comes from a Hermitian matrix or linear combination of Hermitian
matrices, and {\tt 0} otherwise.
\item
{\tt FRONTMTX\_IS\_NONSYMMETRIC(frontmtx)} is {\tt 1} if {\tt frontmtx}
comes from a nonsymmetric matrix or linear combination of nonsymmetric
matrices, and {\tt 0} otherwise.
\item
{\tt FRONTMTX\_IS\_DENSE\_FRONTS(frontmtx)} is {\tt 1}
if {\tt frontmtx}
comes from a direct factorization and so stores dense submatrices,
and {\tt 0} otherwise.
\item
{\tt FRONTMTX\_IS\_SPARSE\_FRONTS(frontmtx)} is {\tt 1}
if {\tt frontmtx} comes from an approximate factorization
and so stores sparse submatrices, and {\tt 0} otherwise.
\item
{\tt FRONTMTX\_IS\_PIVOTING(frontmtx)} is {\tt 1}
if pivoting was used during the factorization,
and {\tt 0} otherwise.
\item
{\tt FRONTMTX\_IS\_1D\_MODE(frontmtx)} is {\tt 1}
if the factor are still stored as a one-dimensional data
decomposition (i.e., the matrix has not yet been post-processed),
and {\tt 0} otherwise.
\item
{\tt FRONTMTX\_IS\_2D\_MODE(frontmtx)} is {\tt 1}
if the factor are stored as a two-dimensional data
decomposition (i.e., the matrix has been post-processed),
and {\tt 0} otherwise.
\end{itemize}
FrontMtx/doc/drivers.tex 0100644 0002055 0007177 00000011557 06571267173 0016646 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt DFrontMtx} object}
\label{section:DFrontMtx:drivers}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testGrid msglvl msgFile n1 n2 n3 maxzeros maxsize seed type
symmetryflag sparsityflag pivotingflag tau droptol
lockflag nrhs
\end{verbatim}
This driver program tests the serial {\tt FrontMtx\_factor()}
and {\tt FrontMtx\_solve()} methods for the linear system $AX = B$.
Use the script file {\tt do\_grid} for testing.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
{\tt n1} is the number of points in the first grid direction.
\item
{\tt n2} is the number of points in the second grid direction.
\item
{\tt n3} is the number of points in the third grid direction.
\item
{\tt maxzeros} is used to merge small fronts together into larger
fronts.
Look at the {\tt ETree} object for
the {\tt ETree\_mergeFronts\{One,All,Any\}()} methods.
\item
{\tt maxsize} is used to split large fronts into smaller
fronts.
See the {\tt ETree\_splitFronts()} method.
\item
The {\tt seed} parameter is a random number seed.
\item
The {\tt type} parameter specifies a real or complex linear system.
\begin{itemize}
\item
{\tt type = 1 (SPOOLES\_REAL)} for real,
\item
{\tt type = 2 (SPOOLES\_COMPLEX)} for complex.
\end{itemize}
\item
The {\tt symmetryflag} parameter specifies the symmetry of the matrix.
\begin{itemize}
\item
{\tt type = 0 (SPOOLES\_SYMMETRIC)} for $A$ real or complex symmetric,
\item
{\tt type = 1 (SPOOLES\_HERMITIAN)} for $A$ complex Hermitian,
\item
{\tt type = 2 (SPOOLES\_NONSYMMETRIC)}
\end{itemize}
for $A$ real or complex nonsymmetric.
\item
The {\tt sparsityflag} parameter signals a direct or approximate
factorization.
\begin{itemize}
\item
{\tt sparsityflag = 0 (FRONTMTX\_DENSE\_FRONTS)} implies a direct
factorization, the fronts will be stored as dense submatrices.
\item
{\tt sparsityflag = 1 (FRONTMTX\_SPARSE\_FRONTS)} implies an
approximate factorization.
The fronts will be stored as sparse submatrices, where
the entries in the triangular factors will be
subjected to a drop tolerance test --- if the magnitude of an entry
is {\tt droptol} or larger, it will be stored, otherwise it will be
dropped.
\end{itemize}
\item
The {\tt pivotingflag} parameter signals whether pivoting for
stability will be enabled or not.
\begin{itemize}
\item
If {\tt pivotingflag = 0 (SPOOLES\_NO\_PIVOTING)},
no pivoting will be done.
\item
If {\tt pivotingflag = 1 (SPOOLES\_PIVOTING)},
pivoting will be done to ensure that all
entries in $U$ and $L$ have magnitude less than {\tt tau}.
\end{itemize}
\item
The {\tt tau} parameter is an upper bound on the magnitude of the
entries in $L$ and $U$ when pivoting is enabled.
\item
The {\tt droptol} parameter is a lower bound on the magnitude of the
entries in $L$ and $U$ when the approximate factorization is enabled.
\item
When {\tt lockflag} is zero, the mutual exclusion lock for the
factor matrix is not enabled.
When {\tt lockflag} is not zero, the mutual exclusion lock is set.
This capability is here to test the overhead for the locks for a
serial factorization.
\item
The {\tt nrhs} parameter is the number of right hand sides to solve
as one block.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testQRgrid msglvl msgFile n1 n2 n3 seed nrhs type
\end{verbatim}
This driver program tests the serial {\tt FrontMtx\_QR\_factor()}
and {\tt FrontMtx\_QR\_solve()} methods for the least squares problem
$ \min_X \| F - A X \|_F$.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
Use {\tt msglvl = 1} for just timing output.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
{\tt n1} is the number of points in the first grid direction.
\item
{\tt n2} is the number of points in the second grid direction.
\item
{\tt n3} is the number of points in the third grid direction.
\item
The {\tt seed} parameter is a random number seed.
\item
The {\tt nrhs} parameter is the number of right hand sides to solve
as one block.
\item
The {\tt type} parameter specifies a real or complex linear system.
\begin{itemize}
\item
{\tt type = 1 (SPOOLES\_REAL)} for real,
\item
{\tt type = 2 (SPOOLES\_COMPLEX)} for complex.
\end{itemize}
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
FrontMtx/doc/intro.tex 0100644 0002055 0007177 00000023670 06571267173 0016322 0 ustar 00cleve compmath 0000040 0000006 \par
\chapter{{\tt FrontMtx}: Front matrix}
\par
The {\tt FrontMtx} object is used to solve linear systems of
equations by computing and using an $LU$ or $U^TDU$ factorization
of a matrix or matrix pencil.
The ``front'' in its name refers to a multifrontal formulation of
the factor matrices.
We don't actually use the multifrontal factorization method,
(rather a left-looking block general sparse algorithm), but the
storage of the factors and the computations are based on ``fronts''.
\par
There are four orthogonal axes that describe a front matrix.
\begin{itemize}
\item
The entries of the matrix can be double precision real or double
precision complex.
\item
The factorization could be from a real or complex symmetric matrix,
from a Hermitian matrix, or from a real or complex nonsymmetric matrix.
In addition, the matrix can be represented as $A + \sigma B$,
a linear combination of two matrices.
\item
The factorization can be performed with or without pivoting
for numerical stability.
\item
The factorization can be {\it direct} or {\it approximate}.
In the former case, the submatrices of the factors
are stored as dense matrices.
In the latter case, a user supplied drop tolerance is used to
decide which entries to keep in the factorization.
\end{itemize}
The front matrix can exist in three different environments:
serial, shared memory with parallelism enabled using Solaris or
POSIX threads, and distributed memory using MPI.
\par
This object computes, stores and solves linear
systems using three types of factorizations:
\begin{enumerate}
\item
$(A + \sigma B) = P(U^T + I)D(I + U)P^T$,
where $A$ and $B$ are symmetric or Hermitian matrices.
If pivoting is not enabled, $D$ is a diagonal matrix.
If pivoting is enabled, $D$ has $1 \times 1$ and $2 \times 2$
blocks on its diagonal.
$U$ is strictly upper triangular, and the nonzero structures
of $U$ and $D$ are disjoint.
$P$ is a permutation matrix.
If pivoting is not used, $P$ is the identity.
\item
$(A + \sigma B) = P(L + I)D(I + U)Q^T$ for a square
nonsymmetric matrix $A$ with symmetric structure.
$D$ is a diagonal matrix.
$U$ is strictly upper triangular.
$L$ is strictly lower triangular.
$P$ and $Q$ are permutation matrices.
If pivoting is not used, $P$ and $Q$ are the identity.
\item
$A = QR$ for square or rectangular $A$.
$Q$ is an orthogonal matrix that is not explicitly computed or
stored.
$R$ is upper triangular.
\end{enumerate}
\par
The factorization is performed using a one dimensional
decomposition of the global sparse matrix.
A typical {\it front} of the matrix is found the shaded portion of
the figure below.
\begin{center}
\makebox{
% \psfig{file=simple.eps,width=1.0in,height=1.00in}
\psfig{file=../../FrontMtx/doc/simple.eps,width=1.0in,height=1.00in}
}
\end{center}
A front is indivisible, it is found on one processor, and one processor
or one thread is responsible for its internal computations.
This is extremely important if we want to support pivoting for
stability, for deciding how to choose the pivot elements in the
front requires continuous up-to-date information about all the
entries in the front.
If a front were partitioned among threads or processors, the
cost of the communication to select pivot elements would be intolerable.
\par
Solving a nonsymmetric linear system
$(A + \sigma B)X = B$ is done in the following steps.
\begin{itemize}
\item Factor $(A + \sigma B) = P(L + I)D(I + U)Q^T$.
\item Solve $(L + I) Y = P^T B$
\item Solve $D Z = Y$
\item Solve $(I + U) W = Z$
\item $X = Q W$.
\end{itemize}
Release 1.0 used a one-dimensional data decomposition for the solves.
Release 2.0 has changed to a two-dimensional data decomposition to
increase the available parallelism.
After the factorization is computed using a one-dimensional data
decomposition, we post-process the matrix to obtain the
two-dimensional decomposition and then perform the forward and
backsolves.
\par
To use the front matrix object, the user need know about only the
initialization, factor, postprocess and solve methods.
% Let us take a quick look at the necessary data structures.
Here are the objects that a front matrix interacts with from the
user's or ``external'' perspective.
\begin{itemize}
\item
A sparse matrix $A$ that is to be factored is contain in a
{\tt InpMtx} object.
This object has been designed to be easy to use, to assemble
and permute matrix entries, and to be put into a convenient form to
be assembled into the front matrix.
It contains real or complex matrix entries.
\item
The linear combination $A + \sigma B$ is found in a {\tt Pencil}
object.
\item
The {\tt ETree} object contains the front
tree that governs the factorization and solve.
Inside this object are the dimensions of each front (the number of
internal and external rows and columns), the tree connectivity of
the fronts, and a map from each vertex to the front that contains
it as an internal row and column.
The {\tt FrontMtx} object contains a pointer to an {\tt ETree}
object, but it does not modify the object, nor does it own the
storage for the {\tt ETree} object.
Thus multiple front matrices can all point to the same {\tt ETree}
object simultaneously.
\item
An {\tt IVL} object ({\tt I}nteger {\tt V}ector {\tt L}ist),
contains the symbolic factorization.
For each front, it gives the list of internal and external rows and
columns, used to initialize a front prior to its factorization.
For a factorization without pivoting, this object stores the index
information for the factors, and so is used during the forward and
backsolves.
For a factorization with pivoting, the index information for a
front may change, so this object is not used during the solves.
As for the {\tt ETree} object, the symbolic factorization is
neither modified or owned by the front matrix object.
\item
Working storage is necessary during the factor and solves.
Instead of forcing one way of managing working storage,
(e.g., simple {\tt malloc} and {\tt free's} or a complex management
of one large work array), we have abstracted this behavior into two
objects.
\begin{itemize}
\item
The {\tt SubMtxManager} object manages instances of the {\tt
SubMtx} object, used to store submatrices of the factors and
working storage during the solves.
The {\tt FrontMtx} object contains a pointer to this manager
object, set upon initialization.
\item
The {\tt ChvManager} object manages instances of the {\tt
Chv} object, used to store fronts during the factorization.
This manager object is passed to the front matrix object in a call
to the factorization methods.
\end{itemize}
The user can easily override the behavior of these two
manager objects.
Our default supplied object are simple in their functionality
--- they are either wrappers around {\tt malloc()} and {\tt free()}
calls, or they manage a pool of available objects.
We measure their overhead and storage requirements during the
factorizations and solve.
\item
The right hand side $B$ and solution $X$ are stored in
{\tt DenseMtx} objects.
This object is a very simple wrapper around a dense matrix stored
either column major or row major.
(Our solves presently require the storage to be column major.)
The matrices $B$ and $X$ can be either global (as in a serial or
shared memory environment) or partitioned into local matrices
(as in a distributed implementation).
\item
A parallel factorization requires a map from fronts to threads
or processors,
and this functionality is supplied by an {\tt IV} ({\tt I}nteger
{\tt V}ector) object.
\item
The parallel solve requires a map from the submatrices to the
threads or processors.
This two-dimensional map is embodied in the {\tt SolveMap} object.
\end{itemize}
\par
To see how the front matrix object interacts with the other objects
in the {\bf SPOOLES} library, here is a brief description of the
objects ``internal'' to the front matrix, its factorization and solve.
\par
\begin{itemize}
\item
The {\tt Chv} object stores a front as a block {\it chevron}.
Updates to the front, its assembly of postponed data (when pivoting
is enabled) or aggregate data (in a parallel factorization),
and the factorization of the fully assembled front, take place
within the context of this object.
\item
The {\tt SubMtx} object is used to store a submatrix of the factor
matrices $D$, $L$ and $U$.
Once a front is factored it is split into one or more of these
submatrix objects.
After the factorization is complete, the data structures are
postprocessed to yield submatrices that contain the coupling
between fronts.
The working storage during the solves is also managed by {\tt
SubMtx} objects.
\item
Each submatrix represents the coupling between two fronts,
$I$ and $J$.
To enable rapid random access to these submatrices, we use a
{\tt I2Ohash} object that is a hash table whose keys are two
integers and whose data is a {\tt void *} pointer.
\item
The set of nonzero submatrices, i.e., the nonzero couplings
between two fronts, is kept in one or two {\tt IVL} objects.
This information is necessary for the factorization and forward and
backsolves.
\item
The factorization and solves require {\it lists} of fronts and
submatrices to manage assembly of data and synchronization.
We encapsulate these functions in the
{\tt ChvList} and {\tt SubMtxList} objects
that operate in serial, multithreaded and MPI environments.
\item
For a factorization with pivoting, the composition of a front
(its dimensions and the row and column indices) may change, so we
need additional data structures to store this information.
We use an {\tt IV} object to store the front size --- the number of
rows and columns that were eliminated when the front was factored.
We use an {\tt IVL} object to store the column indices --- internal
and external --- and if the matrix is nonsymmetric, another {\tt
IVL} object to store the row indices.
\item
If we have a multithreaded factorization and use pivoting or an
approximate factorization, we need exclusive access
to the {\tt IV} object that stores the final front size,
and the {\tt IVL} object(s) that store the final row and column
indices for the front.
Therefore we use a {\tt Lock} object to govern exclusive
access to these objects.
\end{itemize}
end{itemize}
Release 1.0 used a one-dimensional data decomposition for tFrontMtx/doc/main.tex 0100644 0002055 0007177 00000001172 06650656226 0016103 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\newcommand{\bnd}[1]{{\partial{#1}}}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\input psfig
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt FrontMtx} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt FrontMtx} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
FrontMtx/doc/proto.tex 0100644 0002055 0007177 00000156111 06650220231 0016305 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt FrontMtx} methods}
\label{section:FrontMtx:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt FrontMtx} object.
\par
\subsection{Basic methods}
\label{subsection:FrontMtx:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
FrontMtx * FrontMtx_new ( void ) ;
\end{verbatim}
\index{FrontMtx_new@{\tt FrontMtx\_new()}}
This method simply allocates storage for the {\tt FrontMtx} structure
and then sets the default fields by a call to
{\tt FrontMtx\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_setDefaultFields ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_setDefaultFields@{\tt FrontMtx\_setDefaultFields()}}
The structure's fields are set to default values:
{\tt nfront}, {\tt neqns}, {\tt nentD}, {\tt nentL}, {\tt nentU} and
{\tt nlocks} are set to zero.
Five scalars are set to their default values,
\begin{center}
\begin{tabular}{lcl}
{\tt type} & = & {\tt SPOOLES\_REAL} \\
{\tt symmetryflag} & = & {\tt SPOOLES\_SYMMETRIC} \\
{\tt sparsityflag} & = & {\tt FRONTMTX\_DENSE\_FRONTS} \\
{\tt pivotingflag} & = & {\tt SPOOLES\_NO\_PIVOTING} \\
{\tt dataMode} & = & {\tt FRONTMTX\_1D\_MODE}
\end{tabular}
\end{center}
and the structure's pointers are set to {\tt NULL}.
% {\tt tree},
% {\tt frontETree},
% {\tt symbfacIVL},
% {\tt frontsizesIV},
% {\tt rowadjIVL},
% {\tt coladjIVL},
% {\tt lowerblockIVL},
% {\tt upperblockIVL},
% {\tt p\_mtxDJJ},
% {\tt p\_mtxUJJ},
% {\tt p\_mtxUJN},
% {\tt p\_mtxLJJ},
% {\tt p\_mtxLNJ},
% {\tt lowerhash},
% {\tt upperhash} and
% {\tt lock}
% are set to {\tt NULL} .
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_clearData ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_clearData@{\tt FrontMtx\_clearData()}}
This method clears the object and free's any owned data
by invoking the {\tt \_clearData()} methods for its internal
{\tt IV} and {\tt IVL} objects, ({\it not} including
the {\tt frontETree} and {\tt symbfacIVL} objects that are not
owned by this {\tt FrontMtx} object).
If the {\tt lock} pointer is not {\tt NULL}, the lock is destroyed
via a call to {\tt Lock\_free()} and its storage is then
free'd.
There is a concluding call to {\tt FrontMtx\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_free ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_free@{\tt FrontMtx\_free()}}
This method releases any storage by a call to
{\tt FrontMtx\_clearData()} and then free the space for {\tt frontmtx}.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Instance methods}
\label{subsection:FrontMtx:proto:instance}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_nfront ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_nfront@{\tt FrontMtx\_nfront()}}
This method returns the number of fronts in the matrix.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_neqns ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_neqns@{\tt FrontMtx\_neqns()}}
This method returns the number of equations in the matrix.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Tree * FrontMtx_frontTree ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_frontTree@{\tt FrontMtx\_frontTree()}}
This method returns the {\tt Tree} object for the fronts.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_initialFrontDimensions ( FrontMtx *frontmtx, int J,
int *pnD, int *pnL, int *pnU, int *pnbytes ) ;
\end{verbatim}
\index{FrontMtx_initialFrontDimensions@{\tt FrontMtx\_initialFrontDimensions()}}
This method fills the four pointer arguments with the number of
internal rows and columns, number of rows in the lower block,
number of columns in the upper block, and number of bytes for a
{\tt Chv} object to hold the front.
in front {\tt J}.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
or if {\tt J} is not in {\tt [0,nfront)},
or if any of the four pointer arguments are NULL,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_frontSize ( FrontMtx *frontmtx, int J ) ;
\end{verbatim}
\index{FrontMtx_frontSize@{\tt FrontMtx\_frontSize()}}
This method returns the number of internal rows and columns
in front {\tt J}.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt frontsizesIV} is {\tt NULL},
or if {\tt J} is not in {\tt [0,nfront)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_setFrontSize ( FrontMtx *frontmtx, int J, int size ) ;
\end{verbatim}
\index{FrontMtx_setFrontsize@{\tt FrontMtx\_setFrontSize()}}
This method sets the number of internal rows and columns
in front {\tt J} to be {\tt size}.
This method is used during factorizations with pivoting enabled
since we cannot tell ahead of time how many rows and columns in a
front will be eliminated.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt frontsizesIV} is {\tt NULL},
or if {\tt J} is not in {\tt [0,nfront)},
or if ${\tt size} < 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_columnIndices ( FrontMtx *frontmtx, int J,
int *pncol, int **pindices ) ;
\end{verbatim}
\index{FrontMtx_columnIndices@{\tt FrontMtx\_columnIndices()}}
This method fills {\tt *pncol} with the number of columns
and {\tt *pindices} with a pointer to the column indices for front
{\tt J}.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt pncol} or {\tt pindices} is {\tt NULL},
or if {\tt J} is not in {\tt [0,nfront)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_rowIndices ( FrontMtx *frontmtx, int J,
int *pnrow, int **pindices ) ;
\end{verbatim}
\index{FrontMtx_rowIndices@{\tt FrontMtx\_rowIndices()}}
This method fills {\tt *pnrow} with the number of rows
and {\tt *pindices} with a pointer to the row indices for front
{\tt J}.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt pnrow} or {\tt pindices} is {\tt NULL},
or if {\tt J} is not in {\tt [0,nfront)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
SubMtx * FrontMtx_diagMtx ( FrontMtx *frontmtx, int J ) ;
\end{verbatim}
\index{FrontMtx_diagMtx@{\tt FrontMtx\_diagMtx()}}
This method returns a pointer to the object that contains
submatrix $D_{J,J}$.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
or if {\tt J} is not in {\tt [0,nfront)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
SubMtx * FrontMtx_upperMtx ( FrontMtx *frontmtx, int J, int K ) ;
\end{verbatim}
\index{FrontMtx_upperMtx@{\tt FrontMtx\_upperMtx()}}
This method returns a pointer to the object that contains
submatrix $U_{J,K}$.
If $K = nfront$, then the object containing $U_{J,\bnd{J}}$ is
returned.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
or if {\tt J} is not in {\tt [0,nfront)},
or if {\tt K} is not in {\tt [0,nfront]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
SubMtx * FrontMtx_lowerMtx ( FrontMtx *frontmtx, int K, int J ) ;
\end{verbatim}
\index{FrontMtx_lowerMtx@{\tt FrontMtx\_lowerMtx()}}
This method returns a pointer to the object that contains
submatrix $L_{K,J}$.
If $K = nfront$, then the object containing $L_{\bnd{J},J}$ is
returned.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
or if {\tt J} is not in {\tt [0,nfront)},
or if {\tt K} is not in {\tt [0,nfront]},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_lowerAdjFronts ( FrontMtx *frontmtx, int J,
int *pnadj, int **padj ) ;
\end{verbatim}
\index{FrontMtx_lowerAdjFronts@{\tt FrontMtx\_lowerAdjFronts()}}
This method fills {\tt *pnadj} with the number of fronts adjacent to
{\tt J} in $L$ and fills {\tt *padj} with a pointer to the first
entry of a vector containing the ids of the adjacent fronts.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt pnadj} or {\tt ppadj} is {\tt NULL},
or if {\tt J} is not in {\tt [0,nfront)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_upperAdjFronts ( FrontMtx *frontmtx, int J,
int *pnadj, int **padj ) ;
\end{verbatim}
\index{FrontMtx_upperAdjFronts@{\tt FrontMtx\_upperAdjFronts()}}
This method fills {\tt *pnadj} with the number of fronts adjacent to
{\tt J} in $U$ and fills {\tt *padj} with a pointer to the first
entry of a vector containing the ids of the adjacent fronts.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt pnadj} or {\tt ppadj} is {\tt NULL},
or if {\tt J} is not in {\tt [0,nfront)},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_nLowerBlocks ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_nLowerBlocks@{\tt FrontMtx\_nLowerBlocks()}}
This method returns the number of nonzero $L_{K,J}$ submatrices.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_nUpperBlocks ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_nUpperBlocks@{\tt FrontMtx\_nUpperBlocks()}}
This method returns the number of nonzero $U_{J,K}$ submatrices.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IVL * FrontMtx_upperBlockIVL ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_upperBlockIVL@{\tt FrontMtx\_upperBlockIVL()}}
This method returns a pointer to the {\tt IVL} object that holds
the upper blocks.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IVL * FrontMtx_lowerBlockIVL ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_lowerBlockIVL@{\tt FrontMtx\_lowerBlockIVL()}}
This method returns a pointer to the {\tt IVL} object that holds
the lower blocks.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initialization methods}
\label{subsection:FrontMtx:proto:initialization}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_init ( FrontMtx *frontmtx, ETree *frontETree,
IVL *symbfacIVL, int type, int symmetryflag, int sparsityflag,
int pivotingflag, int lockflag, int myid, IV *ownersIV,
SubMtxManager *manager, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_init@{\tt FrontMtx\_init()}}
This method initializes the object, allocating and initializing the
internal objects as necessary.
See the previous section on data structures for the meanings of the
{\tt type}, {\tt symmetryflag}, {\tt sparsityflag} and
{\tt pivotingflag} parameters.
The {\tt lockflag} parameter has the following meaning.
\begin{itemize}
\item {\tt 0} --- the {\tt Lock} object is not allocated
or initialized.
\item {\tt 1} --- the {\tt Lock} object is allocated and initialized
to synchronize only threads in this process.
\item {\tt 2} --- the {\tt Lock} object is allocated and initialized
to synchronize threads in this and other processes.
\end{itemize}
If {\tt lockflag} is not {\tt 0}, the lock is allocated and
initialized.
\par
This method allocates as much storage as possible.
When pivoting is not enabled and dense fronts are stored
the structure of the factor matrix is fixed and given by the
{\tt frontETree} object.
The diagonal $D_{J,J}$,
upper triangular $U_{J,J}$ and $U_{J,\bnd{J}}$ matrices,
and lower triangular $L_{J,J}$ and $L_{\bnd{J},J}$ matrices
are allocated.
\par
The {\tt myid} and {\tt ownersIV} parameters are used in
a distributed environment where we specify which process
owns each front. When we can preallocate data structures
(when there is no pivoting and dense fronts are stored) we
need each process to determine what parts of the data it
can allocate and set up. In a serial or multithreaded
environment, use {\tt ownersIV = NULL}.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt frontETree} or {\tt symbfacIVL} is {\tt NULL},
or if {\tt type}, {\tt symmetryflag}, {\tt sparsityflag}
or {\tt pivotingflag} are not valid,
or if {\tt lockflag} is not {\tt 0}, {\tt 1} or {\tt 2},
or if {\tt ownersIV} is not {\tt NULL} and {\tt myid < 0},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility Factorization methods}
\label{subsection:FrontMtx:proto:utility-factor}
\par
The following methods are called by all the factor methods
--- serial, multithreaded and MPI.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_initializeFront ( FrontMtx *frontmtx, Chv *frontJ, int J ) ;
\end{verbatim}
\index{FrontMtx_initializeFront@{\tt FrontMtx\_initializeFront()}}
This method is called to initialize a front.
The number of internal rows and columns is found from the front
{\tt ETree} object and the row and column indices are obtained
from the symbolic factorization {\tt IVL} object.
The front {\tt Chv} object is initialized via a call to
{\tt Chv\_init()}, and the column indices and row indices (when
nonsymemtric) are copied.
Finally the front's entries are zeroed via a call to
{\tt Chv\_zero()}.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
char FrontMtx_factorVisit ( FrontMtx *frontmtx, Pencil *pencil, int J,
int myid, int owners[], Chv *fronts[], int lookahead, double tau,
double droptol, char status[], IP *heads[], IV *pivotsizesIV, DV *workDV,
int parent[], ChvList *aggList, ChvList *postList, ChvManager *chvmanager,
int stats[], double cpus[], int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_factorVisit@{\tt FrontMtx\_factorVisit()}}
This method is called during the serial, multithreaded and MPI
factorizations when front {\tt J} is visited during the bottom-up
traversal of the tree.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Chv * FrontMtx_setupFront ( FrontMtx *frontmtx, Pencil *pencil, int J,
int myid, int owners[], ChvManager *chvmanager,
double cpus[], int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_setupFront@{\tt FrontMtx\_setupFront()}}
This method is called by {\tt FrontMtx\_visitFront()} to initialize
the front's {\tt Chv} object and load original entries if applicable.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IP ** FrontMtx_factorSetup ( FrontMtx *frontmtx, IV *frontOwnersIV,
int myid, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_factorSetup@{\tt FrontMtx\_factorSetup()}}
This method is called by the serial, multithreaded and MPI
factorizations methods to initialize a data structure that contains
the front-to-front updates that this thread or processor will perform.
The data structure is a vector of pointers to {\tt IP} objects that
holds the heads of list of updates for each front.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int * FrontMtx_nactiveChild ( FrontMtx *frontmtx, char *status, int myid ) ;
\end{verbatim}
\index{FrontMtx_nactiveChild@{\tt FrontMtx\_nactiveChild()}}
This method is called by the multithreaded and MPI factorizations
to create an integer vector that contains the number of active
children of each front with respect to this thread or processor.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt status} is {\tt NULL},
or if ${\tt myid} < 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Ideq * FrontMtx_setUpDequeue ( FrontMtx *frontmtx, int owners[], int myid,
char status[], IP *heads[], char activeFlag,
char inactiveFlag, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_nactiveChild@{\tt FrontMtx\_nactiveChild()}}
This method is called by the multithreaded and MPI factorizations
to create and return an integer dequeue object to schedule the bottom-up
traversal of the front tree.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt owners} or {\tt status} is {\tt NULL},
or if ${\tt myid} < 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_loadActiveLeaves ( FrontMtx *frontmtx, char status[],
char activeFlag, Ideq *dequeue ) ;
\end{verbatim}
\index{FrontMtx_loadActiveLeaves@{\tt FrontMtx\_loadActiveLeaves()}}
This method is called by the multithreaded and MPI factor and solve
methods to load the dequeue with the active leaves in the front
tree with respect to the thread or processor.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ChvList * FrontMtx_postList ( FrontMtx *frontmtx, IV *frontOwnersIV,
int lockflag ) ;
\end{verbatim}
\index{FrontMtx_postList@{\tt FrontMtx\_postList()}}
This method is called by the multithreaded and MPI factor
methods to create and return a list object to hold postponed
chevrons and help synchronize the factorization.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
ChvList * FrontMtx_aggregateList ( FrontMtx *frontmtx,
IV *frontOwnersIV, int lockflag ) ;
\end{verbatim}
\index{FrontMtx_aggregateList@{\tt FrontMtx\_aggregateList()}}
This method is called by the multithreaded factor
methods to create and return a list object to hold aggregate
fronts and help synchronize the factorization.
There is an analogous {\tt FrontMtx\_MPI\_aggregateList()} method
for the MPI environment.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt frontOwnersIV} is {\tt NULL},
or if {\tt lockflag} is invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_loadEntries ( Chv *frontJ, DPencil *pencil,
int msglvl, FILE *msgFile) ;
\end{verbatim}
\index{FrontMtx_loadEntries@{\tt FrontMtx\_loadEntries()}}
This method is called to load the original entries into a front.
\par \noindent {\it Error checking:}
If {\tt frontJ} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_update ( FrontMtx *frontmtx, Chv *frontJ, IP *heads[],
char status[], DV *tempDV, int msglvl, FILE *msgFile) ;
\end{verbatim}
\index{FrontMtx_update@{\tt FrontMtx\_update()}}
This method is called to update the current front stored in {\tt frontJ}
from all descendent fronts.
(For the multithreaded and MPI factorizations, updates come from
all owned descendent fronts.)
The {\tt heads[]} vector maintains the linked list of completed
fronts that still have ancestors to update.
The {\tt tempDV} object is used as working storage by the {\tt Chv}
update methods, its size is automatically resized.
When pivoting is disabled, the maximum size of the {\tt tempDV}
object is three times the maximum number of internal rows and columns
in a front.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Chv * FrontMtx_assemblePostponedData ( FrontMtx *frontmtx, Chv *frontJ,
ChvList *postponedlist, ChvManager *chvmanager, int *pndelay) ;
\end{verbatim}
\index{FrontMtx_assemblePostponedData@{\tt FrontMtx\_assemblePostponedData()}}
This method is called to assemble any postponed data
from its children fronts into the current front.
{\tt frontJ} contains the updates from the descendents.
Any postponed data is found in the list in {\tt postponedlist}.
If this list is empty, a new front is created to hold the aggregate
updates and the postponed data, and
the {\tt chvmanager} object receives the aggregate and postponed {\tt
Chv} objects.
The number of delayed rows and columns is returned in {\tt *pndelay}
--- this is used during the factorization of the front that
follows immediately.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
FrontMtx_storePostponedData ( FrontMtx *frontmtx, Chv *frontJ,
int npost, int K, ChvList *postponedlist, ChvManager *chvmanager ) ;
\end{verbatim}
\index{FrontMtx_storePostponedData@{\tt FrontMtx\_storePostponedData()}}
This method is used to store any postponed rows and columns from
the current front {\tt frontJ} into a {\tt Chv} object obtained
from the {\tt chvmanager} object and place it into the list of
postponed objects for {\tt K}, its parent, found in the {\tt
postponedlist} object.
The {\tt frontJ} object is unchanged by this method.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
FrontMtx_storeFront ( FrontMtx *frontmtx, Chv *frontJ, IV *pivotsizesIV,
double droptol, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_storeFront@{\tt FrontMtx\_storeFront()}}
This method is used to store the eliminated rows and columns of the
current front {\tt frontJ} into the factor matrix storage.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Serial Factorization method}
\label{subsection:FrontMtx:proto:factor}
There are two factorization methods: the first is for factoring
a matrix $A$ stored in a {\tt DInpMtx} object, the second factors
a linear combination $A + \sigma B$ stored in a {\tt DPencil} object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Chv * FrontMtx_factorInpMtx ( FrontMtx *frontmtx, InpMtx *inpmtx, double tau,
double droptol, ChvManager *chvmanager, int *perror,
double cpus[], int stats[], int msglvl, FILE *msgFile ) ;
Chv * FrontMtx_factorPencil ( FrontMtx *frontmtx, Pencil *pencil, double tau,
double droptol, ChvManager *chvmanager, int *perror,
double cpus[], int stats[], int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_factorInpMtx@{\tt FrontMtx\_factorInpMtx()}}
\index{FrontMtx_factorPencil@{\tt FrontMtx\_factorPencil()}}
These two serial factorization methods factor a matrix $A$
(stored in {\tt inpmtx}) or
a matrix pencil $A + \sigma B$ (stored in {\tt pencil}).
The {\tt tau} parameter is used when pivoting is enabled, each
entry in $U$ and $L$ (when nonsymmetric) will have magnitude less
than or equal to {\tt tau}.
The {\tt droptol} parameter is used when the fronts are stored in
a sparse format, each entry in $U$ and $L$ (when nonsymmetric)
will have magnitude greater than or equal to {\tt droptol}.
\par
The return value is a pointer to the first element in a list of
{\tt Chv} objects that contain the rows and columns that were
not able to be eliminated.
In all present cases, this should be {\tt NULL}; we have left this
return value as a hook to future factorizations via stages.
The {\tt perror} parameter is an address that is filled with an
error code on return.
If the factorization has completed, then {\tt *perror} is a
negative number.
If {\tt *perror} is in the range {\tt [0,nfront)}, then an error
has been detected at front {\tt *perror}.
On return, the {\tt cpus[]} vector is filled with the following
information.
\begin{itemize}
\item
{\tt cpus[0]} --- time spent initializing the fronts.
\item
{\tt cpus[1]} --- time spent loading the original entries.
\item
{\tt cpus[2]} --- time spent accumulating updates from descendents.
\item
{\tt cpus[3]} --- time spent assembling postponed data.
\item
{\tt cpus[4]} --- time spent to factor the fronts.
\item
{\tt cpus[5]} --- time spent to extract postponed data.
\item
{\tt cpus[6]} --- time spent to store the factor entries.
\item
{\tt cpus[7]} --- miscellaneous time.
\item
{\tt cpus[8]} --- total time in the method.
\end{itemize}
On return, the {\tt stats[]} vector is filled with the following
information.
\begin{itemize}
\item
{\tt stats[0]} --- number of pivots.
\item
{\tt stats[1]} --- number of pivot tests.
\item
{\tt stats[2]} --- number of delayed rows and columns.
\item
{\tt stats[3]} --- number of entries in $D$.
\item
{\tt stats[4]} --- number of entries in $L$.
\item
{\tt stats[5]} --- number of entries in $U$.
\end{itemize}
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt pencil}, {\tt cpus} or {\tt stats}
is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{QR factorization utility methods}
\label{subsection:FrontMtx:proto:utilityQR}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_QR_setup ( FrontMtx *frontmtx, InpMtx *mtxA, IVL **prowsIVL,
int **pfirstnz, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_QR_setup@{\tt FrontMtx\_QR\_setup()}}
This method sets up the {\tt rowsIVL} and {\tt firstnz[]} data
structures.
The address of {\tt rowsIVL} is placed in {\tt *prowsIVL}
and the address of {\tt firstnz} is placed in {\tt *pfirstnz}.
List {\tt J} of {\tt rowsIVL} contains the rows of $A$ that will be
assembled into front {\tt J}.
The leading column with a nonzero entry in row {\tt j} is found in
{\tt firstnz[j]}.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt mtxA}, {\tt prowsIVL} or {\tt pfirstnz}
is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_QR_factorVisit ( FrontMtx *frontmtx, int J, InpMtx *mtxA,
IVL *rowsIVL, int firstnz[], ChvList *updList, ChvManager *chvmanager,
char status[], int colmap[], DV *workDV, double cpus[],
double *pfacops, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_QR_factorVisit@{\tt FrontMtx\_QR\_factorVisit()}}
This method visits front {\tt J} during the $QR$ factorization.
The number of operations to reduce the staircase matrix to upper
trapezoidal or triangular form is incremented in {\tt *pfacops}.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt mtxA}, {\tt rowsIVL}, {\tt firstnz},
{\tt updlist}, {\tt chvmanager}, {\tt status}, {\tt colmap},
{\tt workDV}, {\tt cpus} or {\tt pfacops} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
A2 * FrontMtx_QR_assembleFront ( FrontMtx *frontmtx, int J, InpMtx *mtxA,
IVL *rowsIVL, int firstnz[], int colmap[], Chv *firstchild,
DV *workDV, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_QR_assembleFront@{\tt FrontMtx\_QR\_assembleFront()}}
This method creates an {\tt A2} object to hold the front,
assembles any original rows of $A$ and any update
matrices from the children into the front,
and then returns the front.
The rows and update matrices are assembled into staircase form,
so no subsequent permutations of the rows is necessary.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt mtxA}, {\tt rowsIVL}, {\tt firstnz},
{\tt colmap} or {\tt workDV} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_QR_storeFront ( FrontMtx *frontmtx, int J, A2 *frontJ,
int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_QR_storeFront@{\tt FrontMtx\_QR\_storeFront()}}
This method takes as input {\tt frontJ}, the front in trapezoidal
or triangular form.
It scales the strict upper triangle or trapezoid by the diagonal
entries, then squares the diagonal entries.
(This transforms $R^TR$ into $(U^T + I)D(I+U)$
or $R^HR$ into $(U^H + I)D(I+U)$ for our solves.)
It then stores the entries into the factor matrix.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt frontJ} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Chv * FrontMtx_QR_storeUpdate ( FrontMtx *frontmtx, int J, A2 *frontJ,
ChvManager *chvmanager, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_QR_storeUpdate@{\tt FrontMtx\_QR\_storeUpdate()}}
This method takes as input {\tt frontJ}, the front in trapezoidal
or triangular form.
It extracts the update matrix, stores the entries in a {\tt Chv} object,
and returns the {\tt Chv} object.
entries, then squares the diagonal entries.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt frontJ} or {\tt chvmanager} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Serial $QR$ Factorization method}
\label{subsection:FrontMtx:proto:factorQR}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_QR_factor ( FrontMtx *frontmtx, InpMtx *mtxA,
ChvManager *chvmanager, double cpus[],
double *pfacops, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_QR_factor@{\tt FrontMtx\_QR\_factor()}}
This method computes the
$(U^T+I)D(I+U)$ factorization of $A^TA$ if $A$ is real
or
$(U^H+I)D(I+U)$ factorization of $A^HA$ if $A$ is complex.
The {\tt chvmanager} object manages the working storage.
On return, the {\tt cpus[]} vector is filled as follows.
\begin{itemize}
\item
{\tt cpus[0]} -- setup time, time to compute the {\tt rowsIVL}
and {\tt firstnz[]} objects
\item
{\tt cpus[1]} -- time to initialize and load the staircase matrices
\item
{\tt cpus[2]} -- time to factor the matrices
\item
{\tt cpus[3]} -- time to scale and store the factor entries
\item
{\tt cpus[4]} -- time to store the update entries
\item
{\tt cpus[5]} -- miscellaneous time
\item
{\tt cpus[6]} -- total time
\end{itemize}
On return, {\tt *pfacops} contains the number of floating point
operations done by the factorization.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt frontJ} or {\tt chvmanager} is {\tt NULL},
or if {\tt msglvl > 0} and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Postprocessing methods}
\label{subsection:FrontMtx:proto:postprocess}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_postProcess ( FrontMtx *frontmtx, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_postProcess@{\tt FrontMtx\_postProcess()}}
This method does post-processing chores after the factorization is
complete.
If pivoting was enabled, the method
permutes the row and column adjacency objects,
permutes the lower and upper matrices,
and updates the block adjacency objects.
The chevron submatrices $L_{\bnd{J},J}$ and $U_{J,\bnd{J}}$
are split into $L_{K,J}$ and $U_{J,K}$
where $K \cap \bnd{J} \ne \emptyset$.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
or if {\tt msglvl} > 0 and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_permuteUpperAdj ( FrontMtx *frontmtx,
int msglvl, FILE *msgFile ) ;
void FrontMtx_permuteLowerAdj ( FrontMtx *frontmtx,
int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_permuteUpperAdj@{\tt FrontMtx\_permuteUpperAdj()}}
\index{FrontMtx_permuteLowerAdj@{\tt FrontMtx\_permuteLowerAdj()}}
These methods are called during the postprocessing step,
where they permute the upper and lower adjacency structures so that
vertices in $\bnd{J}$ are in ascending order with respect to the
indices in $K \cup \bnd{K}$, where $K$ is the parent of $J$.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
or if {\tt msglvl} > 0 and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_permuteUpperMatrices ( FrontMtx *frontmtx,
int msglvl, FILE *msgFile ) ;
void FrontMtx_permuteLowerMatrices ( FrontMtx *frontmtx,
int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_permuteUpperMatrices@{\tt FrontMtx\_permuteUpperMatrices()}}
\index{FrontMtx_permuteLowerMatrices@{\tt FrontMtx\_permuteLowerMatrices()}}
These methods are called during the postprocessing step,
where they permute the upper $U_{J,\bnd{J}}$ and lower $L_{\bnd{J},J}$
submatrices so that
the columns in $U_{J,\bnd{J}}$ and rows in $L_{\bnd{J},J}$
are in ascending order with the columns and rows of the final
matrix.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
or if {\tt msglvl} > 0 and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_splitUpperMatrices ( FrontMtx *frontmtx, int msglvl, FILE *msgFile ) ;
void FrontMtx_splitLowerMatrices ( FrontMtx *frontmtx, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_splitUpperMatrices@{\tt FrontMtx\_splitUpperMatrices()}}
\index{FrontMtx_splitLowerMatrices@{\tt FrontMtx\_splitLowerMatrices()}}
These methods are called during the postprocessing step,
where they split the chevron submatrices $L_{\bnd{J},J}$
and $U_{J,\bnd{J}}$ into $L_{K,J}$ and $U_{J,K}$
where $K \cap \bnd{J} \ne \emptyset$.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
or if {\tt msglvl} > 0 and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility Solve methods}
\label{subsection:FrontMtx:proto:utility-solve}
\par
The following methods are called by all the solve methods
--- serial, multithreaded and MPI.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
SubMtx ** FrontMtx_loadRightHandSide ( FrontMtx *frontmtx, DenseMtx *mtxB,
int owners[], int myid, SubMtxManager *mtxmanager,
int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_loadRightHandSide@{\tt FrontMtx\_loadRightHandSide()}}
This method creates and returns a vector of pointers to {\tt
SubMtx} objects that hold pointers to the right hand side
submatrices owned by the thread or processor.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_forwardVisit ( FrontMtx *frontmtx, int J, int nrhs,
int *owners, int myid, SubMtxManager *mtxmanager, SubMtxList *aggList,
SubMtx *p_mtx[], char frontIsDone[], IP *heads[], SubMtx *p_agg[],
char status[], int msglvl, FILE *msgFile) ;
\end{verbatim}
\index{FrontMtx_forwardVisit@{\tt FrontMtx\_forwardVisit()}}
This method is used to visit front {\tt J} during the forward solve,
$(U^T + I)Y = B$, $(U^H + I)Y = B$ or $(L + I)Y = B$.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_diagonalVisit ( FrontMtx *frontmtx, int J, int owners[],
int myid, SubMtx *p_mtx[], char frontIsDone[], SubMtx *p_agg[],
int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_diagonalVisit@{\tt FrontMtx\_diagonalVisit()}}
This method is used to visit front {\tt J} during the diagonal solve,
$DZ = Y$.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_backwardVisit ( FrontMtx *frontmtx, int J, int nrhs,
int *owners, int myid, SubMtxManager *mtxmanager, SubMtxList *aggList,
SubMtx *p_mtx[], char frontIsDone[], IP *heads[], SubMtx *p_agg[],
char status[], int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_backwardVisit@{\tt FrontMtx\_backwardVisit()}}
This method is used to visit front {\tt J} during the backward solve,
$(U + I)Y = B$.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_storeSolution ( FrontMtx *frontmtx, int owners[], int myid,
SubMtxManager *mtxmanager, SubMtx *p_mtx[],
DenseMtx *mtxX, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_storeSolution@{\tt FrontMtx\_storeSolution()}}
This method stores the solution in the {\tt solmtx} dense matrix object.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IP ** FrontMtx_forwardSetup ( FrontMtx *frontmtx, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_forwardSetup@{\tt FrontMtx\_forwardSetup()}}
This method is used to set up a data structure of {\tt IP} objects
that hold the updates of the form
$Y_J := Y_J - U_{I,J}^T X_I$,
$Y_J := Y_J - U_{I,J}^H X_I$ or
$Y_J := Y_J - L_{J,I} X_I$
that will be performed by this thread or processor.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IP ** FrontMtx_backwardSetup ( FrontMtx *frontmtx, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_backwardSetup@{\tt FrontMtx\_backwardSetup()}}
This method is used to set up a data structure of {\tt IP} objects
that hold the updates of the form
$Z_J := Z_J - U_{J,K} X_K$
that will be performed by this thread or processor.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_loadActiveRoots ( FrontMtx *frontmtx, char status[],
char activeFlag, Ideq *dequeue ) ;
\end{verbatim}
\index{FrontMtx_loadActiveRoots@{\tt FrontMtx\_loadActiveRoots()}}
This method loads the active roots for a thread or a processor into
the dequeue for the backward solve.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Serial Solve method}
\label{subsection:FrontMtx:proto:solve-serial}
\par
\begin{enumerate}
%=======================================================================
\item
\begin{verbatim}
void FrontMtx_solve ( FrontMtx *frontmtx, DenseMtx *mtxX, DenseMtx *mtxB,
SubMtxManager *mtxmanager, double cpus[], int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_solve@{\tt FrontMtx\_solve()}}
This method is used to solve one of three linear systems of equations
---
$(U^T + I)D(I + U) X = B$,
$(U^H + I)D(I + U) X = B$ or
$(L + I)D(I + U) X = B$.
Entries of $B$ are {\it read} from {\tt mtxB} and
entries of $X$ are written to {\tt mtxX}.
Therefore, {\tt mtxX} and {\tt mtxB} can be the same object.
(Note, this does not hold true for an MPI factorization with pivoting.)
The {\tt mtxmanager} object manages the working storage using the solve.
On return the {\tt cpus[]} vector is filled with the following.
\begin{itemize}
\item
{\tt cpus[0]} --- set up the solves
\item
{\tt cpus[1]} --- fetch right hand side and store solution
\item
{\tt cpus[2]} --- forward solve
\item
{\tt cpus[3]} --- diagonal solve
\item
{\tt cpus[4]} --- backward solve
\item
{\tt cpus[5]} --- total time in the method.
\end{itemize}
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt mtxB} or {\tt cpus}
is {\tt NULL},
or if {\tt msglvl} > 0 and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%=======================================================================
\end{enumerate}
\par
\subsection{Serial $QR$ Solve method}
\label{subsection:FrontMtx:proto:QRsolve-serial}
\par
\begin{enumerate}
%=======================================================================
\item
\begin{verbatim}
void FrontMtx_QR_solve ( FrontMtx *frontmtx, InpMtx *mtxA, DenseMtx *mtxX,
DenseMtx *mtxB, SubMtxManager *mtxmanager,
double cpus[], int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_QR_solve@{\tt FrontMtx\_QR\_solve()}}
This method is used to minimize $\|B - AX\|_F$, where
$A$ is stored in {\tt mtxA},
$B$ is stored in {\tt mtxB},
and $X$ will be stored in {\tt mtxX}.
The {\tt frontmtx} object contains a
$(U^T+I)D(I+U)$ factorization of $A^TA$ if $A$ is real
or
$(U^H+I)D(I+U)$ factorization of $A^HA$ if $A$ is complex.
We solve the seminormal equations
$(U^T+I)D(I+U)X = A^TB$ or $(U^H+I)D(I+U)X = A^HB$
for $X$.
The {\tt mtxmanager} object manages the working storage
used in the solves.
On return the {\tt cpus[]} vector is filled with the following.
\begin{itemize}
\item
{\tt cpus[0]} --- set up the solves
\item
{\tt cpus[1]} --- fetch right hand side and store solution
\item
{\tt cpus[2]} --- forward solve
\item
{\tt cpus[3]} --- diagonal solve
\item
{\tt cpus[4]} --- backward solve
\item
{\tt cpus[5]} --- total time in the solve method.
\item
{\tt cpus[6]} --- time to compute $A^TB$ or $A^HB$.
\item
{\tt cpus[7]} --- total time.
\end{itemize}
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt mtxA}, {\tt mtxX}, {\tt mtxB} or {\tt cpus}
is {\tt NULL},
or if {\tt msglvl} > 0 and {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%=======================================================================
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:FrontMtx:proto:utility}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * FrontMtx_colmapIV ( FrontMtx *frontmtx ) ;
IV * FrontMtx_rowmapIV ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_colmapIV@{\tt FrontMtx\_colmapIV()}}
\index{FrontMtx_rowmapIV@{\tt FrontMtx\_rowmapIV()}}
These methods construct and return an {\tt IV} object that map the
rows and columns to the fronts that contains them.
\par \noindent {\it Error checking:}
None presently.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * FrontMtx_ownedRowsIV ( FrontMtx *frontmtx, int myid, IV *ownersIV,
int msglvl, FILE *msgFile ) ;
IV * FrontMtx_ownedColumnsIV ( FrontMtx *frontmtx, int myid, IV *ownersIV,
int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{FrontMtx_ownedColumns@{\tt FrontMtx\_ownedColumns()}}
\index{FrontMtx_ownedRows@{\tt FrontMtx\_ownedRows()}}
These methods construct and return {\tt IV} objects that
contain the ids of the rows and columns that belong to fronts that
are owned by processor {\tt myid}.
If {\tt ownersIV} is {\tt NULL}, an {\tt IV} object is returned
that contains {\tt \{0,1,2,3, ..., nfront-1\}}.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IVL * FrontMtx_makeUpperBlockIVL ( FrontMtx *frontmtx, IV *colmapIV ) ;
IVL * FrontMtx_makeLowerBlockIVL ( FrontMtx *frontmtx, IV *rowmapIV ) ;
\end{verbatim}
\index{FrontMtx_makeUpperBlockIVL@{\tt FrontMtx\_makeUpperBlockIVL()}}
\index{FrontMtx_makeLowerBlockIVL@{\tt FrontMtx\_makeLowerBlockIVL()}}
These methods construct and return {\tt IVL} objects that
contain the submatrix structure of the lower and upper factors.
The {\tt IV} objects map the rows and columns of the matrix to the
fronts in the factor matrix that contain them.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt colmapIV} or {\tt rowmapIV} are {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void FrontMtx_inertia ( FrontMtx *frontmtx, int *pnneg, int *pnzero, int *pnpos ) ;
\end{verbatim}
\index{FrontMtx_inertia@{\tt FrontMtx\_inertia()}}
This method determines the inertia of a symmetric matrix
based on the $(U^T + I)D(I + U)$ factorization.
The number of negative eigenvalues is returned in {\tt *pnneg},
the number of zero eigenvalues is returned in {\tt *pnzero},
and the number of positive eigenvalues is returned in {\tt *pnpos}.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt pnneg}, {\tt pnzero}
or {\tt pnpos} is {\tt NULL},
or if ${\tt symmetryflag} \ne 0$
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_nSolveOps ( FrontMtx *frontmtx ) ;
\end{verbatim}
\index{FrontMtx_nSolveOps@{\tt FrontMtx\_nSolveOps()}}
This method computes and return the number of floating point
operations for a solve with a single right hand side.
\par \noindent {\it Error checking:}
If {\tt frontmtx} is {\tt NULL},
or if {\tt type} or {\tt symmetryflag} are invalid,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:FrontMtx:proto:IO}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_readFromFile ( FrontMtx *frontmtx, char *fn ) ;
\end{verbatim}
\index{FrontMtx_readFromFile@{\tt FrontMtx\_readFromFile()}}
\par
This method reads a {\tt FrontMtx object} from a file.
It tries to open the file and if it is successful,
it then calls {\tt FrontMtx\_readFromFormattedFile()} or
{\tt FrontMtx\_readFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.frontmtxf} (for a formatted file)
or {\tt *.frontmtxb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_readFromFormattedFile ( FrontMtx *frontmtx, FILE *fp ) ;
\end{verbatim}
\index{FrontMtx_readFromFormattedFile@{\tt FrontMtx\_readFromFormattedFile()}}
\par
This method reads a {\tt FrontMtx} object from a formatted file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fscanf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_readFromBinaryFile ( FrontMtx *frontmtx, FILE *fp ) ;
\end{verbatim}
\index{FrontMtx_readFromBinaryFile@{\tt FrontMtx\_readFromBinaryFile()}}
This method reads a {\tt FrontMtx} object from a binary file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fread}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_writeToFile ( FrontMtx *frontmtx, char *fn ) ;
\end{verbatim}
\index{FrontMtx_writeToFile@{\tt FrontMtx\_writeToFile()}}
\par
This method writes a {\tt FrontMtx object} to a file.
It tries to open the file and if it is successful,
it then calls {\tt FrontMtx\_writeFromFormattedFile()} or
{\tt FrontMtx\_writeFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.frontmtxf} (for a formatted file)
or {\tt *.frontmtxb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_writeToFormattedFile ( FrontMtx *frontmtx, FILE *fp ) ;
\end{verbatim}
\index{FrontMtx_writeToFormattedFile@{\tt FrontMtx\_writeToFormattedFile()}}
\par
This method writes a {\tt FrontMtx} object to a formatted file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fprintf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_writeToBinaryFile ( FrontMtx *frontmtx, FILE *fp ) ;
\end{verbatim}
\index{FrontMtx_writeToBinaryFile@{\tt FrontMtx\_writeToBinaryFile()}}
\par
This method writes a {\tt FrontMtx} object to a binary file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fwrite}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_writeForHumanEye ( FrontMtx *frontmtx, FILE *fp ) ;
\end{verbatim}
\index{FrontMtx_writeForHumanEye@{\tt FrontMtx\_writeForHumanEye()}}
\par
This method writes a {\tt FrontMtx} object to a file in a human
readable format.
The method {\tt FrontMtx\_writeStats()} is called to write out the
header and statistics.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_writeStats ( FrontMtx *frontmtx, FILE *fp ) ;
\end{verbatim}
\index{FrontMtx_writeStats@{\tt FrontMtx\_writeStats()}}
\par
The header and statistics are written to a file.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt frontmtx} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int FrontMtx_writeForMatlab ( FrontMtx *frontmtx, char *Lname, char *Dname,
char *Uname, FILE *fp ) ;
\end{verbatim}
\index{FrontMtx_writeForMatlab@{\tt FrontMtx\_writeForMatlab()}}
\par
This method writes out the factor matrix entries in a
Matlab-readable form.
{\tt Lname} is a string for the lower triangular matrix,
{\tt Dname} is a string for the diagonal matrix,
and {\tt Uname} is a string for the upper triangular matrix.
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt Lname}, {\tt Dname}, {\tt Uname}
or {\tt fp} are {\tt NULL},
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
\par
--- fetch right hand side and store solution
\item
{\tt cpus[2]} --- forward solve
\item
{\tt cpus[3]} --- diagonal solve
\item
{\tt cpus[4]} --- backward solve
\item
{\tt cpus[5]} --- total time in the solve method.
\item
{\tt cpus[6]} --- time to compute $A^TB$ or $A^HB$.
\item
{\tt cpus[7]} --- total time.
\end{itemize}
\par \noindent {\it Error checking:}
If {\tt frontmtx}, {\tt mtxA}, {\tt mtxX}, {\tt mtxB} or {\tt cpus}
is {\tt FrontMtx/doc/intro.tex.bak 0100644 0002055 0007177 00000023420 06571267173 0017047 0 ustar 00cleve compmath 0000040 0000006 \par
\chapter{{\tt FrontMtx}: \break Front matrix}
\par
This object computes, stores and solves linear
systems using two types of factorizations:
\begin{enumerate}
\item
$(A + \sigma B) = P(U^T + I)D(I + U)P^T$ for a symmetric matrix $A$.
If pivoting is not enabled, $D$ is a diagonal matrix.
If pivoting is enabled, $D$ has $1 \times 1$ and $2 \times 2$
blocks on its diagonal.
$U$ is strictly upper triangular, and the nonzero structures
of $U$ and $D$ are disjoint.
$P$ is a permutation matrix.
\item
$(A + \sigma B) = P(L + I)D(I + U)Q^T$ for a nonsymmetric matrix $A$
with symmetric structure.
$D$ is a diagonal matrix.
$U$ is strictly upper triangular.
$L$ is strictly lower triangular.
$P$ and $Q$ are permutation matrices.
\end{enumerate}
Pivoting for numerical stability is an optional feature,
and the storage of the factors $L$ and $U$ may be sparse,
i.e., entries of small magnitude can be dropped from the matrix.
\par
Let us take a quick look at the necessary data structures.
\begin{itemize}
\item
There is a pointer to a {\tt ETree} object that contains the front
tree that governs the factorization and solve.
Inside this object are the dimensions of each front (the number of
internal and external rows and columns), the tree connectivity of
the fronts, and a map from each vertex to the front that contains
it as an internal row and column.
\item
There is a pointer to an {\tt IVL} object that contains the
symbolic factorization.
For each front, it gives the list of internal and external rows and
columns, used to initialize a front prior to its factorization.
For a factorization without pivoting, this object stores the index
information for the factors, and so is used during the forward and
backsolves.
For a factorization with pivoting, the index information for a
front may change, so this object is not used during the solves.
\item
For a factorization with pivoting, the composition of a front
(its dimensions and the row and column indices) may change, so we
need additional data structures to store this information.
We use an {\tt IV} object to store the front size --- the number of
rows and columns that were eliminated when the front was factored.
We use an {\tt IVL} object to store the column indices --- internal
and external --- and if the matrix is nonsymmetric, another {\tt
IVL} object to store the row indices.
\item
If we have a multithreaded factorization and use pivoting or an
approximate factorization, we need exclusive access
to the {\tt IV} object that stores the final front size,
and the {\tt IVL} object(s) that store the final row and column
indices for the front.
Therefore we use a {\tt Lock} object to govern exclusive
access to these objects.
\end{itemize}
\par
The $(L+I)D(I+U)$ and $(U^T+I)D(I+U)$ factorizations are computed
using a {\it 1-dimensional} decomposition of the matrix.
Consider a matrix partitioned into eight fronts.
\begin{center}
\setlength{\unitlength}{0.04in}
\begin{picture}(80,80)
\put(-10,40){\makebox(0,0){$A = $}}
\put(0,0){\framebox(80,80){}}
% \put(0,0){\framebox(10,70){}}
% \put(10,0){\framebox(10,60){}}
% \put(20,0){\framebox(10,50){}}
% \put(30,0){\framebox(10,40){}}
% \put(40,0){\framebox(10,30){}}
% \put(50,0){\framebox(10,20){}}
% \put(60,0){\framebox(10,10){}}
\put( 0, 70){\line(1,0){80}}
\put(10, 60){\line(1,0){70}}
\put(20, 50){\line(1,0){60}}
\put(30, 40){\line(1,0){50}}
\put(40, 30){\line(1,0){40}}
\put(50, 20){\line(1,0){30}}
\put(60, 10){\line(1,0){20}}
\put(10, 80){\line(0,-1){80}}
\put(20, 70){\line(0,-1){70}}
\put(30, 60){\line(0,-1){60}}
\put(40, 50){\line(0,-1){50}}
\put(50, 40){\line(0,-1){40}}
\put(60, 30){\line(0,-1){30}}
\put(70, 20){\line(0,-1){20}}
\put( 5, 75){\makebox(0,0){$A_{0,0}$}}
\put(15, 65){\makebox(0,0){$A_{1,1}$}}
\put(25, 55){\makebox(0,0){$A_{2,2}$}}
\put(35, 45){\makebox(0,0){$A_{3,3}$}}
\put(45, 35){\makebox(0,0){$A_{4,4}$}}
\put(55, 25){\makebox(0,0){$A_{5,5}$}}
\put(65, 15){\makebox(0,0){$A_{6,6}$}}
\put(75, 5){\makebox(0,0){$A_{7,7}$}}
\put( 5, 35){\makebox(0,0){$A_{*,0}$}}
\put(15, 30){\makebox(0,0){$A_{*,1}$}}
\put(25, 25){\makebox(0,0){$A_{*,2}$}}
\put(35, 20){\makebox(0,0){$A_{*,3}$}}
\put(45, 15){\makebox(0,0){$A_{*,4}$}}
\put(55, 10){\makebox(0,0){$A_{*,5}$}}
\put(65, 5){\makebox(0,0){$A_{*,6}$}}
\put(45, 75){\makebox(0,0){$A_{0,*}$}}
\put(50, 65){\makebox(0,0){$A_{1,*}$}}
\put(55, 55){\makebox(0,0){$A_{2,*}$}}
\put(60, 45){\makebox(0,0){$A_{3,*}$}}
\put(65, 35){\makebox(0,0){$A_{4,*}$}}
\put(70, 25){\makebox(0,0){$A_{5,*}$}}
\put(75, 15){\makebox(0,0){$A_{6,*}$}}
\end{picture}
\end{center}
The $A_{i,i}$ matrices on the diagonal are square, but they need
not be the same size.
The off-diagonal matrices $A_{*,i}$ and $A_{i,*}$ use a $*$
notation for their rows and columns, respectively, where $*$ means
all indices that follow the $i$'th block.
We shall associate with each front a set of row and column indices,
so we write $A_{J,J}$ for $A_{i,i}$, where $J$ is the set of row
and column indices for front $i$.
\par
Consider the case where $A$ is structurally symmetric.
We factor $A$ into $(L + I)D(I + U)$, where $L$ is strictly lower
triangular, $D $ is diagonal, and $U$ is strictly upper triangular.
$L$, $D$ and $U$ inherit the block structure of $A$, so we have
$L_{*,J}$, $L_{J,J}$, $D_{J,J}$, $U_{J,J}$ and $U_{J,*}$ matrices.
\par
The off-diagonal matrices of $A$, $L$ and $U$ are usually very sparse.
We use special notation to define their nonzero rows and columns.
% We write $A_{\bnd{J},J}$ for $A_{*,J}$ and $A_{J,\bnd{J}}$ for
% $A_{J,*}$, and similar notation for $L$ and $U$.
The set $\bnd{J}$ is the set of indices $k$ such that
$l_{k,j} \ne 0$ or $u_{j,k} \ne 0$ for some $j \in J$.
$U_{J,*}$ and $U_{J,\bnd{J}}$ are related by some permutation matrix
$A$ where
$
U_{J,*} Q =
\left \lbrack \begin{array}{cc}
U_{J,\bnd{J}} & 0
\end{array} \right \rbrack
$.
Similar relations hold for $A_{J,*}$, $A_{*,J}$ and $L_{*,J}$.
We never operate on or store $U_{J,*}$, for this would waste
storage and operations.
Rather we store and operate on $U_{J,\bnd{J}}$ instead.
\par
By multiplying the matrices on the right of
$A = (L + I)D(I + U)$, we arrive at the three equations that define
the factorization.
\begin{eqnarray*}
A_{J,J} & = & (L_{J,J}+I) D_{J,J} (I+U_{J,J})
+ \sum_{I < J} L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J} \\
A_{J,\bnd{J}} & = & (L_{J,J}+I) D_{J,J} U_{J, \bnd{J}}
+ \sum_{I < J} L_{\bnd{I} \cap J, I}
D_{I, I} U_{I, \bnd{I} \cap \bnd{J}} \\
A_{\bnd{J},J} & = & L_{\bnd{J},J} D_{J,J} (I+U_{J,J})
+ \sum_{I < J} L_{\bnd{I} \cap \bnd{J}, I}
D_{I, I} U_{I, \bnd{I} \cap J}
\end{eqnarray*}
Since we are somewhat informal with our notation above, let us take
a moment to make it more precise.
\begin{itemize}
\item
In the summation $\sum_{I < J}$, $I$ and $J$ are index sets.
We use the convention that $I < J$ when the front that has index
set $I$ is numbered before the front that has index set $J$.
In the following we will use $I$ to refer to the front with index
set $I$, as well as the index set itself.
\item
The row index set for $L_{\bnd{I} \cap J,I}$ is the intersection of
the indices in $\bnd{I}$ with those of $J$.
The index set $\bnd{I} \cap \bnd{J}$ is similarly defined.
\item
The multiplication
$L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J}$
generates a matrix whose rows are
$\bnd{I} \cap J$ and whose columns are $\bnd{I} \cap J$,
and this matrix is to be added into a matrix whose rows and columns
are $J$.
If $\bnd{I} \cap J \ne J$, then this operation is not well defined.
We use the convention that the entries in
$L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J}$
are {\it scatter/add}'ed into their proper location.
This is a generalization of an indexed {\tt axpy} operation
applied to matrices.
\end{itemize}
Just because front $I$ precedes front $J$ does not mean the there
is any nonempty intersection between $\bnd{I}$ and $J$.
(A sparse matrix should also have a sparse block structure!)
If $\bnd{I} \cap J = \emptyset$, then
$L_{\bnd{I} \cap J,I}$ and $U_{I,\bnd{I} \cap J}$
are zero matrices.
We can rewrite the above equations to take advantage of this
ohservation.
\begin{eqnarray*}
A_{J,J} & = & (L_{J,J}+I) D_{J,J} (I+U_{J,J})
+ \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J} \\
A_{J,\bnd{J}} & = & (L_{J,J}+I) D_{J,J} U_{J, \bnd{J}}
+ \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap \bnd{J}} \\
A_{\bnd{J},J} & = & L_{\bnd{J},J} D_{J,J} (I+U_{J,J})
+ \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap \bnd{J}, I} D_{I, I} U_{I, \bnd{I} \cap J}
\end{eqnarray*}
These are the defining equations to compute an $A = (L+I)D(I+U)$
factorization without pivoting. We can rearrange the terms and
order the steps to give the factorization algorithm.
\begin{figure}
\caption{Serial factorization without pivoting}
\label{figure:serial-factorization}
\begin{center}
\fbox{
\begin{minipage}{4 in}
\begin{tabbing}
XXX\=XXX\=XXX\=\kill
for $I$ = 0, $\ldots$, \# of fronts \\
\> compute
$\displaystyle
T_{J,J} = A_{J,J}
- \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap J}$ \\
\> compute
$\displaystyle
T_{J,\bnd{J}} = A_{J,\bnd{J}}
- \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap J, I} D_{I, I} U_{I, \bnd{I} \cap \bnd{J}}$ \\
\> compute
$\displaystyle
T_{\bnd{J},J} = A_{\bnd{J},J}
- \sum_{\bnd{I} \cap J \ne \emptyset}
L_{\bnd{I} \cap \bnd{J}, I} D_{I, I} U_{I, \bnd{I} \cap J}$ \\
\> solve
$
\left \lbrack \begin{array}{cc}
(L_{J,J}+I) D_{J,J} (I+U_{J,J}) & (L_{J,J}+I) D_{J,J} U_{J, \bnd{J}} \\
L_{\bnd{J},J} D_{J,J} (I+U_{J,J}) & 0
\end{array} \right \rbrack
=
\left \lbrack \begin{array}{cc}
T_{J,J} & T_{J,\bnd{J}} \\
T_{\bnd{J},J} & 0 \\
\end{array} \right \rbrack
$ \\
\>\> for $D_{J,J}$, $L_{J,J}$, $L_{\bnd{J},J}$,
$U_{J,J}$ and $U_{J,\bnd{J}}$
\end{tabbing}
\end{minipage}
}
\end{center}
\end{figure}
ertex to the front that contains
it as an internal row and column.
\item
There is a pointer to an {\tt IVL} object that contains the
symbolic factorization.
For each front, it gives the list of internal and external rows and
columns, used tFrontMtx/doc/main.log 0100644 0002055 0007177 00000022551 06650220241 0016050 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.14159 (C version 6.1) (format=latex 97.4.4) 16 JAN 1999 15:28
**main
(main.tex
LaTeX2e <1996/12/01> patch level 1
Babel and hyphenation patterns for english, german, loaded.
(/home/tex/teTeX/texmf/tex/latex/base/latex209.def
File: latex209.def 1996/05/21 v0.51 Standard LaTeX file
Entering LaTeX 2.09 compatibility mode.
\footheight=\dimen102
\@maxsep=\dimen103
\@dblmaxsep=\dimen104
\@cla=\count79
\@clb=\count80
\mscount=\count81
(/home/tex/teTeX/texmf/tex/latex/base/tracefnt.sty
Package: tracefnt 1996/07/26 v3.0i Standard LaTeX package (font tracing)
\tracingfonts=\count82
LaTeX Info: Redefining \selectfont on input line 139.
)
\symbold=\mathgroup4
\symsans=\mathgroup5
\symtypewriter=\mathgroup6
\symitalic=\mathgroup7
\symsmallcaps=\mathgroup8
\symslanted=\mathgroup9
LaTeX Font Info: Redeclaring math alphabet \mathbf on input line 306.
LaTeX Font Info: Redeclaring math alphabet \mathsf on input line 307.
LaTeX Font Info: Redeclaring math alphabet \mathtt on input line 308.
LaTeX Font Info: Redeclaring math alphabet \mathit on input line 314.
LaTeX Info: Redefining \em on input line 324.
(/home/tex/teTeX/texmf/tex/latex/base/latexsym.sty
Package: latexsym 1996/11/20 v2.2d Standard LaTeX package (lasy symbols)
\symlasy=\mathgroup10
LaTeX Font Info: Overwriting symbol font `lasy' in version `bold'
(Font) U/lasy/m/n --> U/lasy/b/n on input line 85.
)
LaTeX Font Info: Redeclaring math delimiter \lgroup on input line 388.
LaTeX Font Info: Redeclaring math delimiter \rgroup on input line 390.
LaTeX Font Info: Redeclaring math delimiter \bracevert on input line 392.
(/home/tex/teTeX/texmf/tex/latex/config/latex209.cfg
(/home/tex/teTeX/texmf/tex/latex/tools/rawfonts.sty
Compatibility mode: package `' requested, but `rawfonts' provided.
Package: rawfonts 1994/05/08 Low-level LaTeX 2.09 font compatibility
(/home/tex/teTeX/texmf/tex/latex/tools/somedefs.sty
Package: somedefs 1994/06/01 Toolkit for optional definitions
)
LaTeX Font Info: Try loading font information for U+lasy on input line 36.
(/home/tex/teTeX/texmf/tex/latex/base/ulasy.fd
File: ulasy.fd 1996/11/20 v2.2dLaTeX symbol font definitions
))))
(/home/tex/teTeX/texmf/tex/latex/base/report.cls
Document Class: report 1996/10/31 v1.3u Standard LaTeX document class
(/home/tex/teTeX/texmf/tex/latex/base/leqno.clo
File: leqno.clo 1996/07/26 v1.1b Standard LaTeX option (left equation numbers)
)
(/home/tex/teTeX/texmf/tex/latex/base/size11.clo
File: size11.clo 1996/10/31 v1.3u Standard LaTeX file (size option)
)
\c@part=\count83
\c@chapter=\count84
\c@section=\count85
\c@subsection=\count86
\c@subsubsection=\count87
\c@paragraph=\count88
\c@subparagraph=\count89
\c@figure=\count90
\c@table=\count91
\abovecaptionskip=\skip41
\belowcaptionskip=\skip42
Compatibility mode: definition of \rm ignored.
Compatibility mode: definition of \sf ignored.
Compatibility mode: definition of \tt ignored.
Compatibility mode: definition of \bf ignored.
Compatibility mode: definition of \it ignored.
Compatibility mode: definition of \sl ignored.
Compatibility mode: definition of \sc ignored.
LaTeX Info: Redefining \cal on input line 622.
LaTeX Info: Redefining \mit on input line 623.
\bibindent=\dimen105
)
(/home/tex/teTeX/texmf/tex/generic/local/psfig/psfig.tex
\@unused=\write3
\ps@stream=\read1
\p@intvaluex=\dimen106
\p@intvaluey=\dimen107
psfig/tex 1.10-dvips
)
\@indexfile=\write4
Writing index file main.idx
(main.aux)
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 20.
LaTeX Font Info: ... okay on input line 20.
(intro.tex
Chapter 1.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <10.95> on input line 5.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <8> on input line 5.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <6> on input line 5.
LaTeX Font Info: Try loading font information for OMS+cmr on input line 16.
(/home/tex/teTeX/texmf/tex/latex/base/omscmr.fd
File: omscmr.fd 1997/01/14 v2.5a Standard LaTeX font definitions
)
LaTeX Font Info: Font shape `OMS/cmr/m/n' in size <10.95> not available
(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 16.
[1
]
psfig: searching ../../FrontMtx/doc/simple.eps for bounding box
psfig: including ../../FrontMtx/doc/simple.eps
[2] [3]) (dataStructure.tex [4]
Overfull \hbox (12.9766pt too wide) in paragraph at lines 54--59
[]\OT1/cmtt/m/n/10.95 Tree *tree \OT1/cmr/m/n/10.95 : Tree ob-ject that holds t
he tree of fronts. Note, nor-mally this is \OT1/cmtt/m/n/10.95 frontETree->tree
\OT1/cmr/m/n/10.95 ,
[]
[5]) (proto.tex [6] [7] [8] [9] [10]
Overfull \hbox (0.26903pt too wide) in paragraph at lines 411--411
[] \OT1/cmtt/m/n/10.95 int parent[], ChvList *aggList, ChvList *postList, Ch
vManager *chvmanager,[]
[]
Overfull \hbox (11.7664pt too wide) in paragraph at lines 463--463
[] \OT1/cmtt/m/n/10.95 char inactiveFlag, int ms
glvl, FILE *msgFile ) ;[]
[]
[11]
Overfull \hbox (6.01772pt too wide) in paragraph at lines 529--529
[] \OT1/cmtt/m/n/10.95 char status[], DV *tempDV, int ms
glvl, FILE *msgFile) ;[]
[]
[12]
Overfull \hbox (0.26903pt too wide) in paragraph at lines 610--610
[]\OT1/cmtt/m/n/10.95 Chv * FrontMtx_factorInpMtx ( FrontMtx *frontmtx, InpMtx
*inpmtx, double tau,[]
[]
Overfull \hbox (0.26903pt too wide) in paragraph at lines 610--610
[] \OT1/cmtt/m/n/10.95 double cpus[], int stats[], int msgl
vl, FILE *msgFile ) ;[]
[]
Overfull \hbox (0.26903pt too wide) in paragraph at lines 610--610
[]\OT1/cmtt/m/n/10.95 Chv * FrontMtx_factorPencil ( FrontMtx *frontmtx, Pencil
*pencil, double tau,[]
[]
Overfull \hbox (0.26903pt too wide) in paragraph at lines 610--610
[] \OT1/cmtt/m/n/10.95 double cpus[], int stats[], int msgl
vl, FILE *msgFile ) ;[]
[]
[13]
Overfull \hbox (2.58154pt too wide) in paragraph at lines 717--725
\OT1/cmr/m/it/10.95 Error check-ing: \OT1/cmr/m/n/10.95 If \OT1/cmtt/m/n/10.95
frontmtx\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95 mtxA\OT1/cmr/m/n/10.95 , \OT1/
cmtt/m/n/10.95 rowsIVL\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95 firstnz\OT1/cmr/
m/n/10.95 , \OT1/cmtt/m/n/10.95 updlist\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95
chvmanager\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95 status\OT1/cmr/m/n/10.95 ,
\OT1/cmtt/m/n/10.95 colmap\OT1/cmr/m/n/10.95 ,
[]
[14]
Overfull \hbox (46.25853pt too wide) in paragraph at lines 765--765
[] \OT1/cmtt/m/n/10.95 ChvManager *chvmanager,
int msglvl, FILE *msgFile ) ;[]
[]
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <12> on input line 779.
Overfull \hbox (0.26903pt too wide) in paragraph at lines 833--833
[]\OT1/cmtt/m/n/10.95 void FrontMtx_postProcess ( FrontMtx *frontmtx, int msgl
vl, FILE *msgFile ) ;[]
[]
[15]
Overfull \hbox (40.50984pt too wide) in paragraph at lines 891--891
[]\OT1/cmtt/m/n/10.95 void FrontMtx_splitUpperMatrices ( FrontMtx *frontmtx, i
nt msglvl, FILE *msgFile ) ;[]
[]
Overfull \hbox (40.50984pt too wide) in paragraph at lines 891--891
[]\OT1/cmtt/m/n/10.95 void FrontMtx_splitLowerMatrices ( FrontMtx *frontmtx, i
nt msglvl, FILE *msgFile ) ;[]
[]
[16]
Overfull \hbox (11.7664pt too wide) in paragraph at lines 979--979
[]\OT1/cmtt/m/n/10.95 IP ** FrontMtx_forwardSetup ( FrontMtx *frontmtx, int ms
glvl, FILE *msgFile ) ;[]
[]
Overfull \hbox (17.51509pt too wide) in paragraph at lines 993--993
[]\OT1/cmtt/m/n/10.95 IP ** FrontMtx_backwardSetup ( FrontMtx *frontmtx, int m
sglvl, FILE *msgFile ) ;[]
[]
[17]
Overfull \hbox (17.51509pt too wide) in paragraph at lines 1024--1024
[] \OT1/cmtt/m/n/10.95 SubMtxManager *mtxmanager, double cpus[], int m
sglvl, FILE *msgFile ) ;[]
[]
[18]
LaTeX Font Info: Try loading font information for OMS+cmtt on input line 114
2.
LaTeX Font Info: No file OMScmtt.fd. on input line 1142.
LaTeX Font Warning: Font shape `OMS/cmtt/m/n' undefined
(Font) using `OMS/cmsy/m/n' instead
(Font) for symbol `textbraceleft' on input line 1142.
Overfull \hbox (34.76115pt too wide) in paragraph at lines 1165--1165
[]\OT1/cmtt/m/n/10.95 void FrontMtx_inertia ( FrontMtx *frontmtx, int *pnneg,
int *pnzero, int *pnpos ) ;[]
[]
[19] [20]) (drivers.tex [21] [22]) (main.ind [23] [24
] [25
]) (main.aux)
LaTeX Font Warning: Some font shapes were not available, defaults substituted.
)
Here is how much of TeX's memory you used:
836 strings out of 10908
8802 string characters out of 72189
54462 words of memory out of 262141
3678 multiletter control sequences out of 9500
23753 words of font info for 89 fonts, out of 150000 for 255
14 hyphenation exceptions out of 607
22i,7n,21p,313b,426s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (25 pages, 81688 bytes).
U/lasy/m/n --> U/lasy/b/n on input line 85.
)
LaTeX Font Info: Redeclaring math delimiter \lgroup on input line 388.
LaTeX Font Info: RedeclarFrontMtx/doc/main.idx 0100644 0002055 0007177 00000012564 06650220241 0016056 0 ustar 00cleve compmath 0000040 0000006 \indexentry{FrontMtx_new@{\tt FrontMtx\_new()}}{7}
\indexentry{FrontMtx_setDefaultFields@{\tt FrontMtx\_setDefaultFields()}}{7}
\indexentry{FrontMtx_clearData@{\tt FrontMtx\_clearData()}}{7}
\indexentry{FrontMtx_free@{\tt FrontMtx\_free()}}{7}
\indexentry{FrontMtx_nfront@{\tt FrontMtx\_nfront()}}{7}
\indexentry{FrontMtx_neqns@{\tt FrontMtx\_neqns()}}{7}
\indexentry{FrontMtx_frontTree@{\tt FrontMtx\_frontTree()}}{8}
\indexentry{FrontMtx_initialFrontDimensions@{\tt FrontMtx\_initialFrontDimensions()}}{8}
\indexentry{FrontMtx_frontSize@{\tt FrontMtx\_frontSize()}}{8}
\indexentry{FrontMtx_setFrontsize@{\tt FrontMtx\_setFrontSize()}}{8}
\indexentry{FrontMtx_columnIndices@{\tt FrontMtx\_columnIndices()}}{8}
\indexentry{FrontMtx_rowIndices@{\tt FrontMtx\_rowIndices()}}{8}
\indexentry{FrontMtx_diagMtx@{\tt FrontMtx\_diagMtx()}}{8}
\indexentry{FrontMtx_upperMtx@{\tt FrontMtx\_upperMtx()}}{9}
\indexentry{FrontMtx_lowerMtx@{\tt FrontMtx\_lowerMtx()}}{9}
\indexentry{FrontMtx_lowerAdjFronts@{\tt FrontMtx\_lowerAdjFronts()}}{9}
\indexentry{FrontMtx_upperAdjFronts@{\tt FrontMtx\_upperAdjFronts()}}{9}
\indexentry{FrontMtx_nLowerBlocks@{\tt FrontMtx\_nLowerBlocks()}}{9}
\indexentry{FrontMtx_nUpperBlocks@{\tt FrontMtx\_nUpperBlocks()}}{9}
\indexentry{FrontMtx_upperBlockIVL@{\tt FrontMtx\_upperBlockIVL()}}{9}
\indexentry{FrontMtx_lowerBlockIVL@{\tt FrontMtx\_lowerBlockIVL()}}{9}
\indexentry{FrontMtx_init@{\tt FrontMtx\_init()}}{10}
\indexentry{FrontMtx_initializeFront@{\tt FrontMtx\_initializeFront()}}{10}
\indexentry{FrontMtx_factorVisit@{\tt FrontMtx\_factorVisit()}}{11}
\indexentry{FrontMtx_setupFront@{\tt FrontMtx\_setupFront()}}{11}
\indexentry{FrontMtx_factorSetup@{\tt FrontMtx\_factorSetup()}}{11}
\indexentry{FrontMtx_nactiveChild@{\tt FrontMtx\_nactiveChild()}}{11}
\indexentry{FrontMtx_nactiveChild@{\tt FrontMtx\_nactiveChild()}}{11}
\indexentry{FrontMtx_loadActiveLeaves@{\tt FrontMtx\_loadActiveLeaves()}}{11}
\indexentry{FrontMtx_postList@{\tt FrontMtx\_postList()}}{12}
\indexentry{FrontMtx_aggregateList@{\tt FrontMtx\_aggregateList()}}{12}
\indexentry{FrontMtx_loadEntries@{\tt FrontMtx\_loadEntries()}}{12}
\indexentry{FrontMtx_update@{\tt FrontMtx\_update()}}{12}
\indexentry{FrontMtx_assemblePostponedData@{\tt FrontMtx\_assemblePostponedData()}}{12}
\indexentry{FrontMtx_storePostponedData@{\tt FrontMtx\_storePostponedData()}}{12}
\indexentry{FrontMtx_storeFront@{\tt FrontMtx\_storeFront()}}{13}
\indexentry{FrontMtx_factorInpMtx@{\tt FrontMtx\_factorInpMtx()}}{13}
\indexentry{FrontMtx_factorPencil@{\tt FrontMtx\_factorPencil()}}{13}
\indexentry{FrontMtx_QR_setup@{\tt FrontMtx\_QR\_setup()}}{14}
\indexentry{FrontMtx_QR_factorVisit@{\tt FrontMtx\_QR\_factorVisit()}}{14}
\indexentry{FrontMtx_QR_assembleFront@{\tt FrontMtx\_QR\_assembleFront()}}{14}
\indexentry{FrontMtx_QR_storeFront@{\tt FrontMtx\_QR\_storeFront()}}{15}
\indexentry{FrontMtx_QR_storeUpdate@{\tt FrontMtx\_QR\_storeUpdate()}}{15}
\indexentry{FrontMtx_QR_factor@{\tt FrontMtx\_QR\_factor()}}{15}
\indexentry{FrontMtx_postProcess@{\tt FrontMtx\_postProcess()}}{16}
\indexentry{FrontMtx_permuteUpperAdj@{\tt FrontMtx\_permuteUpperAdj()}}{16}
\indexentry{FrontMtx_permuteLowerAdj@{\tt FrontMtx\_permuteLowerAdj()}}{16}
\indexentry{FrontMtx_permuteUpperMatrices@{\tt FrontMtx\_permuteUpperMatrices()}}{16}
\indexentry{FrontMtx_permuteLowerMatrices@{\tt FrontMtx\_permuteLowerMatrices()}}{16}
\indexentry{FrontMtx_splitUpperMatrices@{\tt FrontMtx\_splitUpperMatrices()}}{16}
\indexentry{FrontMtx_splitLowerMatrices@{\tt FrontMtx\_splitLowerMatrices()}}{16}
\indexentry{FrontMtx_loadRightHandSide@{\tt FrontMtx\_loadRightHandSide()}}{16}
\indexentry{FrontMtx_forwardVisit@{\tt FrontMtx\_forwardVisit()}}{17}
\indexentry{FrontMtx_diagonalVisit@{\tt FrontMtx\_diagonalVisit()}}{17}
\indexentry{FrontMtx_backwardVisit@{\tt FrontMtx\_backwardVisit()}}{17}
\indexentry{FrontMtx_storeSolution@{\tt FrontMtx\_storeSolution()}}{17}
\indexentry{FrontMtx_forwardSetup@{\tt FrontMtx\_forwardSetup()}}{17}
\indexentry{FrontMtx_backwardSetup@{\tt FrontMtx\_backwardSetup()}}{17}
\indexentry{FrontMtx_loadActiveRoots@{\tt FrontMtx\_loadActiveRoots()}}{18}
\indexentry{FrontMtx_solve@{\tt FrontMtx\_solve()}}{18}
\indexentry{FrontMtx_QR_solve@{\tt FrontMtx\_QR\_solve()}}{18}
\indexentry{FrontMtx_colmapIV@{\tt FrontMtx\_colmapIV()}}{19}
\indexentry{FrontMtx_rowmapIV@{\tt FrontMtx\_rowmapIV()}}{19}
\indexentry{FrontMtx_ownedColumns@{\tt FrontMtx\_ownedColumns()}}{19}
\indexentry{FrontMtx_ownedRows@{\tt FrontMtx\_ownedRows()}}{19}
\indexentry{FrontMtx_makeUpperBlockIVL@{\tt FrontMtx\_makeUpperBlockIVL()}}{19}
\indexentry{FrontMtx_makeLowerBlockIVL@{\tt FrontMtx\_makeLowerBlockIVL()}}{19}
\indexentry{FrontMtx_inertia@{\tt FrontMtx\_inertia()}}{19}
\indexentry{FrontMtx_nSolveOps@{\tt FrontMtx\_nSolveOps()}}{19}
\indexentry{FrontMtx_readFromFile@{\tt FrontMtx\_readFromFile()}}{20}
\indexentry{FrontMtx_readFromFormattedFile@{\tt FrontMtx\_readFromFormattedFile()}}{20}
\indexentry{FrontMtx_readFromBinaryFile@{\tt FrontMtx\_readFromBinaryFile()}}{20}
\indexentry{FrontMtx_writeToFile@{\tt FrontMtx\_writeToFile()}}{20}
\indexentry{FrontMtx_writeToFormattedFile@{\tt FrontMtx\_writeToFormattedFile()}}{20}
\indexentry{FrontMtx_writeToBinaryFile@{\tt FrontMtx\_writeToBinaryFile()}}{20}
\indexentry{FrontMtx_writeForHumanEye@{\tt FrontMtx\_writeForHumanEye()}}{21}
\indexentry{FrontMtx_writeStats@{\tt FrontMtx\_writeStats()}}{21}
\indexentry{FrontMtx_writeForMatlab@{\tt FrontMtx\_writeForMatlab()}}{21}
FrontMtx/doc/main.aux 0100644 0002055 0007177 00000005063 06650220241 0016063 0 ustar 00cleve compmath 0000040 0000006 \relax
\@writefile{toc}{\contentsline {chapter}{\numberline {1}{\tt FrontMtx}: Front matrix}{1}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {1.1}Data Structures}{4}}
\newlabel{section:FrontMtx:dataStructure}{{1.1}{4}}
\@writefile{toc}{\contentsline {section}{\numberline {1.2}Prototypes and descriptions of {\tt FrontMtx} methods}{6}}
\newlabel{section:FrontMtx:proto}{{1.2}{6}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.1}Basic methods}{7}}
\newlabel{subsection:FrontMtx:proto:basics}{{1.2.1}{7}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.2}Instance methods}{7}}
\newlabel{subsection:FrontMtx:proto:instance}{{1.2.2}{7}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.3}Initialization methods}{10}}
\newlabel{subsection:FrontMtx:proto:initialization}{{1.2.3}{10}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.4}Utility Factorization methods}{10}}
\newlabel{subsection:FrontMtx:proto:utility-factor}{{1.2.4}{10}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.5}Serial Factorization method}{13}}
\newlabel{subsection:FrontMtx:proto:factor}{{1.2.5}{13}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.6}QR factorization utility methods}{14}}
\newlabel{subsection:FrontMtx:proto:utilityQR}{{1.2.6}{14}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.7}Serial $QR$ Factorization method}{15}}
\newlabel{subsection:FrontMtx:proto:factorQR}{{1.2.7}{15}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.8}Postprocessing methods}{16}}
\newlabel{subsection:FrontMtx:proto:postprocess}{{1.2.8}{16}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.9}Utility Solve methods}{16}}
\newlabel{subsection:FrontMtx:proto:utility-solve}{{1.2.9}{16}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.10}Serial Solve method}{18}}
\newlabel{subsection:FrontMtx:proto:solve-serial}{{1.2.10}{18}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.11}Serial $QR$ Solve method}{18}}
\newlabel{subsection:FrontMtx:proto:QRsolve-serial}{{1.2.11}{18}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.12}Utility methods}{19}}
\newlabel{subsection:FrontMtx:proto:utility}{{1.2.12}{19}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.13}IO methods}{20}}
\newlabel{subsection:FrontMtx:proto:IO}{{1.2.13}{20}}
\@writefile{toc}{\contentsline {section}{\numberline {1.3}Driver programs for the {\tt DFrontMtx} object}{21}}
\newlabel{section:DFrontMtx:drivers}{{1.3}{21}}
section:FrontMtx:proto:basics}{{1.2.1}{7}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.2}Instance methods}{7}}
\newlabel{subsection:FrontMtx:proto:instance}{{1.2.2}{7}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.3}Initialization methods}{10}}
\newlabel{subsection:FrontMtx:proto:initialization}{{1.2.3}{10}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2.4}Utility Factorization methods}{10}}
\newlabel{subsectioFrontMtx/doc/makefile 0100644 0002055 0007177 00000000027 06571267174 0016135 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
FrontMtx/doc/main.ind 0100644 0002055 0007177 00000006305 06572065761 0016061 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt FrontMtx\_aggregateList()}, 12
\item {\tt FrontMtx\_assemblePostponedData()}, 12
\item {\tt FrontMtx\_backwardSetup()}, 17
\item {\tt FrontMtx\_backwardVisit()}, 17
\item {\tt FrontMtx\_clearData()}, 7
\item {\tt FrontMtx\_colmapIV()}, 19
\item {\tt FrontMtx\_columnIndices()}, 8
\item {\tt FrontMtx\_diagMtx()}, 8
\item {\tt FrontMtx\_diagonalVisit()}, 17
\item {\tt FrontMtx\_factorInpMtx()}, 13
\item {\tt FrontMtx\_factorPencil()}, 13
\item {\tt FrontMtx\_factorSetup()}, 11
\item {\tt FrontMtx\_factorVisit()}, 11
\item {\tt FrontMtx\_forwardSetup()}, 17
\item {\tt FrontMtx\_forwardVisit()}, 17
\item {\tt FrontMtx\_free()}, 7
\item {\tt FrontMtx\_frontSize()}, 8
\item {\tt FrontMtx\_frontTree()}, 8
\item {\tt FrontMtx\_inertia()}, 19
\item {\tt FrontMtx\_init()}, 10
\item {\tt FrontMtx\_initialFrontDimensions()}, 8
\item {\tt FrontMtx\_initializeFront()}, 10
\item {\tt FrontMtx\_loadActiveLeaves()}, 11
\item {\tt FrontMtx\_loadActiveRoots()}, 18
\item {\tt FrontMtx\_loadEntries()}, 12
\item {\tt FrontMtx\_loadRightHandSide()}, 17
\item {\tt FrontMtx\_lowerAdjFronts()}, 9
\item {\tt FrontMtx\_lowerBlockIVL()}, 9
\item {\tt FrontMtx\_lowerMtx()}, 9
\item {\tt FrontMtx\_makeLowerBlockIVL()}, 19
\item {\tt FrontMtx\_makeUpperBlockIVL()}, 19
\item {\tt FrontMtx\_nactiveChild()}, 11
\item {\tt FrontMtx\_neqns()}, 7
\item {\tt FrontMtx\_new()}, 7
\item {\tt FrontMtx\_nfront()}, 7
\item {\tt FrontMtx\_nLowerBlocks()}, 9
\item {\tt FrontMtx\_nUpperBlocks()}, 9
\item {\tt FrontMtx\_ownedColumns()}, 19
\item {\tt FrontMtx\_ownedRows()}, 19
\item {\tt FrontMtx\_permuteLowerAdj()}, 16
\item {\tt FrontMtx\_permuteLowerMatrices()}, 16
\item {\tt FrontMtx\_permuteUpperAdj()}, 16
\item {\tt FrontMtx\_permuteUpperMatrices()}, 16
\item {\tt FrontMtx\_postList()}, 12
\item {\tt FrontMtx\_postProcess()}, 16
\item {\tt FrontMtx\_QR\_assembleFront()}, 14
\item {\tt FrontMtx\_QR\_factor()}, 15
\item {\tt FrontMtx\_QR\_factorVisit()}, 14
\item {\tt FrontMtx\_QR\_setup()}, 14
\item {\tt FrontMtx\_QR\_solve()}, 18
\item {\tt FrontMtx\_QR\_storeFront()}, 15
\item {\tt FrontMtx\_QR\_storeUpdate()}, 15
\item {\tt FrontMtx\_readFromBinaryFile()}, 20
\item {\tt FrontMtx\_readFromFile()}, 20
\item {\tt FrontMtx\_readFromFormattedFile()}, 20
\item {\tt FrontMtx\_rowIndices()}, 8
\item {\tt FrontMtx\_rowmapIV()}, 19
\item {\tt FrontMtx\_setDefaultFields()}, 7
\item {\tt FrontMtx\_setFrontSize()}, 8
\item {\tt FrontMtx\_setupFront()}, 11
\item {\tt FrontMtx\_solve()}, 18
\item {\tt FrontMtx\_splitLowerMatrices()}, 16
\item {\tt FrontMtx\_splitUpperMatrices()}, 16
\item {\tt FrontMtx\_storeFront()}, 13
\item {\tt FrontMtx\_storePostponedData()}, 12
\item {\tt FrontMtx\_storeSolution()}, 17
\item {\tt FrontMtx\_update()}, 12
\item {\tt FrontMtx\_upperAdjFronts()}, 9
\item {\tt FrontMtx\_upperBlockIVL()}, 9
\item {\tt FrontMtx\_upperMtx()}, 9
\item {\tt FrontMtx\_writeForHumanEye()}, 20
\item {\tt FrontMtx\_writeStats()}, 21
\item {\tt FrontMtx\_writeToBinaryFile()}, 20
\item {\tt FrontMtx\_writeToFile()}, 20
\item {\tt FrontMtx\_writeToFormattedFile()}, 20
\end{theindex}
FrontMtx/doc/main.ilg 0100644 0002055 0007177 00000000457 06572065761 0016064 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (76 entries accepted, 0 rejected).
Sorting entries....done (483 comparisons).
Generating output file main.ind....done (79 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
FrontMtx/doc/simple.eps 0100644 0002055 0007177 00000000270 06571267174 0016437 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 100.0 100.0
%%%EndComments
0.5 setgray
25 0 75 75 rectfill
1.0 setgray
50 0 50 50 rectfill
0.0 setgray
0 0 100 100 rectstroke
showpage
GPart.h 0100644 0002055 0007177 00000000100 06534106402 0013246 0 ustar 00cleve compmath 0000040 0000006 #ifndef _GPart_
#define _GPart_
#include "GPart/GPart.h"
#endif
GPart/DDsepInfo.h 0100644 0002055 0007177 00000007421 06540043606 0015101 0 ustar 00cleve compmath 0000040 0000006 /* DDsepInfo.h */
#ifndef _DDsepInfo_
#define _DDsepInfo_
#include "../cfiles.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
this structure is used in the GPart_RBviaDDSEP method
seed -- random number seed
minweight -- minimum weight for any fishnet domain,
default value is 50
maxweight -- maximum weight for any fishnet domain,
default value is 100
freeze -- multiplier used to freeze nodes in the multisector,
default value is 4.0
alpha -- cost function parameter, default value is 1.0
maxcompweight -- any leaf component must have
weight less than this value
ntreeobj -- accumulator for the number of objects
in the domain/separator tree
DDoption -- option for finding domain decomposition
1 --> use Fishnet on each subgraph
2 --> use Fishnet on graph, then projection on each subgraph
nlayer -- number of layers to be used in the smoothing process
2 --> use two-sided dulmage-mendelsohn smoothing
2k+1 --> use k layers of wide separator smoothing
cpuDD -- cpu time for domain decomposition
cpuMap -- cpu time to compute the domain/segment maps
cpuBPG -- cpu time to create the domain/segment bipartite graphs
cpuBKL -- cpu time to find the initial separators using the
block kernihan-lin algorithm
cpuSmooth -- cpu time to smooth the separators
cpuSplit -- cpu time to split the subgraphs
cpuTotal -- total cpu time
msglvl -- message level, default value is 0
msgFile -- message file, default is stdout
---------------------------------------------------------------------
*/
typedef
struct _DDsepInfo {
int seed ;
int minweight ;
int maxweight ;
double freeze ;
double alpha ;
int maxcompweight ;
int ntreeobj ;
int DDoption ;
int nlayer ;
double cpuDD ;
double cpuMap ;
double cpuBPG ;
double cpuBKL ;
double cpuSmooth ;
double cpuSplit ;
double cpuTotal ;
int msglvl ;
FILE *msgFile ;
} DDsepInfo ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in DDsepInfo.c -----------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------
construct a new instance of the DDsepInfo object
created -- 96feb24, cca
------------------------------------------------
*/
DDsepInfo *
DDsepInfo_new (
void
) ;
/*
---------------------------------------------
set the default fields of the DDsepInfo object
created -- 96feb24, cca
---------------------------------------------
*/
void
DDsepInfo_setDefaultFields (
DDsepInfo *info
) ;
/*
---------------------------------------------
clear the data fields for a DDsepInfo object
created -- 96feb24, cca
---------------------------------------------
*/
void
DDsepInfo_clearData (
DDsepInfo *info
) ;
/*
------------------------
free the DDsepInfo object
created -- 96feb24, cca
------------------------
*/
void
DDsepInfo_free (
DDsepInfo *info
) ;
/*
-----------------------
write the CPU times
created -- 97nov06, cca
-----------------------
*/
void
DDsepInfo_writeCpuTimes (
DDsepInfo *info,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
#endif
GPart/GPart.h 0100644 0002055 0007177 00000037242 06540043617 0014311 0 ustar 00cleve compmath 0000040 0000006 /* GPart.h */
#include "../Graph.h"
#include "../BPG.h"
#include "../DSTree.h"
#include "../Tree.h"
#include "../IV.h"
#include "../cfiles.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------------------
The GPart object is used to generate and store information
about a partition of the graph.
id -- id for the object
g -- pointer to Graph object, not free'd by the destructor
nvtx -- # of vertices in the graph, internal vertices only
nvbnd -- # of vertices in the boundary of the graph,
ncomp -- # of components in the graph
compidsIV -- IV object that contains a map from
vertices to components, size nvtx
compids[v] == 0 --> v is on the interface
compids[v] != 0 --> v belongs to domain compids[v]
cweightsIV -- IV object that contains the component weights
par -- pointer to parent GPart object
fch -- pointer to first child GPart object
sib -- pointer to sibling GPart object
vtxMapIV -- IV object that contains a map map from local vertices
to parent's vertices or global vertices
msglvl -- message level, default is zero
msgFile -- message file pointer, default is stdout
created -- 95oct21, cca
----------------------------------------------------------------
*/
typedef struct _GPart GPart ;
struct _GPart {
int id ;
Graph *g ;
int nvtx ;
int nvbnd ;
int ncomp ;
IV compidsIV ;
IV cweightsIV ;
GPart *par ;
GPart *fch ;
GPart *sib ;
IV vtxMapIV ;
int msglvl ;
FILE *msgFile ;
} ;
/*
------------------------------------------
include the DDsepInfo object's header file
------------------------------------------
*/
#include "DDsepInfo.h"
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in basics.c --------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------
construct a new instance of the GPart object
created -- 95oct05, cca
--------------------------------------------
*/
GPart *
GPart_new (
void
) ;
/*
---------------------------------------------
set the default fields of the GPart object
created -- 95oct05, cca
modified -- 95nov29, cca
par, fch, sib and vtxMap fields included
---------------------------------------------
*/
void
GPart_setDefaultFields (
GPart *gpart
) ;
/*
---------------------------------------------
clear the data fields for a GPart object
created -- 95oct05, cca
modified -- 95nov29, cca
par, fch, sib and vtxMap fields included
---------------------------------------------
*/
void
GPart_clearData (
GPart *gpart
) ;
/*
------------------------
free the GPart object
created -- 95oct05, cca
modified -- 95nov29, cca
gpart now free'd
------------------------
*/
void
GPart_free (
GPart *gpart
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in DDviaFishnet.c --------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------------
purpose -- to construct and return a multisector
using the fishnet algorithm
freeze -- parameter used to keep nodes of high degree
in the interface
minweight -- minimum weight for a domain
maxweight -- maximum weight for a domain
seed -- random number seed
created -- 96feb16, cca
---------------------------------------------------------------
*/
void
GPart_DDviaFishnet (
GPart *gpart,
double freeze,
int minweight,
int maxweight,
int seed
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in DDviaProjection.c -----------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------
set the compids[] vector using a global map from vertices
to domains and interface nodes.
DDmapIV -- IV object that contains the map from vertices
to domains and interface nodes
created -- 96mar17, cca
---------------------------------------------------------
*/
void
GPart_DDviaProjection (
GPart *gpart,
IV *DDmapIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in DDsepInfo.c -----------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------
construct a new instance of the DDsepInfo object
created -- 96feb24, cca
------------------------------------------------
*/
DDsepInfo *
DDsepInfo_new (
void
) ;
/*
---------------------------------------------
set the default fields of the DDsepInfo object
created -- 96feb24, cca
---------------------------------------------
*/
void
DDsepInfo_setDefaultFields (
DDsepInfo *info
) ;
/*
---------------------------------------------
clear the data fields for a DDsepInfo object
created -- 96feb24, cca
---------------------------------------------
*/
void
DDsepInfo_clearData (
DDsepInfo *info
) ;
/*
------------------------
free the DDsepInfo object
created -- 96feb24, cca
------------------------
*/
void
DDsepInfo_free (
DDsepInfo *info
) ;
/*
-----------------------
write the CPU times
created -- 97nov06, cca
-----------------------
*/
void
DDsepInfo_writeCpuTimes (
DDsepInfo *info,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in domSegMap.c -----------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------------------
fill *pndom with ndom, the number of domains.
fill *pnseg with nseg, the number of segments.
domains are numbered in [0, ndom), segments in [ndom,ndom+nseg).
return -- an IV object that contains the map
from vertices to segments
created -- 99feb29, cca
--------------------------------------------------------------------
*/
IV *
GPart_domSegMap (
GPart *gpart,
int *pndom,
int *pnseg
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in identifyWideSep.c -----------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------------
identify the wide separator
return -- IV object that holds the nodes in the wide separator
created -- 96oct21, cca
--------------------------------------------------------------
*/
IV *
GPart_identifyWideSep (
GPart *gpart,
int nlevel1,
int nlevel2
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in init.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------
initialize the GPart object
created -- 95oct05, cca
---------------------------
*/
void
GPart_init (
GPart *gpart,
Graph *g
) ;
/*
-----------------------
set the message fields
created -- 96oct21, cca
-----------------------
*/
void
GPart_setMessageInfo (
GPart *gpart,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in makeYCmap.c -----------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------------
make the map from wide separator vertices Y
to components {0, 1, 2, 3}.
YCmap[y] == 0 --> y is not adjacent to either component
YCmap[y] == 1 --> y is adjacent to only component 1
YCmap[y] == 2 --> y is adjacent to only component 2
YCmap[y] == 3 --> y is adjacent to components 1 and 2
created -- 96jun09, cca
-------------------------------------------------------
*/
IV *
GPart_makeYCmap (
GPart *gpart,
IV *YVmapIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in RBviaDDsep.c ----------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------------------
this method constructs recursive partition of a graph.
it returns a DSTree object to represent the splitting of
the tree into subgraphs.
the info object contains the information needed by the
DDsep algorithm.
created -- 96feb24, cca
--------------------------------------------------------
*/
DSTree *
GPart_RBviaDDsep (
GPart *gpart,
DDsepInfo *info
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in smoothBisector.c ------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------
smooth a wide separator
nlevel -- number of levels one each side of the separator
to include into the separator
alpha -- partition cost function parameter
created -- 96jun02, cca
---------------------------------------------------------
*/
float
GPart_smoothBisector (
GPart *gpart,
int nlevel,
float alpha
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in smoothBy2layers.c -----------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------
smooth a bisector using the alternating two-layer algorithm
option -- network flag
1 --> make the network bipartite as for the
Dulmage-Mendelsohn decomposition
otherwise -- use network induced by the wide separator
alpha -- cost function parameter
created -- 96jun08, cca
-----------------------------------------------------------
*/
void
GPart_smoothBy2layers (
GPart *gpart,
int option,
float alpha
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in smoothYSep.c ----------------------------------
------------------------------------------------------------------------
*/
/*
------------------------------------------------------------
smooth the wide separator given by YVmapIV by forming
the associated network, solving the max flow problem,
and examining two min-cuts.
YVmapIV -- map from wide vertices Y to vertices V
YCmapIV -- map from wide vertices Y to {0,1,2,3}
YCmap[y] = 0 --> treat y as an internal node
adjacent to neither component
YCmap[y] = 1 --> treat y as adjacent only to component 1
YCmap[y] = 2 --> treat y as adjacent only to component 2
YCmap[y] = 3 --> treat y as adjacent to components 1 and 2
alpha -- cost function parameter
created -- 96jun08, cca
------------------------------------------------------------
*/
float
GPart_smoothYSep (
GPart *gpart,
IV *YVmapIV,
IV *YCmapIV,
float alpha
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in split.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
--------------------------------------------
split the graph partition object into pieces
created -- 95nov29, cca
--------------------------------------------
*/
void
GPart_split (
GPart *gpart
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in TwoSetViaBKL.c --------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------------
given a domain decomposition, find a bisector
1. construct the domain/segment graph
2. use block kernihan-lin to get an initial bisector
alpha -- cost function parameter for BKL
seed -- random number seed
cpus -- array to store CPU times
cpus[0] -- time to find domain/segment map
cpus[1] -- time to find domain/segment bipartite graph
cpus[2] -- time to find two-set partition
return value -- cost of the partition
created -- 96mar09, cca
-----------------------------------------------------------------
*/
double
GPart_TwoSetViaBKL (
GPart *gpart,
double alpha,
int seed,
double cpus[]
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
----- methods found in util.c ----------------------------------------
------------------------------------------------------------------------
*/
/*
----------------------------------------------------
set the component weights from the compids[] vector
created -- 95oct05, cca
modified -- 95nov29, cca
----------------------------------------------------
*/
void
GPart_setCweights (
GPart *gpart
) ;
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 95oct05, cca
----------------------------------------------
*/
int
GPart_sizeOf (
GPart *gpart
) ;
/*
----------------------------------------------------
return 1 if vertex is adjacent to only one domain
and fill *pdomid with the domain's id
return 0 otherwise
created -- 95oct19, cca
-------------------------------------------------
*/
int
GPart_vtxIsAdjToOneDomain (
GPart *gpart,
int v,
int *pdomid
) ;
/*
------------------------------------------------------
return 1 if the partition has a valid vertex separator
0 otherwise
created -- 95oct18, cca
------------------------------------------------------
*/
int
GPart_validVtxSep (
GPart *gpart
) ;
/*
-------------------------------------
return an IV object filled with the
weights of the component's boundaries
created -- 96oct21, cca
-------------------------------------
*/
IV *
GPart_bndWeightsIV (
GPart *gpart
) ;
/*--------------------------------------------------------------------*/
GPart/makefile 0100644 0002055 0007177 00000000223 06636223601 0014607 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd drivers ; make clean
cd doc ; make clean
GPart/src/makefile 0100644 0002055 0007177 00000001446 06636023232 0015404 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = GPart
$(OBJ).a : \
$(OBJ).a(DDviaFishnet.o) \
$(OBJ).a(DDviaProjection.o) \
$(OBJ).a(DDsepInfo.o) \
$(OBJ).a(RBviaDDsep.o) \
$(OBJ).a(TwoSetViaBKL.o) \
$(OBJ).a(basics.o) \
$(OBJ).a(domSegMap.o) \
$(OBJ).a(identifyWideSep.o) \
$(OBJ).a(init.o) \
$(OBJ).a(makeYCmap.o) \
$(OBJ).a(smoothBisector.o) \
$(OBJ).a(smoothBy2layers.o) \
$(OBJ).a(smoothYSep.o) \
$(OBJ).a(split.o) \
$(OBJ).a(util.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
GPart/src/makeGlobalLib 0100644 0002055 0007177 00000001172 06600261025 0016303 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = GPart
SRC = DDviaFishnet.c \
DDviaProjection.c \
DDsepInfo.c \
RBviaDDsep.c \
TwoSetViaBKL.c \
basics.c \
domSegMap.c \
identifyWideSep.c \
init.c \
makeYCmap.c \
smoothBisector.c \
smoothBy2layers.c \
smoothYSep.c \
split.c \
util.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
GPart/src/DDsepInfo.c 0100644 0002055 0007177 00000010116 06534106120 0015650 0 ustar 00cleve compmath 0000040 0000006 /* DDsepInfo.c */
#include "../DDsepInfo.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
------------------------------------------------
construct a new instance of the DDsepInfo object
created -- 96feb24, cca
------------------------------------------------
*/
DDsepInfo *
DDsepInfo_new (
void
) {
DDsepInfo *info ;
ALLOCATE(info, struct _DDsepInfo, 1) ;
DDsepInfo_setDefaultFields(info) ;
return(info) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
set the default fields of the DDsepInfo object
created -- 96feb24, cca
---------------------------------------------
*/
void
DDsepInfo_setDefaultFields (
DDsepInfo *info
) {
if ( info == NULL ) {
fprintf(stderr, "\n fatal error in DDsepInfo_setDefaultFields(%p)"
"\n bad input\n", info) ;
exit(-1) ;
}
info->seed = 1 ;
info->minweight = 40 ;
info->maxweight = 80 ;
info->freeze = 4.0 ;
info->alpha = 1.0 ;
info->maxcompweight = 500 ;
info->ntreeobj = 0 ;
info->DDoption = 1 ;
info->nlayer = 3 ;
info->cpuDD = 0.0 ;
info->cpuMap = 0.0 ;
info->cpuBPG = 0.0 ;
info->cpuBKL = 0.0 ;
info->cpuSmooth = 0.0 ;
info->cpuSplit = 0.0 ;
info->cpuTotal = 0.0 ;
info->msglvl = 0 ;
info->msgFile = stdout ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
clear the data fields for a DDsepInfo object
created -- 96feb24, cca
---------------------------------------------
*/
void
DDsepInfo_clearData (
DDsepInfo *info
) {
if ( info == NULL ) {
fprintf(stderr, "\n fatal error in DDsepInfo_clearData(%p)"
"\n bad input\n", info) ;
exit(-1) ;
}
DDsepInfo_setDefaultFields(info) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------
free the DDsepInfo object
created -- 96feb24, cca
------------------------
*/
void
DDsepInfo_free (
DDsepInfo *info
) {
if ( info == NULL ) {
fprintf(stderr, "\n fatal error in DDsepInfo_free(%p)"
"\n bad input\n", info) ;
exit(-1) ;
}
DDsepInfo_clearData(info) ;
#if MYDEBUG > 0
fprintf(stdout, "\n trying to free info") ;
fflush(stdout) ;
#endif
FREE(info) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
write the CPU times
created -- 97nov06, cca
-----------------------
*/
void
DDsepInfo_writeCpuTimes (
DDsepInfo *info,
FILE *msgFile
) {
double cpuMisc ;
/*
---------------
check the input
---------------
*/
if ( info == NULL || msgFile == NULL ) {
fprintf(stderr, "\n fatal error in DDsepInfo_writeCpuTimes(%p,%p)"
"\n bad input\n", info, msgFile) ;
exit(-1) ;
}
cpuMisc = info->cpuTotal - info->cpuDD - info->cpuSplit - info->cpuMap
- info->cpuBPG - info->cpuBKL - info->cpuSmooth ;
if ( info->cpuTotal > 0 ) {
fprintf(msgFile,
"\n\n CPU breakdown for graph partition"
"\n raw CPU per cent"
"\n misc : %9.2f %6.1f%%"
"\n Split : %9.2f %6.1f%%"
"\n find DD : %9.2f %6.1f%%"
"\n DomSeg Map : %9.2f %6.1f%%"
"\n DomSeg BPG : %9.2f %6.1f%%"
"\n BKL : %9.2f %6.1f%%"
"\n Smooth : %9.2f %6.1f%%"
"\n Total : %9.2f %6.1f%%",
cpuMisc, 100.*cpuMisc/info->cpuTotal,
info->cpuSplit, 100.*info->cpuSplit/info->cpuTotal,
info->cpuDD, 100.*info->cpuDD/info->cpuTotal,
info->cpuMap, 100.*info->cpuMap/info->cpuTotal,
info->cpuBPG, 100.*info->cpuBPG/info->cpuTotal,
info->cpuBKL, 100.*info->cpuBKL/info->cpuTotal,
info->cpuSmooth, 100.*info->cpuSmooth/info->cpuTotal,
info->cpuTotal, 100.) ;
}
return ; }
/*--------------------------------------------------------------------*/
GPart/src/DDviaFishnet.c 0100644 0002055 0007177 00000042013 06534106120 0016346 0 ustar 00cleve compmath 0000040 0000006 /* DDviaFishnet.c */
#include "../GPart.h"
#include "../../IIheap.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------
declarations for static functions
---------------------------------
*/
static int
GPart_freeze (
GPart *gpart,
double freeze,
int extdegs[]
) ;
static void
GPart_indpSetGrowth (
GPart *gpart,
int maxWeight,
int seed
) ;
static void
GPart_absDomains (
GPart *gpart,
int minweight
) ;
static void
GPart_absBoundary (
GPart *gpart
) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
purpose -- to construct and return a multisector
using the fishnet algorithm
freeze -- parameter used to keep nodes of high degree
in the interface
minweight -- minimum weight for a domain
maxweight -- maximum weight for a domain
seed -- random number seed
created -- 96feb16, cca
---------------------------------------------------------------
*/
void
GPart_DDviaFishnet (
GPart *gpart,
double freeze,
int minweight,
int maxweight,
int seed
) {
double cpus[6], t1, t2 ;
int nV, v ;
int *extdegs ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || freeze < 0.0
|| minweight < 0 || maxweight < 0 || minweight >= maxweight ) {
fprintf(stderr,
"\n fatal error in GPart_DDviaFishnet(%p,%f,%d,%d,%d)"
"\n bad input\n", gpart, freeze, minweight, maxweight, seed) ;
exit(-1) ;
}
/*
----------------------------
compute the external degrees
----------------------------
*/
MARKTIME(t1) ;
nV = gpart->g->nvtx ;
extdegs = IVinit(nV, 0) ;
for ( v = 0 ; v < nV ; v++ ) {
extdegs[v] = Graph_externalDegree(gpart->g, v) ;
}
MARKTIME(t2) ;
cpus[0] = t2 - t1 ;
/*
-------------------
freeze the vertices
-------------------
*/
MARKTIME(t1) ;
GPart_freeze(gpart, freeze, extdegs) ;
MARKTIME(t2) ;
cpus[1] = t2 - t1 ;
/*
---------------------------------------------
grow the partition via independent set growth
---------------------------------------------
*/
MARKTIME(t1) ;
GPart_indpSetGrowth(gpart, maxweight, seed) ;
IVfree(extdegs) ;
MARKTIME(t2) ;
cpus[2] = t2 - t1 ;
if ( gpart->ncomp == 1 ) {
IV_fill(&gpart->compidsIV, 1) ;
return ;
}
/*
------------------------
absorb the small domains
------------------------
*/
MARKTIME(t1) ;
GPart_absDomains(gpart, minweight) ;
MARKTIME(t2) ;
cpus[3] = t2 - t1 ;
if ( gpart->ncomp <= 1 ) {
IV_fill(&gpart->compidsIV, 1) ;
return ;
}
/*
--------------------------
absorb the excess boundary
--------------------------
*/
MARKTIME(t1) ;
GPart_absBoundary(gpart) ;
MARKTIME(t2) ;
cpus[4] = t2 - t1 ;
if ( gpart->msglvl > 1 ) {
fprintf(gpart->msgFile,
"\n FISHNET CPU breakdown"
"\n CPU %8.3f : compute external degrees"
"\n CPU %8.3f : freeze vertices of high degree"
"\n CPU %8.3f : independent set growth"
"\n CPU %8.3f : absorb small domains"
"\n CPU %8.3f : absorb excess boundary",
cpus[0], cpus[1], cpus[2], cpus[3], cpus[4]) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------
freeze vertices into the interface that
have external degree >= freeze * cutoff
return value -- # of frozen vertices
created -- 95oct05, cca
---------------------------------------
*/
static int
GPart_freeze (
GPart *gpart,
double freeze,
int extdegs[]
) {
Graph *g ;
int cutoff, iv, median, nfrozen, nvtx ;
int *compids, *vids ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || (g = gpart->g) == NULL || extdegs == NULL ) {
fprintf(stderr, "\n fatal error in GPart_freeze(%p,%f,%p)"
"\n bad input\n", gpart, freeze, extdegs) ;
exit(-1) ;
}
nvtx = gpart->nvtx ;
compids = IV_entries(&gpart->compidsIV) ;
/*
-------------------------------------------------------
sort the vertices in ascending order of external degree
-------------------------------------------------------
*/
vids = IVinit(nvtx, 0) ;
IVramp(nvtx, vids, 0, 1) ;
if ( gpart->msglvl > 3 ) {
int v ;
for ( v = 0 ; v < nvtx ; v++ ) {
fprintf(gpart->msgFile,
"\n vertex %d, external degree %d", v, extdegs[v]) ;
fflush(gpart->msgFile) ;
}
}
IV2qsortUp(nvtx, extdegs, vids) ;
/*
--------------------------------
get the median and cutoff values
--------------------------------
*/
median = extdegs[nvtx/2] ;
cutoff = (int) (freeze * median) ;
if ( gpart->msglvl > 2 ) {
fprintf(gpart->msgFile, "\n median = %d, cutoff = %d", median, cutoff) ;
fflush(gpart->msgFile) ;
}
/*
-------------------------------------------------------
freeze vertices whose degree is greater than the cutoff
-------------------------------------------------------
*/
nfrozen = 0 ;
for ( iv = nvtx - 1 ; iv >= 0 ; iv-- ) {
if ( extdegs[iv] < cutoff ) {
break ;
}
compids[vids[iv]] = 0 ;
nfrozen++ ;
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(vids) ;
return(nfrozen) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
set up the partition via independent set growth
maxWeight -- maximum weight for any domain
seed -- random number seed, if seed > 0 then
the vertices are visited in some random order,
else the vertices are visited 0, 1, ..., nvtx - 1
note : the gpart->compids[] vector is assumed to be initialized
outside this method. any vertex v such that compids[v] == -1
is eligible to be put into a domain. this allows the user
to pre-specify vertices to be in the separator (by setting
compids[v] = -1 prior to calling this method), e.g.,
vertices of abnormally high degree should be forced to be
separator vertices.
created -- 95oct05, cca
-------------------------------------------------------------------
*/
static void
GPart_indpSetGrowth (
GPart *gpart,
int maxWeight,
int seed
) {
Graph *g ;
int domweight, i, iv, last, ndom, now, nvtx, v, vsize, w ;
int *compids, *cweights, *list, *vadj, *vids, *vwghts ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || (g = gpart->g) == NULL || maxWeight < 0 ) {
fprintf(stderr, "\n fatal error in GPart_indpSepGrowth(%p,%d,%d)"
"\n bad input\n", gpart, maxWeight, seed) ;
exit(-1) ;
}
vwghts = g->vwghts ;
/*
--------------------------------
set all component ids != 0 to -1
--------------------------------
*/
nvtx = gpart->nvtx ;
compids = IV_entries(&gpart->compidsIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( compids[v] != 0 ) {
compids[v] = -1 ;
}
}
/*
-----------------------------------------------------------------
set up the vector that determines the order to visit the vertices
-----------------------------------------------------------------
*/
vids = IVinit2(nvtx) ;
IVramp(nvtx, vids, 0, 1) ;
if ( seed > 0 ) {
IVshuffle(nvtx, vids, seed) ;
}
/*
------------------------------
set up the working list vector
------------------------------
*/
list = IVinit(nvtx, -1) ;
/*
-----------------------------------
visit the vertices and grow domains
-----------------------------------
*/
ndom = 0 ;
for ( iv = 0 ; iv < nvtx ; iv++ ) {
v = vids[iv] ;
if ( gpart->msglvl > 4 ) {
fprintf(gpart->msgFile, "\n\n visiting v = %d, compids[%d] = %d",
v, v, compids[v]) ;
}
if ( compids[v] == -1 ) {
/*
-----------------------------------------
eligible vertex has not yet been visited,
create a new domain with v as the seed
-----------------------------------------
*/
ndom++ ;
if ( gpart->msglvl > 3 ) {
fprintf(gpart->msgFile,
"\n\n domain %d : seed vertex %d", ndom, v) ;
fflush(gpart->msgFile) ;
}
domweight = 0 ;
now = last = 0 ;
list[0] = v ;
while ( now <= last ) {
v = list[now++] ;
if ( gpart->msglvl > 4 ) {
fprintf(gpart->msgFile,
"\n adding %d to domain %d, weight %d",
v, ndom, ((vwghts != NULL) ? vwghts[v] : 1)) ;
fflush(gpart->msgFile) ;
}
/*
---------------------
add v to domain icomp
---------------------
*/
compids[v] = ndom ;
domweight += (vwghts != NULL) ? vwghts[v] : 1 ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( i = 0 ; i < vsize ; i++ ) {
if ( (w = vadj[i]) < nvtx && compids[w] == -1 ) {
/*
-----------------------------------------
w has not yet been touched, put on list
set compids[w] = -2 to make sure it isn't
put on the list twice
-----------------------------------------
*/
compids[w] = -2 ;
list[++last] = w ;
}
}
if ( domweight >= maxWeight ) {
/*
---------------------------------------------
domain is large enough, mark all the rest of
the vertices in the list as boundary vertices
---------------------------------------------
*/
while ( now <= last ) {
w = list[now++] ;
if ( gpart->msglvl > 4 ) {
fprintf(gpart->msgFile,
"\n adding %d to interface, weight %d",
w, ((vwghts != NULL) ? vwghts[w] : 1)) ;
fflush(gpart->msgFile) ;
}
compids[w] = 0 ;
}
}
}
if ( gpart->msglvl > 2 ) {
fprintf(gpart->msgFile,
"\n domain %d, weight %d", ndom, domweight) ;
fflush(gpart->msgFile) ;
}
}
}
/*
---------------------------------------------------------------------
set the number of components and resize the component weights vector
---------------------------------------------------------------------
*/
gpart->ncomp = ndom ;
IV_setSize(&gpart->cweightsIV, 1 + ndom) ;
IV_fill(&gpart->cweightsIV, 0) ;
cweights = IV_entries(&gpart->cweightsIV) ;
/*
-----------------------------------------------
set the weights of the interface and components
-----------------------------------------------
*/
if ( vwghts != NULL ) {
for ( v = 0 ; v < nvtx ; v++ ) {
cweights[compids[v]] += vwghts[v] ;
}
} else {
for ( v = 0 ; v < nvtx ; v++ ) {
cweights[compids[v]]++ ;
}
}
/*
-------------------------
free the two work vectors
-------------------------
*/
IVfree(list) ;
IVfree(vids) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------
absorb small domains into the interface.
this method assumes that the component weights vector has been set
95oct05, cca
------------------------------------------------------------------
*/
static void
GPart_absDomains (
GPart *gpart,
int minweight
) {
Graph *g ;
int c, ierr, ndom, nnewdom, nvtx, v ;
int *compids, *cweights, *dmap, *head, *link, *vwghts ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || (g = gpart->g) == NULL ) {
fprintf(stderr, "\n fatal error in GPart_absDomains(%p,%d)"
"\n bad input\n", gpart, minweight) ;
exit(-1) ;
}
nvtx = gpart->nvtx ;
vwghts = g->vwghts ;
ndom = gpart->ncomp ;
compids = IV_entries(&gpart->compidsIV) ;
cweights = IV_entries(&gpart->cweightsIV) ;
/*
----------------------------------------------
get the linked list for vertices and component
----------------------------------------------
*/
head = IVinit(ndom+1, -1) ;
link = IVinit(nvtx, -1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
c = compids[v] ;
link[v] = head[c] ;
head[c] = v ;
}
dmap = IVinit(ndom+1, -1) ;
nnewdom = 0 ;
dmap[0] = 0 ;
for ( c = 1 ; c <= ndom ; c++ ) {
if ( cweights[c] < minweight ) {
if ( gpart->msglvl > 2 ) {
fprintf(gpart->msgFile,
"\n interface absorbs component %d, weight %d",
c, cweights[c]) ;
fflush(gpart->msgFile) ;
}
for ( v = head[c] ; v != -1 ; v = link[v] ) {
compids[v] = 0 ;
}
cweights[0] += cweights[c] ;
cweights[c] = 0 ;
dmap[c] = 0 ;
} else {
dmap[c] = ++nnewdom ;
}
if ( gpart->msglvl > 2 ) {
fprintf(gpart->msgFile, "\n dmap[%d] = %d", c, dmap[c]) ;
fflush(gpart->msgFile) ;
}
}
if ( nnewdom != ndom ) {
/*
------------------------
set the new # of domains
------------------------
*/
gpart->ncomp = nnewdom ;
/*
-------------------------
set the new component ids
-------------------------
*/
if ( gpart->msglvl > 3 ) {
fprintf(gpart->msgFile, "\n old component ids") ;
IVfp80(gpart->msgFile, nvtx, compids, 80, &ierr) ;
fflush(gpart->msgFile) ;
}
for ( v = 0 ; v < nvtx ; v++ ) {
c = compids[v] ;
compids[v] = dmap[c] ;
}
if ( gpart->msglvl > 3 ) {
fprintf(gpart->msgFile, "\n new component ids") ;
IVfp80(gpart->msgFile, nvtx, compids, 80, &ierr) ;
fflush(gpart->msgFile) ;
}
/*
-----------------------------
set the new component weights
-----------------------------
*/
if ( gpart->msglvl > 2 ) {
fprintf(gpart->msgFile, "\n old cweights") ;
IVfp80(gpart->msgFile, ndom+1, cweights, 80, &ierr) ;
fflush(gpart->msgFile) ;
}
for ( c = 1 ; c <= ndom ; c++ ) {
if ( dmap[c] != 0 ) {
cweights[dmap[c]] = cweights[c] ;
}
}
IV_setSize(&gpart->cweightsIV, nnewdom) ;
if ( gpart->msglvl > 2 ) {
fprintf(gpart->msgFile, "\n new cweights") ;
IVfp80(gpart->msgFile, nnewdom+1, cweights, 80, &ierr) ;
fflush(gpart->msgFile) ;
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(head) ;
IVfree(link) ;
IVfree(dmap) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
absorb the excess boundary
created -- 95oct05, cca
revised -- 95oct19, cca
very simple scheme
------------------------------------------------------------
*/
static void
GPart_absBoundary (
GPart *gpart
) {
Graph *g ;
int count, domid, ierr, ii, oldcount, ntest, nvtx, rc, v, vwght ;
int *compids, *cweights, *list, *vwghts ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || (g = gpart->g) == NULL ) {
fprintf(stderr, "\n fatal error in GPart_absBoundary(%p)"
"\n bad input\n", gpart) ;
exit(-1) ;
}
nvtx = gpart->nvtx ;
compids = IV_entries(&gpart->compidsIV) ;
cweights = IV_entries(&gpart->cweightsIV) ;
vwghts = gpart->g->vwghts ;
/*
----------------------
create working storage
----------------------
*/
list = IVinit(nvtx, -1) ;
/*
-----------------------------------------
load all interface vertices into the list
------------------------------------------
*/
count = 0 ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( compids[v] == 0 ) {
list[count++] = v ;
}
}
oldcount = -1 ;
while ( count > 0 ) {
if ( gpart->msglvl > 2 ) {
fprintf(gpart->msgFile, "\n\n new pass, count = %d", count) ;
}
ntest = count ;
count = 0 ;
for ( ii = 0 ; ii < ntest ; ii++ ) {
v = list[ii] ;
rc = GPart_vtxIsAdjToOneDomain(gpart, v, &domid) ;
if ( rc == 1 ) {
/*
-----------------------------------------
transfer interface vertex v into domain c
-----------------------------------------
*/
compids[v] = domid ;
vwght = (vwghts != NULL) ? vwghts[v] : 1 ;
cweights[0] -= vwght ;
cweights[domid] += vwght ;
if ( gpart->msglvl > 3 ) {
fprintf(gpart->msgFile,
"\n moving vertex %d with weight %d to domain %d"
"\n now, cweights[0] = %d, cweights[%d] = %d",
v, vwght, domid, cweights[0], domid, cweights[domid]) ;
fflush(gpart->msgFile) ;
}
} else if ( domid == -1 ) {
/*
----------------------------------------------------------
vertex v is still not adjacent to any domain, keep on list
----------------------------------------------------------
*/
if ( gpart->msglvl > 3 ) {
fprintf(gpart->msgFile,
"\n keeping vertex %d on list", v) ;
}
list[count++] = v ;
}
}
if ( count == oldcount ) {
break ;
} else {
oldcount = count ;
}
}
IVfree(list) ;
return ; }
/*--------------------------------------------------------------------*/
}
}
/*
-----------------------------------------------------------------
set up the vector that determines the order to visit the vertices
-----------------------------------------------------------------
*/
vids = IVinit2(nvtx) ;
IVramp(nvtx, vids, 0, 1) ;
if ( seed > 0 ) {
IVshuffle(nvtx, vids, seed) ;
}
/*
------------------------------
set up the working list vector
------------------------------
*/
list = IVinit(nvtx, -1) ;
/*
-----------------------------------
GPart/src/DDviaProjection.c 0100644 0002055 0007177 00000003615 06534106120 0017067 0 ustar 00cleve compmath 0000040 0000006 /* DDviaProjection.c */
#include"../GPart.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
set the compids[] vector using a global map from vertices
to domains and interface nodes.
DDmapIV -- IV object that contains the map from vertices
to domains and interface nodes
created -- 96mar17, cca
---------------------------------------------------------
*/
void
GPart_DDviaProjection (
GPart *gpart,
IV *DDmapIV
) {
int *compids, *domainMap, *map, *vtxMap ;
int dom, domloc, ndom, ndomloc, nvtx, vglob, vloc ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || DDmapIV == NULL ) {
fprintf(stderr, "\n fatal error in GPart_DDviaProjection(%p,%p)"
"\n bad input\n", gpart, DDmapIV) ;
exit(-1) ;
}
nvtx = gpart->nvtx ;
compids = IV_entries(&gpart->compidsIV) ;
/*
--------------------------
find the number of domains
--------------------------
*/
vtxMap = IV_entries(&gpart->vtxMapIV) ;
map = IV_entries(DDmapIV) ;
ndom = IV_max(DDmapIV) ;
/*
------------------------
check for a quick return
------------------------
*/
if ( gpart->par == NULL ) {
IVcopy(nvtx, compids, map) ;
gpart->ncomp = ndom ;
return ;
}
/*
----------------------------------------
fill compids[] with the local domain ids
----------------------------------------
*/
domainMap = IVinit(ndom+1, -1) ;
ndomloc = 0 ;
for ( vloc = 0 ; vloc < nvtx ; vloc++ ) {
vglob = vtxMap[vloc] ;
if ( (dom = map[vglob]) > 0 ) {
if ( (domloc = domainMap[dom]) == -1 ) {
domloc = domainMap[dom] = ++ndomloc ;
}
compids[vloc] = domloc ;
} else {
compids[vloc] = 0 ;
}
}
gpart->ncomp = ndomloc ;
IVfree(domainMap) ;
return ; }
/*--------------------------------------------------------------------*/
GPart/src/RBviaDDsep.c 0100644 0002055 0007177 00000036412 06534106120 0015767 0 ustar 00cleve compmath 0000040 0000006 /* RBviaDDsep.c */
#include "../DDsepInfo.h"
#include "../GPart.h"
#include "../../timings.h"
#define NSPLIT 8
#define BE_CAUTIOUS 0
/*--------------------------------------------------------------------*/
/*
-----------------------------------
prototype for static visit() method
-----------------------------------
*/
static void visit ( GPart *gpart, int map[], int vpar[],
IV *DDmapIV, DDsepInfo *info) ;
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
this method constructs recursive partition of a graph.
it returns a DSTree object to represent the splitting of
the tree into subgraphs.
the info object contains the information needed by the
DDsep algorithm.
created -- 96feb24, cca
--------------------------------------------------------
*/
DSTree *
GPart_RBviaDDsep (
GPart *gpart,
DDsepInfo *info
) {
double t0, t1, t2, t3 ;
DSTree *dstree ;
FILE *msgFile ;
GPart *child ;
int ierr, msglvl, nvtx ;
int *map, *vpar ;
IV *DDmapIV, *DSmapIV ;
Tree *tree ;
/*
---------------
check the input
---------------
*/
MARKTIME(t0) ;
if ( gpart == NULL
|| (nvtx = gpart->nvtx) <= 0
|| info == NULL
) {
fprintf(stderr, "\n fatal error in GPart_RBviaDDsep(%p,%p)"
"\n bad input\n", gpart, info) ;
exit(-1) ;
}
msglvl = gpart->msglvl ;
msgFile = gpart->msgFile ;
/*
-------------------------
check that gpart is a root
-------------------------
*/
if ( gpart->par != NULL ) {
fprintf(stderr, "\n fatal error in GPart_RBviaDDsep(%p,%p)"
"\n gpart must be a root \n", gpart, info) ;
exit(-1) ;
}
/*
-----------------------------
create map and parent vectors
-----------------------------
*/
vpar = IVinit(nvtx, -1) ;
DSmapIV = IV_new() ;
IV_init(DSmapIV, nvtx, NULL) ;
map = IV_entries(DSmapIV) ;
IVfill(nvtx, map, -1) ;
info->ntreeobj = 0 ;
if ( info->DDoption == 2 ) {
/*
------------------------------------------------
get one global domain decomposition via fishnet,
then project it on each subgraph
------------------------------------------------
*/
MARKTIME(t1) ;
GPart_DDviaFishnet(gpart, info->freeze, info->minweight,
info->maxweight, info->seed) ;
DDmapIV = IV_new() ;
IV_init(DDmapIV, nvtx, NULL) ;
IV_copy(DDmapIV, &gpart->compidsIV) ;
IV_fill(&gpart->compidsIV, 1) ;
MARKTIME(t2) ;
info->cpuDD += t2 - t1 ;
} else {
DDmapIV = NULL ;
}
/*
---------------------------------------------
split the graph into its connected components
---------------------------------------------
*/
MARKTIME(t1) ;
GPart_split(gpart) ;
MARKTIME(t2) ;
info->cpuSplit += t2 - t1 ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n after initial split, ncomp = %d",
gpart->ncomp) ;
fflush(msgFile) ;
}
if ( gpart->ncomp > 0 ) {
for ( child = gpart->fch ; child != NULL ; child = child->sib ) {
child->id = info->ntreeobj++ ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n\n ### component %d", child->id) ;
Graph_writeStats(child->g, msgFile) ;
if ( msglvl > 3 && msgFile != NULL ) {
Graph_writeForHumanEye(child->g, msgFile) ;
if ( IV_size(&child->vtxMapIV) > 0 ) {
fprintf(msgFile,
"\n vtxMap(%d) :", child->nvtx) ;
IV_fp80(&child->vtxMapIV, msgFile, 80, &ierr) ;
}
}
}
fflush(msgFile) ;
}
}
/*
------------------------------
visit each connected component
------------------------------
*/
if ( gpart->fch != NULL ) {
while ( (child = gpart->fch) != NULL ) {
gpart->fch = child->sib ;
visit(child, map, vpar, DDmapIV, info) ;
Graph_free(child->g) ;
GPart_free(child) ;
}
} else {
gpart->id = info->ntreeobj++ ;
visit(gpart, map, vpar, DDmapIV, info) ;
}
/*
------------------------
create the DSTree object
------------------------
*/
tree = Tree_new() ;
Tree_init2(tree, info->ntreeobj, vpar) ;
dstree = DSTree_new() ;
DSTree_init2(dstree, tree, DSmapIV) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(vpar) ;
MARKTIME(t3) ;
info->cpuTotal = t3 - t0 ;
return(dstree) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
this method is called for each connected subgraph in the
subgraph tree.
map -- vector mapping vertices to subgraph number
vpar -- vector mapping a subgraph to its parent subgraph
info -- information structure for DDsep
created -- 96feb24, cca
--------------------------------------------------------
*/
static void
visit (
GPart *gpart,
int map[],
int vpar[],
IV *DDmapIV,
DDsepInfo *info
) {
double t1, t2 ;
double cpus[3] ;
FILE *msgFile ;
GPart *child, *par ;
Graph *g ;
int ierr, ii, maxweight, minweight, msglvl,
nvbnd, nvtot, nvtx, parnvtot, totvwght, v, vsize, width ;
int *compids, *parmap, *vadj, *vtxMap ;
/*
-------------------------------
extract dimensions and pointers
-------------------------------
*/
g = gpart->g ;
nvtx = g->nvtx ;
nvbnd = g->nvbnd ;
nvtot = nvtx + nvbnd ;
compids = IV_entries(&gpart->compidsIV) ;
vtxMap = IV_entries(&gpart->vtxMapIV) ;
msgFile = gpart->msgFile ;
msglvl = gpart->msglvl ;
/*
------------------------------
compute the total graph weight
------------------------------
*/
if ( g->type % 2 == 0 ) {
totvwght = nvtx ;
} else {
totvwght = IVsum(nvtx, g->vwghts) ;
}
/*
-----------------
optional messages
-----------------
*/
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile,
"\n\n ### inside visit(%d), parent = %d"
"\n nvtx = %d, nvbnd = %d, nvtot = %d, totvwght = %d",
gpart->id, (gpart->par != NULL) ? gpart->par->id : -1,
nvtx, nvbnd, nvtot, totvwght) ;
fflush(msgFile) ;
}
if ( msglvl > 2 && msgFile != NULL ) {
Graph_writeForHumanEye(gpart->g, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------------
set the vertex map to be global
-------------------------------
*/
if ( (par = gpart->par) != NULL
&& (parmap = IV_entries(&par->vtxMapIV)) != NULL ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n before changing map") ;
fprintf(msgFile, "\n vtxMapIV") ;
IV_writeForHumanEye(&gpart->vtxMapIV, msgFile) ;
fprintf(msgFile, "\n parVtxMapIV") ;
IV_writeForHumanEye(&par->vtxMapIV, msgFile) ;
fflush(msgFile) ;
IV_fp80(&gpart->vtxMapIV, msgFile, 80, &ierr) ;
fflush(msgFile) ;
}
parnvtot = par->nvtx + par->nvbnd ;
for ( v = 0 ; v < nvtot ; v++ ) {
#if BE_CAUTIOUS > 0
if ( vtxMap[v] < 0 || vtxMap[v] >= parnvtot ) {
fprintf(stderr,
"\n error changing map, vtxMap[[%d] = %d, parnvtot = %d",
v, vtxMap[v], parnvtot) ;
exit(-1) ;
}
#endif
vtxMap[v] = parmap[vtxMap[v]] ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n after changing map") ;
IV_fp80(&gpart->vtxMapIV, msgFile, 80, &ierr) ;
fflush(msgFile) ;
}
}
if ( totvwght <= info->maxcompweight ) {
gpart->ncomp = 1 ;
} else {
/*
----------------------------------------------
try to find a bisector via the DDsep algorithm
----------------------------------------------
*/
if ( msglvl > 1 ) {
fprintf(msgFile, "\n try to find a bisector") ;
fflush(msgFile) ;
}
MARKTIME(t1) ;
switch ( info->DDoption ) {
case 1 :
/*
----------------------------------------------------------
use the fishnet algorithm to find the domain decomposition
----------------------------------------------------------
*/
if ( info->maxweight * NSPLIT <= totvwght ) {
minweight = info->minweight ;
maxweight = info->maxweight ;
} else {
maxweight = totvwght / NSPLIT ;
if ( maxweight < 2 ) {
maxweight = 2 ;
}
minweight = maxweight / 2 ;
}
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n calling DDviaFishnet with minweight = %d, maxweight = %d",
minweight, maxweight) ;
fflush(msgFile) ;
}
GPart_DDviaFishnet(gpart, info->freeze, minweight,
maxweight, info->seed) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n return from DDviaFishnet") ;
fflush(msgFile) ;
}
break ;
case 2 :
/*
-----------------------------------------------------------------
use projection from a global map to find the domain decomposition
-----------------------------------------------------------------
*/
GPart_DDviaProjection(gpart, DDmapIV) ;
break ;
}
MARKTIME(t2) ;
info->cpuDD += t2 - t1 ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n after DD: %d domains", gpart->ncomp) ;
}
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n partition weights :") ;
IV_fp80(&gpart->cweightsIV, msgFile, 25, &ierr) ;
}
#if BE_CAUTIOUS > 0
if ( GPart_validVtxSep(gpart) == 1 ) {
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(stdout, "\n DD: valid vertex separator ") ;
}
} else {
fprintf(stderr, "\n DD: invalid vertex separator ") ;
exit(-1) ;
}
#endif
if ( gpart->ncomp > 1 ) {
/*
--------------------------------
find an initial bisector via BKL
--------------------------------
*/
GPart_TwoSetViaBKL(gpart, info->alpha, info->seed, cpus) ;
info->cpuMap += cpus[0] ;
info->cpuBPG += cpus[1] ;
info->cpuBKL += cpus[2] ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n BKL final weights : ") ;
IV_fp80(&gpart->cweightsIV, msgFile, 25, &ierr) ;
}
#if BE_CAUTIOUS > 0
if ( GPart_validVtxSep(gpart) == 1 ) {
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(stdout, "\n BKL: valid vertex separator ") ;
}
} else {
fprintf(stderr, "\n BKL: invalid vertex separator ") ;
exit(-1) ;
}
#endif
}
if ( gpart->ncomp > 1 ) {
/*
---------------------------------------
find an improved bisector via smoothing
---------------------------------------
*/
MARKTIME(t1) ;
if ( info->nlayer <= 2 ) {
GPart_smoothBy2layers(gpart, info->nlayer, info->alpha) ;
} else if ( (width = info->nlayer/2) > 0 ) {
GPart_smoothBisector(gpart, width, info->alpha) ;
}
MARKTIME(t2) ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n smoothed weights : ") ;
IV_fp80(&gpart->cweightsIV, msgFile, 25, &ierr) ;
}
#if BE_CAUTIOUS > 0
if ( GPart_validVtxSep(gpart) == 1 ) {
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(stdout, "\n smoothed: valid vertex separator ") ;
}
} else {
fprintf(stderr, "\n smoothed: invalid vertex separator ") ;
exit(-1) ;
}
#endif
info->cpuSmooth += t2 - t1 ;
}
if ( gpart->ncomp > 1 ) {
/*
----------------------------------
split the subgraph into components
----------------------------------
*/
MARKTIME(t1) ;
GPart_split(gpart) ;
MARKTIME(t2) ;
info->cpuSplit += t2 - t1 ;
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n SPLIT weights : ") ;
IV_fp80(&gpart->cweightsIV, msgFile, 20, &ierr) ;
fflush(msgFile) ;
}
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile, "\n compids") ;
IV_fp80(&gpart->compidsIV, msgFile, 80, &ierr) ;
fflush(msgFile) ;
}
}
}
if ( gpart->ncomp > 1 ) {
/*
---------------------------------------
a separator was found and the graph has
been split into connected components
---------------------------------------
*/
for ( child = gpart->fch ; child != NULL ; child = child->sib) {
child->id = info->ntreeobj++ ;
vpar[child->id] = gpart->id ;
}
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile,
"\n after initial split, ncomp = %d", gpart->ncomp) ;
for ( child = gpart->fch ; child != NULL ; child = child->sib) {
fprintf(msgFile, "\n\n ### component %d", child->id) ;
Graph_writeStats(child->g, msgFile) ;
if ( msglvl > 3 && msgFile != NULL ) {
Graph_writeForHumanEye(child->g, msgFile) ;
if ( IV_size(&child->vtxMapIV) > 0 ) {
fprintf(msgFile,
"\n vtxMap(%d) :", child->nvtx) ;
IV_fp80(&child->vtxMapIV, msgFile, 80, &ierr) ;
}
}
}
fflush(msgFile) ;
}
/*
------------------------------
visit each connected component
------------------------------
*/
while ( (child = gpart->fch) != NULL ) {
gpart->fch = child->sib ;
visit(child, map, vpar, DDmapIV, info) ;
if ( msglvl > 2 && msgFile != NULL ) {
fprintf(msgFile,
"\n return from visiting child %d", child->id) ;
fflush(msgFile) ;
}
Graph_free(child->g) ;
GPart_free(child) ;
}
/*
-----------------------------------------------------------
map adjacency structure of the separator back to the global
numbering and set the map for the separator vertices
-----------------------------------------------------------
*/
if ( gpart->par != NULL ) {
for ( v = 0 ; v < nvtx ; v++ ) {
if ( compids[v] == 0 ) {
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
#if BE_CAUTIOUS > 0
if ( vadj[ii] < 0 || vadj[ii] >= nvtot ) {
fprintf(stderr,
"\n 1.0 whoa, error, vadj[[%d] = %d, nvtot = %d",
ii, vadj[ii], nvtot) ;
exit(-1) ;
}
#endif
vadj[ii] = vtxMap[vadj[ii]] ;
}
map[vtxMap[v]] = gpart->id ;
}
}
} else {
for ( v = 0 ; v < nvtx ; v++ ) {
if ( compids[v] == 0 ) {
map[v] = gpart->id ;
}
}
}
} else {
/*
-----------------------------------------------------
the subgraph was not split. map the adjacency back to
the global numbering and set the map for the vertices
-----------------------------------------------------
*/
if ( msglvl > 1 && msgFile != NULL ) {
fprintf(msgFile, "\n this subgraph is a domain") ;
}
if ( gpart->par != NULL ) {
for ( v = 0 ; v < nvtx ; v++ ) {
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
#if BE_CAUTIOUS > 0
if ( vadj[ii] < 0 || vadj[ii] >= nvtot ) {
fprintf(stderr,
"\n 2.0 whoa, error, vadj[[%d] = %d, nvtot = %d",
ii, vadj[ii], nvtot) ;
exit(-1) ;
}
#endif
vadj[ii] = vtxMap[vadj[ii]] ;
}
}
for ( v = 0 ; v < nvtx ; v++ ) {
map[vtxMap[v]] = gpart->id ;
}
} else {
for ( v = 0 ; v < nvtx ; v++ ) {
map[v] = gpart->id ;
}
}
}
return ; }
/*--------------------------------------------------------------------*/
= gpart->g ;
nvtx = g->nvtx ;
nvbnd = g->nvbnd ;
nvtot = nvtx + nvbnd ;
compids = IV_entries(&gpart->compidsIV) ;
vtxMap = IV_entries(&gpart->vtxMapIV) ;
msgFile = gpart->msgFile ;
msglvl = gpart->msglvl ;
/*
---------------------GPart/src/TwoSetViaBKL.c 0100644 0002055 0007177 00000014230 06534106120 0016254 0 ustar 00cleve compmath 0000040 0000006 /* TwoSetViaBKL.c */
#include "../GPart.h"
#include "../../BKL.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------------
given a domain decomposition, find a bisector
1. construct the domain/segment graph
2. use block kernihan-lin to get an initial bisector
alpha -- cost function parameter for BKL
seed -- random number seed
cpus -- array to store CPU times
cpus[0] -- time to find domain/segment map
cpus[1] -- time to find domain/segment bipartite graph
cpus[2] -- time to find two-set partition
return value -- cost of the partition
created -- 96mar09, cca
-----------------------------------------------------------------
*/
double
GPart_TwoSetViaBKL (
GPart *gpart,
double alpha,
int seed,
double cpus[]
) {
BKL *bkl ;
BPG *bpg ;
double t1, t2 ;
FILE *msgFile ;
float bestcost ;
Graph *g, *gc ;
int c, flag, ierr, msglvl, ndom, nseg, nvtx, v ;
int *compids, *cweights, *dscolors, *dsmap, *vwghts ;
IV *dsmapIV ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || cpus == NULL ) {
fprintf(stderr, "\n fatal error in GPart_DDsep(%p,%f,%d,%p)"
"\n bad input\n", gpart, alpha, seed, cpus) ;
exit(-1) ;
}
g = gpart->g ;
nvtx = gpart->nvtx ;
compids = IV_entries(&gpart->compidsIV) ;
cweights = IV_entries(&gpart->cweightsIV) ;
vwghts = g->vwghts ;
msglvl = gpart->msglvl ;
msgFile = gpart->msgFile ;
/*
HARDCODE THE ALPHA PARAMETER.
*/
alpha = 1.0 ;
/*
------------------------------
(1) get the domain/segment map
(2) get the compressed graph
(3) create the bipartite graph
------------------------------
*/
MARKTIME(t1) ;
dsmapIV = GPart_domSegMap(gpart, &ndom, &nseg) ;
dsmap = IV_entries(dsmapIV) ;
MARKTIME(t2) ;
cpus[0] = t2 - t1 ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n CPU %9.5f : generate domain-segment map",
t2 - t1) ;
fprintf(msgFile, "\n ndom = %d, nseg = %d", ndom, nseg) ;
fflush(msgFile) ;
}
/*
-----------------------------------------
create the domain/segment bipartite graph
-----------------------------------------
*/
MARKTIME(t1) ;
gc = Graph_compress(gpart->g, dsmap, 1) ;
bpg = BPG_new() ;
BPG_init(bpg, ndom, nseg, gc) ;
MARKTIME(t2) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n CPU %9.5f : create domain-segment graph",
t2 - t1) ;
fflush(msgFile) ;
}
cpus[1] = t2 - t1 ;
if ( msglvl > 2 ) {
if ( bpg->graph->vwghts != NULL ) {
fprintf(msgFile, "\n domain weights :") ;
IVfp80(msgFile, bpg->nX, bpg->graph->vwghts, 17, &ierr) ;
fprintf(msgFile, "\n segment weights :") ;
IVfp80(msgFile, bpg->nY, bpg->graph->vwghts+bpg->nX, 18, &ierr) ;
fflush(msgFile) ;
}
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n dsmapIV ") ;
IV_writeForHumanEye(dsmapIV, msgFile) ;
fprintf(msgFile, "\n\n domain/segment bipartite graph ") ;
BPG_writeForHumanEye(bpg, msgFile) ;
fflush(msgFile) ;
}
/*
------------------------------------
create and initialize the BKL object
------------------------------------
*/
MARKTIME(t1) ;
flag = 5 ;
bkl = BKL_new() ;
BKL_init(bkl, bpg, alpha) ;
BKL_setInitPart(bkl, flag, seed, NULL) ;
bestcost = BKL_evalfcn(bkl) ;
gpart->ncomp = 2 ;
MARKTIME(t2) ;
cpus[2] = t2 - t1 ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n CPU %9.5f : initialize BKL object", t2 - t1) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n BKL : flag = %d, seed = %d", flag, seed) ;
fprintf(msgFile, ", initial cost = %.2f", bestcost) ;
fflush(msgFile) ;
fprintf(msgFile, ", cweights = < %d %d %d >",
bkl->cweights[0], bkl->cweights[1], bkl->cweights[2]) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n colors") ;
IVfp80(msgFile, bkl->nreg, bkl->colors, 80, &ierr) ;
fflush(msgFile) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n BKL initial weights : ") ;
IVfp80(msgFile, 3, bkl->cweights, 25, &ierr) ;
fflush(msgFile) ;
}
/*
--------------------------------
improve the partition via fidmat
--------------------------------
*/
MARKTIME(t1) ;
bestcost = BKL_fidmat(bkl) ;
MARKTIME(t2) ;
cpus[2] += t2 - t1 ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n CPU %9.5f : improve the partition via fidmat",
t2 - t1) ;
fflush(msgFile) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n BKL : %d passes", bkl->npass) ;
fprintf(msgFile, ", %d flips", bkl->nflips) ;
fprintf(msgFile, ", %d gainevals", bkl->ngaineval) ;
fprintf(msgFile, ", %d improve steps", bkl->nimprove) ;
fprintf(msgFile, ", cost = %9.2f", bestcost) ;
}
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n BKL STATS < %9d %9d %9d > %9.2f < %4d %4d %4d %4d %4d >",
bkl->cweights[0], bkl->cweights[1], bkl->cweights[2],
bestcost, bkl->npass, bkl->npatch, bkl->nflips, bkl->nimprove,
bkl->ngaineval) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n colors") ;
IVfp80(msgFile, bkl->nreg, bkl->colors, 80, &ierr) ;
fflush(msgFile) ;
}
/*
----------------------------
set compids[] and cweights[]
----------------------------
*/
MARKTIME(t1) ;
dscolors = bkl->colors ;
gpart->ncomp = 2 ;
IV_setSize(&gpart->cweightsIV, 3) ;
cweights = IV_entries(&gpart->cweightsIV) ;
cweights[0] = cweights[1] = cweights[2] = 0 ;
if ( vwghts == NULL ) {
for ( v = 0 ; v < nvtx ; v++ ) {
compids[v] = c = dscolors[dsmap[v]] ;
cweights[c]++ ;
}
} else {
for ( v = 0 ; v < nvtx ; v++ ) {
compids[v] = c = dscolors[dsmap[v]] ;
cweights[c] += vwghts[v] ;
}
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n BKL partition : < %d %d %d >",
cweights[0], cweights[1], cweights[2]) ;
fflush(msgFile) ;
}
/*
------------------------------------
free the BKL object, the BPG object
and the domain/segment map IV object
------------------------------------
*/
BKL_free(bkl) ;
IV_free(dsmapIV) ;
BPG_free(bpg) ;
MARKTIME(t2) ;
cpus[2] += t2 - t1 ;
return((double) bestcost) ; }
/*--------------------------------------------------------------------*/
sgFile) ;
}
/*
-----------------------------------------
create the domain/segment bipartite graph
-----------------------------------------
*/
MARKTIME(t1) ;
gc = Graph_compress(gpart->g, dsmap, 1) ;
bpg = BPG_new() ;
BPG_init(bpg, ndom, nseg, gc) ;
MARKTIME(t2) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n CPU %9.5f : create domain-segment graph",GPart/src/basics.c 0100644 0002055 0007177 00000005122 06534106120 0015302 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../GPart.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
construct a new instance of the GPart object
created -- 95oct05, cca
--------------------------------------------
*/
GPart *
GPart_new (
void
) {
GPart *gpart ;
ALLOCATE(gpart, struct _GPart, 1) ;
GPart_setDefaultFields(gpart) ;
return(gpart) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
set the default fields of the GPart object
created -- 95oct05, cca
modified -- 95nov29, cca
par, fch, sib and vtxMap fields included
---------------------------------------------
*/
void
GPart_setDefaultFields (
GPart *gpart
) {
if ( gpart == NULL ) {
fprintf(stderr, "\n fatal error in GPart_setDefaultFields(%p)"
"\n bad input\n", gpart) ;
exit(-1) ;
}
gpart->id = -1 ;
gpart->g = NULL ;
gpart->nvtx = 0 ;
gpart->nvbnd = 0 ;
gpart->ncomp = 0 ;
gpart->par = NULL ;
gpart->fch = NULL ;
gpart->sib = NULL ;
IV_setDefaultFields(&gpart->compidsIV) ;
IV_setDefaultFields(&gpart->cweightsIV) ;
IV_setDefaultFields(&gpart->vtxMapIV) ;
gpart->msglvl = 0 ;
gpart->msgFile = NULL ;
return ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
clear the data fields for a GPart object
created -- 95oct05, cca
modified -- 95nov29, cca
par, fch, sib and vtxMap fields included
---------------------------------------------
*/
void
GPart_clearData (
GPart *gpart
) {
if ( gpart == NULL ) {
fprintf(stderr, "\n fatal error in GPart_clearData(%p)"
"\n bad input\n", gpart) ;
exit(-1) ;
}
IV_clearData(&gpart->compidsIV) ;
IV_clearData(&gpart->cweightsIV) ;
IV_clearData(&gpart->vtxMapIV) ;
GPart_setDefaultFields(gpart) ;
return ; }
/*--------------------------------------------------------------------*/
/*
------------------------
free the GPart object
created -- 95oct05, cca
modified -- 95nov29, cca
gpart now free'd
------------------------
*/
void
GPart_free (
GPart *gpart
) {
if ( gpart == NULL ) {
fprintf(stderr, "\n fatal error in GPart_free(%p)"
"\n bad input\n", gpart) ;
exit(-1) ;
}
GPart_clearData(gpart) ;
#if MYDEBUG > 0
fprintf(stdout, "\n trying to free gpart") ;
fflush(stdout) ;
#endif
FREE(gpart) ;
return ; }
/*--------------------------------------------------------------------*/
GPart/src/domSegMap.c 0100644 0002055 0007177 00000032234 06540252072 0015723 0 ustar 00cleve compmath 0000040 0000006 /* domSegMap.c */
#include "../GPart.h"
#include "../../timings.h"
#define NTIMES 12
static int icputimes ;
static double cputimes[NTIMES] ;
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------------
fill *pndom with ndom, the number of domains.
fill *pnseg with nseg, the number of segments.
domains are numbered in [0, ndom), segments in [ndom,ndom+nseg).
return -- an IV object that contains the map
from vertices to segments
created -- 99feb29, cca
--------------------------------------------------------------------
*/
IV *
GPart_domSegMap (
GPart *gpart,
int *pndom,
int *pnseg
) {
FILE *msgFile ;
Graph *g ;
int adjdom, count, d, first, ierr, ii, jj1, jj2, last, ndom,
msglvl, nextphi, nPhi, nPsi, nV, phi, phi0, phi1, phi2, phi3,
psi, sigma, size, size0, size1, size2, v, vsize, w ;
int *adj, *adj0, *adj1, *adj2, *compids, *dmark, *dsmap, *head,
*link, *list, *offsets, *PhiToPsi, *PhiToV, *PsiToSigma,
*vadj, *VtoPhi ;
IV *dsmapIV ;
IVL *PhiByPhi, *PhiByPowD, *PsiByPowD ;
/*
--------------------
set the initial time
--------------------
*/
icputimes = 0 ;
MARKTIME(cputimes[icputimes]) ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL
|| (g = gpart->g) == NULL
|| pndom == NULL
|| pnseg == NULL ) {
fprintf(stderr, "\n fatal error in GPart_domSegMap(%p,%p,%p)"
"\n bad input\n", gpart, pndom, pnseg) ;
exit(-1) ;
}
compids = IV_entries(&gpart->compidsIV) ;
msglvl = gpart->msglvl ;
msgFile = gpart->msgFile ;
/*
------------------------
create the map IV object
------------------------
*/
nV = g->nvtx ;
dsmapIV = IV_new() ;
IV_init(dsmapIV, nV, NULL) ;
dsmap = IV_entries(dsmapIV) ;
/*
----------------------------------
check compids[] and get the number
of domains and interface vertices
----------------------------------
*/
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
ndom = nPhi = 0 ;
for ( v = 0 ; v < nV ; v++ ) {
if ( (d = compids[v]) < 0 ) {
fprintf(stderr,
"\n fatal error in GPart_domSegMap(%p,%p,%p)"
"\n compids[%d] = %d\n", gpart, pndom, pnseg,
v, compids[v]) ;
exit(-1) ;
} else if ( d == 0 ) {
nPhi++ ;
} else if ( ndom < d ) {
ndom = d ;
}
}
*pndom = ndom ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n Inside GPart_domSegMap") ;
fprintf(msgFile, "\n %d domains, %d Phi vertices", ndom, nPhi) ;
}
if ( ndom == 1 ) {
IVfill(nV, dsmap, 0) ;
*pndom = 1 ;
*pnseg = 0 ;
return(dsmapIV) ;
}
/*
--------------------------------
get the maps
PhiToV : [0,nPhi) |---> [0,nV)
VtoPhi : [0,nV) |---> [0,nPhi)
--------------------------------
*/
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
PhiToV = IVinit(nPhi, -1) ;
VtoPhi = IVinit(nV, -1) ;
for ( v = 0, phi = 0 ; v < nV ; v++ ) {
if ( (d = compids[v]) == 0 ) {
PhiToV[phi] = v ;
VtoPhi[v] = phi++ ;
}
}
if ( phi != nPhi ) {
fprintf(stderr,
"\n fatal error in GPart_domSegMap(%p,%p,%p)"
"\n phi = %d != %d = nPhi\n",
gpart, pndom, pnseg, phi, nPhi) ;
exit(-1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n PhiToV(%d) :", nPhi) ;
IVfp80(msgFile, nPhi, PhiToV, 15, &ierr) ;
fflush(msgFile) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n VtoPhi(%d) :", nV) ;
IVfp80(msgFile, nV, VtoPhi, 15, &ierr) ;
fflush(msgFile) ;
}
/*
---------------------------------------------------
create an IVL object, PhiByPowD, to hold lists from
the interface vertices to their adjacent domains
---------------------------------------------------
*/
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
dmark = IVinit(ndom+1, -1) ;
if ( nPhi >= ndom ) {
list = IVinit(nPhi, -1) ;
} else {
list = IVinit(ndom, -1) ;
}
PhiByPowD = IVL_new() ;
IVL_init1(PhiByPowD, IVL_CHUNKED, nPhi) ;
for ( phi = 0 ; phi < nPhi ; phi++ ) {
v = PhiToV[phi] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
/*
if ( phi == 0 ) {
int ierr ;
fprintf(msgFile, "\n adj(%d,%d) = ", v, phi) ;
IVfp80(msgFile, vsize, vadj, 15, &ierr) ;
fflush(msgFile) ;
}
*/
count = 0 ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
if ( (w = vadj[ii]) < nV
&& (d = compids[w]) > 0
&& dmark[d] != phi ) {
dmark[d] = phi ;
list[count++] = d ;
}
}
if ( count > 0 ) {
IVqsortUp(count, list) ;
IVL_setList(PhiByPowD, phi, count, list) ;
}
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n PhiByPowD : interface x adjacent domains") ;
IVL_writeForHumanEye(PhiByPowD, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------------------------------------
create an IVL object, PhiByPhi to hold lists
from the interface vertices to interface vertices.
(s,t) are in the list if (s,t) is an edge in the graph
and s and t do not share an adjacent domain
-------------------------------------------------------
*/
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
PhiByPhi = IVL_new() ;
IVL_init1(PhiByPhi, IVL_CHUNKED, nPhi) ;
offsets = IVinit(nPhi, 0) ;
head = IVinit(nPhi, -1) ;
link = IVinit(nPhi, -1) ;
for ( phi1 = 0 ; phi1 < nPhi ; phi1++ ) {
count = 0 ;
if ( msglvl > 2 ) {
v = PhiToV[phi1] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
fprintf(msgFile, "\n checking out phi = %d, v = %d", phi1, v) ;
fprintf(msgFile, "\n adj(%d) : ", v) ;
IVfp80(msgFile, vsize, vadj, 10, &ierr) ;
}
/*
-------------------------------------------------------------
get (phi1, phi0) edges that were previously put into the list
-------------------------------------------------------------
*/
if ( msglvl > 3 ) {
if ( head[phi1] == -1 ) {
fprintf(msgFile, "\n no previous edges") ;
} else {
fprintf(msgFile, "\n previous edges :") ;
}
}
for ( phi0 = head[phi1] ; phi0 != -1 ; phi0 = nextphi ) {
if ( msglvl > 3 ) {
fprintf(msgFile, " %d", phi0) ;
}
nextphi = link[phi0] ;
list[count++] = phi0 ;
IVL_listAndSize(PhiByPhi, phi0, &size0, &adj0) ;
if ( (ii = ++offsets[phi0]) < size0 ) {
/*
----------------------------
link phi0 into the next list
----------------------------
*/
phi2 = adj0[ii] ;
link[phi0] = head[phi2] ;
head[phi2] = phi0 ;
}
}
/*
--------------------------
get new edges (phi1, phi2)
--------------------------
*/
IVL_listAndSize(PhiByPowD, phi1, &size1, &adj1) ;
v = PhiToV[phi1] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
if ( (w = vadj[ii]) < nV
&& compids[w] == 0
&& (phi2 = VtoPhi[w]) > phi1 ) {
if ( msglvl > 3 ) {
fprintf(msgFile, "\n checking out phi2 = %d", phi2) ;
}
/*
--------------------------------------------------
see if phi1 and phi2 have a common adjacent domain
--------------------------------------------------
*/
IVL_listAndSize(PhiByPowD, phi2, &size2, &adj2) ;
adjdom = 0 ;
jj1 = jj2 = 0 ;
while ( jj1 < size1 && jj2 < size2 ) {
if ( adj1[jj1] < adj2[jj2] ) {
jj1++ ;
} else if ( adj1[jj1] > adj2[jj2] ) {
jj2++ ;
} else {
if ( msglvl > 3 ) {
fprintf(msgFile, ", common adj domain %d", adj1[jj1]) ;
}
adjdom = 1 ;
break ;
}
}
if ( adjdom == 0 ) {
if ( msglvl > 3 ) {
fprintf(msgFile, ", no adjacent domain") ;
}
list[count++] = phi2 ;
}
}
}
if ( count > 0 ) {
/*
---------------------
set the list for phi1
---------------------
*/
IVqsortUp(count, list) ;
IVL_setList(PhiByPhi, phi1, count, list) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n edge list for %d :", phi1) ;
IVfp80(msgFile, count, list, 15, &ierr) ;
}
for ( ii = 0, phi2 = -1 ; ii < count ; ii++ ) {
if ( list[ii] > phi1 ) {
offsets[phi1] = ii ;
phi2 = list[ii] ;
break ;
}
}
if ( phi2 != -1 ) {
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n linking %d into list for %d", phi1, phi2) ;
}
link[phi1] = head[phi2] ;
head[phi2] = phi1 ;
}
/*
phi2 = list[0] ;
link[phi1] = head[phi2] ;
head[phi2] = phi1 ;
*/
}
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n PhiByPhi : interface x interface") ;
IVL_writeForHumanEye(PhiByPhi, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------
get the PhiToPsi map
--------------------
*/
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
PhiToPsi = IVinit(nPhi, -1) ;
nPsi = 0 ;
for ( phi = 0 ; phi < nPhi ; phi++ ) {
if ( PhiToPsi[phi] == -1 ) {
/*
---------------------------
phi not yet mapped to a psi
---------------------------
*/
first = last = 0 ;
list[0] = phi ;
PhiToPsi[phi] = nPsi ;
while ( first <= last ) {
phi2 = list[first++] ;
IVL_listAndSize(PhiByPhi, phi2, &size, &adj) ;
for ( ii = 0 ; ii < size ; ii++ ) {
phi3 = adj[ii] ;
if ( PhiToPsi[phi3] == -1 ) {
PhiToPsi[phi3] = nPsi ;
list[++last] = phi3 ;
}
}
}
nPsi++ ;
}
}
if ( msglvl > 1 ) {
fprintf(msgFile, "\n nPsi = %d", nPsi) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n PhiToPsi(%d) :", nPhi) ;
IVfp80(msgFile, nPhi, PhiToPsi, 15, &ierr) ;
fflush(msgFile) ;
}
/*
---------------------------------
create an IVL object, Psi --> 2^D
---------------------------------
*/
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
IVfill(nPsi, head, -1) ;
IVfill(nPhi, link, -1) ;
for ( phi = 0 ; phi < nPhi ; phi++ ) {
psi = PhiToPsi[phi] ;
link[phi] = head[psi] ;
head[psi] = phi ;
}
PsiByPowD = IVL_new() ;
IVL_init1(PsiByPowD, IVL_CHUNKED, nPsi) ;
IVfill(ndom+1, dmark, -1) ;
for ( psi = 0 ; psi < nPsi ; psi++ ) {
count = 0 ;
for ( phi = head[psi] ; phi != -1 ; phi = link[phi] ) {
v = PhiToV[phi] ;
Graph_adjAndSize(g, v, &size, &adj) ;
for ( ii = 0 ; ii < size ; ii++ ) {
if ( (w = adj[ii]) < nV
&& (d = compids[w]) > 0
&& dmark[d] != psi ) {
dmark[d] = psi ;
list[count++] = d ;
}
}
}
if ( count > 0 ) {
IVqsortUp(count, list) ;
IVL_setList(PsiByPowD, psi, count, list) ;
}
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n PsiByPowD(%d) :", nPhi) ;
IVL_writeForHumanEye(PsiByPowD, msgFile) ;
fflush(msgFile) ;
}
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
/*
-------------------------------------
now get the map Psi |---> Sigma that
is the equivalence map over PhiByPowD
-------------------------------------
*/
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
PsiToSigma = IVL_equivMap1(PsiByPowD) ;
*pnseg = 1 + IVmax(nPsi, PsiToSigma, &ii) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n nSigma = %d", *pnseg) ;
fprintf(msgFile, "\n PsiToSigma(%d) :", nPhi) ;
IVfp80(msgFile, nPsi, PsiToSigma, 15, &ierr) ;
fflush(msgFile) ;
}
/*
--------------------------------------------------------------
now fill the map from the vertices to the domains and segments
--------------------------------------------------------------
*/
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
for ( v = 0 ; v < nV ; v++ ) {
if ( (d = compids[v]) > 0 ) {
dsmap[v] = d - 1 ;
} else {
phi = VtoPhi[v] ;
psi = PhiToPsi[phi] ;
sigma = PsiToSigma[psi] ;
dsmap[v] = ndom + sigma ;
}
}
/*
------------------------
free the working storage
------------------------
*/
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
IVL_free(PhiByPhi) ;
IVL_free(PhiByPowD) ;
IVL_free(PsiByPowD) ;
IVfree(PhiToV) ;
IVfree(VtoPhi) ;
IVfree(dmark) ;
IVfree(list) ;
IVfree(PhiToPsi) ;
IVfree(head) ;
IVfree(link) ;
IVfree(offsets) ;
IVfree(PsiToSigma) ;
icputimes++ ;
MARKTIME(cputimes[icputimes]) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n domain/segment map timings split") ;
fprintf(msgFile,
"\n %9.5f : create the DSmap object"
"\n %9.5f : get numbers of domain and interface vertices"
"\n %9.5f : generate PhiToV and VtoPhi"
"\n %9.5f : generate PhiByPowD"
"\n %9.5f : generate PhiByPhi"
"\n %9.5f : generate PhiToPsi"
"\n %9.5f : generate PsiByPowD"
"\n %9.5f : generate PsiToSigma"
"\n %9.5f : generate dsmap"
"\n %9.5f : free working storage"
"\n %9.5f : total time",
cputimes[1] - cputimes[0],
cputimes[2] - cputimes[1],
cputimes[3] - cputimes[2],
cputimes[4] - cputimes[3],
cputimes[5] - cputimes[4],
cputimes[6] - cputimes[5],
cputimes[7] - cputimes[6],
cputimes[8] - cputimes[7],
cputimes[9] - cputimes[8],
cputimes[10] - cputimes[9],
cputimes[11] - cputimes[0]) ;
}
return(dsmapIV) ; }
/*--------------------------------------------------------------------*/
GPart/src/identifyWideSep.c 0100644 0002055 0007177 00000015115 06534106120 0017135 0 ustar 00cleve compmath 0000040 0000006 /* identifyWideSep.c */
#include "../GPart.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
identify the wide separator
return -- IV object that holds the nodes in the wide separator
created -- 96oct21, cca
--------------------------------------------------------------
*/
IV *
GPart_identifyWideSep (
GPart *gpart,
int nlevel1,
int nlevel2
) {
FILE *msgFile ;
Graph *g ;
int count, first, ierr, ii, ilevel, last, msglvl,
nfirst, now, nsecond, nsep, nvtx, v, vsize, w ;
int *compids, *list, *mark, *vadj ;
IV *sepIV ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || (g = gpart->g) == NULL
|| nlevel1 < 0 || nlevel2 < 0 ) {
fprintf(stderr, "\n fatal error in GPart_identifyWideSep(%p,%d,%d)"
"\n bad input\n", gpart, nlevel1, nlevel2) ;
exit(-1) ;
}
g = gpart->g ;
compids = IV_entries(&gpart->compidsIV) ;
nvtx = g->nvtx ;
mark = IVinit(nvtx, -1) ;
list = IVinit(nvtx, -1) ;
msglvl = gpart->msglvl ;
msgFile = gpart->msgFile ;
/*
--------------------------------------
load the separator nodes into the list
--------------------------------------
*/
nsep = 0 ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( compids[v] == 0 ) {
list[nsep++] = v ;
mark[v] = 0 ;
}
}
count = nsep ;
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n GPart_identifyWideSep : %d separator nodes loaded",
count) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
IVfp80(msgFile, nsep, list, 80, &ierr) ;
fflush(msgFile) ;
}
/*
----------------------------------------------
loop over the number of levels out that form
the wide separator towards the first component
----------------------------------------------
*/
if ( nlevel1 >= 1 ) {
first = count ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n level = %d, first = %d", 1, first) ;
fflush(msgFile) ;
}
for ( now = 0 ; now < nsep ; now++ ) {
v = list[now] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %d : ", v) ;
IVfp80(msgFile, vsize, vadj, 80, &ierr) ;
fflush(msgFile) ;
}
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w < nvtx && mark[w] == -1 && compids[w] == 1 ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n adding %d to list", w) ;
fflush(msgFile) ;
}
list[count++] = w ;
mark[w] = 1 ;
}
}
}
now = first ;
for ( ilevel = 2 ; ilevel <= nlevel1 ; ilevel++ ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n level = %d, first = %d", ilevel, first);
fflush(msgFile) ;
}
last = count - 1 ;
while ( now <= last ) {
v = list[now++] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %d : ", v) ;
IVfp80(msgFile, vsize, vadj, 80, &ierr) ;
fflush(msgFile) ;
}
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w < nvtx && mark[w] == -1 && compids[w] == 1 ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n adding %d to list", w) ;
fflush(msgFile) ;
}
mark[w] = 1 ;
list[count++] = w ;
}
}
}
}
}
nfirst = count - nsep ;
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n %d nodes added from the first component", nfirst) ;
fflush(msgFile) ;
}
if ( msglvl > 3 ) {
IVfp80(msgFile, nfirst, &list[nsep], 80, &ierr) ;
fflush(msgFile) ;
}
/*
----------------------------------------------
loop over the number of levels out that form
the wide separator towards the second component
----------------------------------------------
*/
if ( nlevel2 >= 1 ) {
first = count ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n level = %d, first = %d", 1, first) ;
fflush(msgFile) ;
}
for ( now = 0 ; now < nsep ; now++ ) {
v = list[now] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %d : ", v) ;
IVfp80(msgFile, vsize, vadj, 80, &ierr) ;
fflush(msgFile) ;
}
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w < nvtx && mark[w] == -1 && compids[w] == 2 ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n adding %d to list", w) ;
fflush(msgFile) ;
}
list[count++] = w ;
mark[w] = 2 ;
}
}
}
now = first ;
for ( ilevel = 2 ; ilevel <= nlevel2 ; ilevel++ ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n level = %d, first = %d", ilevel, first);
fflush(msgFile) ;
}
last = count - 1 ;
while ( now <= last ) {
v = list[now++] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %d : ", v) ;
IVfp80(msgFile, vsize, vadj, 80, &ierr) ;
fflush(msgFile) ;
}
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w < nvtx && mark[w] == -1 && compids[w] == 2 ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n adding %d to list", w) ;
fflush(msgFile) ;
}
mark[w] = 2 ;
list[count++] = w ;
}
}
}
}
}
nsecond = count - nsep - nfirst ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n %d nodes added from the second component",
nsecond) ;
fflush(msgFile) ;
}
if ( msglvl > 3 ) {
IVfp80(msgFile, nsecond, &list[nsep + nfirst], 80, &ierr) ;
fflush(msgFile) ;
}
IVqsortUp(count, list) ;
/*
--------------------
create the IV object
--------------------
*/
sepIV = IV_new() ;
IV_init(sepIV, count, NULL) ;
IVcopy(count, IV_entries(sepIV), list) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n separator has %d nodes", IV_size(sepIV)) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n sepIV") ;
IV_writeForHumanEye(sepIV, msgFile) ;
fflush(msgFile) ;
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(mark) ;
IVfree(list) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n return from GPart_identifyWideSep") ;
fflush(msgFile) ;
}
return(sepIV) ; }
/*--------------------------------------------------------------------*/
GPart/src/init.c 0100644 0002055 0007177 00000002450 06534106120 0015002 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../GPart.h"
/*--------------------------------------------------------------------*/
/*
---------------------------
initialize the GPart object
created -- 95oct05, cca
---------------------------
*/
void
GPart_init (
GPart *gpart,
Graph *g
) {
if ( gpart == NULL || g == NULL || g->nvtx <= 0 ) {
fprintf(stderr, "\n fatal error in GPart_init(%p,%p)"
"\n bad input\n", gpart, g) ;
exit(-1) ;
}
GPart_clearData(gpart) ;
gpart->nvtx = g->nvtx ;
gpart->nvbnd = g->nvbnd ;
gpart->g = g ;
gpart->ncomp = 1 ;
IV_setSize(&gpart->compidsIV, g->nvtx) ;
IV_fill(&gpart->compidsIV, 1) ;
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------
set the message fields
created -- 96oct21, cca
-----------------------
*/
void
GPart_setMessageInfo (
GPart *gpart,
int msglvl,
FILE *msgFile
) {
if ( gpart == NULL ) {
fprintf(stderr, "\n fatal error in GPart_setMessageInfo(%p,%d,%p)"
"\n bad input\n", gpart, msglvl, msgFile) ;
exit(-1) ;
}
gpart->msglvl = msglvl ;
if ( msgFile != NULL ) {
gpart->msgFile = msgFile ;
} else {
gpart->msgFile = stdout ;
}
return ; }
/*--------------------------------------------------------------------*/
GPart/src/makeYCmap.c 0100644 0002055 0007177 00000007311 06534106120 0015707 0 ustar 00cleve compmath 0000040 0000006 /* makeYCmap.c */
#include "../GPart.h"
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
make the map from wide separator vertices Y
to components {0, 1, 2, 3}.
YCmap[y] == 0 --> y is not adjacent to either component
YCmap[y] == 1 --> y is adjacent to only component 1
YCmap[y] == 2 --> y is adjacent to only component 2
YCmap[y] == 3 --> y is adjacent to components 1 and 2
created -- 96jun09, cca
-------------------------------------------------------
*/
IV *
GPart_makeYCmap (
GPart *gpart,
IV *YVmapIV
) {
Graph *g ;
int ii, nvtx, nY, v, vsize, w, y ;
int *compids, *vadj, *VYmap, *YCmap, *YVmap ;
IV *YCmapIV ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || (g = gpart->g) == NULL
|| (nvtx = gpart->nvtx) <= 0
|| YVmapIV == NULL || (nY = IV_size(YVmapIV)) <= 0
|| (YVmap = IV_entries(YVmapIV)) == NULL ) {
fprintf(stderr, "\n fatal error in GPart_makeYCmap(%p,%p)"
"\n bad input\n", gpart, YVmapIV) ;
if ( YVmapIV != NULL ) {
fprintf(stderr, "\n YVmapIV") ;
IV_writeForHumanEye(YVmapIV, stderr) ;
}
exit(-1) ;
}
compids = IV_entries(&gpart->compidsIV) ;
/*
--------------------------------
generate the inverse V --> Y map
--------------------------------
*/
VYmap = IVinit(nvtx, -1) ;
for ( y = 0 ; y < nY ; y++ ) {
v = YVmap[y] ;
VYmap[v] = y ;
}
/*
------------------------------------
initialize the Y --> C map IV object
------------------------------------
*/
YCmapIV = IV_new();
IV_init(YCmapIV, nY, NULL) ;
YCmap = IV_entries(YCmapIV) ;
/*
---------------
fill the fields
---------------
*/
for ( y = 0 ; y < nY ; y++ ) {
YCmap[y] = 0 ;
v = YVmap[y] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w < nvtx && VYmap[w] == -1 ) {
/*
--------------------------------
w is not in the wide separator Y
--------------------------------
*/
if ( compids[w] == 1 ) {
/*
---------------------------------------
v is adjacent to component 1 setminus Y
---------------------------------------
*/
if ( YCmap[y] == 2 ) {
/*
------------------------------------
v is already adjacent to component 2
so it is adjacent to both components
------------------------------------
*/
YCmap[y] = 3 ;
break ;
} else {
/*
----------------------------------
set map value but keep on checking
----------------------------------
*/
YCmap[y] = 1 ;
}
} else if ( compids[w] == 2 ) {
/*
---------------------------------------
v is adjacent to component 2 setminus Y
---------------------------------------
*/
if ( YCmap[y] == 1 ) {
/*
------------------------------------
v is already adjacent to component 1
so it is adjacent to both components
------------------------------------
*/
YCmap[y] = 3 ;
break ;
} else {
/*
----------------------------------
set map value but keep on checking
----------------------------------
*/
YCmap[y] = 2 ;
}
}
}
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(VYmap) ;
return(YCmapIV) ; }
/*--------------------------------------------------------------------*/
GPart/src/smoothBisector.c 0100644 0002055 0007177 00000011337 06534106121 0017050 0 ustar 00cleve compmath 0000040 0000006 /* smoothBisector.c */
#include "../GPart.h"
#include "../../Ideq.h"
/*--------------------------------------------------------------------*/
/*
----------------------------------------
static definition of evaluation function
----------------------------------------
*/
static float eval ( float alpha, float wS, float wB, float wW) ;
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
smooth a wide separator
nlevel -- number of levels one each side of the separator
to include into the separator
alpha -- partition cost function parameter
created -- 96jun02, cca
---------------------------------------------------------
*/
float
GPart_smoothBisector (
GPart *gpart,
int nlevel,
float alpha
) {
FILE *msgFile ;
float balance, bestcost, cost, newcost ;
Graph *g ;
int ierr, ipass, msglvl ;
int *compids, *cweights, *vwghts ;
IV *YCmapIV, *YVmapIV ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || nlevel < 0 || alpha < 0.0 ) {
fprintf(stderr, "\n fatal error in GPart_smoothBisector(%p,%d,%f)"
"\n bad input\n", gpart, nlevel, alpha) ;
exit(-1) ;
}
g = gpart->g ;
compids = IV_entries(&gpart->compidsIV) ;
cweights = IV_entries(&gpart->cweightsIV) ;
vwghts = g->vwghts ;
msglvl = gpart->msglvl ;
msgFile = gpart->msgFile ;
bestcost = eval(alpha, cweights[0], cweights[1], cweights[2]) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n smoothBisector : nlevel = %d, alpha = %f",
nlevel, alpha) ;
fprintf(msgFile, "\n old partition cost %.3f, weights = %5d %5d %5d",
bestcost, cweights[0], cweights[1], cweights[2]) ;
fflush(msgFile) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n compids") ;
IVfp80(msgFile, g->nvtx, compids, 80, &ierr) ;
}
/*
------------------------------------
loop while improvement is being made
------------------------------------
*/
ipass = 0 ;
while ( 1 ) {
if ( msglvl > 1 ) {
if ( cweights[1] >= cweights[2] ) {
balance = ((double) cweights[1]) / cweights[2] ;
} else {
balance = ((double) cweights[2]) / cweights[1] ;
}
cost = cweights[0] * (1 + alpha * balance) ;
fprintf(msgFile,
"\n\n ### pass %d, cweights : %d %d %d, balance = %5.3f, cost = %.1f",
ipass, cweights[0], cweights[1], cweights[2],
balance, cost) ;
fflush(msgFile) ;
}
/*
---------------------------
identify the wide separator
---------------------------
*/
YVmapIV = GPart_identifyWideSep(gpart, nlevel, nlevel) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n nlevel = %d, |widesep| = %d",
nlevel, IV_size(YVmapIV)) ;
fflush(msgFile) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n YVmapIV") ;
IV_writeForHumanEye(YVmapIV, msgFile) ;
}
/*
-------------------------------------------------
get the Y = Y_0 cup Y_1 cup Y_2 cup Y_3 partition
-------------------------------------------------
*/
YCmapIV = GPart_makeYCmap(gpart, YVmapIV) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n YCmapIV found") ;
fflush(msgFile) ;
}
/*
--------------------
smooth the separator
--------------------
*/
newcost = GPart_smoothYSep(gpart, YVmapIV, YCmapIV, alpha) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n newcost = %.3f", newcost) ;
fflush(msgFile) ;
}
/*
------------------------
free the two map vectors
------------------------
*/
IV_free(YVmapIV) ;
IV_free(YCmapIV) ;
/*
-------------------------------
check for an improved partition
-------------------------------
*/
if ( newcost == bestcost ) {
break ;
} else {
bestcost = newcost ;
}
ipass++ ;
}
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n\n final partition weights [%d %d %d], cost = %.3f",
cweights[0], cweights[1], cweights[2], bestcost) ;
fflush(msgFile) ;
}
return(bestcost) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------
partition evaluation function
-----------------------------
*/
static float
eval (
float alpha,
float wS,
float wB,
float wW
) {
float cost ;
#if MYDEBUG > 2
fprintf(msgFile, "\n alpha = %f, wS = %f, wB = %f, wW = %f",
alpha, wS, wB, wW) ;
#endif
if ( wB == 0 || wW == 0 ) {
cost = (wS + wB + wW) * (wS + wB + wW) ;
} else if ( wB >= wW ) {
cost = wS*(1. + (alpha*wB)/wW) ;
} else {
cost = wS*(1. + (alpha*wW)/wB) ;
}
#if MYDEBUG > 2
fprintf(msgFile, ", cost = %f", cost) ;
#endif
return(cost) ; }
/*--------------------------------------------------------------------*/
GPart/src/smoothBy2layers.c 0100644 0002055 0007177 00000011762 06534106121 0017154 0 ustar 00cleve compmath 0000040 0000006 /* smoothBy2layers.c */
#include "../GPart.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------
static declaration of evaluation function
-----------------------------------------
*/
static float eval ( float alpha, float wS, float wB, float wW ) ;
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
smooth a bisector using the alternating two-layer algorithm
option -- network flag
1 --> make the network bipartite as for the
Dulmage-Mendelsohn decomposition
otherwise -- use network induced by the wide separator
alpha -- cost function parameter
created -- 96jun08, cca
-----------------------------------------------------------
*/
void
GPart_smoothBy2layers (
GPart *gpart,
int option,
float alpha
) {
FILE *msgFile ;
float bestcost, newcost ;
int ierr, large, msglvl, nY, pass, small, y ;
int *cweights, *YCmap ;
IV *YCmapIV, *YVmapIV ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || alpha < 0.0 ) {
fprintf(stderr, "\n fatal error in GPart_smoothBy2layers(%p,%f)"
"\n bad input\n", gpart, alpha) ;
exit(-1) ;
}
pass = 1 ;
cweights = IV_entries(&gpart->cweightsIV) ;
bestcost = eval(alpha, cweights[0], cweights[1], cweights[2]) ;
msgFile = gpart->msgFile ;
msglvl = gpart->msglvl ;
while ( 1 ) {
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n\n PASS %d : attempting a move towards the larger component",
pass) ;
fflush(msgFile) ;
}
if ( cweights[1] >= cweights[2] ) {
large = 1 ; small = 2 ;
YVmapIV = GPart_identifyWideSep(gpart, 1, 0) ;
} else {
large = 2 ; small = 1 ;
YVmapIV = GPart_identifyWideSep(gpart, 0, 1) ;
}
YCmapIV = GPart_makeYCmap(gpart, YVmapIV) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n YCmapIV") ;
IV_writeForHumanEye(YCmapIV, msgFile) ;
fflush(msgFile) ;
}
IV_sizeAndEntries(YCmapIV, &nY, &YCmap) ;
if ( option == 1 ) {
/*
----------------------------
generate a bipartite network
----------------------------
*/
for ( y = 0 ; y < nY ; y++ ) {
if ( YCmap[y] != small ) {
YCmap[y] = large ;
}
}
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n calling GPartSmoothYSep") ;
fflush(msgFile) ;
}
newcost = GPart_smoothYSep(gpart, YVmapIV, YCmapIV, alpha) ;
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n\n bestcost = %.2f, newcost = %.2f", bestcost, newcost) ;
fflush(msgFile) ;
}
IV_free(YVmapIV) ;
IV_free(YCmapIV) ;
if ( newcost == bestcost ) {
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n\n PASS %d : attempting a move towards the smaller component",
pass) ;
fflush(msgFile) ;
}
if ( cweights[1] >= cweights[2] ) {
large = 1 ; small = 2 ;
YVmapIV = GPart_identifyWideSep(gpart, 0, 1) ;
} else {
large = 2 ; small = 1 ;
YVmapIV = GPart_identifyWideSep(gpart, 1, 0) ;
}
YCmapIV = GPart_makeYCmap(gpart, YVmapIV) ;
IV_sizeAndEntries(YCmapIV, &nY, &YCmap) ;
if ( option == 1 ) {
/*
----------------------------
generate a bipartite network
----------------------------
*/
for ( y = 0 ; y < nY ; y++ ) {
if ( YCmap[y] != large ) {
YCmap[y] = small ;
}
}
}
newcost = GPart_smoothYSep(gpart, YVmapIV, YCmapIV, alpha) ;
if ( msglvl > 2 ) {
fprintf(msgFile,
"\n\n bestcost = %.2f, newcost = %.2f", bestcost, newcost) ;
fflush(msgFile) ;
}
IV_free(YVmapIV) ;
IV_free(YCmapIV) ;
}
if ( newcost == bestcost ) {
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n no improvement made") ;
fflush(msgFile) ;
}
break ;
} else {
bestcost = newcost ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n improvement made") ;
fflush(msgFile) ;
}
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n compids") ;
IVfp80(msgFile, gpart->nvtx, IV_entries(&gpart->compidsIV),
80, &ierr) ;
fflush(msgFile) ;
}
}
pass++ ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n leaving smoothBy2layers") ;
fflush(msgFile) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------
partition evaluation function
-----------------------------
*/
static float
eval (
float alpha,
float wS,
float wB,
float wW
) {
float bestcost ;
if ( wB == 0 || wW == 0 ) {
bestcost = (wS + wB + wW) * (wS + wB + wW) ;
} else if ( wB >= wW ) {
bestcost = wS*(1. + (alpha*wB)/wW) ;
} else {
bestcost = wS*(1. + (alpha*wW)/wB) ;
}
return(bestcost) ; }
/*--------------------------------------------------------------------*/
GPart/src/smoothYSep.c 0100644 0002055 0007177 00000047105 06633547072 0016176 0 ustar 00cleve compmath 0000040 0000006 /* smoothYSep.c */
#include "../GPart.h"
#include "../../Network.h"
/*--------------------------------------------------------------------*/
/*
-----------------
static prototypes
-----------------
*/
static Network *
createNetwork ( Graph *g, int compids[], IV *YVmapIV, IV *YCmapIV,
IV *NYmapIV, int msglvl, FILE *msgFile ) ;
static void getNewCompids ( int nnode, int NYmap[], int YCmap[],
int mark[], int Ycompids[],
int msglvl, FILE *msgFile ) ;
static float eval ( float alpha, float wS, float wB, float wW) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------
smooth the wide separator given by YVmapIV by forming
the associated network, solving the max flow problem,
and examining two min-cuts.
YVmapIV -- map from wide vertices Y to vertices V
YCmapIV -- map from wide vertices Y to {0,1,2,3}
YCmap[y] = 0 --> treat y as an internal node
adjacent to neither component
YCmap[y] = 1 --> treat y as adjacent only to component 1
YCmap[y] = 2 --> treat y as adjacent only to component 2
YCmap[y] = 3 --> treat y as adjacent to components 1 and 2
alpha -- cost function parameter
created -- 96jun08, cca
------------------------------------------------------------
*/
float
GPart_smoothYSep (
GPart *gpart,
IV *YVmapIV,
IV *YCmapIV,
float alpha
) {
FILE *msgFile ;
float bestcost, newcost1, newcost2 ;
Graph *g ;
Ideq *deq ;
int ierr, msglvl, nnode, newcomp, nY, oldcomp, v, vwght, y ;
int *compids, *cweights, *mark, *vwghts,
*Ycompids1, *Ycompids2, *YCmap, *YVmap ;
int deltas[3] ;
IV *NYmapIV ;
Network *network ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || (g = gpart->g) == NULL
|| YVmapIV == NULL
|| (nY = IV_size(YVmapIV)) <= 0
|| (YVmap = IV_entries(YVmapIV)) == NULL
|| YCmapIV == NULL
|| IV_size(YCmapIV) != nY
|| (YCmap = IV_entries(YCmapIV)) == NULL
|| alpha < 0.0 ) {
fprintf(stderr, "\n fatal error in GPart_smoothSep(%p,%p,%p,%f)"
"\n bad input\n", gpart, YVmapIV, YCmapIV, alpha) ;
exit(-1) ;
}
compids = IV_entries(&gpart->compidsIV) ;
cweights = IV_entries(&gpart->cweightsIV) ;
vwghts = g->vwghts ;
msgFile = gpart->msgFile ;
msglvl = gpart->msglvl ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n YVmapIV") ;
IV_writeForHumanEye(YVmapIV, msgFile) ;
fprintf(msgFile, "\n YCmapIV") ;
IV_writeForHumanEye(YCmapIV, msgFile) ;
}
/*
------------------
create the network
------------------
*/
NYmapIV = IV_new() ;
network = createNetwork(g, compids, YVmapIV, YCmapIV, NYmapIV,
msglvl, msgFile) ;
Network_setMessageInfo(network, msglvl, msgFile) ;
nnode = network->nnode ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n network : %d nodes, %d arcs",
nnode, network->narc) ;
fflush(msgFile) ;
}
if ( msglvl > 4 ) {
Network_writeForHumanEye(network, msgFile) ;
}
/*
--------------------
solve for a max flow
--------------------
*/
Network_findMaxFlow(network) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n after max flow solution, %d arc traversals",
network->ntrav) ;
fflush(msgFile) ;
}
if ( msglvl > 4 ) {
Network_writeForHumanEye(network, msgFile) ;
}
/*
------------------------------
evaluate the present partition
------------------------------
*/
bestcost = eval(alpha, cweights[0], cweights[1], cweights[2]) ;
if ( msglvl > 1 ) {
int maxval, minval, val1, val2 ;
fprintf(msgFile, "\n present partition : < %d, %d, %d >",
cweights[0], cweights[1], cweights[2]) ;
val1 = cweights[1] ;
val2 = cweights[2] ;
minval = (val1 <= val2) ? val1 : val2 ;
maxval = (val1 > val2) ? val1 : val2 ;
if ( minval == 0 ) {
fprintf(msgFile, ", imbalance = infinite") ;
} else {
fprintf(msgFile,
", imbalance = %6.3f", ((double) maxval)/minval) ;
}
fprintf(msgFile, ", cost = %.2f", bestcost) ;
fflush(msgFile) ;
}
/*
---------------------------
set up some working storage
---------------------------
*/
deq = Ideq_new() ;
Ideq_resize(deq, nnode) ;
mark = IVinit(nnode, -1) ;
Ycompids1 = IVinit(nY, -1) ;
Ycompids2 = IVinit(nY, -1) ;
/*
---------------------------------------
find a min-cut starting from the source
and evaluate the partition
---------------------------------------
*/
Network_findMincutFromSource(network, deq, mark) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n mark starting from source") ;
IVfp80(msgFile, nnode, mark, 80, &ierr) ;
fflush(msgFile) ;
}
getNewCompids(nnode, IV_entries(NYmapIV), YCmap, mark, Ycompids1,
msglvl, msgFile) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n Ycompids1") ;
IVfp80(msgFile, nY, Ycompids1, 80, &ierr) ;
fflush(msgFile) ;
}
deltas[0] = deltas[1] = deltas[2] = 0 ;
for ( y = 0 ; y < nY ; y++ ) {
v = YVmap[y] ;
oldcomp = compids[v] ;
newcomp = Ycompids1[y] ;
if ( msglvl > 5 ) {
fprintf(msgFile, "\n y = %d, v = %d, oldcomp = %d, newcomp = %d",
y, v, oldcomp, newcomp) ;
fflush(msgFile) ;
}
if ( oldcomp != newcomp ) {
vwght = (vwghts != NULL) ? vwghts[v] : 1 ;
deltas[oldcomp] -= vwght ;
deltas[newcomp] += vwght ;
}
}
newcost1 = eval(alpha, cweights[0] + deltas[0],
cweights[1] + deltas[1], cweights[2] + deltas[2]) ;
if ( msglvl > 1 ) {
int maxval, minval, val1, val2 ;
fprintf(msgFile,
"\n min-cut from source: < %d, %d, %d >",
cweights[0] + deltas[0], cweights[1] + deltas[1],
cweights[2] + deltas[2]) ;
val1 = cweights[1] + deltas[1] ;
val2 = cweights[2] + deltas[2] ;
minval = (val1 <= val2) ? val1 : val2 ;
maxval = (val1 > val2) ? val1 : val2 ;
if ( minval == 0 ) {
fprintf(msgFile, ", imbalance = infinite") ;
} else {
fprintf(msgFile,
", imbalance = %6.3f", ((double) maxval)/minval) ;
}
fprintf(msgFile, ", newcost1 = %.2f", newcost1) ;
fflush(msgFile) ;
}
/*
---------------------------------------
find a min-cut starting from the sink
and evaluate the partition
---------------------------------------
*/
Network_findMincutFromSink(network, deq, mark) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n mark starting from sink") ;
IVfp80(msgFile, nnode, mark, 80, &ierr) ;
fflush(msgFile) ;
}
getNewCompids(nnode, IV_entries(NYmapIV), YCmap, mark, Ycompids2,
msglvl, msgFile) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n Ycompids2") ;
IVfp80(msgFile, nY, Ycompids2, 80, &ierr) ;
fflush(msgFile) ;
}
deltas[0] = deltas[1] = deltas[2] = 0 ;
for ( y = 0 ; y < nY ; y++ ) {
v = YVmap[y] ;
oldcomp = compids[v] ;
newcomp = Ycompids2[y] ;
if ( oldcomp != newcomp ) {
vwght = (vwghts != NULL) ? vwghts[v] : 1 ;
deltas[oldcomp] -= vwght ;
deltas[newcomp] += vwght ;
}
}
newcost2 = eval(alpha, cweights[0] + deltas[0],
cweights[1] + deltas[1], cweights[2] + deltas[2]) ;
if ( msglvl > 1 ) {
int maxval, minval, val1, val2 ;
fprintf(msgFile,
"\n min-cut from sink: < %d, %d, %d >",
cweights[0] + deltas[0], cweights[1] + deltas[1],
cweights[2] + deltas[2]) ;
val1 = cweights[1] + deltas[1] ;
val2 = cweights[2] + deltas[2] ;
minval = (val1 <= val2) ? val1 : val2 ;
maxval = (val1 > val2) ? val1 : val2 ;
if ( minval == 0 ) {
fprintf(msgFile, ", imbalance = infinite") ;
} else {
fprintf(msgFile,
", imbalance = %6.3f", ((double) maxval)/minval) ;
}
fprintf(msgFile, ", newcost1 = %.2f", newcost2) ;
fflush(msgFile) ;
}
/*
---------------------------------------------
decide whether to accept either new partition
---------------------------------------------
*/
if ( newcost1 <= newcost2 && newcost1 < bestcost ) {
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n accepting new partition from source min-cut") ;
fflush(msgFile) ;
}
for ( y = 0 ; y < nY ; y++ ) {
v = YVmap[y] ;
oldcomp = compids[v] ;
newcomp = Ycompids1[y] ;
if ( oldcomp != newcomp ) {
compids[v] = newcomp ;
vwght = (vwghts != NULL) ? vwghts[v] : 1 ;
cweights[oldcomp] -= vwght ;
cweights[newcomp] += vwght ;
}
}
bestcost = newcost1 ;
if ( msglvl > 1 ) {
fprintf(msgFile, ", cost = %.3f", bestcost) ;
fflush(msgFile) ;
}
} else if ( newcost2 <= newcost1 && newcost2 < bestcost ) {
if ( msglvl > 1 ) {
fprintf(msgFile, "\n accepting new partition from sink min-cut") ;
fflush(msgFile) ;
}
for ( y = 0 ; y < nY ; y++ ) {
v = YVmap[y] ;
oldcomp = compids[v] ;
newcomp = Ycompids2[y] ;
if ( oldcomp != newcomp ) {
compids[v] = newcomp ;
vwght = (vwghts != NULL) ? vwghts[v] : 1 ;
cweights[oldcomp] -= vwght ;
cweights[newcomp] += vwght ;
}
}
bestcost = newcost2 ;
if ( msglvl > 1 ) {
fprintf(msgFile, ", cost = %.3f", bestcost) ;
fflush(msgFile) ;
}
}
/*
------------------------
free the working storage
------------------------
*/
Network_free(network) ;
IV_free(NYmapIV) ;
IVfree(mark) ;
IVfree(Ycompids1) ;
IVfree(Ycompids2) ;
Ideq_free(deq) ;
return(bestcost) ; }
/*--------------------------------------------------------------------*/
/*
------------------
create the network
------------------
*/
static Network *
createNetwork (
Graph *g,
int compids[],
IV *YVmapIV,
IV *YCmapIV,
IV *NYmapIV,
int msglvl,
FILE *msgFile
) {
int first, ierr, ii, i0, i1, i12, i2, maxcap, mnode,
n0, n1, n12, n2, nvtx, nY, second, sink, source, v, vnet,
vsize, vwght, w, wnet, y, zwid ;
int *NYmap, *vadj, *VNmap, *vwghts, *YCmap, *YVmap ;
Network *network ;
/*
---------------
check the input
---------------
*/
if ( g == NULL || (nvtx = g->nvtx) <= 0 || compids == NULL
|| YVmapIV == NULL
|| (nY = IV_size(YVmapIV)) <= 0
|| (YVmap = IV_entries(YVmapIV)) == NULL
|| YCmapIV == NULL
|| nY != IV_size(YCmapIV)
|| (YCmap = IV_entries(YCmapIV)) == NULL
|| NYmapIV == NULL ) {
fprintf(stderr, "\n fatal error in createNetwork(%p,%p,%p,%p,%p)"
"\n bad input\n", g, compids, YVmapIV, NYmapIV, YCmapIV) ;
exit(-1) ;
}
vwghts = g->vwghts ;
if ( vwghts == NULL ) {
maxcap = nvtx ;
} else {
maxcap = IVsum(nvtx, vwghts) ;
}
if ( msglvl > 4 ) {
fprintf(msgFile, "\n maxcap = %d", maxcap) ;
fflush(msgFile) ;
}
/*
--------------------------------------------------
count the number of nodes in each of the four sets
--------------------------------------------------
*/
n1 = n12 = n0 = n2 = 0 ;
for ( y = 0 ; y < nY ; y++ ) {
switch ( YCmap[y] ) {
case 0 : n0++ ; break ;
case 1 : n1++ ; break ;
case 2 : n2++ ; break ;
case 3 : n12++ ; break ;
default :
fprintf(stderr, "\n fatal error, y = %d, YCmap[%d] = %d",
y, y, YCmap[y]) ;
exit(-1) ;
}
}
mnode = 1 + n1 + n12 + 2*n0 + n2 + 1 ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n n12 = %d, n1 = %d, n0 = %d, n2 = %d",
n12, n1, n0, n2) ;
fprintf(msgFile, "\n %d nodes in the network", mnode) ;
fflush(msgFile) ;
}
/*
-----------------------------------
set up the N --> Y and V --> N maps
-----------------------------------
*/
IV_init(NYmapIV, mnode, NULL) ;
NYmap = IV_entries(NYmapIV) ;
VNmap = IVinit(nvtx, -1) ;
i12 = 1 ;
i1 = 1 + n12 ;
i0 = 1 + n12 + n1 ;
i2 = 1 + n12 + n1 + 2*n0 ;
for ( y = 0 ; y < nY ; y++ ) {
v = YVmap[y] ;
switch ( YCmap[y] ) {
case 0 :
NYmap[i0] = y ;
NYmap[i0+1] = y ;
VNmap[v] = i0 ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n comp 0 : y = %d, v = %d, i0 = %d and %d",
y, v, i0, i0+1) ;
fflush(msgFile) ;
}
i0 += 2 ;
break ;
case 1 :
NYmap[i1] = y ;
VNmap[v] = i1 ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n comp 1 : y = %d, v = %d, i1 = %d",
y, v, i1) ;
fflush(msgFile) ;
}
i1++ ;
break ;
case 2 :
NYmap[i2] = y ;
VNmap[v] = i2 ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n comp 2 : y = %d, v = %d, i2 = %d",
y, v, i2) ;
fflush(msgFile) ;
}
i2++ ;
break ;
case 3 :
NYmap[i12] = y ;
VNmap[v] = i12 ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n comp 12 : y = %d, v = %d, i12 = %d",
y, v, i12) ;
fflush(msgFile) ;
}
i12++ ;
break ;
default :
fprintf(stderr,
"\n fatal error, y = %d, v = %d, YCmap[%d] = %d",
y, v, y, YCmap[y]) ;
exit(-1) ;
}
}
if ( msglvl > 4 ) {
fprintf(msgFile, "\n NYmapIV") ;
IV_writeForHumanEye(NYmapIV, msgFile) ;
fprintf(msgFile, "\n VNmap") ;
IVfp80(msgFile, nvtx, VNmap, 80, &ierr) ;
fflush(msgFile) ;
}
/*
-------------------------
create the Network object
-------------------------
*/
source = 0 ;
sink = mnode - 1 ;
network = Network_new() ;
Network_init(network, mnode, 0) ;
/*
---------------
insert the arcs
---------------
*/
for ( y = 0 ; y < nY ; y++ ) {
v = YVmap[y] ;
vnet = VNmap[v] ;
vwght = (vwghts != NULL) ? vwghts[v] : 1 ;
if ( msglvl > 4 ) {
fprintf(msgFile,
"\n checking out y = %d, v = %d, vnet = %d, vwght = %d",
y, v, vnet, vwght) ;
fflush(msgFile) ;
}
switch ( YCmap[y] ) {
case 0 :
first = vnet ;
second = first + 1 ;
Network_addArc(network, first, second, vwght, 0) ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n S: arc (%d, %d) --> (%d,%d)",
v, v, first, second) ;
fflush(msgFile) ;
}
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w < nvtx && v != w && (wnet = VNmap[w]) != -1 ) {
zwid = NYmap[wnet] ;
if ( YCmap[zwid] == 0 ) {
first = vnet + 1 ;
second = wnet ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n S: arc (%d, %d) --> (%d,%d)",
v, w, first, second) ;
fflush(msgFile) ;
}
Network_addArc(network, first, second, maxcap, 0) ;
}
}
}
break ;
case 1 :
first = source ;
second = vnet ;
Network_addArc(network, first, second, vwght, 0) ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n B: arc (source, %d) --> (%d,%d)",
v, first, second) ;
fflush(msgFile) ;
}
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n w = %d", w) ;
fflush(msgFile) ;
}
if ( w < nvtx && v != w && (wnet = VNmap[w]) != -1 ) {
zwid = NYmap[wnet] ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n wnet = %d", wnet) ;
fflush(msgFile) ;
fprintf(msgFile, "\n zwid = %d", zwid) ;
fflush(msgFile) ;
}
if ( YCmap[zwid] != 1 ) {
first = vnet ;
second = wnet ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n B: arc (%d, %d) --> (%d,%d)",
v, w, first, second) ;
fflush(msgFile) ;
}
Network_addArc(network, first, second, maxcap, 0) ;
}
}
}
break ;
case 2 :
first = vnet ;
second = sink ;
Network_addArc(network, first, second, vwght, 0) ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n B: arc (%d, sink) --> (%d,%d)",
v, first, second) ;
fflush(msgFile) ;
}
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w < nvtx && v != w && (wnet = VNmap[w]) != -1 ) {
zwid = NYmap[wnet] ;
if ( YCmap[zwid] == 0 ) {
first = wnet + 1 ;
second = vnet ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n B: arc (%d, %d) --> (%d,%d)",
w, v, first, second) ;
fflush(msgFile) ;
}
Network_addArc(network, first, second, maxcap, 0) ;
}
}
}
break ;
case 3 :
first = source ;
second = vnet ;
Network_addArc(network, first, second, vwght, 0) ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n B: arc (source, %d) --> (%d,%d)",
v, first, second) ;
fflush(msgFile) ;
}
first = vnet ;
second = sink ;
Network_addArc(network, first, second, vwght, 0) ;
if ( msglvl > 4 ) {
fprintf(msgFile, "\n B: arc (%d, sink) --> (%d,%d)",
v, first, second) ;
fflush(msgFile) ;
}
break ;
default :
fprintf(stderr,
"\n fatal error, y = %d, v = %d, YCmap[%d] = %d",
y, v, y, YCmap[y]) ;
exit(-1) ;
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(VNmap) ;
return(network) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------
partition evaluation function
-----------------------------
*/
static float
eval (
float alpha,
float wS,
float wB,
float wW
) {
float cost ;
if ( wB == 0 || wW == 0 ) {
cost = (wS + wB + wW) * (wS + wB + wW) ;
} else if ( wB >= wW ) {
cost = wS*(1. + (alpha*wB)/wW) ;
} else {
cost = wS*(1. + (alpha*wW)/wB) ;
}
return(cost) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
given a min-cut via the mark[] vector,
get the new component ids
created -- 96jun08, cca
--------------------------------------
*/
static void
getNewCompids (
int nnode,
int NYmap[],
int YCmap[],
int mark[],
int Ycompids[],
int msglvl,
FILE *msgFile
) {
int sink, y, ynet ;
/*
------------------------------------------
decide whether to accept the new separator
------------------------------------------
*/
sink = nnode - 1 ;
ynet = 1 ;
while ( ynet < sink ) {
y = NYmap[ynet] ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n ynet = %d, y = %d, YCmap[%d] = %d",
ynet, y, y, YCmap[y]) ;
fflush(msgFile) ;
}
switch ( YCmap[y] ) {
case 0 :
if ( mark[ynet] != mark[ynet+1] ) {
Ycompids[y] = 0 ;
} else {
Ycompids[y] = mark[ynet] ;
}
ynet += 2 ;
break ;
case 1 :
if ( mark[ynet] == 1 ) {
Ycompids[y] = 1 ;
} else {
Ycompids[y] = 0 ;
}
ynet++ ;
break ;
case 2 :
if ( mark[ynet] == 2 ) {
Ycompids[y] = 2 ;
} else {
Ycompids[y] = 0 ;
}
ynet++ ;
break ;
case 3 :
Ycompids[y] = 0 ;
ynet++ ;
break ;
default :
fprintf(stderr, "\n fatal error in getNewCompids()"
"\n ynet = %d, y = %d, YCmap[%d] = %d",
ynet, y, y, YCmap[y]) ;
exit(-1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, ", Ycompids[%d] = %d", y, Ycompids[y]) ;
fflush(msgFile) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
*YCmapIV,
IV *NYmapIV,
int msglvl,
FILE *msgFile
) {
int first, ierr, ii, i0, i1, i12, i2, maxcap, mnode,
n0, n1, n12, n2, nvtx, nY, second, sink, source, v, vnet,
vsize, vwght, w, wnet, y, zwid ;
int *NYmap, *vadj, *VNmap, *vwghts, *YCmap, *YVmap ;
Network *network ;
/*
---------------
check the input
---------------
*/
if ( g == NULL || (nvtx = g->nvtx) <= 0 || compids =GPart/src/split.c 0100644 0002055 0007177 00000005731 06534106121 0015200 0 ustar 00cleve compmath 0000040 0000006 /* split.c */
#include "../GPart.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
split the graph partition object into pieces
created -- 95nov29, cca
--------------------------------------------
*/
void
GPart_split (
GPart *gpart
) {
FILE *msgFile ;
GPart *gpartchild ;
Graph *g, *gchild ;
int domwght, icomp, ierr, msglvl, ncomp, nvtot, nvtx, sepwght ;
int *compids, *cweights, *map ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || (g = gpart->g) == NULL ) {
fprintf(stderr, "\n fatal error in GPart_split(%p)"
"\n bad input\n", gpart) ;
exit(-1) ;
}
if ( gpart->fch != NULL ) {
fprintf(stderr, "\n fatal error in GPart_split(%p)"
"\n child(ren) exist, already split\n", gpart) ;
exit(-1) ;
}
msgFile = gpart->msgFile ;
msglvl = gpart->msglvl ;
/*
------------------------------
count the number of subgraphs
and fill the cweights[] vector
------------------------------
*/
nvtx = g->nvtx ;
GPart_setCweights(gpart) ;
ncomp = gpart->ncomp ;
cweights = IV_entries(&gpart->cweightsIV) ;
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n\n inside GPart_split, %d components, cweights : ",
ncomp) ;
IV_fp80(&gpart->cweightsIV, msgFile, 25, &ierr) ;
}
if ( ncomp == 1 ) {
return ;
}
/*
-----------------------------------------
compute the weight of the components and
count the number of nontrivial components
-----------------------------------------
*/
sepwght = cweights[0] ;
domwght = 0 ;
for ( icomp = 1 ; icomp <= ncomp ; icomp++ ) {
domwght += cweights[icomp] ;
}
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n separator weight = %d, weight of components = %d",
sepwght, domwght) ;
}
/*
------------------------------------------------------
for each component
create its subgraph with boundary
create a GPart object to contain the subgraph
and set as the child of the present GPart object
end for
------------------------------------------------------
*/
compids = IV_entries(&gpart->compidsIV) ;
for ( icomp = 1 ; icomp <= ncomp ; icomp++ ) {
gpartchild = GPart_new() ;
gchild = Graph_subGraph(g, icomp, compids, &map) ;
if ( msglvl > 3 ) {
fprintf(msgFile, "\n\n component %d", icomp) ;
fprintf(msgFile, "\n map to parent") ;
IVfp80(msgFile, gchild->nvtx + gchild->nvbnd, map, 80, &ierr) ;
Graph_writeForHumanEye(gchild, msgFile) ;
fflush(msgFile) ;
}
GPart_init(gpartchild, gchild) ;
nvtot = gpartchild->nvtx + gpartchild->nvbnd ;
IV_init2(&gpartchild->vtxMapIV, nvtot, nvtot, 1, map) ;
gpartchild->par = gpart ;
gpartchild->sib = gpart->fch ;
gpart->fch = gpartchild ;
gpartchild->msglvl = gpart->msglvl ;
gpartchild->msgFile = gpart->msgFile ;
}
return ; }
/*--------------------------------------------------------------------*/
GPart/src/util.c 0100644 0002055 0007177 00000016553 06534106121 0015026 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../GPart.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
set the component weights from the compids[] vector
created -- 95oct05, cca
modified -- 95nov29, cca
----------------------------------------------------
*/
void
GPart_setCweights (
GPart *gpart
) {
Graph *g ;
int ierr, ii, last, ncomp, now, nvtx, u, usize, v, w ;
int *compids, *cweights, *list, *uadj, *vwghts ;
/*
--------------
check the data
--------------
*/
if ( gpart == NULL ) {
fprintf(stderr, "\n fatal error in GPart_setCweights(%p)"
"\n bad input\n", gpart) ;
exit(-1) ;
}
if ( (nvtx = gpart->nvtx) <= 0 || (g = gpart->g) == NULL ) {
fprintf(stderr, "\n fatal error in GPart_setCweights(%p)"
"\n bad Gpart object\n", gpart) ;
exit(-1) ;
}
/*
----------------------------------------------------------
set the component id of all non-multisector vertices to -1
----------------------------------------------------------
*/
compids = IV_entries(&gpart->compidsIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( compids[v] != 0 ) {
compids[v] = -1 ;
}
}
/*
----------------------------------------------------------
compute the number of components and set the component ids
----------------------------------------------------------
*/
list = IVinit(nvtx, -1) ;
ncomp = 0 ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( compids[v] == -1 ) {
compids[v] = ++ncomp ;
now = last = 0 ;
list[now] = v ;
while ( now <= last ) {
u = list[now++] ;
Graph_adjAndSize(g, u, &usize, &uadj) ;
for ( ii = 0 ; ii < usize ; ii++ ) {
if ( (w = uadj[ii]) < nvtx && compids[w] == -1 ) {
compids[w] = ncomp ;
list[++last] = w ;
}
}
}
}
}
/*
----------------------------
set the number of components
----------------------------
*/
gpart->ncomp = ncomp ;
/*
-------------------------
set the component weights
-------------------------
*/
IV_setSize(&gpart->cweightsIV, 1 + ncomp) ;
cweights = IV_entries(&gpart->cweightsIV) ;
IVzero(1 + ncomp, cweights) ;
if ( (vwghts = gpart->g->vwghts) != NULL ) {
for ( v = 0 ; v < nvtx ; v++ ) {
cweights[compids[v]] += vwghts[v] ;
}
} else {
for ( v = 0 ; v < nvtx ; v++ ) {
cweights[compids[v]]++ ;
}
}
/*
------------------------
free the working storage
------------------------
*/
IVfree(list) ;
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 95oct05, cca
----------------------------------------------
*/
int
GPart_sizeOf (
GPart *gpart
) {
int nbytes ;
if ( gpart == NULL ) {
fprintf(stderr, "\n fatal error in GPart_sizeOf(%p)"
"\n bad input\n", gpart) ;
exit(-1) ;
}
nbytes = sizeof(struct _GPart) ;
nbytes += IV_size(&gpart->compidsIV) ;
nbytes += IV_size(&gpart->cweightsIV) ;
nbytes += IV_size(&gpart->vtxMapIV) ;
return(nbytes) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
return 1 if vertex is adjacent to only one domain
and fill *pdomid with the domain's id
return 0 otherwise
created -- 95oct19, cca
-------------------------------------------------
*/
int
GPart_vtxIsAdjToOneDomain (
GPart *gpart,
int v,
int *pdomid
) {
Graph *g ;
int domid, ii, nvtx, u, Vi, vsize ;
int *compids, *vadj ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || v < 0 || (nvtx = gpart->nvtx) <= v
|| (g = gpart->g) == NULL || pdomid == NULL ) {
fprintf(stderr,
"\n fatal error in GPart_vtxIsAdjToOneDomain(%p,%d,%p)"
"\n bad input\n", gpart, v, pdomid) ;
exit(-1) ;
}
compids = IV_entries(&gpart->compidsIV) ;
/*
------------------------------------------
fill domids[] with ids of adjacent domains
------------------------------------------
*/
Graph_adjAndSize(g, v, &vsize, &vadj) ;
domid = *pdomid = -1 ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
if ( (u = vadj[ii]) < nvtx && (Vi = compids[u]) > 0 ) {
if ( domid == -1 ) {
*pdomid = domid = Vi ;
} else if ( Vi != domid ) {
return(0) ;
}
}
}
if ( domid == -1 ) {
return(0) ;
} else {
return(1) ; }
}
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
return 1 if the partition has a valid vertex separator
0 otherwise
created -- 95oct18, cca
------------------------------------------------------
*/
int
GPart_validVtxSep (
GPart *gpart
) {
Graph *g ;
int icomp, ii, nvtx, v, vsize, w ;
int *compids, *vadj ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL ) {
fprintf(stderr, "\n fatal error in GPart_validVtxSep(%p)"
"\n bad input\n", gpart) ;
exit(-1) ;
}
nvtx = gpart->nvtx ;
g = gpart->g ;
compids = IV_entries(&gpart->compidsIV) ;
/*
---------------------------------------------------
loop over the vertices
check that each non-separator vertex is adjacent to
vertices only in its component or in the separator
---------------------------------------------------
*/
for ( v = 0 ; v < nvtx ; v++ ) {
if ( (icomp = compids[v]) != 0 ) {
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
if ( (w = vadj[ii]) < nvtx ) {
if ( compids[w] != 0 && compids[w] != icomp ) {
fprintf(stderr,
"\n vertex %d, component %d, is adjacent to vertex %d, component %d",
v, icomp, w, compids[w]) ;
return(0) ;
}
}
}
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------
return an IV object filled with the
weights of the component's boundaries
created -- 96oct21, cca
-------------------------------------
*/
IV *
GPart_bndWeightsIV (
GPart *gpart
) {
Graph *graph ;
int icomp, ii, ncomp, nvtx, v, vsize, vwght, w ;
int *bnd, *compids, *cweights, *mark, *vadj, *vwghts ;
IV *bndIV ;
/*
---------------
check the input
---------------
*/
if ( gpart == NULL || (graph = gpart->g) == NULL ) {
fprintf(stderr, "\n fatal error in GPart_bndWeightsIV(%p)"
"\n bad input\n", gpart) ;
exit(-1) ;
}
nvtx = gpart->nvtx ;
ncomp = gpart->ncomp ;
compids = IV_entries(&gpart->compidsIV) ;
cweights = IV_entries(&gpart->cweightsIV) ;
vwghts = graph->vwghts ;
bndIV = IV_new() ;
IV_init(bndIV, 1 + ncomp, NULL) ;
IV_fill(bndIV, 0) ;
bnd = IV_entries(bndIV) ;
mark = IVinit(ncomp+1, -1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( compids[v] == 0 ) {
vwght = (vwghts == NULL) ? 1 : vwghts[v] ;
Graph_adjAndSize(graph, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( (icomp = compids[w]) != 0 && mark[icomp] != v ) {
mark[icomp] = v ;
bnd[icomp] += vwght ;
}
}
}
}
IVfree(mark) ;
return(bndIV) ; }
/*--------------------------------------------------------------------*/
GPart/drivers/do_DDviaFishnet 0100755 0002055 0007177 00000001222 06542760412 0017507 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = BCSSTK24
set inGraphFile = $matrices/$matrix/orig1.graphf
set msglvl = 2
set msgFile = stdout
set firstseed = 1
set lastseed = 2
set lastseed = 21
set lastseed = 6
set lastseed = 51
set lastseed = 11
set lastseed = 1
set minweight = 100
set maxweight = 200
set freeze = 4.0
set outIVfile = none
set outIVfile = $matrices/$matrix/fishnet.ivf
@ seed = $firstseed
while ( $seed <= $lastseed )
testDDviaFishnet $msglvl $msgFile $inGraphFile \
$freeze $minweight $maxweight $seed \
$outIVfile
@ seed = $seed + 1
end
GPart/drivers/do_RBviaDDsep 0100755 0002055 0007177 00000003117 06545170061 0017125 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set matrix = BCSSTK16
set matrix = BCSSTK24
set inGraphFile = $matrices/$matrix/orig0.graphf
set inGraphFile = $matrices/$matrix/orig1.graphf
set msglvl = 1
set msgFile = stdout
set nseed = 1
set nseed = 21
set minweight = 10
set maxweight = 20
set minweight = 50
set maxweight = 100
set minweight = 200
set maxweight = 400
set minweight = 5
set maxweight = 10
set minweight = 100
set maxweight = 200
set alpha = 0.25
set alpha = 1.0
set freeze = 4.0
set maxDomWeight = 200000
set maxDomWeight = 8000
set maxDomWeight = 2000
set maxDomWeight = 4000
set maxDomWeight = 500
set maxDomWeight = 250
set maxDomWeight = 8000
set maxDomWeight = 16000
set maxDomWeight = 9
set maxDomWeight = 200
set maxDomWeight = 500
set maxDomWeight = 10
set maxDomWeight = 100
set DDoption = 1
set ordertype = 1
set outIVfile = $matrices/$matrix/levels50.ivf
set outIVfile = none
set outDSTreeFile = $matrices/$matrix/ms.dstreef
set outDSTreeFile = none
set outDSTreeFile = $matrices/$matrix/nd.dstreef
set seed = 1
set nlayer = 3
set msgFile = $matrix.res.$nlayer.$alpha
set msgFile = res.$matrix
set msgFile = stdout
set firstseed = 1
set lastseed = 11
set lastseed = 1
@ seed = $firstseed
while ( $seed <= $lastseed )
echo 'maxDomWeight = ' $maxDomWeight ' seed = ' $seed
testRBviaDDsep $msglvl $msgFile $inGraphFile $seed \
$minweight $maxweight $freeze $alpha \
$maxDomWeight $DDoption $nlayer
@ seed = $seed + 1
end
4.0
set maxDomWeight = 200000
set maxDomWeight = 8000
set maxDomWeight = 2000
set maxDomWeight = 4000
set maxDomWeight = 500
set maxDomWeight = 250
set maxDomWeight = 8000
set maxDomWeight = 16000
set maxDomWeight = 9
set maxDomWeight = 200
set maxDomWeight = 500
set maxDomWeight = 10
set maxDomWeight = 100
set DDoption = 1
set ordertype = 1
set outIVfile = $matrices/$matrix/levels50.ivf
set outIVfile = none
set ouGPart/drivers/do_RBviaDDsep2 0100755 0002055 0007177 00000002652 06545170064 0017215 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set matrix = BCSSTK16
set matrix = BCSSTK24
set inGraphFile = $matrices/$matrix/orig0.graphf
set inGraphFile = $matrices/$matrix/orig1.graphf
set msglvl = 1
set msgFile = res14
set msgFile = stdout
set nseed = 21
set nseed = 1
set minweight = 100
set maxweight = 200
set minweight = 200
set maxweight = 400
set minweight = 10
set maxweight = 20
set minweight = 5
set maxweight = 10
set minweight = 50
set maxweight = 100
set alpha = 0.25
set freeze = 4.0
set alpha = 1.0
set alpha = 0.1
set maxDomWeight = 200000
set maxDomWeight = 8000
set maxDomWeight = 2000
set maxDomWeight = 4000
set maxDomWeight = 500
set maxDomWeight = 250
set maxDomWeight = 8000
set maxDomWeight = 16000
set maxDomWeight = 9
set maxDomWeight = 200
set maxDomWeight = 500
set maxDomWeight = 1
set maxDomWeight = 100
set maxDomWeight = 50
set DDoption = 1
set ordertype = 1
set outIVfile = $matrices/$matrix/levels50.ivf
set outIVfile = none
set outDSTreeFile = $matrices/$matrix/ms.dstreef
set outDSTreeFile = $matrices/$matrix/nd.dstreef
set outDSTreeFile = none
set nlayer = 3
set ntest = 21
set ntest = 1
echo 'maxDomWeight = ' $maxDomWeight
testRBviaDDsep2 $msglvl $msgFile $inGraphFile $ntest \
$minweight $maxweight $freeze $alpha \
$maxDomWeight $DDoption $nlayer
GPart/drivers/do_SmoothBisector 0100755 0002055 0007177 00000001110 06545170105 0020134 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = BCSSTK16
set inGraphFile = $matrices/$matrix/orig1.graphb
set inIVfile = $matrices/$matrix/bkl.ivf
set msglvl = 1
set smoothOption = 2
set smoothOption = 1
set smoothOption = 3
set msgFile = stdout
set alpha = 1.0
echo ' inGraphFile = ' $inGraphFile
foreach smoothOption ( 1 2 3 4 5 )
set outIVfile = $matrices/$matrix/bkl$smoothOption.ivf
set outIVfile = none
testSmoothBisector $msglvl $msgFile $inGraphFile $inIVfile \
$smoothOption $alpha $outIVfile
end
GPart/drivers/do_TwoSetViaBKL 0100755 0002055 0007177 00000001442 06542760537 0017431 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set matrix = BCSSTK16
set matrix = BCSSTK24
set inGraphFile = $matrices/$matrix/orig0.graphf
set inGraphFile = $matrices/$matrix/orig1.graphf
set msglvl = 2
set msgFile = stdout
set firstseed = 1
set lastseed = 2
set lastseed = 21
set lastseed = 6
set lastseed = 51
set lastseed = 11
set lastseed = 1
set alpha = 1.0
echo ' matrix = ' $matrix
set inIVfile = $matrices/$matrix/fishnet.ivf
set outIVfile = $matrices/$matrix/bkl.ivf
set outIVfile = none
set msgFile = stdout
@ seed = $firstseed
while ( $seed <= $lastseed )
testTwoSetViaBKL $msglvl $msgFile $inGraphFile \
$inIVfile $seed $alpha $outIVfile
@ seed = $seed + 1
end
GPart/drivers/do_mkDSTree 0100755 0002055 0007177 00000003203 06553752135 0016663 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set matrix = BCSSTK16
set matrix = BCSSTK24
set inGraphFile = $matrices/$matrix/orig0.graphf
set inGraphFile = $matrices/$matrix/orig1.graphf
set matrices = ../../../matrices
set matrix = GRD15x15x127
set inGraphFile = $matrices/$matrix/orig0.graphb
set msglvl = 1
set msgFile = stdout
set nseed = 21
set nseed = 1
set minweight = 10
set maxweight = 20
set minweight = 100
set maxweight = 200
set minweight = 200
set maxweight = 400
set minweight = 50
set maxweight = 100
set minweight = 5
set maxweight = 10
set freeze = 4.0
set alpha = 0.25
set alpha = 0.5
set alpha = 0.75
set alpha = 1.0
set alpha = 0.1
set maxDomWeight = 200000
set maxDomWeight = 8000
set maxDomWeight = 2000
set maxDomWeight = 4000
set maxDomWeight = 500
set maxDomWeight = 250
set maxDomWeight = 8000
set maxDomWeight = 16000
set maxDomWeight = 9
set maxDomWeight = 200
set maxDomWeight = 500
set maxDomWeight = 25
set maxDomWeight = 1
set maxDomWeight = 100
set maxDomWeight = 343
set maxDomWeight = 3375
set DDoption = 1
set ordertype = 1
set outIVfile = $matrices/$matrix/levels50.ivf
set outIVfile = $matrices/$matrix/levels.ivf
set outIVfile = none
set outDSTreeFile = $matrices/$matrix/ms.dstreef
set outDSTreeFile = $matrices/$matrix/nd.dstreef
set outDSTreeFile = none
set outDSTreeFile = $matrices/$matrix/nd2.dstreef
set seed = 4
set nlayer = 2
mkDSTree $msglvl $msgFile $inGraphFile $seed \
$minweight $maxweight $freeze $alpha \
$maxDomWeight $DDoption $nlayer $outDSTreeFile
GPart/drivers/makefile 0100644 0002055 0007177 00000001762 06653142460 0016300 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = testDDviaFishnet \
testTwoSetViaBKL \
testSmoothBisector \
testRBviaDDsep \
mkDSTree \
testRBviaDDsep2
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
mkDSTree : mkDSTree.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testSmoothBisector : testSmoothBisector.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testTwoSetViaBKL : testTwoSetViaBKL.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testDDviaFishnet : testDDviaFishnet.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testRBviaDDsep2 : testRBviaDDsep2.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testRBviaDDsep : testRBviaDDsep.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
GPart/drivers/mkDSTree.c 0100644 0002055 0007177 00000014764 06540047036 0016426 0 ustar 00cleve compmath 0000040 0000006 /* mkDSTree.c */
#include "../GPart.h"
#include "../../DSTree.h"
#include "../../MSMD.h"
#include "../../BKL.h"
#include "../../ETree.h"
#include "../../Perm.h"
#include "../../IV.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------------------------
test the recursive bisection algorithm that uses
(1) fishnet to get the domain decomposition
(2) domain/segment BKL to get the two set partition
(3) Dulmadge-Mendelsohn decomposition to smooth the bisector
the output is a DSTree object to hold the domain/separator tree
created -- 96mar09, cca
---------------------------------------------------------------
*/
{
char *inGraphFileName, *msgFileName, *outDSTreeFileName ;
DSTree *dstree ;
DDsepInfo *info ;
double alpha, freeze, msCPU, t1, t2 ;
FILE *msgFile ;
GPart *gpart ;
Graph *gf ;
int DDoption, maxdomweight, maxweight, minweight, msglvl,
nlayer, nvtx, rc, seed ;
if ( argc != 13 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile seed"
"\n minweight maxweight freeze alpha maxdomwght "
"\n DDoption nlayer outDSTreeFileName"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n seed -- random number seed"
"\n minweight -- minimum domain weight"
"\n maxweight -- maximum domain weight"
"\n freeze -- cutoff multiplier for nodes of high degree"
"\n alpha -- cost function parameter"
"\n maxdomweight -- maximum subgraph weight"
"\n DDoption -- option for domain decomposition"
"\n 1 --> fishnet for each subgraph"
"\n 2 --> fishnet for graph, projection for each subgraph"
"\n nlayer -- number of layers for max flow improvement"
"\n outDSTreeFileName -- output file, must be *.dstreef"
"\n or *.dstreeb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
msgFileName = argv[2] ;
if ( strcmp(msgFileName, "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(msgFileName, "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], msgFileName) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
seed = atoi(argv[4]) ;
minweight = atoi(argv[5]) ;
maxweight = atoi(argv[6]) ;
freeze = atof(argv[7]) ;
alpha = atof(argv[8]) ;
maxdomweight = atoi(argv[9]) ;
DDoption = atoi(argv[10]) ;
nlayer = atoi(argv[11]) ;
outDSTreeFileName = argv[12] ;
fprintf(msgFile,
"\n %s : "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n seed -- %d"
"\n minweight -- %d"
"\n maxweight -- %d"
"\n freeze -- %f"
"\n alpha -- %f"
"\n maxdomweight -- %d"
"\n DDoption -- %d"
"\n nlayer -- %d"
"\n outDSTreeFile -- %s"
"\n", argv[0], msglvl, msgFileName, inGraphFileName, seed,
minweight, maxweight, freeze, alpha, maxdomweight, DDoption,
nlayer, outDSTreeFileName) ;
fflush(msgFile) ;
/*
---------------------------------------
initialize the DDsep information object
---------------------------------------
*/
info = DDsepInfo_new() ;
info->seed = seed ;
info->minweight = minweight ;
info->maxweight = maxweight ;
info->freeze = freeze ;
info->alpha = alpha ;
info->DDoption = DDoption ;
info->maxcompweight = maxdomweight ;
info->nlayer = nlayer ;
info->msglvl = msglvl ;
info->msgFile = msgFile ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
gf = Graph_new() ;
Graph_setDefaultFields(gf) ;
if ( (rc = Graph_readFromFile(gf, inGraphFileName)) != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, gf, inGraphFileName) ;
exit(-1) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
nvtx = gf->nvtx ;
if ( msglvl < 4 ) {
Graph_writeStats(gf, msgFile) ;
fflush(msgFile) ;
} else {
Graph_writeForHumanEye(gf, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------
create the GPart object
-----------------------
*/
MARKTIME(t1) ;
gpart = GPart_new() ;
GPart_init(gpart, gf) ;
GPart_setMessageInfo(gpart, msglvl, msgFile) ;
MARKTIME(t2) ;
/*
------------------------------------------
get the DSTree object that represents the
domain/separator partition of the vertices
------------------------------------------
*/
MARKTIME(t1) ;
dstree = GPart_RBviaDDsep(gpart, info) ;
MARKTIME(t2) ;
msCPU = t2 - t1 ;
fprintf(msgFile, "\n\n CPU %9.5f : find subgraph tree ", msCPU) ;
DDsepInfo_writeCpuTimes(info, msgFile) ;
if ( msglvl > 0 ) {
fprintf(msgFile, "\n # subgraphs = %d", dstree->tree->n) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n DSTree subgraph tree") ;
DSTree_writeForHumanEye(dstree, msgFile) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n map from vertices to subgraphs") ;
IV_writeForHumanEye(dstree->mapIV, msgFile) ;
fflush(msgFile) ;
}
DDsepInfo_free(info) ;
/*
--------------------------------------------
renumber the tree via a post-order traversal
--------------------------------------------
*/
DSTree_renumberViaPostOT(dstree) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n renumbered DSTree subgraph tree") ;
DSTree_writeForHumanEye(dstree, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------------------------
optionally write the DSTree object to a file
--------------------------------------------
*/
if ( strcmp(outDSTreeFileName, "none") != 0 ) {
DSTree_writeToFile(dstree, outDSTreeFileName) ;
}
/*
----------------------------
free all the working storage
----------------------------
*/
Graph_free(gpart->g) ;
GPart_free(gpart) ;
DSTree_free(dstree) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
GPart/drivers/testDDviaFishnet.c 0100644 0002055 0007177 00000012001 06540045322 0020132 0 ustar 00cleve compmath 0000040 0000006 /* testDDviaFishnet.c */
#include "../GPart.h"
#include "../../DSTree.h"
#include "../../MSMD.h"
#include "../../BKL.h"
#include "../../ETree.h"
#include "../../Perm.h"
#include "../../IV.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------------------------
read in a Graph and generate a domain decomposition via fishnet
created -- 96oct21, cca
---------------------------------------------------------------
*/
{
char *inGraphFileName, *msgFileName, *outIVfileName ;
double t1, t2 ;
FILE *msgFile ;
float freeze ;
GPart *gpart ;
Graph *graph ;
int maxweight, minweight, msglvl, nvtx, rc, seed ;
if ( argc != 9 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile "
"\n freeze minweight maxweight seed outIVfile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n freeze -- freeze factor, try 4"
"\n minweight -- minimum domain weight"
"\n maxweight -- maximum domain weight"
"\n seed -- random number seed"
"\n outIVfile -- output file for vertex component ids,"
"\n must be *.ivf or *.ivb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
msgFileName = argv[2] ;
if ( strcmp(msgFileName, "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(msgFileName, "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], msgFileName) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
freeze = atof(argv[4]) ;
minweight = atoi(argv[5]) ;
maxweight = atoi(argv[6]) ;
seed = atoi(argv[7]) ;
outIVfileName = argv[8] ;
fprintf(msgFile,
"\n %s : "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n freeze -- %f"
"\n minweight -- %d"
"\n maxweight -- %d"
"\n seed -- %d"
"\n outIVfile -- %s"
"\n", argv[0], msglvl, msgFileName, inGraphFileName, freeze,
minweight, maxweight, seed, outIVfileName) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
graph = Graph_new() ;
Graph_setDefaultFields(graph) ;
if ( (rc = Graph_readFromFile(graph, inGraphFileName)) != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
nvtx = graph->nvtx ;
if ( msglvl < 4 ) {
Graph_writeStats(graph, msgFile) ;
fflush(msgFile) ;
} else {
Graph_writeForHumanEye(graph, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------
create the GPart object
-----------------------
*/
MARKTIME(t1) ;
gpart = GPart_new() ;
GPart_init(gpart, graph) ;
GPart_setMessageInfo(gpart, msglvl, msgFile) ;
MARKTIME(t2) ;
/*
---------------------------------------------
generate the domain decomposition via Fishnet
---------------------------------------------
*/
MARKTIME(t1) ;
GPart_DDviaFishnet(gpart, freeze, minweight, maxweight, seed) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : generate domain decomposition",
t2 - t1) ;
/*
-------------------------------------------
check that we have a valid vertex separator
-------------------------------------------
*/
if ( 1 != GPart_validVtxSep(gpart) ) {
fprintf(msgFile, "\n\n WHOA : multisector is not valid\n\n") ;
fflush(msgFile) ;
}
/*
----------------------------------
get the boundary weights IV object
----------------------------------
*/
if ( msglvl > 1 ) {
int icomp, ncomp ;
int *bnd, *cweights ;
IV *bndIV ;
bndIV = GPart_bndWeightsIV(gpart) ;
bnd = IV_entries(bndIV) ;
ncomp = gpart->ncomp ;
cweights = IV_entries(&gpart->cweightsIV) ;
fprintf(stdout,
"\n %% component id, component weight, boundary weight"
"\n data = [ ...") ;
for ( icomp = 0 ; icomp <= ncomp ; icomp++ ) {
fprintf(stdout, "\n %8d %8d %8d",
icomp, cweights[icomp], bnd[icomp]) ;
}
fprintf(stdout, " ] ") ;
IV_free(bndIV) ;
}
/*
------------------------------------------
optionally write out the compids IV object
------------------------------------------
*/
if ( strcmp(outIVfileName, "none") != 0 ) {
IV_writeToFile(&gpart->compidsIV, outIVfileName) ;
}
/*
------------------------
free the data structures
------------------------
*/
GPart_free(gpart) ;
Graph_free(graph) ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
GPart/drivers/testRBviaDDsep.c 0100644 0002055 0007177 00000027031 06540046134 0017560 0 ustar 00cleve compmath 0000040 0000006 /* testRBviaDDsep.c */
#include "../GPart.h"
#include "../../DSTree.h"
#include "../../MSMD.h"
#include "../../BKL.h"
#include "../../ETree.h"
#include "../../Perm.h"
#include "../../IV.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
------------------------------------------------------------
test the recursive bisection algorithm that uses
(1) fishnet to get the domain decomposition
(2) domain/segment BKL to get the two set partition
(3) Dulmadge-Mendelsohn decomposition to smooth the bisector
created -- 96mar09, cca
------------------------------------------------------------
*/
{
char *inGraphFileName, *msgFileName ;
DSTree *dstree ;
DDsepInfo *info ;
double alpha, freeze, msCPU, msops, ndCPU, ndops,
phiFrac, rbCPU, t1, t2 ;
ETree *etree ;
FILE *msgFile ;
GPart *gpart ;
Graph *gf ;
int DDoption, ierr, maxdomweight, maxweight, minweight,
msnfind, msnzf, msglvl,
ndnfind, ndnzf, nlayer, nvtx, phiWeight, rc, seed ;
int *emap ;
IV *stagesIV ;
MSMD *msmd ;
MSMDinfo *msmdinfo ;
if ( argc != 12 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile seed"
"\n minweight maxweight freeze alpha maxdomwght "
"\n DDoption nlayer"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n seed -- random number seed"
"\n minweight -- minimum domain weight"
"\n maxweight -- maximum domain weight"
"\n freeze -- cutoff multiplier for nodes of high degree"
"\n alpha -- cost function parameter"
"\n maxdomweight -- maximum subgraph weight"
"\n DDoption -- option for domain decomposition"
"\n 1 --> fishnet for each subgraph"
"\n 2 --> fishnet for graph, projection for each subgraph"
"\n nlayer -- number of layers for max flow improvement"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
msgFileName = argv[2] ;
if ( strcmp(msgFileName, "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(msgFileName, "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], msgFileName) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
seed = atoi(argv[4]) ;
minweight = atoi(argv[5]) ;
maxweight = atoi(argv[6]) ;
freeze = atof(argv[7]) ;
alpha = atof(argv[8]) ;
maxdomweight = atoi(argv[9]) ;
DDoption = atoi(argv[10]) ;
nlayer = atoi(argv[11]) ;
fprintf(msgFile,
"\n %s : "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n seed -- %d"
"\n minweight -- %d"
"\n maxweight -- %d"
"\n freeze -- %f"
"\n alpha -- %f"
"\n maxdomweight -- %d"
"\n DDoption -- %d"
"\n nlayer -- %d"
"\n", argv[0], msglvl, msgFileName, inGraphFileName, seed,
minweight, maxweight, freeze, alpha, maxdomweight, DDoption,
nlayer) ;
fflush(msgFile) ;
/*
---------------------------------------
initialize the DDsep information object
---------------------------------------
*/
info = DDsepInfo_new() ;
info->seed = seed ;
info->minweight = minweight ;
info->maxweight = maxweight ;
info->freeze = freeze ;
info->alpha = alpha ;
info->DDoption = DDoption ;
info->maxcompweight = maxdomweight ;
info->nlayer = nlayer ;
info->msglvl = msglvl ;
info->msgFile = msgFile ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
gf = Graph_new() ;
Graph_setDefaultFields(gf) ;
if ( (rc = Graph_readFromFile(gf, inGraphFileName)) != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, gf, inGraphFileName) ;
exit(-1) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
nvtx = gf->nvtx ;
if ( msglvl > 3 ) {
Graph_writeForHumanEye(gf, msgFile) ;
fflush(msgFile) ;
} else if ( msglvl > 1 ) {
Graph_writeStats(gf, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------
create the GPart object
-----------------------
*/
MARKTIME(t1) ;
gpart = GPart_new() ;
GPart_init(gpart, gf) ;
GPart_setMessageInfo(gpart, msglvl, msgFile) ;
MARKTIME(t2) ;
/*
------------------------------------------
get the DSTree object that represents the
domain/separator partition of the vertices
------------------------------------------
*/
MARKTIME(t1) ;
dstree = GPart_RBviaDDsep(gpart, info) ;
MARKTIME(t2) ;
rbCPU = t2 - t1 ;
fprintf(msgFile, "\n\n CPU %9.5f : find subgraph tree, %d subgraphs ",
rbCPU, dstree->tree->n) ;
if ( msglvl > 0 ) {
DDsepInfo_writeCpuTimes(info, msgFile) ;
}
/*
--------------------------------------------
compute the weight of the separator vertices
--------------------------------------------
*/
phiWeight = DSTree_separatorWeight(dstree, gf->vwghts) ;
phiFrac = ((double) phiWeight) / gf->totvwght ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n # subgraphs = %d", dstree->tree->n) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n DSTree subgraph tree") ;
DSTree_writeForHumanEye(dstree, msgFile) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n map from vertices to subgraphs") ;
IV_writeForHumanEye(dstree->mapIV, msgFile) ;
fflush(msgFile) ;
}
DDsepInfo_free(info) ;
/*
------------------------------------
set the stages for nested dissection
------------------------------------
*/
stagesIV = DSTree_NDstages(dstree) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n stages for ND") ;
IV_writeForHumanEye(stagesIV, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------------------
order as incomplete nested dissection
-------------------------------------
*/
msmdinfo = MSMDinfo_new() ;
msmdinfo->compressFlag = 2 ;
msmdinfo->prioType = 1 ;
msmdinfo->stepType = 1 ;
msmdinfo->seed = seed ;
msmdinfo->msglvl = msglvl ;
msmdinfo->msgFile = msgFile ;
MARKTIME(t1) ;
msmd = MSMD_new() ;
MSMD_order(msmd, gf, IV_entries(stagesIV), msmdinfo) ;
MARKTIME(t2) ;
ndCPU = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : order the graph via ND", ndCPU) ;
fflush(msgFile) ;
if ( msglvl > 1 ) {
MSMDinfo_print(msmdinfo, msgFile) ;
fflush(msgFile) ;
}
IV_free(stagesIV) ;
/*
----------------------
extract the front tree
----------------------
*/
MARKTIME(t1) ;
emap = IVinit(nvtx, -1) ;
etree = MSMD_frontETree(msmd) ;
ndnfind = ETree_nFactorIndices(etree) ;
ndnzf = ETree_nFactorEntries(etree, SPOOLES_SYMMETRIC) ;
ndops = ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
MARKTIME(t2) ;
fprintf(msgFile,
"\n CPU %9.5f : make the elimination tree", t2 - t1) ;
fprintf(msgFile,
"\n ND FACTOR : %9d indices, %9d entries, %9.0f operations",
ndnfind, ndnzf, ndops) ;
/*
ETree_writeToFile(etree, "temp.etreef") ;
*/
if ( msglvl > 3 ) {
ETree_writeForHumanEye(etree, msgFile) ;
fflush(msgFile) ;
} else if ( msglvl > 1 ) {
ETree_writeStats(etree, msgFile) ;
fflush(msgFile) ;
}
fprintf(msgFile, "\n STATSND %10d %10.0f %8.3f %8.3f %8.3f",
ndnzf, ndops, rbCPU, ndCPU, rbCPU + ndCPU) ;
MSMD_free(msmd) ;
MSMDinfo_free(msmdinfo) ;
ETree_free(etree) ;
IVfree(emap) ;
/*
-----------------------------------------
set the stages for two-stage multisection
-----------------------------------------
*/
stagesIV = DSTree_MS2stages(dstree) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n stages for MS2") ;
IV_writeForHumanEye(stagesIV, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------------
order as two-stage multisection
-------------------------------
*/
msmdinfo = MSMDinfo_new() ;
msmdinfo->compressFlag = 2 ;
msmdinfo->prioType = 3 ;
msmdinfo->stepType = 1 ;
msmdinfo->seed = seed ;
msmdinfo->msglvl = msglvl ;
msmdinfo->msgFile = msgFile ;
MARKTIME(t1) ;
msmd = MSMD_new() ;
MSMD_order(msmd, gf, IV_entries(stagesIV), msmdinfo) ;
MARKTIME(t2) ;
msCPU = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : order the graph via MS", msCPU) ;
fflush(msgFile) ;
if ( msglvl > 1 ) {
MSMDinfo_print(msmdinfo, msgFile) ;
fflush(msgFile) ;
}
IV_free(stagesIV) ;
/*
----------------------
extract the front tree
----------------------
*/
MARKTIME(t1) ;
emap = IVinit(nvtx, -1) ;
etree = MSMD_frontETree(msmd) ;
msnfind = ETree_nFactorIndices(etree) ;
msnzf = ETree_nFactorEntries(etree, SPOOLES_SYMMETRIC) ;
msops = ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
MARKTIME(t2) ;
fprintf(msgFile,
"\n CPU %9.5f : make the elimination tree", t2 - t1) ;
fprintf(msgFile,
"\n MS FACTOR : %9d indices, %9d entries, %9.0f operations",
msnfind, msnzf, msops) ;
if ( msglvl > 3 ) {
ETree_writeForHumanEye(etree, msgFile) ;
fflush(msgFile) ;
} else if ( msglvl > 1 ) {
ETree_writeStats(etree, msgFile) ;
fflush(msgFile) ;
}
fprintf(msgFile, "\n STATSMS2 %10d %10.0f %8.3f %8.3f %8.3f",
msnzf, msops, rbCPU, msCPU, rbCPU + msCPU) ;
MSMD_free(msmd) ;
MSMDinfo_free(msmdinfo) ;
ETree_free(etree) ;
IVfree(emap) ;
/*
------------------------
print out the statistics
------------------------
*/
fprintf(msgFile,
"\n ALL %6.3f %8.3f %8d %10.0f %8.3f %8d %10.0f %8.3f",
phiFrac, rbCPU, ndnzf, ndops, ndCPU, msnzf, msops, msCPU) ;
/*
-----------------------
order as minimum degree
-----------------------
*/
/*
msmdinfo = MSMDinfo_new() ;
msmdinfo->compressFlag = 2 ;
msmdinfo->prioType = 3 ;
msmdinfo->stepType = 1 ;
msmdinfo->seed = seed ;
msmdinfo->msglvl = msglvl ;
msmdinfo->msgFile = msgFile ;
MARKTIME(t1) ;
msmd = MSMD_new() ;
MSMD_order(msmd, gf, NULL, msmdinfo) ;
MARKTIME(t2) ;
orderCPU = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : order the graph", orderCPU) ;
fflush(msgFile) ;
MSMDinfo_print(msmdinfo, msgFile) ;
fflush(msgFile) ;
*/
/*
----------------------
extract the front tree
----------------------
*/
/*
MARKTIME(t1) ;
emap = IVinit(nvtx, -1) ;
etree = MSMD_frontETree(msmd) ;
nfind = ETree_nFactorIndices(etree) ;
nzf = ETree_nFactorEntries(etree, SPOOLES_SYMMETRIC) ;
ops = ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
MARKTIME(t2) ;
fprintf(msgFile,
"\n CPU %9.5f : make the elimination tree", t2 - t1) ;
fprintf(msgFile,
"\n FACTOR : %9d indices, %9d entries, %9.0f operations",
nfind, nzf, ops) ;
if ( msglvl < 3 ) {
ETree_writeStats(etree, msgFile) ;
fflush(msgFile) ;
} else {
ETree_writeForHumanEye(etree, msgFile) ;
fflush(msgFile) ;
}
fprintf(msgFile, "\n STATSMD %10d %10.0f %8.3f %8.3f %8.3f",
nzf, ops, 0.0, orderCPU, 0.0 + orderCPU) ;
MSMD_free(msmd) ;
MSMDinfo_free(msmdinfo) ;
ETree_free(etree) ;
IVfree(emap) ;
*/
/*
----------------------------
free all the working storage
----------------------------
*/
Graph_free(gpart->g) ;
GPart_free(gpart) ;
DSTree_free(dstree) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
intf(msgFile, "\n\n CPU %9.5f : find subgraph tree, %d subgraphs ",
rbCPU, dstree->tree->n) ;
if ( msglvl > 0 ) {
DDsepInfo_writeCpuTimes(info, msgFile) ;
}
/*
--------------------------------------------
compute the weight of the separator vertices
--------------------------------------------
*/
phiWeight = DSTree_separatorWeight(dstree, gf->vwghts) ;
phiFrac = ((double) phiWeight) / gf->totvwght ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n # subgraphs = %d",GPart/drivers/testRBviaDDsep2.c 0100644 0002055 0007177 00000031306 06540045147 0017645 0 ustar 00cleve compmath 0000040 0000006 /* testRBviaDDsep2.c */
#include "../GPart.h"
#include "../../DSTree.h"
#include "../../MSMD.h"
#include "../../BKL.h"
#include "../../ETree.h"
#include "../../Perm.h"
#include "../../IV.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
------------------------------------------------------------
test the recursive bisection algorithm that uses
(1) fishnet to get the domain decomposition
(2) domain/segment BKL to get the two set partition
(3) Dulmadge-Mendelsohn decomposition to smooth the bisector
created -- 96mar09, cca
------------------------------------------------------------
*/
{
char *inGraphFileName, *msgFileName ;
DSTree *dstree ;
DDsepInfo *info ;
double alpha, freeze, msCPU, msops, ndCPU, ndops,
phiFrac, rbCPU, t1, t2 ;
double *fracvec, *mscpuvec, *msopsvec,
*ndcpuvec, *ndopsvec, *rbcpuvec ;
ETree *etree ;
FILE *msgFile ;
GPart *gpart ;
Graph *gf ;
int DDoption, maxdomweight, maxweight, minweight,
msnfind, msnzf, msglvl,
ndnfind, ndnzf, nlayer, ntest, nvtx, phiWeight, rc, seed ;
int *emap, *msnzfvec, *ndnzfvec ;
IV *stagesIV ;
MSMD *msmd ;
MSMDinfo *msmdinfo ;
if ( argc != 12 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile ntest"
"\n minweight maxweight freeze alpha maxdomwght "
"\n DDoption nlayer"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n ntest -- number of tests to make"
"\n minweight -- minimum domain weight"
"\n maxweight -- maximum domain weight"
"\n freeze -- cutoff multiplier for nodes of high degree"
"\n alpha -- cost function parameter"
"\n maxdomweight -- maximum subgraph weight"
"\n DDoption -- option for domain decomposition"
"\n 1 --> fishnet for each subgraph"
"\n 2 --> fishnet for graph, projection for each subgraph"
"\n nlayer -- number of layers for max flow improvement"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
msgFileName = argv[2] ;
if ( strcmp(msgFileName, "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(msgFileName, "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], msgFileName) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
ntest = atoi(argv[4]) ;
if ( ntest % 2 == 0 ) {
ntest++ ;
}
minweight = atoi(argv[5]) ;
maxweight = atoi(argv[6]) ;
freeze = atof(argv[7]) ;
alpha = atof(argv[8]) ;
maxdomweight = atoi(argv[9]) ;
DDoption = atoi(argv[10]) ;
nlayer = atoi(argv[11]) ;
fprintf(msgFile,
"\n %s : "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n ntest -- %d"
"\n minweight -- %d"
"\n maxweight -- %d"
"\n freeze -- %f"
"\n alpha -- %f"
"\n maxdomweight -- %d"
"\n DDoption -- %d"
"\n nlayer -- %d"
"\n", argv[0], msglvl, msgFileName, inGraphFileName, ntest,
minweight, maxweight, freeze, alpha, maxdomweight, DDoption,
nlayer) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
gf = Graph_new() ;
Graph_setDefaultFields(gf) ;
if ( (rc = Graph_readFromFile(gf, inGraphFileName)) != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, gf, inGraphFileName) ;
exit(-1) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
nvtx = gf->nvtx ;
if ( msglvl > 3 ) {
Graph_writeForHumanEye(gf, msgFile) ;
fflush(msgFile) ;
} else if ( msglvl > 1 ) {
Graph_writeStats(gf, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------------
allocate the statistics vectors
-------------------------------
*/
fracvec = DVinit(ntest, 0.0) ;
ndnzfvec = IVinit(ntest, 0) ;
msnzfvec = IVinit(ntest, 0) ;
ndopsvec = DVinit(ntest, 0.0) ;
msopsvec = DVinit(ntest, 0.0) ;
rbcpuvec = DVinit(ntest, 0.0) ;
ndcpuvec = DVinit(ntest, 0.0) ;
mscpuvec = DVinit(ntest, 0.0) ;
/*
-------------------
loop over the tests
-------------------
*/
for ( seed = 1 ; seed <= ntest ; seed++ ) {
/*
---------------------------------------
initialize the DDsep information object
---------------------------------------
*/
info = DDsepInfo_new() ;
info->seed = seed ;
info->minweight = minweight ;
info->maxweight = maxweight ;
info->freeze = freeze ;
info->alpha = alpha ;
info->DDoption = DDoption ;
info->maxcompweight = maxdomweight ;
info->nlayer = nlayer ;
info->msglvl = msglvl ;
info->msgFile = msgFile ;
/*
-----------------------
create the GPart object
-----------------------
*/
MARKTIME(t1) ;
gpart = GPart_new() ;
GPart_init(gpart, gf) ;
GPart_setMessageInfo(gpart, msglvl, msgFile) ;
MARKTIME(t2) ;
/*
------------------------------------------
get the DSTree object that represents the
domain/separator partition of the vertices
------------------------------------------
*/
MARKTIME(t1) ;
dstree = GPart_RBviaDDsep(gpart, info) ;
MARKTIME(t2) ;
rbCPU = t2 - t1 ;
phiWeight = DSTree_separatorWeight(dstree, gf->vwghts) ;
fprintf(msgFile,
"\n\n CPU %9.5f : find subgraph tree, %d subgraphs, |Phi| = %d ",
rbCPU, dstree->tree->n, phiWeight) ;
if ( msglvl > 0 ) {
DDsepInfo_writeCpuTimes(info, msgFile) ;
}
/*
--------------------------------------------
compute the weight of the separator vertices
--------------------------------------------
*/
if ( gf->totvwght == 0 ) {
if ( gf->vwghts == NULL ) {
gf->totvwght = nvtx ;
} else {
gf->totvwght = IVsum(nvtx, gf->vwghts) ;
}
}
phiFrac = ((double) phiWeight) / gf->totvwght ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n # subgraphs = %d", dstree->tree->n) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n DSTree subgraph tree") ;
DSTree_writeForHumanEye(dstree, msgFile) ;
fflush(msgFile) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n map from vertices to subgraphs") ;
IV_writeForHumanEye(dstree->mapIV, msgFile) ;
fflush(msgFile) ;
}
DDsepInfo_free(info) ;
/*
-----------------------------------------
set the stages for two-stage multisection
-----------------------------------------
*/
stagesIV = DSTree_MS2stages(dstree) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n stages for MS2") ;
IV_writeForHumanEye(stagesIV, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------
read in the graph
-----------------
Graph_readFromFile(gf, inGraphFileName) ;
*/
/*
-------------------------------
order as two-stage multisection
-------------------------------
*/
msmdinfo = MSMDinfo_new() ;
msmdinfo->compressFlag = 2 ;
msmdinfo->prioType = 1 ;
msmdinfo->stepType = 1 ;
msmdinfo->seed = seed ;
msmdinfo->msglvl = msglvl ;
msmdinfo->msgFile = msgFile ;
MARKTIME(t1) ;
msmd = MSMD_new() ;
MSMD_order(msmd, gf, IV_entries(stagesIV), msmdinfo) ;
MARKTIME(t2) ;
msCPU = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : order the graph via MS", msCPU) ;
fflush(msgFile) ;
if ( msglvl > 1 ) {
MSMDinfo_print(msmdinfo, msgFile) ;
fflush(msgFile) ;
}
IV_free(stagesIV) ;
/*
----------------------
extract the front tree
----------------------
*/
MARKTIME(t1) ;
emap = IVinit(nvtx, -1) ;
etree = MSMD_frontETree(msmd) ;
msnfind = ETree_nFactorIndices(etree) ;
msnzf = ETree_nFactorEntries(etree, SPOOLES_SYMMETRIC) ;
msops = ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
MARKTIME(t2) ;
fprintf(msgFile,
"\n CPU %9.5f : make the elimination tree", t2 - t1) ;
fprintf(msgFile,
"\n MS FACTOR : %9d indices, %9d entries, %9.0f operations",
msnfind, msnzf, msops) ;
if ( msglvl > 3 ) {
ETree_writeForHumanEye(etree, msgFile) ;
fflush(msgFile) ;
} else if ( msglvl > 1 ) {
ETree_writeStats(etree, msgFile) ;
fflush(msgFile) ;
}
fprintf(msgFile, "\n STATSMS2 %10d %10.0f %8.3f %8.3f %8.3f",
msnzf, msops, rbCPU, msCPU, rbCPU + msCPU) ;
MSMD_free(msmd) ;
MSMDinfo_free(msmdinfo) ;
ETree_free(etree) ;
IVfree(emap) ;
/*
------------------------------------
set the stages for nested dissection
------------------------------------
*/
stagesIV = DSTree_NDstages(dstree) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n stages for ND") ;
IV_writeForHumanEye(stagesIV, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------
read in the graph
-----------------
Graph_readFromFile(gf, inGraphFileName) ;
*/
/*
-------------------------------------
order as incomplete nested dissection
-------------------------------------
*/
msmdinfo = MSMDinfo_new() ;
msmdinfo->compressFlag = 2 ;
msmdinfo->prioType = 1 ;
msmdinfo->stepType = 1 ;
msmdinfo->seed = seed ;
msmdinfo->msglvl = msglvl ;
msmdinfo->msgFile = msgFile ;
MARKTIME(t1) ;
msmd = MSMD_new() ;
MSMD_order(msmd, gf, IV_entries(stagesIV), msmdinfo) ;
MARKTIME(t2) ;
ndCPU = t2 - t1 ;
fprintf(msgFile, "\n CPU %9.5f : order the graph via ND", ndCPU) ;
fflush(msgFile) ;
if ( msglvl > 1 ) {
MSMDinfo_print(msmdinfo, msgFile) ;
fflush(msgFile) ;
}
IV_free(stagesIV) ;
/*
----------------------
extract the front tree
----------------------
*/
MARKTIME(t1) ;
emap = IVinit(nvtx, -1) ;
etree = MSMD_frontETree(msmd) ;
ndnfind = ETree_nFactorIndices(etree) ;
ndnzf = ETree_nFactorEntries(etree, SPOOLES_SYMMETRIC) ;
ndops = ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
MARKTIME(t2) ;
fprintf(msgFile,
"\n CPU %9.5f : make the elimination tree", t2 - t1) ;
fprintf(msgFile,
"\n ND FACTOR : %9d indices, %9d entries, %9.0f operations",
ndnfind, ndnzf, ndops) ;
if ( msglvl > 3 ) {
ETree_writeForHumanEye(etree, msgFile) ;
fflush(msgFile) ;
} else if ( msglvl > 1 ) {
ETree_writeStats(etree, msgFile) ;
fflush(msgFile) ;
}
fprintf(msgFile, "\n STATSND %10d %10.0f %8.3f %8.3f %8.3f",
ndnzf, ndops, rbCPU, ndCPU, rbCPU + ndCPU) ;
MSMD_free(msmd) ;
MSMDinfo_free(msmdinfo) ;
ETree_free(etree) ;
IVfree(emap) ;
/*
------------------------
print out the statistics
------------------------
*/
fprintf(msgFile,
"\n ALL %6.3f %8.3f %8d %10.0f %8.3f %8d %10.0f %8.3f",
phiFrac, rbCPU, ndnzf, ndops, ndCPU, msnzf, msops, msCPU) ;
/*
----------------------------
free all the working storage
----------------------------
*/
GPart_free(gpart) ;
DSTree_free(dstree) ;
/*
--------------------
store the statistics
--------------------
*/
fracvec[seed-1] = phiFrac ;
rbcpuvec[seed-1] = rbCPU ;
ndcpuvec[seed-1] = ndCPU ;
mscpuvec[seed-1] = msCPU ;
ndnzfvec[seed-1] = ndnzf ;
msnzfvec[seed-1] = msnzf ;
ndopsvec[seed-1] = ndops ;
msopsvec[seed-1] = msops ;
}
/*
---------------------------
print out the median values
---------------------------
*/
DVqsortUp(ntest, fracvec) ;
DVqsortUp(ntest, rbcpuvec) ;
DVqsortUp(ntest, ndcpuvec) ;
DVqsortUp(ntest, mscpuvec) ;
IVqsortUp(ntest, ndnzfvec) ;
IVqsortUp(ntest, msnzfvec) ;
DVqsortUp(ntest, ndopsvec) ;
DVqsortUp(ntest, msopsvec) ;
fprintf(msgFile,
"\n MEDIAN %6.3f %8.3f %8d %10.0f %8.3f %8d %10.0f %8.3f",
fracvec[ntest/2], rbcpuvec[ntest/2], ndnzfvec[ntest/2],
ndopsvec[ntest/2], ndcpuvec[ntest/2], msnzfvec[ntest/2],
msopsvec[ntest/2], mscpuvec[ntest/2]) ;
/*
----------------------------
free all the working storage
----------------------------
*/
Graph_free(gf) ;
DVfree(fracvec) ;
IVfree(ndnzfvec) ;
IVfree(msnzfvec) ;
DVfree(ndopsvec) ;
DVfree(msopsvec) ;
DVfree(rbcpuvec) ;
DVfree(ndcpuvec) ;
DVfree(mscpuvec) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
GPart/drivers/testSmoothBisector.c 0100644 0002055 0007177 00000016105 06540046602 0020601 0 ustar 00cleve compmath 0000040 0000006 /* testSmooth4.c */
#include "../GPart.h"
#include "../../DSTree.h"
#include "../../MSMD.h"
#include "../../BKL.h"
#include "../../ETree.h"
#include "../../Perm.h"
#include "../../IV.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
------------------------------------------
(1) read in a Graph,
(2) read in a 2-set partition
(3) smooth the separator
(4) optionally write out new partition
created -- 96oct21, cca
------------------------------------------
*/
{
char *inGraphFileName, *inIVfileName,
*msgFileName, *outIVfileName ;
double alpha, cost, t1, t2 ;
FILE *msgFile ;
GPart *gpart ;
Graph *graph ;
int ierr, msglvl, option, nvtx, rc ;
IV *tagsIV ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile inIVfile "
"\n option alpha outIVfile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n inIVFile -- input file, must be *.ivf or *.ivb"
"\n option -- smoothing option"
"\n 1 --> bipartite 2-layers"
"\n 2 --> non-bipartite 2-layers"
"\n k > 2 --> k/2 layers on each side"
"\n alpha -- cost function parameter"
"\n outIVFile -- output file, must be *.ivf or *.ivb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
msgFileName = argv[2] ;
if ( strcmp(msgFileName, "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(msgFileName, "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], msgFileName) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
inIVfileName = argv[4] ;
option = atoi(argv[5]) ;
alpha = atof(argv[6]) ;
outIVfileName = argv[7] ;
fprintf(msgFile,
"\n %s : "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n inIVfile -- %s"
"\n option -- %d"
"\n alpha -- %f"
"\n outIVfile -- %s"
"\n", argv[0], msglvl,
msgFileName, inGraphFileName, inIVfileName,
option, alpha, outIVfileName) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
graph = Graph_new() ;
Graph_setDefaultFields(graph) ;
if ( (rc = Graph_readFromFile(graph, inGraphFileName)) != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
nvtx = graph->nvtx ;
if ( msglvl < 4 ) {
Graph_writeStats(graph, msgFile) ;
fflush(msgFile) ;
} else {
Graph_writeForHumanEye(graph, msgFile) ;
fflush(msgFile) ;
}
/*
------------------------
read in the IV object
------------------------
*/
if ( strcmp(inIVfileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
tagsIV = IV_new() ;
IV_setDefaultFields(tagsIV) ;
if ( (rc = IV_readFromFile(tagsIV, inIVfileName)) != 1 ) {
fprintf(msgFile, "\n return value %d from IV_readFromFile(%p,%s)",
rc, tagsIV, inIVfileName) ;
exit(-1) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in tagsIV from file %s",
t2 - t1, inIVfileName) ;
nvtx = IV_size(tagsIV) ;
if ( msglvl < 4 ) {
IV_writeStats(tagsIV, msgFile) ;
fflush(msgFile) ;
} else {
IV_writeForHumanEye(tagsIV, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------
create the GPart object
-----------------------
*/
MARKTIME(t1) ;
gpart = GPart_new() ;
GPart_init(gpart, graph) ;
GPart_setMessageInfo(gpart, msglvl, msgFile) ;
IV_copy(&gpart->compidsIV, tagsIV) ;
GPart_setCweights(gpart) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : GPart initialized", t2 - t1) ;
fprintf(msgFile, "\n cweights : ") ;
IVfp80(msgFile, 1 + gpart->ncomp, IV_entries(&gpart->cweightsIV),
30, &ierr) ;
fflush(msgFile) ;
if ( msglvl > 0 ) {
int wB, wS, wW ;
int *cweights = IV_entries(&gpart->cweightsIV) ;
fprintf(msgFile, "\n initial component weights :") ;
IVfp80(msgFile, 1+gpart->ncomp, cweights, 20, &ierr) ;
wS = cweights[0] ;
wB = cweights[1] ;
wW = cweights[2] ;
if ( wB < wW ) {
wB = wW ;
wW = cweights[1] ;
}
cost = wS*(1. + (alpha*wB)/wW) ;
fprintf(msgFile,
"\n initial |S| = %d , balance = %6.3f , cpu = %8.3f , cost = %8.1f\n",
wS, ((double) wB)/wW, t2 - t1, cost) ;
fflush(msgFile) ;
}
/*
-------------------------------------------
check that we have a valid vertex separator
-------------------------------------------
*/
if ( 1 != GPart_validVtxSep(gpart) ) {
fprintf(msgFile, "\n\n WHOA : separator is not valid"
"\n\n WHOA : separator is not valid\n\n") ;
fflush(msgFile) ;
}
/*
--------------------
smooth the separator
--------------------
*/
MARKTIME(t1) ;
if ( option <= 2 ) {
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n calling GPart_smoothBy2layers with option %d",
option) ;
fflush(stdout) ;
}
GPart_smoothBy2layers(gpart, option, alpha) ;
} else {
if ( msglvl > 1 ) {
fprintf(msgFile,
"\n calling GPart_smoothBisector with option %d",
option/2) ;
fflush(stdout) ;
}
GPart_smoothBisector(gpart, option/2, alpha) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n\n CPU %9.5f : improve bisector", t2 - t1) ;
if ( msglvl > 0 ) {
int wB, wS, wW ;
int *cweights = IV_entries(&gpart->cweightsIV) ;
fprintf(msgFile, "\n final component weights :") ;
IVfp80(msgFile, 1+gpart->ncomp, cweights, 20, &ierr) ;
wS = cweights[0] ;
wB = cweights[1] ;
wW = cweights[2] ;
if ( wB < wW ) {
wB = wW ;
wW = cweights[1] ;
}
cost = wS*(1. + (alpha*wB)/wW) ;
fprintf(msgFile,
"\n final |S| = %d , balance = %6.3f , cpu = %8.3f , cost = %8.1f\n",
wS, ((double) wB)/wW, t2 - t1, cost) ;
fflush(msgFile) ;
}
/*
-------------------------------------------
check that we have a valid vertex separator
-------------------------------------------
*/
if ( 1 != GPart_validVtxSep(gpart) ) {
fprintf(msgFile, "\n\n WHOA : separator is not valid"
"\n\n WHOA : separator is not valid\n\n") ;
fflush(msgFile) ;
}
/*
------------------------------------------
optionally write the tags file out to disk
------------------------------------------
*/
if ( strcmp(outIVfileName, "none") != 0 ) {
IV_writeToFile(&gpart->compidsIV, outIVfileName) ;
}
/*
------------------------
free the data structures
------------------------
*/
GPart_free(gpart) ;
Graph_free(graph) ;
IV_free(tagsIV) ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
GPart/drivers/testTwoSetViaBKL.c 0100644 0002055 0007177 00000012301 06540046421 0020044 0 ustar 00cleve compmath 0000040 0000006 /* testTwoSetViaBKL.c */
#include "../GPart.h"
#include "../../DSTree.h"
#include "../../MSMD.h"
#include "../../BKL.h"
#include "../../ETree.h"
#include "../../Perm.h"
#include "../../IV.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-----------------------------------------------
read in a Graph,
read in a components IV object
find the two set partition via BKL
created -- 96oct21, cca
-----------------------------------------------
*/
{
char *inGraphFileName, *inIVfileName, *msgFileName,
*outIVfileName ;
double alpha, t1, t2 ;
double cpus[3] ;
FILE *msgFile ;
GPart *gpart ;
Graph *graph ;
int ierr, msglvl, nvtx, rc, seed ;
IV *compidsIV ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile inIVfileName "
"\n seed alpha outIVfileName"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n inIVfile -- input file, must be *.ivf or *.ivb"
"\n seed -- random number seed"
"\n alpha -- partition cost parameter"
"\n outIVfile -- output file, must be *.ivf or *.ivb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
msgFileName = argv[2] ;
if ( strcmp(msgFileName, "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(msgFileName, "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], msgFileName) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
inIVfileName = argv[4] ;
seed = atoi(argv[5]) ;
alpha = atof(argv[6]) ;
outIVfileName = argv[7] ;
fprintf(msgFile,
"\n %s : "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n inIVfile -- %s"
"\n seed -- %d"
"\n alpha -- %f"
"\n outIVfile -- %s"
"\n", argv[0], msglvl, msgFileName, inGraphFileName,
inIVfileName, seed, alpha, outIVfileName) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
graph = Graph_new() ;
Graph_setDefaultFields(graph) ;
if ( (rc = Graph_readFromFile(graph, inGraphFileName)) != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
nvtx = graph->nvtx ;
if ( msglvl < 4 ) {
Graph_writeStats(graph, msgFile) ;
fflush(msgFile) ;
} else {
Graph_writeForHumanEye(graph, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------
read in the IV object
---------------------
*/
if ( strcmp(inIVfileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
compidsIV = IV_new() ;
IV_setDefaultFields(compidsIV) ;
if ( (rc = IV_readFromFile(compidsIV, inIVfileName)) != 1 ) {
fprintf(msgFile, "\n return value %d from IV_readFromFile(%p,%s)",
rc, compidsIV, inIVfileName) ;
exit(-1) ;
}
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in compidsIV from file %s",
t2 - t1, inIVfileName) ;
if ( msglvl < 4 ) {
IV_writeStats(compidsIV, msgFile) ;
fflush(msgFile) ;
} else {
IV_writeForHumanEye(compidsIV, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------
create the GPart object
-----------------------
*/
MARKTIME(t1) ;
gpart = GPart_new() ;
GPart_init(gpart, graph) ;
IV_copy(&gpart->compidsIV, compidsIV) ;
GPart_setMessageInfo(gpart, msglvl, msgFile) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : GPart initialized", t2 - t1) ;
/*
--------------------------------
find an initial bisector via BKL
--------------------------------
*/
MARKTIME(t1) ;
GPart_TwoSetViaBKL(gpart, alpha, seed, cpus) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : generate bisector",
t2 - t1) ;
fprintf(msgFile, "\n initial component weights :") ;
IVfp80(msgFile, 1+gpart->ncomp, IV_entries(&gpart->cweightsIV),
30, &ierr) ;
fflush(msgFile) ;
/*
-------------------------------------------
check that we have a valid vertex separator
-------------------------------------------
*/
if ( 1 != GPart_validVtxSep(gpart) ) {
fprintf(msgFile, "\n\n WHOA : separator is not valid"
"\n\n WHOA : separator is not valid\n\n") ;
fflush(msgFile) ;
}
/*
------------------------------------------------
optionally write the compids IV object to a file
------------------------------------------------
*/
if ( strcmp(outIVfileName, "none") != 0 ) {
IV_writeToFile(&gpart->compidsIV, outIVfileName) ;
}
/*
------------------------
free the data structures
------------------------
*/
GPart_free(gpart) ;
Graph_free(graph) ;
IV_free(compidsIV) ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
GPart/doc/ 0042755 0002055 0007177 00000000000 06542767400 0013672 5 ustar 00cleve compmath 0000040 0000006 GPart/doc/dataStructure.tex 0100644 0002055 0007177 00000011315 06534106121 0017226 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structures}
\label{section:GPart:dataStructure}
\par
The {\tt GPart} structure has a pointer to a {\tt Graph} object
and other fields that contain information about the partition
of the graph.
\par
The following fields are always active.
\begin{itemize}
\item
{\tt Graph *graph} : pointer to the {\tt Graph} object
\item
{\tt int nvtx} : number of internal vertices of the graph
\item
{\tt int nvbnd} : number of boundary vertices of the graph
\item
{\tt int ncomp} : number of components in the graph
\item
{\tt IV compidsIV} : an {\tt IV} object that holds the component
ids of the internal vertices --- {\tt compids[v] == 0}
means that the vertex is in the separator or multisector.
\item
{\tt IV cweightsIV} : an {\tt IV} object that holds the component
weights --- {\tt cweights[icomp]} stores the weight
of component {\tt icomp}, {\tt cweights[0]} is the separator
or multisector weight.
\item
{\tt int msglvl} : message level parameter.
When {\tt msglvl = 0}, no output is produced.
When {\tt msglvl = 1}, only ``scalar'' output is provided,
no vectors are printed or any print statements in a loop.
When {\tt msglvl > 1}, beware, there can be a fair amount of output.
\item
{\tt FILE *msgFile}
: message file pointer, default value is {\tt stdout}.
\end{itemize}
The following fields are used when building a domain/separator tree
during the recursive dissection process.
\begin{itemize}
\item {\tt int id} : id of the partition object
\item {\tt GPart *par} : pointer to a parent {\tt GPart} object
\item {\tt GPart *fch} : pointer to a first child {\tt GPart} object
\item {\tt GPart *sib} : pointer to a sibling {\tt GPart} object
\item {\tt IV vtxMapIV} : an {\tt IV} object of size
{\tt nvtx + nvbnd}, contains a map from the vertices of the graph
to either the vertices of its parent or to the vertices
of the root graph
\end{itemize}
\par
The {\tt DDsepInfo} {\it helper}-object is used during the {\tt DDSEP}
recursive bisection process.
It contains input parameters for the different stages of the {\tt
DDSEP} algorithm, and collects statistics about the CPU time spent
in each stage.
\par
\begin{itemize}
\item These parameters are used to generate the domain decomposition.
\begin{itemize}
\item {\tt int minweight}: minimum target weight for a domain
\item {\tt int maxweight}: maximum target weight for a domain
\item {\tt double freeze}: multiplier used to freeze vertices of high
degree into the multisector. If the degree of {\tt v} is more
than {\tt freeze} times the median degree, {\tt v} is placed
into the multisector.
\item {\tt int seed}: random number seed
\item {\tt int DDoption}: If {\tt 1}, a new domain decomposition is
constructed for each subgraph. If {\tt 2}, a domain
decomposition is constructed for the original graph,
and its projection onto a subgraph is used to define the
domain decomposition on the subgraph.
\end{itemize}
\item These parameters are used to find the initial and final bisectors.
\begin{itemize}
\item {\tt double alpha}: cost function parameter
\item {\tt int seed}: random number seed
\item {\tt int nlayer}: number of layers to use to form a wide
separator $Y$ from a 2-set partition $[S,B,W]$.
If {\tt nlayer = 1} or {\tt 2},
$Y = S \cup (Adj(S) \cap B)$
or $Y = S \cup (Adj(S) \cap W)$.
When {\tt nlayer = 1} the network is forced to be bipartite.
If {\tt nlayer = 3}, $Y_3 = S \cup Adj(S)$,
and for {\tt nlayer = 2k+1},
$Y_{2k+1} = Y_{2k-1} \cup Adj(Y_{2k-1})$.
\end{itemize}
\item These parameters accumulate CPU times.
\begin{itemize}
\item {\tt double cpuDD}: time to construct the domain decompositions
\item {\tt double cpuMap}: time to construct the maps from vertices
to domains and segments
\item {\tt double cpuBPG}: time to construct the domain/segment
bipartite graphs
\item {\tt double cpuBKL}: time to find the initial separators via the
Block Kernighan-Lin algorithm on the domain/segment graphs
\item {\tt double cpuSmooth}: time to smooth the bisectors
\item {\tt double cpuSplit}: time to split the subgraphs
\item {\tt double cpuTotal}: total cpu time
\end{itemize}
\item Miscellaneous parameters.
\begin{itemize}
\item {\tt int maxcompweight}:
an attempt is made to split any subgraph
that has weight greater than {\tt maxcompweight}.
\item {\tt int ntreeobj}: number of tree objects in the tree, used
to set {\tt gpart->id} and used to initialize the {\tt DSTree}
object.
\item {\tt int msglvl} : message level
\item {\tt FILE *msgFile} : message file pointer
\end{itemize}
\end{itemize}
GPart/doc/intro.tex 0100644 0002055 0007177 00000005741 06650230074 0015541 0 ustar 00cleve compmath 0000040 0000006 \chapter{{\tt GPart}: Graph Partitioning Object}
\label{chapter:GPart:intro}
\par
The {\tt GPart} object is used to create a partition of a graph.
We use an explicit vertex separator to split a graph (or a
subgraph) into the separator and two or more connected components.
This process proceeds recursively until the subgraphs are too small
to split (given by some user-supplied parameter).
\par
At present, there is one path for splitting a graph (or a subgraph).
\begin{itemize}
\item
Find a {\it domain decomposition} of the graph.
The graph's vertices $V$ are partitioned into {\it domains},
$\Omega_1, \ldots, \Omega_m$, each a connected component,
and the interface vertices $\Phi$.
The boundary of a domain $\Omega_i$ (those vertices not in the domain
but adjacent to a vertex in the domain), written
$\mbox{adj}(\Omega_i)$, are a subset of $\Phi$, the interface
vertices.
We use the term {\it multisector} for $\Phi$, for it generalizes
the notion of bisector.
\par
We currently find the domain decomposition by growing domains from
random seed vertices.
Upper and lower bounds are placed on the weights of the domains.
\item
Given a domain decomposition of the graph $\langle \Phi, \Omega_1,
\ldots, \Omega_m \rangle$, we find a {\it 2-set partition}
$[S, B, W]$ of the vertices, where $S \subseteq \Phi$,
$\mbox{Adj}(B) \subseteq S$ and $\mbox{Adj}(W) \subseteq S$.
Note, it may be the case that $B$ and/or $W$ are not connected
components.
\par
We currently find a 2-set partition by forming a {\it
domain-segment} bipartite graph where the segments partition the
interface nodes $\Phi$.
We use a block Kernighan-Lin method to find an edge separator of
this domain-segment graph.
Since the ``edges'' are segments, an edge separator of the
domain-segment graph is truly a vertex separator of the original
graph.
\item
Given a 2-set decomposition $[S,B,W]$ of the graph, we improve
the partition by {\it smoothing} $S$.
The goal is to decrease the size of $S$, or improve the balance
of the two sets (minimize $\left| |B| - |W| \right |$, or both.
Our present approach is to generate a {\it wide separator} $Y$
where $S \subseteq Y$ and try to find a separator
$\widehat S \subseteq Y$ that induces a better partition
$[{\widehat S}, {\widehat B}, {\widehat W}]$.
\par
To do this, we form a network and solve a max flow problem.
The nodes in $B \setminus Y$ are condensed into the {\it source}
while the nodes in $W \setminus Y$ are condensed into the {\it sink}.
The rest of the network is formed using the structure of the
subgraph induced by $Y$.
Given a {\it min-cut} of the network we can identify a separator
${\widehat S} \subseteq Y$ that has minimal weight.
We examine two (possibly) different min-cuts and evaluate the
partitions induced via their minimal weight separators, and accept
a better partition if present.
\end{itemize}
This process we call {\tt DDSEP}, which is short for {\it {\tt D}omain
{\tt D}ecomposition {\tt SEP}arator},
explained in more detail in
\cite{ash97-DDSEP} and
\cite{ash98-maxflow}.
\par
GPart/doc/main.tex 0100644 0002055 0007177 00000001100 06650656230 0015321 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt GPart} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt GPart} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
GPart/doc/main.ind 0100644 0002055 0007177 00000002014 06540033655 0015276 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt DDsepInfo\_clearData()}, 9
\item {\tt DDsepInfo\_free()}, 10
\item {\tt DDsepInfo\_new()}, 9
\item {\tt DDsepInfo\_setDefaultFields()}, 9
\indexspace
\item {\tt GPart\_bndWeightsIV()}, 6
\item {\tt GPart\_clearData()}, 4
\item {\tt GPart\_DDviaFishnet()}, 6
\item {\tt GPart\_DDviaProjection()}, 6
\item {\tt GPart\_domSegMap()}, 7
\item {\tt GPart\_free()}, 4
\item {\tt GPart\_identifyWideSep()}, 7
\item {\tt GPart\_init()}, 4
\item {\tt GPart\_makeYCmap()}, 7
\item {\tt GPart\_new()}, 4
\item {\tt GPart\_RBviaDDsep()}, 9
\item {\tt GPart\_setCweights()}, 5
\item {\tt GPart\_setDefaultFields()}, 4
\item {\tt GPart\_setMessageInfo()}, 4
\item {\tt GPart\_sizeOf()}, 5
\item {\tt GPart\_smoothBisector()}, 8
\item {\tt GPart\_smoothBy2layers()}, 8
\item {\tt GPart\_smoothYSep()}, 8
\item {\tt GPart\_split()}, 5
\item {\tt GPart\_TwoSetViaBKL()}, 6
\item {\tt GPart\_validVtxSep()}, 5
\item {\tt GPart\_vtxIsAdjToOneDomain()}, 5
\end{theindex}
GPart/doc/main.log 0100644 0002055 0007177 00000007524 06540033667 0015323 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 11 JUN 1998 13:01
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
)
\@indexfile=\write3
Writing index file main.idx
(main.aux) (intro.tex
Chapter 1.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 1.
LaTeX Warning: Citation `ash95-DDSEP' on page 1 undefined on input line 67.
LaTeX Warning: Citation `ash96-maxflow' on page 1 undefined on input line 68.
[1
]) (dataStructure.tex
Overfull \hbox (10.03406pt too wide) in paragraph at lines 20--24
[] []\elvtt IV compidsIV \elvrm : an \elvtt IV \elvrm ob-ject that holds the co
m-po-nent ids of the in-ter-nal ver-tices --- \elvtt compids[v]
\hbox(7.60416+2.43333)x442.37993, glue set - 1.0
.\hbox(0.0+0.0)x0.0
.\glue 0.0
.\hbox(4.86667+0.0)x0.0
..\glue 0.0
..\glue -21.90005
..\glue -5.475
..\hbox(4.86667+0.0)x21.90005, glue set 21.90005fil
...\glue 0.0 plus 1.0fil minus 1.0fil
...\hbox(4.86667+0.0)x0.0, glue set - 5.475fil []
..\glue 5.475
.\penalty 0
.\elvtt I
.etc.
[2]) (proto.tex [3] [4] [5]
LaTeX Warning: Citation `ash95-DDSEP' on page 6 undefined on input line 247.
[6] [7] [8] [9]) (drivers.tex
LaTeX Warning: Citation `ash95-DDSEP' on page 10 undefined on input line 16.
Overfull \hbox (19.63927pt too wide) in paragraph at lines 30--35
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
LaTeX Warning: Citation `ash95-DDSEP' on page 10 undefined on input line 59.
[10]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 76--81
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
Overfull \hbox (19.63927pt too wide) in paragraph at lines 119--124
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
[11]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 169--174
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
Overfull \hbox (19.63927pt too wide) in paragraph at lines 230--235
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
[12]) (main.ind [13] [14
]) (main.aux) )
Here is how much of TeX's memory you used:
215 strings out of 11977
2346 string characters out of 87269
34975 words of memory out of 262141
2149 multiletter control sequences out of 9500
19780 words of font info for 75 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
13i,12n,17p,182b,260s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (14 pages, 48468 bytes).
80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/libGPart/doc/main.aux 0100644 0002055 0007177 00000004473 06540033667 0015337 0 ustar 00cleve compmath 0000040 0000006 \relax
\citation{ash95-DDSEP}
\citation{ash96-maxflow}
\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}{\string\ptt\space GPart}: Graph Partitioning Object}{1}}
\@writefile{lof}{\string\addvspace\space {10\p@ }}
\@writefile{lot}{\string\addvspace\space {10\p@ }}
\newlabel{chapter:GPart:intro}{{1}{1}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Data Structures}{2}}
\newlabel{section:GPart:dataStructure}{{1.1}{2}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Prototypes and descriptions of {\string\ptt\space GPart} methods}{3}}
\newlabel{section:GPart:proto}{{1.2}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.1}Basic methods}{4}}
\newlabel{subsection:GPart:proto:basics}{{1.2.1}{4}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Initializer methods}{4}}
\newlabel{subsection:GPart:proto:initializers}{{1.2.2}{4}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.3}Utility methods}{5}}
\newlabel{subsection:GPart:proto:utilities}{{1.2.3}{5}}
\citation{ash95-DDSEP}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.4}Domain decomposition methods}{6}}
\newlabel{subsection:GPart:proto:domain-decomposition}{{1.2.4}{6}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.5}Methods to generate a 2-set partition}{6}}
\newlabel{subsection:GPart:proto:2-set}{{1.2.5}{6}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.6}Methods to improve a 2-set partition}{7}}
\newlabel{subsection:GPart:proto:improve}{{1.2.6}{7}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.7}Recursive Bisection method}{9}}
\newlabel{subsection:GPart:proto:RB}{{1.2.7}{9}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.8}{\string\ptt\space DDsepInfo} methods}{9}}
\newlabel{subsection:GPart:proto:DDsepInfo}{{1.2.8}{9}}
\citation{ash95-DDSEP}
\citation{ash95-DDSEP}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}Driver programs for the {\string\ptt\space GPart} object}{10}}
\newlabel{section:GPart:drivers}{{1.3}{10}}
GPart/doc/drivers.tex 0100644 0002055 0007177 00000025712 06650230152 0016061 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt GPart} object}
\label{section:GPart:drivers}
\par
This section contains brief descriptions of four driver programs.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testDDviaFishnet msglvl msgFile inGraphFile freeze minweight maxweight
seed outIVfile
\end{verbatim}
This driver program constructs a domain decomposition via the {\it
fishnet} algorithm \cite{ash97-DDSEP}.
It reads in a {\tt Graph} object from a file, finds the domain
decomposition using the four input parameters, then optionally
writes out the map from vertices to components to a file.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
\item
The {\tt msgFile} parameter determines the output file --- if {\tt
msgFile} is {\tt stdout}, then the output file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt freeze} parameter is used to place nodes of high degree
into the multisector.
If the external degree of a vertex is {\tt freeze} times the
average degree, then it is placed in the multisector.
\item
The {\it target} minimum weight for a domain is {\tt minweight}.
\item
The {\it target} maximum weight for a domain is {\tt maxweight}.
\item
The {\tt seed} parameter is a random number seed.
\item
The {\tt outIVfile} parameter is the output file for the {\tt IV}
object that contains the map from vertices to components.
If {\tt outIVfile} is {\tt "none"}, then there is no output,
otherwise {\tt outIVfile}
must be of the form {\tt *.ivf} or {\tt *.ivb}.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testTwoSetViaBKL msglvl msgFile inGraphFile inIVfile
seed alpha outIVfile
\end{verbatim}
This driver program constructs a two-set partition via the
Block Kernighan-Lin algorithm \cite{ash97-DDSEP}.
It reads in a {\tt Graph} object and an {\tt IV} object that holds
the map from vertices to components (e.g., the output from the
driver program {\tt testDDviaFishet}) from two files,
constructs the domain-segment graph and finds an initial
separator, then optionally
writes out the new map from vertices to components to a file.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
\item
The {\tt msgFile} parameter determines the output file --- if {\tt
msgFile} is {\tt stdout}, then the output file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt inIVfile} parameter is the input file for the {\tt IV}
object that contains the map from vertices to domains and multisector.
It {\tt inIVfile} must be of the form {\tt *.ivf} or {\tt *.ivb}.
\item
The {\tt seed} parameter is a random number seed.
\item
The {\tt alpha} parameter controls the partition evaluation function.
\item
The {\tt outIVfile} parameter is the output file for the {\tt IV}
object that contains the map from vertices to separator and the
two components.
If {\tt outIVfile} is {\tt "none"}, then there is no output,
otherwise {\tt outIVfile}
must be of the form {\tt *.ivf} or {\tt *.ivb}.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testSmoothBisector msglvl msgFile inGraphFile inIVfile
option alpha outIVfile
\end{verbatim}
This driver program smooths a bisector of a graph by solving a
sequence of max-flow network problems.
It reads in a {\tt Graph} object and an {\tt IV} object that holds
the map from vertices to components (e.g., the output from the
driver program {\tt testTwoSetViaBKL}) from two files,
smooths the separator and
then optionally writes out the new component ids map to a file.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
\item
The {\tt msgFile} parameter determines the output file --- if {\tt
msgFile} is {\tt stdout}, then the output file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt inIVfile} parameter is the input file for the {\tt IV}
object that contains the map from vertices to domains and multisector.
It {\tt inIVfile} must be of the form {\tt *.ivf} or {\tt *.ivb}.
\item
The {\tt option} parameter specifies the type of network
optimization problem that will be solved.
\begin{itemize}
\item
{\tt option = 1} --- each network has two layers and is bipartite.
\item
{\tt option = 2}
--- each network has two layers but need not be bipartite.
\item
{\tt option = 2} --- each network has {\tt option/2} layers
on each side of the separator.
\end{itemize}
\item
The {\tt alpha} parameter controls the partition evaluation function.
\item
The {\tt outIVfile} parameter is the output file for the {\tt IV}
object that contains the map from vertices to separator and the
two components.
If {\tt outIVfile} is {\tt "none"}, then there is no output,
otherwise {\tt outIVfile}
must be of the form {\tt *.ivf} or {\tt *.ivb}.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testRBviaDDsep msglvl msgFile inGraphFile seed minweight maxweight
freeze alpha maxdomweight DDoption nlayer
testRBviaDDsep2 msglvl msgFile inGraphFile nruns seed minweight maxweight
freeze alpha maxdomweight DDoption nlayer
\end{verbatim}
These driver programs construct a multisector via recursive
bisection and orders the graph using nested dissection and
multisection using the multisector.
{\tt testRBviaDDsep} executes only one run while
{\tt testRBviaDDsep2} executes {\tt nruns} runs with random
permutations of the graph.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
\item
The {\tt msgFile} parameter determines the output file --- if {\tt
msgFile} is {\tt stdout}, then the output file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt nruns} parameter is the number of runs made with the
graph randomly permuted.
\item
The {\tt seed} parameter is a random number seed.
\item
The {\it target} minimum weight for a domain is {\tt minweight}.
\item
The {\it target} maximum weight for a domain is {\tt maxweight}.
\item
The {\tt freeze} parameter is used to place nodes of high degree
into the multisector.
If the external degree of a vertex is {\tt freeze} times the
average degree, then it is placed in the multisector.
\item
The {\tt alpha} parameter controls the partition evaluation function.
\item
The {\tt maxdomweight} parameter controls the recursive bisection
--- no subgraph with weight less than {\tt maxdomweight} is
further split.
\item
The {\tt DDoption} parameter controls the initial domain/segment
partition on each subgraph.
When {\tt DDDoption = 1} we use the fishnet algorithm for each
subgraph.
When {\tt DDDoption = 1} we use the fishnet algorithm once for the
entire graph and this is then projected down onto each subgraph.
\item
The {\tt nlayer} parameter governs the smoothing process by specifying
the type of network optimization problem that will be solved.
\begin{itemize}
\item
{\tt nlayer = 1} --- each network has two layers and is bipartite.
\item
{\tt nlayer = 2}
--- each network has two layers but need not be bipartite.
\item
{\tt nlayer > 2} --- each network has {\tt option/2} layers
on each side of the separator.
\end{itemize}
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
mkDSTree msglvl msgFile inGraphFile seed minweight maxweight
freeze alpha maxdomweight DDoption nlayer outDSTreeFile
\end{verbatim}
This driver program constructs a domain/separator tree using
recursive bisection.
The {\tt DSTree} object is optionally written to a file.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output.
\item
The {\tt msgFile} parameter determines the output file --- if {\tt
msgFile} is {\tt stdout}, then the output file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt seed} parameter is a random number seed.
\item
The {\it target} minimum weight for a domain is {\tt minweight}.
\item
The {\it target} maximum weight for a domain is {\tt maxweight}.
\item
The {\tt freeze} parameter is used to place nodes of high degree
into the multisector.
If the external degree of a vertex is {\tt freeze} times the
average degree, then it is placed in the multisector.
\item
The {\tt alpha} parameter controls the partition evaluation function.
\item
The {\tt maxdomweight} parameter controls the recursive bisection
--- no subgraph with weight less than {\tt maxdomweight} is
further split.
\item
The {\tt DDoption} parameter controls the initial domain/segment
partition on each subgraph.
When {\tt DDDoption = 1} we use the fishnet algorithm for each
subgraph.
When {\tt DDDoption = 1} we use the fishnet algorithm once for the
entire graph and this is then projected down onto each subgraph.
\item
The {\tt nlayer} parameter governs the smoothing process by specifying
the type of network optimization problem that will be solved.
\begin{itemize}
\item
{\tt nlayer = 1} --- each network has two layers and is bipartite.
\item
{\tt nlayer = 2}
--- each network has two layers but need not be bipartite.
\item
{\tt nlayer > 2} --- each network has {\tt option/2} layers
on each side of the separator.
\end{itemize}
\item
The {\tt outDSTreeFile} parameter is the output file
for the {\tt DSTree} object.
It must be of the form {\tt *.dstreef} or {\tt *.dstreeb}.
If {\tt outDSTreeFile} is not {\tt "none"},
the {\tt DSTree} object is written to the file via the
{\tt DSTree\_writeToFile()} method.
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
t {\tt inIVfile} must be of the form {\tt *.ivf} or {\GPart/doc/proto.tex 0100644 0002055 0007177 00000064202 06650230155 0015546 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt GPart} methods}
\label{section:GPart:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt GPart} object.
% There are four families:
% basics,
% IO,
% initializers
% and
% utilities.
There are no IO methods.
\par
\subsection{Basic methods}
\label{subsection:GPart:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
GPart * GPart_new ( void ) ;
\end{verbatim}
\index{GPart_new@{\tt GPart\_new()}}
This method simply allocates storage for the {\tt GPart} structure
and then sets the default fields by a call to
{\tt GPart\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void GPart_setDefaultFields ( GPart *gpart ) ;
\end{verbatim}
\index{GPart_setDefaultFields@{\tt GPart\_setDefaultFields()}}
This method sets the structure's fields to default values:
{\tt id = -1}, {\tt nvtx = nvbnd = ncomp = 0},
{\tt g} = {\tt par} = {\tt fch} = {\tt sib} = {\tt NULL},
and the default fields for {\tt compidsIV}, {\tt cweightsIV}
and {\tt vtxMapIV} are set via calls to {\tt
IV\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt gpart} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void GPart_clearData ( GPart *gpart ) ;
\end{verbatim}
\index{GPart_clearData@{\tt GPart\_clearData()}}
The {\tt IV\_clearData()} method is called for the
{\tt compidsIV}, {\tt cweightsIV} and
{\tt vtxMapIV} objects.
The structure's fields are then set
with a call to {\tt GPart\_setDefaultFields()}.
Note, storage for the {\tt Graph} object {\tt gpart->graph}
is {\bf not} free'd.
The {\tt GPart} object does not own its {\tt Graph} object,
it only uses it.
\par \noindent {\it Error checking:}
If {\tt gpart} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void GPart_free ( GPart *gpart ) ;
\end{verbatim}
\index{GPart_free@{\tt GPart\_free()}}
This method releases any storage by a call to
{\tt GPart\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt gpart} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initializer methods}
\label{subsection:GPart:proto:initializers}
\par
There are two initializer methods.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void GPart_init ( GPart *gpart, Graph *graph ) ;
\end{verbatim}
\index{GPart_init@{\tt GPart\_init()}}
This method initializes the {\tt Gpart} object given a {\tt Graph}
object as input.
Any previous data is cleared with a call to
{\tt GPart\_clearData()}.
The {\tt graph}, {\tt nvtx}, {\tt nvbnd} fields are set.
The {\tt compidsIV} and {\tt cweightsIV} {\tt IV} objects are
initialized.
The remaining fields are not changed from their default values.
\par \noindent {\it Error checking:}
If {\tt gpart} or {\tt g} is {\tt NULL},
or if $\mbox{\tt g->nvtx} \le 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void GPart_setMessageInfo ( GPart *gpart, int msglvl, FILE *msgFile ) ;
\end{verbatim}
\index{GPart_setMessageInfo@{\tt GPart\_setMessageInfo()}}
This method sets the {\tt msglvl} and {\tt msgFile} fields.
\par \noindent {\it Error checking:}
If {\tt gpart} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:GPart:proto:utilities}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void GPart_setCweights ( GPart *gpart ) ;
\end{verbatim}
\index{GPart_setCweights@{\tt GPart\_setCweights()}}
This method sets the component weights vector {\tt cweightsIV}.
We assume that the {\tt compidsIV} vector has been set prior to
entering this method.
The weight of a component is not simply the sum of the weights of
the vertices with that component's id.
We accept the separator or multisector vertices (those {\tt v} with
{\tt compids[v] == 0}) but then find the connected components of
the remaining vertices, renumbering the {\tt compidsIV} vector
where necessary.
Thus, {\tt ncomp} and {\tt compidsIV} may be updated,
and {\tt cweightsIV} is set.
\par \noindent {\it Error checking:}
If {\tt gpart} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int GPart_sizeOf ( GPart *gpart ) ;
\end{verbatim}
\index{GPart_sizeOf@{\tt GPart\_sizeOf()}}
This method returns the number of bytes owned by the object.
This includes the structure itself, the {\tt compidsIV},
{\tt cweightsIV} and {\tt vtxMapIV} arrays (if present),
but {\tt not} the {\tt Graph} object.
\par \noindent {\it Error checking:}
If {\tt gpart} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int GPart_validVtxSep ( GPart *gpart ) ;
\end{verbatim}
\index{GPart_validVtxSep@{\tt GPart\_validVtxSep()}}
This method returns 1 if the partition defined by the {\tt
compidsIV} vector has a valid vertex separator and zero otherwise.
When there is a valid vertex separator, there are no
adjacent vertices not in the multisector that belong to different
components (as defined by the {\tt compidsIV} vector).
\par \noindent {\it Error checking:}
If {\tt gpart} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void GPart_split ( GPart *gpart ) ;
\end{verbatim}
\index{GPart_split@{\tt GPart\_split()}}
This method is used to split a subgraph during the nested
dissection process that builds a tree of {\tt GPart} objects.
We first generate a valid partition via the
{\tt GPart\_setCweights()} method,
and
then split the graph into its component subgraphs.
Each subgraph is
assigned to a new child {\tt GPart} object.
The {\tt Graph} object for each subgraph is formed from the parent
graph using the {\tt Graph\_subGraph()} method.
This means that the storage for the adjacency lists of the subgraph
is taken from the storage for the parent graph --- the lists are
mapped into the local ordering via the {\tt vtxMap} vector.
After {\tt GPart\_split(gpart)} is called, the adjacency lists for the
vertices in {\tt gpart->g} are no longer valid.
\par \noindent {\it Error checking:}
If {\tt gpart} or {\tt g} is {\tt NULL},
or if {\tt gpart->fch} is not {\tt NULL}
(meaning that the subgraph has already been split),
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int GPart_vtxIsAdjToOneDomain ( GPart *gpart, int v, int *pdomid ) ;
\end{verbatim}
\index{GPart_vtxIsAdjToOneDomain@{\tt GPart\_vtxIsAdjToOneDomain()}}
This method determines whether the vertex {\tt v} is
adjacent to just one domain or not.
We use this method to make a separator or multisector minimal.
If the vertex is adjacent to only one domain, the return value is
{\tt 1} and {\tt *pdomid} is set to the domain's id.
If a vertex is adjacent to zero or two or more domains, the return
value is zero.
If a vertex belongs to a domain, it is considered adjacent to that
domain.
\par \noindent {\it Error checking:}
If {\tt gpart}, {\tt g} or {\tt domid} is {\tt NULL},
or if {\tt v} is out of range
(i.e., ${\tt v} < 0$ or ${\tt nvtx} \le {\tt v}$),
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * GPart_bndWeightsIV ( GPart *gpart ) ;
\end{verbatim}
\index{GPart_bndWeightsIV@{\tt GPart\_bndWeightsIV()}}
This method returns an {\tt IV} object that contains the weights of
the vertices on the boundaries of the components.
\par \noindent {\it Error checking:}
If {\tt gpart} or {\tt g} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Domain decomposition methods}
\label{subsection:GPart:proto:domain-decomposition}
\par
There are presently two methods that create a domain decomposition
of a graph or a subgraph.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void GPart_DDviaFishnet ( GPart *gpart, double frac, int minweight,
int maxweight, int seed ) ;
\end{verbatim}
\index{GPart_DDviaFishnet@{\tt GPart\_DDviaFishnet()}}
This method generates a domain decomposition of a graph using the
{\it fishnet} algorithm (see \cite{ash97-DDSEP} for details).
On return, the {\tt compidsIV} vector is filled with component ids
and {\tt ncomp} is set with the number of domains.
The {\tt frac} parameter governs the exclusion of nodes of high
degree from the domain sets.
We have found this to be useful for some graphs.
Nodes of very high degree (relative to the average or mean degree)
can severely distort a domain decomposition.
We have found that setting {\tt frac} to four works well in
practice.
The {\tt minweight} and {\tt maxweight} parameters are the minimum
target weight and maximum target weight for a domain.
The {\tt seed} parameter is used to insert a degree of randomness
into the algorithm.
This allows us to make several runs and take the best partition.
\par \noindent {\it Error checking:}
If {\tt gpart} or {\tt g} is {\tt NULL},
or if ${\tt freeze} \le 0.0$,
or if ${\tt minweight} < 0$,
or if ${\tt maxweight} < 0$,
or if ${\tt minweight} \ge {\tt maxweight}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void GPart_DDviaProjection ( GPart *gpart, IV *DDmapIV ) ;
\end{verbatim}
\index{GPart_DDviaProjection@{\tt GPart\_DDviaProjection()}}
This method generates a domain decomposition for a subgraph by
projecting an existing domain decoposition for the original graph
onto the subgraph.
Using this method (as opposed to generating a domain decomposition
for each subgraph) can typically save 15\% of the overall time
to find the graph decomposition, though the resulting partition is
usually not as good.
\par \noindent {\it Error checking:}
If {\tt gpart} or {\tt DDmapIV} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Methods to generate a 2-set partition}
\label{subsection:GPart:proto:2-set}
\par
These two methods are used to generate a 2-set partition
$[S,B,W]$ from a domain decomposition.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double GPart_TwoSetViaBKL ( GPart *gpart, double alpha, int seed,
double cpus[] ) ;
\end{verbatim}
\index{GPart_TwoSetViaBKL@{\tt GPart\_TwoSetViaBKL()}}
This method takes a domain decomposition $\{\Phi, \Omega_1,
\ldots, \Omega_m\}$ defined by the {\tt compidsIV} vector
and generates a two set partition $[S,B,W]$.
We first compute the map from vertices to domains and segments
(the segments partition the interface nodes $\Phi$).
We then construct the bipartite graph that represents the
connectivity of the domains and segments.
Each segment is an ``edge'' that connects two ``adjacent'' domains.
This allows us to use a variant of the Kernighan-Lin algorithm to
find an ``edge'' separator formed of segments,
which is really a vertex separator, a subset of $\Phi$.
The {\tt alpha} parameter is used in the cost function evaluation
for the partition,
$\displaystyle
\mbox{cost}([S,B,W]) = |S|\left(1 + \alpha
\frac{\max\{|B|,|W|\}}
{\min\{|B|,|W|\}}
\right)
$.
The {\tt seed} parameter is used to randomize the algorithm.
One can make several runs with different seeds and chose the best
partition.
The {\tt cpus[]} array is used to store execution times for
segments of the algorithm:
{\tt cpus[0]} stores the time to compute the domain/segment map;
{\tt cpus[2]} stores the time to create the domain/segment bipartite
graph;
{\tt cpus[3]} stores the time to find the bisector using the block
Kernighan-Lin algorithm.
\par \noindent {\it Error checking:}
If {\tt gpart} or {\tt cpus} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * GPart_domSegMap ( GPart *gpart, int *pndom, int *pnseg ) ;
\end{verbatim}
\index{GPart_domSegMap@{\tt GPart\_domSegMap()}}
This method takes a domain decomposition as defined by the {\tt
compidsIV} vector and generates the map from the vertices to the
domains and segments that are used in the Block Kernighan-Lin
procedure to find an initial separator.
The map is returned in an {\tt IV} object, and the numbers of
domains and segments are set in the {\tt pndom} and {\tt pnseg}
addresses.
This method is called by {\tt GPart\_TwoSetViaBKL}.
\par \noindent {\it Error checking:}
If {\tt gpart}, {\tt g}, {\tt pndom} or {\tt pnseg} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Methods to improve a 2-set partition}
\label{subsection:GPart:proto:improve}
\par
These methods are used to improve a 2-set partition $[S,B,W]$.
They hinge on finding a {\it wide separator} $Y$ and constructing a
better separator ${\widehat S} \subseteq Y$.
The {\tt alpha} parameter is used in the cost function
$\displaystyle
\mbox{cost}([S,B,W]) = |S|\left(1 + \alpha
\frac{\max\{|B|,|W|\}}
{\min\{|B|,|W|\}}
\right)
$.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * GPart_identifyWideSep ( GPart *gpart, int nlayer1, int nlayer2 ) ;
\end{verbatim}
\index{GPart_identifyWideSep@{\tt GPart\_identifyWideSep()}}
This method takes a 2-set partition $[S,B,W]$ and identifies a {\it wide
separator} $Y$ that contains $S$.
The portions of $B$ and $W$ that are included in $Y$ are specified
using the {\tt nlayer1} and {\tt nlayer2} parameters.
If both are zero, then $Y$ is simply $S$.
If {\tt nlayer1 > 0}, then $Y$ contains all vertices
in the first component whose distance is {\tt nlayer1} or less from
$S$, and similarly for {\tt nlayer2 > 0}.
The vertices in $Y$ are placed in an {\tt IV} object which is then
returned.
\par \noindent {\it Error checking:}
If {\tt gpart} or {\tt g} is {\tt NULL},
or if ${\tt nlevel1} < 0$ or ${\tt nlevel2} < 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * GPart_makeYCmap ( GPart *gpart, IV *YVmapIV ) ;
\end{verbatim}
\index{GPart_makeYCmap@{\tt GPart\_makeYCmap()}}
This method contructs and returns an {\tt IV} object that is the
blueprint used to form the network.
The wide separator $Y$ can be partitioned into four disjoint sets
(though some may be empty):
\begin{eqnarray*}
Y_0 & = & \{y \in Y\ |\
y \notin Adj(B \setminus Y)
% y \cap Adj(B \setminus Y) = \emptyset
\mbox{\ and\ }
y \notin Adj(W \setminus Y)
% y \cap Adj(W \setminus Y) = \emptyset
\} \\
Y_1 & = & \{y \in Y\ |\
y \in Adj(B \setminus Y)
% y \cap Adj(B \setminus Y) \ne \emptyset
\mbox{\ and\ }
y \notin Adj(W \setminus Y)
% y \cap Adj(W \setminus Y) = \emptyset
\} \\
Y_2 & = & \{y \in Y\ |\
y \notin Adj(B \setminus Y)
% y \cap Adj(B \setminus Y) = \emptyset
\mbox{\ and\ }
y \in Adj(W \setminus Y)
% y \cap Adj(W \setminus Y) \ne \emptyset
\} \\
Y_3 & = & \{y \in Y\ |\
y \in Adj(B \setminus Y)
% y \cap Adj(B \setminus Y) \ne \emptyset
\mbox{\ and\ }
y \in Adj(W \setminus Y)
% y \cap Adj(W \setminus Y) \ne \emptyset
\}
\end{eqnarray*}
The {\tt YVmapIV} object contains the list of vertices in the wide
separator $Y$.
The {\tt IV} object that is returned, (called {\tt YCmapIV} in
the calling method) contains the subscripts of the $Y_0$, $Y_1$,
$Y_2$ or $Y_3$ sets that contains each vertex.
\par \noindent {\it Error checking:}
If {\tt gpart}, {\tt g} or {\tt YVmapIV} is {\tt NULL},
or if ${\tt nvtx} \le 0$,
or if {\tt YVmapIV} is empty,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void * GPart_smoothBy2layers ( GPart *gpart, int bipartite, float alpha ) ;
\end{verbatim}
\index{GPart_smoothBy2layers@{\tt GPart\_smoothBy2layers()}}
This method forms the wide separator $Y$ from two layers of
vertices, either $Y_B = S \cup (Adj(S) \cap B)$
or $Y_W = S \cup (Adj(S) \cap W)$.
(If $|B| \ge |W|$, we first look at $Y_B$ and if no improvement can
be made we look at $Y_W$, and the reverse if $|W| > |B|$.)
The {\tt bipartite} parameter defines the type of network problem
we solve.
The network induced by the wide separator $Y$ need not be bipartite,
and will not be bipartite if $Y_0 \ne \emptyset$ or $Y_3 \ne \emptyset$,
($Y_0$ and $Y_3$ are defined immediately above).
The $Y_3$ set is not important, since it must be included in any
separator ${\widehat S} \subseteq Y$.
When $Y_0$ is not empty, it forms a layer {\it between} $Y_1$ and $Y_2$,
and so the network is not bipartite.
We can force the network to be bipartite
(set {\tt bipartite} to {\tt 1}) by moving all nodes in $Y_0$ to
the appropriate $Y_1$ or $Y_2$.
When the graph is unit-weight and the network is bipartite,
we can use the Dulmage-Mendelsohn decomposition to find one
or more separators of minimum weight.
In general, forcing a non-bipartite network to be bipartite results
in possibly a larger separator, so we do not recommend this option.
The capability is there to compare the Dulmage-Mendelsohn
decomposition smoothers with the more general (and robust) max
flow smoothers.
\par \noindent {\it Error checking:}
If {\tt gpart} is {\tt NULL},
or if ${\tt alpha} < 0.0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
float * GPart_smoothYSep ( GPart *gpart, IV *YVmapIV,
IV *YCmapIV, float alpha ) ;
\end{verbatim}
\index{GPart_smoothYSep@{\tt GPart\_smoothYSep()}}
This methods takes as input a 2-set partition $[S,B,W]$
(defined by {\tt gpart->compidsIV}), a wide separator $Y$
(defined by {\tt YVmapIV}) and a
$\langle Y_0, Y_1, Y_2, Y_3 \rangle$ partition of $Y$
(defined by {\tt YCmapIV}) and attempts to find a better partition.
A max flow problem is solved on a network induced by
$\langle Y_0, Y_1, Y_2, Y_3 \rangle$.
Two min-cuts and the partitions they induce are examined and the
better partition is accepted if better than $[S,B,W]$.
The parameter {\tt alpha} is used in the partition's cost function,
and the cost of the best partition is returned.
\par \noindent {\it Error checking:}
If {\tt gpart}, {\tt YVmapIV} or {\tt YCmapIV} is {\tt NULL},
or if ${\tt alpha} < 0.0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
float * GPart_smoothBisector ( GPart *gpart, int nlayer, float alpha ) ;
\end{verbatim}
\index{GPart_smoothBisector@{\tt GPart\_smoothBisector()}}
This method takes a two-set partition $[S,B,W]$ as defined by the
{\tt compidsIV} vector and improves it (if possible).
The methods returns the cost of
a (possibly) new two-set partition
$[{\widehat S}, {\widehat B}, {\widehat W}]$
defined by the {\tt compidsIV} vector.
The wide separator $Y$ that is constructed is {\it centered} around
$S$, i.e., $Y$ includes all nodes in $B$ and $W$ that are {\tt
nlayer} distance or less from $S$.
This method calls {\tt GPart\_smoothYSep()}.
\par \noindent {\it Error checking:}
If {\tt gpart} is {\tt NULL},
or if ${\tt nlevel} < 0$,
or if ${\tt alpha} < 0.0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Recursive Bisection method}
\label{subsection:GPart:proto:RB}
\par
There is presently one method to construct the domain/separator tree.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
DSTree * GPart_RBviaDDsep ( GPart *gpart, DDsepInfo *info ) ;
\end{verbatim}
\index{GPart_RBviaDDsep@{\tt GPart\_RBviaDDsep()}}
This method performs a recursive bisection of the graph using the
{\tt DDSEP} algorithm and returns a {\tt DSTree} object that represents
the domain/separator tree and the map from vertices to domains and
separators.
The {\tt DDsepInfo} structure contains all the parameters to the
different steps of the {\tt DDSEP} algorithm (the fishnet method to find
the domain decomposition, the Block Kernighan-Lin method to find an
initial separator, and solves a max flow problem to
improve the separator).
An attempt is made to split a subgraph if the weight of the
internal vertices of the subgraph exceeds {\tt info->maxcompweight}.
The cpu times for the different segments of the algorithm are
accumulated in fields of the {\tt DDsepInfo} object.
\par \noindent {\it Error checking:}
If {\tt gpart} or {\tt info} is {\tt NULL},
or if ${\tt nvtx} \le 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{{\tt DDsepInfo} methods}
\label{subsection:GPart:proto:DDsepInfo}
\par
The {\tt DDsepInfo} {\it helper}-object is used during the
{\tt DDSEP} recursive bisection process.
It stores the necessary input parameters for the different stages
of the {\tt DDSEP} algorithm and collects statistics about the
resulting partition.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
DDsepInfo * DDsepInfo_new ( void ) ;
\end{verbatim}
\index{DDepInfo_new@{\tt DDsepInfo\_new()}}
This method simply allocates storage for the {\tt DDsepInfo} structure
and then sets the default fields by a call to
{\tt DDsepInfo\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DDsepInfo_setDefaultFields ( DDsepInfo *info ) ;
\end{verbatim}
\index{DDepInfo_setDefaultFields@{\tt DDsepInfo\_setDefaultFields()}}
This method checks to see whether {\tt info} is {\tt NULL}.
If so, an error message is printed and the program exits.
Otherwise, the structure's fields are set to the following
default values.
\begin{verbatim}
info->seed = 1 ; info->cpuDD = 0.0 ;
info->minweight = 40 ; info->cpuMap = 0.0 ;
info->maxweight = 80 ; info->cpuBPG = 0.0 ;
info->frac = 4.0 ; info->cpuBKL = 0.0 ;
info->alpha = 1.0 ; info->cpuSmooth = 0.0 ;
info->maxcompweight = 500 ; info->cpuSplit = 0.0 ;
info->ntreeobj = 0 ; info->cpuTotal = 0.0 ;
info->DDoption = 1 ; info->msglvl = 0 ;
info->nlayer = 3 ; info->msgFile = stdout ;
\end{verbatim}
\par \noindent {\it Error checking:}
If {\tt info} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DDsepInfo_clearData ( DDsepInfo *info ) ;
\end{verbatim}
\index{DDepInfo_clearData@{\tt DDsepInfo\_clearData()}}
This method checks to see whether {\tt info} is {\tt NULL}.
{\tt DDsepInfo\_setDefaultFields()} is
called to set the default values.
\par \noindent {\it Error checking:}
If {\tt info} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DDsepInfo_free ( DDsepInfo *info ) ;
\end{verbatim}
\index{DDepInfo_free@{\tt DDsepInfo\_free()}}
This method checks to see whether {\tt info} is {\tt NULL}.
If so, an error message is printed and the program exits.
Otherwise, it releases any storage by a call to
{\tt DDsepInfo\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt info} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DDsepInfo_writeCpuTimes ( DDsepInfo *info, FILE *msgFile ) ;
\end{verbatim}
\index{DDepInfo_writeCpuTimes@{\tt DDsepInfo\_writeCpuTimes()}}
This method writes a breakdown of the CPU times in a meaningful
format.
Here is sample output.
\begin{verbatim}
CPU breakdown for graph partition
raw CPU per cent
misc : 1.61 1.2%
Split : 24.68 17.7%
find DD : 12.13 8.7%
DomSeg Map : 13.09 9.4%
DomSeg BPG : 4.66 3.3%
BKL : 5.68 4.1%
Smooth : 77.83 55.7%
Total : 139.67 100.0%
\end{verbatim}
\par \noindent {\it Error checking:}
If {\tt info} or {\tt msgFile} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
Y) = \emptyset
\} \\
Y_1 & = & \{y \in Y\ |\
y \in Adj(B \setminus Y)
% y \cap Adj(B \setminus Y) \ne \emptyset
\mbox{\ and\ }
y \notin Adj(W \setminus Y)
% y \cap Adj(W \setminus Y) = \emptyset
\} \\
Y_2 & = & \{y \in Y\ |\
y \notin Adj(B \setminus Y)
% y \cap Adj(B \setminus Y) = \emptyset
GPart/doc/main.idx 0100644 0002055 0007177 00000003051 06540033667 0015315 0 ustar 00cleve compmath 0000040 0000006 \indexentry{GPart_new@{\tt GPart\_new()}}{4}
\indexentry{GPart_setDefaultFields@{\tt GPart\_setDefaultFields()}}{4}
\indexentry{GPart_clearData@{\tt GPart\_clearData()}}{4}
\indexentry{GPart_free@{\tt GPart\_free()}}{4}
\indexentry{GPart_init@{\tt GPart\_init()}}{4}
\indexentry{GPart_setMessageInfo@{\tt GPart\_setMessageInfo()}}{4}
\indexentry{GPart_setCweights@{\tt GPart\_setCweights()}}{5}
\indexentry{GPart_sizeOf@{\tt GPart\_sizeOf()}}{5}
\indexentry{GPart_validVtxSep@{\tt GPart\_validVtxSep()}}{5}
\indexentry{GPart_split@{\tt GPart\_split()}}{5}
\indexentry{GPart_vtxIsAdjToOneDomain@{\tt GPart\_vtxIsAdjToOneDomain()}}{5}
\indexentry{GPart_bndWeightsIV@{\tt GPart\_bndWeightsIV()}}{6}
\indexentry{GPart_DDviaFishnet@{\tt GPart\_DDviaFishnet()}}{6}
\indexentry{GPart_DDviaProjection@{\tt GPart\_DDviaProjection()}}{6}
\indexentry{GPart_TwoSetViaBKL@{\tt GPart\_TwoSetViaBKL()}}{6}
\indexentry{GPart_domSegMap@{\tt GPart\_domSegMap()}}{7}
\indexentry{GPart_identifyWideSep@{\tt GPart\_identifyWideSep()}}{7}
\indexentry{GPart_makeYCmap@{\tt GPart\_makeYCmap()}}{7}
\indexentry{GPart_smoothBy2layers@{\tt GPart\_smoothBy2layers()}}{8}
\indexentry{GPart_smoothYSep@{\tt GPart\_smoothYSep()}}{8}
\indexentry{GPart_smoothBisector@{\tt GPart\_smoothBisector()}}{8}
\indexentry{GPart_RBviaDDsep@{\tt GPart\_RBviaDDsep()}}{9}
\indexentry{DDepInfo_new@{\tt DDsepInfo\_new()}}{9}
\indexentry{DDepInfo_setDefaultFields@{\tt DDsepInfo\_setDefaultFields()}}{9}
\indexentry{DDepInfo_clearData@{\tt DDsepInfo\_clearData()}}{9}
\indexentry{DDepInfo_free@{\tt DDsepInfo\_free()}}{10}
GPart/doc/main.ilg 0100644 0002055 0007177 00000000457 06540033655 0015310 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (26 entries accepted, 0 rejected).
Sorting entries....done (126 comparisons).
Generating output file main.ind....done (33 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
GPart/doc/makefile 0100644 0002055 0007177 00000000027 06576271254 0015370 0 ustar 00cleve compmath 0000040 0000006 clean :
- rm -f *.dvi
Graph.h 0100644 0002055 0007177 00000000100 06534106402 0013272 0 ustar 00cleve compmath 0000040 0000006 #ifndef _Graph_
#define _Graph_
#include "Graph/Graph.h"
#endif
Graph/Graph.h 0100644 0002055 0007177 00000056236 06616657274 0014403 0 ustar 00cleve compmath 0000040 0000006 /* Graph.h */
#include "../IVL.h"
#include "../IV.h"
#include "../cfiles.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
The Graph object represents one of three types of graphs,
defined by its "type" field.
The Graph object uses IVL objects to store the vertex adjacency
lists and edge weight lists (for types 2 and 3).
The Graph object also supports graphs with "boundaries".
This need arose from ordering graphs using constrained
minimum degree where boundary vertices contribute to the
degree but are not eliminated.
created : 95-sep27, cca
---------------------------------------------------------------
*/
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
data fields
type -- type of graph
type vertices weighted? edges weighted?
0 no no
1 yes no
2 no yes
3 yes yes
nvtx -- number of vertices, also equals adjIVL->nlist
and ewghtIVL->nlist
nvbnd -- number of boundary vertices
nedges -- number of edges, also equals adjIVL->tsize
and ewghtIVL->tsize
totvwght -- total vertex weight
totewght -- total edge weight
adjIVL -- IVL object that holds the adjacency lists
vwghts -- int vector that holds the vertex weights,
size nvtx + nvbnd, not NULL if type % 2 == 1
ewghtIVL -- IVL object that holds the edge weight lists,
not NULL if type >= 2
---------------------------------------------------------
*/
typedef struct _Graph Graph ;
struct _Graph {
int type ;
int nvtx ;
int nvbnd ;
int nedges ;
int totvwght ;
int totewght ;
IVL *adjIVL ;
int *vwghts ;
IVL *ewghtIVL ;
} ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in basics.c -------------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------
purpose -- create and return a new Graph object
created -- 95sep27, cca
-----------------------------------------------
*/
Graph *
Graph_new (
void
) ;
/*
------------------------------------------------------
purpose -- set the default fields for the Graph object
created -- 95sep27, cca
------------------------------------------------------
*/
void
Graph_setDefaultFields (
Graph *g
) ;
/*
--------------------------------
purpose -- clear the data fields
created -- 95sep27, cca
--------------------------------
*/
void
Graph_clearData (
Graph *g
) ;
/*
--------------------------------
purpose -- free the Graph object
created -- 95sep27, cca
--------------------------------
*/
void
Graph_free (
Graph *g
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in compress.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------------
given a graph g and a fine-to-coarse map vector cmap[],
return a compressed graph with type coarseType.
note, the compressed graph will have no trivial boundary
even if the original graph did have a boundary.
created -- 95sep29, cca
---------------------------------------------------------------
*/
Graph *
Graph_compress (
Graph *g,
int cmap[],
int coarseType
) ;
/*
---------------------------------------------------------------
given a graph g and a fine-to-coarse map vector *mapIV,
return a compressed graph with type coarseType.
note, the compressed graph will have no trivial boundary
even if the original graph did have a boundary.
created -- 96mar02, cca
---------------------------------------------------------------
*/
Graph *
Graph_compress2 (
Graph *g,
IV *mapIV,
int coarseType
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in equivMap.c -----------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------
fill an IV object with an equivalence map
if ( map[u] == map[v] ) then
then u and v are adjacent to the same vertices
endif
NOTE : each empty list is mapped to a different value
return value -- IV object that contains the equivalence map
created -- 96feb23, cca
-----------------------------------------------------------
*/
IV *
Graph_equivMap (
Graph *g
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in expand.c -------------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------------------
purpose -- take a Graph object and a map to expand it, create and
return a bigger unit weight Graph object. this is useful
for expanding a compressed graph into a unit weight graph.
created -- 96mar02, cca
---------------------------------------------------------------------
*/
Graph *
Graph_expand (
Graph *g,
int nvtxbig,
int map[]
) ;
/*
---------------------------------------------------------------------
purpose -- take a Graph object and a map to expand it, create and
return a bigger unit weight Graph object. this is useful
for expanding a compressed graph into a unit weight graph.
created -- 96mar02, cca
---------------------------------------------------------------------
*/
Graph *
Graph_expand2 (
Graph *g,
IV *mapIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in fillFromOffsets.c ----------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------------------------
purpose -- take an adjacency structure in the
(offsets[neqns+1], adjncy[*]) form
and load the Graph object
g -- pointer to Graph object, must be initialized with nvtx = neqns
neqns -- # of equations
offsets -- offsets vector
adjncy -- big adjacency vector
note, the adjacency for list v is found in
adjncy[offsets[v]:offsets[v+1]-1]
also note, offsets[] and adjncy[] must be zero based,
if (offsets,adjncy) come from a harwell-boeing file, they use
the fortran numbering, so each value must be decremented to
conform with C's zero based numbering
flag -- task flag
flag = 0 --> just set the adjacency list for v to be that
found in adjncy[offsets[v]:offsets[v+1]-1]
flag = 1 --> the input adjancency is just the upper triangle
(or strict upper triangle) as from a harwell-boeing
file. fill the Graph object with the full adjacency
structure, including (v,v) edges
created -- 96mar16, cca
-------------------------------------------------------------------
*/
void
Graph_fillFromOffsets (
Graph *g,
int neqns,
int offsets[],
int adjncy[],
int flag
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in init.c ---------------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------
basic initializer for the Graph object
type -- graph type
nvtx -- # of vertices
nvbnd -- # of boundary vertices
nedges -- # of edges
adjType -- IVL type for adjacency object
ewghtType -- IVL type for edge weights object
created -- 95sep27, cca
---------------------------------------------
*/
void
Graph_init1 (
Graph *g,
int type,
int nvtx,
int nvbnd,
int nedges,
int adjType,
int ewghtType
) ;
/*
--------------------------------------------------------
second initializer for the Graph object.
this function is used in the I/O routines
Graph_readFromFormattedFile(Graph *g, FILE *fp) and
Graph_readFromBinaryFile(Graph *g, FILE *fp) where
the IVL object(s) and vwghts[] vector are created
independently.
type -- graph type
nvtx -- # of vertices
nvbnd -- # of boundary vertices
nedges -- # of edges
totvwght -- total vertex weight
totewght -- total edge weight
adjIVL -- IVL object for adjacency structure
vwghts -- pointer to integer vector for vertex weights
ewghtIVL -- IVL object for edge weights
created -- 95sep27, cca
--------------------------------------------------------
*/
void
Graph_init2 (
Graph *g,
int type,
int nvtx,
int nvbnd,
int nedges,
int totvwght,
int totewght,
IVL *adjIVL,
int *vwghts,
IVL *ewghtIVL
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in util.c ---------------------------------------------
------------------------------------------------------------------------
*/
/*
---------------------------------------------------------------------
return the external degree (in terms of vertex weight) of vertex v
created -- 95oct05, cca
---------------------------------------------------------------------
*/
int
Graph_externalDegree (
Graph *g,
int v
) ;
/*
-----------------------------------
method to access the adjacency list
created -- 95oct05, cca
-----------------------------------
*/
void
Graph_adjAndSize (
Graph *g,
int jvtx,
int *psize,
int **padj
) ;
/*
-----------------------------------------------
method to access the adjacency list
and possibly the edge weight list for a vertex.
created -- 95sep29, cca
-----------------------------------------------
*/
void
Graph_adjAndEweights (
Graph *g,
int jvtx,
int *psize,
int **padj,
int **pewghts
) ;
/*
----------------------------------------------------
return the number of bytes taken by the Graph object
created -- 95oct05, cca
----------------------------------------------------
*/
int
Graph_sizeOf (
Graph *g
) ;
/*
--------------------------------------
create and return an IV object filled
with a map from vertices to components
created -- 96feb25, cca
--------------------------------------
*/
IV *
Graph_componentMap (
Graph *g
) ;
/*
-----------------------------------------------------------------
given a Graph g and map from vertices to components,
fill counts[icomp] with the number of vertices in component icomp
and fill weight[icomp] with their weight
created -- 96feb25, cca
-----------------------------------------------------------------
*/
void
Graph_componentStats (
Graph *g,
int map[],
int counts[],
int weights[]
) ;
/*
-------------------------------------------------------------------
create and return a subgraph and a map from
its vertices to the vertices of the graph.
g -- graph from which to extract the subgraph
icomp -- component from which comes the vertices of the subgraph,
icomp > 0
compids -- component ids vector of graph
pmap -- pointer to hold address of map vector, the map from
the subgraph's vertices to the graph's vertices
return value -- pointer to subgraph Graph object
created -- 95nov10, cca
-------------------------------------------------------------------
*/
Graph *
Graph_subGraph (
Graph *g,
int icomp,
int compids[],
int **pmap
) ;
/*
----------------------------------
return 1 if the graph is symmetric
return 0 otherwise
created -- 96oct31, cca
----------------------------------
*/
int
Graph_isSymmetric (
Graph *graph
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in polar.c --------------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------
perform a breadth-first search
v -- vertex to check out
levelsIV -- IV object that holds the levels vector
listIV -- IV object to hold order of search
parIV -- IV object to hold parent vector
return value -- depth of the search tree
created -- 96jul13, cca
-----------------------------------------------------------
*/
int
Graph_BFS (
Graph *graph,
int v,
IV *levelsIV,
IV *listIV,
IV *parIV
) ;
/*
------------------------------------------------------------
perform a breadth-first search from a list of seed vertices.
seedsIV -- IV object that holds the seed vertices
levelsIV -- IV object that holds the levels vector
listIV -- IV object to hold order of search
parIV -- IV object to hold parent vector
return value -- depth of the search tree
created -- 96jul19, cca
------------------------------------------------------------
*/
int
Graph_BFS2 (
Graph *graph,
IV *seedsIV,
IV *levelsIV,
IV *listIV,
IV *parIV
) ;
/*
----------------------------------------------------------
find a pseudodiameter of a graph.
fill *pstart and *pend with the endpoint vertices.
fill startLevelsIV and endLevelsIV with the level vectors
for the BFS from the start and end vertices, respectively.
created -- 96jul13, cca
----------------------------------------------------------
*/
void
Graph_pseudodiameter (
Graph *g,
int root,
IV *startLevelsIV,
IV *endLevelsIV,
int *pstart,
int *pend
) ;
/*
----------------------------------------------------------
create and return an IV object that contains a list of
vertices that are in the major axis of the graph.
we have dropped two levels structures from end vertices
to approximate the diameter of the graph.
a vertex v is in the major axis if
levels1[v] + levels2[v] - tolerance <= d(s,e)
fill *pstart and *pend with the endpoint vertices.
created -- 96jul13, cca
----------------------------------------------------------
*/
IV *
Graph_majorAxis (
Graph *graph,
int vstart,
int vend,
IV *startLevelsIV,
IV *endLevelsIV,
int tolerance
) ;
/*
-----------------------------------------------------------
compute and return the polar moment of inertia for a vertex
v -- vertex to check out
levelsIV -- IV object that holds the levels vector
listIV -- IV object for workspace
created -- 96jul13, cca
-----------------------------------------------------------
*/
double
Graph_polarMoment (
Graph *graph,
int v,
IV *levelsIV,
IV *listIV
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in setListsFromOffsets.c ------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------------------------
purpose --
take an adjacency structure in the (offsets[neqns+1], adjncy[*])
form and load the Graph object. note, pointers to the lists are
set, no new storage is allocated for the adjacency lists.
however, during the ordering process each adjacency lists
may be shuffled.
g -- pointer to Graph object,
must be initialized with nvtx = neqns
neqns -- # of equations
offsets -- offsets vector
adjncy -- big adjacency vector
note, the adjacency for list v is found in
adjncy[offsets[v]:offsets[v+1]-1]
also note, offsets[] and adjncy[] must be zero based,
if (offsets,adjncy) come from a harwell-boeing file, they use
the fortran numbering, so each value must be decremented to
conform with C's zero based numbering
created -- 96oct24, cca
-------------------------------------------------------------------
*/
void
Graph_setListsFromOffsets (
Graph *g,
int neqns,
int offsets[],
int adjncy[]
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in wirebasket.c ---------------------------------------
------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------
on input
stages[v] = 0 --> vertex is in a domain
stages[v] > 0 --> vertex is in the multisector
this remains true on output, but the stage of a multisector
vertex is equal to the number of different domains that
are found within radius edges from itself
created -- 97jul30, cca
-----------------------------------------------------------
*/
void
Graph_wirebasketStages (
Graph *graph,
IV *stagesIV,
int radius
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in IO.c -----------------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------
purpose -- to read in a Graph object from a file
input --
fn -- filename, must be *.graphb or *.graphf
return value -- 1 if success, 0 if failure
created -- 95sep29, cca
-------------------------------------------------
*/
int
Graph_readFromFile (
Graph *graph,
char *fn
) ;
/*
-------------------------------------------------------
purpose -- to read in a Graph object from a CHACO file
input --
fn -- filename
return value -- 1 if success, 0 if failure
created -- 98sep20, jjs
--------------------------------------------------------
*/
int
Graph_readFromChacoFile (
Graph *graph,
char *fn
) ;
/*
--------------------------------------------------------
purpose -- to read a Graph object from a formatted file
return value -- 1 if success, 0 if failure
created -- 95sep29, cca
--------------------------------------------------------
*/
int
Graph_readFromFormattedFile (
Graph *graph,
FILE *fp
) ;
/*
----------------------------------------------------
purpose -- to read a Graph object from a binary file
return value -- 1 if success, 0 if failure
created -- 95sep29, cca
----------------------------------------------------
*/
int
Graph_readFromBinaryFile (
Graph *graph,
FILE *fp
) ;
/*
--------------------------------------------
purpose -- to write a Graph object to a file
input --
fn -- filename
*.graphb -- binary
*.graphf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 95sep29, cca
--------------------------------------------
*/
int
Graph_writeToFile (
Graph *graph,
char *fn
) ;
/*
------------------------------------------------------
purpose -- to write a Graph object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 95sep29, cca
------------------------------------------------------
*/
int
Graph_writeToFormattedFile (
Graph *graph,
FILE *fp
) ;
/*
---------------------------------------------------
purpose -- to write a Graph object to a binary file
return value -- 1 if success, 0 otherwise
created -- 95sep29, cca
---------------------------------------------------
*/
int
Graph_writeToBinaryFile (
Graph *graph,
FILE *fp
) ;
/*
-------------------------------------------------
purpose -- to write a Graph object for a human eye
return value -- 1 if success, 0 otherwise
created -- 95sep29, cca
-------------------------------------------------
*/
int
Graph_writeForHumanEye (
Graph *graph,
FILE *fp
) ;
/*
-----------------------------------------------------------
purpose -- to write out the statistics for the Graph object
return value -- 1 if success, 0 otherwise
created -- 95sep29, cca
-----------------------------------------------------------
*/
int
Graph_writeStats (
Graph *graph,
FILE *fp
) ;
/*
---------------------------------
write out a graph to a METIS file
created -- 95oct18, cca
---------------------------------
*/
int
Graph_writeToMetisFile (
Graph *g,
FILE *fp
) ;
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------------------------
---- functions in getTree.c ------------------------------------------
------------------------------------------------------------------------
*/
/*
-------------------------------------------------
purpose -- to extract a maximal tree from a graph
on input,
if mark[v] == 'N' then
v is eligible to be placed in the tree
endif
i.e., mark[] serves as a mask vector
on return,
if ( mark[v] == 'Y' ) then
v is in the tree, parent of v = par[v]
else
mark[v] = 'N', not in tree
endif
created -- 98apr10, cca
-------------------------------------------------
*/
void
Graph_getTree (
Graph *graph,
int par[],
char mark[],
int seed,
int msglvl,
FILE *msgFile
) ;
/*
--------------------------------------------------------
purpose -- to extract a maximal nlevel-tree from a graph
(a vertex v can have an edge in the graph with itself
and any ancestor within nlevel levels in the tree.)
on input,
if mark[v] == 'N' then
v is eligible to be placed in the tree
endif
i.e., mark[] serves as a mask vector
on return,
if ( mark[v] == 'Y' ) then
v is in the tree, parent of v = par[v]
else
mark[v] = 'N', not in tree
endif
created -- 98apr10, cca
--------------------------------------------------------
*/
void
Graph_getTree2 (
Graph *graph,
int nlevel,
int par[],
char mark[],
int seed,
int msglvl,
FILE *msgFile
) ;
/*--------------------------------------------------------------------*/
tIV -- IV object to hold order of search
parIV -- IV object to hold parent vector
return value -- depth of the search tree
created -- 96jul13, cca
-----------------------------------------------------------
*/
int
Graph_BFS (
Graph *graph,
int v,
IV *levelsIV,
IV *listIV,
IV *parIV
) ;
/*
----Graph/makefile 0100644 0002055 0007177 00000000223 06636223603 0014635 0 ustar 00cleve compmath 0000040 0000006 all_drivers :
cd drivers ; make drivers
lib :
cd src ; make makeLib
clean :
cd src ; make clean
cd drivers ; make clean
cd doc ; make clean
Graph/src/makefile 0100644 0002055 0007177 00000001134 06636024266 0015432 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = Graph
$(OBJ).a : \
$(OBJ).a(IO.o) \
$(OBJ).a(basics.o) \
$(OBJ).a(compress.o) \
$(OBJ).a(equivMap.o) \
$(OBJ).a(expand.o) \
$(OBJ).a(fillFromOffsets.o) \
$(OBJ).a(init.o) \
$(OBJ).a(setListsFromOffsets.o) \
$(OBJ).a(util.o) \
$(OBJ).a(wirebasket.o)
$(RANLIB) $(OBJ).a
@echo $(OBJ).a is now up-to-date
clean :
- rm -f *.a *.o
makeLib :
perl ../../makeLib > makeG
make -f makeG
rm -f makeG
updateLib :
perl ../../updLib > makeG
make -f makeG
rm -f makeG
Graph/src/makeGlobalLib 0100644 0002055 0007177 00000000777 06600261032 0016337 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
OBJ = Graph
SRC = IO.c \
basics.c \
compress.c \
equivMap.c \
expand.c \
fillFromOffsets.c \
init.c \
setListsFromOffsets.c \
util.c \
wirebasket.c
OBJ_FILES = ${SRC:.c=.o}
.c.o :
$(PURIFY) $(CC) -c $(CFLAGS) $*.c -o $(OBJ)_$*.o
../../spooles.a : ${OBJ_FILES}
$(AR) $(ARFLAGS) ../../spooles.a $(OBJ)_*.o
rm -f $(OBJ)_*.o
$(RANLIB) ../../spooles.a
Graph/src/IO.c 0100644 0002055 0007177 00000075766 06650175400 0014424 0 ustar 00cleve compmath 0000040 0000006 /* IO.c */
#include "../Graph.h"
#define BUFLEN 100000
static const char *suffixb = ".graphb" ;
static const char *suffixf = ".graphf" ;
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to read in a Graph object from a file
input --
fn -- filename, must be *.graphb or *.graphf
return value -- 1 if success, 0 if failure
created -- 95sep29, cca
-------------------------------------------------
*/
int
Graph_readFromFile (
Graph *graph,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( graph == NULL || fn == NULL ) {
fprintf(stderr, "\n error in Graph_readFromFile(%p,%s)"
"\n bad input\n", graph, fn) ;
return(0) ;
}
/*
-------------
read the file
-------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "rb")) == NULL ) {
fprintf(stderr, "\n error in Graph_readFromFile(%p,%s)"
"\n unable to open file %s", graph, fn, fn) ;
rc = 0 ;
} else {
rc = Graph_readFromBinaryFile(graph, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "r")) == NULL ) {
fprintf(stderr, "\n error in Graph_readFromFile(%p,%s)"
"\n unable to open file %s", graph, fn, fn) ;
rc = 0 ;
} else {
rc = Graph_readFromFormattedFile(graph, fp) ;
fclose(fp) ;
}
} else {
fprintf(stderr, "\n error in Graph_readFromFile(%p,%s)"
"\n bad Graph file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
graph, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
} else {
fprintf(stderr, "\n error in Graph_readFromFile(%p,%s)"
"\n bad Graph file name %s,"
"\n must end in %s (binary) or %s (formatted)\n",
graph, fn, fn, suffixb, suffixf) ;
rc = 0 ;
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
purpose -- to read in a Graph object from a CHACO file
input --
fn -- filename
return value -- 1 if success, 0 if failure
created -- 98sep20, jjs
--------------------------------------------------------
*/
int
Graph_readFromChacoFile (
Graph *graph,
char *fn
) {
char *rc ;
FILE *fp;
int nvtx, nedges, format;
char string[BUFLEN], *s1, *s2;
int k, v, vsize, w, vwghts, ewghts;
int *adjncy, *weights, *vwghtsINT;
IVL *adjIVL, *ewghtIVL;
/*
---------------
check the input
---------------
*/
if ((graph == NULL) || (fn == NULL)) {
fprintf(stderr, "\n error in Graph_readFromFile(%p,%s)"
"\n bad input\n", graph, fn);
return(0);
}
/*
---------------------
clear the data fields
---------------------
*/
Graph_clearData(graph);
/*
----------------------------------------------
open file and read in nvtx, nedges, and format
----------------------------------------------
*/
if ((fp = fopen(fn, "r")) == (FILE*)NULL) {
fprintf(stderr, "\n error in Graph_readFromChacoFile(%p,%s)"
"\n unable to open file %s", graph, fn, fn);
return(0);
}
/*
-------------
skip comments
-------------
*/
do {
rc = fgets(string, BUFLEN, fp) ;
if ( rc == NULL ) {
fprintf(stderr, "\n error in Graph_readFromChacoFile()"
"\n error skipping comments in file %s\n", fn) ;
return(0) ;
}
} while ( string[0] == '%');
/*
-------------------------------------------------
read in # vertices, # edges and (optional) format
-------------------------------------------------
*/
format = 0;
if (sscanf(string, "%d %d %d", &nvtx, &nedges, &format) < 2) {
fprintf(stderr, "\n error in Graph_readFromChacoFile(%p,%s)"
"\n unable to read header of file %s", graph, fn, fn);
return(0);
}
ewghts = ((format % 10) > 0);
vwghts = (((format / 10) % 10) > 0);
if (format >= 100) {
fprintf(stderr, "\n error in Graph_readFromChacoFile(%p,%s)"
"\n unknown format", graph, fn);
return(0);
}
/*
------------------------------------------------------------------
initialize vector(s) to hold adjacency and (optional) edge weights
------------------------------------------------------------------
*/
adjncy = IVinit(nvtx, -1) ;
if ( ewghts ) {
weights = IVinit(nvtx, -1) ;
} else {
weights = NULL ;
}
/*
---------------------------
initialize the Graph object
---------------------------
*/
nedges *= 2;
nedges += nvtx;
Graph_init1(graph, 2*ewghts+vwghts, nvtx, 0, nedges,
IVL_CHUNKED, IVL_CHUNKED);
adjIVL = graph->adjIVL;
if (ewghts) {
ewghtIVL = graph->ewghtIVL;
weights[0] = 0; /* self loops have no weight */
}
if (vwghts) vwghtsINT = graph->vwghts;
/*
---------------------------
read in all adjacency lists
---------------------------
*/
k = 0;
for (v = 0; v < nvtx; v++) {
/*
-------------
skip comments
-------------
*/
do {
rc = fgets(string, BUFLEN, fp);
if ( rc == NULL ) {
fprintf(stderr, "\n error in Graph_readFromChacoFile()"
"\n error reading adjacency for vertex %d in file %s\n",
v, fn) ;
IVfree(adjncy) ;
if ( weights != NULL ) {
IVfree(weights) ;
}
return(0) ;
}
} while ( string[0] == '%');
/*
-------------------------
check for buffer overflow
-------------------------
*/
if (strlen(string) == BUFLEN-1) {
fprintf(stderr, "\n error in Graph_readFromChacoFile(%p,%s)"
"\n unable to read adjacency lists of file %s (line "
"buffer too small)\n", graph, fn, fn);
IVfree(adjncy) ;
if ( weights != NULL ) {
IVfree(weights) ;
}
return(0);
}
/*
----------------------------------------------
read in (optional) vertex weight,
adjacent vertices, and (optional) edge weights
----------------------------------------------
*/
s1 = string;
if (vwghts) vwghtsINT[v] = (int)strtol(string, &s1, 10);
adjncy[0] = v; /* insert self loop needed by spooles */
if ( ewghts ) {
weights[0] = 0;
}
vsize = 1;
while ((w = (int)strtol(s1, &s2, 10)) > 0) {
adjncy[vsize] = --w; /* node numbering starts with 0 */
s1 = s2;
if (ewghts)
{ weights[vsize] = (int)strtol(s1, &s2, 10);
s1 = s2;
}
vsize++;
}
/*
---------------------------------
sort the lists in ascending order
---------------------------------
*/
if ( ewghts ) {
IV2qsortUp(vsize, adjncy, weights) ;
} else {
IVqsortUp(vsize, adjncy) ;
}
/*
--------------------------------
set the lists in the IVL objects
--------------------------------
*/
IVL_setList(adjIVL, v, vsize, adjncy);
if (ewghts) IVL_setList(ewghtIVL, v, vsize, weights);
k += vsize;
}
/*
-----------------------------------
close the file and do a final check
-----------------------------------
*/
fclose(fp);
/*
------------------------
free the working storage
------------------------
*/
IVfree(adjncy) ;
if ( weights != NULL ) {
IVfree(weights) ;
}
/*
----------------
check for errors
----------------
*/
if ((k != nedges) || (v != nvtx)) {
fprintf(stderr, "\n error in Graph_readFromChacoFile()"
"\n number of nodes/edges does not match with header of %s"
"\n k %d, nedges %d, v %d, nvtx %d\n",
fn, k, nedges, v, nvtx);
return(0);
}
return(1); }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
purpose -- to read a Graph object from a formatted file
return value -- 1 if success, 0 if failure
created -- 95sep29, cca
--------------------------------------------------------
*/
int
Graph_readFromFormattedFile (
Graph *graph,
FILE *fp
) {
int nedges, nvbnd, nvtx, rc, totewght, totvwght, type ;
int itemp[6] ;
int *vwghts ;
IVL *adjIVL, *ewghtIVL ;
/*
---------------
check the input
---------------
*/
if ( graph == NULL || fp == NULL ) {
fprintf(stderr, "\n error in Graph_readFromFormattedFile(%p,%p)"
"\n bad input\n", graph, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
Graph_clearData(graph) ;
/*
---------------------------------------------
read in the six scalar parameters
type, nvtx, nvbnd, nedges, totvwght, totewght
---------------------------------------------
*/
if ( (rc = IVfscanf(fp, 6, itemp)) != 6 ) {
fprintf(stderr, "\n error in Graph_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", graph, fp, rc, 6) ;
return(0) ;
}
type = itemp[0] ;
nvtx = itemp[1] ;
nvbnd = itemp[2] ;
nedges = itemp[3] ;
totvwght = itemp[4] ;
totewght = itemp[5] ;
/*
--------------------------------------------------
create the adjIVL IVL object,
set its type to IVL_CHUNKED, then read in its data
--------------------------------------------------
*/
adjIVL = IVL_new() ;
IVL_setDefaultFields(adjIVL) ;
adjIVL->type = IVL_CHUNKED ;
rc = IVL_readFromFormattedFile(adjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in Graph_readFromFormattedFile(%p,%p)"
"\n trying to read in adjIVL"
"\n return code %d from IVL_readFormattedFile(%p,%p)",
graph, fp, rc, adjIVL, fp) ;
return(0) ;
}
if ( type % 2 == 1 ) {
int nvtot, wght ;
/*
--------------------------
vertex weights are present
--------------------------
*/
nvtot = nvtx + nvbnd ;
vwghts = IVinit2(nvtot) ;
if ( (rc = IVfscanf(fp, nvtot, vwghts)) != nvtot ) {
fprintf(stderr, "\n error in Graph_readFromFormattedFile(%p,%p)"
"\n %d items of %d read\n", graph, fp, rc, nvtot) ;
return(0) ;
}
wght = IVsum(nvtot, vwghts) ;
if ( wght != totvwght ) {
fprintf(stderr, "\n error in Graph_readFromFormattedFile(%p,%p)"
"\n totvwght = %d, IVsum(vwghts) = %d\n",
graph, fp, totvwght, wght) ;
return(0) ;
}
} else {
vwghts = NULL ;
}
if ( type >= 2 ) {
int wght ;
/*
-----------------------------------------------------
edge weights are present, create the ewghtIVL object,
set its type to IVL_CHUNKED, then read in its data
-----------------------------------------------------
*/
ewghtIVL = IVL_new() ;
IVL_setDefaultFields(ewghtIVL) ;
ewghtIVL->type = IVL_CHUNKED ;
rc = IVL_readFromFormattedFile(ewghtIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in Graph_readFromFormattedFile(%p,%p)"
"\n trying to read in ewghtIVL"
"\n return code %d from IVL_readFormattedFile(%p,%p)",
graph, fp, rc, ewghtIVL, fp) ;
return(0) ;
}
wght = IVL_sum(ewghtIVL) ;
if ( wght != totewght ) {
fprintf(stderr, "\n error in Graph_readFromFormattedFile(%p,%p)"
"\n totewght = %d, IVL_sum(ewghtIVL) = %d\n",
graph, fp, totewght, wght) ;
return(0) ;
}
} else {
ewghtIVL = NULL ;
}
/*
---------------------
initialize the object
---------------------
*/
Graph_init2(graph, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
purpose -- to read a Graph object from a binary file
return value -- 1 if success, 0 if failure
created -- 95sep29, cca
----------------------------------------------------
*/
int
Graph_readFromBinaryFile (
Graph *graph,
FILE *fp
) {
int nedges, nvbnd, nvtx, rc, totewght, totvwght, type ;
int itemp[6] ;
int *vwghts ;
IVL *adjIVL, *ewghtIVL ;
/*
---------------
check the input
---------------
*/
if ( graph == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in Graph_readFromBinaryFile(%p,%p)"
"\n bad input\n", graph, fp) ;
return(0) ;
}
/*
---------------------
clear the data fields
---------------------
*/
Graph_clearData(graph) ;
/*
---------------------------------------------
read in the six scalar parameters
type, nvtx, nvbnd, nedges, totvwght, totewght
---------------------------------------------
*/
if ( (rc = fread((void *) itemp, sizeof(int), 6, fp)) != 6 ) {
fprintf(stderr, "\n error in Graph_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", graph, fp, rc, 6) ;
return(0) ;
}
type = itemp[0] ;
nvtx = itemp[1] ;
nvbnd = itemp[2] ;
nedges = itemp[3] ;
totvwght = itemp[4] ;
totewght = itemp[5] ;
/*
--------------------------------------------------
create the adjIVL IVL object,
set its type to IVL_CHUNKED, then read in its data
--------------------------------------------------
*/
adjIVL = IVL_new() ;
IVL_setDefaultFields(adjIVL) ;
adjIVL->type = IVL_CHUNKED ;
rc = IVL_readFromBinaryFile(adjIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in Graph_readFromBinaryFile(%p,%p)"
"\n trying to read in adjIVL"
"\n return code %d from IVL_readBinaryFile(%p,%p)",
graph, fp, rc, adjIVL, fp) ;
return(0) ;
}
if ( type % 2 == 1 ) {
int nvtot, wght ;
/*
--------------------------
vertex weights are present
--------------------------
*/
nvtot = nvtx + nvbnd ;
vwghts = IVinit2(nvtot) ;
if ( (rc = fread((void *) vwghts, sizeof(int), nvtot, fp)) != nvtot){
fprintf(stderr, "\n error in Graph_readFromBinaryFile(%p,%p)"
"\n %d items of %d read\n", graph, fp, rc, nvtx+nvbnd) ;
return(0) ;
}
wght = IVsum(nvtot, vwghts) ;
if ( wght != totvwght ) {
fprintf(stderr, "\n error in Graph_readFromBinaryFile(%p,%p)"
"\n totvwght = %d, IVsum(vwghts) = %d\n",
graph, fp, totvwght, wght) ;
return(0) ;
}
} else {
vwghts = NULL ;
}
if ( type > 2 ) {
int wght ;
/*
-----------------------------------------------------
edge weights are present, create the ewghtIVL object,
set its type to IVL_CHUNKED, then read in its data
-----------------------------------------------------
*/
ewghtIVL = IVL_new() ;
IVL_setDefaultFields(ewghtIVL) ;
ewghtIVL->type = IVL_CHUNKED ;
rc = IVL_readFromBinaryFile(ewghtIVL, fp) ;
if ( rc != 1 ) {
fprintf(stderr, "\n error in Graph_readFromBinaryFile(%p,%p)"
"\n trying to read in ewghtIVL"
"\n return code %d from IVL_readBinaryFile(%p,%p)",
graph, fp, rc, ewghtIVL, fp) ;
return(0) ;
}
wght = IVL_sum(ewghtIVL) ;
if ( wght != totewght ) {
fprintf(stderr, "\n error in Graph_readFromBinaryFile(%p,%p)"
"\n totewght = %d, IVL_sum(ewghtIVL) = %d\n",
graph, fp, totewght, wght) ;
return(0) ;
}
} else {
ewghtIVL = NULL ;
}
/*
---------------------
initialize the object
---------------------
*/
Graph_init2(graph, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL) ;
return(1) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------
purpose -- to write a Graph object to a file
input --
fn -- filename
*.graphb -- binary
*.graphf -- formatted
anything else -- for human eye
return value -- 1 if success, 0 otherwise
created -- 95sep29, cca
--------------------------------------------
*/
int
Graph_writeToFile (
Graph *graph,
char *fn
) {
FILE *fp ;
int fnlength, rc, sulength ;
/*
---------------
check the input
---------------
*/
if ( graph == NULL || fn == NULL ) {
fprintf(stderr, "\n fatal error in Graph_writeToFile(%p,%s)"
"\n bad input\n", graph, fn) ;
return(0) ;
}
if ( graph->type < 0 || 3 < graph->type ) {
fprintf(stderr, "\n fatal error in Graph_writeToFile(%p,%s)"
"\n bad type = %d", graph, fn, graph->type) ;
return(0) ;
}
/*
------------------
write out the file
------------------
*/
fnlength = strlen(fn) ;
sulength = strlen(suffixb) ;
if ( fnlength > sulength ) {
if ( strcmp(&fn[fnlength-sulength], suffixb) == 0 ) {
if ( (fp = fopen(fn, "wb")) == NULL ) {
fprintf(stderr, "\n error in Graph_writeToFile(%p,%s)"
"\n unable to open file %s", graph, fn, fn) ;
rc = 0 ;
} else {
rc = Graph_writeToBinaryFile(graph, fp) ;
fclose(fp) ;
}
} else if ( strcmp(&fn[fnlength-sulength], suffixf) == 0 ) {
if ( (fp = fopen(fn, "w")) == NULL ) {
fprintf(stderr, "\n error in Graph_writeToFile(%p,%s)"
"\n unable to open file %s", graph, fn, fn) ;
rc = 0 ;
} else {
rc = Graph_writeToFormattedFile(graph, fp) ;
fclose(fp) ;
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in Graph_writeToFile(%p,%s)"
"\n unable to open file %s", graph, fn, fn) ;
rc = 0 ;
} else {
rc = Graph_writeForHumanEye(graph, fp) ;
fclose(fp) ;
}
}
} else {
if ( (fp = fopen(fn, "a")) == NULL ) {
fprintf(stderr, "\n error in Graph_writeToFile(%p,%s)"
"\n unable to open file %s", graph, fn, fn) ;
rc = 0 ;
} else {
rc = Graph_writeForHumanEye(graph, fp) ;
fclose(fp) ;
}
}
return(rc) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- to write a Graph object to a formatted file
return value -- 1 if success, 0 otherwise
created -- 95sep29, cca
------------------------------------------------------
*/
int
Graph_writeToFormattedFile (
Graph *graph,
FILE *fp
) {
int ierr, rc ;
/*
---------------
check the input
---------------
*/
if ( graph == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in Graph_writeToFormattedFile(%p,%p)"
"\n bad input\n", graph, fp) ;
return(0) ;
}
if ( graph->type < 0 || 3 < graph->type ) {
fprintf(stderr, "\n fatal error in Graph_writeToFormattedFile(%p,%p)"
"\n bad type = %d", graph, fp, graph->type) ;
return(0) ;
}
/*
-----------------------------------
write out the six scalar parameters
-----------------------------------
*/
rc = fprintf(fp, "\n %d %d %d %d %d %d",
graph->type, graph->nvtx, graph->nvbnd,
graph->nedges, graph->totvwght, graph->totewght) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in Graph_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from first fprintf\n", graph, fp, rc) ;
return(0) ;
}
/*
---------------------------------
write out the adjacency structure
---------------------------------
*/
rc = IVL_writeToFormattedFile(graph->adjIVL, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in Graph_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from IVL_writeToFormattedFile(%p,%p)"
"\n while attempting to write out adjIVL\n",
graph, fp, rc, graph->adjIVL, fp) ;
return(0) ;
}
/*
-----------------------------------------
write out the vwghts[] vector, if present
-----------------------------------------
*/
if ( graph->type % 2 == 1 ) {
if ( graph->vwghts == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_writeToFormattedFile(%p,%p)"
"\n graph->type = %d, graph->vwghts == NULL\n",
graph, fp, graph->type) ;
return(0) ;
}
IVfp80(fp, graph->nvtx+graph->nvbnd, graph->vwghts, 80, &ierr) ;
if ( ierr < 0 ) {
fprintf(stderr,
"\n fatal error in Graph_writeToFormattedFile(%p,%p)"
"\n ierr = %d, return from vwghts[] IVfp80\n",
graph, fp, ierr) ;
return(0) ;
}
}
/*
-------------------------------------
write out the edge weights IVL object
-------------------------------------
*/
if ( graph->type >= 2 ) {
if ( graph->ewghtIVL == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_writeToFormattedFile(%p,%p)"
"\n graph->type = %d, graph->ewghtIVL == NULL\n",
graph, fp, graph->type) ;
return(0) ;
}
rc = IVL_writeToFormattedFile(graph->ewghtIVL, fp) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in Graph_writeToFormattedFile(%p,%p)"
"\n rc = %d, return from IVL_writeToFormattedFile(%p,%p)"
"\n while attempting to write out ewghtIVL\n",
graph, fp, rc, graph->ewghtIVL, fp) ;
return(0) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------
purpose -- to write a Graph object to a binary file
return value -- 1 if success, 0 otherwise
created -- 95sep29, cca
---------------------------------------------------
*/
int
Graph_writeToBinaryFile (
Graph *graph,
FILE *fp
) {
int rc ;
int itemp[6] ;
/*
---------------
check the input
---------------
*/
if ( graph == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in Graph_writeToBinaryFile(%p,%p)"
"\n bad input\n", graph, fp) ;
return(0) ;
}
if ( graph->type < 0 || 3 < graph->type ) {
fprintf(stderr, "\n fatal error in Graph_writeToBinaryFile(%p,%p)"
"\n bad type = %d", graph, fp, graph->type) ;
return(0) ;
}
/*
-----------------------------------
write out the six scalar parameters
-----------------------------------
*/
itemp[0] = graph->type ;
itemp[1] = graph->nvtx ;
itemp[2] = graph->nvbnd ;
itemp[3] = graph->nedges ;
itemp[4] = graph->totvwght ;
itemp[5] = graph->totewght ;
rc = fwrite((void *) itemp, sizeof(int), 6, fp) ;
if ( rc != 6 ) {
fprintf(stderr, "\n error in Graph_writeToBinaryFile(%p,%p)"
"\n %d of %d scalar items written\n", graph, fp, rc, 6) ;
return(0) ;
}
/*
---------------------------------
write out the adjacency structure
---------------------------------
*/
rc = IVL_writeToBinaryFile(graph->adjIVL, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in Graph_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from IVL_writeToBinaryFile(%p,%p)"
"\n while attempting to write out adjIVL\n",
graph, fp, rc, graph->adjIVL, fp) ;
return(0) ;
}
/*
-----------------------------------------
write out the vwghts[] vector, if present
-----------------------------------------
*/
if ( graph->type % 2 == 1 ) {
if ( graph->vwghts == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_writeToBinaryFile(%p,%p)"
"\n graph->type = %d, graph->vwghts == NULL\n",
graph, fp, graph->type) ;
return(0) ;
}
rc = fwrite((void *) graph->vwghts, sizeof(int),
graph->nvtx + graph->nvbnd, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in Graph_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from vwghts[] fwrite\n",
graph, fp, rc) ;
return(0) ;
}
}
/*
-------------------------------------
write out the edge weights IVL object
-------------------------------------
*/
if ( graph->type >= 2 ) {
if ( graph->ewghtIVL == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_writeToBinaryFile(%p,%p)"
"\n graph->type = %d, graph->ewghtIVL == NULL\n",
graph, fp, graph->type) ;
return(0) ;
}
rc = IVL_writeToBinaryFile(graph->ewghtIVL, fp) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in Graph_writeToBinaryFile(%p,%p)"
"\n rc = %d, return from IVL_writeToBinaryFile(%p,%p)"
"\n while attempting to write out ewghtIVL\n",
graph, fp, rc, graph->ewghtIVL, fp) ;
return(0) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------
purpose -- to write a Graph object for a human eye
return value -- 1 if success, 0 otherwise
created -- 95sep29, cca
-------------------------------------------------
*/
int
Graph_writeForHumanEye (
Graph *graph,
FILE *fp
) {
int ierr, rc ;
if ( graph == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in Graph_writeForHumanEye(%p,%p)"
"\n bad input\n", graph, fp) ;
exit(-1) ;
}
/*
------------------------
write out the statistics
------------------------
*/
if ( (rc = Graph_writeStats(graph, fp)) == 0 ) {
fprintf(stderr, "\n fatal error in Graph_writeForHumanEye(%p,%p)"
"\n rc = %d, return from Graph_writeStats(%p,%p)\n",
graph, fp, rc, graph, fp) ;
return(0) ;
}
if ( graph->adjIVL != NULL ) {
/*
----------------------------------
write out the adjacency IVL object
----------------------------------
*/
fprintf(fp, "\n\n adjacency IVL object") ;
rc = IVL_writeForHumanEye(graph->adjIVL, fp) ;
if ( rc < 0 ) {
fprintf(stderr, "\n fatal error in Graph_writeForHumanEye(%p,%p)"
"\n rc = %d, return from IVL_writeForHumanEye(%p,%p)"
"\n while attempting to write out adjIVL\n",
graph, fp, rc, graph->adjIVL, fp) ;
return(0) ;
}
}
/*
----------------------------------------------
write out the vertex weights vector if present
----------------------------------------------
*/
if ( graph->type % 2 == 1 ) {
if ( graph->vwghts == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_writeForHumanEye(%p,%p)"
"\n graph->type = %d, graph->vwghts == NULL\n",
graph, fp, graph->type) ;
return(0) ;
}
fprintf(fp, "\n\n vertex weights ") ;
IVfp80(fp, graph->nvtx + graph->nvbnd, graph->vwghts, 80, &ierr) ;
if ( ierr < 0 ) {
fprintf(stderr,
"\n fatal error in Graph_writeForHumanEye(%p,%p)"
"\n ierr = %d, return from vwghts[] IVfp80\n",
graph, fp, ierr) ;
return(0) ;
}
}
/*
------------------------------------------------
write out the edge weight IVL object, if present
------------------------------------------------
*/
if ( graph->type >= 2 ) {
if ( graph->ewghtIVL == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_writeForHumanEye(%p,%p)"
"\n graph->type = %d, graph->ewghtIVL == NULL\n",
graph, fp, graph->type) ;
return(0) ;
}
fprintf(fp, "\n\n edge weights IVL object") ;
rc = IVL_writeForHumanEye(graph->ewghtIVL, fp) ;
if ( rc < 0 ) {
fprintf(stderr,
"\n fatal error in Graph_writeForHumanEye(%p,%p)"
"\n rc = %d, return from IVL_writeForHumanEye(%p,%p)"
"\n while attempting to write out ewghtIVL\n",
graph, fp, rc, graph->ewghtIVL, fp) ;
return(0) ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
purpose -- to write out the statistics for the Graph object
return value -- 1 if success, 0 otherwise
created -- 95sep29, cca
-----------------------------------------------------------
*/
int
Graph_writeStats (
Graph *graph,
FILE *fp
) {
int rc ;
/*
---------------
check the input
---------------
*/
if ( graph == NULL || fp == NULL ) {
fprintf(stderr, "\n error in Graph_writeStats(%p,%p)"
"\n bad input\n", graph, fp) ;
exit(-1) ;
}
switch ( graph->type ) {
case 0 :
rc = fprintf(fp, "\n Graph : unweighted graph object :") ;
break ;
case 1 :
rc = fprintf(fp, "\n Graph : vertices weighted graph object :") ;
break ;
case 2 :
rc = fprintf(fp, "\n Graph : edges weighted graph object :") ;
break ;
case 3 :
rc = fprintf(fp,
"\n Graph : vertices and edges weighted graph object :") ;
break ;
default :
fprintf(stderr, "\n fatal error in Graph_writeStats(%p,%p)"
"\n invalid graph->type = %d\n", graph, fp, graph->type) ;
return(0) ;
}
if ( rc < 0 ) { goto IO_error ; }
fflush(fp) ;
rc = fprintf(fp,
"\n %d internal vertices, %d boundary vertices, %d edges",
graph->nvtx, graph->nvbnd, graph->nedges) ;
if ( rc < 0 ) { goto IO_error ; }
fflush(fp) ;
rc = fprintf(fp,
"\n %d internal vertex weight, %d boundary vertex weight",
(graph->vwghts != NULL) ? IVsum(graph->nvtx, graph->vwghts) : graph->nvtx,
(graph->vwghts != NULL) ? IVsum(graph->nvbnd, graph->vwghts + graph->nvtx) : graph->nvbnd) ;
if ( rc < 0 ) { goto IO_error ; }
if ( graph->type >= 2 ) {
rc = fprintf(fp, "\n %d total edge weight",
graph->totewght) ;
}
if ( rc < 0 ) { goto IO_error ; }
return(1) ;
IO_error :
fprintf(stderr, "\n fatal error in Graph_writeStats(%p,%p)"
"\n rc = %d, return from fprintf\n", graph, fp, rc) ;
return(0) ;
}
/*--------------------------------------------------------------------*/
/*
---------------------------------
write out a graph to a METIS file
created -- 95oct18, cca
---------------------------------
*/
int
Graph_writeToMetisFile (
Graph *g,
FILE *fp
) {
int ii, nedge, nvtx, v, vsize, w ;
int *vewghts, *vadj ;
/*
---------------
check the input
---------------
*/
if ( g == NULL || fp == NULL ) {
fprintf(stderr, "\n fatal error in Graph_writeToMetisFile(%p,%p)"
"\n bad input\n", g, fp) ;
exit(-1) ;
}
nvtx = g->nvtx ;
nedge = (g->nedges - nvtx)/2 ;
switch ( g->type ) {
case 0 :
fprintf(fp, " %d %d ", nvtx, nedge) ;
for ( v = 0 ; v < nvtx ; v++ ) {
fprintf(fp, "\n ") ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w != v && w < nvtx ) {
fprintf(fp, " %d", w + 1) ;
}
}
}
break ;
case 1 :
fprintf(fp, " %d %d 10", nvtx, nedge) ;
for ( v = 0 ; v < nvtx ; v++ ) {
fprintf(fp, "\n %d", g->vwghts[v]) ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w != v && w < nvtx ) {
fprintf(fp, " %d", w + 1) ;
}
}
}
break ;
case 2 :
fprintf(fp, " %d %d 1", nvtx, nedge) ;
for ( v = 0 ; v < nvtx ; v++ ) {
fprintf(fp, "\n") ;
Graph_adjAndEweights(g, v, &vsize, &vadj, &vewghts) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w != v && w < nvtx ) {
fprintf(fp, " %d %d", w + 1, vewghts[ii]) ;
}
}
}
break ;
case 3 :
fprintf(fp, " %d %d 11", nvtx, nedge) ;
for ( v = 0 ; v < nvtx ; v++ ) {
fprintf(fp, "\n %d", g->vwghts[v]) ;
Graph_adjAndEweights(g, v, &vsize, &vadj, &vewghts) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w != v && w < nvtx ) {
fprintf(fp, " %d %d", w + 1, vewghts[ii]) ;
}
}
}
break ;
}
return(1) ; }
/*--------------------------------------------------------------------*/
raph *gGraph/src/basics.c 0100644 0002055 0007177 00000005656 06653142743 0015357 0 ustar 00cleve compmath 0000040 0000006 /* basics.c */
#include "../Graph.h"
#define MYTRACE 0
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
purpose -- create and return a new Graph object
created -- 95sep27, cca
-----------------------------------------------
*/
Graph *
Graph_new (
void
) {
Graph *g ;
#if MYTRACE > 0
fprintf(stdout, "\n just inside Graph_new()") ;
fflush(stdout) ;
#endif
ALLOCATE(g, struct _Graph, 1) ;
Graph_setDefaultFields(g) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving Graph_new()") ;
fflush(stdout) ;
#endif
return(g) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------------------
purpose -- set the default fields for the Graph object
created -- 95sep27, cca
------------------------------------------------------
*/
void
Graph_setDefaultFields (
Graph *g
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside Graph_setDefaultFields(%p)", g) ;
fflush(stdout) ;
#endif
if ( g == NULL ) {
fprintf(stderr, "\n fatal error in Graph_setDefaultFields(%p)"
"\n graph is NULL\n", g) ;
exit(-1) ;
}
g->type = 0 ;
g->nvtx = 0 ;
g->nvbnd = 0 ;
g->nedges = 0 ;
g->totvwght = 0 ;
g->totewght = 0 ;
g->adjIVL = NULL ;
g->vwghts = NULL ;
g->ewghtIVL = NULL ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving Graph_setDefaultFields(%p)", g) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------
purpose -- clear the data fields
created -- 95sep27, cca
--------------------------------
*/
void
Graph_clearData (
Graph *g
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside Graph_clearData(%p)", g) ;
fflush(stdout) ;
#endif
if ( g == NULL ) {
fprintf(stderr, "\n fatal error in Graph_clearData(%p)"
"\n graph is NULL\n", g) ;
exit(-1) ;
}
if ( g->adjIVL != NULL ) {
IVL_free(g->adjIVL) ;
}
if ( g->vwghts != NULL ) {
IVfree(g->vwghts) ;
}
if ( g->ewghtIVL != NULL ) {
IVL_free(g->ewghtIVL) ;
}
Graph_setDefaultFields(g) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving Graph_clearData(%p)", g) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------
purpose -- free the Graph object
created -- 95sep27, cca
--------------------------------
*/
void
Graph_free (
Graph *g
) {
#if MYTRACE > 0
fprintf(stdout, "\n just inside Graph_free(%p)", g) ;
fflush(stdout) ;
#endif
if ( g == NULL ) {
fprintf(stderr, "\n fatal error in Graph_free(%p)"
"\n graph is NULL\n", g) ;
exit(-1) ;
}
Graph_clearData(g) ;
FREE(g) ;
#if MYTRACE > 0
fprintf(stdout, "\n leaving Graph_free(%p)", g) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
Graph/src/compress.c 0100644 0002055 0007177 00000022251 06534106104 0015721 0 ustar 00cleve compmath 0000040 0000006 /* compress.c */
#include "../Graph.h"
#define MYDEBUG 0
#define MYTRACE 0
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
given a graph g and a fine-to-coarse map vector *mapIV,
return a compressed graph with type coarseType.
note, the compressed graph will have no trivial boundary
even if the original graph did have a boundary.
created -- 96mar02, cca
---------------------------------------------------------------
*/
Graph *
Graph_compress2 (
Graph *g,
IV *mapIV,
int coarseType
) {
/*
-------------------------------------------
check input and get dimensions and pointers
-------------------------------------------
*/
if ( g == NULL || mapIV == NULL
|| g->nvtx != IV_size(mapIV)
|| coarseType < 0 || 3 < coarseType ) {
fprintf(stderr, "\n fatal error in Graph_compress2(%p,%p,%d)"
"\n bad input\n", g, mapIV, coarseType) ;
if ( g != NULL ) {
Graph_writeStats(g, stderr) ;
}
if ( mapIV != NULL ) {
IV_writeStats(mapIV, stderr) ;
}
exit(-1) ;
}
return(Graph_compress(g, IV_entries(mapIV), coarseType)) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
given a graph g and a fine-to-coarse map vector cmap[],
return a compressed graph with type coarseType.
note, the compressed graph will have no trivial boundary
even if the original graph did have a boundary.
created -- 95sep29, cca
---------------------------------------------------------------
*/
Graph *
Graph_compress (
Graph *g,
int cmap[],
int coarseType
) {
Graph *g2 ;
int ierr, ii, j, jj, jsize, J, Jsize, k, K, ncvtx, nvtx, wght ;
int *head, *indices, *jind, *Jind, *jwghts, *Jwghts,
*link, *mark, *vwghts, *Vwghts ;
IVL *adjIVL, *AdjIVL, *ewghtIVL, *EwghtIVL ;
#if MYTRACE > 0
fprintf(stdout, "\n just inside Graph_compress(%p,%p,%d)",
g, cmap, coarseType) ;
fflush(stdout) ;
#endif
/*
-------------------------------------------
check input and get dimensions and pointers
-------------------------------------------
*/
if ( g == NULL || cmap == NULL || coarseType < 0 || 3 < coarseType ) {
fprintf(stderr, "\n fatal error in Graph_compress(%p,%p,%d)"
"\n bad input\n", g, cmap, coarseType) ;
exit(-1) ;
}
if ( (nvtx = g->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in Graph_compress(%p,%p,%d)"
"\n nvtx = %d\n", g, cmap, coarseType, nvtx) ;
exit(-1) ;
}
if ( (adjIVL = g->adjIVL) == NULL ) {
fprintf(stderr, "\n fatal error in Graph_compress(%p,%p,%d)"
"\n adjIVL is NULL\n", g, cmap, coarseType) ;
exit(-1) ;
}
if ( g->type % 2 == 1 && (vwghts = g->vwghts) == NULL ) {
fprintf(stderr, "\n fatal error in Graph_compress(%p,%p,%d)"
"\n g->type = %d and g->vwghts is NULL\n",
g, cmap, coarseType, g->type) ;
exit(-1) ;
}
if ( g->type >= 2 && (ewghtIVL = g->ewghtIVL) == NULL ) {
fprintf(stderr, "\n fatal error in Graph_compress(%p,%p,%d)"
"\n g->type = %d and g->ewghtIVL is NULL\n",
g, cmap, coarseType, g->type) ;
exit(-1) ;
}
if ( IVmin(nvtx, cmap, &j) < 0 ) {
fprintf(stderr, "\n fatal error in Graph_compress(%p,%p,%d)"
"\n IVmin(cmap) = %d\n",
g, cmap, coarseType, IVmin(nvtx, cmap, &j)) ;
exit(-1) ;
}
ncvtx = 1 + IVmax(nvtx, cmap, &j) ;
#if MYDEBUG > 0
fprintf(stdout, "\n ncvtx = %d", ncvtx) ;
fflush(stdout) ;
#endif
/*
----------------------------------
initialize the coarse graph object
----------------------------------
*/
g2 = Graph_new() ;
Graph_init1(g2, coarseType, ncvtx, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ;
if ( (AdjIVL = g2->adjIVL) == NULL ) {
fprintf(stderr, "\n fatal error in Graph_compress(%p,%p,%d)"
"\n AdjIVL is NULL\n", g, cmap, coarseType) ;
exit(-1) ;
}
if ( g2->type % 2 == 1 && (Vwghts = g2->vwghts) == NULL ) {
fprintf(stderr, "\n fatal error in Graph_compress(%p,%p,%d)"
"\n g2->type = %d and g2->vwghts is NULL\n",
g, cmap, coarseType, g2->type) ;
exit(-1) ;
}
if ( g2->type >= 2 && (EwghtIVL = g2->ewghtIVL) == NULL ) {
fprintf(stderr, "\n fatal error in Graph_compress(%p,%p,%d)"
"\n g2->type = %d and g2->ewghtIVL is NULL\n",
g, cmap, coarseType, g2->type) ;
exit(-1) ;
}
#if MYDEBUG > 0
fprintf(stdout, "\n after initializing the coarse graph object") ;
Graph_writeStats(g2, stdout) ;
fflush(stdout) ;
#endif
/*
--------------------------------
set up the head and link vectors
--------------------------------
*/
head = IVinit(ncvtx, -1) ;
link = IVinit(nvtx, -1) ;
for ( j = 0 ; j < nvtx ; j++ ) {
J = cmap[j] ;
link[j] = head[J] ;
head[J] = j ;
}
/*
------------------------------------------------
fill the adjacency structure of the coarse graph
------------------------------------------------
*/
indices = IVinit2(ncvtx) ;
mark = IVinit(ncvtx, -1) ;
for ( J = 0 ; J < ncvtx ; J++ ) {
#if MYDEBUG > 0
fprintf(stdout, "\n\n checking out J = %d", J) ;
#endif
Jsize = 0 ;
for ( j = head[J] ; j != -1 ; j = link[j] ) {
IVL_listAndSize(adjIVL, j, &jsize, &jind) ;
#if MYDEBUG > 0
fprintf(stdout, "\n adj j = %d : ", j) ;
IVfp80(stdout, jsize, jind, 20, &ierr) ;
#endif
for ( ii = 0 ; ii < jsize ; ii++ ) {
if ( (k = jind[ii]) < nvtx ) {
K = cmap[k] ;
#if MYDEBUG > 0
fprintf(stdout, "\n k = %d, K = %d", k, K) ;
#endif
if ( mark[K] != J ) {
#if MYDEBUG > 0
fprintf(stdout, ", added") ;
#endif
mark[K] = J ;
indices[Jsize++] = K ;
}
}
}
}
if ( Jsize > 0 ) {
IVqsortUp(Jsize, indices) ;
}
IVL_setList(AdjIVL, J, Jsize, indices) ;
#if MYDEBUG > 0
fprintf(stdout, "\n setting list %d :", J) ;
IVfp80(stdout, Jsize, indices, 20, &ierr) ;
#endif
}
g2->nedges = AdjIVL->tsize ;
IVfree(indices) ;
IVfree(mark) ;
if ( coarseType % 2 == 1 ) {
/*
-------------------------------------------
fill the vertex weights of the coarse graph
-------------------------------------------
*/
for ( J = 0 ; J < ncvtx ; J++ ) {
wght = 0 ;
for ( j = head[J] ; j != -1 ; j = link[j] ) {
if ( g->type % 2 == 1 ) {
wght += vwghts[j] ;
} else {
wght++ ;
}
}
Vwghts[J] = wght ;
}
g2->totvwght = IVsum(ncvtx, Vwghts) ;
#if MYDEBUG > 0
{ int ierr ;
fprintf(stdout, "\n Vwghts(%d) : ", ncvtx) ;
IVfp80(stdout, ncvtx, Vwghts, 80, &ierr) ;
fflush(stdout) ;
}
#endif
} else {
/*
-------------------------------------------------
coarse graph does not have vertex weights,
set total vertex weight to the number of vertices
-------------------------------------------------
*/
g2->totvwght = ncvtx ;
}
if ( coarseType >= 2 ) {
/*
-----------------------------------------
fill the edge weights of the coarse graph
-----------------------------------------
*/
for ( J = 0 ; J < ncvtx ; J++ ) {
IVL_listAndSize(AdjIVL, J, &Jsize, &Jind) ;
IVL_setList(EwghtIVL, J, Jsize, NULL) ;
}
if ( g->type >= 2 ) {
/*
---------------------------
fine graph had edge weights
---------------------------
*/
for ( j = 0 ; j < nvtx ; j++ ) {
J = cmap[j] ;
IVL_listAndSize(adjIVL, j, &jsize, &jind) ;
IVL_listAndSize(ewghtIVL, j, &jsize, &jwghts) ;
IVL_listAndSize(AdjIVL, J, &Jsize, &Jind) ;
IVL_listAndSize(EwghtIVL, J, &Jsize, &Jwghts) ;
for ( ii = 0 ; ii < jsize ; ii++ ) {
k = jind[ii] ;
if ( k < nvtx ) {
K = cmap[k] ;
for ( jj = 0 ; jj < Jsize ; jj++ ) {
if ( Jind[jj] == K ) {
Jwghts[jj] += jwghts[ii] ;
break ;
}
}
}
}
}
} else {
/*
------------------------------------
fine graph did not have edge weights
------------------------------------
*/
for ( j = 0 ; j < nvtx ; j++ ) {
J = cmap[j] ;
IVL_listAndSize(adjIVL, j, &jsize, &jind) ;
IVL_listAndSize(AdjIVL, J, &Jsize, &Jind) ;
IVL_listAndSize(EwghtIVL, J, &Jsize, &Jwghts) ;
for ( ii = 0 ; ii < jsize ; ii++ ) {
k = jind[ii] ;
if ( k < nvtx ) {
K = cmap[k] ;
for ( jj = 0 ; jj < Jsize ; jj++ ) {
if ( Jind[jj] == K ) {
Jwghts[jj]++ ;
break ;
}
}
}
}
}
}
g2->totewght = IVL_sum(EwghtIVL) ;
} else {
/*
--------------------------------------------
coarse graph does not have edge weights,
set total edge weight to the number of edges
--------------------------------------------
*/
g2->totewght = g2->nedges ;
}
/*
------------------------------
free the head and link vectors
------------------------------
*/
IVfree(head) ;
IVfree(link) ;
return(g2) ; }
/*--------------------------------------------------------------------*/
Graph/src/equivMap.c 0100644 0002055 0007177 00000012552 06534106104 0015660 0 ustar 00cleve compmath 0000040 0000006 /* equivMap.c */
#include "../Graph.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------
fill an IV object with an equivalence map
if ( map[u] == map[v] ) then
then u and v are adjacent to the same vertices
endif
NOTE : each empty list is mapped to a different value
return value -- IV object that contains the equivalence map
created -- 96feb23, cca
-----------------------------------------------------------
*/
IV *
Graph_equivMap (
Graph *g
) {
int ierr, ii, ismapped, jj, nvtx, nvtx2, u, usize, v, vsize, vsum ;
int *chksum, *eqmap, *mark, *uadj, *vadj ;
IV *eqmapIV ;
/*
---------------
check the input
---------------
*/
if ( g == NULL || (nvtx = g->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in Graph_equivMap(%p)"
"\n bad input\n", g) ;
exit(-1) ;
}
/*
-----------------------------------------
initialize map and set up working storage
-----------------------------------------
*/
eqmapIV = IV_new() ;
IV_init(eqmapIV, nvtx, NULL) ;
eqmap = IV_entries(eqmapIV) ;
IVfill(nvtx, eqmap, -1) ;
mark = IVinit(nvtx, -1) ;
chksum = IVinit(nvtx, -1) ;
/*
-----------------------------------------
loop over the vertices in ascending order
-----------------------------------------
*/
nvtx2 = 0 ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( eqmap[v] == -1 ) {
Graph_adjAndSize(g, v, &vsize, &vadj) ;
if ( vsize == 0 ) {
/*
------------------------------
list is empty, map to new list
------------------------------
*/
#if MYDEBUG > 1
fprintf(stdout,
"\n vertex %d, empty list, map to %d", v, eqmap[v]) ;
fflush(stdout) ;
#endif
eqmap[v] = nvtx2++ ;
} else {
/*
----------------
compute checksum
----------------
*/
vsum = v ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
if ( vadj[ii] != v ) {
vsum += vadj[ii] ;
}
}
chksum[v] = vsum ;
#if MYDEBUG > 1
fprintf(stdout,
"\n vertex %d, checksum = %d", v, chksum[v]) ;
fflush(stdout) ;
#endif
/*
-------------------------------------------------------
look at all adjacent vertices with numbers lower than v
-------------------------------------------------------
*/
ismapped = 0 ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
if ( (u = vadj[ii]) < v && chksum[u] == vsum ) {
/*
------------------------------
u and v have the same checksum
------------------------------
*/
#if MYDEBUG > 1
fprintf(stdout,
"\n checking vertex %d, checksum = %d",
u, chksum[u]) ;
fflush(stdout) ;
#endif
Graph_adjAndSize(g, u, &usize, &uadj) ;
if ( vsize == usize ) {
/*
----------------------------------------------
the adjacency lists are the same size, compare
----------------------------------------------
*/
if ( ismapped == 0 ) {
/*
---------------------------
mark all vertices in adj(v)
---------------------------
*/
mark[v] = v ;
for ( jj = 0 ; jj < vsize ; jj++ ) {
mark[vadj[jj]] = v ;
}
ismapped = 1 ;
}
/*
-------------------------------------------------
check to see if all vertices in adj(u) are marked
-------------------------------------------------
*/
for ( jj = 0 ; jj < usize ; jj++ ) {
if ( mark[uadj[jj]] != v ) {
#if MYDEBUG > 1
fprintf(stdout,
"\n vertex %d is adjacent to %d but not %d", uadj[jj], u, v) ;
#endif
break ;
}
}
if ( jj == usize ) {
/*
----------------------------------
lists are identical, set map for v
to be the same as the map for u
----------------------------------
*/
#if MYDEBUG > 1
fprintf(stdout,
"\n lists are identical, map[%d] = map[%d] = %d",
v, u, eqmap[u]) ;
fflush(stdout) ;
#endif
eqmap[v] = eqmap[u] ;
break ;
}
}
}
}
if ( eqmap[v] == -1 ) {
/*
------------------------------------------------
v was not found to be indistinguishable from any
adjacent vertex with lower number, set map value
------------------------------------------------
*/
#if MYDEBUG > 1
fprintf(stdout, "\n mapping %d to %d", v, nvtx2) ;
fflush(stdout) ;
#endif
eqmap[v] = nvtx2++ ;
}
}
}
}
IVfree(mark) ;
IVfree(chksum) ;
#if MYDEBUG > 0
fprintf(stdout, "\n final map") ;
IVfp80(stdout, nvtx, eqmap, 80, &ierr) ;
fflush(stdout) ;
#endif
return(eqmapIV) ; }
/*--------------------------------------------------------------------*/
Graph/src/expand.c 0100644 0002055 0007177 00000010302 06534106104 0015337 0 ustar 00cleve compmath 0000040 0000006 /* expand.c */
#include "../Graph.h"
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
purpose -- take a Graph object and a map to expand it, create and
return a bigger unit weight Graph object. this is useful
for expanding a compressed graph into a unit weight graph.
created -- 96mar02, cca
---------------------------------------------------------------------
*/
Graph *
Graph_expand2 (
Graph *g,
IV *mapIV
) {
/*
---------------
check the input
---------------
*/
if ( g == NULL
|| g->nvtx <= 0
|| mapIV == NULL
|| IV_entries(mapIV) == NULL ) {
fprintf(stderr, "\n fatal error in Graph_expand2(%p,%p)"
"\n bad input\n", g, mapIV) ;
exit(-1) ;
}
return(Graph_expand(g, IV_size(mapIV), IV_entries(mapIV))) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
purpose -- take a Graph object and a map to expand it, create and
return a bigger unit weight Graph object. this is useful
for expanding a compressed graph into a unit weight graph.
created -- 96mar02, cca
---------------------------------------------------------------------
*/
Graph *
Graph_expand (
Graph *g,
int nvtxbig,
int map[]
) {
Graph *gbig ;
int count, ii, nedge, nvtx, v, vbig, vsize, w ;
int *head, *indices, *link, *mark, *vadj ;
IVL *adjIVL, *adjbigIVL ;
/*
---------------
check the input
---------------
*/
if ( g == NULL || nvtxbig <= 0 || map == NULL ) {
fprintf(stderr, "\n fatal error in Graph_expand(%p,%d,%p)"
"\n bad input\n", g, nvtxbig, map) ;
exit(-1) ;
}
nvtx = g->nvtx ;
adjIVL = g->adjIVL ;
/*
----------------------------------------
set up the linked lists for the vertices
----------------------------------------
*/
head = IVinit(nvtx, -1) ;
link = IVinit(nvtxbig, -1) ;
for ( vbig = 0 ; vbig < nvtxbig ; vbig++ ) {
v = map[vbig] ;
link[vbig] = head[v] ;
head[v] = vbig ;
}
/*
--------------------------------
create the expanded Graph object
--------------------------------
*/
gbig = Graph_new() ;
Graph_init1(gbig, 0, nvtxbig, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ;
adjbigIVL = gbig->adjIVL ;
/*
-------------------------------------------
fill the lists in the expanded Graph object
-------------------------------------------
*/
indices = IVinit(nvtxbig, -1) ;
mark = IVinit(nvtx, -1) ;
nedge = 0 ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( head[v] != -1 ) {
/*
------------------------------
load the indices that map to v
------------------------------
*/
mark[v] = v ;
count = 0 ;
for ( vbig = head[v] ; vbig != -1 ; vbig = link[vbig] ) {
indices[count++] = vbig ;
}
/*
---------------------------------------------------
load the indices that map to vertices adjacent to v
---------------------------------------------------
*/
IVL_listAndSize(adjIVL, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w < nvtx && mark[w] != v ) {
mark[w] = v ;
for ( vbig = head[w] ; vbig != -1 ; vbig = link[vbig] ) {
indices[count++] = vbig ;
}
}
}
/*
--------------------------------------
sort the index list in ascending order
--------------------------------------
*/
IVqsortUp(count, indices) ;
/*
-------------------------------------------------------
each vertex in the big IVL object has its own list.
-------------------------------------------------------
*/
for ( vbig = head[v] ; vbig != -1 ; vbig = link[vbig] ) {
IVL_setList(adjbigIVL, vbig, count, indices) ;
nedge += count ;
}
}
}
gbig->nedges = nedge ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(head) ;
IVfree(link) ;
IVfree(indices) ;
IVfree(mark) ;
return(gbig) ; }
/*--------------------------------------------------------------------*/
mapIV) == NULL ) {
fprintf(stderr, "\n fatal error in Graph_expand2(%p,%p)"
"\n bad input\n", g, mapIV) ;
exit(-1) ;
}
return(Graph_expand(g, IV_size(mapIV), IV_entries(mapIV))) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------Graph/src/fillFromOffsets.c 0100644 0002055 0007177 00000013234 06540020157 0017173 0 ustar 00cleve compmath 0000040 0000006 /* fillFromOffsets.c */
#include "../Graph.h"
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
purpose -- take an adjacency structure in the
(offsets[neqns+1], adjncy[*]) form
and load the Graph object
g -- pointer to Graph object, must be initialized with nvtx = neqns
neqns -- # of equations
offsets -- offsets vector
adjncy -- big adjacency vector
note, the adjacency for list v is found in
adjncy[offsets[v]:offsets[v+1]-1]
also note, offsets[] and adjncy[] must be zero based,
if (offsets,adjncy) come from a harwell-boeing file, they use
the fortran numbering, so each value must be decremented to
conform with C's zero based numbering
flag -- task flag
flag = 0 --> just set the adjacency list for v to be that
found in adjncy[offsets[v]:offsets[v+1]-1]
flag = 1 --> the input adjancency is just the upper triangle
(or strict upper triangle) as from a harwell-boeing
file. fill the Graph object with the full adjacency
structure, including (v,v) edges
created -- 96mar16, cca
-------------------------------------------------------------------
*/
void
Graph_fillFromOffsets (
Graph *g,
int neqns,
int offsets[],
int adjncy[],
int flag
) {
IVL *adjIVL ;
/*
---------------
check the input
---------------
*/
if ( g == NULL
|| neqns <= 0
|| offsets == NULL
|| adjncy == NULL
|| flag < 0
|| flag > 1 ) {
fprintf(stderr,
"\n fatal error in Graph_fillFromOffsets(%p,%d,%p,%p,%d)"
"\n bad input\n", g, neqns, offsets, adjncy, flag) ;
exit(-1) ;
}
/*
---------------------------
initialize the Graph object
---------------------------
*/
Graph_init1(g, 0, neqns, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ;
adjIVL = g->adjIVL ;
if ( flag == 0 ) {
int count, ii, nedge, v, w ;
int *list, *mark ;
/*
----------------------------------------------
simple map, do not enforce symmetric structure
----------------------------------------------
*/
list = IVinit(neqns, -1) ;
mark = IVinit(neqns, -1) ;
for ( v = 0, nedge = 0 ; v < neqns ; v++ ) {
count = 0 ;
for ( ii = offsets[v] ; ii < offsets[v+1] ; ii++ ) {
w = adjncy[ii] ;
if ( v == neqns ) {
fprintf(stdout, "\n hey there!! (v,w) = (%d,%d)", v, w) ;
}
if ( 0 <= w && w < neqns && mark[w] != v ) {
list[count++] = w ;
mark[w] = v ;
}
}
if ( mark[v] != v ) {
list[count++] = v ;
mark[v] = v ;
}
IVqsortUp(count, list) ;
IVL_setList(adjIVL, v, count, list) ;
nedge += count ;
}
g->totvwght = neqns ;
g->totewght = g->nedges = nedge ;
/*
----------------------------
now free the working storage
----------------------------
*/
IVfree(list) ;
IVfree(mark) ;
} else {
int ii, jj, u, v, vsize, w ;
int *head, *link, *list, *sizes, *vadj ;
int **p_adj ;
/*
-------------------------------------------
enforce symmetric structure and (v,v) edges
make a first pass to check the input
-------------------------------------------
*/
fprintf(stdout, "\n offsets") ;
IVfprintf(stdout, neqns+1, offsets) ;
for ( v = 0 ; v < neqns ; v++ ) {
fprintf(stdout, "\n v = %d", v) ;
for ( ii = offsets[v] ; ii < offsets[v+1] ; ii++ ) {
fprintf(stdout, "\n w = %d", adjncy[ii]) ;
if ( (w = adjncy[ii]) < v || neqns <= w ) {
fprintf(stderr,
"\n fatal error in Graph_fillFromOffsets(%p,%d,%p,%p,%d)"
"\n list %d, entry %d\n", g, neqns, offsets, adjncy,
flag, v, w) ;
exit(-1) ;
}
}
}
head = IVinit(neqns, -1) ;
link = IVinit(neqns, -1) ;
list = IVinit(neqns, -1) ;
sizes = IVinit(neqns, 0) ;
p_adj = PIVinit(neqns) ;
for ( v = 0 ; v < neqns ; v++ ) {
vsize = 0 ;
/*
-------------------------
add edges to vertices < v
-------------------------
*/
while ( (u = head[v]) != -1 ) {
head[v] = link[u] ;
list[vsize++] = u ;
if ( --sizes[u] > 0 ) {
w = *(++p_adj[u]) ;
link[u] = head[w] ;
head[w] = u ;
}
}
/*
-----------------
add in edge (v,v)
-----------------
*/
list[vsize++] = v ;
jj = vsize ;
/*
-------------------------
add edges to vertices > v
-------------------------
*/
for ( ii = offsets[v] ; ii < offsets[v+1] ; ii++ ) {
if ( (w = adjncy[ii]) != v ) {
list[vsize++] = w ;
}
}
/*
---------------------
sort and set the list
---------------------
*/
IVqsortUp(vsize, list) ;
IVL_setList(adjIVL, v, vsize, list) ;
/*
--------------------------------------------------
link v to first vertex in its lists greater than v
--------------------------------------------------
*/
if ( jj < vsize ) {
IVL_listAndSize(adjIVL, v, &vsize, &vadj) ;
w = vadj[jj] ;
link[v] = head[w] ;
head[w] = v ;
sizes[v] = vsize - jj ;
p_adj[v] = &vadj[jj] ;
}
g->nedges += vsize ;
}
g->totvwght = neqns ;
g->totewght = g->nedges ;
/*
----------------------------
now free the working storage
----------------------------
*/
IVfree(head) ;
IVfree(link) ;
IVfree(list) ;
IVfree(sizes) ;
PIVfree(p_adj) ;
}
return ; }
/*--------------------------------------------------------------------*/
Graph/src/init.c 0100644 0002055 0007177 00000020467 06534106104 0015040 0 ustar 00cleve compmath 0000040 0000006 /* init.c */
#include "../Graph.h"
#define MYTRACE 0
/*--------------------------------------------------------------------*/
/*
---------------------------------------------
basic initializer for the Graph object
type -- graph type
nvtx -- # of vertices
nvbnd -- # of boundary vertices
nedges -- # of edges
adjType -- IVL type for adjacency object
ewghtType -- IVL type for edge weights object
created -- 95sep27, cca
---------------------------------------------
*/
void
Graph_init1 (
Graph *g,
int type,
int nvtx,
int nvbnd,
int nedges,
int adjType,
int ewghtType
) {
int nvtot ;
#if MYTRACE > 0
fprintf(stdout, "\n just inside Graph_init1(%p,%d,%d,%d,%d,%d,%d)",
g, type, nvtx, nvbnd, nedges, adjType, ewghtType) ;
fflush(stdout) ;
#endif
/*
---------------
check the input
---------------
*/
if ( g == NULL ) {
fprintf(stderr, "\n fatal error in Graph_init1(%p,%d,%d,%d,%d,%d,%d)"
"\n graph is NULL\n",
g, type, nvtx, nvbnd, nedges, adjType, ewghtType) ;
exit(-1) ;
}
if ( type < 0 || type >= 4 ) {
fprintf(stderr, "\n fatal error in Graph_init1(%p,%d,%d,%d,%d,%d,%d)"
"\n invalid type = %d, must be in [0,3]\n",
g, type, nvtx, nvbnd, nedges, adjType, ewghtType, type) ;
exit(-1) ;
}
if ( nvtx <= 0 ) {
fprintf(stderr, "\n fatal error in Graph_init1(%p,%d,%d,%d,%d,%d,%d)"
"\n nvtx = %d, must be positive\n",
g, type, nvtx, nvbnd, nedges, adjType, ewghtType, nvtx) ;
exit(-1) ;
}
if ( nvbnd < 0 ) {
fprintf(stderr, "\n fatal error in Graph_init1(%p,%d,%d,%d,%d,%d,%d)"
"\n nvbnd = %d, must be nonnegative\n",
g, type, nvtx, nvbnd, nedges, adjType, ewghtType, nvbnd) ;
exit(-1) ;
}
if ( nedges < 0 ) {
fprintf(stderr, "\n fatal error in Graph_init1(%p,%d,%d,%d,%d,%d,%d)"
"\n nedges = %d, must be nonnegative\n",
g, type, nvtx, nvbnd, nedges, adjType, ewghtType, nedges) ;
exit(-1) ;
}
#if MYTRACE > 0
fprintf(stdout, "\n input checks out") ;
fflush(stdout) ;
#endif
switch ( adjType ) {
case IVL_CHUNKED :
case IVL_SOLO :
case IVL_UNKNOWN :
break ;
default :
fprintf(stderr, "\n fatal error in Graph_init1(%p,%d,%d,%d,%d,%d,%d)"
"\n invalid adjType = %d\n",
g, type, nvtx, nvbnd, nedges, adjType, ewghtType, adjType) ;
exit(-1) ;
}
switch ( ewghtType ) {
case IVL_CHUNKED :
case IVL_SOLO :
case IVL_UNKNOWN :
break ;
default :
fprintf(stderr, "\n fatal error in Graph_init1(%p,%d,%d,%d,%d,%d,%d)"
"\n invalid ewghtType = %d\n",
g, type, nvtx, nvbnd, nedges, adjType, ewghtType, ewghtType) ;
exit(-1) ;
}
/*
-------------------------
clear the data structures
-------------------------
*/
Graph_clearData(g) ;
/*
---------------------
set the scalar fields
---------------------
*/
g->type = type ;
g->nvtx = nvtx ;
g->nvbnd = nvbnd ;
g->nedges = nedges ;
nvtot = nvtx + nvbnd ;
/*
----------------------------
set the adjacency IVL object
----------------------------
*/
g->adjIVL = IVL_new() ;
if ( nedges == 0 || adjType == IVL_UNKNOWN ) {
IVL_init1(g->adjIVL, adjType, nvtot) ;
} else {
IVL_init2(g->adjIVL, adjType, nvtot, nedges) ;
}
if ( type % 2 == 1 ) {
/*
-----------------------------
set the vertex weights vector
-----------------------------
*/
g->vwghts = IVinit(nvtot, 0) ;
}
if ( type >= 2 ) {
/*
-------------------------------
set the edge weights IVL object
-------------------------------
*/
g->ewghtIVL = IVL_new() ;
if ( nedges == 0 || ewghtType == IVL_UNKNOWN ) {
IVL_init1(g->ewghtIVL, ewghtType, nvtot) ;
} else {
IVL_init2(g->ewghtIVL, ewghtType, nvtot, nedges) ;
}
}
#if MYTRACE > 0
fprintf(stdout, "\n leaving Graph_init1(%p,%d,%d,%d,%d,%d,%d)",
g, type, nvtx, nvbnd, nedges, adjType, ewghtType) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------
second initializer for the Graph object.
this function is used in the I/O routines
Graph_readFromFormattedFile(Graph *g, FILE *fp) and
Graph_readFromBinaryFile(Graph *g, FILE *fp) where
the IVL object(s) and vwghts[] vector are created
independently.
type -- graph type
nvtx -- # of vertices
nvbnd -- # of boundary vertices
nedges -- # of edges
totvwght -- total vertex weight
totewght -- total edge weight
adjIVL -- IVL object for adjacency structure
vwghts -- pointer to integer vector for vertex weights
ewghtIVL -- IVL object for edge weights
created -- 95sep27, cca
--------------------------------------------------------
*/
void
Graph_init2 (
Graph *g,
int type,
int nvtx,
int nvbnd,
int nedges,
int totvwght,
int totewght,
IVL *adjIVL,
int *vwghts,
IVL *ewghtIVL
) {
#if MYTRACE > 0
fprintf(stdout,
"\n just inside Graph_init2(%p,%d,%d,%d,%d,%d,%d,%p,%p,%p)",
g, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL) ;
fflush(stdout) ;
#endif
/*
---------------
check the input
---------------
*/
if ( g == NULL ) {
fprintf(stdout,
"\n fatal error in Graph_init2(%p,%d,%d,%d,%d,%d,%d,%p,%p,%p)"
"\n graph is NULL\n",
g, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL) ;
exit(-1) ;
}
if ( type < 0 || type >= 4 ) {
fprintf(stdout,
"\n fatal error in Graph_init2(%p,%d,%d,%d,%d,%d,%d,%p,%p,%p)"
"\n invalid type = %d, must be in [0,3]\n",
g, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL, type) ;
exit(-1) ;
}
if ( nvtx <= 0 ) {
fprintf(stdout,
"\n fatal error in Graph_init2(%p,%d,%d,%d,%d,%d,%d,%p,%p,%p)"
"\n nvtx = %d, must be positive\n",
g, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL, nvtx) ;
exit(-1) ;
}
if ( nvbnd < 0 ) {
fprintf(stdout,
"\n fatal error in Graph_init2(%p,%d,%d,%d,%d,%d,%d,%p,%p,%p)"
"\n nvbnd = %d, must be nonnegative\n",
g, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL, nvbnd) ;
exit(-1) ;
}
if ( nedges < 0 ) {
fprintf(stdout,
"\n fatal error in Graph_init2(%p,%d,%d,%d,%d,%d,%d,%p,%p,%p)"
"\n nedges = %d, must be nonnegative\n",
g, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL, nedges) ;
exit(-1) ;
}
if ( adjIVL == NULL ) {
fprintf(stdout,
"\n fatal error in Graph_init2(%p,%d,%d,%d,%d,%d,%d,%p,%p,%p)"
"\n adjIVL is NULL\n",
g, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL) ;
exit(-1) ;
}
if ( (type % 2 == 1) && (vwghts == NULL) ) {
fprintf(stdout,
"\n fatal error in Graph_init2(%p,%d,%d,%d,%d,%d,%d,%p,%p,%p)"
"\n type = %d, vwghts is NULL",
g, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL, type) ;
exit(-1) ;
}
if ( (type >= 2) && (ewghtIVL == NULL) ) {
fprintf(stdout,
"\n fatal error in Graph_init2(%p,%d,%d,%d,%d,%d,%d,%p,%p,%p)"
"\n type = %d, ewghtIVL is NULL",
g, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL, type) ;
exit(-1) ;
}
/*
-------------------------
clear the data structures
-------------------------
*/
Graph_clearData(g) ;
/*
---------------------
set the scalar fields
---------------------
*/
g->type = type ;
g->nvtx = nvtx ;
g->nvbnd = nvbnd ;
g->nedges = nedges ;
g->totvwght = totvwght ;
g->totewght = totewght ;
/*
---------------------------------------------
set the IVL objects and vertex weights vector
---------------------------------------------
*/
g->adjIVL = adjIVL ;
if ( type % 2 == 1 ) {
g->vwghts = vwghts ;
}
if ( type >= 2 ) {
g->ewghtIVL = ewghtIVL ;
}
#if MYTRACE > 0
fprintf(stdout,
"\n leaving Graph_init2(%p,%d,%d,%d,%d,%d,%d,%p,%p,%p)"
"\n type = %d, ewghtIVL is NULL",
g, type, nvtx, nvbnd, nedges, totvwght, totewght,
adjIVL, vwghts, ewghtIVL, type) ;
fflush(stdout) ;
#endif
return ; }
/*--------------------------------------------------------------------*/
Graph/src/setListsFromOffsets.c 0100644 0002055 0007177 00000004066 06534106104 0020062 0 ustar 00cleve compmath 0000040 0000006 /* setListsFromOffsets.c */
#include "../Graph.h"
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
purpose --
take an adjacency structure in the (offsets[neqns+1], adjncy[*])
form and load the Graph object. note, pointers to the lists are
set, no new storage is allocated for the adjacency lists.
however, during the ordering process each adjacency lists
may be shuffled.
g -- pointer to Graph object,
must be initialized with nvtx = neqns
neqns -- # of equations
offsets -- offsets vector
adjncy -- big adjacency vector
note, the adjacency for list v is found in
adjncy[offsets[v]:offsets[v+1]-1]
also note, offsets[] and adjncy[] must be zero based,
if (offsets,adjncy) come from a harwell-boeing file, they use
the fortran numbering, so each value must be decremented to
conform with C's zero based numbering
created -- 96oct24, cca
-------------------------------------------------------------------
*/
void
Graph_setListsFromOffsets (
Graph *g,
int neqns,
int offsets[],
int adjncy[]
) {
int v, vsize ;
IVL *adjIVL ;
/*
---------------
check the input
---------------
*/
if ( g == NULL
|| neqns <= 0
|| offsets == NULL
|| adjncy == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_setListsFromOffsets(%p,%d,%p,%p)"
"\n bad input\n", g, neqns, offsets, adjncy) ;
exit(-1) ;
}
/*
---------------------------
initialize the Graph object
---------------------------
*/
Graph_init1(g, 0, neqns, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ;
adjIVL = g->adjIVL ;
/*
-----------------------------
set the pointers to the lists
-----------------------------
*/
for ( v = 0 ; v < neqns ; v++ ) {
if ( (vsize = offsets[v+1] - offsets[v]) > 0 ) {
IVL_setPointerToList(adjIVL, v, vsize, &adjncy[offsets[v]]) ;
}
}
return ; }
/*--------------------------------------------------------------------*/
Graph/src/util.c 0100644 0002055 0007177 00000031150 06534106104 0015041 0 ustar 00cleve compmath 0000040 0000006 /* util.c */
#include "../Graph.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
return the external degree (in terms of vertex weight) of vertex v
created -- 95oct05, cca
---------------------------------------------------------------------
*/
int
Graph_externalDegree (
Graph *g,
int v
) {
int ii, vsize, w, weight ;
int *vadj, *vwghts ;
/*
---------------
check the input
---------------
*/
if ( g == NULL || v < 0 || g->nvtx + g->nvbnd <= v ) {
fprintf(stderr, "\n fatal error in Graph_externalDegree(%p,%d)"
"\n bad input\n", g, v) ;
exit(-1) ;
}
vwghts = g->vwghts ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0, weight = 0 ; ii < vsize ; ii++ ) {
if ( (w = vadj[ii]) != v ) {
weight += (vwghts != NULL) ? vwghts[w] : 1 ;
}
}
return(weight) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------
method to access the adjacency list
created -- 95oct05, cca
-----------------------------------
*/
void
Graph_adjAndSize (
Graph *g,
int jvtx,
int *psize,
int **padj
) {
/*
---------------
check the input
---------------
*/
if ( g == NULL || jvtx < 0 || g->nvtx + g->nvbnd <= jvtx
|| psize == NULL || padj == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_adjAndSize(%p,%d,%p,%p)"
"\n bad input\n", g, jvtx, psize, padj) ;
exit(-1) ;
}
if ( g->adjIVL == NULL ) {
fprintf(stderr, "\n fatal error in Graph_adjAndSize(%p,%d,%p,%p)"
"\n g->adjIVL == NULL\n", g, jvtx, psize, padj) ;
exit(-1) ;
}
IVL_listAndSize(g->adjIVL, jvtx, psize, padj) ;
/*
here is fast code but not safe code
*/
/*
*psize = g->adjIVL->sizes[jvtx] ;
*padj = g->adjIVL->p_vec[jvtx] ;
*/
return ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------
method to access the adjacency list
and possibly the edge weight list for a vertex.
created -- 95sep29, cca
-----------------------------------------------
*/
void
Graph_adjAndEweights (
Graph *g,
int jvtx,
int *psize,
int **padj,
int **pewghts
) {
/*
---------------
check the input
---------------
*/
if ( g == NULL || jvtx < 0 || g->nvtx + g->nvbnd <= jvtx
|| psize == NULL || padj == NULL || pewghts == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_adjAndEwghts(%p,%d,%p,%p,%p)"
"\n bad input\n",
g, jvtx, psize, padj, pewghts) ;
exit(-1) ;
}
if ( g->adjIVL == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_adjAndEwghts(%p,%d,%p,%p,%p)"
"\n g->adjIVL == NULL\n",
g, jvtx, psize, padj, pewghts) ;
exit(-1) ;
}
if ( g->type >= 2 && g->ewghtIVL == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_adjAndEwghts(%p,%d,%p,%p,%p)"
"\n g->type = %d and g->ewghtIVL == NULL\n",
g, jvtx, psize, padj, pewghts, g->type) ;
exit(-1) ;
}
IVL_listAndSize(g->adjIVL, jvtx, psize, padj) ;
if ( g->type >= 2 ) {
IVL_listAndSize(g->ewghtIVL, jvtx, psize, pewghts) ;
} else {
*pewghts = NULL ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------------------
return the number of bytes taken by the Graph object
created -- 95oct05, cca
----------------------------------------------------
*/
int
Graph_sizeOf (
Graph *g
) {
int nbytes ;
/*
---------------
check the input
---------------
*/
if ( g == NULL ) {
fprintf(stderr, "\n fatal error in Graph_sizeOf(%p)"
"\n bad input\n", g) ;
exit(-1) ;
}
nbytes = sizeof(struct _Graph) ;
if ( g->vwghts != NULL ) {
nbytes += (g->nvtx + g->nvbnd)*sizeof(int) ;
}
if ( g->adjIVL != NULL ) {
nbytes += IVL_sizeOf(g->adjIVL) ;
}
if ( g->ewghtIVL != NULL ) {
nbytes += IVL_sizeOf(g->ewghtIVL) ;
}
return(nbytes) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------
create and return an IV object filled
with a map from vertices to components
created -- 96feb25, cca
--------------------------------------
*/
IV *
Graph_componentMap (
Graph *g
) {
int ii, last, ncomp, now, nvtx, u, usize, v, w ;
int *list, *map, *uadj ;
IV *mapIV ;
/*
---------------
check the input
---------------
*/
if ( g == NULL ) {
fprintf(stderr, "\n fatal error in Graph_componentMap(%p)"
"\n bad input\n", g) ;
exit(-1) ;
}
if ( (nvtx = g->nvtx) <= 0 ) {
return(NULL) ;
}
mapIV = IV_new() ;
IV_init(mapIV, nvtx, NULL) ;
map = IV_entries(mapIV) ;
list = IVinit(nvtx, -1) ;
for ( v = 0, ncomp = 0 ; v < nvtx ; v++ ) {
if ( map[v] == -1 ) {
/*
-------------------------------
seed vertex for a new component
-------------------------------
*/
map[v] = ncomp ;
now = last = 0 ;
list[0] = v ;
while ( now <= last ) {
u = list[now++] ;
Graph_adjAndSize(g, u, &usize, &uadj) ;
for ( ii = 0 ; ii < usize ; ii++ ) {
w = uadj[ii] ;
if ( map[w] == -1 ) {
/*
------------------
add w to component
------------------
*/
list[++last] = w ;
map[w] = ncomp ;
}
}
}
ncomp++ ;
}
}
IVfree(list) ;
return(mapIV) ; }
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------------
given a Graph g and map from vertices to components,
fill counts[icomp] with the number of vertices in component icomp
and fill weight[icomp] with their weight
created -- 96feb25, cca
-----------------------------------------------------------------
*/
void
Graph_componentStats (
Graph *g,
int map[],
int counts[],
int weights[]
) {
int ncomp, nvtx, v, vcomp ;
int *vwghts ;
/*
---------------
check the input
---------------
*/
if ( g == NULL || map == NULL || counts == NULL || weights == NULL ) {
fprintf(stderr, "\n fatal error in Graph_componentStats(%p,%p,%p,%p)"
"\n bad input\n", g, map, counts, weights) ;
exit(-1) ;
}
/*
--------------------
fill the two vectors
--------------------
*/
nvtx = g->nvtx ;
ncomp = 1 + IVmax(nvtx, map, &v) ;
if ( (vwghts = g->vwghts) != NULL ) {
for ( v = 0 ; v < nvtx ; v++ ) {
vcomp = map[v] ;
counts[vcomp]++ ;
weights[vcomp] += vwghts[v] ;
}
} else {
for ( v = 0 ; v < nvtx ; v++ ) {
vcomp = map[v] ;
counts[vcomp]++ ;
}
IVcopy(ncomp, weights, counts) ;
}
return ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------------------
create and return a subgraph and a map from
its vertices to the vertices of the graph.
g -- graph from which to extract the subgraph
icomp -- component from which comes the vertices of the subgraph,
icomp > 0
compids -- component ids vector of graph
pmap -- pointer to hold address of map vector, the map from
the subgraph's vertices to the graph's vertices
return value -- pointer to subgraph Graph object
created -- 95nov10, cca
-------------------------------------------------------------------
*/
Graph *
Graph_subGraph (
Graph *g,
int icomp,
int compids[],
int **pmap
) {
Graph *gsub ;
int count, ii, iv, nvbnd, nvbndsub, nvtx, nvtxsub, nvtot, nvtotsub,
v, vsub, vsize, w, wsub ;
int *invmap, *map, *vadj ;
/*
---------------
check the input
---------------
*/
if ( g == NULL || icomp <= 0 || compids == NULL || pmap == NULL ) {
fprintf(stderr, "\n fatal error in Graph_subGraph(%p,%d,%p,%p)"
"\n bad input\n", g, icomp, compids, pmap) ;
exit(-1) ;
}
if ( g->type < 0 || g->type >= 2 ) {
fprintf(stderr, "\n fatal error in Graph_subGraph(%p,%d,%p,%p)"
"\n g->type = 0 or 1 currently supported\n",
g, icomp, compids, pmap) ;
exit(-1) ;
}
nvtx = g->nvtx ;
nvbnd = g->nvbnd ;
nvtot = nvtx + nvbnd ;
/*
------------------------------------------------
generate the map vectors
map : subgraph's vertices to graph's vertices
invmap : graph's vertices to subgraph's vertices
------------------------------------------------
*/
map = IVinit(nvtot, -1) ;
invmap = IVinit(nvtot, -1) ;
for ( v = 0, count = 0 ; v < nvtx ; v++ ) {
if ( compids[v] == icomp ) {
map[count] = v ;
invmap[v] = count++ ;
}
}
nvtxsub = count ;
/*
----------------------------------------------
now get the boundary vertices for the subgraph
----------------------------------------------
*/
for ( iv = 0 ; iv < nvtxsub ; iv++ ) {
v = map[iv] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( w < nvtx ) {
if ( compids[w] == 0 && invmap[w] == -1 ) {
map[count] = w ;
invmap[w] = count++ ;
}
} else if ( invmap[w] == -1 ) {
map[count] = w ;
invmap[w] = count++ ;
}
}
}
nvbndsub = count - nvtxsub;
nvtotsub = count ;
IVqsortUp(nvbndsub, &map[nvtxsub]) ;
for ( ii = nvtxsub ; ii < nvtotsub ; ii++ ) {
v = map[ii] ;
invmap[v] = ii ;
}
/*
-----------------------
initialize the subgraph
-----------------------
*/
gsub = Graph_new() ;
Graph_init1(gsub, g->type, nvtxsub, nvbndsub,
0, IVL_CHUNKED, IVL_UNKNOWN) ;
/*
---------------------------------------------
fill the adjacency structure of the subgraph
note: the pointers of the subgraph point into
the adjacency lists of the parent graph
and the indices are overwritten.
---------------------------------------------
*/
for ( vsub = 0 ; vsub < nvtxsub ; vsub++ ) {
v = map[vsub] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
IVL_setPointerToList(gsub->adjIVL, vsub, vsize, vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
vadj[ii] = invmap[vadj[ii]] ;
}
IVqsortUp(vsize, vadj) ;
}
if ( nvbndsub > 0 ) {
int *ind = IVinit(nvtot, -1) ;
for ( vsub = nvtxsub ; vsub < nvtotsub ; vsub++ ) {
v = map[vsub] ;
Graph_adjAndSize(g, v, &vsize, &vadj) ;
for ( ii = 0, count = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( (wsub = invmap[w]) != -1 ) {
ind[count++] = wsub ;
}
}
IVqsortUp(count, ind) ;
IVL_setList(gsub->adjIVL, vsub, count, ind) ;
}
IVfree(ind) ;
}
/*
---------------------------------
fill vertex weights if applicable
---------------------------------
*/
if ( gsub->type % 2 == 1 ) {
gsub->totvwght = 0 ;
for ( vsub = 0 ; vsub < nvtotsub ; vsub++ ) {
v = map[vsub] ;
gsub->totvwght += g->vwghts[v] ;
gsub->vwghts[vsub] = g->vwghts[v] ;
}
} else {
gsub->totvwght = gsub->nvtx ;
}
/*
----------------------------------------------------------------
free the inverse map, create a new map[] vector the right size,
copy the old map vector into the new and free the old map vector
----------------------------------------------------------------
*/
IVfree(invmap) ;
*pmap = IVinit(nvtotsub, -1) ;
IVcopy(nvtotsub, *pmap, map) ;
IVfree(map) ;
return(gsub) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------
return 1 if the graph is symmetric
return 0 otherwise
created -- 96oct31, cca
----------------------------------
*/
int
Graph_isSymmetric (
Graph *graph
) {
int ii, jj, nvtx, rc, v, vsize, w, wsize ;
int *vadj, *wadj ;
/*
---------------
check the input
---------------
*/
if ( graph == NULL ) {
fprintf(stderr, "\n fatal error in Graph_isSymmetric(%p)"
"\n bad input\n", graph) ;
exit(-1) ;
}
/*
----------------------
loop over the vertices
----------------------
*/
rc = 1 ;
nvtx = graph->nvtx ;
for ( v = 0 ; v < nvtx ; v++ ) {
Graph_adjAndSize(graph, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
Graph_adjAndSize(graph, w, &wsize, &wadj) ;
for ( jj = 0 ; jj < wsize ; jj++ ) {
if ( wadj[jj] == v ) {
break ;
}
}
if ( jj == wsize ) {
fprintf(stdout, "\n edge (%d,%d) present, edge (%d,%d) is not",
v, w, w, v) ;
rc = 0 ;
/*
return(rc) ;
*/
}
}
}
return(rc) ; }
/*--------------------------------------------------------------------*/
g, jvtx, psize, padj, pewghts) ;
exit(-1) ;
}
if ( g->adjIVL == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_adjAndEwghts(%p,%d,%p,%p,%p)"
"\n g->adjIVL == NULL\n",
g, jvtx, psize, padj, pewghts) ;
exit(-1) ;
}
if ( g->type >= 2 && g->ewghtIVL == NULL ) {
fprintf(stderr,
"\n fatal error in Graph_adjAndEwghts(%p,%d,%p,%p,%p)"
Graph/src/wirebasket.c 0100644 0002055 0007177 00000011315 06605241771 0016236 0 ustar 00cleve compmath 0000040 0000006 /* wirebasket.c */
#include "../Graph.h"
#define MYDEBUG 1
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------------
on input
stages[v] = 0 --> vertex is in a domain
stages[v] > 0 --> vertex is in the multisector
this remains true on output, but the stage of a multisector
vertex is equal to the number of different domains that
are found within radius edges from itself
created -- 97jul30, cca
---------------------------------------------------------------------
*/
void
Graph_wirebasketStages (
Graph *graph,
IV *stagesIV,
int radius
) {
int count, idom, ierr, ii, last, ndom, now, nvtx, u, v, vsize, w ;
int *dist, *dmark, *domids, *list, *stages, *vadj, *vmark ;
/*
---------------
check the input
---------------
*/
if ( graph == NULL || stagesIV == NULL || radius < 0 ) {
fprintf(stderr, "\n fatal error in Graph_wirebasketStages(%p,%p,%d)"
"\n bad input\n", graph, stagesIV, radius) ;
exit(-1) ;
}
IV_sizeAndEntries(stagesIV, &nvtx, &stages) ;
if ( nvtx != graph->nvtx || stages == NULL ) {
fprintf(stderr, "\n fatal error in Graph_wirebasketStages(%p,%p,%d)"
"\n stages->nvtx = %d, graph->nvtx = %d, stages = %p\n",
graph, stagesIV, nvtx, radius, graph->nvtx, stages) ;
exit(-1) ;
}
/*
-----------------------------------------------
fill domids[]
domids[v] = -1 --> v is in the multisector
domids[v] != -1 --> v is in domain domids[v]
-----------------------------------------------
*/
domids = IVinit(nvtx, -1) ;
list = IVinit(nvtx, -1) ;
for ( u = 0, ndom = 0 ; u < nvtx ; u++ ) {
#if MYDEBUG > 1
fprintf(stdout, "\n vertex %d, stage %d, domid %d",
u, stages[u], domids[u]) ;
#endif
if ( stages[u] == 0 && domids[u] == -1 ) {
#if MYDEBUG > 1
fprintf(stdout, "\n vertex %d starts domain %d", u, ndom) ;
#endif
list[now = last = 0] = u ;
domids[u] = ndom ;
while ( now <= last ) {
v = list[now++] ;
Graph_adjAndSize(graph, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( stages[w] == 0 && domids[w] == -1 ) {
#if MYDEBUG > 1
fprintf(stdout, "\n adding vertex %d", w) ;
#endif
domids[w] = ndom ;
list[++last] = w ;
}
}
}
ndom++ ;
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n domids") ;
fprintf(stdout, "\n %d", nvtx) ;
IVfp80(stdout, nvtx, domids, 80, &ierr) ;
#endif
/*
--------------------------------------------------------
fill the stages of the multisector vertices based on the
number of different domains that are within radius steps
--------------------------------------------------------
*/
dmark = IVinit(ndom, -1) ;
vmark = IVinit(nvtx, -1) ;
dist = IVinit(nvtx, -1) ;
for ( u = 0 ; u < nvtx ; u++ ) {
if ( stages[u] != 0 ) {
#if MYDEBUG > 1
fprintf(stdout, "\n\n checking out schur vertex %d", u) ;
#endif
list[now = last = 0] = u ;
vmark[u] = u ;
dist[u] = 0 ;
count = 0 ;
while ( now <= last ) {
v = list[now++] ;
Graph_adjAndSize(graph, v, &vsize, &vadj) ;
#if MYDEBUG > 1
fprintf(stdout,
"\n removing vertex %d from list, dist %d",
v, dist[v]) ;
#endif
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
#if MYDEBUG > 1
fprintf(stdout,
"\n adjacent vertex %d, vmark %d, domids %d",
w, vmark[w], domids[w]) ;
#endif
if ( vmark[w] != u ) {
vmark[w] = u ;
if ( (idom = domids[w]) != -1 ) {
if ( dmark[idom] != u ) {
#if MYDEBUG > 1
fprintf(stdout, ", marking domain %d", idom) ;
#endif
dmark[idom] = u ;
count++ ;
}
} else if ( dist[v] < radius - 1 ) {
#if MYDEBUG > 1
fprintf(stdout, ", adding %d to list", w) ;
#endif
dist[w] = dist[v] + 1 ;
list[++last] = w ;
}
}
}
}
stages[u] = count ;
#if MYDEBUG > 1
fprintf(stdout, "\n setting stage of %d to be %d", u, count) ;
#endif
}
}
#if MYDEBUG > 0
fprintf(stdout, "\n stages") ;
fprintf(stdout, "\n %d", nvtx) ;
IVfp80(stdout, nvtx, stages, 80, &ierr) ;
#endif
/*
------------------------
free the working storage
------------------------
*/
IVfree(domids) ;
IVfree(list) ;
IVfree(dmark) ;
IVfree(vmark) ;
IVfree(dist) ;
return ; }
/*--------------------------------------------------------------------*/
Graph/drivers/do_checkComponents 0100755 0002055 0007177 00000000400 06574270573 0020354 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inFile = $matrices/$matrix/orig0.graphf
set inFile = /local1/ARPA/matrices/i4a/orig1.graphb
set msglvl = 1
set msgFile = stdout
checkComponents $msglvl $msgFile $inFile
Graph/drivers/do_compressGraph 0100755 0002055 0007177 00000001332 06574266312 0020047 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set matrices = ../../../matrices
set matrix = BCELL14
set inGraphFile = $matrices/$matrix/orig0.graphf
set inGraphFile = $matrices/$matrix/orig0.graphb
set inGraphFile = /local1/ARPA/matrices/i4a/orig0.graphb
set coarseType = 1
set outGraphFile = none
set outGraphFile = $matrices/$matrix/orig$coarseType.graphb
set outGraphFile = /local1/ARPA/matrices/i4a/orig1.graphb
set outMapFile = none
set outMapFile = $matrices/$matrix/map$coarseType.ivb
set outMapFile = /local1/ARPA/matrices/i4a/map$coarseType.ivb
set msglvl = 1
set msgFile = stdout
compressGraph $msglvl $msgFile \
$inGraphFile $coarseType $outMapFile $outGraphFile
Graph/drivers/do_expandGraph 0100755 0002055 0007177 00000000551 06542760617 0017477 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = BCSSTK24
set inGraphFile = $matrices/$matrix/orig1.graphf
set outGraphFile = $matrices/$matrix/orig0.graphf
set outGraphFile = none
set inMapFile = $matrices/$matrix/eqmap.ivf
set msglvl = 1
set msgFile = stdout
expandGraph $msglvl $msgFile \
$inGraphFile $inMapFile $outGraphFile
Graph/drivers/do_mkGridGraph 0100755 0002055 0007177 00000000602 06633545331 0017425 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set msglvl = 3
set msgFile = stdout
set stencil = 9
set n1 = 10
set n2 = 1
set n3 = 1
set matrices = ../../Matrices
set matrix = GRD15x15x15
set matrix = GRD7x7x7
set matrices = ../../../matrices
set matrix = TRI10
set outFile = none
set outFile = $matrices/$matrix/orig0.graphf
mkGridGraph $msglvl $msgFile $stencil $n1 $n2 $n3 $outFile
Graph/drivers/do_testChacoIO 0100755 0002055 0007177 00000000637 06616661622 0017406 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set matrices = ../../../matrices
set matrix = metisExample
set matrix = kartik
set inFile = $matrices/$matrix/graph11.metis
set inFile = $matrices/$matrix/kartik.chaco
set outFile = $matrices/$matrix/orig0.graphb
set outFile = none
set msglvl = 5
set msgFile = stdout
testChacoIO $msglvl $msgFile $inFile $outFile
Graph/drivers/do_testIO 0100755 0002055 0007177 00000000621 06545170200 0016425 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inFile = $matrices/$matrix/orig0.graphf
set outFile = $matrices/$matrix/orig0.graphb
set outFile = none
set matrix = BCSSTK24
set inFile = $matrices/$matrix/orig1.graphb
set outFile = $matrices/$matrix/orig1.graphf
set outFile = none
set msglvl = 1
set msgFile = stdout
testIO $msglvl $msgFile $inFile $outFile
Graph/drivers/do_testIsSymmetric 0100755 0002055 0007177 00000000314 06545170206 0020373 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = BCSSTK24
set msglvl = 3
set msgFile = stdout
set inFile = $matrices/$matrix/orig1.graphf
testIsSymmetric $msglvl $msgFile $inFile
Graph/drivers/do_testWirebasket 0100755 0002055 0007177 00000001377 06605240620 0020230 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = BCSSTK24
set matrices = ../../../matrices
set matrix = R10KV
set msglvl = 1
set msgFile = stdout
set inGraphFile = $matrices/$matrix/orig1.graphf
set inGraphFile = $matrices/$matrix/orig0.graphf
set inGraphFile = $matrices/$matrix/orig0.graphb
set inStagesFile = $matrices/$matrix/bkl.ivf
set inStagesFile = $matrices/$matrix/ddstages0.ivf
set inStagesFile = $matrices/$matrix/fishnet.ivf
set inStagesFile = $matrices/$matrix/ndms.ivf
set outStagesFile = $matrices/$matrix/stages.ivf
set outStagesFile = none
set radius = 2
set outStagesFile = $matrices/$matrix/wirebasket$radius.ivf
testWirebasket $msglvl $msgFile \
$inGraphFile $inStagesFile $outStagesFile $radius
Graph/drivers/do_writeMetisFile 0100755 0002055 0007177 00000000455 06545170231 0020163 0 ustar 00cleve compmath 0000040 0000006 #! /bin/csh -f
set matrices = ../../Matrices
set matrix = R2D100
set inFile = $matrices/$matrix/orig0.graphf
set outFile = $matrices/$matrix/metis.graph
set outFile = metis.graph
set outFile = none
set msglvl = 3
set msgFile = stdout
writeMetisFile $msglvl $msgFile $inFile $outFile
Graph/drivers/makefile 0100644 0002055 0007177 00000002631 06653142473 0016324 0 ustar 00cleve compmath 0000040 0000006 include ../../Make.inc
#-----------------------------------------------------------------------
LIBS = ../../spooles.a -lm
DRIVERS = checkComponents \
compressGraph \
expandGraph \
mkGridGraph \
testIO \
testIsSymmetric \
testWirebasket\
writeMetisFile
drivers : ${DRIVERS}
clean :
- rm -f *.a *.o ${DRIVERS}
checkComponents : checkComponents.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
compressGraph : compressGraph.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
expandGraph : expandGraph.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
mkGridGraph : mkGridGraph.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testChacoIO : testChacoIO.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testIO : testIO.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testIsSymmetric : testIsSymmetric.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
testWirebasket : testWirebasket.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
writeMetisFile : writeMetisFile.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
writeAIJ : writeAIJ.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
ckComponents.o ../../spooles.a
${PURIFY} ${CC} $@.o -o $@ $(PURIFY_GCC_VERSION) ${LIBS}
compressGraphGraph/drivers/checkComponents.c 0100644 0002055 0007177 00000006416 06540263722 0020114 0 ustar 00cleve compmath 0000040 0000006 /* checkComponents.c */
#include "../Graph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
--------------------------------------------------
read in a Graph and check for connected components
created -- 96fmar02, cca
--------------------------------------------------
*/
{
char *inGraphFileName ;
double t1, t2 ;
int icomp, msglvl, ncomp, rc, v ;
int *counts, *weights ;
IV *mapIV ;
Graph *g ;
FILE *msgFile ;
if ( argc != 4 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n",
argv[0], msglvl, argv[2], inGraphFileName) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
g = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(g, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, g, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(g, msgFile) ;
} else {
Graph_writeStats(g, msgFile) ;
}
fflush(msgFile) ;
/*
---------------------------------------
get the map from vertices to components
---------------------------------------
*/
MARKTIME(t1) ;
mapIV = Graph_componentMap(g) ;
MARKTIME(t2) ;
ncomp = 1 + IV_max(mapIV) ;
fprintf(msgFile, "\n CPU %9.5f : find %d components",
t2 - t1, ncomp) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n component map") ;
IV_writeForHumanEye(mapIV, msgFile) ;
}
/*
------------------------------------
get the statistics on the components
------------------------------------
*/
counts = IVinit(ncomp, 0) ;
weights = IVinit(ncomp, 0) ;
MARKTIME(t1) ;
Graph_componentStats(g, IV_entries(mapIV), counts, weights) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : compute component statistics",
t2 - t1) ;
fprintf(msgFile, "\n\n component # vertices weight") ;
for ( icomp = 0 ; icomp < ncomp ; icomp++ ) {
fprintf(msgFile, "\n %7d %7d %7d",
icomp, counts[icomp], weights[icomp]) ;
}
/*
----------------
free the storage
----------------
*/
Graph_free(g) ;
IV_free(mapIV) ;
IVfree(counts) ;
IVfree(weights) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
Graph/drivers/compressGraph.c 0100644 0002055 0007177 00000011461 06540264107 0017600 0 ustar 00cleve compmath 0000040 0000006 /* compressGraph.c */
#include "../Graph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------
1) read in graph
2) get the equivalence map
3) optionally write out equivalence map
4) get compressed graph
5) optionally write out compressed graph map
created -- 95mar02, cca
-------------------------------------------------
*/
{
char *inGraphFileName, *outIVfileName, *outGraphFileName ;
double t1, t2 ;
int coarseType, msglvl, rc ;
Graph *gc, *gf ;
FILE *msgFile ;
IV *mapIV ;
if ( argc != 7 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile "
"\n coarseType outMapFile outGraphFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file for graph"
"\n must be *.graphf or *.graphb"
"\n coarseType -- type for compressed graph"
"\n outMapFile -- output file for map vector"
"\n must be *.ivf or *.ivb"
"\n outGraphFile -- output file for compressed graph"
"\n must be *.graphf or *.graphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
coarseType = atoi(argv[4]) ;
outIVfileName = argv[5] ;
outGraphFileName = argv[6] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n coarseType -- %d"
"\n outMapFile -- %s"
"\n outGraphFile -- %s"
"\n",
argv[0], msglvl, argv[2], inGraphFileName,
coarseType, outIVfileName, outGraphFileName) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
gf = Graph_new() ;
rc = Graph_readFromFile(gf, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, gf, inGraphFileName) ;
exit(-1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
Graph_writeForHumanEye(gf, msgFile) ;
fflush(msgFile) ;
} else {
Graph_writeStats(gf, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------
get the equivalence map
-----------------------
*/
MARKTIME(t1) ;
mapIV = Graph_equivMap(gf) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : create equivalence map", t2 - t1) ;
if ( msglvl > 1 ) {
fprintf(msgFile, "\n\n equivalence map IV object") ;
IV_writeForHumanEye(mapIV, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
write out the map IV object
---------------------------
*/
if ( strcmp(outIVfileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = IV_writeToFile(mapIV, outIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write map IV to file %s",
t2 - t1, outIVfileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from IV_writeToFile(%p,%s)",
rc, mapIV, outIVfileName) ;
}
}
/*
------------------------
get the compressed graph
------------------------
*/
MARKTIME(t1) ;
gc = Graph_compress(gf, IV_entries(mapIV), coarseType) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : compress the graph", t2 - t1) ;
fprintf(msgFile, "\n\n compressed graph") ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(gc, msgFile) ;
fflush(msgFile) ;
} else {
Graph_writeStats(gc, msgFile) ;
fflush(msgFile) ;
}
/*
--------------------------
write out the Graph object
--------------------------
*/
if ( strcmp(outGraphFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = Graph_writeToFile(gc, outGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write compressed graph to file %s",
t2 - t1, outGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from Graph_writeToFile(%p,%s)",
rc, gc, outGraphFileName) ;
exit(-1) ;
}
}
/*
----------------
free the objects
----------------
*/
Graph_free(gf) ;
Graph_free(gc) ;
IV_free(mapIV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
Graph/drivers/expandGraph.c 0100644 0002055 0007177 00000011004 06540264356 0017223 0 ustar 00cleve compmath 0000040 0000006 /* expandGraph.c */
#include "../Graph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
------------------------------------------
1) read in graph
2) read in the expand map
4) get expanded graph
5) optionally write out expanded graph map
created -- 95mar02, cca
------------------------------------------
*/
{
char *inGraphFileName, *inIVfileName, *outGraphFileName ;
double t1, t2 ;
int msglvl, rc ;
Graph *gc, *gf ;
FILE *msgFile ;
IV *mapIV ;
if ( argc != 6 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile "
"\n inMapFile outGraphFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file for graph"
"\n must be *.graphf or *.graphb"
"\n inMapFile -- output file for map vector"
"\n must be *.ivf or *.ivb"
"\n outGraphFile -- output file for compressed graph"
"\n must be *.graphf or *.graphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
inIVfileName = argv[4] ;
outGraphFileName = argv[5] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n inMapFile -- %s"
"\n outGraphFile -- %s"
"\n",
argv[0], msglvl, argv[2], inGraphFileName,
inIVfileName, outGraphFileName) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
gc = Graph_new() ;
rc = Graph_readFromFile(gc, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, gc, inGraphFileName) ;
exit(-1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
Graph_writeForHumanEye(gc, msgFile) ;
fflush(msgFile) ;
} else {
Graph_writeStats(gc, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------
read in the IV object
---------------------
*/
if ( strcmp(inIVfileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
MARKTIME(t1) ;
mapIV = IV_new() ;
rc = IV_readFromFile(mapIV, inIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in IV from file %s",
t2 - t1, inIVfileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from IV_readFromFile(%p,%s)",
rc, mapIV, inIVfileName) ;
exit(-1) ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n after reading IV object from file %s",
inIVfileName) ;
IV_writeForHumanEye(mapIV, msgFile) ;
fflush(msgFile) ;
} else {
IV_writeStats(mapIV, msgFile) ;
fflush(msgFile) ;
}
/*
-------------------------
create the expanded graph
-------------------------
*/
MARKTIME(t1) ;
gf = Graph_expand2(gc, mapIV) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : create expanded graph", t2 - t1) ;
fprintf(msgFile, "\n\n expanded Graph object") ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(gf, msgFile) ;
fflush(msgFile) ;
} else {
Graph_writeStats(gf, msgFile) ;
fflush(msgFile) ;
}
/*
-----------------------------------
write out the expanded Graph object
-----------------------------------
*/
if ( strcmp(outGraphFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = Graph_writeToFile(gf, outGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write expanded graph to file %s",
t2 - t1, outGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from Graph_writeToFile(%p,%s)",
rc, gf, outGraphFileName) ;
}
}
/*
----------------
free the objects
----------------
*/
Graph_free(gf) ;
Graph_free(gc) ;
IV_free(mapIV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
Graph/drivers/mkGridGraph.c 0100644 0002055 0007177 00000017773 06540265152 0017177 0 ustar 00cleve compmath 0000040 0000006 /* mkGridGraph.c */
#include "../Graph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------
generate a Graph object for a grid
created -- 96mar15, cca
-------------------------------------------------
*/
{
char *outFileName ;
double t1, t2 ;
FILE *msgFile ;
Graph *graph ;
int count, msglvl, i, ij, ijk, imax, imin, inow,
j, jmax, jmin, jnow, k, kmax, kmin, know,
nvtx, n1, n2, n3, rc, stencil ;
int *list ;
IVL *adjIVL ;
if ( argc != 8 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile stencil n1 n2 n3 outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n stencil -- type of stencil, 5, 9, 27 or 13"
"\n n1 -- # of grid points in first dimension"
"\n n2 -- # of grid points in second dimension"
"\n n3 -- # of grid points in third dimension"
"\n outFile -- output file, must be *.graphf or *.graphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
stencil = atoi(argv[3]) ;
switch ( stencil ) {
case 5 :
case 7 :
case 9 :
case 13 :
case 27 :
break ;
default :
fprintf(stderr, "\n fatal error in mkGridGraph"
"\n stencil = %d, must be 5, 7, 9, 13 or 27\n", stencil) ;
exit(-1) ;
}
n1 = atoi(argv[4]) ;
n2 = atoi(argv[5]) ;
n3 = atoi(argv[6]) ;
if ( n1 < 1 || n2 < 1 || n3 < 1 ) {
fprintf(stderr, "\n fatal error in mkGridGraph"
"\n n1 = %d, n2 = %d, n3 = %d, all must be positive\n",
n1, n2, n3) ;
exit(-1) ;
}
nvtx = n1 * n2 * n3 ;
outFileName = argv[7] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n stencil -- %d"
"\n n1 -- %d"
"\n n2 -- %d"
"\n n3 -- %d"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], stencil, n1, n2, n3, outFileName) ;
fflush(msgFile) ;
/*
----------------------
set the default fields
----------------------
*/
graph = Graph_new() ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n after setting default fields") ;
Graph_writeForHumanEye(graph, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------
initialize the Graph object
---------------------------
*/
Graph_init1(graph, 0, nvtx, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
fflush(msgFile) ;
}
adjIVL = graph->adjIVL ;
list = IVinit(nvtx, -1) ;
switch ( stencil ) {
case 5 :
for ( j = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
ij = i + j * n1 ;
count = 0 ;
if ( j >= 1 ) {
list[count++] = ij - n1 ;
}
if ( i >= 1 ) {
list[count++] = ij - 1 ;
}
/*
list[count++] = ij ;
*/
if ( i <= n1 - 2 ) {
list[count++] = ij + 1 ;
}
if ( j <= n2 - 2 ) {
list[count++] = ij + n1 ;
}
IVqsortUp(count, list) ;
IVL_setList(adjIVL, ij, count, list) ;
}
}
break ;
case 7 :
for ( k = 0 ; k < n3 ; k++ ) {
for ( j = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
ijk = i + j*n1 + k*n1*n2 ;
count = 0 ;
if ( k >= 1 ) {
list[count++] = ijk - n1*n2 ;
}
if ( j >= 1 ) {
list[count++] = ijk - n1 ;
}
if ( i >= 1 ) {
list[count++] = ijk - 1 ;
}
list[count++] = ijk ;
if ( i <= n1 - 2 ) {
list[count++] = ijk + 1 ;
}
if ( j <= n2 - 2 ) {
list[count++] = ijk + n1 ;
}
if ( k <= n3 - 2 ) {
list[count++] = ijk + n1*n2 ;
}
IVqsortUp(count, list) ;
IVL_setList(adjIVL, ijk, count, list) ;
}
}
}
break ;
case 9 :
for ( j = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
ij = i + j * n1 ;
count = 0 ;
if ( j >= 1 ) {
if ( i >= 1 ) {
list[count++] = ij - n1 - 1 ;
}
list[count++] = ij - n1 ;
if ( i <= n1 - 2 ) {
list[count++] = ij - n1 + 1 ;
}
}
if ( i >= 1 ) {
list[count++] = ij - 1 ;
}
list[count++] = ij ;
if ( i <= n1 - 2 ) {
list[count++] = ij + 1 ;
}
if ( j <= n2 - 2 ) {
if ( i >= 1 ) {
list[count++] = ij + n1 - 1 ;
}
list[count++] = ij + n1 ;
if ( i <= n1 - 2 ) {
list[count++] = ij + n1 + 1 ;
}
}
IVqsortUp(count, list) ;
IVL_setList(adjIVL, ij, count, list) ;
}
}
break ;
case 13 :
for ( j = 0 ; j < n2 ; j++ ) {
for ( i = 0 ; i < n1 ; i++ ) {
ij = i + j * n1 ;
count = 0 ;
if ( j >= 2 ) {
list[count++] = ij - 2*n1 ;
}
if ( j >= 1 ) {
if ( i >= 1 ) {
list[count++] = ij - n1 - 1 ;
}
list[count++] = ij - n1 ;
if ( i <= n1 - 2 ) {
list[count++] = ij - n1 + 1 ;
}
}
if ( i >= 2 ) {
list[count++] = ij - 2 ;
}
if ( i >= 1 ) {
list[count++] = ij - 1 ;
}
list[count++] = ij ;
if ( i <= n1 - 2 ) {
list[count++] = ij + 1 ;
}
if ( i <= n1 - 3 ) {
list[count++] = ij + 2 ;
}
if ( j <= n2 - 2 ) {
if ( i >= 1 ) {
list[count++] = ij + n1 - 1 ;
}
list[count++] = ij + n1 ;
if ( i <= n1 - 2 ) {
list[count++] = ij + n1 + 1 ;
}
}
if ( j <= n2 - 3 ) {
list[count++] = ij + 2*n1 ;
}
IVqsortUp(count, list) ;
IVL_setList(adjIVL, ij, count, list) ;
}
}
break ;
case 27 :
for ( k = 0 ; k < n3 ; k++ ) {
kmin = (k > 0) ? k-1 : k ;
kmax = (k < n3-1) ? k+1 : k ;
for ( j = 0 ; j < n2 ; j++ ) {
jmin = (j > 0) ? j-1 : j ;
jmax = (j < n2-1) ? j+1 : j ;
for ( i = 0 ; i < n1 ; i++ ) {
ijk = i + j*n1 + k*n1*n2 ;
imin = (i > 0) ? i-1 : i ;
imax = (i < n1-1) ? i+1 : i ;
for ( know = kmin, count = 0 ; know <= kmax ; know++ ) {
for ( jnow = jmin ; jnow <= jmax ; jnow++ ) {
for ( inow = imin ; inow <= imax ; inow++ ) {
list[count++] = inow + jnow*n1 + know*n1*n2 ;
}
}
}
IVqsortUp(count, list) ;
IVL_setList(adjIVL, ijk, count, list) ;
}
}
}
break ;
default :
break ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n ") ;
Graph_writeForHumanEye(graph, msgFile) ;
}
/*
--------------------------
write out the Graph object
--------------------------
*/
if ( strcmp(outFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = Graph_writeToFile(graph, outFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write graph to file %s",
t2 - t1, outFileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from Graph_writeToFile(%p,%s)",
rc, graph, outFileName) ;
}
}
/*
------------------------
free the working storage
------------------------
*/
Graph_free(graph) ;
IVfree(list) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
ist[cGraph/drivers/test1.c 0100644 0002055 0007177 00000001626 06616653561 0016037 0 ustar 00cleve compmath 0000040 0000006 /* test1.c */
#include
/*--------------------------------------------------------------------*/
int
main (
int argc,
char *argv[]
) {
char ctemp ;
FILE *fp ;
int itemp, rc ;
if ( argc != 2 ) {
fprintf(stdout, "\n usage : filename") ;
return(0) ;
}
if ( (fp = fopen(argv[1], "r")) == NULL ) {
fprintf(stderr, "\n unable to open file %s\n", argv[1]) ;
}
/*
---------------
check the input
---------------
*/
while ( 1 ) {
rc = fscanf(fp, "%d%c", &itemp, &ctemp) ;
if ( rc != 2 ) {
fprintf(stdout, "\n error, rc = %d", rc) ;
break ;
}
fprintf(stdout, "\n itemp = '%d', ctemp = '%c'", itemp, ctemp) ;
if ( ctemp == '\n' ) {
fprintf(stdout, "\n newline") ;
}
if ( ctemp == EOF ) {
fprintf(stdout, "\n end of file") ;
break ;
}
}
return(1) ; }
/*--------------------------------------------------------------------*/
Graph/drivers/testChacoIO.c 0100644 0002055 0007177 00000005711 06616657416 0017146 0 ustar 00cleve compmath 0000040 0000006 /* testChacoIO.c */
#include "../Graph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------
test Graph_readFromChacoFile,
useful for translating between Chaco/Metis files
and formatted *.graphf and binary *.graphb files.
created -- 98oct31, cca
-------------------------------------------------
*/
{
char *inGraphFileName, *outGraphFileName ;
double t1, t2 ;
int msglvl, rc ;
Graph *graph ;
FILE *msgFile ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.graphf or *.graphb"
"\n outFile -- output file, must be *.graphf or *.graphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
outGraphFileName = argv[4] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], inGraphFileName, outGraphFileName) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromChacoFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from Graph_readFromChacoFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
--------------------------
write out the Graph object
--------------------------
*/
if ( strcmp(outGraphFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = Graph_writeToFile(graph, outGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write graph to file %s",
t2 - t1, outGraphFileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_writeToFile(%p,%s)",
rc, graph, outGraphFileName) ;
}
/*
---------------------
free the Graph object
---------------------
*/
Graph_free(graph) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
Graph/drivers/testIO.c 0100644 0002055 0007177 00000005642 06540265330 0016175 0 ustar 00cleve compmath 0000040 0000006 /* testIO.c */
#include "../Graph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------
test Graph_readFromFile and Graph_writeToFile,
useful for translating between formatted *.graphf
and binary *.graphb files.
created -- 96fmar02, cca
-------------------------------------------------
*/
{
char *inGraphFileName, *outGraphFileName ;
double t1, t2 ;
int msglvl, rc ;
Graph *graph ;
FILE *msgFile ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.graphf or *.graphb"
"\n outFile -- output file, must be *.graphf or *.graphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
outGraphFileName = argv[4] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], inGraphFileName, outGraphFileName) ;
fflush(msgFile) ;
/*
----------------------
read in the Graph object
----------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
------------------------
write out the Graph object
------------------------
*/
if ( strcmp(outGraphFileName, "none") != 0 ) {
MARKTIME(t1) ;
rc = Graph_writeToFile(graph, outGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write graph to file %s",
t2 - t1, outGraphFileName) ;
}
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_writeToFile(%p,%s)",
rc, graph, outGraphFileName) ;
}
/*
---------------------
free the Graph object
---------------------
*/
Graph_free(graph) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
Graph/drivers/testIsSymmetric.c 0100644 0002055 0007177 00000004771 06540265441 0020143 0 ustar 00cleve compmath 0000040 0000006 /* testIsSymmetric.c */
#include "../Graph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-----------------------------------------
check to see whether a graph is symmetric
created -- 96oct31, cca
-----------------------------------------
*/
{
char *inGraphFileName ;
double t1, t2 ;
int msglvl, rc ;
Graph *graph ;
FILE *msgFile ;
if ( argc != 4 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile "
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.graphf or *.graphb"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n",
argv[0], msglvl, argv[2], inGraphFileName) ;
fflush(msgFile) ;
/*
----------------------
read in the Graph object
----------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
-------------------------------------------
check to see whether the graph is symmetric
-------------------------------------------
*/
rc = Graph_isSymmetric(graph) ;
if ( rc == 1 ) {
fprintf(msgFile, "\n graph is symmetric") ;
} else {
fprintf(msgFile, "\n graph is not symmetric") ;
}
/*
---------------------
free the Graph object
---------------------
*/
Graph_free(graph) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
Graph/drivers/testWirebasket.c 0100644 0002055 0007177 00000012402 06605242303 0017753 0 ustar 00cleve compmath 0000040 0000006 /* testWirebasket.c */
#include "../Graph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
---------------------------------------------------
read in a Graph and a stages id IV object,
replace the stages IV object with wirebasket stages
created -- 97jul30, cca
---------------------------------------------------
*/
{
char *inCompidsFileName, *inGraphFileName, *outStagesIVfileName ;
double t1, t2 ;
Graph *graph ;
int msglvl, nvtx, radius, rc, v ;
int *compids, *stages ;
IV *compidsIV, *stagesIV ;
FILE *msgFile ;
if ( argc != 7 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inGraphFile inStagesFile "
"\n outStagesFile radius"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inGraphFile -- input file, must be *.graphf or *.graphb"
"\n inStagesFile -- output file, must be *.ivf or *.ivb"
"\n outStagesFile -- output file, must be *.ivf or *.ivb"
"\n radius -- radius to set the stage "
"\n of a separator vertex"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
inCompidsFileName = argv[4] ;
outStagesIVfileName = argv[5] ;
radius = atoi(argv[6]) ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inGraphFile -- %s"
"\n inStagesFile -- %s"
"\n outStagesFile -- %s"
"\n radius -- %d"
"\n",
argv[0], msglvl, argv[2], inGraphFileName, inCompidsFileName,
outStagesIVfileName, radius) ;
fflush(msgFile) ;
/*
------------------------
read in the Graph object
------------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
---------------------
read in the IV object
---------------------
*/
if ( strcmp(inCompidsFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
compidsIV = IV_new() ;
MARKTIME(t1) ;
rc = IV_readFromFile(compidsIV, inCompidsFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in compidsIV from file %s",
t2 - t1, inCompidsFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from IV_readFromFile(%p,%s)",
rc, compidsIV, inCompidsFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading IV object from file %s",
inCompidsFileName) ;
if ( msglvl > 2 ) {
IV_writeForHumanEye(compidsIV, msgFile) ;
} else {
IV_writeStats(compidsIV, msgFile) ;
}
fflush(msgFile) ;
IV_sizeAndEntries(compidsIV, &nvtx, &compids) ;
/*
----------------------------
convert to the stages vector
----------------------------
*/
stagesIV = IV_new() ;
IV_init(stagesIV, nvtx, NULL) ;
stages = IV_entries(stagesIV) ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( compids[v] == 0 ) {
stages[v] = 1 ;
} else {
stages[v] = 0 ;
}
}
/*
for ( v = 0 ; v < nvtx ; v++ ) {
if ( compids[v] == 0 ) {
stages[v] = 0 ;
} else {
stages[v] = 1 ;
}
}
*/
/*
-------------------------
get the wirebasket stages
-------------------------
*/
Graph_wirebasketStages(graph, stagesIV, radius) ;
IV_sizeAndEntries(stagesIV, &nvtx, &stages) ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( stages[v] == 2 ) {
stages[v] = 1 ;
} else if ( stages[v] > 2 ) {
stages[v] = 2 ;
}
}
fprintf(msgFile, "\n\n new stages IV object") ;
if ( msglvl > 2 ) {
IV_writeForHumanEye(stagesIV, msgFile) ;
} else {
IV_writeStats(stagesIV, msgFile) ;
}
fflush(msgFile) ;
/*
---------------------------
write out the stages object
---------------------------
*/
if ( strcmp(outStagesIVfileName, "none") != 0 ) {
MARKTIME(t1) ;
IV_writeToFile(stagesIV, outStagesIVfileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write stagesIV to file %s",
t2 - t1, outStagesIVfileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from IV_writeToFile(%p,%s)",
rc, stagesIV, outStagesIVfileName) ;
}
}
/*
------------------------
free the working storage
------------------------
*/
Graph_free(graph) ;
IV_free(stagesIV) ;
IV_free(compidsIV) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
mp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileNGraph/drivers/writeAIJ.c 0100644 0002055 0007177 00000006656 06632345237 0016461 0 ustar 00cleve compmath 0000040 0000006 /* writeAIJ.c */
#include "../Graph.h"
#include "../../Drand.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------
read in a Graph and write out an AIJ file
nrow ncol nent
row col entry
...
created -- 98dec05, cca
-------------------------------------------------
*/
{
char *inGraphFileName, *outFileName ;
double t1, t2 ;
Drand *drand ;
int ii, msglvl, nedges, nvtx, rc, v, vsize, w ;
int *vadj ;
Graph *graph ;
FILE *msgFile, *outFile ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile outFileName"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.graphf or *.graphb"
"\n outFile -- output file"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
outFileName = argv[4] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], inGraphFileName, outFileName) ;
fflush(msgFile) ;
/*
----------------------
read in the Graph object
----------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
--------------------------------------
initialize the random number generator
--------------------------------------
*/
drand = Drand_new();
Drand_setSeed(drand, 47) ;
Drand_setUniform(drand, -1., 1.) ;
/*
--------------------------
write out the AIJ entries
--------------------------
*/
if ( strcmp(outFileName, "stdout") == 0 ) {
outFile = stdout ;
} else if ( (outFile = fopen(outFileName, "w")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n", argv[0], outFile) ;
return(-1) ;
}
nvtx = graph->nvtx ;
nedges = graph->nedges ;
fprintf(outFile, "\n %d %d %d", nvtx, nvtx, nvtx + (nedges-nvtx)/2) ;
for ( v = 0 ; v < nvtx ; v++ ) {
Graph_adjAndSize(graph, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( v <= w ) {
fprintf(outFile,
"\n %8d %8d %20.12e", v, w, Drand_value(drand)) ;
}
}
}
fclose(outFile) ;
/*
---------------------
free the Graph object
---------------------
*/
Graph_free(graph) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
Graph/drivers/writeMetisFile.c 0100644 0002055 0007177 00000006100 06540266117 0017714 0 ustar 00cleve compmath 0000040 0000006 /* writeMetisFile.c */
#include "../Graph.h"
#include "../../timings.h"
/*--------------------------------------------------------------------*/
int
main ( int argc, char *argv[] )
/*
-------------------------------------------------
read in a graph and write it out as a Metis File
created -- 97apr03, cca
-------------------------------------------------
*/
{
char *inGraphFileName, *outGraphFileName ;
double t1, t2 ;
FILE *fp, *msgFile ;
int msglvl, rc ;
Graph *graph ;
if ( argc != 5 ) {
fprintf(stdout,
"\n\n usage : %s msglvl msgFile inFile outFile"
"\n msglvl -- message level"
"\n msgFile -- message file"
"\n inFile -- input file, must be *.graphf or *.graphb"
"\n outFile -- output file for a metis file"
"\n", argv[0]) ;
return(0) ;
}
msglvl = atoi(argv[1]) ;
if ( strcmp(argv[2], "stdout") == 0 ) {
msgFile = stdout ;
} else if ( (msgFile = fopen(argv[2], "a")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], argv[2]) ;
return(-1) ;
}
inGraphFileName = argv[3] ;
outGraphFileName = argv[4] ;
fprintf(msgFile,
"\n %s "
"\n msglvl -- %d"
"\n msgFile -- %s"
"\n inFile -- %s"
"\n outFile -- %s"
"\n",
argv[0], msglvl, argv[2], inGraphFileName, outGraphFileName) ;
fflush(msgFile) ;
/*
----------------------
read in the Graph object
----------------------
*/
if ( strcmp(inGraphFileName, "none") == 0 ) {
fprintf(msgFile, "\n no file to read from") ;
exit(0) ;
}
graph = Graph_new() ;
MARKTIME(t1) ;
rc = Graph_readFromFile(graph, inGraphFileName) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s",
t2 - t1, inGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)",
rc, graph, inGraphFileName) ;
exit(-1) ;
}
fprintf(msgFile, "\n\n after reading Graph object from file %s",
inGraphFileName) ;
if ( msglvl > 2 ) {
Graph_writeForHumanEye(graph, msgFile) ;
} else {
Graph_writeStats(graph, msgFile) ;
}
fflush(msgFile) ;
/*
--------------------------
write out the Graph object
--------------------------
*/
if ( strcmp(outGraphFileName, "none") != 0 ) {
if ( (fp = fopen(outGraphFileName, "w")) == NULL ) {
fprintf(stderr, "\n fatal error in %s"
"\n unable to open file %s\n",
argv[0], outGraphFileName) ;
return(-1) ;
}
MARKTIME(t1) ;
rc = Graph_writeToMetisFile(graph, fp) ;
MARKTIME(t2) ;
fprintf(msgFile, "\n CPU %9.5f : write graph to file %s",
t2 - t1, outGraphFileName) ;
if ( rc != 1 ) {
fprintf(msgFile,
"\n return value %d from Graph_writeToMetisFile(%p,%s)",
rc, graph, outGraphFileName) ;
}
}
/*
---------------------
free the Graph object
---------------------
*/
Graph_free(graph) ;
fprintf(msgFile, "\n") ;
fclose(msgFile) ;
return(1) ; }
/*--------------------------------------------------------------------*/
Graph/doc/ 0042755 0002055 0007177 00000000000 06542767400 0013716 5 ustar 00cleve compmath 0000040 0000006 Graph/doc/dataStructure.tex 0100644 0002055 0007177 00000001752 06534106105 0017260 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Data Structure}
\label{section:Graph:dataStructure}
\par
The {\tt Graph} structure has nine fields.
\begin{itemize}
\item {\tt int type} : type of graph \qquad
% \begin{center}
\begin{tabular}{|c|c|c|} \hline
{\tt type} & vertices weighted? & edges weighted? \\ \hline
0 & no & no \\
1 & yes & no \\
2 & no & yes \\
3 & yes & yes \\ \hline
\end{tabular}
% \end{center}
\item {\tt int nvtx } : number of internal vertices
\item {\tt int nvbnd } : number of boundary vertices
\item {\tt int nedges } : number of edges
\item {\tt int totvwght } : total vertex weight
\item {\tt int totewght } : total edge weight
\item {\tt IVL *adjIVL} :
pointer to {\tt IVL} object to hold adjacency lists
\item {\tt int *vwghts} : pointer to a vertex to hold vertex weights
non-{\tt NULL} if {\tt type \% 2 == 1}
\item {\tt IVL *ewghtIVL} : pointer to {\tt IVL} object to hold
edge weight lists, non-{\tt NULL} if {\tt type / 2 == 1}
\end{itemize}
Graph/doc/intro.tex 0100644 0002055 0007177 00000007667 06650230161 0015573 0 ustar 00cleve compmath 0000040 0000006 \par
\chapter{{\tt Graph}: A Graph object}
\label{chapter:Graph}
\par
The {\tt Graph} object is used to represent the graph of a matrix.
The representation uses a set of adjacency lists, one edge list for
each vertex in the graph, and is implemented using an {\tt IVL}
object.\footnote{
The {\tt EGraph} object represents a graph of the matrix,
but stores a list of covering cliques in an {\tt IVL} object.
}
For the {\tt Graph} object,
the vertices and the edges can be either unit weight or non-unit
weight independently.
None of the algorithms in the package {\it at present} use weighted
edges, though most use weighted vertices.
The weighted edges capability is there, and the weighted edges are
also stored using an {\tt IVL} object.
\par
The {\tt Graph} object is not too sophisticated, i.e., we chose
{\bf not} to implement a method to find a separator of a graph
inside this object.
Such complex functionality is best left to higher level objects,
and our method based on domain decomposition \cite{ash97-DDSEP}
is found in the {\tt GPart} object.
\par
A graph can also be a subgraph of another graph --- nested dissection
is the natural recursive partition of a graph --- and it pays to
use the knowledge of the boundary of a subgraph.
We chose not to implement a ``sub''-graph object separately from a
graph object, thus our {\tt Graph} object can have a boundary.
One specifies {\tt nvtx}, the number of internal vertices,
and {\tt nvbnd}, the number of external or boundary vertices.
The labels for internal vertices are found in {\tt [0, nvtx)}
and those for boundary vertices are found in {\tt [nvtx, nvtx+nvbnd)}.
\par
It is easy to create a {\tt Graph} object: one specifies the number
of internal and boundary vertices, the type of graph (weighted or
unit weight vertices and edges), and then uses the methods for the
{\tt IVL} object to add adjacency lists and (possibly) lists of edge
weights.
The {\tt Graph} object relies strongly on the {\tt IVL} object.
\par
Weighted graphs are commonly used in partitioning and ordering
algorithm, and they normally arise from {\it compressing} the graph
in some manner.
Let us write the unit weight graph as $G(V,E)$ and the weighted
graph as ${\bf G}({\bf V}, {\bf E})$, and let $\phi : V \mapsto {\bf V}$
be the map from unit weight vertices to weighted vertices.
Let $u$ and $v$ be vertices and $(u,v)$ be an edge in $G(V,E)$,
and let ${\bf u}$ and ${\bf v}$ be vertices
and $({\bf u},{\bf v})$ be an edge in ${\bf G}({\bf V}, {\bf E})$.
The weight of a vertex is $w({\bf u})$, the number of unit weight
vertices in the weighted vertex.
The weight of an edge is
$w({\bf u},{\bf v})$, the number of $(u,v)$ edges in the
unit weight graph where $u \in {\bf u}$ and $v \in {\bf v}$.
\par
The natural compressed graph \cite{ash95-compressed-graphs},
\cite{dam92-compressed}
is very important for many matrices from structral
analysis and computational fluid mechanics.
This type of graph has one special property:
$$
w({\bf u}, {\bf v}) = w({\bf u}) \cdot w({\bf v})
$$
and it is the smallest graph with this property.
The compression is {\it loss-less},
for given ${\bf G}({\bf V},{\bf E})$ and $\phi$,
we can reconstruct the unit weight graph $G(V,E)$.
In effect, we can work with the natural compressed graph to find
separators and orderings and map back to the unit weight graph.
The savings in time and space can be considerable.
\par
The {\tt Graph} object has a method to find the $\phi$ map for the
natural compressed graph; it requires $O(|V|)$ space and $O(|E|)$
time.
There is a method to compress a graph
(i.e., given $G(V,E)$ and an arbitrary $\phi$,
construct ${\bf G}({\bf V}, {\bf E})$)
and a method to expand a graph
(i.e., given ${\bf G}({\bf V},{\bf E})$ and an arbitrary $\phi$,
construct $G(V, E)$).
\par
There are several utility methods to return information about the
memory in use by the {\tt Graph object}, to access adjacency lists
and edge weight lists, and to provide information about the
connected components of a graph.
Graph/doc/main.tex 0100644 0002055 0007177 00000001115 06650656232 0015355 0 ustar 00cleve compmath 0000040 0000006 %
% main TeX file
%
\documentclass[leqno,11pt,twoside]{report}
\textwidth 6.5 in
\textheight 8.5 in
\oddsidemargin 0.0 in
\evensidemargin 0.0 in
\topmargin 0.0 in
\baselineskip 20 pt
\parskip 3 pt plus 1 pt minus 1 pt
\makeindex
\input psfig
\begin{document}
\pagestyle{myheadings}
\markboth
{\quad \hrulefill \quad {\tt Graph} : {\it DRAFT} \today \quad \hrulefill}
{\quad \hrulefill \quad {\tt Graph} : {\it DRAFT} \quad \today \hrulefill}
\par
\input intro.tex
\input dataStructure.tex
\input proto.tex
\input drivers.tex
\input main.ind
\end{document}
Graph/doc/proto.tex 0100644 0002055 0007177 00000055620 06650175402 0015601 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Prototypes and descriptions of {\tt Graph} methods}
\label{section:Graph:proto}
\par
This section contains brief descriptions including prototypes
of all methods that belong to the {\tt Graph} object.
\par
\subsection{Basic methods}
\label{subsection:Graph:proto:basics}
\par
As usual, there are four basic methods to support object creation,
setting default fields, clearing any allocated data, and free'ing
the object.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Graph * Graph_new ( void ) ;
\end{verbatim}
\index{Graph_new@{\tt Graph\_new()}}
This method simply allocates storage for the {\tt Graph} structure
and then sets the default fields by a call to
{\tt Graph\_setDefaultFields()}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Graph_setDefaultFields ( Graph *graph ) ;
\end{verbatim}
\index{Graph_setDefaultFields@{\tt Graph\_setDefaultFields()}}
This method sets the structure's fields to default values:
{\tt type}, {\tt nvtx}, {\tt nvbnd}, {\tt nedges}, {\tt totwght} and
{\tt totewght} are all zero, and {\tt adjIVL}, {\tt vwghts} and
{\tt ewghtIVL} are all {\tt NULL}.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Graph_clearData ( Graph *graph ) ;
\end{verbatim}
\index{Graph_clearData@{\tt Graph\_clearData()}}
This method clears the data for the object.
If {\tt adjIVL} is not {\tt NULL},
then {\tt IVL\_free(adjIVL)} is called to free the {\tt IVL}
object.
If {\tt ewghtIVL} is not {\tt NULL},
then {\tt IVL\_free(ewghtIVL)} is called to free the {\tt IVL}
object.
If {\tt vwghts} is not {\tt NULL},
then {\tt IVfree(vwghts)} is called to free the {\tt int}
vector.
The structure's fields are then set to their default values
with a call to {\tt Graph\_setDefaultFields()}.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Graph_free ( Graph *graph ) ;
\end{verbatim}
\index{Graph_free@{\tt Graph\_free()}}
This method releases any storage by a call to
{\tt Graph\_clearData()} then free's the storage for the
structure with a call to {\tt free()}.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Initializer methods}
\label{subsection:Graph:proto:initializers}
\par
There are three initializer methods.
The first is most commonly used, the second is used within the IO
routines, and the third is used to create a {\tt Graph} object from
the {\tt offsets[]/adjncy[]} format for the adjacency structure.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Graph_init1 ( Graph *graph, int type, int nvtx, int nvbnd, int nedges,
int adjType, int ewghtType ) ;
\end{verbatim}
\index{Graph_init1@{\tt Graph\_init1()}}
This is the basic initializer method.
Any previous data is cleared with a call to {\tt Graph\_clearData()}.
Then the scalar fields are set and the {\tt adjIVL} object is
initialized.
If {\tt type} is {\tt 1} or {\tt 3}, the {\tt vwghts} vector is
initialized to zeros.
If {\tt type} is {\tt 2} or {\tt 3}, the {\tt ewghtIVL} object
is initialized.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL},
{\tt type} is invalid ({\tt type} must be in {\tt [0,3]}),
{\tt nvtx} is non-positive,
{\tt nvbnd} or {\tt nedges} is negative, or
{\tt adjType} of {\tt ewghtType} is invalid (they must be
{\tt IVL\_CHUNKED},
{\tt IVL\_SOLO} or
{\tt IVL\_UNKNOWN}).
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Graph_init2 ( Graph *graph, int type, int nvtx, int nvbnd, int nedges,
int totvwght, int totewght, IVL *adjIVL, int *vwghts, IVL *ewghtIVL)
\end{verbatim}
\index{Graph_init2@{\tt Graph\_init2()}}
This method is used by the IO read methods.
When a {\tt Graph} object is read from a file, the {\tt IVL}
object(s) must be initialized and then read in from the file.
Therefore, we need an initialization method that allows us to set
pointers to the {\tt IVL} objects and the {\tt vwghts} vector.
Note, {\tt adjIVL}, {\tt vwghts} and {\tt ewghtIVL} are owned by
the {\tt Graph} object and will be free'd when the {\tt Graph}
object is free'd.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt adjIVL} is {\tt NULL},
{\tt type} is invalid ({\tt type} must be in {\tt [0,3]}),
{\tt nvtx} is non-positive,
{\tt nvbnd} or {\tt nedges} is negative,
or if {\tt type \% 2 = 1} and {\tt vwghts} is {\tt NULL},
or if ${\tt type} \ge 2$ and {\tt ewghtIVL} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Graph_fillFromOffsets ( Graph *graph, int neqns, int offsets[],
int adjncy[], int flag )
\end{verbatim}
\index{Graph_fillFromOffsets@{\tt Graph\_fillFromOffsets()}}
This method initializes the {\tt Graph} object using an adjacency
structure, as is the storage format for a Harwell-Boeing matrix.
The entries in list {\tt v} are found in {\tt adjncy[i1:i2]}, where
{\tt i1 = offsets[v]} and {\tt i2 = offsets[v+1]-1}.
The {\tt offsets[]} and {\tt adjncy[]} arrays are assumed to be
zero-based (as are C-arrays), not one-based (as are Fortran arrays).
If {\tt flag == 0} then the lists are simply loaded
into the {\tt Graph} object.
If {\tt flag == 1}, the adjacency structure must be upper, meaning
that the list for {\tt v} contains entries that are greater than or
equal to {\tt v}.
The {\tt Graph} will have a full adjacency
structure, including the {\tt (v,v)} edges.
\par \noindent {\it Error checking:}
If {\tt graph}, {\tt offsets} or {\tt adjncy} is {\tt NULL},
or if ${\tt neqns} \le 0$,
or if ${\tt flag} < 0$ or if ${\tt flag} > 1$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Graph_setListsFromOffsets ( Graph *graph, int neqns,
int offsets[], int adjncy[] ) ;
\end{verbatim}
\index{Graph_setListsFromOffsets@{\tt Graph\_setListsFromOffsets()}}
This method initializes the {\tt Graph} object using a {\it full}
adjacency structure.
The entries in list {\tt v} are found in {\tt adjncy[i1:i2]}, where
{\tt i1 = offsets[v]} and {\tt i2 = offsets[v+1]-1}.
The {\tt offsets[]} and {\tt adjncy[]} arrays are assumed to be
zero-based (as are C-arrays), not one-based (as are Fortran arrays).
Use this method with caution --- the adjacency list for vertex
{\tt v} must contain {\tt v} and {\it all} vertices it is adjacent to.
Note, new storage for the adjacency lists is not allocated, the
{\tt Graph} object's {\tt IVL} object points into the storage
in {\tt adjncy[]}.
\par \noindent {\it Error checking:}
If {\tt graph}, {\tt offsets} or {\tt adjncy} is {\tt NULL},
or if ${\tt neqns} \le 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Compress and Expand methods}
\label{subsection:Graph:proto:compress}
\par
These three methods find an equivalence map for the natural
compressed graph, compress a graph, and expand a graph.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * Graph_equivMap ( Graph *graph ) ;
\end{verbatim}
\index{Graph_equivMap@{\tt Graph\_equivMap()}}
This method constructs the equivalence map from the graph to its
natural compressed graph.
The map $\phi : V \mapsto {\bf V}$ is then constructed
(see the Introduction in this section)
and put into an {\tt IV} object that is then returned.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL} or {\tt nvtx <= 0},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Graph * Graph_compress ( Graph *graph, int map[], int coarseType ) ;
Graph * Graph_compress2 ( Graph *graph, IV *mapIV, int coarseType ) ;
\end{verbatim}
\index{Graph_compress@{\tt Graph\_compress()}}
\index{Graph_compress2@{\tt Graph\_compress2()}}
This {\tt Graph} and map objects ({\tt map[]} or {\tt mapIV}) are
checked and if any errors are found, the appropriate message is
printed and the program exits.
The compressed graph object is constructed and returned.
Note, the compressed graph does not have a boundary, even though
the original graph may have one.
\par \noindent {\it Error checking:}
If {\tt graph}, {\tt map} or {\tt mapIV} is {\tt NULL},
or if ${\tt nvtx} \le 0$,
or if ${\tt coarseType} < 0$,
or if $ 3 < {\tt coarseType}$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Graph * Graph_expand ( Graph *graph, int nvtxbig, int map[] ) ;
Graph * Graph_expand2 ( Graph *graph, IV *mapIV ) ;
\end{verbatim}
\index{Graph_expand@{\tt Graph\_expand()}}
\index{Graph_expand2@{\tt Graph\_expand2()}}
This {\tt Graph} and map objects ({\tt map[]} or {\tt mapIV}) are
checked and if any errors are found, the appropriate message is
printed and the program exits.
The expanded unit weight graph object is constructed and returned.
\par \noindent {\it Error checking:}
If {\tt graph}, {\tt map} or {\tt mapIV} is {\tt NULL},
or if ${\tt nvtxbig} \le 0$,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Wirebasket domain decomposition ordering}
\label{subsection:Graph:proto:wirebasket}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Graph_wirebasketStages ( Graph *graph, IV *stagesIV, int radius ) ;
\end{verbatim}
\index{Graph_wirebasketStages@{\tt Graph\_wirebasketStages()}}
This method is used to group the vertices into stages that is
suitable for a wirebasket domain decomposition of a general graph.
On input, {\tt stages[v] = 0} means that {\tt v} is in a domain.
On output, {\tt stages[v]} contains the stage of elimination ---
zero is for all vertices in the domains.
If {\tt stages[v] > 0}, then it is the number of domains that
are found within {\tt radius} edges of {\tt v}.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt stagesIV} is {\tt NULL},
or if {\tt radius < 0},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{Utility methods}
\label{subsection:Graph:proto:utilities}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_sizeOf ( Graph *graph ) ;
\end{verbatim}
\index{Graph_sizeOf@{\tt Graph\_sizeOf()}}
This method returns the number of bytes taken by this object.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Graph_externalDegree ( Graph *graph, int v ) ;
\end{verbatim}
\index{Graph_externalDegree@{\tt Graph\_externalDegree()}}
This method returns the weight of $\mbox{adj}(\mbox{\tt v})$.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL},
or {\tt v} is out of range,
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_adjAndSize ( Graph *graph, int u, int *pusize, int **puadj) ;
\end{verbatim}
\index{Graph_adjAndSize@{\tt Graph\_adjAndSize()}}
This method fills {\tt *pusize} with the size of the adjacency
list for {\tt u}
and {\tt *puadj} points to the start of the list vector.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL},
or if {\tt u < 0} or {\tt u >= nvtx}
or if {\tt pusize} or {\tt puadj} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_adjAndEweights ( Graph *graph, int u, int *pusize,
int **puadj, int **puewghts) ;
\end{verbatim}
\index{Graph_adjAndEweights@{\tt Graph\_adjAndEweights()}}
This method fills {\tt *psize} with the size of the adjacency
list, {\tt *puadj} points to the start of the list vector
and {\tt *puewghts} points to the start of the edge weights vector.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL},
or if {\tt u < 0} or {\tt u >= nvtx}
or if {\tt pusize}, {\tt puadj} or {\tt puewghts} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
IV * Graph_componentMap ( Graph *graph ) ;
\end{verbatim}
\index{Graph_componentMap@{\tt Graph\_componentMap()}}
This method computes and returns an IV object that holds a
map from vertices to components.
The values of the map vector are in the range
{\tt [0, number of components)}.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL} then
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void Graph_componentStats ( Graph *graph, int map[],
int counts[], int weights[] ) ;
\end{verbatim}
\index{Graph_componentStats@{\tt Graph\_componentStats()}}
This method computes some statistics about the components.
The length of {\tt map} is {\tt nvtx}.
The number of components is {\tt 1 + max(map)},
and the length of {\tt counts[]} and {\tt weights[]} must be as
large as the number of components.
On return, {\tt counts[icomp]} and {\tt weights[icomp]} are filled
with the number of vertices and weight of the vertices in component
{\tt icomp}, respectively.
\par \noindent {\it Error checking:}
If {\tt graph}, {\tt map}, {\tt counts} or {\tt weights}
is {\tt NULL}, then
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
Graph * Graph_subGraph ( Graph *graph, int icomp, int compids[], int **pmap ) ;
\end{verbatim}
\index{Graph_subGraph@{\tt Graph\_subGraph()}}
This method is used by the graph partitioning methods.
For a graph $G(V,E)$, a vertex separator $S \subset V$ is found
which separates the subgraph induced by $V \setminus S$
into two or more connected components.
We construct a new graph object for each component using this method.
The {\tt compids[]} vector maps the internal vertices
of the parent graph into components.
This method extracts the subgraph associated with component {\tt
icomp}.
\par
There is one key design feature.
{\it Most of the storage for the adjacency lists of the subgraph is
the same as its parent graph.}
This keeps us from replicating too much storage.
The subgraph has internal vertices and boundary vertices
(the latter contain at least part of $S$.)
Each adjacency list for an internal vertex of the subgraph points
to the corresponding adjacency list for the vertex in the parent graph.
Each adjacency list for a boundary vertex of the subgraph is new
storage, and only these lists are free'd when the subgraph is free'd.
A map vector is created that maps the subgraphs's vertices (both
internal and boundary) into the parent graph's vertices; the
address of the map vector is put into {\tt *pmap}.
The adjacency lists for the subgraph are overwritten by the {\tt map[]}
vector.
This renders the graph object invalid.
The graph partitioning methods map the vertices back to their
original values.
Presently, only graphs with unit edge weights are allowed as input.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL} or {\tt icomp < 0}
or {\tt compids} or {\tt pmap} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_isSymmetric ( Graph *graph ) ;
\end{verbatim}
\index{Graph_isSymmetric@{\tt Graph\_isSymmetric()}}
This method returns {\tt 1}
if the graph is symmetric (i.e., edge {\tt (i,j)} is
present if and only if edge {\tt (j,i)} is present) and {\tt 0}
otherwise.
\par \noindent {\it Error checking:}
If {\tt graph} is {\tt NULL},
an error message is printed and the program exits.
%-----------------------------------------------------------------------
\end{enumerate}
\par
\subsection{IO methods}
\label{subsection:Graph:proto:IO}
\par
There are the usual eight IO routines.
The file structure of a {\tt Graph} object is simple:
The six scalar fields come first:
{\tt type},
{\tt nvtx},
{\tt nvbnd},
{\tt nedges},
{\tt totvwght} and
{\tt totewght}.
The adjacency {\tt IVL} structure {\tt adjIVL} follows.
If the graph has non-unit vertex weights, i.e., {\tt type \% 2 == 1},
the {\tt vwghts} vector follows.
If the graph has non-unit edge weights, i.e., {\tt type / 2 == 1},
the {\tt IVL} structure {\tt ewghtIVL} follows.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_readFromFile ( Graph *graph, char *fn ) ;
\end{verbatim}
\index{Graph_readFromFile@{\tt Graph\_readFromFile()}}
\par
This method reads a {\tt Graph object} from a file.
It tries to open the file and if it is successful,
it then calls {\tt Graph\_readFromFormattedFile()} or
{\tt Graph\_readFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.graphf} (for a formatted file)
or {\tt *.graphb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_readFromFormattedFile ( Graph *graph, FILE *fp ) ;
\end{verbatim}
\index{Graph_readFromFormattedFile@{\tt Graph\_readFromFormattedFile()}}
\par
This method reads a {\tt Graph} object from a formatted file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fscanf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt fp} are {\tt NULL}
an error message is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_readFromBinaryFile ( Graph *graph, FILE *fp ) ;
\end{verbatim}
\index{Graph_readFromBinaryFile@{\tt Graph\_readFromBinaryFile()}}
This method reads a {\tt Graph} object from a binary file.
If there are no errors in reading the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fread}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_writeToFile ( Graph *graph, char *fn ) ;
\end{verbatim}
\index{Graph_writeToFile@{\tt Graph\_writeToFile()}}
\par
This method writes a {\tt Graph object} to a file.
It tries to open the file and if it is successful,
it then calls {\tt Graph\_writeFromFormattedFile()} or
{\tt Graph\_writeFromBinaryFile()},
closes the file
and returns the value returned from the called routine.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt fn} are {\tt NULL},
or if {\tt fn} is not of the form
{\tt *.graphf} (for a formatted file)
or {\tt *.graphb} (for a binary file),
an error message is printed and the method returns zero.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_writeToFormattedFile ( Graph *graph, FILE *fp ) ;
\end{verbatim}
\index{Graph_writeToFormattedFile@{\tt Graph\_writeToFormattedFile()}}
\par
This method writes a {\tt Graph} object to a formatted file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fprintf}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_writeToBinaryFile ( Graph *graph, FILE *fp ) ;
\end{verbatim}
\index{Graph_writeToBinaryFile@{\tt Graph\_writeToBinaryFile()}}
\par
This method writes a {\tt Graph} object to a binary file.
If there are no errors in writing the data,
the value {\tt 1} is returned.
If an IO error is encountered from {\tt fwrite}, zero is returned.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_writeForHumanEye ( Graph *graph, FILE *fp ) ;
\end{verbatim}
\index{Graph_writeForHumanEye@{\tt Graph\_writeForHumanEye()}}
\par
This method writes a {\tt Graph} object to a file in a human
readable format.
The method {\tt Graph\_writeStats()} is called to write out the
header and statistics.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_writeStats ( Graph *graph, FILE *fp ) ;
\end{verbatim}
\index{Graph_writeStats@{\tt Graph\_writeStats()}}
\par
The header and statistics are written to a file.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int Graph_writeToMetisFile ( Graph *graph, FILE *fp ) ;
\end{verbatim}
\index{Graph_writeToMetisFile@{\tt Graph\_writeToMetisFile()}}
\par
This method writes a {\tt Graph} object to a file in the format of
the {\bf METIS} or {\bf CHACO} packages.
The value {\tt 1} is returned.
\par \noindent {\it Error checking:}
If {\tt graph} or {\tt fp} are {\tt NULL} an error message
is printed and zero is returned.
%-----------------------------------------------------------------------
\end{enumerate}
weights()}}
This method fills {\tt *psize} with the size of the adjacency
list, {\tt *puadj} points to the startGraph/doc/main.log 0100644 0002055 0007177 00000012365 06540266340 0015342 0 ustar 00cleve compmath 0000040 0000006 This is TeX, Version 3.1415 (C version 6.1) (format=lplain 94.11.14) 12 JUN 1998 11:01
**main
(main.tex
LaTeX Version 2.09 <25 March 1992>
(/usr/local/lib/texmf/tex/latex209/report.sty
Standard Document Style `report' <14 Jan 92>.
(/usr/local/lib/texmf/tex/latex209/rep11.sty)
\descriptionmargin=\dimen99
\c@part=\count79
\c@chapter=\count80
\c@section=\count81
\c@subsection=\count82
\c@subsubsection=\count83
\c@paragraph=\count84
\c@subparagraph=\count85
\c@figure=\count86
\c@table=\count87
(/usr/local/lib/texmf/tex/latex209/titlepag.sty
Document Style Option `titlepage' -- Released 16 June 1991.
)) (/usr/local/lib/texmf/tex/latex209/leqno.sty
Document style option `leqno' - released 29 Sep 1991
)
\@indexfile=\write3
Writing index file main.idx
(/usr/local/lib/texmf/tex/generic/psfig/psfig.tex
\@unused=\write4
\ps@stream=\read1
\p@intvaluex=\dimen100
\p@intvaluey=\dimen101
psfig/tex 1.10-dvips
) (main.aux) (intro.tex
Chapter 1.
LaTeX Warning: No \tt typeface in this size, using \rm on input line 2.
LaTeX Warning: Citation `ash95-DDSEP' on page 1 undefined on input line 24.
LaTeX Warning: Citation `ash95-compressed-graphs' on page 1 undefined on input
line 59.
LaTeX Warning: Citation `dam92-compressed' on page 1 undefined on input line 60
.
[1
]) (dataStructure.tex) (proto.tex [2]
Overfull \hbox (22.0743pt too wide) in paragraph at lines 92--100
[]\elvrm This is the ba-sic ini-tial-izer method. Any pre-vi-ous data is cleare
d with a call to \elvtt Graph[]clearData()\elvrm .
\hbox(7.60416+2.43333)x442.37993, glue set - 1.0
.\hbox(0.0+0.0)x0.0
.\elvrm T
.\elvrm h
.\elvrm i
.\elvrm s
.etc.
[3] [4] [5]
Overfull \hbox (11.7664pt too wide) in paragraph at lines 360--360
[] []\elvtt Graph * Graph_subGraph ( Graph *graph, int icomp, int compids[], i
nt **pmap ) ;[]
\hbox(7.60416+2.43333)x469.75499
.\glue(\leftskip) 27.37506
.\hbox(0.0+0.0)x0.0
.\glue 0.0
.\hbox(7.05666+0.0)x0.0
..\glue 0.0
..\glue 0.0
..\glue -21.90005
..\glue -5.475
..\hbox(7.05666+0.0)x21.90005, glue set 21.90005fil
...\glue 0.0 plus 1.0fil minus 1.0fil
...\hbox(7.05666+0.0)x0.0, glue set - 8.51668fil []
..etc.
.\penalty 0
.etc.
[6] [7]) (drivers.tex
Overfull \hbox (19.63927pt too wide) in paragraph at lines 28--32
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
Overfull \hbox (19.63927pt too wide) in paragraph at lines 55--60
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
[8]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 105--110
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
[9]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 185--190
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
Overfull \hbox (15.38101pt too wide) in paragraph at lines 190--194
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is writ-ten to the file via the \elvtt Graph[]writeToFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
Overfull \hbox (19.63927pt too wide) in paragraph at lines 216--220
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
[10]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 247--252
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
psfig: searching ../../Graph/doc/rad1.eps for bounding box
psfig: including ../../Graph/doc/rad1.eps
psfig: searching ../../Graph/doc/rad2.eps for bounding box
psfig: including ../../Graph/doc/rad2.eps
[11]
Overfull \hbox (19.63927pt too wide) in paragraph at lines 301--306
\elvtt *.graphf \elvrm or \elvtt *.graphb\elvrm . The \elvtt Graph \elvrm ob-je
ct is read from the file via the \elvtt Graph[]readFromFile()
\hbox(7.60416+2.43333)x418.2899, glue set - 1.0
.\elvtt *
.\elvtt .
.\elvtt g
.\elvtt r
.\elvtt a
.etc.
) (main.ind [12] [13
]) (main.aux) )
Here is how much of TeX's memory you used:
442 strings out of 11977
4537 string characters out of 87269
37981 words of memory out of 262141
2362 multiletter control sequences out of 9500
19780 words of font info for 75 fonts, out of 100000 for 255
14 hyphenation exceptions out of 607
14i,6n,17p,182b,260s stack positions out of 300i,40n,60p,3000b,4000s
Output written on main.dvi (13 pages, 42228 bytes).
Graph/doc/main.aux 0100644 0002055 0007177 00000003576 06540266340 0015362 0 ustar 00cleve compmath 0000040 0000006 \relax
\citation{ash95-DDSEP}
\citation{ash95-compressed-graphs}
\citation{dam92-compressed}
\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}{\string\ptt\space Graph}: A Graph object}{1}}
\@writefile{lof}{\string\addvspace\space {10\p@ }}
\@writefile{lot}{\string\addvspace\space {10\p@ }}
\newlabel{chapter:Graph}{{1}{1}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Data Structure}{2}}
\newlabel{section:Graph:dataStructure}{{1.1}{2}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Prototypes and descriptions of {\string\ptt\space Graph} methods}{2}}
\newlabel{section:Graph:proto}{{1.2}{2}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.1}Basic methods}{3}}
\newlabel{subsection:Graph:proto:basics}{{1.2.1}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Initializer methods}{3}}
\newlabel{subsection:Graph:proto:initializers}{{1.2.2}{3}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.3}Compress and Expand methods}{4}}
\newlabel{subsection:Graph:proto:compress}{{1.2.3}{4}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.4}Wirebasket domain decomposition ordering}{5}}
\newlabel{subsection:Graph:proto:wirebasket}{{1.2.4}{5}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.5}Utility methods}{5}}
\newlabel{subsection:Graph:proto:utilities}{{1.2.5}{5}}
\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.6}IO methods}{7}}
\newlabel{subsection:Graph:proto:IO}{{1.2.6}{7}}
\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}Driver programs for the {\string\ptt\space Graph} object}{8}}
\newlabel{section:Graph:drivers}{{1.3}{8}}
Graph/doc/drivers.tex 0100644 0002055 0007177 00000027671 06540266276 0016131 0 ustar 00cleve compmath 0000040 0000006 \par
\section{Driver programs for the {\tt Graph} object}
\label{section:Graph:drivers}
\par
This section contains brief descriptions of six driver programs.
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
checkComponents msglvl msgFile inGraphFile
\end{verbatim}
This driver program reads in a {\tt Graph} object from a file,
and prints out information about the number of vertices and weights
of the vertices in the components.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means that all objects are written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
compressGraph msglvl msgFile inGraphFile coarseType outMapFile outGraphFile
\end{verbatim}
This driver program reads in a {\tt Graph} object from a file,
computes the equivalence map to its natural compressed graph
(the first graph need not be unit weight), and constructs the
natural compressed graph.
The equivalence map and compressed graph are optionally written out
to files.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means that all objects are written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt coarseType} parameter defines the type of compressed
graph; valid values are in {\tt [0,3]}.
\item
The {\tt outMapFile} parameter is the output file for the {\tt IV}
object that holds the equivalence map.
If {\tt outMapFile} is {\tt none} then the {\tt IV} object is not
written to a file.
Otherwise, the {\tt IV\_writeToFile()} method is called to write
the {\tt IV} object to
a formatted file (if {\tt outMapFile} is of the form {\tt *.ivf}),
or
a binary file (if {\tt outMapFile} is of the form {\tt *.ivb}).
\item
The {\tt outGraphFile} parameter is the output file for the
compressed {\tt Graph} object.
If {\tt outGraphFile} is {\tt none} then the {\tt Graph} object is not
written to a file.
Otherwise, the {\tt Graph\_writeToFile()} method is called to write
the graph to
a formatted file (if {\tt outGraphFile} is of the form {\tt *.graphf}),
or
a binary file (if {\tt outGraphFile} is of the form {\tt *.graphb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
expandGraph msglvl msgFile inGraphFile inMapFile outGraphFile
\end{verbatim}
This driver program reads in a {\tt Graph} object and a map {\tt
IV} object from two files.
It then creates a new {\tt Graph} object which is the original
graph ``expanded'' by the map, and optionally writes this object
to a file.
The program {\tt expandGraph} is the inverse of {\tt compressGraph}.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means that all objects are written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt inMapFile} parameter is the input file for the {\tt IV}
object that holds the expansion map.
The {\tt IV\_readFromFile()} method is called to read
the map from
a formatted file (if {\tt inMapFile} is of the form {\tt *.ivf}),
or
a binary file (if {\tt inMapFile} is of the form {\tt *.ivb}).
\item
The {\tt outGraphFile} parameter is the output file for the
compressed {\tt Graph} object.
If {\tt outGraphFile} is {\tt none} then the {\tt Graph} object is not
written to a file.
Otherwise, the {\tt Graph\_writeToFile()} method is called to write
the graph to
a formatted file (if {\tt outGraphFile} is of the form {\tt *.graphf}),
or
a binary file (if {\tt outGraphFile} is of the form {\tt *.graphb}).
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
mkGridGraph msglvl msgFile stencil n1 n2 n3 outFile
\end{verbatim}
This driver program creates a Graph object for a finite difference
operator on a ${\tt n1} \times {\tt n2} \times {\tt n3}$ regular grid.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means that all objects are written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
Valid {\tt stencil} values are
{\tt 5} for a 2-D 5-point operator,
{\tt 7} for a 3-D 7-point operator,
{\tt 9} for a 2-D 9-point operator,
{\tt 13} for a 2-D 13-point operator
and
{\tt 27} for a 3-D 27-point operator.
\item
{\tt n1} is the number of points in the first direction.
\item
{\tt n2} is the number of points in the second direction.
\item
{\tt n3} is the number of points in the third direction,
ignored for {\tt stencil} = {\tt 5}, {\tt 9} and {\tt 13}.
\item
The {\tt Graph} object is written to file {\tt outFile}.
It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is written to the file via the
{\tt Graph\_writeToFile()} method.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testIO msglvl msgFile inFile outFile
\end{verbatim}
This driver program reads in a {\tt Graph} object from {\tt inFile}
and writes out the object to {\tt outFile}
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt Graph} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt outFile} parameter is the output file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is written to the file via the
{\tt Graph\_writeToFile()} method.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testIsSymmetric msglvl msgFile inFile
\end{verbatim}
This driver program reads in a {\tt Graph} object and tests whether
it is symmetric using the {\tt Graph\_isSymmetric()} method.
This was useful in one application where the {\tt Graph} object was
constructed improperly.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt Graph} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\end{itemize}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
testWirebasket msglvl msgFile inGraphFile inStagesFile
outStagesFile radius
\end{verbatim}
This driver program reads in a {\tt Graph} object and
and a file that contains the stages ids of the vertices,
(stage equal to zero means the vertex is in the Schur complement),
and overwrites the stages vector to specify the stage that the
vertex lies for a wirebasket domain decomposition of the graph.
For a Schur complement vertex, its stage is precisely the number of
domains that lie within {\tt radius} edges of it.
The new stages vector is written to the {\tt outStagesFile} file.
\par
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means the {\tt Graph} object is written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt inStagesFile} parameter is the input file for the {\tt IV}
object that holds the component ids.
It must be of the form {\tt *.ivf} or {\tt *.ivb}.
The {\tt IV} object is read from the file via the
{\tt IV\_readFromFile()} method.
\item
The {\tt outStagesFile} parameter is the output file for the
stages {\tt IV} object.
It must be of the form {\tt *.ivf} or {\tt *.ivb}.
The {\tt IV} object is written to the file via the
{\tt IV\_writeToFile()} method.
\item
The {\tt radius} parameter is used to define the stage of a Schur
complement vertex, namely the stage is the number of domains that
are found within {\tt radius} edges of the vertex.
\end{itemize}
The two plots below illustrate the wirebasket stages for a $15
\times 15$ grid.
They show the stages for {\tt radius = 1} on the
left and {\tt radius = 2} on the right.
The domains are $3 \times 3$ subgrids whose vertices have labels
equal to zero.
\begin{center}
\makebox{
% \psfig{file=rad1.eps,width=2.7in,height=2.70in}
\psfig{file=../../Graph/doc/rad1.eps,width=2.7in,height=2.70in}
% \psfig{file=rad2.eps,width=2.7in,height=2.70in}
\psfig{file=../../Graph/doc/rad2.eps,width=2.7in,height=2.70in}
}
\end{center}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
writeMetisFile msglvl msgFile inGraphFile outMetisFile
\end{verbatim}
This driver program reads in an {\tt Graph} object and write it out
to a file in the format required by the {\bf METIS} software
package.
\begin{itemize}
\item
The {\tt msglvl} parameter determines the amount of output ---
taking {\tt msglvl >= 3} means that all objects are written
to the message file.
\item
The {\tt msgFile} parameter determines the message file --- if {\tt
msgFile} is {\tt stdout}, then the message file is {\it stdout},
otherwise a file is opened with {\it append} status to receive any
output data.
\item
The {\tt inGraphFile} parameter is the input file for the {\tt Graph}
object. It must be of the form {\tt *.graphf} or {\tt *.graphb}.
The {\tt Graph} object is read from the file via the
{\tt Graph\_readFromFile()} method.
\item
The {\tt outMetisFile} parameter is the outfile file for the {\bf
METIS} graph object.
\end{itemize}
%-----------------------------------------------------------------------
\end{enumerate}
stdout},
otherwise a file is opened with {\it append} status to receiveGraph/doc/main.idx 0100644 0002055 0007177 00000003502 06540266340 0015336 0 ustar 00cleve compmath 0000040 0000006 \indexentry{Graph_new@{\tt Graph\_new()}}{3}
\indexentry{Graph_setDefaultFields@{\tt Graph\_setDefaultFields()}}{3}
\indexentry{Graph_clearData@{\tt Graph\_clearData()}}{3}
\indexentry{Graph_free@{\tt Graph\_free()}}{3}
\indexentry{Graph_init1@{\tt Graph\_init1()}}{3}
\indexentry{Graph_init2@{\tt Graph\_init2()}}{4}
\indexentry{Graph_fillFromOffsets@{\tt Graph\_fillFromOffsets()}}{4}
\indexentry{Graph_setListsFromOffsets@{\tt Graph\_setListsFromOffsets()}}{4}
\indexentry{Graph_equivMap@{\tt Graph\_equivMap()}}{4}
\indexentry{Graph_compress@{\tt Graph\_compress()}}{5}
\indexentry{Graph_compress2@{\tt Graph\_compress2()}}{5}
\indexentry{Graph_expand@{\tt Graph\_expand()}}{5}
\indexentry{Graph_expand2@{\tt Graph\_expand2()}}{5}
\indexentry{Graph_wirebasketStages@{\tt Graph\_wirebasketStages()}}{5}
\indexentry{Graph_sizeOf@{\tt Graph\_sizeOf()}}{5}
\indexentry{Graph_externalDegree@{\tt Graph\_externalDegree()}}{5}
\indexentry{Graph_adjAndSize@{\tt Graph\_adjAndSize()}}{6}
\indexentry{Graph_adjAndEweights@{\tt Graph\_adjAndEweights()}}{6}
\indexentry{Graph_componentMap@{\tt Graph\_componentMap()}}{6}
\indexentry{Graph_componentStats@{\tt Graph\_componentStats()}}{6}
\indexentry{Graph_subGraph@{\tt Graph\_subGraph()}}{6}
\indexentry{Graph_isSymmetric@{\tt Graph\_isSymmetric()}}{7}
\indexentry{Graph_readFromFile@{\tt Graph\_readFromFile()}}{7}
\indexentry{Graph_readFromFormattedFile@{\tt Graph\_readFromFormattedFile()}}{7}
\indexentry{Graph_readFromBinaryFile@{\tt Graph\_readFromBinaryFile()}}{7}
\indexentry{Graph_writeToFile@{\tt Graph\_writeToFile()}}{7}
\indexentry{Graph_writeToFormattedFile@{\tt Graph\_writeToFormattedFile()}}{7}
\indexentry{Graph_writeToBinaryFile@{\tt Graph\_writeToBinaryFile()}}{8}
\indexentry{Graph_writeForHumanEye@{\tt Graph\_writeForHumanEye()}}{8}
\indexentry{Graph_writeStats@{\tt Graph\_writeStats()}}{8}
Graph/doc/main.ind 0100644 0002055 0007177 00000002244 06540266306 0015330 0 ustar 00cleve compmath 0000040 0000006 \begin{theindex}
\item {\tt Graph\_adjAndEweights()}, 6
\item {\tt Graph\_adjAndSize()}, 6
\item {\tt Graph\_clearData()}, 3
\item {\tt Graph\_componentMap()}, 6
\item {\tt Graph\_componentStats()}, 6
\item {\tt Graph\_compress()}, 5
\item {\tt Graph\_compress2()}, 5
\item {\tt Graph\_equivMap()}, 4
\item {\tt Graph\_expand()}, 5
\item {\tt Graph\_expand2()}, 5
\item {\tt Graph\_externalDegree()}, 5
\item {\tt Graph\_fillFromOffsets()}, 4
\item {\tt Graph\_free()}, 3
\item {\tt Graph\_init1()}, 3
\item {\tt Graph\_init2()}, 4
\item {\tt Graph\_isSymmetric()}, 7
\item {\tt Graph\_new()}, 3
\item {\tt Graph\_readFromBinaryFile()}, 7
\item {\tt Graph\_readFromFile()}, 7
\item {\tt Graph\_readFromFormattedFile()}, 7
\item {\tt Graph\_setDefaultFields()}, 3
\item {\tt Graph\_setListsFromOffsets()}, 4
\item {\tt Graph\_sizeOf()}, 5
\item {\tt Graph\_subGraph()}, 6
\item {\tt Graph\_wirebasketStages()}, 5
\item {\tt Graph\_writeForHumanEye()}, 8
\item {\tt Graph\_writeStats()}, 8
\item {\tt Graph\_writeToBinaryFile()}, 8
\item {\tt Graph\_writeToFile()}, 7
\item {\tt Graph\_writeToFormattedFile()}, 7
\end{theindex}
Graph/doc/main.ilg 0100644 0002055 0007177 00000000457 06540266306 0015335 0 ustar 00cleve compmath 0000040 0000006 This is makeindex, portable version 2.12 [26-May-1993].
Scanning input file main.idx....done (30 entries accepted, 0 rejected).
Sorting entries....done (141 comparisons).
Generating output file main.ind....done (34 lines written, 0 warnings).
Output written in main.ind.
Transcript written in main.ilg.
Graph/doc/rad2.eps 0100644 0002055 0007177 00000074615 06534106105 0015255 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 600.0 600.0
/radius 15 def
/Helvetica findfont 18.75 scalefont setfont
/M {moveto} def
/L {lineto} def
/ACF { % stack : x y radius
newpath 0 360 arc closepath fill
} def
/str 6 string def
/drawLabel { % x y label radius
/radius exch def
/label exch def
/y exch def
/x exch def
gsave
1.0 setgray
x radius add y moveto
x y radius 0 360 arc
fill
0.0 setgray
x radius add y moveto
x y radius 0 360 arc
stroke
x y moveto
label stringwidth pop 2 div neg radius 2 div neg rmoveto
label show
grestore
} def
gsave
0.001 setlinewidth
0.0 setgray
newpath
60 20 M 20 20 L
100 20 M 60 20 L
220 20 M 180 20 L
260 20 M 220 20 L
380 20 M 340 20 L
420 20 M 380 20 L
540 20 M 500 20 L
580 20 M 540 20 L
20 60 M 20 20 L
20 60 M 60 20 L
60 60 M 20 20 L
60 60 M 60 20 L
60 60 M 100 20 L
60 60 M 20 60 L
100 60 M 60 20 L
100 60 M 100 20 L
100 60 M 60 60 L
140 60 M 140 20 L
180 60 M 180 20 L
180 60 M 220 20 L
220 60 M 180 20 L
220 60 M 220 20 L
220 60 M 260 20 L
220 60 M 180 60 L
260 60 M 220 20 L
260 60 M 260 20 L
260 60 M 220 60 L
300 60 M 300 20 L
340 60 M 340 20 L
340 60 M 380 20 L
380 60 M 340 20 L
380 60 M 380 20 L
380 60 M 420 20 L
380 60 M 340 60 L
420 60 M 380 20 L
420 60 M 420 20 L
420 60 M 380 60 L
460 60 M 460 20 L
500 60 M 500 20 L
500 60 M 540 20 L
540 60 M 500 20 L
540 60 M 540 20 L
540 60 M 580 20 L
540 60 M 500 60 L
580 60 M 540 20 L
580 60 M 580 20 L
580 60 M 540 60 L
20 100 M 20 60 L
20 100 M 60 60 L
60 100 M 20 60 L
60 100 M 60 60 L
60 100 M 100 60 L
60 100 M 20 100 L
100 100 M 60 60 L
100 100 M 100 60 L
100 100 M 60 100 L
180 100 M 180 60 L
180 100 M 220 60 L
220 100 M 180 60 L
220 100 M 220 60 L
220 100 M 260 60 L
220 100 M 180 100 L
260 100 M 220 60 L
260 100 M 260 60 L
260 100 M 220 100 L
340 100 M 340 60 L
340 100 M 380 60 L
380 100 M 340 60 L
380 100 M 380 60 L
380 100 M 420 60 L
380 100 M 340 100 L
420 100 M 380 60 L
420 100 M 420 60 L
420 100 M 380 100 L
500 100 M 500 60 L
500 100 M 540 60 L
540 100 M 500 60 L
540 100 M 540 60 L
540 100 M 580 60 L
540 100 M 500 100 L
580 100 M 540 60 L
580 100 M 580 60 L
580 100 M 540 100 L
60 140 M 20 140 L
100 140 M 140 100 L
140 140 M 140 100 L
140 140 M 100 140 L
180 140 M 140 100 L
180 140 M 140 140 L
260 140 M 300 100 L
300 140 M 300 100 L
300 140 M 260 140 L
340 140 M 300 100 L
340 140 M 300 140 L
420 140 M 460 100 L
460 140 M 460 100 L
460 140 M 420 140 L
500 140 M 460 100 L
500 140 M 460 140 L
580 140 M 540 140 L
stroke
newpath
60 180 M 20 180 L
100 180 M 60 180 L
140 180 M 100 140 L
140 180 M 140 140 L
140 180 M 180 140 L
220 180 M 180 180 L
260 180 M 220 180 L
300 180 M 260 140 L
300 180 M 300 140 L
300 180 M 340 140 L
380 180 M 340 180 L
420 180 M 380 180 L
460 180 M 420 140 L
460 180 M 460 140 L
460 180 M 500 140 L
540 180 M 500 180 L
580 180 M 540 180 L
20 220 M 20 180 L
20 220 M 60 180 L
60 220 M 20 180 L
60 220 M 60 180 L
60 220 M 100 180 L
60 220 M 20 220 L
100 220 M 60 180 L
100 220 M 100 180 L
100 220 M 60 220 L
180 220 M 180 180 L
180 220 M 220 180 L
220 220 M 180 180 L
220 220 M 220 180 L
220 220 M 260 180 L
220 220 M 180 220 L
260 220 M 220 180 L
260 220 M 260 180 L
260 220 M 220 220 L
340 220 M 340 180 L
340 220 M 380 180 L
380 220 M 340 180 L
380 220 M 380 180 L
380 220 M 420 180 L
380 220 M 340 220 L
420 220 M 380 180 L
420 220 M 420 180 L
420 220 M 380 220 L
500 220 M 500 180 L
500 220 M 540 180 L
540 220 M 500 180 L
540 220 M 540 180 L
540 220 M 580 180 L
540 220 M 500 220 L
580 220 M 540 180 L
580 220 M 580 180 L
580 220 M 540 220 L
20 260 M 20 220 L
20 260 M 60 220 L
60 260 M 20 220 L
60 260 M 60 220 L
60 260 M 100 220 L
60 260 M 20 260 L
100 260 M 60 220 L
100 260 M 100 220 L
100 260 M 60 260 L
180 260 M 180 220 L
180 260 M 220 220 L
220 260 M 180 220 L
220 260 M 220 220 L
220 260 M 260 220 L
220 260 M 180 260 L
260 260 M 220 220 L
260 260 M 260 220 L
260 260 M 220 260 L
340 260 M 340 220 L
340 260 M 380 220 L
380 260 M 340 220 L
380 260 M 380 220 L
380 260 M 420 220 L
380 260 M 340 260 L
420 260 M 380 220 L
420 260 M 420 220 L
420 260 M 380 260 L
500 260 M 500 220 L
500 260 M 540 220 L
540 260 M 500 220 L
540 260 M 540 220 L
540 260 M 580 220 L
540 260 M 500 260 L
580 260 M 540 220 L
580 260 M 580 220 L
580 260 M 540 260 L
60 300 M 20 300 L
100 300 M 140 260 L
140 300 M 140 260 L
140 300 M 100 300 L
180 300 M 140 260 L
180 300 M 140 300 L
260 300 M 300 260 L
300 300 M 300 260 L
300 300 M 260 300 L
340 300 M 300 260 L
340 300 M 300 300 L
stroke
newpath
420 300 M 460 260 L
460 300 M 460 260 L
460 300 M 420 300 L
500 300 M 460 260 L
500 300 M 460 300 L
580 300 M 540 300 L
60 340 M 20 340 L
100 340 M 60 340 L
140 340 M 100 300 L
140 340 M 140 300 L
140 340 M 180 300 L
220 340 M 180 340 L
260 340 M 220 340 L
300 340 M 260 300 L
300 340 M 300 300 L
300 340 M 340 300 L
380 340 M 340 340 L
420 340 M 380 340 L
460 340 M 420 300 L
460 340 M 460 300 L
460 340 M 500 300 L
540 340 M 500 340 L
580 340 M 540 340 L
20 380 M 20 340 L
20 380 M 60 340 L
60 380 M 20 340 L
60 380 M 60 340 L
60 380 M 100 340 L
60 380 M 20 380 L
100 380 M 60 340 L
100 380 M 100 340 L
100 380 M 60 380 L
180 380 M 180 340 L
180 380 M 220 340 L
220 380 M 180 340 L
220 380 M 220 340 L
220 380 M 260 340 L
220 380 M 180 380 L
260 380 M 220 340 L
260 380 M 260 340 L
260 380 M 220 380 L
340 380 M 340 340 L
340 380 M 380 340 L
380 380 M 340 340 L
380 380 M 380 340 L
380 380 M 420 340 L
380 380 M 340 380 L
420 380 M 380 340 L
420 380 M 420 340 L
420 380 M 380 380 L
500 380 M 500 340 L
500 380 M 540 340 L
540 380 M 500 340 L
540 380 M 540 340 L
540 380 M 580 340 L
540 380 M 500 380 L
580 380 M 540 340 L
580 380 M 580 340 L
580 380 M 540 380 L
20 420 M 20 380 L
20 420 M 60 380 L
60 420 M 20 380 L
60 420 M 60 380 L
60 420 M 100 380 L
60 420 M 20 420 L
100 420 M 60 380 L
100 420 M 100 380 L
100 420 M 60 420 L
180 420 M 180 380 L
180 420 M 220 380 L
220 420 M 180 380 L
220 420 M 220 380 L
220 420 M 260 380 L
220 420 M 180 420 L
260 420 M 220 380 L
260 420 M 260 380 L
260 420 M 220 420 L
340 420 M 340 380 L
340 420 M 380 380 L
380 420 M 340 380 L
380 420 M 380 380 L
380 420 M 420 380 L
380 420 M 340 420 L
420 420 M 380 380 L
420 420 M 420 380 L
420 420 M 380 420 L
500 420 M 500 380 L
500 420 M 540 380 L
540 420 M 500 380 L
540 420 M 540 380 L
540 420 M 580 380 L
540 420 M 500 420 L
580 420 M 540 380 L
580 420 M 580 380 L
580 420 M 540 420 L
60 460 M 20 460 L
100 460 M 140 420 L
140 460 M 140 420 L
140 460 M 100 460 L
180 460 M 140 420 L
stroke
newpath
180 460 M 140 460 L
260 460 M 300 420 L
300 460 M 300 420 L
300 460 M 260 460 L
340 460 M 300 420 L
340 460 M 300 460 L
420 460 M 460 420 L
460 460 M 460 420 L
460 460 M 420 460 L
500 460 M 460 420 L
500 460 M 460 460 L
580 460 M 540 460 L
60 500 M 20 500 L
100 500 M 60 500 L
140 500 M 100 460 L
140 500 M 140 460 L
140 500 M 180 460 L
220 500 M 180 500 L
260 500 M 220 500 L
300 500 M 260 460 L
300 500 M 300 460 L
300 500 M 340 460 L
380 500 M 340 500 L
420 500 M 380 500 L
460 500 M 420 460 L
460 500 M 460 460 L
460 500 M 500 460 L
540 500 M 500 500 L
580 500 M 540 500 L
20 540 M 20 500 L
20 540 M 60 500 L
60 540 M 20 500 L
60 540 M 60 500 L
60 540 M 100 500 L
60 540 M 20 540 L
100 540 M 60 500 L
100 540 M 100 500 L
100 540 M 60 540 L
180 540 M 180 500 L
180 540 M 220 500 L
220 540 M 180 500 L
220 540 M 220 500 L
220 540 M 260 500 L
220 540 M 180 540 L
260 540 M 220 500 L
260 540 M 260 500 L
260 540 M 220 540 L
340 540 M 340 500 L
340 540 M 380 500 L
380 540 M 340 500 L
380 540 M 380 500 L
380 540 M 420 500 L
380 540 M 340 540 L
420 540 M 380 500 L
420 540 M 420 500 L
420 540 M 380 540 L
500 540 M 500 500 L
500 540 M 540 500 L
540 540 M 500 500 L
540 540 M 540 500 L
540 540 M 580 500 L
540 540 M 500 540 L
580 540 M 540 500 L
580 540 M 580 500 L
580 540 M 540 540 L
20 580 M 20 540 L
20 580 M 60 540 L
60 580 M 20 540 L
60 580 M 60 540 L
60 580 M 100 540 L
60 580 M 20 580 L
100 580 M 60 540 L
100 580 M 100 540 L
100 580 M 60 580 L
140 580 M 140 540 L
180 580 M 180 540 L
180 580 M 220 540 L
220 580 M 180 540 L
220 580 M 220 540 L
220 580 M 260 540 L
220 580 M 180 580 L
260 580 M 220 540 L
260 580 M 260 540 L
260 580 M 220 580 L
300 580 M 300 540 L
340 580 M 340 540 L
340 580 M 380 540 L
380 580 M 340 540 L
380 580 M 380 540 L
380 580 M 420 540 L
380 580 M 340 580 L
420 580 M 380 540 L
420 580 M 420 540 L
420 580 M 380 580 L
460 580 M 460 540 L
500 580 M 500 540 L
500 580 M 540 540 L
540 580 M 500 540 L
540 580 M 540 540 L
540 580 M 580 540 L
stroke
newpath
540 580 M 500 580 L
580 580 M 540 540 L
580 580 M 580 540 L
580 580 M 540 580 L
stroke
grestore
gsave
0.001 setlinewidth
0.0 setgray
newpath
140 20 M 100 20 L
180 20 M 140 20 L
300 20 M 260 20 L
340 20 M 300 20 L
460 20 M 420 20 L
500 20 M 460 20 L
100 60 M 140 20 L
140 60 M 100 20 L
140 60 M 180 20 L
140 60 M 100 60 L
180 60 M 140 20 L
180 60 M 140 60 L
260 60 M 300 20 L
300 60 M 260 20 L
300 60 M 340 20 L
300 60 M 260 60 L
340 60 M 300 20 L
340 60 M 300 60 L
420 60 M 460 20 L
460 60 M 420 20 L
460 60 M 500 20 L
460 60 M 420 60 L
500 60 M 460 20 L
500 60 M 460 60 L
100 100 M 140 60 L
140 100 M 100 60 L
140 100 M 140 60 L
140 100 M 180 60 L
140 100 M 100 100 L
180 100 M 140 60 L
180 100 M 140 100 L
260 100 M 300 60 L
300 100 M 260 60 L
300 100 M 300 60 L
300 100 M 340 60 L
300 100 M 260 100 L
340 100 M 300 60 L
340 100 M 300 100 L
420 100 M 460 60 L
460 100 M 420 60 L
460 100 M 460 60 L
460 100 M 500 60 L
460 100 M 420 100 L
500 100 M 460 60 L
500 100 M 460 100 L
20 140 M 20 100 L
20 140 M 60 100 L
60 140 M 20 100 L
60 140 M 60 100 L
60 140 M 100 100 L
100 140 M 60 100 L
100 140 M 100 100 L
100 140 M 60 140 L
140 140 M 100 100 L
140 140 M 180 100 L
180 140 M 180 100 L
180 140 M 220 100 L
220 140 M 180 100 L
220 140 M 220 100 L
220 140 M 260 100 L
220 140 M 180 140 L
260 140 M 220 100 L
260 140 M 260 100 L
260 140 M 220 140 L
300 140 M 260 100 L
300 140 M 340 100 L
340 140 M 340 100 L
340 140 M 380 100 L
380 140 M 340 100 L
380 140 M 380 100 L
380 140 M 420 100 L
380 140 M 340 140 L
420 140 M 380 100 L
420 140 M 420 100 L
420 140 M 380 140 L
460 140 M 420 100 L
460 140 M 500 100 L
500 140 M 500 100 L
500 140 M 540 100 L
540 140 M 500 100 L
540 140 M 540 100 L
540 140 M 580 100 L
540 140 M 500 140 L
580 140 M 540 100 L
580 140 M 580 100 L
20 180 M 20 140 L
20 180 M 60 140 L
60 180 M 20 140 L
60 180 M 60 140 L
60 180 M 100 140 L
100 180 M 60 140 L
100 180 M 100 140 L
100 180 M 140 140 L
140 180 M 100 180 L
180 180 M 140 140 L
180 180 M 180 140 L
180 180 M 220 140 L
180 180 M 140 180 L
220 180 M 180 140 L
220 180 M 220 140 L
stroke
newpath
220 180 M 260 140 L
260 180 M 220 140 L
260 180 M 260 140 L
260 180 M 300 140 L
300 180 M 260 180 L
340 180 M 300 140 L
340 180 M 340 140 L
340 180 M 380 140 L
340 180 M 300 180 L
380 180 M 340 140 L
380 180 M 380 140 L
380 180 M 420 140 L
420 180 M 380 140 L
420 180 M 420 140 L
420 180 M 460 140 L
460 180 M 420 180 L
500 180 M 460 140 L
500 180 M 500 140 L
500 180 M 540 140 L
500 180 M 460 180 L
540 180 M 500 140 L
540 180 M 540 140 L
540 180 M 580 140 L
580 180 M 540 140 L
580 180 M 580 140 L
100 220 M 140 180 L
140 220 M 100 180 L
140 220 M 140 180 L
140 220 M 180 180 L
140 220 M 100 220 L
180 220 M 140 180 L
180 220 M 140 220 L
260 220 M 300 180 L
300 220 M 260 180 L
300 220 M 300 180 L
300 220 M 340 180 L
300 220 M 260 220 L
340 220 M 300 180 L
340 220 M 300 220 L
420 220 M 460 180 L
460 220 M 420 180 L
460 220 M 460 180 L
460 220 M 500 180 L
460 220 M 420 220 L
500 220 M 460 180 L
500 220 M 460 220 L
100 260 M 140 220 L
140 260 M 100 220 L
140 260 M 140 220 L
140 260 M 180 220 L
140 260 M 100 260 L
180 260 M 140 220 L
180 260 M 140 260 L
260 260 M 300 220 L
300 260 M 260 220 L
300 260 M 300 220 L
300 260 M 340 220 L
300 260 M 260 260 L
340 260 M 300 220 L
340 260 M 300 260 L
420 260 M 460 220 L
460 260 M 420 220 L
460 260 M 460 220 L
460 260 M 500 220 L
460 260 M 420 260 L
500 260 M 460 220 L
500 260 M 460 260 L
20 300 M 20 260 L
20 300 M 60 260 L
60 300 M 20 260 L
60 300 M 60 260 L
60 300 M 100 260 L
100 300 M 60 260 L
100 300 M 100 260 L
100 300 M 60 300 L
140 300 M 100 260 L
140 300 M 180 260 L
180 300 M 180 260 L
180 300 M 220 260 L
220 300 M 180 260 L
220 300 M 220 260 L
220 300 M 260 260 L
220 300 M 180 300 L
260 300 M 220 260 L
260 300 M 260 260 L
260 300 M 220 300 L
300 300 M 260 260 L
300 300 M 340 260 L
340 300 M 340 260 L
340 300 M 380 260 L
380 300 M 340 260 L
380 300 M 380 260 L
380 300 M 420 260 L
380 300 M 340 300 L
420 300 M 380 260 L
420 300 M 420 260 L
420 300 M 380 300 L
460 300 M 420 260 L
460 300 M 500 260 L
500 300 M 500 260 L
stroke
newpath
500 300 M 540 260 L
540 300 M 500 260 L
540 300 M 540 260 L
540 300 M 580 260 L
540 300 M 500 300 L
580 300 M 540 260 L
580 300 M 580 260 L
20 340 M 20 300 L
20 340 M 60 300 L
60 340 M 20 300 L
60 340 M 60 300 L
60 340 M 100 300 L
100 340 M 60 300 L
100 340 M 100 300 L
100 340 M 140 300 L
140 340 M 100 340 L
180 340 M 140 300 L
180 340 M 180 300 L
180 340 M 220 300 L
180 340 M 140 340 L
220 340 M 180 300 L
220 340 M 220 300 L
220 340 M 260 300 L
260 340 M 220 300 L
260 340 M 260 300 L
260 340 M 300 300 L
300 340 M 260 340 L
340 340 M 300 300 L
340 340 M 340 300 L
340 340 M 380 300 L
340 340 M 300 340 L
380 340 M 340 300 L
380 340 M 380 300 L
380 340 M 420 300 L
420 340 M 380 300 L
420 340 M 420 300 L
420 340 M 460 300 L
460 340 M 420 340 L
500 340 M 460 300 L
500 340 M 500 300 L
500 340 M 540 300 L
500 340 M 460 340 L
540 340 M 500 300 L
540 340 M 540 300 L
540 340 M 580 300 L
580 340 M 540 300 L
580 340 M 580 300 L
100 380 M 140 340 L
140 380 M 100 340 L
140 380 M 140 340 L
140 380 M 180 340 L
140 380 M 100 380 L
180 380 M 140 340 L
180 380 M 140 380 L
260 380 M 300 340 L
300 380 M 260 340 L
300 380 M 300 340 L
300 380 M 340 340 L
300 380 M 260 380 L
340 380 M 300 340 L
340 380 M 300 380 L
420 380 M 460 340 L
460 380 M 420 340 L
460 380 M 460 340 L
460 380 M 500 340 L
460 380 M 420 380 L
500 380 M 460 340 L
500 380 M 460 380 L
100 420 M 140 380 L
140 420 M 100 380 L
140 420 M 140 380 L
140 420 M 180 380 L
140 420 M 100 420 L
180 420 M 140 380 L
180 420 M 140 420 L
260 420 M 300 380 L
300 420 M 260 380 L
300 420 M 300 380 L
300 420 M 340 380 L
300 420 M 260 420 L
340 420 M 300 380 L
340 420 M 300 420 L
420 420 M 460 380 L
460 420 M 420 380 L
460 420 M 460 380 L
460 420 M 500 380 L
460 420 M 420 420 L
500 420 M 460 380 L
500 420 M 460 420 L
20 460 M 20 420 L
20 460 M 60 420 L
60 460 M 20 420 L
60 460 M 60 420 L
60 460 M 100 420 L
100 460 M 60 420 L
100 460 M 100 420 L
100 460 M 60 460 L
140 460 M 100 420 L
140 460 M 180 420 L
180 460 M 180 420 L
stroke
newpath
180 460 M 220 420 L
220 460 M 180 420 L
220 460 M 220 420 L
220 460 M 260 420 L
220 460 M 180 460 L
260 460 M 220 420 L
260 460 M 260 420 L
260 460 M 220 460 L
300 460 M 260 420 L
300 460 M 340 420 L
340 460 M 340 420 L
340 460 M 380 420 L
380 460 M 340 420 L
380 460 M 380 420 L
380 460 M 420 420 L
380 460 M 340 460 L
420 460 M 380 420 L
420 460 M 420 420 L
420 460 M 380 460 L
460 460 M 420 420 L
460 460 M 500 420 L
500 460 M 500 420 L
500 460 M 540 420 L
540 460 M 500 420 L
540 460 M 540 420 L
540 460 M 580 420 L
540 460 M 500 460 L
580 460 M 540 420 L
580 460 M 580 420 L
20 500 M 20 460 L
20 500 M 60 460 L
60 500 M 20 460 L
60 500 M 60 460 L
60 500 M 100 460 L
100 500 M 60 460 L
100 500 M 100 460 L
100 500 M 140 460 L
140 500 M 100 500 L
180 500 M 140 460 L
180 500 M 180 460 L
180 500 M 220 460 L
180 500 M 140 500 L
220 500 M 180 460 L
220 500 M 220 460 L
220 500 M 260 460 L
260 500 M 220 460 L
260 500 M 260 460 L
260 500 M 300 460 L
300 500 M 260 500 L
340 500 M 300 460 L
340 500 M 340 460 L
340 500 M 380 460 L
340 500 M 300 500 L
380 500 M 340 460 L
380 500 M 380 460 L
380 500 M 420 460 L
420 500 M 380 460 L
420 500 M 420 460 L
420 500 M 460 460 L
460 500 M 420 500 L
500 500 M 460 460 L
500 500 M 500 460 L
500 500 M 540 460 L
500 500 M 460 500 L
540 500 M 500 460 L
540 500 M 540 460 L
540 500 M 580 460 L
580 500 M 540 460 L
580 500 M 580 460 L
100 540 M 140 500 L
140 540 M 100 500 L
140 540 M 140 500 L
140 540 M 180 500 L
140 540 M 100 540 L
180 540 M 140 500 L
180 540 M 140 540 L
260 540 M 300 500 L
300 540 M 260 500 L
300 540 M 300 500 L
300 540 M 340 500 L
300 540 M 260 540 L
340 540 M 300 500 L
340 540 M 300 540 L
420 540 M 460 500 L
460 540 M 420 500 L
460 540 M 460 500 L
460 540 M 500 500 L
460 540 M 420 540 L
500 540 M 460 500 L
500 540 M 460 540 L
100 580 M 140 540 L
140 580 M 100 540 L
140 580 M 180 540 L
140 580 M 100 580 L
180 580 M 140 540 L
180 580 M 140 580 L
260 580 M 300 540 L
300 580 M 260 540 L
300 580 M 340 540 L
300 580 M 260 580 L
stroke
newpath
340 580 M 300 540 L
340 580 M 300 580 L
420 580 M 460 540 L
460 580 M 420 540 L
460 580 M 500 540 L
460 580 M 420 580 L
500 580 M 460 540 L
500 580 M 460 580 L
stroke
grestore
gsave
0.1 setlinewidth
0.0 setgray
20.000 20.000 (0) radius drawLabel
60.000 20.000 (0) radius drawLabel
100.002 20.000 (0) radius drawLabel
140.002 20.000 (2) radius drawLabel
179.998 20.000 (0) radius drawLabel
219.998 20.000 (0) radius drawLabel
259.999 20.000 (0) radius drawLabel
300.000 20.000 (2) radius drawLabel
340.001 20.000 (0) radius drawLabel
380.002 20.000 (0) radius drawLabel
420.002 20.000 (0) radius drawLabel
459.998 20.000 (2) radius drawLabel
499.998 20.000 (0) radius drawLabel
539.999 20.000 (0) radius drawLabel
580.000 20.000 (0) radius drawLabel
20.000 60.000 (0) radius drawLabel
60.000 60.000 (0) radius drawLabel
100.002 60.000 (0) radius drawLabel
140.002 60.000 (2) radius drawLabel
179.998 60.000 (0) radius drawLabel
219.998 60.000 (0) radius drawLabel
259.999 60.000 (0) radius drawLabel
300.000 60.000 (2) radius drawLabel
340.001 60.000 (0) radius drawLabel
380.002 60.000 (0) radius drawLabel
420.002 60.000 (0) radius drawLabel
459.998 60.000 (2) radius drawLabel
499.998 60.000 (0) radius drawLabel
539.999 60.000 (0) radius drawLabel
580.000 60.000 (0) radius drawLabel
20.000 100.002 (0) radius drawLabel
60.000 100.002 (0) radius drawLabel
100.002 100.002 (0) radius drawLabel
140.002 100.002 (4) radius drawLabel
179.998 100.002 (0) radius drawLabel
219.998 100.002 (0) radius drawLabel
259.999 100.002 (0) radius drawLabel
300.000 100.002 (4) radius drawLabel
340.001 100.002 (0) radius drawLabel
380.002 100.002 (0) radius drawLabel
420.002 100.002 (0) radius drawLabel
459.998 100.002 (4) radius drawLabel
499.998 100.002 (0) radius drawLabel
539.999 100.002 (0) radius drawLabel
580.000 100.002 (0) radius drawLabel
20.000 140.002 (2) radius drawLabel
60.000 140.002 (2) radius drawLabel
100.002 140.002 (4) radius drawLabel
140.002 140.002 (4) radius drawLabel
179.998 140.002 (4) radius drawLabel
219.998 140.002 (2) radius drawLabel
259.999 140.002 (4) radius drawLabel
300.000 140.002 (4) radius drawLabel
340.001 140.002 (4) radius drawLabel
380.002 140.002 (2) radius drawLabel
420.002 140.002 (4) radius drawLabel
459.998 140.002 (4) radius drawLabel
499.998 140.002 (4) radius drawLabel
539.999 140.002 (2) radius drawLabel
580.000 140.002 (2) radius drawLabel
20.000 179.998 (0) radius drawLabel
60.000 179.998 (0) radius drawLabel
100.002 179.998 (0) radius drawLabel
140.002 179.998 (4) radius drawLabel
179.998 179.998 (0) radius drawLabel
219.998 179.998 (0) radius drawLabel
259.999 179.998 (0) radius drawLabel
300.000 179.998 (4) radius drawLabel
340.001 179.998 (0) radius drawLabel
380.002 179.998 (0) radius drawLabel
420.002 179.998 (0) radius drawLabel
459.998 179.998 (4) radius drawLabel
499.998 179.998 (0) radius drawLabel
539.999 179.998 (0) radius drawLabel
580.000 179.998 (0) radius drawLabel
20.000 219.998 (0) radius drawLabel
60.000 219.998 (0) radius drawLabel
100.002 219.998 (0) radius drawLabel
140.002 219.998 (2) radius drawLabel
179.998 219.998 (0) radius drawLabel
219.998 219.998 (0) radius drawLabel
259.999 219.998 (0) radius drawLabel
300.000 219.998 (2) radius drawLabel
340.001 219.998 (0) radius drawLabel
380.002 219.998 (0) radius drawLabel
420.002 219.998 (0) radius drawLabel
459.998 219.998 (2) radius drawLabel
499.998 219.998 (0) radius drawLabel
539.999 219.998 (0) radius drawLabel
580.000 219.998 (0) radius drawLabel
20.000 259.999 (0) radius drawLabel
60.000 259.999 (0) radius drawLabel
100.002 259.999 (0) radius drawLabel
140.002 259.999 (4) radius drawLabel
179.998 259.999 (0) radius drawLabel
219.998 259.999 (0) radius drawLabel
259.999 259.999 (0) radius drawLabel
300.000 259.999 (4) radius drawLabel
340.001 259.999 (0) radius drawLabel
380.002 259.999 (0) radius drawLabel
420.002 259.999 (0) radius drawLabel
459.998 259.999 (4) radius drawLabel
499.998 259.999 (0) radius drawLabel
539.999 259.999 (0) radius drawLabel
580.000 259.999 (0) radius drawLabel
20.000 300.000 (2) radius drawLabel
60.000 300.000 (2) radius drawLabel
100.002 300.000 (4) radius drawLabel
140.002 300.000 (4) radius drawLabel
179.998 300.000 (4) radius drawLabel
219.998 300.000 (2) radius drawLabel
259.999 300.000 (4) radius drawLabel
300.000 300.000 (4) radius drawLabel
340.001 300.000 (4) radius drawLabel
380.002 300.000 (2) radius drawLabel
420.002 300.000 (4) radius drawLabel
459.998 300.000 (4) radius drawLabel
499.998 300.000 (4) radius drawLabel
539.999 300.000 (2) radius drawLabel
580.000 300.000 (2) radius drawLabel
20.000 340.001 (0) radius drawLabel
60.000 340.001 (0) radius drawLabel
100.002 340.001 (0) radius drawLabel
140.002 340.001 (4) radius drawLabel
179.998 340.001 (0) radius drawLabel
219.998 340.001 (0) radius drawLabel
259.999 340.001 (0) radius drawLabel
300.000 340.001 (4) radius drawLabel
340.001 340.001 (0) radius drawLabel
380.002 340.001 (0) radius drawLabel
420.002 340.001 (0) radius drawLabel
459.998 340.001 (4) radius drawLabel
499.998 340.001 (0) radius drawLabel
539.999 340.001 (0) radius drawLabel
580.000 340.001 (0) radius drawLabel
20.000 380.002 (0) radius drawLabel
60.000 380.002 (0) radius drawLabel
100.002 380.002 (0) radius drawLabel
140.002 380.002 (2) radius drawLabel
179.998 380.002 (0) radius drawLabel
219.998 380.002 (0) radius drawLabel
259.999 380.002 (0) radius drawLabel
300.000 380.002 (2) radius drawLabel
340.001 380.002 (0) radius drawLabel
380.002 380.002 (0) radius drawLabel
420.002 380.002 (0) radius drawLabel
459.998 380.002 (2) radius drawLabel
499.998 380.002 (0) radius drawLabel
539.999 380.002 (0) radius drawLabel
580.000 380.002 (0) radius drawLabel
20.000 420.002 (0) radius drawLabel
60.000 420.002 (0) radius drawLabel
100.002 420.002 (0) radius drawLabel
140.002 420.002 (4) radius drawLabel
179.998 420.002 (0) radius drawLabel
219.998 420.002 (0) radius drawLabel
259.999 420.002 (0) radius drawLabel
300.000 420.002 (4) radius drawLabel
340.001 420.002 (0) radius drawLabel
380.002 420.002 (0) radius drawLabel
420.002 420.002 (0) radius drawLabel
459.998 420.002 (4) radius drawLabel
499.998 420.002 (0) radius drawLabel
539.999 420.002 (0) radius drawLabel
580.000 420.002 (0) radius drawLabel
20.000 459.998 (2) radius drawLabel
60.000 459.998 (2) radius drawLabel
100.002 459.998 (4) radius drawLabel
140.002 459.998 (4) radius drawLabel
179.998 459.998 (4) radius drawLabel
219.998 459.998 (2) radius drawLabel
259.999 459.998 (4) radius drawLabel
300.000 459.998 (4) radius drawLabel
340.001 459.998 (4) radius drawLabel
380.002 459.998 (2) radius drawLabel
420.002 459.998 (4) radius drawLabel
459.998 459.998 (4) radius drawLabel
499.998 459.998 (4) radius drawLabel
539.999 459.998 (2) radius drawLabel
580.000 459.998 (2) radius drawLabel
20.000 499.998 (0) radius drawLabel
60.000 499.998 (0) radius drawLabel
100.002 499.998 (0) radius drawLabel
140.002 499.998 (4) radius drawLabel
179.998 499.998 (0) radius drawLabel
219.998 499.998 (0) radius drawLabel
259.999 499.998 (0) radius drawLabel
300.000 499.998 (4) radius drawLabel
340.001 499.998 (0) radius drawLabel
380.002 499.998 (0) radius drawLabel
420.002 499.998 (0) radius drawLabel
459.998 499.998 (4) radius drawLabel
499.998 499.998 (0) radius drawLabel
539.999 499.998 (0) radius drawLabel
580.000 499.998 (0) radius drawLabel
20.000 539.999 (0) radius drawLabel
60.000 539.999 (0) radius drawLabel
100.002 539.999 (0) radius drawLabel
140.002 539.999 (2) radius drawLabel
179.998 539.999 (0) radius drawLabel
219.998 539.999 (0) radius drawLabel
259.999 539.999 (0) radius drawLabel
300.000 539.999 (2) radius drawLabel
340.001 539.999 (0) radius drawLabel
380.002 539.999 (0) radius drawLabel
420.002 539.999 (0) radius drawLabel
459.998 539.999 (2) radius drawLabel
499.998 539.999 (0) radius drawLabel
539.999 539.999 (0) radius drawLabel
580.000 539.999 (0) radius drawLabel
20.000 580.000 (0) radius drawLabel
60.000 580.000 (0) radius drawLabel
100.002 580.000 (0) radius drawLabel
140.002 580.000 (2) radius drawLabel
179.998 580.000 (0) radius drawLabel
219.998 580.000 (0) radius drawLabel
259.999 580.000 (0) radius drawLabel
300.000 580.000 (2) radius drawLabel
340.001 580.000 (0) radius drawLabel
380.002 580.000 (0) radius drawLabel
420.002 580.000 (0) radius drawLabel
459.998 580.000 (2) radius drawLabel
499.998 580.000 (0) radius drawLabel
539.999 580.000 (0) radius drawLabel
580.000 580.000 (0) radius drawLabel
grestore
showpage
260 500 M 300 460 L
300 500 M 260 500 L
340 500 M 300 460 L
340 500 M 340 460 L
340Graph/doc/rad1.eps 0100644 0002055 0007177 00000074615 06534106105 0015254 0 ustar 00cleve compmath 0000040 0000006 %!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 0.0 0.0 600.0 600.0
/radius 15 def
/Helvetica findfont 18.75 scalefont setfont
/M {moveto} def
/L {lineto} def
/ACF { % stack : x y radius
newpath 0 360 arc closepath fill
} def
/str 6 string def
/drawLabel { % x y label radius
/radius exch def
/label exch def
/y exch def
/x exch def
gsave
1.0 setgray
x radius add y moveto
x y radius 0 360 arc
fill
0.0 setgray
x radius add y moveto
x y radius 0 360 arc
stroke
x y moveto
label stringwidth pop 2 div neg radius 2 div neg rmoveto
label show
grestore
} def
gsave
0.001 setlinewidth
0.0 setgray
newpath
60 20 M 20 20 L
100 20 M 60 20 L
220 20 M 180 20 L
260 20 M 220 20 L
380 20 M 340 20 L
420 20 M 380 20 L
540 20 M 500 20 L
580 20 M 540 20 L
20 60 M 20 20 L
20 60 M 60 20 L
60 60 M 20 20 L
60 60 M 60 20 L
60 60 M 100 20 L
60 60 M 20 60 L
100 60 M 60 20 L
100 60 M 100 20 L
100 60 M 60 60 L
140 60 M 140 20 L
180 60 M 180 20 L
180 60 M 220 20 L
220 60 M 180 20 L
220 60 M 220 20 L
220 60 M 260 20 L
220 60 M 180 60 L
260 60 M 220 20 L
260 60 M 260 20 L
260 60 M 220 60 L
300 60 M 300 20 L
340 60 M 340 20 L
340 60 M 380 20 L
380 60 M 340 20 L
380 60 M 380 20 L
380 60 M 420 20 L
380 60 M 340 60 L
420 60 M 380 20 L
420 60 M 420 20 L
420 60 M 380 60 L
460 60 M 460 20 L
500 60 M 500 20 L
500 60 M 540 20 L
540 60 M 500 20 L
540 60 M 540 20 L
540 60 M 580 20 L
540 60 M 500 60 L
580 60 M 540 20 L
580 60 M 580 20 L
580 60 M 540 60 L
20 100 M 20 60 L
20 100 M 60 60 L
60 100 M 20 60 L
60 100 M 60 60 L
60 100 M 100 60 L
60 100 M 20 100 L
100 100 M 60 60 L
100 100 M 100 60 L
100 100 M 60 100 L
140 100 M 140 60 L
180 100 M 180 60 L
180 100 M 220 60 L
220 100 M 180 60 L
220 100 M 220 60 L
220 100 M 260 60 L
220 100 M 180 100 L
260 100 M 220 60 L
260 100 M 260 60 L
260 100 M 220 100 L
300 100 M 300 60 L
340 100 M 340 60 L
340 100 M 380 60 L
380 100 M 340 60 L
380 100 M 380 60 L
380 100 M 420 60 L
380 100 M 340 100 L
420 100 M 380 60 L
420 100 M 420 60 L
420 100 M 380 100 L
460 100 M 460 60 L
500 100 M 500 60 L
500 100 M 540 60 L
540 100 M 500 60 L
540 100 M 540 60 L
540 100 M 580 60 L
540 100 M 500 100 L
580 100 M 540 60 L
580 100 M 580 60 L
580 100 M 540 100 L
60 140 M 20 140 L
100 140 M 140 100 L
100 140 M 60 140 L
180 140 M 140 100 L
220 140 M 180 140 L
260 140 M 300 100 L
260 140 M 220 140 L
340 140 M 300 100 L
380 140 M 340 140 L
420 140 M 460 100 L
420 140 M 380 140 L
500 140 M 460 100 L
540 140 M 500 140 L
580 140 M 540 140 L
stroke
newpath
60 180 M 20 180 L
100 180 M 60 180 L
140 180 M 100 140 L
140 180 M 180 140 L
220 180 M 180 180 L
260 180 M 220 180 L
300 180 M 260 140 L
300 180 M 340 140 L
380 180 M 340 180 L
420 180 M 380 180 L
460 180 M 420 140 L
460 180 M 500 140 L
540 180 M 500 180 L
580 180 M 540 180 L
20 220 M 20 180 L
20 220 M 60 180 L
60 220 M 20 180 L
60 220 M 60 180 L
60 220 M 100 180 L
60 220 M 20 220 L
100 220 M 60 180 L
100 220 M 100 180 L
100 220 M 60 220 L
140 220 M 140 180 L
180 220 M 180 180 L
180 220 M 220 180 L
220 220 M 180 180 L
220 220 M 220 180 L
220 220 M 260 180 L
220 220 M 180 220 L
260 220 M 220 180 L
260 220 M 260 180 L
260 220 M 220 220 L
300 220 M 300 180 L
340 220 M 340 180 L
340 220 M 380 180 L
380 220 M 340 180 L
380 220 M 380 180 L
380 220 M 420 180 L
380 220 M 340 220 L
420 220 M 380 180 L
420 220 M 420 180 L
420 220 M 380 220 L
460 220 M 460 180 L
500 220 M 500 180 L
500 220 M 540 180 L
540 220 M 500 180 L
540 220 M 540 180 L
540 220 M 580 180 L
540 220 M 500 220 L
580 220 M 540 180 L
580 220 M 580 180 L
580 220 M 540 220 L
20 260 M 20 220 L
20 260 M 60 220 L
60 260 M 20 220 L
60 260 M 60 220 L
60 260 M 100 220 L
60 260 M 20 260 L
100 260 M 60 220 L
100 260 M 100 220 L
100 260 M 60 260 L
140 260 M 140 220 L
180 260 M 180 220 L
180 260 M 220 220 L
220 260 M 180 220 L
220 260 M 220 220 L
220 260 M 260 220 L
220 260 M 180 260 L
260 260 M 220 220 L
260 260 M 260 220 L
260 260 M 220 260 L
300 260 M 300 220 L
340 260 M 340 220 L
340 260 M 380 220 L
380 260 M 340 220 L
380 260 M 380 220 L
380 260 M 420 220 L
380 260 M 340 260 L
420 260 M 380 220 L
420 260 M 420 220 L
420 260 M 380 260 L
460 260 M 460 220 L
500 260 M 500 220 L
500 260 M 540 220 L
540 260 M 500 220 L
540 260 M 540 220 L
540 260 M 580 220 L
540 260 M 500 260 L
580 260 M 540 220 L
580 260 M 580 220 L
580 260 M 540 260 L
60 300 M 20 300 L
100 300 M 140 260 L
100 300 M 60 300 L
180 300 M 140 260 L
220 300 M 180 300 L
260 300 M 300 260 L
260 300 M 220 300 L
340 300 M 300 260 L
stroke
newpath
380 300 M 340 300 L
420 300 M 460 260 L
420 300 M 380 300 L
500 300 M 460 260 L
540 300 M 500 300 L
580 300 M 540 300 L
60 340 M 20 340 L
100 340 M 60 340 L
140 340 M 100 300 L
140 340 M 180 300 L
220 340 M 180 340 L
260 340 M 220 340 L
300 340 M 260 300 L
300 340 M 340 300 L
380 340 M 340 340 L
420 340 M 380 340 L
460 340 M 420 300 L
460 340 M 500 300 L
540 340 M 500 340 L
580 340 M 540 340 L
20 380 M 20 340 L
20 380 M 60 340 L
60 380 M 20 340 L
60 380 M 60 340 L
60 380 M 100 340 L
60 380 M 20 380 L
100 380 M 60 340 L
100 380 M 100 340 L
100 380 M 60 380 L
140 380 M 140 340 L
180 380 M 180 340 L
180 380 M 220 340 L
220 380 M 180 340 L
220 380 M 220 340 L
220 380 M 260 340 L
220 380 M 180 380 L
260 380 M 220 340 L
260 380 M 260 340 L
260 380 M 220 380 L
300 380 M 300 340 L
340 380 M 340 340 L
340 380 M 380 340 L
380 380 M 340 340 L
380 380 M 380 340 L
380 380 M 420 340 L
380 380 M 340 380 L
420 380 M 380 340 L
420 380 M 420 340 L
420 380 M 380 380 L
460 380 M 460 340 L
500 380 M 500 340 L
500 380 M 540 340 L
540 380 M 500 340 L
540 380 M 540 340 L
540 380 M 580 340 L
540 380 M 500 380 L
580 380 M 540 340 L
580 380 M 580 340 L
580 380 M 540 380 L
20 420 M 20 380 L
20 420 M 60 380 L
60 420 M 20 380 L
60 420 M 60 380 L
60 420 M 100 380 L
60 420 M 20 420 L
100 420 M 60 380 L
100 420 M 100 380 L
100 420 M 60 420 L
140 420 M 140 380 L
180 420 M 180 380 L
180 420 M 220 380 L
220 420 M 180 380 L
220 420 M 220 380 L
220 420 M 260 380 L
220 420 M 180 420 L
260 420 M 220 380 L
260 420 M 260 380 L
260 420 M 220 420 L
300 420 M 300 380 L
340 420 M 340 380 L
340 420 M 380 380 L
380 420 M 340 380 L
380 420 M 380 380 L
380 420 M 420 380 L
380 420 M 340 420 L
420 420 M 380 380 L
420 420 M 420 380 L
420 420 M 380 420 L
460 420 M 460 380 L
500 420 M 500 380 L
500 420 M 540 380 L
540 420 M 500 380 L
540 420 M 540 380 L
540 420 M 580 380 L
540 420 M 500 420 L
580 420 M 540 380 L
580 420 M 580 380 L
580 420 M 540 420 L
60 460 M 20 460 L
100 460 M 140 420 L
stroke
newpath
100 460 M 60 460 L
180 460 M 140 420 L
220 460 M 180 460 L
260 460 M 300 420 L
260 460 M 220 460 L
340 460 M 300 420 L
380 460 M 340 460 L
420 460 M 460 420 L
420 460 M 380 460 L
500 460 M 460 420 L
540 460 M 500 460 L
580 460 M 540 460 L
60 500 M 20 500 L
100 500 M 60 500 L
140 500 M 100 460 L
140 500 M 180 460 L
220 500 M 180 500 L
260 500 M 220 500 L
300 500 M 260 460 L
300 500 M 340 460 L
380 500 M 340 500 L
420 500 M 380 500 L
460 500 M 420 460 L
460 500 M 500 460 L
540 500 M 500 500 L
580 500 M 540 500 L
20 540 M 20 500 L
20 540 M 60 500 L
60 540 M 20 500 L
60 540 M 60 500 L
60 540 M 100 500 L
60 540 M 20 540 L
100 540 M 60 500 L
100 540 M 100 500 L
100 540 M 60 540 L
140 540 M 140 500 L
180 540 M 180 500 L
180 540 M 220 500 L
220 540 M 180 500 L
220 540 M 220 500 L
220 540 M 260 500 L
220 540 M 180 540 L
260 540 M 220 500 L
260 540 M 260 500 L
260 540 M 220 540 L
300 540 M 300 500 L
340 540 M 340 500 L
340 540 M 380 500 L
380 540 M 340 500 L
380 540 M 380 500 L
380 540 M 420 500 L
380 540 M 340 540 L
420 540 M 380 500 L
420 540 M 420 500 L
420 540 M 380 540 L
460 540 M 460 500 L
500 540 M 500 500 L
500 540 M 540 500 L
540 540 M 500 500 L
540 540 M 540 500 L
540 540 M 580 500 L
540 540 M 500 540 L
580 540 M 540 500 L
580 540 M 580 500 L
580 540 M 540 540 L
20 580 M 20 540 L
20 580 M 60 540 L
60 580 M 20 540 L
60 580 M 60 540 L
60 580 M 100 540 L
60 580 M 20 580 L
100 580 M 60 540 L
100 580 M 100 540 L
100 580 M 60 580 L
140 580 M 140 540 L
180 580 M 180 540 L
180 580 M 220 540 L
220 580 M 180 540 L
220 580 M 220 540 L
220 580 M 260 540 L
220 580 M 180 580 L
260 580 M 220 540 L
260 580 M 260 540 L
260 580 M 220 580 L
300 580 M 300 540 L
340 580 M 340 540 L
340 580 M 380 540 L
380 580 M 340 540 L
380 580 M 380 540 L
380 580 M 420 540 L
380 580 M 340 580 L
420 580 M 380 540 L
420 580 M 420 540 L
420 580 M 380 580 L
460 580 M 460 540 L
500 580 M 500 540 L
500 580 M 540 540 L
540 580 M 500 540 L
540 580 M 540 540 L
540 580 M 580 540 L
stroke
newpath
540 580 M 500 580 L
580 580 M 540 540 L
580 580 M 580 540 L
580 580 M 540 580 L
stroke
grestore
gsave
0.001 setlinewidth
0.0 setgray
newpath
140 20 M 100 20 L
180 20 M 140 20 L
300 20 M 260 20 L
340 20 M 300 20 L
460 20 M 420 20 L
500 20 M 460 20 L
100 60 M 140 20 L
140 60 M 100 20 L
140 60 M 180 20 L
140 60 M 100 60 L
180 60 M 140 20 L
180 60 M 140 60 L
260 60 M 300 20 L
300 60 M 260 20 L
300 60 M 340 20 L
300 60 M 260 60 L
340 60 M 300 20 L
340 60 M 300 60 L
420 60 M 460 20 L
460 60 M 420 20 L
460 60 M 500 20 L
460 60 M 420 60 L
500 60 M 460 20 L
500 60 M 460 60 L
100 100 M 140 60 L
140 100 M 100 60 L
140 100 M 180 60 L
140 100 M 100 100 L
180 100 M 140 60 L
180 100 M 140 100 L
260 100 M 300 60 L
300 100 M 260 60 L
300 100 M 340 60 L
300 100 M 260 100 L
340 100 M 300 60 L
340 100 M 300 100 L
420 100 M 460 60 L
460 100 M 420 60 L
460 100 M 500 60 L
460 100 M 420 100 L
500 100 M 460 60 L
500 100 M 460 100 L
20 140 M 20 100 L
20 140 M 60 100 L
60 140 M 20 100 L
60 140 M 60 100 L
60 140 M 100 100 L
100 140 M 60 100 L
100 140 M 100 100 L
140 140 M 100 100 L
140 140 M 140 100 L
140 140 M 180 100 L
140 140 M 100 140 L
180 140 M 180 100 L
180 140 M 220 100 L
180 140 M 140 140 L
220 140 M 180 100 L
220 140 M 220 100 L
220 140 M 260 100 L
260 140 M 220 100 L
260 140 M 260 100 L
300 140 M 260 100 L
300 140 M 300 100 L
300 140 M 340 100 L
300 140 M 260 140 L
340 140 M 340 100 L
340 140 M 380 100 L
340 140 M 300 140 L
380 140 M 340 100 L
380 140 M 380 100 L
380 140 M 420 100 L
420 140 M 380 100 L
420 140 M 420 100 L
460 140 M 420 100 L
460 140 M 460 100 L
460 140 M 500 100 L
460 140 M 420 140 L
500 140 M 500 100 L
500 140 M 540 100 L
500 140 M 460 140 L
540 140 M 500 100 L
540 140 M 540 100 L
540 140 M 580 100 L
580 140 M 540 100 L
580 140 M 580 100 L
20 180 M 20 140 L
20 180 M 60 140 L
60 180 M 20 140 L
60 180 M 60 140 L
60 180 M 100 140 L
100 180 M 60 140 L
100 180 M 100 140 L
100 180 M 140 140 L
140 180 M 140 140 L
140 180 M 100 180 L
180 180 M 140 140 L
180 180 M 180 140 L
180 180 M 220 140 L
180 180 M 140 180 L
220 180 M 180 140 L
stroke
newpath
220 180 M 220 140 L
220 180 M 260 140 L
260 180 M 220 140 L
260 180 M 260 140 L
260 180 M 300 140 L
300 180 M 300 140 L
300 180 M 260 180 L
340 180 M 300 140 L
340 180 M 340 140 L
340 180 M 380 140 L
340 180 M 300 180 L
380 180 M 340 140 L
380 180 M 380 140 L
380 180 M 420 140 L
420 180 M 380 140 L
420 180 M 420 140 L
420 180 M 460 140 L
460 180 M 460 140 L
460 180 M 420 180 L
500 180 M 460 140 L
500 180 M 500 140 L
500 180 M 540 140 L
500 180 M 460 180 L
540 180 M 500 140 L
540 180 M 540 140 L
540 180 M 580 140 L
580 180 M 540 140 L
580 180 M 580 140 L
100 220 M 140 180 L
140 220 M 100 180 L
140 220 M 180 180 L
140 220 M 100 220 L
180 220 M 140 180 L
180 220 M 140 220 L
260 220 M 300 180 L
300 220 M 260 180 L
300 220 M 340 180 L
300 220 M 260 220 L
340 220 M 300 180 L
340 220 M 300 220 L
420 220 M 460 180 L
460 220 M 420 180 L
460 220 M 500 180 L
460 220 M 420 220 L
500 220 M 460 180 L
500 220 M 460 220 L
100 260 M 140 220 L
140 260 M 100 220 L
140 260 M 180 220 L
140 260 M 100 260 L
180 260 M 140 220 L
180 260 M 140 260 L
260 260 M 300 220 L
300 260 M 260 220 L
300 260 M 340 220 L
300 260 M 260 260 L
340 260 M 300 220 L
340 260 M 300 260 L
420 260 M 460 220 L
460 260 M 420 220 L
460 260 M 500 220 L
460 260 M 420 260 L
500 260 M 460 220 L
500 260 M 460 260 L
20 300 M 20 260 L
20 300 M 60 260 L
60 300 M 20 260 L
60 300 M 60 260 L
60 300 M 100 260 L
100 300 M 60 260 L
100 300 M 100 260 L
140 300 M 100 260 L
140 300 M 140 260 L
140 300 M 180 260 L
140 300 M 100 300 L
180 300 M 180 260 L
180 300 M 220 260 L
180 300 M 140 300 L
220 300 M 180 260 L
220 300 M 220 260 L
220 300 M 260 260 L
260 300 M 220 260 L
260 300 M 260 260 L
300 300 M 260 260 L
300 300 M 300 260 L
300 300 M 340 260 L
300 300 M 260 300 L
340 300 M 340 260 L
340 300 M 380 260 L
340 300 M 300 300 L
380 300 M 340 260 L
380 300 M 380 260 L
380 300 M 420 260 L
420 300 M 380 260 L
420 300 M 420 260 L
460 300 M 420 260 L
460 300 M 460 260 L
460 300 M 500 260 L
460 300 M 420 300 L
500 300 M 500 260 L
stroke
newpath
500 300 M 540 260 L
500 300 M 460 300 L
540 300 M 500 260 L
540 300 M 540 260 L
540 300 M 580 260 L
580 300 M 540 260 L
580 300 M 580 260 L
20 340 M 20 300 L
20 340 M 60 300 L
60 340 M 20 300 L
60 340 M 60 300 L
60 340 M 100 300 L
100 340 M 60 300 L
100 340 M 100 300 L
100 340 M 140 300 L
140 340 M 140 300 L
140 340 M 100 340 L
180 340 M 140 300 L
180 340 M 180 300 L
180 340 M 220 300 L
180 340 M 140 340 L
220 340 M 180 300 L
220 340 M 220 300 L
220 340 M 260 300 L
260 340 M 220 300 L
260 340 M 260 300 L
260 340 M 300 300 L
300 340 M 300 300 L
300 340 M 260 340 L
340 340 M 300 300 L
340 340 M 340 300 L
340 340 M 380 300 L
340 340 M 300 340 L
380 340 M 340 300 L
380 340 M 380 300 L
380 340 M 420 300 L
420 340 M 380 300 L
420 340 M 420 300 L
420 340 M 460 300 L
460 340 M 460 300 L
460 340 M 420 340 L
500 340 M 460 300 L
500 340 M 500 300 L
500 340 M 540 300 L
500 340 M 460 340 L
540 340 M 500 300 L
540 340 M 540 300 L
540 340 M 580 300 L
580 340 M 540 300 L
580 340 M 580 300 L
100 380 M 140 340 L
140 380 M 100 340 L
140 380 M 180 340 L
140 380 M 100 380 L
180 380 M 140 340 L
180 380 M 140 380 L
260 380 M 300 340 L
300 380 M 260 340 L
300 380 M 340 340 L
300 380 M 260 380 L
340 380 M 300 340 L
340 380 M 300 380 L
420 380 M 460 340 L
460 380 M 420 340 L
460 380 M 500 340 L
460 380 M 420 380 L
500 380 M 460 340 L
500 380 M 460 380 L
100 420 M 140 380 L
140 420 M 100 380 L
140 420 M 180 380 L
140 420 M 100 420 L
180 420 M 140 380 L
180 420 M 140 420 L
260 420 M 300 380 L
300 420 M 260 380 L
300 420 M 340 380 L
300 420 M 260 420 L
340 420 M 300 380 L
340 420 M 300 420 L
420 420 M 460 380 L
460 420 M 420 380 L
460 420 M 500 380 L
460 420 M 420 420 L
500 420 M 460 380 L
500 420 M 460 420 L
20 460 M 20 420 L
20 460 M 60 420 L
60 460 M 20 420 L
60 460 M 60 420 L
60 460 M 100 420 L
100 460 M 60 420 L
100 460 M 100 420 L
140 460 M 100 420 L
140 460 M 140 420 L
140 460 M 180 420 L
140 460 M 100 460 L
180 460 M 180 420 L
180 460 M 220 420 L
180 460 M 140 460 L
stroke
newpath
220 460 M 180 420 L
220 460 M 220 420 L
220 460 M 260 420 L
260 460 M 220 420 L
260 460 M 260 420 L
300 460 M 260 420 L
300 460 M 300 420 L
300 460 M 340 420 L
300 460 M 260 460 L
340 460 M 340 420 L
340 460 M 380 420 L
340 460 M 300 460 L
380 460 M 340 420 L
380 460 M 380 420 L
380 460 M 420 420 L
420 460 M 380 420 L
420 460 M 420 420 L
460 460 M 420 420 L
460 460 M 460 420 L
460 460 M 500 420 L
460 460 M 420 460 L
500 460 M 500 420 L
500 460 M 540 420 L
500 460 M 460 460 L
540 460 M 500 420 L
540 460 M 540 420 L
540 460 M 580 420 L
580 460 M 540 420 L
580 460 M 580 420 L
20 500 M 20 460 L
20 500 M 60 460 L
60 500 M 20 460 L
60 500 M 60 460 L
60 500 M 100 460 L
100 500 M 60 460 L
100 500 M 100 460 L
100 500 M 140 460 L
140 500 M 140 460 L
140 500 M 100 500 L
180 500 M 140 460 L
180 500 M 180 460 L
180 500 M 220 460 L
180 500 M 140 500 L
220 500 M 180 460 L
220 500 M 220 460 L
220 500 M 260 460 L
260 500 M 220 460 L
260 500 M 260 460 L
260 500 M 300 460 L
300 500 M 300 460 L
300 500 M 260 500 L
340 500 M 300 460 L
340 500 M 340 460 L
340 500 M 380 460 L
340 500 M 300 500 L
380 500 M 340 460 L
380 500 M 380 460 L
380 500 M 420 460 L
420 500 M 380 460 L
420 500 M 420 460 L
420 500 M 460 460 L
460 500 M 460 460 L
460 500 M 420 500 L
500 500 M 460 460 L
500 500 M 500 460 L
500 500 M 540 460 L
500 500 M 460 500 L
540 500 M 500 460 L
540 500 M 540 460 L
540 500 M 580 460 L
580 500 M 540 460 L
580 500 M 580 460 L
100 540 M 140 500 L
140 540 M 100 500 L
140 540 M 180 500 L
140 540 M 100 540 L
180 540 M 140 500 L
180 540 M 140 540 L
260 540 M 300 500 L
300 540 M 260 500 L
300 540 M 340 500 L
300 540 M 260 540 L
340 540 M 300 500 L
340 540 M 300 540 L
420 540 M 460 500 L
460 540 M 420 500 L
460 540 M 500 500 L
460 540 M 420 540 L
500 540 M 460 500 L
500 540 M 460 540 L
100 580 M 140 540 L
140 580 M 100 540 L
140 580 M 180 540 L
140 580 M 100 580 L
180 580 M 140 540 L
180 580 M 140 580 L
260 580 M 300 540 L
300 580 M 260 540 L
300 580 M 340 540 L
300 580 M 260 580 L
stroke
newpath
340 580 M 300 540 L
340 580 M 300 580 L
420 580 M 460 540 L
460 580 M 420 540 L
460 580 M 500 540 L
460 580 M 420 580 L
500 580 M 460 540 L
500 580 M 460 580 L
stroke
grestore
gsave
0.1 setlinewidth
0.0 setgray
20.000 20.000 (0) radius drawLabel
60.000 20.000 (0) radius drawLabel
100.002 20.000 (0) radius drawLabel
140.002 20.000 (2) radius drawLabel
179.998 20.000 (0) radius drawLabel
219.998 20.000 (0) radius drawLabel
259.999 20.000 (0) radius drawLabel
300.000 20.000 (2) radius drawLabel
340.001 20.000 (0) radius drawLabel
380.002 20.000 (0) radius drawLabel
420.002 20.000 (0) radius drawLabel
459.998 20.000 (2) radius drawLabel
499.998 20.000 (0) radius drawLabel
539.999 20.000 (0) radius drawLabel
580.000 20.000 (0) radius drawLabel
20.000 60.000 (0) radius drawLabel
60.000 60.000 (0) radius drawLabel
100.002 60.000 (0) radius drawLabel
140.002 60.000 (2) radius drawLabel
179.998 60.000 (0) radius drawLabel
219.998 60.000 (0) radius drawLabel
259.999 60.000 (0) radius drawLabel
300.000 60.000 (2) radius drawLabel
340.001 60.000 (0) radius drawLabel
380.002 60.000 (0) radius drawLabel
420.002 60.000 (0) radius drawLabel
459.998 60.000 (2) radius drawLabel
499.998 60.000 (0) radius drawLabel
539.999 60.000 (0) radius drawLabel
580.000 60.000 (0) radius drawLabel
20.000 100.002 (0) radius drawLabel
60.000 100.002 (0) radius drawLabel
100.002 100.002 (0) radius drawLabel
140.002 100.002 (2) radius drawLabel
179.998 100.002 (0) radius drawLabel
219.998 100.002 (0) radius drawLabel
259.999 100.002 (0) radius drawLabel
300.000 100.002 (2) radius drawLabel
340.001 100.002 (0) radius drawLabel
380.002 100.002 (0) radius drawLabel
420.002 100.002 (0) radius drawLabel
459.998 100.002 (2) radius drawLabel
499.998 100.002 (0) radius drawLabel
539.999 100.002 (0) radius drawLabel
580.000 100.002 (0) radius drawLabel
20.000 140.002 (2) radius drawLabel
60.000 140.002 (2) radius drawLabel
100.002 140.002 (2) radius drawLabel
140.002 140.002 (4) radius drawLabel
179.998 140.002 (2) radius drawLabel
219.998 140.002 (2) radius drawLabel
259.999 140.002 (2) radius drawLabel
300.000 140.002 (4) radius drawLabel
340.001 140.002 (2) radius drawLabel
380.002 140.002 (2) radius drawLabel
420.002 140.002 (2) radius drawLabel
459.998 140.002 (4) radius drawLabel
499.998 140.002 (2) radius drawLabel
539.999 140.002 (2) radius drawLabel
580.000 140.002 (2) radius drawLabel
20.000 179.998 (0) radius drawLabel
60.000 179.998 (0) radius drawLabel
100.002 179.998 (0) radius drawLabel
140.002 179.998 (2) radius drawLabel
179.998 179.998 (0) radius drawLabel
219.998 179.998 (0) radius drawLabel
259.999 179.998 (0) radius drawLabel
300.000 179.998 (2) radius drawLabel
340.001 179.998 (0) radius drawLabel
380.002 179.998 (0) radius drawLabel
420.002 179.998 (0) radius drawLabel
459.998 179.998 (2) radius drawLabel
499.998 179.998 (0) radius drawLabel
539.999 179.998 (0) radius drawLabel
580.000 179.998 (0) radius drawLabel
20.000 219.998 (0) radius drawLabel
60.000 219.998 (0) radius drawLabel
100.002 219.998 (0) radius drawLabel
140.002 219.998 (2) radius drawLabel
179.998 219.998 (0) radius drawLabel
219.998 219.998 (0) radius drawLabel
259.999 219.998 (0) radius drawLabel
300.000 219.998 (2) radius drawLabel
340.001 219.998 (0) radius drawLabel
380.002 219.998 (0) radius drawLabel
420.002 219.998 (0) radius drawLabel
459.998 219.998 (2) radius drawLabel
499.998 219.998 (0) radius drawLabel
539.999 219.998 (0) radius drawLabel
580.000 219.998 (0) radius drawLabel
20.000 259.999 (0) radius drawLabel
60.000 259.999 (0) radius drawLabel
100.002 259.999 (0) radius drawLabel
140.002 259.999 (2) radius drawLabel
179.998 259.999 (0) radius drawLabel
219.998 259.999 (0) radius drawLabel
259.999 259.999 (0) radius drawLabel
300.000 259.999 (2) radius drawLabel
340.001 259.999 (0) radius drawLabel
380.002 259.999 (0) radius drawLabel
420.002 259.999 (0) radius drawLabel
459.998 259.999 (2) radius drawLabel
499.998 259.999 (0) radius drawLabel
539.999 259.999 (0) radius drawLabel
580.000 259.999 (0) radius drawLabel
20.000 300.000 (2) radius drawLabel
60.000 300.000 (2) radius drawLabel
100.002 300.000 (2) radius drawLabel
140.002 300.000 (4) radius drawLabel
179.998 300.000 (2) radius drawLabel
219.998 300.000 (2) radius drawLabel
259.999 300.000 (2) radius drawLabel
300.000 300.000 (4) radius drawLabel
340.001 300.000 (2) radius drawLabel
380.002 300.000 (2) radius drawLabel
420.002 300.000 (2) radius drawLabel
459.998 300.000 (4) radius drawLabel
499.998 300.000 (2) radius drawLabel
539.999 300.000 (2) radius drawLabel
580.000 300.000 (2) radius drawLabel
20.000 340.001 (0) radius drawLabel
60.000 340.001 (0) radius drawLabel
100.002 340.001 (0) radius drawLabel
140.002 340.001 (2) radius drawLabel
179.998 340.001 (0) radius drawLabel
219.998 340.001 (0) radius drawLabel
259.999 340.001 (0) radius drawLabel
300.000 340.001 (2) radius drawLabel
340.001 340.001 (0) radius drawLabel
380.002 340.001 (0) radius drawLabel
420.002 340.001 (0) radius drawLabel
459.998 340.001 (2) radius drawLabel
499.998 340.001 (0) radius drawLabel
539.999 340.001 (0) radius drawLabel
580.000 340.001 (0) radius drawLabel
20.000 380.002 (0) radius drawLabel
60.000 380.002 (0) radius drawLabel
100.002 380.002 (0) radius drawLabel
140.002 380.002 (2) radius drawLabel
179.998 380.002 (0) radius drawLabel
219.998 380.002 (0) radius drawLabel
259.999 380.002 (0) radius drawLabel
300.000 380.002 (2) radius drawLabel
340.001 380.002 (0) radius drawLabel
380.002 380.002 (0) radius drawLabel
420.002 380.002 (0) radius drawLabel
459.998 380.002 (2) radius drawLabel
499.998 380.002 (0) radius drawLabel
539.999 380.002 (0) radius drawLabel
580.000 380.002 (0) radius drawLabel
20.000 420.002 (0) radius drawLabel
60.000 420.002 (0) radius drawLabel
100.002 420.002 (0) radius drawLabel
140.002 420.002 (2) radius drawLabel
179.998 420.002 (0) radius drawLabel
219.998 420.002 (0) radius drawLabel
259.999 420.002 (0) radius drawLabel
300.000 420.002 (2) radius drawLabel
340.001 420.002 (0) radius drawLabel
380.002 420.002 (0) radius drawLabel
420.002 420.002 (0) radius drawLabel
459.998 420.002 (2) radius drawLabel
499.998 420.002 (0) radius drawLabel
539.999 420.002 (0) radius drawLabel
580.000 420.002 (0) radius drawLabel
20.000 459.998 (2) radius drawLabel
60.000 459.998 (2) radius drawLabel
100.002 459.998 (2) radius drawLabel
140.002 459.998 (4) radius drawLabel
179.998 459.998 (2) radius drawLabel
219.998 459.998 (2) radius drawLabel
259.999 459.998 (2) radius drawLabel
300.000 459.998 (4) radius drawLabel
340.001 459.998 (2) radius drawLabel
380.002 459.998 (2) radius drawLabel
420.002 459.998 (2) radius drawLabel
459.998 459.998 (4) radius drawLabel
499.998 459.998 (2) radius drawLabel
539.999 459.998 (2) radius drawLabel
580.000 459.998 (2) radius drawLabel
20.000 499.998 (0) radius drawLabel
60.000 499.998 (0) radius drawLabel
100.002 499.998 (0) radius drawLabel
140.002 499.998 (2) radius drawLabel
179.998 499.998 (0) radius drawLabel
219.998 499.998 (0) radius drawLabel
259.999 499.998 (0) radius drawLabel
300.000 499.998 (2) radius drawLabel
340.001 499.998 (0) radius drawLabel
380.002 499.998 (0) radius drawLabel
420.002 499.998 (0) radius drawLabel
459.998 499.998 (2) radius drawLabel
499.998 499.998 (0) radius drawLabel
539.999 499.998 (0) radius drawLabel
580.000 499.998 (0) radius drawLabel
20.000 539.999 (0) radius drawLabel
60.000 539.999 (0) radius drawLabel
100.002 539.999 (0) radius drawLabel
140.002 539.999 (2) radius drawLabel
179.998 539.999 (0) radius drawLabel
219.998 539.999 (0) radius drawLabel
259.999 539.999 (0) radius drawLabel
300.000 539.999 (2) radius drawLabel
340.001 539.999 (0) radius drawLabel
380.002 539.999 (0) radius drawLabel
420.002 539.999 (0) radius drawLabel
459.998 539.999 (2) radius drawLabel
499.998 539.999 (0) radius drawLabel
539.999 539.999 (0) radius drawLabel
580.000 539.999 (0) radius drawLabel
20.000 580.000 (0) radius drawLabel
60.000 580.000 (0) radius drawLabel
100.002 580.000 (0) radius drawLabel
140.002 580.000 (2) radius drawLabel
179.998 580.000 (0) radius drawLabel
219.998 580.000 (0) radius drawLabel
259.999 580.000 (0) radius drawLabel
300.000 580.000 (2) radius drawLabel
340.001 580.000 (0) radius drawLabel
380.002 580.000 (0) radius drawLabel
420.002 580.000 (0) radius drawLabel
459.998 580.000 (2) radius drawLabel
499.998 580.000 (0) radius drawLabel
539.999 580.000 (0) radius drawLabel
580.000 580.000 (0) radius drawLabel
grestore
showpage
260 500 M 260 460 L
260 500 M 300 460 L
300 500 M 300 460 L
300 500 M 260 500 L
340Graph/doc/GRD15x15rad2.eps.gz 0100644 0002055 0007177 00000007564 06534106105 0016734 0 ustar 00cleve compmath 0000040 0000006 85 GRD15x15rad2.eps ]ݎ
ߧ^h/pnA/ @`l/N QC#
Ǟs"&A8_}{:M:7^}ۇ{͔NǛwLe?=_ߏMo>ܿ}i:믗O?NÇ̓ojztt}tǻO4%Mwo7O/˳T^>=O|Zw/8K?^~yA]˛W51]t{xsé{>&0ߟrV m;<uOE{k9pǧS~?u]}CiUp^%Wtֺʟ?H9+0J
, *T>o9P%>$W@z2u%D =WZ g!ȝT'elZJ5ג|}1c*㮔 (JVK-D}2:Q.I'e(F0I(N|ً?$_/R
@-Eb,hyCpqsrTrrŕS%wWwrxCQj*9ʞ\CPNs"7{!\
p8Rɱ+Ǯ(sǩBSO=@ giВT-vuX"tՏ6_KrY 6m$xYc!{ lbaVc{Y8=~2@
bl/ǀ`),UJ
>
m,2V+EW!FM 㔜]VVܵ0_/guuxETRvd5K .Zgׂ:CT,mt@V(2g۾XC&7i9 p=j~s
g 0yă# #,<7
u-he"Zϻ ɹ'gO^rXYs*_yc)3( bPKrY,߂;[Ќ+R6_{5?Lpm1
ά fHi`)/A\t%5Gc]SZx5Ĩig:A)9 w=jgrfY<"۴ wA`Qxhk!E#,L /Y6RPXkA!eWAFP"A|WD d_PIxͼ"\B Ϡ;Ds*_[aiiWAeª/ew'[N?_-h[)PEl/@[H+0Ytda3o!.g̐$CӬ
6hB]d`Gc]SZx5Ĩi:A)9 w=jrfY<"۴ wA`Qxhk!E#,L /Yp]P